telepathy-gabble-0.18.3/0000775000175000017500000000000012332445275016205 5ustar00cassidycassidy00000000000000telepathy-gabble-0.18.3/configure.ac0000664000175000017500000003525612332443575020507 0ustar00cassidycassidy00000000000000AC_PREREQ([2.59]) # Making releases: # set the new version number: # odd minor -> development series # even minor -> stable series # increment micro for each release within a series # set gabble_nano_version to 0. m4_define([gabble_major_version], [0]) m4_define([gabble_minor_version], [18]) m4_define([gabble_micro_version], [3]) m4_define([gabble_nano_version], [0]) # Some magic m4_define([gabble_base_version], [gabble_major_version.gabble_minor_version.gabble_micro_version]) m4_define([gabble_version], [m4_if(gabble_nano_version, 0, [gabble_base_version], [gabble_base_version].[gabble_nano_version])]) AC_INIT([Telepathy Gabble], [gabble_version], [https://bugs.freedesktop.org/enter_bug.cgi?product=Telepathy&component=gabble]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([1.9 -Wno-portability tar-ustar]) AM_CONFIG_HEADER(config.h) AC_USE_SYSTEM_EXTENSIONS m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES]) dnl check for tools AC_PROG_CC AC_PROG_CC_STDC AC_PROG_INSTALL AC_PROG_LIBTOOL AC_PROG_MKDIR_P AC_CHECK_HEADERS_ONCE([ arpa/inet.h arpa/nameser.h fcntl.h ifaddrs.h netdb.h netinet/in.h sys/ioctl.h sys/un.h unistd.h ]) # on Darwin, these headers are interdependent, according to autoconf.info AC_CHECK_HEADERS([sys/socket.h], [], [], [ #include #include #include ]) AC_CHECK_HEADERS([net/if.h], [], [], [ #include #include #include #ifdef HAVE_SYS_SOCKET_H # include #endif ]) # Autoconf has a handy macro for this, since it tends to have dependencies AC_HEADER_RESOLV COMPILER_OPTIMISATIONS COMPILER_COVERAGE ifelse(gabble_nano_version, 0, [ official_release=yes ], [ official_release=no ]) AM_CONDITIONAL([OFFICIAL_RELEASE], [test "x$official_release" = xyes]) TP_COMPILER_WARNINGS([ERROR_CFLAGS], [test "x$official_release" = xno], [all \ extra \ declaration-after-statement \ shadow \ strict-prototypes \ missing-declarations \ missing-prototypes \ sign-compare \ nested-externs \ pointer-arith \ format-security \ init-self], [missing-field-initializers \ deprecated-declarations \ unused-parameter]) AC_SUBST([ERROR_CFLAGS]) #------------------------------------------------------------ # Detect Operating system based on $host #------------------------------------------------------------ AC_MSG_CHECKING([operating system]) case "$host" in *-*-*mingw*|*-*-*cygwin*) platform=win32 AC_MSG_RESULT($platform) ;; *) platform=unix AC_MSG_RESULT($platform) ;; esac AM_CONDITIONAL([WINDOWS], [test "$platform" = "win32"]) # ----------------------------------------------------------- # Make CA certificates path configurable # Stolen from GIO's TLS # ----------------------------------------------------------- AC_MSG_CHECKING([location of system Certificate Authority list]) AC_ARG_WITH(ca-certificates, [AC_HELP_STRING([--with-ca-certificates=@<:@path@:>@], [path to system Certificate Authority list])]) if test "$with_ca_certificates" = "no"; then AC_MSG_RESULT([disabled]) else if test -z "$with_ca_certificates"; then for f in /etc/pki/tls/certs/ca-bundle.crt \ /etc/ssl/certs/ca-certificates.crt; do if test -f "$f"; then with_ca_certificates="$f" fi done if test -z "$with_ca_certificates"; then AC_MSG_ERROR([could not find. Use --with-ca-certificates=path to set, or --without-ca-certificates to disable]) fi fi AC_MSG_RESULT($with_ca_certificates) AC_DEFINE_UNQUOTED([GTLS_SYSTEM_CA_CERTIFICATES], ["$with_ca_certificates"], [path to system Certificate Authority list]) fi if test -n "$with_ca_certificates"; then if ! test -f "$with_ca_certificates"; then AC_MSG_WARN([Specified certificate authority file '$with_ca_certificates' does not exist]) fi fi AC_ARG_ENABLE(debug, AC_HELP_STRING([--disable-debug],[compile without debug code]), enable_debug=$enableval, enable_debug=yes ) ifelse(gabble_nano_version, 0, [ # Gabble is version x.y.z - disable coding style checks by default AC_ARG_ENABLE(coding-style-checks, AC_HELP_STRING([--enable-coding-style-checks], [check coding style using grep]), [ENABLE_CODING_STYLE_CHECKS=$enableval], [ENABLE_CODING_STYLE_CHECKS=no] ) ], [ # Gabble is version x.y.z.1 - enable coding style checks by default AC_ARG_ENABLE(coding-style-checks, AC_HELP_STRING([--disable-coding-style-checks], [do not check coding style using grep]), [ENABLE_CODING_STYLE_CHECKS=$enableval], [ENABLE_CODING_STYLE_CHECKS=yes]) ]) if test x$enable_debug = xyes; then AC_DEFINE(ENABLE_DEBUG, [], [Enable debug code]) fi AM_CONDITIONAL([ENABLE_DEBUG], [test "x$enable_debug" = xyes]) AC_SUBST([ENABLE_CODING_STYLE_CHECKS]) AC_ARG_ENABLE([installed-tests], AC_HELP_STRING([--enable-installed-tests], [make tests installable]), [installed_tests=$enableval], [installed_tests=no]) if test x$installed_tests = xyes; then AC_DEFINE(ENABLE_INSTALLED_TESTS, [], [Make tests installable]) fi AM_CONDITIONAL([ENABLE_INSTALLED_TESTS], [test "x$installed_tests" = xyes]) gabbletestsdir=${libdir}/telepathy-gabble-tests AC_SUBST(gabbletestsdir) AC_ARG_ENABLE([is-a-phone], AC_HELP_STRING([--enable-is-a-phone], [advertise that we are a phone, not a PC]), [is_a_phone=$enableval], [is_a_phone=no]) if test x$is_a_phone = xyes; then AC_DEFINE(CLIENT_TYPE, ["phone"], [Client type from http://xmpp.org/registrar/disco-categories.html#client]) CLIENT_TYPE=phone else AC_DEFINE(CLIENT_TYPE, ["pc"], [Client type from http://xmpp.org/registrar/disco-categories.html#client]) CLIENT_TYPE=pc fi AC_SUBST(CLIENT_TYPE) # whether to assert when g_critical() is used AC_ARG_ENABLE([fatal-criticals], AC_HELP_STRING([--disable-fatal-criticals], [do not assert because of critical warnings]), [fatal_criticals=$enableval], [fatal_criticals=yes]) if test x$fatal_criticals = xyes; then AC_DEFINE(ENABLE_FATAL_CRITICALS, [], [Critical warnings will result in an assertion]) fi AM_CONDITIONAL([ENABLE_FATAL_CRITICALS], [test "x$fatal_criticals" = xyes]) dnl dummy check for gtk-doc AC_ARG_ENABLE(gtk-doc, AC_HELP_STRING([--enable-gtk-doc],[does not actually do anything]), enable_gtk_doc=yes, enable_gtk_doc=no) AM_CONDITIONAL([ENABLE_GTK_DOC], [test "x$enable_gtk_doc" = xyes]) dnl Check for Glib PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.32, gobject-2.0, gthread-2.0, gio-2.0]) PKG_CHECK_MODULES(GMODULE, [gmodule-2.0 >= 2.32]) AC_DEFINE(GLIB_VERSION_MIN_REQUIRED, GLIB_VERSION_2_30, [Ignore post 2.30 deprecations]) AC_DEFINE(GLIB_VERSION_MAX_ALLOWED, GLIB_VERSION_2_32, [Prevent post 2.32 APIs]) AC_SUBST(GLIB_CFLAGS) AC_SUBST(GLIB_LIBS) GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` AC_SUBST(GLIB_GENMARSHAL) # These must contain "exec" for automake to work right (install-exec, # not install-data). # # Private directory for Wocky and the gabble-plugins library if test "x$pluginexeclibdir" = x; then pluginexeclibdir='${libdir}/telepathy/gabble-0/lib' fi AC_ARG_VAR([pluginexeclibdir]) # The actual plugins if test "x$pluginexecdir" = x; then pluginexecdir='${libdir}/telepathy/gabble-0/plugins' fi AC_ARG_VAR([pluginexecdir]) AC_ARG_ENABLE(plugins, AC_HELP_STRING([--disable-plugins], [disable plugin loader]), [enable_plugins=$enableval], [enable_plugins=yes]) if test x$enable_plugins = xyes; then AC_DEFINE(ENABLE_PLUGINS, [], [Enable plugins]) PKG_CHECK_MODULES(GMODULE, [gmodule-2.0]) AC_ARG_ENABLE(plugin-api, AC_HELP_STRING([--enable-plugin-api], [install headers for third-party plugins (experimental)]), [ enable_plugin_api=$enableval wocky_install_headers_dir="${includedir}/telepathy-gabble-0" ], [enable_plugin_api=no]) fi AC_SUBST(GMODULE_CFLAGS) AC_SUBST(GMODULE_LIBS) AM_CONDITIONAL(ENABLE_PLUGINS, test x$enable_plugins = xyes) AC_SUBST(ENABLE_PLUGINS) AM_CONDITIONAL(ENABLE_PLUGIN_API, test x$enable_plugin_api = xyes) AC_ARG_ENABLE(channel-type-call, AC_HELP_STRING([--disable-channel-type-call], [disable support for the draft Channel.Type.Call]), [enable_channel_type_call=$enableval], [enable_channel_type_call=yes]) if test x$enable_channel_type_call = xyes; then AC_DEFINE(ENABLE_CHANNEL_TYPE_CALL, [], [Enable Channel.Type.Call]) fi AM_CONDITIONAL(ENABLE_CHANNEL_TYPE_CALL, test x$enable_channel_type_call = xyes) dnl Check for D-Bus PKG_CHECK_MODULES(DBUS, [dbus-1 >= 1.1.0, dbus-glib-1 >= 0.82]) AC_SUBST(DBUS_CFLAGS) AC_SUBST(DBUS_LIBS) AC_DEFINE(TP_SEAL_ENABLE, [], [Prevent to use sealed variables]) AC_DEFINE(TP_DISABLE_SINGLE_INCLUDE, [], [Disable single header include]) AC_DEFINE(TP_VERSION_MIN_REQUIRED, TP_VERSION_0_18, [Ignore post 0.18 deprecations]) AC_DEFINE(TP_VERSION_MAX_ALLOWED, TP_VERSION_0_20, [Prevent post 0.20 APIs]) PKG_CHECK_MODULES(TP_GLIB, [telepathy-glib >= 0.19.9]) AC_SUBST(TP_GLIB_CFLAGS) AC_SUBST(TP_GLIB_LIBS) dnl Check for code generation tools XSLTPROC= AC_CHECK_PROGS([XSLTPROC], [xsltproc]) if test -z "$XSLTPROC"; then AC_MSG_ERROR([xsltproc (from the libxslt source package) is required]) fi AM_PATH_PYTHON([2.5]) # Check for a Python >= 2.5 with Twisted, to run the tests AC_MSG_CHECKING([for Python with Twisted and XMPP protocol support]) if $PYTHON -c "import twisted.words.xish.domish, twisted.words.protocols.jabber, twisted.internet.reactor" >/dev/null 2>&1; then TEST_PYTHON="$PYTHON" else TEST_PYTHON=false fi AC_MSG_RESULT([$TEST_PYTHON]) AC_SUBST(TEST_PYTHON) AM_CONDITIONAL([WANT_TWISTED_TESTS], test false != "$TEST_PYTHON") # We have to run Wocky's configure *before* looking for it with PKG_CHECK_MODULES so wocky-uninstalled.pc has been generated # If you don't specify --prefix, it starts off as NONE. Autoconf # would normally do this defaulting for us later, but that's too # late to help Wocky. if test "x${prefix}" = "xNONE"; then prefix=/usr/local fi # We tell Wocky to install its headers alongside gabble's so that an actual # separate Wocky installation won't clash with them. This is a bit of a hack. # AX_CONFIG_DIR doesn't make it very easy to pass extra arguments to the # submodule's configure. prev_ac_configure_args=$ac_configure_args ac_configure_args="$ac_configure_args --with-installed-headers=${wocky_install_headers_dir} --enable-shared-suffix=${PACKAGE}-${VERSION} --libdir=${pluginexeclibdir}" if test "x$ENABLE_CODING_STYLE_CHECKS" = xyes ; then ac_configure_args="$ac_configure_args --enable-coding-style-checks" else ac_configure_args="$ac_configure_args --disable-coding-style-checks" fi if test "x$tp_werror" = xyes && test "x$official_release" = xno; then ac_configure_args="$ac_configure_args --enable-Werror" else ac_configure_args="$ac_configure_args --disable-Werror" fi dnl wocky prev_top_build_prefix=$ac_top_build_prefix AX_CONFIG_DIR([lib/ext/wocky]) ac_top_build_prefix=$prev_top_build_prefix ac_configure_args=$prev_ac_configure_args dnl Check if Android build AC_ARG_ENABLE(submodules, AS_HELP_STRING([--disable-submodules],[Use system versions of Wocky, rather than submodules]), build_submodules=$enableval, build_submodules=yes ) dnl Check for Wocky # re-enable once Wocky has been released as a lib if test x$build_submodules = xyes; then export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:"$ac_top_build_prefix"lib/ext/wocky/wocky fi PKG_CHECK_MODULES(WOCKY, wocky >= 0.0.0) AC_SUBST(WOCKY_CFLAGS) AC_SUBST(WOCKY_LIBS) AC_ARG_ENABLE(google-relay, AC_HELP_STRING([--disable-google-relay], [disable Google Jingle relay support]), [enable_google_relay=$enableval], [enable_google_relay=yes]) if test x$enable_google_relay = xyes; then AC_DEFINE(ENABLE_GOOGLE_RELAY, [], [Enable Google Jingle relay support]) dnl Check for libsoup PKG_CHECK_MODULES(SOUP, libsoup-2.4) else SOUP_CFLAGS= SOUP_LIBS= fi AC_SUBST(SOUP_CFLAGS) AC_SUBST(SOUP_LIBS) AM_CONDITIONAL([ENABLE_GOOGLE_RELAY], [test "x$enable_google_relay" = xyes]) AC_ARG_ENABLE(file-transfer, AC_HELP_STRING([--disable-file-transfer], [disable file transfer support]), [enable_ft=$enableval], [enable_ft=yes]) if test x$enable_ft = xyes; then AC_DEFINE(ENABLE_FILE_TRANSFER, [], [Enable file transfer]) fi AM_CONDITIONAL([ENABLE_FILE_TRANSFER], [test "x$enable_ft" = xyes]) AC_ARG_ENABLE(voip, AC_HELP_STRING([--disable-voip], [disable VoIP support (and, consequently, Jingle-based file transfer support]), [enable_voip=$enableval], [enable_voip=yes]) if test x$enable_voip = xyes; then AC_DEFINE(ENABLE_VOIP, [], [Enable VoIP]) fi AM_CONDITIONAL([ENABLE_VOIP], [test "x$enable_voip" = xyes]) if test x$enable_voip = xyes -a x$enable_ft = xyes; then enable_jingle_ft=yes AC_DEFINE(ENABLE_JINGLE_FILE_TRANSFER, [], [Enable file transfer]) dnl Check for libnice PKG_CHECK_MODULES(NICE, nice >= 0.0.11) else enable_jingle_ft=no NICE_CFLAGS= NICE_LIBS= fi AC_SUBST(NICE_CFLAGS) AC_SUBST(NICE_LIBS) AM_CONDITIONAL([ENABLE_JINGLE_FILE_TRANSFER], [test "x$enable_jingle_ft" = xyes]) AC_CHECK_FUNCS(getifaddrs memset select strndup setresuid setreuid strerror) AC_OUTPUT( Makefile \ docs/Makefile \ extensions/Makefile \ src/Makefile \ m4/Makefile \ data/Makefile \ tests/Makefile \ tools/Makefile \ tests/suppressions/Makefile \ tests/twisted/Makefile \ lib/Makefile \ lib/ext/Makefile \ lib/gibber/Makefile \ plugins/Makefile \ gabble/Makefile \ gabble/telepathy-gabble-uninstalled.pc \ gabble/telepathy-gabble.pc ) if test false != "$TEST_PYTHON"; then tests_enabled=yes else tests_enabled=no fi echo " Configure summary: Compiler....................: ${CC} Compiler Flags..............: ${CFLAGS} ${ERROR_CFLAGS} Prefix......................: ${prefix} Coding style checks.........: ${ENABLE_CODING_STYLE_CHECKS} Enable debug................: ${enable_debug} Python tests................: ${tests_enabled} Install unit tests..........: ${installed_tests} Features: Client type.................: \"${CLIENT_TYPE}\" Plugin support..............: ${enable_plugins} Plugin headers installed....: ${enable_plugin_api} Channel.Type.Call support...: ${enable_channel_type_call} Google relay support........: ${enable_google_relay} File transfer support.......: ${enable_ft} Jingle file transfer support: ${enable_jingle_ft} VoIP support................: ${enable_voip} " telepathy-gabble-0.18.3/README0000644000175000017500000000550311570651565017072 0ustar00cassidycassidy00000000000000================ telepathy-gabble ================ Gabble is a Jabber/XMPP connection manager for the Telepathy framework, currently supporting: * single-user chats * multi-user chats * voice/video calling * file transfer with Jabber/XMPP and Google Talk interoperability. Telepathy is a D-Bus framework for unifying real time communication, including instant messaging, voice calls and video calls. It abstracts differences between protocols to provide a unified interface for applications. Requirements ============ telepathy-gabble requires: telepathy-glib GLib, GObject libdbus The D-Bus GLib bindings libxml2 libnice libsoup and either: GNUTLS or OpenSSL At build time, it also requires: GNU make pkg-config libxslt, xsltproc Python See configure.ac for full details, including versions required. Building from git also requires the GNU build system (Autoconf, Automake, libtool). Bugs, feature requests and to-do list ===================================== Report all bugs, feature requests and "to-do" items here: Versioning policy ================= We use an "odd/even" versioning scheme where the minor version (the y in x.y.z) determines stability - stable branches have y even, development branches have y odd. Unreleased builds straight from git identify themselves as version "x.y.z.1". These are compiled with -Werror, so they might stop working if your gcc version issues more warnings than ours. If this is a problem for you, use a release tarball. Contact info ============ This package is maintained by the Telepathy project: Telepathy development is supported by Collabora Ltd. . Hacking ======= The current version of telepathy-gabble is always available from the 'master' branch of: (gitweb) Stable branches are in the same repository, and are called telepathy-gabble-0.6 etc. Proposed patches awaiting review can usually be found in Merge Monkey: Please follow . telepathy-gabble-0.18.3/aclocal.m40000664000175000017500000015616412332443653020060 0ustar00cassidycassidy00000000000000# generated automatically by aclocal 1.13.4 -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # serial 1 (pkg-config-0.24) # # Copyright © 2004 Scott James Remnant . # # 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. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # PKG_PROG_PKG_CONFIG([MIN-VERSION]) # ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])# PKG_PROG_PKG_CONFIG # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # # Check to see whether a particular set of modules exists. Similar # to PKG_CHECK_MODULES(), but does not set variables or print errors. # # Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) # only at the first occurence in configure.ac, so if the first place # it's called might be skipped (such as if it is within an "if", you # have to call PKG_CHECK_EXISTS manually # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) # --------------------------------------------- m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])# _PKG_CONFIG # _PKG_SHORT_ERRORS_SUPPORTED # ----------------------------- AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])# _PKG_SHORT_ERRORS_SUPPORTED # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], # [ACTION-IF-NOT-FOUND]) # # # Note that if there is a possibility the first call to # PKG_CHECK_MODULES might not happen, you should be sure to include an # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac # # # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])# PKG_CHECK_MODULES # PKG_INSTALLDIR(DIRECTORY) # ------------------------- # Substitutes the variable pkgconfigdir as the location where a module # should install pkg-config .pc files. By default the directory is # $libdir/pkgconfig, but the default can be changed by passing # DIRECTORY. The user can override through the --with-pkgconfigdir # parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ]) dnl PKG_INSTALLDIR # PKG_NOARCH_INSTALLDIR(DIRECTORY) # ------------------------- # Substitutes the variable noarch_pkgconfigdir as the location where a # module should install arch-independent pkg-config .pc files. By # default the directory is $datadir/pkgconfig, but the default can be # changed by passing DIRECTORY. The user can override through the # --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ]) dnl PKG_NOARCH_INSTALLDIR # PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, # [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # ------------------------------------------- # Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])# PKG_CHECK_VAR # Copyright (C) 2002-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # 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. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.13' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.13.4], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.13.4])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each '.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # 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. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # -*- Autoconf -*- # Obsolete and "removed" macros, that must however still report explicit # error messages when used, to smooth transition. # # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. AC_DEFUN([AM_CONFIG_HEADER], [AC_DIAGNOSE([obsolete], ['$0': this macro is obsolete. You should use the 'AC][_CONFIG_HEADERS' macro instead.])dnl AC_CONFIG_HEADERS($@)]) AC_DEFUN([AM_PROG_CC_STDC], [AC_PROG_CC am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc AC_DIAGNOSE([obsolete], ['$0': this macro is obsolete. You should simply use the 'AC][_PROG_CC' macro instead. Also, your code should no longer depend upon 'am_cv_prog_cc_stdc', but upon 'ac_cv_prog_cc_stdc'.])]) AC_DEFUN([AM_C_PROTOTYPES], [AC_FATAL([automatic de-ANSI-fication support has been removed])]) AU_DEFUN([fp_C_PROTOTYPES], [AM_C_PROTOTYPES]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # --------------------------------------------------------------------------- # Adds support for distributing Python modules and packages. To # install modules, copy them to $(pythondir), using the python_PYTHON # automake variable. To install a package with the same name as the # automake package, install to $(pkgpythondir), or use the # pkgpython_PYTHON automake variable. # # The variables $(pyexecdir) and $(pkgpyexecdir) are provided as # locations to install python extension modules (shared libraries). # Another macro is required to find the appropriate flags to compile # extension modules. # # If your package is configured with a different prefix to python, # users will have to add the install directory to the PYTHONPATH # environment variable, or create a .pth file (see the python # documentation for details). # # If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will # cause an error if the version of python installed on the system # doesn't meet the requirement. MINIMUM-VERSION should consist of # numbers and dots only. AC_DEFUN([AM_PATH_PYTHON], [ dnl Find a Python interpreter. Python versions prior to 2.0 are not dnl supported. (2.0 was released on October 16, 2000). m4_define_default([_AM_PYTHON_INTERPRETER_LIST], [python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 dnl python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0]) AC_ARG_VAR([PYTHON], [the Python interpreter]) m4_if([$1],[],[ dnl No version check is needed. # Find any Python interpreter. if test -z "$PYTHON"; then AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :) fi am_display_PYTHON=python ], [ dnl A version check is needed. if test -n "$PYTHON"; then # If the user set $PYTHON, use it and don't search something else. AC_MSG_CHECKING([whether $PYTHON version is >= $1]) AM_PYTHON_CHECK_VERSION([$PYTHON], [$1], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_MSG_ERROR([Python interpreter is too old])]) am_display_PYTHON=$PYTHON else # Otherwise, try each interpreter until we find one that satisfies # VERSION. AC_CACHE_CHECK([for a Python interpreter with version >= $1], [am_cv_pathless_PYTHON],[ for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do test "$am_cv_pathless_PYTHON" = none && break AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break]) done]) # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. if test "$am_cv_pathless_PYTHON" = none; then PYTHON=: else AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON]) fi am_display_PYTHON=$am_cv_pathless_PYTHON fi ]) if test "$PYTHON" = :; then dnl Run any user-specified action, or abort. m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])]) else dnl Query Python for its version number. Getting [:3] seems to be dnl the best way to do this; it's what "site.py" does in the standard dnl library. AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version], [am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`]) AC_SUBST([PYTHON_VERSION], [$am_cv_python_version]) dnl Use the values of $prefix and $exec_prefix for the corresponding dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made dnl distinct variables so they can be overridden if need be. However, dnl general consensus is that you shouldn't need this ability. AC_SUBST([PYTHON_PREFIX], ['${prefix}']) AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}']) dnl At times (like when building shared libraries) you may want dnl to know which OS platform Python thinks this is. AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform], [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`]) AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform]) # Just factor out some code duplication. am_python_setup_sysconfig="\ import sys # Prefer sysconfig over distutils.sysconfig, for better compatibility # with python 3.x. See automake bug#10227. try: import sysconfig except ImportError: can_use_sysconfig = 0 else: can_use_sysconfig = 1 # Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: # try: from platform import python_implementation if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7': can_use_sysconfig = 0 except ImportError: pass" dnl Set up 4 directories: dnl pythondir -- where to install python scripts. This is the dnl site-packages directory, not the python standard library dnl directory like in previous automake betas. This behavior dnl is more consistent with lispdir.m4 for example. dnl Query distutils for this directory. AC_CACHE_CHECK([for $am_display_PYTHON script directory], [am_cv_python_pythondir], [if test "x$prefix" = xNONE then am_py_prefix=$ac_default_prefix else am_py_prefix=$prefix fi am_cv_python_pythondir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pythondir in $am_py_prefix*) am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` ;; *) case $am_py_prefix in /usr|/System*) ;; *) am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac ]) AC_SUBST([pythondir], [$am_cv_python_pythondir]) dnl pkgpythondir -- $PACKAGE directory under pythondir. Was dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is dnl more consistent with the rest of automake. AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE]) dnl pyexecdir -- directory for installing python extension modules dnl (shared libraries) dnl Query distutils for this directory. AC_CACHE_CHECK([for $am_display_PYTHON extension module directory], [am_cv_python_pyexecdir], [if test "x$exec_prefix" = xNONE then am_py_exec_prefix=$am_py_prefix else am_py_exec_prefix=$exec_prefix fi am_cv_python_pyexecdir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pyexecdir in $am_py_exec_prefix*) am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` ;; *) case $am_py_exec_prefix in /usr|/System*) ;; *) am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac ]) AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir]) dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE) AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE]) dnl Run any user-specified action. $2 fi ]) # AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) # --------------------------------------------------------------------------- # Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION. # Run ACTION-IF-FALSE otherwise. # This test uses sys.hexversion instead of the string equivalent (first # word of sys.version), in order to cope with versions such as 2.2c1. # This supports Python 2.0 or higher. (2.0 was released on October 16, 2000). AC_DEFUN([AM_PYTHON_CHECK_VERSION], [prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] sys.exit(sys.hexversion < minverhex)" AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # 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 ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $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 if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/ax_config_dir.m4]) m4_include([m4/compiler.m4]) m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) m4_include([m4/tp-compiler-flag.m4]) m4_include([m4/tp-compiler-warnings.m4]) telepathy-gabble-0.18.3/src/0000775000175000017500000000000012332445274016773 5ustar00cassidycassidy00000000000000telepathy-gabble-0.18.3/src/bytestream-muc.c0000664000175000017500000004115512332440117022075 0ustar00cassidycassidy00000000000000/* * bytestream-muc.c - Source for GabbleBytestreamMuc * Copyright (C) 2007 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "bytestream-muc.h" #include #include #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_BYTESTREAM #include "bytestream-factory.h" #include "bytestream-iface.h" #include "connection.h" #include "debug.h" #include "disco.h" #include "namespaces.h" #include "util.h" /* 45k gives us 60k after base64 encoding, allowing 4k of header before we hit * ejabberd's default 64k maximum stanza size */ #define MAX_BLOCK_SIZE (1024 * 45) static void bytestream_iface_init (gpointer g_iface, gpointer iface_data); G_DEFINE_TYPE_WITH_CODE (GabbleBytestreamMuc, gabble_bytestream_muc, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GABBLE_TYPE_BYTESTREAM_IFACE, bytestream_iface_init)); /* properties */ enum { PROP_CONNECTION = 1, PROP_PEER_HANDLE, PROP_PEER_HANDLE_TYPE, PROP_STREAM_ID, PROP_PEER_JID, PROP_STATE, PROP_PROTOCOL, LAST_PROPERTY }; struct _GabbleBytestreamMucPrivate { GabbleConnection *conn; TpHandle peer_handle; TpHandleType peer_handle_type; gchar *stream_id; GabbleBytestreamState state; const gchar *peer_jid; /* (gchar *): sender's muc-JID -> (GString *): accumulated message data */ GHashTable *buffers; gboolean dispose_has_run; }; #define GABBLE_BYTESTREAM_MUC_GET_PRIVATE(obj) ((obj)->priv) static void free_buffer (GString *buffer) { g_string_free (buffer, TRUE); } static void gabble_bytestream_muc_init (GabbleBytestreamMuc *self) { GabbleBytestreamMucPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_BYTESTREAM_MUC, GabbleBytestreamMucPrivate); self->priv = priv; priv->buffers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) free_buffer); } static void gabble_bytestream_muc_dispose (GObject *object) { GabbleBytestreamMuc *self = GABBLE_BYTESTREAM_MUC (object); GabbleBytestreamMucPrivate *priv = GABBLE_BYTESTREAM_MUC_GET_PRIVATE (self); if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; if (priv->state != GABBLE_BYTESTREAM_STATE_CLOSED) { gabble_bytestream_iface_close (GABBLE_BYTESTREAM_IFACE (self), NULL); } G_OBJECT_CLASS (gabble_bytestream_muc_parent_class)->dispose (object); } static void gabble_bytestream_muc_finalize (GObject *object) { GabbleBytestreamMuc *self = GABBLE_BYTESTREAM_MUC (object); GabbleBytestreamMucPrivate *priv = GABBLE_BYTESTREAM_MUC_GET_PRIVATE (self); g_free (priv->stream_id); if (priv->buffers != NULL) { g_hash_table_unref (priv->buffers); priv->buffers = NULL; } G_OBJECT_CLASS (gabble_bytestream_muc_parent_class)->finalize (object); } static void gabble_bytestream_muc_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleBytestreamMuc *self = GABBLE_BYTESTREAM_MUC (object); GabbleBytestreamMucPrivate *priv = GABBLE_BYTESTREAM_MUC_GET_PRIVATE (self); switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, priv->conn); break; case PROP_PEER_HANDLE: g_value_set_uint (value, priv->peer_handle); break; case PROP_PEER_HANDLE_TYPE: g_value_set_uint (value, TP_HANDLE_TYPE_ROOM); break; case PROP_STREAM_ID: g_value_set_string (value, priv->stream_id); break; case PROP_PEER_JID: g_value_set_string (value, priv->peer_jid); break; case PROP_STATE: g_value_set_uint (value, priv->state); break; case PROP_PROTOCOL: g_value_set_string (value, NS_MUC_BYTESTREAM); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_bytestream_muc_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleBytestreamMuc *self = GABBLE_BYTESTREAM_MUC (object); GabbleBytestreamMucPrivate *priv = GABBLE_BYTESTREAM_MUC_GET_PRIVATE (self); switch (property_id) { case PROP_CONNECTION: priv->conn = g_value_get_object (value); break; case PROP_PEER_HANDLE: priv->peer_handle = g_value_get_uint (value); break; case PROP_STREAM_ID: g_free (priv->stream_id); priv->stream_id = g_value_dup_string (value); break; case PROP_STATE: if (priv->state != g_value_get_uint (value)) { priv->state = g_value_get_uint (value); g_signal_emit_by_name (object, "state-changed", priv->state); } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static GObject * gabble_bytestream_muc_constructor (GType type, guint n_props, GObjectConstructParam *props) { GObject *obj; GabbleBytestreamMucPrivate *priv; TpHandleRepoIface *room_repo; obj = G_OBJECT_CLASS (gabble_bytestream_muc_parent_class)-> constructor (type, n_props, props); priv = GABBLE_BYTESTREAM_MUC_GET_PRIVATE (GABBLE_BYTESTREAM_MUC (obj)); g_assert (priv->conn != NULL); g_assert (priv->peer_handle != 0); room_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_ROOM); priv->peer_jid = tp_handle_inspect (room_repo, priv->peer_handle); return obj; } static void gabble_bytestream_muc_class_init ( GabbleBytestreamMucClass *gabble_bytestream_muc_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_bytestream_muc_class); g_type_class_add_private (gabble_bytestream_muc_class, sizeof (GabbleBytestreamMucPrivate)); object_class->dispose = gabble_bytestream_muc_dispose; object_class->finalize = gabble_bytestream_muc_finalize; object_class->get_property = gabble_bytestream_muc_get_property; object_class->set_property = gabble_bytestream_muc_set_property; object_class->constructor = gabble_bytestream_muc_constructor; g_object_class_override_property (object_class, PROP_CONNECTION, "connection"); g_object_class_override_property (object_class, PROP_PEER_HANDLE, "peer-handle"); g_object_class_override_property (object_class, PROP_PEER_HANDLE_TYPE, "peer-handle-type"); g_object_class_override_property (object_class, PROP_STREAM_ID, "stream-id"); g_object_class_override_property (object_class, PROP_PEER_JID, "peer-jid"); g_object_class_override_property (object_class, PROP_STATE, "state"); g_object_class_override_property (object_class, PROP_PROTOCOL, "protocol"); } enum { FRAG_COMPLETE = 0, FRAG_FIRST, FRAG_MIDDLE, FRAG_LAST }; static gboolean send_data_to (GabbleBytestreamMuc *self, const gchar *to, gboolean groupchat, guint len, const gchar *str) { GabbleBytestreamMucPrivate *priv = GABBLE_BYTESTREAM_MUC_GET_PRIVATE (self); guint sent, stanza_count; guint frag; if (priv->state != GABBLE_BYTESTREAM_STATE_OPEN) { DEBUG ("can't send data through a not open bytestream (state: %d)", priv->state); return FALSE; } sent = 0; stanza_count = 0; while (sent < len) { gboolean ret; gchar *encoded; guint send_now; GError *error = NULL; WockyStanza *msg; WockyNode *data = NULL; msg = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, to, '(', "data", '*', &data, ':', NS_MUC_BYTESTREAM, '@', "sid", priv->stream_id, ')', GABBLE_AMP_DO_NOT_STORE_SPEC, NULL); g_assert (data != NULL); if (groupchat) { wocky_node_set_attribute (wocky_stanza_get_top_node (msg), "type", "groupchat"); } if ((len - sent) > MAX_BLOCK_SIZE) { /* We can't send all the remaining data in one stanza */ send_now = MAX_BLOCK_SIZE; if (stanza_count == 0) frag = FRAG_FIRST; else frag = FRAG_MIDDLE; } else { /* Send all the remaining data */ send_now = (len - sent); if (stanza_count == 0) frag = FRAG_COMPLETE; else frag = FRAG_LAST; } encoded = g_base64_encode ((const guchar *) str + sent, send_now); wocky_node_set_content (data, encoded); switch (frag) { case FRAG_FIRST: wocky_node_set_attribute (data, "frag", "first"); break; case FRAG_MIDDLE: wocky_node_set_attribute (data, "frag", "middle"); break; case FRAG_LAST: wocky_node_set_attribute (data, "frag", "last"); break; } DEBUG ("send %d bytes", send_now); ret = _gabble_connection_send (priv->conn, msg, &error); g_free (encoded); if (!ret) { DEBUG ("error sending pseusdo IBB Muc stanza: %s", error->message); g_error_free (error); g_object_unref (msg); return FALSE; } sent += send_now; stanza_count++; g_object_unref (msg); } DEBUG ("finished to send %d bytes (%d stanzas needed)", len, stanza_count); return TRUE; } /* * gabble_bytestream_muc_send * * Implements gabble_bytestream_iface_send on GabbleBytestreamIface */ static gboolean gabble_bytestream_muc_send (GabbleBytestreamIface *iface, guint len, const gchar *str) { GabbleBytestreamMuc *self = GABBLE_BYTESTREAM_MUC (iface); GabbleBytestreamMucPrivate *priv = GABBLE_BYTESTREAM_MUC_GET_PRIVATE (self); return send_data_to (self, priv->peer_jid, TRUE, len, str); } void gabble_bytestream_muc_receive (GabbleBytestreamMuc *self, WockyStanza *msg) { GabbleBytestreamMucPrivate *priv = GABBLE_BYTESTREAM_MUC_GET_PRIVATE (self); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); const gchar *from; WockyNode *data; GString *str; guchar *st; gsize outlen; TpHandle sender; GString *buffer; const gchar *frag_val; guint frag; gboolean fully_received = FALSE; /* caller must have checked for this in order to know which bytestream to * route this packet to */ data = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "data", NS_MUC_BYTESTREAM); g_assert (data != NULL); if (priv->state != GABBLE_BYTESTREAM_STATE_OPEN) { DEBUG ("can't receive data through a not open bytestream (state: %d)", priv->state); return; } from = wocky_node_get_attribute ( wocky_stanza_get_top_node (msg), "from"); g_return_if_fail (from != NULL); sender = tp_handle_lookup (contact_repo, from, GUINT_TO_POINTER (GABBLE_JID_ROOM_MEMBER), NULL); if (sender == 0) { DEBUG ("ignoring data in MUC from unknown contact %s", from); return; } frag_val = wocky_node_get_attribute (data, "frag"); if (frag_val == NULL) frag = FRAG_COMPLETE; else if (!tp_strdiff (frag_val, "first")) frag = FRAG_FIRST; else if (!tp_strdiff (frag_val, "middle")) frag = FRAG_MIDDLE; else if (!tp_strdiff (frag_val, "last")) frag = FRAG_LAST; else if (!tp_strdiff (frag_val, "complete")) frag = FRAG_COMPLETE; else { DEBUG ("Invalid frag value: %s", frag_val); return; } st = g_base64_decode (data->content, &outlen); str = g_string_new_len ((const gchar *) st, outlen); g_free (st); if (str == NULL) { DEBUG ("base64 decoding failed"); return; } buffer = g_hash_table_lookup (priv->buffers, from); if (frag == FRAG_COMPLETE) { if (buffer != NULL) { DEBUG ("Drop incomplete buffer of %s. " "Received new unfragmented data", from); g_hash_table_remove (priv->buffers, from); } fully_received = TRUE; } else if (frag == FRAG_FIRST) { if (buffer != NULL) { DEBUG ("Drop incomplete buffer of %s. " "Received first part of new data", from); g_hash_table_remove (priv->buffers, from); } else { DEBUG ("New buffer for %s", from); } g_hash_table_insert (priv->buffers, g_strdup (from), str); } else if (frag == FRAG_MIDDLE) { if (buffer == NULL) { DEBUG ("Drop middle part stanza from %s, first parts not buffered", from); } else { DEBUG ("Append data to buffer of %s (%" G_GSIZE_FORMAT " bytes)", from, str->len); g_string_append_len (buffer, str->str, str->len); } g_string_free (str, TRUE); } else if (frag == FRAG_LAST) { if (buffer == NULL) { DEBUG ("Drop last part stanza from %s, first parts not buffered", from); g_string_free (str, TRUE); } else { DEBUG ("Received last part from %s, buffer flushed", from); g_string_prepend_len (str, buffer->str, buffer->len); g_hash_table_remove (priv->buffers, from); fully_received = TRUE; } } if (fully_received) { DEBUG ("fully received %" G_GSIZE_FORMAT " bytes of data", str->len); g_signal_emit_by_name (G_OBJECT (self), "data-received", sender, str); g_string_free (str, TRUE); } } /* * gabble_bytestream_muc_accept * * Implements gabble_bytestream_iface_accept on GabbleBytestreamIface */ static void gabble_bytestream_muc_accept (GabbleBytestreamIface *iface, GabbleBytestreamAugmentSiAcceptReply func, gpointer user_data) { /* Don't have to accept a muc bytestream */ } /* * gabble_bytestream_muc_close * * Implements gabble_bytestream_iface_close on GabbleBytestreamIface */ static void gabble_bytestream_muc_close (GabbleBytestreamIface *iface, GError *error) { GabbleBytestreamMuc *self = GABBLE_BYTESTREAM_MUC (iface); GabbleBytestreamMucPrivate *priv = GABBLE_BYTESTREAM_MUC_GET_PRIVATE (self); if (priv->state == GABBLE_BYTESTREAM_STATE_CLOSED) /* bytestream already closed, do nothing */ return; g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_CLOSED, NULL); } gboolean gabble_bytestream_muc_send_to (GabbleBytestreamMuc *self, TpHandle contact, guint len, gchar *str) { GabbleBytestreamMucPrivate *priv = GABBLE_BYTESTREAM_MUC_GET_PRIVATE (self); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); const gchar *to; to = tp_handle_inspect (contact_repo, contact); g_return_val_if_fail (g_str_has_prefix (to, priv->peer_jid), FALSE); g_return_val_if_fail (to[strlen (priv->peer_jid)] == '/', FALSE); return send_data_to (self, to, FALSE, len, str); } /* * gabll_bytestream_muc_initiate * * Implements gabble_bytestream_iface_initiate on GabbleBytestreamIface */ static gboolean gabble_bytestream_muc_initiate (GabbleBytestreamIface *iface) { /* Nothing to do */ return TRUE; } static void bytestream_iface_init (gpointer g_iface, gpointer iface_data) { GabbleBytestreamIfaceClass *klass = (GabbleBytestreamIfaceClass *) g_iface; klass->initiate = gabble_bytestream_muc_initiate; klass->send = gabble_bytestream_muc_send; klass->close = gabble_bytestream_muc_close; klass->accept = gabble_bytestream_muc_accept; } telepathy-gabble-0.18.3/src/muc-channel.c0000664000175000017500000037473512332441362021346 0ustar00cassidycassidy00000000000000/* * gabble-muc-channel.c - Source for GabbleMucChannel * Copyright (C) 2006 Collabora Ltd. * Copyright (C) 2006 Nokia Corporation * @author Ole Andre Vadla Ravnaas * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "muc-channel.h" #include #include #include #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_MUC #include "connection.h" #include "conn-aliasing.h" #include "conn-util.h" #include "debug.h" #include "disco.h" #include "error.h" #include "message-util.h" #include "room-config.h" #include "namespaces.h" #include "presence.h" #include "util.h" #include "presence-cache.h" #include "gabble-signals-marshal.h" #include "gabble-enumtypes.h" #include "tube-dbus.h" #include "tube-stream.h" #include "private-tubes-factory.h" #include "bytestream-factory.h" #define DEFAULT_JOIN_TIMEOUT 180 #define DEFAULT_LEAVE_TIMEOUT 180 #define MAX_NICK_RETRIES 3 #define PROPS_POLL_INTERVAL_LOW 60 * 5 #define PROPS_POLL_INTERVAL_HIGH 60 static void password_iface_init (gpointer, gpointer); static void subject_iface_init (gpointer, gpointer); #ifdef ENABLE_VOIP static void gabble_muc_channel_start_call_creation (GabbleMucChannel *gmuc, GHashTable *request); static void muc_call_channel_finish_requests (GabbleMucChannel *self, GabbleCallMucChannel *call, GError *error); #endif G_DEFINE_TYPE_WITH_CODE (GabbleMucChannel, gabble_muc_channel, TP_TYPE_BASE_CHANNEL, G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP, tp_group_mixin_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_PASSWORD, password_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_TEXT, tp_message_mixin_text_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_MESSAGES, tp_message_mixin_messages_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_CHAT_STATE, tp_message_mixin_chat_state_iface_init) G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_CONFERENCE, NULL); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_ROOM, NULL); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_ROOM_CONFIG, tp_base_room_config_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_SUBJECT, subject_iface_init); ) static void gabble_muc_channel_send (GObject *obj, TpMessage *message, TpMessageSendingFlags flags); static gboolean gabble_muc_channel_send_chat_state (GObject *object, TpChannelChatState state, GError **error); static void gabble_muc_channel_close (TpBaseChannel *base); /* signal enum */ enum { READY, JOIN_ERROR, PRE_INVITE, CONTACT_JOIN, PRE_PRESENCE, NEW_TUBE, #ifdef ENABLE_VOIP NEW_CALL, #endif LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; /* properties */ enum { PROP_STATE = 1, PROP_INITIALLY_REGISTER, PROP_INVITED, PROP_INVITATION_MESSAGE, PROP_SELF_JID, PROP_WOCKY_MUC, PROP_INITIAL_CHANNELS, PROP_INITIAL_INVITEE_HANDLES, PROP_INITIAL_INVITEE_IDS, PROP_ORIGINAL_CHANNELS, PROP_ROOM_NAME, PROP_SERVER, PROP_SUBJECT, PROP_SUBJECT_ACTOR, PROP_SUBJECT_TIMESTAMP, PROP_CAN_SET_SUBJECT, LAST_PROPERTY }; static const gchar *muc_states[] = { "MUC_STATE_CREATED", "MUC_STATE_INITIATED", "MUC_STATE_AUTH", "MUC_STATE_JOINED", "MUC_STATE_ENDED", }; /* private structures */ struct _GabbleMucChannelPrivate { GabbleMucState state; gboolean closing; gboolean autoclose; gboolean initially_register; guint join_timer_id; guint poll_timer_id; guint leave_timer_id; gboolean must_provide_password; DBusGMethodInvocation *password_ctx; const gchar *jid; gboolean requested; guint nick_retry_count; GString *self_jid; WockyMucRole self_role; WockyMucAffiliation self_affil; guint recv_id; TpBaseRoomConfig *room_config; GHashTable *properties_being_updated; /* Room interface */ gchar *room_name; gchar *server; /* Subject interface */ gchar *subject; gchar *subject_actor; gint64 subject_timestamp; gboolean can_set_subject; DBusGMethodInvocation *set_subject_context; gchar *set_subject_stanza_id; gboolean ready; gboolean dispose_has_run; gboolean invited; gchar *invitation_message; WockyMuc *wmuc; /* tube ID => owned GabbleTubeIface */ GHashTable *tubes; #ifdef ENABLE_VOIP /* Current active call */ GabbleCallMucChannel *call; /* All calls, active one + potential ended ones */ GList *calls; /* List of GSimpleAsyncResults for the various request for a call */ GList *call_requests; gboolean call_initiating; #endif GCancellable *requests_cancellable; GPtrArray *initial_channels; GArray *initial_handles; char **initial_ids; gboolean have_received_error_type_wait; }; typedef struct { GabbleMucChannel *channel; TpMessage *message; gchar *token; } _GabbleMUCSendMessageCtx; static GPtrArray * gabble_muc_channel_get_interfaces (TpBaseChannel *base) { GPtrArray *interfaces; interfaces = TP_BASE_CHANNEL_CLASS ( gabble_muc_channel_parent_class)->get_interfaces (base); g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_GROUP); g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_PASSWORD); g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_CHAT_STATE); g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_MESSAGES); g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_CONFERENCE); g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_ROOM); g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_ROOM_CONFIG); g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_SUBJECT); return interfaces; } static void gabble_muc_channel_init (GabbleMucChannel *self) { GabbleMucChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_MUC_CHANNEL, GabbleMucChannelPrivate); self->priv = priv; priv->requests_cancellable = g_cancellable_new (); priv->tubes = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_object_unref); } static TpHandle create_room_identity (GabbleMucChannel *) G_GNUC_WARN_UNUSED_RESULT; /* signatures for presence handlers */ static void handle_fill_presence (WockyMuc *muc, WockyStanza *stanza, gpointer user_data); static void handle_renamed (GObject *source, WockyStanza *stanza, guint codes, gpointer data); static void handle_error (GObject *source, WockyStanza *stanza, WockyXmppErrorType errtype, const GError *error, gpointer data); static void handle_join (WockyMuc *muc, WockyStanza *stanza, guint codes, gpointer data); static void handle_parted (GObject *source, WockyStanza *stanza, guint codes, const gchar *actor_jid, const gchar *why, const gchar *msg, gpointer data); static void handle_left (GObject *source, WockyStanza *stanza, guint codes, WockyMucMember *who, const gchar *actor_jid, const gchar *why, const gchar *msg, gpointer data); static void handle_presence (GObject *source, WockyStanza *stanza, guint codes, WockyMucMember *who, gpointer data); static void handle_perms (GObject *source, WockyStanza *stanza, GHashTable *code, const gchar *actor, const gchar *why, gpointer data); /* signatures for message handlers */ static void handle_message (GObject *source, WockyStanza *stanza, WockyMucMsgType type, const gchar *xmpp_id, GDateTime *datetime, WockyMucMember *who, const gchar *text, const gchar *subject, WockyMucMsgState state, gpointer data); static void handle_errmsg (GObject *source, WockyStanza *stanza, WockyMucMsgType type, const gchar *xmpp_id, GDateTime *datetime, WockyMucMember *who, const gchar *text, WockyXmppErrorType etype, const GError *error, gpointer data); /* Signatures for some other stuff. */ static void _gabble_muc_channel_handle_subject (GabbleMucChannel *chan, TpHandleType handle_type, TpHandle sender, GDateTime *datetime, const gchar *subject, WockyStanza *msg, const GError *error); static void _gabble_muc_channel_receive (GabbleMucChannel *chan, TpChannelTextMessageType msg_type, TpHandleType handle_type, TpHandle sender, GDateTime *datetime, const gchar *id, const gchar *text, WockyStanza *msg, const GError *send_error, TpDeliveryStatus delivery_status); static void gabble_muc_channel_constructed (GObject *obj) { GabbleMucChannel *self = GABBLE_MUC_CHANNEL (obj); GabbleMucChannelPrivate *priv = self->priv; TpBaseChannel *base = TP_BASE_CHANNEL (self); TpBaseConnection *base_conn = tp_base_channel_get_connection (base); TpHandleRepoIface *room_handles, *contact_handles; TpHandle target, initiator, self_handle; gchar *tmp; TpChannelTextMessageType types[] = { TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION, TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE, }; const gchar * supported_content_types[] = { "text/plain", NULL }; void (*chain_up) (GObject *) = ((GObjectClass *) gabble_muc_channel_parent_class)->constructed; gboolean ok; if (chain_up != NULL) chain_up (obj); room_handles = tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_ROOM); contact_handles = tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT); /* get, and sanity-check, the room's jid */ target = tp_base_channel_get_target_handle (base); priv->jid = tp_handle_inspect (room_handles, target); g_assert (priv->jid != NULL && strchr (priv->jid, '/') == NULL); /* The factory should have given us an initiator */ initiator = tp_base_channel_get_initiator (base); g_assert (initiator != 0); /* create our own identity in the room */ self_handle = create_room_identity (self); /* this causes us to have one ref to the self handle which is unreffed * at the end of this function */ /* initialize our own role and affiliation */ priv->self_role = WOCKY_MUC_ROLE_NONE; priv->self_affil = WOCKY_MUC_AFFILIATION_NONE; /* initialise the wocky muc object */ { GabbleConnection *conn = GABBLE_CONNECTION (base_conn); WockyPorter *porter = gabble_connection_dup_porter (conn); const gchar *room_jid = tp_handle_inspect (contact_handles, self_handle); gchar *user_jid = gabble_connection_get_full_jid (conn); WockyMuc *wmuc = g_object_new (WOCKY_TYPE_MUC, "porter", porter, "jid", room_jid, /* room@service.name/nick */ "user", user_jid, /* user@doma.in/resource */ NULL); /* various presence handlers */ g_signal_connect (wmuc, "nick-change", (GCallback) handle_renamed, self); g_signal_connect (wmuc, "presence", (GCallback) handle_presence, self); g_signal_connect (wmuc, "joined", (GCallback) handle_join, self); g_signal_connect (wmuc, "permissions", (GCallback) handle_perms, self); g_signal_connect (wmuc, "parted", (GCallback) handle_parted, self); g_signal_connect (wmuc, "left", (GCallback) handle_left, self); g_signal_connect (wmuc, "error", (GCallback) handle_error, self); g_signal_connect (wmuc, "fill-presence", G_CALLBACK (handle_fill_presence), self); /* message handler(s) (just one needed so far) */ g_signal_connect (wmuc, "message", (GCallback) handle_message, self); g_signal_connect (wmuc, "message-error",(GCallback) handle_errmsg, self); priv->wmuc = wmuc; g_free (user_jid); g_object_unref (porter); } /* register object on the bus */ if (priv->initially_register) tp_base_channel_register (base); /* initialize group mixin */ tp_group_mixin_init (obj, G_STRUCT_OFFSET (GabbleMucChannel, group), contact_handles, self_handle); /* set initial group flags */ tp_group_mixin_change_flags (obj, TP_CHANNEL_GROUP_FLAG_PROPERTIES | TP_CHANNEL_GROUP_FLAG_CHANNEL_SPECIFIC_HANDLES | TP_CHANNEL_GROUP_FLAG_HANDLE_OWNERS_NOT_AVAILABLE | TP_CHANNEL_GROUP_FLAG_CAN_ADD, 0); /* initialize message mixin */ tp_message_mixin_init (obj, G_STRUCT_OFFSET (GabbleMucChannel, message_mixin), base_conn); tp_message_mixin_implement_sending (obj, gabble_muc_channel_send, G_N_ELEMENTS (types), types, 0, TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_FAILURES | TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_SUCCESSES, supported_content_types); tp_message_mixin_implement_send_chat_state (obj, gabble_muc_channel_send_chat_state); tp_group_mixin_add_handle_owner (obj, self_handle, tp_base_connection_get_self_handle (base_conn)); /* Room interface */ g_object_get (self, "target-id", &tmp, NULL); if (priv->room_name != NULL) ok = wocky_decode_jid (tmp, NULL, &(priv->server), NULL); else ok = wocky_decode_jid (tmp, &(priv->room_name), &(priv->server), NULL); g_free (tmp); /* Asserting here is fine because the target ID has already been * checked so we know it's valid. */ g_assert (ok); priv->subject = NULL; priv->subject_actor = NULL; priv->subject_timestamp = G_MAXINT64; /* fd.o#13157: The subject is currently assumed to be modifiable by everyone * in the room (role >= VISITOR). When that bug is fixed, it will be: */ /* Modifiable via special s, if the user's role is high enough; * "high enough" is defined by the muc#roominfo_changesubject and * muc#roomconfig_changesubject settings. */ priv->can_set_subject = TRUE; { TpBaseRoomConfigProperty mutable_properties[] = { TP_BASE_ROOM_CONFIG_ANONYMOUS, TP_BASE_ROOM_CONFIG_INVITE_ONLY, TP_BASE_ROOM_CONFIG_MODERATED, TP_BASE_ROOM_CONFIG_TITLE, TP_BASE_ROOM_CONFIG_PERSISTENT, TP_BASE_ROOM_CONFIG_PRIVATE, TP_BASE_ROOM_CONFIG_PASSWORD_PROTECTED, TP_BASE_ROOM_CONFIG_PASSWORD, }; guint i; priv->room_config = (TpBaseRoomConfig *) gabble_room_config_new ((TpBaseChannel *) self); for (i = 0; i < G_N_ELEMENTS (mutable_properties); i++) tp_base_room_config_set_property_mutable (priv->room_config, mutable_properties[i], TRUE); /* Just to get those mutable properties out there. */ tp_base_room_config_emit_properties_changed (priv->room_config); } if (priv->invited) { /* invited: add ourself to local pending and the inviter to members */ TpIntset *members = tp_intset_new_containing (initiator); TpIntset *pending = tp_intset_new_containing (self_handle); tp_group_mixin_change_members (obj, priv->invitation_message, members, NULL, pending, NULL, initiator, TP_CHANNEL_GROUP_CHANGE_REASON_INVITED); tp_intset_destroy (members); tp_intset_destroy (pending); /* we've dealt with it (and copied it elsewhere), so there's no point * in keeping it */ g_free (priv->invitation_message); priv->invitation_message = NULL; /* mark channel ready so NewChannel is emitted immediately */ priv->ready = TRUE; } else { /* not invited: add ourselves to members (and hence join immediately) */ GError *error = NULL; GArray *members = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), 1); g_assert (initiator == tp_base_connection_get_self_handle (base_conn)); g_assert (priv->invitation_message == NULL); g_array_append_val (members, self_handle); tp_group_mixin_add_members (obj, members, "", &error); g_assert (error == NULL); g_array_unref (members); } } typedef struct { const gchar *var; const gchar *config_property_name; gboolean value; } FeatureMapping; static FeatureMapping * lookup_feature (const gchar *var) { static FeatureMapping features[] = { { "muc_nonanonymous", "anonymous", FALSE }, { "muc_semianonymous", "anonymous", TRUE }, { "muc_anonymous", "anonymous", TRUE }, { "muc_open", "invite-only", FALSE }, { "muc_membersonly", "invite-only", TRUE }, { "muc_unmoderated", "moderated", FALSE }, { "muc_moderated", "moderated", TRUE }, { "muc_unsecure", "password-protected", FALSE }, { "muc_unsecured", "password-protected", FALSE }, { "muc_passwordprotected", "password-protected", TRUE }, { "muc_temporary", "persistent", FALSE }, { "muc_persistent", "persistent", TRUE }, { "muc_public", "private", FALSE }, { "muc_hidden", "private", TRUE }, /* The MUC namespace is included as a feature in disco results. We ignore * it here. */ { NS_MUC, NULL, FALSE }, { NULL } }; FeatureMapping *f; for (f = features; f->var != NULL; f++) if (strcmp (var, f->var) == 0) return f; return NULL; } static const gchar * map_feature ( WockyNode *feature, GValue *value) { const gchar *var = wocky_node_get_attribute (feature, "var"); FeatureMapping *f; if (var == NULL) return NULL; f = lookup_feature (var); if (f == NULL) { DEBUG ("unhandled feature '%s'", var); return NULL; } if (f->config_property_name != NULL) { g_value_init (value, G_TYPE_BOOLEAN); g_value_set_boolean (value, f->value); } return f->config_property_name; } static const gchar * handle_form ( WockyNode *x, GValue *value) { WockyNodeIter j; WockyNode *field; wocky_node_iter_init (&j, x, "field", NULL); while (wocky_node_iter_next (&j, &field)) { const gchar *var = wocky_node_get_attribute (field, "var"); const gchar *description; if (tp_strdiff (var, "muc#roominfo_description")) continue; description = wocky_node_get_content_from_child (field, "value"); g_value_init (value, G_TYPE_STRING); g_value_set_string (value, description != NULL ? description : ""); return "description"; } return NULL; } static void properties_disco_cb (GabbleDisco *disco, GabbleDiscoRequest *request, const gchar *jid, const gchar *node, WockyNode *query_result, GError *error, gpointer user_data) { GabbleMucChannel *chan = user_data; GabbleMucChannelPrivate *priv = chan->priv; WockyNode *lm_node; WockyNodeIter i; WockyNode *child; g_assert (GABBLE_IS_MUC_CHANNEL (chan)); if (error) { DEBUG ("got error %s", error->message); return; } /* * Update room definition. */ /* ROOM_PROP_NAME */ lm_node = wocky_node_get_child (query_result, "identity"); if (lm_node) { const gchar *category, *type, *name; category = wocky_node_get_attribute (lm_node, "category"); type = wocky_node_get_attribute (lm_node, "type"); name = wocky_node_get_attribute (lm_node, "name"); if (!tp_strdiff (category, "conference") && !tp_strdiff (type, "text") && name != NULL) { g_object_set (priv->room_config, "title", name, NULL); } } wocky_node_iter_init (&i, query_result, NULL, NULL); while (wocky_node_iter_next (&i, &child)) { const gchar *config_property_name = NULL; GValue val = { 0, }; if (strcmp (child->name, "feature") == 0) { config_property_name = map_feature (child, &val); } else if (strcmp (child->name, "x") == 0 && wocky_node_has_ns (child, NS_X_DATA)) { config_property_name = handle_form (child, &val); } if (config_property_name != NULL) { g_object_set_property ((GObject *) priv->room_config, config_property_name, &val); g_value_unset (&val); } } /* This could be the first time we've fetched the room properties, or it * could be a later time; either way, this method does the right thing. */ tp_base_room_config_set_retrieved (priv->room_config); } static void room_properties_update (GabbleMucChannel *chan) { GabbleMucChannelPrivate *priv; TpBaseChannel *base; GabbleConnection *conn; GError *error = NULL; g_assert (GABBLE_IS_MUC_CHANNEL (chan)); priv = chan->priv; base = TP_BASE_CHANNEL (chan); conn = GABBLE_CONNECTION (tp_base_channel_get_connection (base)); if (gabble_disco_request (conn->disco, GABBLE_DISCO_TYPE_INFO, priv->jid, NULL, properties_disco_cb, chan, G_OBJECT (chan), &error) == NULL) { DEBUG ("disco query failed: '%s'", error->message); g_error_free (error); } } static TpHandle create_room_identity (GabbleMucChannel *chan) { TpBaseChannel *base = TP_BASE_CHANNEL (chan); GabbleMucChannelPrivate *priv = chan->priv; TpBaseConnection *conn = tp_base_channel_get_connection (base); TpHandleRepoIface *contact_repo; gchar *alias = NULL; GabbleConnectionAliasSource source; contact_repo = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT); g_assert (priv->self_jid == NULL); source = _gabble_connection_get_cached_alias (GABBLE_CONNECTION (conn), tp_base_connection_get_self_handle (conn), &alias); g_assert (alias != NULL); if (source == GABBLE_CONNECTION_ALIAS_FROM_JID) { /* If our 'alias' is, in fact, our JID, we'll just use the local part as * our MUC resource. */ gchar *local_part; g_assert (wocky_decode_jid (alias, &local_part, NULL, NULL)); g_assert (local_part != NULL); g_free (alias); alias = local_part; } priv->self_jid = g_string_new (priv->jid); g_string_append_c (priv->self_jid, '/'); g_string_append (priv->self_jid, alias); g_free (alias); return tp_handle_ensure (contact_repo, priv->self_jid->str, GUINT_TO_POINTER (GABBLE_JID_ROOM_MEMBER), NULL); } static void send_join_request (GabbleMucChannel *gmuc) { GabbleMucChannelPrivate *priv = gmuc->priv; wocky_muc_join (priv->wmuc, NULL); } static void tube_pre_presence (GabbleMucChannel *gmuc, WockyStanza *stanza) { GabbleMucChannelPrivate *priv = gmuc->priv; TpBaseConnection *conn = tp_base_channel_get_connection ( TP_BASE_CHANNEL (gmuc)); WockyNode *tubes_node; GHashTableIter iter; gpointer value; tubes_node = wocky_node_add_child_with_content_ns ( wocky_stanza_get_top_node (stanza), "tubes", NULL, NS_TUBES); g_hash_table_iter_init (&iter, priv->tubes); while (g_hash_table_iter_next (&iter, NULL, &value)) { GabbleTubeIface *tube = value; TpTubeChannelState state; WockyNode *tube_node; TpTubeType type; TpHandle initiator; g_object_get (tube, "state", &state, "type", &type, "initiator-handle", &initiator, NULL); if (state != TP_TUBE_CHANNEL_STATE_OPEN) continue; if (type == TP_TUBE_TYPE_STREAM && initiator != TP_GROUP_MIXIN (gmuc)->self_handle) /* We only announce stream tubes we initiated */ continue; tube_node = wocky_node_add_child_with_content (tubes_node, "tube", NULL); gabble_tube_iface_publish_in_node (tube, conn, tube_node); } } static gboolean timeout_leave (gpointer data) { GabbleMucChannel *chan = data; DEBUG ("leave timed out (we never got our unavailable presence echoed " "back to us by the conf server), closing channel now"); tp_base_channel_destroyed (TP_BASE_CHANNEL (chan)); return FALSE; } static void send_leave_message (GabbleMucChannel *gmuc, const gchar *reason) { GabbleMucChannelPrivate *priv = gmuc->priv; TpBaseChannel *base = TP_BASE_CHANNEL (gmuc); WockyStanza *stanza = wocky_muc_create_presence (priv->wmuc, WOCKY_STANZA_SUB_TYPE_UNAVAILABLE, reason); tube_pre_presence (gmuc, stanza); g_signal_emit (gmuc, signals[PRE_PRESENCE], 0, stanza); _gabble_connection_send ( GABBLE_CONNECTION (tp_base_channel_get_connection (base)), stanza, NULL); g_object_unref (stanza); priv->leave_timer_id = g_timeout_add_seconds (DEFAULT_LEAVE_TIMEOUT, timeout_leave, gmuc); } static void gabble_muc_channel_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleMucChannel *chan = GABBLE_MUC_CHANNEL (object); GabbleMucChannelPrivate *priv = chan->priv; switch (property_id) { case PROP_STATE: g_value_set_uint (value, priv->state); break; case PROP_INITIALLY_REGISTER: g_value_set_boolean (value, priv->initially_register); break; case PROP_SELF_JID: g_value_set_string (value, priv->self_jid->str); break; case PROP_WOCKY_MUC: g_value_set_object (value, priv->wmuc); break; case PROP_INVITATION_MESSAGE: g_value_set_string (value, ""); break; case PROP_INITIAL_CHANNELS: g_value_set_boxed (value, priv->initial_channels); break; case PROP_INITIAL_INVITEE_HANDLES: g_value_set_boxed (value, priv->initial_handles); break; case PROP_INITIAL_INVITEE_IDS: g_value_set_boxed (value, priv->initial_ids); break; case PROP_ORIGINAL_CHANNELS: /* We don't have a useful value for this - we don't necessarily know * which chatroom member is which global handle, and the main purpose * of OriginalChannels is to be able to split off merged channels, * which we can't do anyway in XMPP. */ g_value_take_boxed (value, g_hash_table_new (NULL, NULL)); break; case PROP_ROOM_NAME: g_value_set_string (value, priv->room_name); break; case PROP_SERVER: g_value_set_string (value, priv->server); break; case PROP_SUBJECT: g_value_set_string (value, priv->subject); break; case PROP_SUBJECT_ACTOR: g_value_set_string (value, priv->subject_actor); break; case PROP_SUBJECT_TIMESTAMP: g_value_set_int64 (value, priv->subject_timestamp); break; case PROP_CAN_SET_SUBJECT: g_value_set_boolean (value, priv->can_set_subject); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void channel_state_changed (GabbleMucChannel *chan, GabbleMucState prev_state, GabbleMucState new_state); static void gabble_muc_channel_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleMucChannel *chan = GABBLE_MUC_CHANNEL (object); GabbleMucChannelPrivate *priv = chan->priv; GabbleMucState prev_state; switch (property_id) { case PROP_STATE: prev_state = priv->state; priv->state = g_value_get_uint (value); if (priv->state != prev_state) channel_state_changed (chan, prev_state, priv->state); break; case PROP_INITIALLY_REGISTER: priv->initially_register = g_value_get_boolean (value); break; case PROP_INVITED: priv->invited = g_value_get_boolean (value); break; case PROP_INVITATION_MESSAGE: g_assert (priv->invitation_message == NULL); priv->invitation_message = g_value_dup_string (value); break; case PROP_INITIAL_CHANNELS: priv->initial_channels = g_value_dup_boxed (value); g_assert (priv->initial_channels != NULL); break; case PROP_INITIAL_INVITEE_HANDLES: priv->initial_handles = g_value_dup_boxed (value); g_assert (priv->initial_handles != NULL); break; case PROP_INITIAL_INVITEE_IDS: priv->initial_ids = g_value_dup_boxed (value); break; case PROP_ROOM_NAME: priv->room_name = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_muc_channel_dispose (GObject *object); static void gabble_muc_channel_finalize (GObject *object); static gboolean gabble_muc_channel_add_member (GObject *obj, TpHandle handle, const gchar *message, GError **error); static gboolean gabble_muc_channel_remove_member (GObject *obj, TpHandle handle, const gchar *message, GError **error); static void gabble_muc_channel_fill_immutable_properties ( TpBaseChannel *chan, GHashTable *properties) { TP_BASE_CHANNEL_CLASS (gabble_muc_channel_parent_class)->fill_immutable_properties ( chan, properties); tp_dbus_properties_mixin_fill_properties_hash ( G_OBJECT (chan), properties, TP_IFACE_CHANNEL_INTERFACE_CONFERENCE, "InitialChannels", TP_IFACE_CHANNEL_INTERFACE_CONFERENCE, "InitialInviteeHandles", TP_IFACE_CHANNEL_INTERFACE_CONFERENCE, "InitialInviteeIDs", TP_IFACE_CHANNEL_INTERFACE_CONFERENCE, "InvitationMessage", TP_IFACE_CHANNEL_INTERFACE_MESSAGES, "MessagePartSupportFlags", TP_IFACE_CHANNEL_INTERFACE_MESSAGES, "DeliveryReportingSupport", TP_IFACE_CHANNEL_INTERFACE_MESSAGES, "SupportedContentTypes", TP_IFACE_CHANNEL_INTERFACE_MESSAGES, "MessageTypes", TP_IFACE_CHANNEL_INTERFACE_ROOM, "RoomName", TP_IFACE_CHANNEL_INTERFACE_ROOM, "Server", NULL); } static void gabble_muc_channel_class_init (GabbleMucChannelClass *gabble_muc_channel_class) { static TpDBusPropertiesMixinPropImpl conference_props[] = { { "Channels", "initial-channels", NULL, }, { "InitialChannels", "initial-channels", NULL }, { "InitialInviteeHandles", "initial-invitee-handles", NULL }, { "InitialInviteeIDs", "initial-invitee-ids", NULL }, { "InvitationMessage", "invitation-message", NULL }, { "OriginalChannels", "original-channels", NULL }, { NULL } }; static TpDBusPropertiesMixinPropImpl room_props[] = { { "RoomName", "room-name", NULL, }, { "Server", "server", NULL }, { NULL } }; static TpDBusPropertiesMixinPropImpl subject_props[] = { { "Subject", "subject", NULL }, { "Actor", "subject-actor", NULL }, { "Timestamp", "subject-timestamp", NULL }, { "CanSet", "can-set-subject", NULL }, { NULL } }; static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { { TP_IFACE_CHANNEL_INTERFACE_CONFERENCE, tp_dbus_properties_mixin_getter_gobject_properties, NULL, conference_props, }, { TP_IFACE_CHANNEL_INTERFACE_ROOM, tp_dbus_properties_mixin_getter_gobject_properties, NULL, room_props, }, { TP_IFACE_CHANNEL_INTERFACE_SUBJECT, tp_dbus_properties_mixin_getter_gobject_properties, NULL, subject_props, }, { NULL } }; GObjectClass *object_class = G_OBJECT_CLASS (gabble_muc_channel_class); TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (object_class); GParamSpec *param_spec; g_type_class_add_private (gabble_muc_channel_class, sizeof (GabbleMucChannelPrivate)); object_class->constructed = gabble_muc_channel_constructed; object_class->get_property = gabble_muc_channel_get_property; object_class->set_property = gabble_muc_channel_set_property; object_class->dispose = gabble_muc_channel_dispose; object_class->finalize = gabble_muc_channel_finalize; base_class->channel_type = TP_IFACE_CHANNEL_TYPE_TEXT; base_class->target_handle_type = TP_HANDLE_TYPE_ROOM; base_class->get_interfaces = gabble_muc_channel_get_interfaces; base_class->fill_immutable_properties = gabble_muc_channel_fill_immutable_properties; base_class->close = gabble_muc_channel_close; param_spec = g_param_spec_uint ("state", "Channel state", "The current state that the channel is in.", 0, G_MAXUINT32, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_STATE, param_spec); param_spec = g_param_spec_boolean ("initially-register", "Initially register", "whether to register the channel on the bus on creation", TRUE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INITIALLY_REGISTER, param_spec); param_spec = g_param_spec_boolean ("invited", "Invited?", "Whether the user has been invited to the channel.", FALSE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INVITED, param_spec); param_spec = g_param_spec_string ("invitation-message", "Invitation message", "The message we were sent when invited; NULL if not invited or if " "already processed", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INVITATION_MESSAGE, param_spec); param_spec = g_param_spec_string ("self-jid", "Our self JID", "Our self muc jid in this room", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SELF_JID, param_spec); param_spec = g_param_spec_object ("wocky-muc", "Wocky MUC Object", "The backend (Wocky) MUC instance", WOCKY_TYPE_MUC, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_WOCKY_MUC, param_spec); param_spec = g_param_spec_boxed ("initial-channels", "Initial Channels", "The initial channels offered with this Conference", TP_ARRAY_TYPE_OBJECT_PATH_LIST, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INITIAL_CHANNELS, param_spec); param_spec = g_param_spec_boxed ("initial-invitee-handles", "Initial Invitee Handles", "The handles of the Conference's initial invitees", DBUS_TYPE_G_UINT_ARRAY, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INITIAL_INVITEE_HANDLES, param_spec); param_spec = g_param_spec_boxed ("initial-invitee-ids", "Initial Invitee IDs", "The identifiers of the Conference's initial invitees", G_TYPE_STRV, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INITIAL_INVITEE_IDS, param_spec); param_spec = g_param_spec_boxed ("original-channels", "OriginalChannels", "Map from channel-specific handles to originally-offered channels", TP_HASH_TYPE_CHANNEL_ORIGINATOR_MAP, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ORIGINAL_CHANNELS, param_spec); param_spec = g_param_spec_string ("room-name", "RoomName", "The human-readable identifier of a chat room.", "", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ROOM_NAME, param_spec); param_spec = g_param_spec_string ("server", "Server", "the DNS name of the server hosting this channel", "", G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SERVER, param_spec); param_spec = g_param_spec_string ("subject", "Subject.Subject", "The subject of the room", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SUBJECT, param_spec); param_spec = g_param_spec_string ("subject-actor", "Subject.Actor", "The JID of the contact who last changed the subject", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SUBJECT_ACTOR, param_spec); param_spec = g_param_spec_int64 ("subject-timestamp", "Subject.Timestamp", "The UNIX timestamp at which the subject was last changed", G_MININT64, G_MAXINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SUBJECT_TIMESTAMP, param_spec); param_spec = g_param_spec_boolean ("can-set-subject", "Subject.CanSet", "Whether we believe we can set the subject", TRUE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CAN_SET_SUBJECT, param_spec); signals[READY] = g_signal_new ("ready", G_OBJECT_CLASS_TYPE (gabble_muc_channel_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[JOIN_ERROR] = g_signal_new ("join-error", G_OBJECT_CLASS_TYPE (gabble_muc_channel_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[PRE_INVITE] = g_signal_new ("pre-invite", G_OBJECT_CLASS_TYPE (gabble_muc_channel_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); signals[CONTACT_JOIN] = g_signal_new ("contact-join", G_OBJECT_CLASS_TYPE (gabble_muc_channel_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals[PRE_PRESENCE] = g_signal_new ("pre-presence", G_OBJECT_CLASS_TYPE (gabble_muc_channel_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[NEW_TUBE] = g_signal_new ("new-tube", G_OBJECT_CLASS_TYPE (gabble_muc_channel_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, /* this should be GABBLE_TYPE_TUBE_IFACE but GObject * wants a value type, not an interface. */ G_TYPE_NONE, 1, TP_TYPE_BASE_CHANNEL); #ifdef ENABLE_VOIP signals[NEW_CALL] = g_signal_new ("new-call", G_OBJECT_CLASS_TYPE (gabble_muc_channel_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, gabble_marshal_VOID__OBJECT_POINTER, G_TYPE_NONE, 2, GABBLE_TYPE_CALL_MUC_CHANNEL, G_TYPE_POINTER); #endif gabble_muc_channel_class->dbus_props_class.interfaces = prop_interfaces; tp_dbus_properties_mixin_class_init (object_class, G_STRUCT_OFFSET (GabbleMucChannelClass, dbus_props_class)); tp_message_mixin_init_dbus_properties (object_class); tp_base_room_config_register_class (base_class); tp_group_mixin_class_init (object_class, G_STRUCT_OFFSET (GabbleMucChannelClass, group_class), gabble_muc_channel_add_member, gabble_muc_channel_remove_member); tp_group_mixin_init_dbus_properties (object_class); tp_group_mixin_class_allow_self_removal (object_class); } static void clear_join_timer (GabbleMucChannel *chan); static void clear_poll_timer (GabbleMucChannel *chan); static void clear_leave_timer (GabbleMucChannel *chan); void gabble_muc_channel_dispose (GObject *object) { GabbleMucChannel *self = GABBLE_MUC_CHANNEL (object); GabbleMucChannelPrivate *priv = self->priv; if (priv->dispose_has_run) return; DEBUG ("called"); priv->dispose_has_run = TRUE; clear_join_timer (self); clear_poll_timer (self); clear_leave_timer (self); tp_clear_object (&priv->wmuc); tp_clear_object (&priv->requests_cancellable); tp_clear_object (&priv->room_config); tp_clear_pointer (&priv->tubes, g_hash_table_unref); if (G_OBJECT_CLASS (gabble_muc_channel_parent_class)->dispose) G_OBJECT_CLASS (gabble_muc_channel_parent_class)->dispose (object); } void gabble_muc_channel_finalize (GObject *object) { GabbleMucChannel *self = GABBLE_MUC_CHANNEL (object); GabbleMucChannelPrivate *priv = self->priv; DEBUG ("called"); /* free any data held directly by the object here */ if (priv->self_jid) { g_string_free (priv->self_jid, TRUE); } if (priv->initial_channels != NULL) { g_boxed_free (TP_ARRAY_TYPE_OBJECT_PATH_LIST, priv->initial_channels); priv->initial_channels = NULL; } if (priv->initial_handles != NULL) { g_boxed_free (DBUS_TYPE_G_UINT_ARRAY, priv->initial_handles); priv->initial_handles = NULL; } if (priv->initial_ids != NULL) { g_boxed_free (G_TYPE_STRV, priv->initial_ids); priv->initial_ids = NULL; } g_free (priv->room_name); g_free (priv->server); g_free (priv->subject); g_free (priv->subject_actor); tp_group_mixin_finalize (object); tp_message_mixin_finalize (object); G_OBJECT_CLASS (gabble_muc_channel_parent_class)->finalize (object); } static void clear_join_timer (GabbleMucChannel *chan) { GabbleMucChannelPrivate *priv = chan->priv; if (priv->join_timer_id != 0) { g_source_remove (priv->join_timer_id); priv->join_timer_id = 0; } } static void clear_poll_timer (GabbleMucChannel *chan) { GabbleMucChannelPrivate *priv = chan->priv; if (priv->poll_timer_id != 0) { g_source_remove (priv->poll_timer_id); priv->poll_timer_id = 0; } } static void clear_leave_timer (GabbleMucChannel *chan) { GabbleMucChannelPrivate *priv = chan->priv; if (priv->leave_timer_id != 0) { g_source_remove (priv->leave_timer_id); priv->leave_timer_id = 0; } } static void change_must_provide_password ( GabbleMucChannel *chan, gboolean must_provide_password) { GabbleMucChannelPrivate *priv; TpChannelPasswordFlags added, removed; g_assert (GABBLE_IS_MUC_CHANNEL (chan)); priv = chan->priv; if (priv->must_provide_password == !!must_provide_password) return; priv->must_provide_password = !!must_provide_password; if (must_provide_password) { added = TP_CHANNEL_PASSWORD_FLAG_PROVIDE; removed = 0; } else { added = 0; removed = TP_CHANNEL_PASSWORD_FLAG_PROVIDE; } DEBUG ("emitting password flags changed, added 0x%X, removed 0x%X", added, removed); tp_svc_channel_interface_password_emit_password_flags_changed ( chan, added, removed); } static void provide_password_return_if_pending (GabbleMucChannel *chan, gboolean success) { GabbleMucChannelPrivate *priv = chan->priv; if (priv->password_ctx) { dbus_g_method_return (priv->password_ctx, success); priv->password_ctx = NULL; } if (success) { change_must_provide_password (chan, FALSE); } } static void close_channel (GabbleMucChannel *chan, const gchar *reason, gboolean inform_muc, TpHandle actor, guint reason_code); static gboolean timeout_join (gpointer data) { GabbleMucChannel *chan = data; DEBUG ("join timed out, closing channel"); provide_password_return_if_pending (chan, FALSE); close_channel (chan, NULL, FALSE, 0, 0); return FALSE; } static gboolean timeout_poll (gpointer data) { GabbleMucChannel *chan = data; DEBUG ("polling for room properties"); room_properties_update (chan); return TRUE; } static void channel_state_changed (GabbleMucChannel *chan, GabbleMucState prev_state, GabbleMucState new_state) { GabbleMucChannelPrivate *priv = chan->priv; TpBaseChannel *base = TP_BASE_CHANNEL (chan); DEBUG ("state changed from %s to %s", muc_states[prev_state], muc_states[new_state]); if (new_state == MUC_STATE_INITIATED) { priv->join_timer_id = g_timeout_add_seconds (DEFAULT_JOIN_TIMEOUT, timeout_join, chan); } else if (new_state == MUC_STATE_JOINED) { gboolean low_bandwidth; gint interval; provide_password_return_if_pending (chan, TRUE); clear_join_timer (chan); g_object_get (GABBLE_CONNECTION (tp_base_channel_get_connection (base)), "low-bandwidth", &low_bandwidth, NULL); if (low_bandwidth) interval = PROPS_POLL_INTERVAL_LOW; else interval = PROPS_POLL_INTERVAL_HIGH; priv->poll_timer_id = g_timeout_add_seconds (interval, timeout_poll, chan); } else if (new_state == MUC_STATE_ENDED) { clear_poll_timer (chan); } if (new_state == MUC_STATE_JOINED || new_state == MUC_STATE_AUTH) { if (!priv->ready) { g_signal_emit (chan, signals[READY], 0); priv->ready = TRUE; } } } static void return_from_set_subject ( GabbleMucChannel *self, const GError *error) { GabbleMucChannelPrivate *priv = self->priv; if (error == NULL) tp_svc_channel_interface_subject_return_from_set_subject ( priv->set_subject_context); else dbus_g_method_return_error (priv->set_subject_context, error); priv->set_subject_context = NULL; tp_clear_pointer (&priv->set_subject_stanza_id, g_free); } static void close_channel (GabbleMucChannel *chan, const gchar *reason, gboolean inform_muc, TpHandle actor, guint reason_code) { TpBaseChannel *base = TP_BASE_CHANNEL (chan); GabbleMucChannelPrivate *priv = chan->priv; GabbleConnection *conn = GABBLE_CONNECTION ( tp_base_channel_get_connection (base)); TpIntset *set; GArray *handles; GError error = { TP_ERROR, TP_ERROR_CANCELLED, "Muc channel closed below us" }; if (tp_base_channel_is_destroyed (base)) return; /* if priv->closing is TRUE, we're waiting for the MUC to echo our * presence. however, if we're being asked to close again, but this * time without letting the muc know, let's actually close. if we * don't then the channel won't disappear from the bus properly. */ if (priv->closing && !inform_muc) { clear_leave_timer (chan); tp_base_channel_destroyed (base); return; } /* If inform_muc is TRUE it means that we're closing the channel * gracefully and we don't mind if the channel doesn't actually * close behind the scenes if a tube/call is still open. Every call * to this function has inform_muc=FALSE, except for Channel.Close() * and RemoveMembers(self_handle) */ if (inform_muc && !gabble_muc_channel_can_be_closed (chan)) { priv->autoclose = TRUE; tp_base_channel_disappear (base); return; } DEBUG ("Closing"); /* Ensure we stay alive even while telling everyone else to abandon us. */ g_object_ref (chan); g_hash_table_remove_all (priv->tubes); #ifdef ENABLE_VOIP muc_call_channel_finish_requests (chan, NULL, &error); #endif g_cancellable_cancel (priv->requests_cancellable); #ifdef ENABLE_VOIP while (priv->calls != NULL) tp_base_channel_close (TP_BASE_CHANNEL (priv->calls->data)); #endif set = tp_intset_new_containing (TP_GROUP_MIXIN (chan)->self_handle); tp_group_mixin_change_members ((GObject *) chan, reason, NULL, set, NULL, NULL, actor, reason_code); tp_intset_destroy (set); /* If we're currently in the MUC, tell it we're leaving and wait for a reply; * handle_parted() will call tp_base_channel_destroyed() and all the Closed * signals will be emitted. (Since there's no waiting-for-password state on * the protocol level, MUC_STATE_AUTH doesn't count as ‘in the MUC’.) See * fd.o#19930 for more details. */ if (inform_muc && priv->state >= MUC_STATE_INITIATED && priv->state != MUC_STATE_AUTH) { send_leave_message (chan, reason); priv->closing = TRUE; } else { tp_base_channel_destroyed (base); } handles = tp_handle_set_to_array (chan->group.members); gabble_presence_cache_update_many (conn->presence_cache, handles, NULL, GABBLE_PRESENCE_UNKNOWN, NULL, 0); g_array_unref (handles); if (priv->set_subject_context != NULL) return_from_set_subject (chan, &error); g_object_set (chan, "state", MUC_STATE_ENDED, NULL); g_object_unref (chan); } gboolean _gabble_muc_channel_is_ready (GabbleMucChannel *chan) { GabbleMucChannelPrivate *priv; g_assert (GABBLE_IS_MUC_CHANNEL (chan)); priv = chan->priv; return priv->ready; } /* returns TRUE if there are no tube or Call channels open in this MUC */ gboolean gabble_muc_channel_can_be_closed (GabbleMucChannel *chan) { GabbleMucChannelPrivate *priv = chan->priv; if (g_hash_table_size (priv->tubes) > 0) return FALSE; if (priv->calls != NULL || priv->call_requests != NULL || priv->call_initiating) return FALSE; return TRUE; } gboolean gabble_muc_channel_get_autoclose (GabbleMucChannel *chan) { return chan->priv->autoclose; } void gabble_muc_channel_set_autoclose (GabbleMucChannel *chan, gboolean autoclose) { chan->priv->autoclose = autoclose; } static gboolean handle_nick_conflict (GabbleMucChannel *chan, WockyStanza *stanza, GError **tp_error) { GabbleMucChannelPrivate *priv = chan->priv; TpBaseChannel *base = TP_BASE_CHANNEL (chan); TpGroupMixin *mixin = TP_GROUP_MIXIN (chan); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( tp_base_channel_get_connection (base), TP_HANDLE_TYPE_CONTACT); TpHandle self_handle; TpIntset *add_rp, *remove_rp; const gchar *from = wocky_stanza_get_from (stanza); /* If this is a nick conflict message with a resource in the JID, and the * resource doesn't match the one we're currently trying to join as, then * ignore it. This works around a bug in Google Talk's MUC server, which * sends the conflict message twice. It's valid for there to be no resource * in the from='' field. If Google didn't include the resource, we couldn't * work around the bug; but they happen to do so, so yay. * * * FIXME: WockyMuc should provide a _join_async() method and do all this for * us. */ g_assert (from != NULL); if (strchr (from, '/') != NULL && tp_strdiff (from, priv->self_jid->str)) { DEBUG ("ignoring spurious conflict message for %s", from); return TRUE; } if (priv->nick_retry_count >= MAX_NICK_RETRIES) { g_set_error (tp_error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "nickname already in use and retry count exceeded"); return FALSE; } /* Add a _ to our jid, and update the group mixin's self handle * and remote pending members appropriately. */ g_string_append_c (priv->self_jid, '_'); g_object_set (priv->wmuc, "jid", priv->self_jid->str, NULL); self_handle = tp_handle_ensure (contact_repo, priv->self_jid->str, GUINT_TO_POINTER (GABBLE_JID_ROOM_MEMBER), NULL); add_rp = tp_intset_new (); remove_rp = tp_intset_new (); tp_intset_add (add_rp, self_handle); tp_intset_add (remove_rp, mixin->self_handle); tp_group_mixin_change_self_handle ((GObject *) chan, self_handle); tp_group_mixin_change_members ((GObject *) chan, NULL, NULL, remove_rp, NULL, add_rp, 0, TP_CHANNEL_GROUP_CHANGE_REASON_RENAMED); tp_intset_destroy (add_rp); tp_intset_destroy (remove_rp); priv->nick_retry_count++; send_join_request (chan); return TRUE; } static void room_created_submit_reply_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { if (conn_util_send_iq_finish (GABBLE_CONNECTION (source), result, NULL, NULL)) DEBUG ("failed to submit room config"); } static WockyNode * config_form_get_form_node (WockyStanza *stanza) { WockyNode *query, *x; WockyNodeIter i; /* find the query node */ query = wocky_node_get_child (wocky_stanza_get_top_node (stanza), "query"); if (query == NULL) return NULL; /* then the form node */ wocky_node_iter_init (&i, query, "x", NS_X_DATA); while (wocky_node_iter_next (&i, &x)) { if (!tp_strdiff (wocky_node_get_attribute (x, "type"), "form")) return x; } return NULL; } static void perms_config_form_reply_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { GabbleMucChannel *self = GABBLE_MUC_CHANNEL (user_data); GabbleMucChannelPrivate *priv = self->priv; WockyStanza *reply = NULL; WockyNode *form_node, *field; WockyNodeIter i; if (!conn_util_send_iq_finish (GABBLE_CONNECTION (source), result, &reply, NULL)) { DEBUG ("request for config form failed, property permissions " "will be inaccurate"); goto OUT; } /* just in case our affiliation has changed in the meantime */ if (priv->self_affil != WOCKY_MUC_AFFILIATION_OWNER) goto OUT; form_node = config_form_get_form_node (reply); if (form_node == NULL) { DEBUG ("form node not found, property permissions will be inaccurate"); goto OUT; } wocky_node_iter_init (&i, form_node, "field", NULL); while (wocky_node_iter_next (&i, &field)) { const gchar *var = wocky_node_get_attribute (field, "var"); if (!tp_strdiff (var, "muc#roomconfig_roomdesc") || !tp_strdiff (var, "muc#owner_roomdesc")) { tp_base_room_config_set_property_mutable (priv->room_config, TP_BASE_ROOM_CONFIG_DESCRIPTION, TRUE); tp_base_room_config_emit_properties_changed (priv->room_config); break; } } OUT: tp_clear_object (&reply); g_object_unref (self); } static void emit_subject_changed (GabbleMucChannel *chan) { const gchar *changed[] = { "Subject", "Actor", "Timestamp", NULL }; tp_dbus_properties_mixin_emit_properties_changed (G_OBJECT (chan), TP_IFACE_CHANNEL_INTERFACE_SUBJECT, changed); } static void update_permissions (GabbleMucChannel *chan) { GabbleMucChannelPrivate *priv = chan->priv; TpBaseChannel *base = TP_BASE_CHANNEL (chan); TpChannelGroupFlags grp_flags_add, grp_flags_rem; /* * Update group flags. */ grp_flags_add = TP_CHANNEL_GROUP_FLAG_CAN_ADD | TP_CHANNEL_GROUP_FLAG_MESSAGE_ADD; grp_flags_rem = 0; if (priv->self_role == WOCKY_MUC_ROLE_MODERATOR) { grp_flags_add |= TP_CHANNEL_GROUP_FLAG_CAN_REMOVE | TP_CHANNEL_GROUP_FLAG_MESSAGE_REMOVE; } else { grp_flags_rem |= TP_CHANNEL_GROUP_FLAG_CAN_REMOVE | TP_CHANNEL_GROUP_FLAG_MESSAGE_REMOVE; } tp_group_mixin_change_flags ((GObject *) chan, grp_flags_add, grp_flags_rem); /* Update RoomConfig.CanUpdateConfiguration */ /* The room configuration is part of the "room definition", so is defined by * the XEP to be editable only by owners. */ if (priv->self_affil == WOCKY_MUC_AFFILIATION_OWNER) { tp_base_room_config_set_can_update_configuration (priv->room_config, TRUE); } else { tp_base_room_config_set_can_update_configuration (priv->room_config, FALSE); } tp_base_room_config_emit_properties_changed (priv->room_config); if (priv->self_affil == WOCKY_MUC_AFFILIATION_OWNER) { /* request the configuration form purely to see if the description * is writable by us in this room. sigh. GO MUC!!! */ GabbleConnection *conn = GABBLE_CONNECTION ( tp_base_channel_get_connection (base)); WockyStanza *stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, priv->jid, '(', "query", ':', WOCKY_NS_MUC_OWNER, ')', NULL); conn_util_send_iq_async (conn, stanza, NULL, perms_config_form_reply_cb, g_object_ref (chan)); g_object_unref (stanza); } } /* connect to wocky-muc:SIG_PRESENCE_ERROR */ static void handle_error (GObject *source, WockyStanza *stanza, WockyXmppErrorType errtype, const GError *error, gpointer data) { GabbleMucChannel *gmuc = GABBLE_MUC_CHANNEL (data); GabbleMucChannelPrivate *priv = gmuc->priv; TpChannelGroupChangeReason reason = TP_CHANNEL_GROUP_CHANGE_REASON_NONE; g_assert (GABBLE_IS_MUC_CHANNEL (gmuc)); if (priv->state >= MUC_STATE_JOINED) { DEBUG ("presence error while already member of the channel -- NYI"); return; } if (error->code == WOCKY_XMPP_ERROR_NOT_AUTHORIZED) { /* channel can sit requiring a password indefinitely */ clear_join_timer (gmuc); /* Password already provided and incorrect? */ if (priv->state == MUC_STATE_AUTH) { provide_password_return_if_pending (gmuc, FALSE); return; } DEBUG ("password required to join; signalling"); change_must_provide_password (gmuc, TRUE); g_object_set (gmuc, "state", MUC_STATE_AUTH, NULL); } else { GError *tp_error = NULL; switch (error->code) { case WOCKY_XMPP_ERROR_FORBIDDEN: tp_error = g_error_new (TP_ERROR, TP_ERROR_CHANNEL_BANNED, "banned from room"); reason = TP_CHANNEL_GROUP_CHANGE_REASON_BANNED; break; case WOCKY_XMPP_ERROR_SERVICE_UNAVAILABLE: tp_error = g_error_new (TP_ERROR, TP_ERROR_CHANNEL_FULL, "room is full"); reason = TP_CHANNEL_GROUP_CHANGE_REASON_BUSY; break; case WOCKY_XMPP_ERROR_REGISTRATION_REQUIRED: tp_error = g_error_new (TP_ERROR, TP_ERROR_CHANNEL_INVITE_ONLY, "room is invite only"); break; case WOCKY_XMPP_ERROR_CONFLICT: if (handle_nick_conflict (gmuc, stanza, &tp_error)) return; break; default: tp_error = g_error_new (TP_ERROR, TP_ERROR_NOT_AVAILABLE, "%s", wocky_xmpp_error_description (error->code)); break; } g_signal_emit (gmuc, signals[JOIN_ERROR], 0, tp_error); close_channel (gmuc, tp_error->message, FALSE, 0, reason); g_error_free (tp_error); } } static void tube_closed_cb (GabbleTubeIface *tube, GabbleMucChannel *gmuc) { GabbleMucChannelPrivate *priv = gmuc->priv; guint64 tube_id; g_object_get (tube, "id", &tube_id, NULL); g_hash_table_remove (priv->tubes, GUINT_TO_POINTER (tube_id)); } static GabbleTubeIface * create_new_tube (GabbleMucChannel *gmuc, TpTubeType type, TpHandle initiator, const gchar *service, GHashTable *parameters, const gchar *stream_id, guint64 tube_id, GabbleBytestreamIface *bytestream, gboolean requested) { GabbleMucChannelPrivate *priv = gmuc->priv; TpBaseChannel *base = TP_BASE_CHANNEL (gmuc); GabbleConnection *conn = GABBLE_CONNECTION ( tp_base_channel_get_connection (base)); TpHandle self_handle = TP_GROUP_MIXIN (gmuc)->self_handle; TpHandle handle = tp_base_channel_get_target_handle (base); GabbleTubeIface *tube; switch (type) { case TP_TUBE_TYPE_DBUS: tube = GABBLE_TUBE_IFACE (gabble_tube_dbus_new (conn, handle, TP_HANDLE_TYPE_ROOM, self_handle, initiator, service, parameters, stream_id, tube_id, bytestream, gmuc, requested)); break; case TP_TUBE_TYPE_STREAM: tube = GABBLE_TUBE_IFACE (gabble_tube_stream_new (conn, handle, TP_HANDLE_TYPE_ROOM, self_handle, initiator, service, parameters, tube_id, gmuc, requested)); break; default: g_return_val_if_reached (NULL); } tp_base_channel_register ((TpBaseChannel *) tube); DEBUG ("create tube %" G_GUINT64_FORMAT, tube_id); g_hash_table_insert (priv->tubes, GUINT_TO_POINTER (tube_id), tube); g_signal_connect (tube, "closed", G_CALLBACK (tube_closed_cb), gmuc); return tube; } static guint64 generate_tube_id (GabbleMucChannel *self) { GabbleMucChannelPrivate *priv = self->priv; guint64 out; /* probably totally overkill */ do { out = g_random_int_range (1, G_MAXINT32); } while (g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (out)) != NULL); return out; } GabbleTubeIface * gabble_muc_channel_tube_request (GabbleMucChannel *self, gpointer request_token, GHashTable *request_properties, gboolean require_new) { GabbleTubeIface *tube; const gchar *channel_type; const gchar *service; GHashTable *parameters = NULL; guint64 tube_id; gchar *stream_id; TpTubeType type; tube_id = generate_tube_id (self); channel_type = tp_asv_get_string (request_properties, TP_PROP_CHANNEL_CHANNEL_TYPE); if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE)) { type = TP_TUBE_TYPE_STREAM; service = tp_asv_get_string (request_properties, TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE); } else if (! tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE)) { type = TP_TUBE_TYPE_DBUS; service = tp_asv_get_string (request_properties, TP_PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME); } else /* This assertion is safe: this function's caller only calls it in one of * the above cases. * FIXME: but it would be better to pass an enum member or something maybe. */ g_assert_not_reached (); /* requested tubes have an empty parameters dict */ parameters = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) tp_g_value_slice_free); /* if the service property is missing, the requestotron rejects the request */ g_assert (service != NULL); DEBUG ("Request a tube channel with type='%s' and service='%s'", channel_type, service); stream_id = gabble_bytestream_factory_generate_stream_id (); tube = create_new_tube (self, type, TP_GROUP_MIXIN (self)->self_handle, service, parameters, stream_id, tube_id, NULL, TRUE); g_free (stream_id); g_hash_table_unref (parameters); return tube; } void gabble_muc_channel_foreach_tubes (GabbleMucChannel *gmuc, TpExportableChannelFunc foreach, gpointer user_data) { GabbleMucChannelPrivate *priv = gmuc->priv; GHashTableIter iter; gpointer value; g_hash_table_iter_init (&iter, priv->tubes); while (g_hash_table_iter_next (&iter, NULL, &value)) { foreach (TP_EXPORTABLE_CHANNEL (value), user_data); } } void gabble_muc_channel_handle_si_stream_request (GabbleMucChannel *self, GabbleBytestreamIface *bytestream, const gchar *stream_id, WockyStanza *msg) { GabbleMucChannelPrivate *priv = self->priv; WockyNode *si_node, *stream_node; const gchar *tmp; guint64 tube_id; GabbleTubeIface *tube; si_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "si", NS_SI); g_return_if_fail (si_node != NULL); stream_node = wocky_node_get_child_ns (si_node, "muc-stream", NS_TUBES); g_return_if_fail (stream_node != NULL); tmp = wocky_node_get_attribute (stream_node, "tube"); if (tmp == NULL) { GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, " has no tube attribute" }; NODE_DEBUG (stream_node, e.message); gabble_bytestream_iface_close (bytestream, &e); return; } tube_id = g_ascii_strtoull (tmp, NULL, 10); if (tube_id == 0 || tube_id > G_MAXUINT32) { GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, " tube ID attribute non-numeric or out of range" }; DEBUG ("tube id is non-numeric or out of range: %s", tmp); gabble_bytestream_iface_close (bytestream, &e); return; } tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id)); if (tube == NULL) { GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, " tube attribute points to a nonexistent " "tube" }; DEBUG ("tube %" G_GUINT64_FORMAT " doesn't exist", tube_id); gabble_bytestream_iface_close (bytestream, &e); return; } DEBUG ("received new bytestream request for existing tube: %" G_GUINT64_FORMAT, tube_id); gabble_tube_iface_add_bytestream (tube, bytestream); } static void tubes_presence_update (GabbleMucChannel *gmuc, TpHandle contact, WockyNode *pnode) { GabbleMucChannelPrivate *priv = gmuc->priv; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( tp_base_channel_get_connection (TP_BASE_CHANNEL (gmuc)), TP_HANDLE_TYPE_CONTACT); const gchar *presence_type; WockyNode *tubes_node; GHashTable *old_dbus_tubes; GHashTableIter iter; gpointer key, value; WockyNodeIter i; WockyNode *tube_node; if (contact == TP_GROUP_MIXIN (gmuc)->self_handle) /* We don't need to inspect our own presence */ return; presence_type = wocky_node_get_attribute (pnode, "type"); if (!tp_strdiff (presence_type, "unavailable")) { g_hash_table_iter_init (&iter, priv->tubes); while (g_hash_table_iter_next (&iter, NULL, &value)) { GabbleTubeDBus *tube = value; if (!GABBLE_IS_TUBE_DBUS (value)) continue; gabble_tube_dbus_remove_name (tube, contact); } } tubes_node = wocky_node_get_child_ns (pnode, "tubes", NS_TUBES); if (tubes_node == NULL) return; /* Fill old_dbus_tubes with D-BUS tubes previously announced by * the contact */ old_dbus_tubes = g_hash_table_new (g_direct_hash, g_direct_equal); g_hash_table_iter_init (&iter, priv->tubes); while (g_hash_table_iter_next (&iter, &key, &value)) { if (!GABBLE_IS_TUBE_DBUS (value)) continue; if (gabble_tube_dbus_handle_in_names (GABBLE_TUBE_DBUS (value), contact)) { g_hash_table_insert (old_dbus_tubes, key, value); } } wocky_node_iter_init (&i, tubes_node, NULL, NULL); while (wocky_node_iter_next (&i, &tube_node)) { const gchar *stream_id; GabbleTubeIface *tube; guint64 tube_id; TpTubeType type; stream_id = wocky_node_get_attribute (tube_node, "stream-id"); if (!gabble_private_tubes_factory_extract_tube_information ( contact_repo, tube_node, NULL, NULL, NULL, NULL, &tube_id)) { DEBUG ("Bad tube ID, skipping to next child of "); continue; } tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id)); if (tube == NULL) { /* We don't know yet this tube */ const gchar *service; TpHandle initiator_handle; GHashTable *parameters; if (gabble_private_tubes_factory_extract_tube_information ( contact_repo, tube_node, &type, &initiator_handle, &service, ¶meters, NULL)) { if (type == TP_TUBE_TYPE_DBUS && initiator_handle == 0) { DEBUG ("D-Bus tube initiator missing"); /* skip to the next child of */ continue; } else if (type == TP_TUBE_TYPE_STREAM) { initiator_handle = contact; } tube = create_new_tube (gmuc, type, initiator_handle, service, parameters, stream_id, tube_id, NULL, FALSE); g_signal_emit (gmuc, signals[NEW_TUBE], 0, tube); g_hash_table_unref (parameters); } } else { /* The contact is in the tube. * Remove it from old_dbus_tubes if needed */ g_hash_table_remove (old_dbus_tubes, GUINT_TO_POINTER (tube_id)); } if (tube == NULL) /* skip to the next child of */ continue; g_object_get (tube, "type", &type, NULL); if (type == TP_TUBE_TYPE_DBUS) { /* Update mapping of handle -> D-Bus name. */ if (!gabble_tube_dbus_handle_in_names (GABBLE_TUBE_DBUS (tube), contact)) { /* Contact just joined the tube */ const gchar *new_name; new_name = wocky_node_get_attribute (tube_node, "dbus-name"); if (!new_name) { DEBUG ("Contact %u isn't announcing their D-Bus name", contact); /* skip to the next child of */ continue; } gabble_tube_dbus_add_name (GABBLE_TUBE_DBUS (tube), contact, new_name); } } } /* Tubes remaining in old_dbus_tubes was left by the contact */ g_hash_table_iter_init (&iter, old_dbus_tubes); while (g_hash_table_iter_next (&iter, NULL, &value)) { gabble_tube_dbus_remove_name (GABBLE_TUBE_DBUS (value), contact); } g_hash_table_unref (old_dbus_tubes); } /* ************************************************************************* */ /* presence related signal handlers */ /* not actually a signal handler, but used by them. */ static void handle_tube_presence (GabbleMucChannel *gmuc, TpHandle from, WockyStanza *stanza) { WockyNode *node = wocky_stanza_get_top_node (stanza); if (from == 0) return; tubes_presence_update (gmuc, from, node); } static TpChannelGroupChangeReason muc_status_codes_to_change_reason (guint codes) { if ((codes & WOCKY_MUC_CODE_BANNED) != 0) return TP_CHANNEL_GROUP_CHANGE_REASON_BANNED; else if ((codes & ( WOCKY_MUC_CODE_KICKED | WOCKY_MUC_CODE_KICKED_AFFILIATION | WOCKY_MUC_CODE_KICKED_ROOM_PRIVATISED | WOCKY_MUC_CODE_KICKED_SHUTDOWN )) != 0) return TP_CHANNEL_GROUP_CHANGE_REASON_KICKED; else return TP_CHANNEL_GROUP_CHANGE_REASON_NONE; } /* connect to wocky-muc:SIG_PARTED, which we will receive when the MUC tells * * us that we have left the channel */ static void handle_parted (GObject *source, WockyStanza *stanza, guint codes, const gchar *actor_jid, const gchar *why, const gchar *msg, gpointer data) { WockyMuc *wmuc = WOCKY_MUC (source); GabbleMucChannel *gmuc = GABBLE_MUC_CHANNEL (data); TpBaseChannel *base = TP_BASE_CHANNEL (gmuc); GabbleMucChannelPrivate *priv = gmuc->priv; TpChannelGroupChangeReason reason = TP_CHANNEL_GROUP_CHANGE_REASON_NONE; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (tp_base_channel_get_connection (base), TP_HANDLE_TYPE_CONTACT); TpIntset *handles = NULL; TpHandle member = 0; TpHandle actor = 0; const char *jid = wocky_muc_jid (wmuc); DEBUG ("called with jid='%s'", jid); member = tp_handle_ensure (contact_repo, jid, NULL, NULL); if (priv->closing) { /* This was a timeout to ensure that leaving a room with a * non-responsive conference server still meant the channel * closed (eventually). */ clear_leave_timer (gmuc); /* Close has been called, and we informed the MUC of our leaving * by sending a presence stanza of type='unavailable'. Now this * has been returned to us we know we've successfully left the * MUC, so we can finally close the channel here. */ tp_base_channel_destroyed (TP_BASE_CHANNEL (gmuc)); return; } if (member == 0) { DEBUG ("bizarre: ignoring our own malformed MUC JID '%s'", jid); return; } handles = tp_intset_new (); tp_intset_add (handles, member); if (actor_jid != NULL) { actor = tp_handle_ensure (contact_repo, actor_jid, NULL, NULL); if (actor == 0) DEBUG ("ignoring invalid actor JID %s", actor_jid); } reason = muc_status_codes_to_change_reason (codes); /* handle_tube_presence creates tubes if need be, so bypass it here: */ tubes_presence_update (gmuc, member, wocky_stanza_get_top_node (stanza)); close_channel (gmuc, why, FALSE, actor, reason); tp_intset_destroy (handles); } /* connect to wocky-muc:SIG_LEFT, which we will receive when the MUC informs * * us someone [else] has left the channel */ static void handle_left (GObject *source, WockyStanza *stanza, guint codes, WockyMucMember *who, const gchar *actor_jid, const gchar *why, const gchar *msg, gpointer data) { GabbleMucChannel *gmuc = GABBLE_MUC_CHANNEL (data); TpBaseChannel *base = TP_BASE_CHANNEL (gmuc); TpChannelGroupChangeReason reason = TP_CHANNEL_GROUP_CHANGE_REASON_NONE; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (tp_base_channel_get_connection (base), TP_HANDLE_TYPE_CONTACT); TpIntset *handles = NULL; TpHandle member = 0; TpHandle actor = 0; member = tp_handle_ensure (contact_repo, who->from, NULL, NULL); if (member == 0) { DEBUG ("ignoring malformed MUC JID '%s'", who->from); return; } handles = tp_intset_new (); tp_intset_add (handles, member); if (actor_jid != NULL) { actor = tp_handle_ensure (contact_repo, actor_jid, NULL, NULL); if (actor == 0) DEBUG ("ignoring invalid actor JID %s", actor_jid); } reason = muc_status_codes_to_change_reason (codes); /* handle_tube_presence creates tubes if need be, so bypass it here: */ tubes_presence_update (gmuc, member, wocky_stanza_get_top_node (stanza)); tp_group_mixin_change_members (data, why, NULL, handles, NULL, NULL, actor, reason); tp_message_mixin_change_chat_state (data, member, TP_CHANNEL_CHAT_STATE_GONE); tp_intset_destroy (handles); } /* connect to wocky-muc:SIG_PERM_CHANGE, which we will receive when the * * MUC informs us our role/affiliation has been altered */ static void handle_perms (GObject *source, WockyStanza *stanza, GHashTable *code, const gchar *actor, const gchar *why, gpointer data) { WockyMuc *wmuc = WOCKY_MUC (source); GabbleMucChannel *gmuc = GABBLE_MUC_CHANNEL (data); GabbleMucChannelPrivate *priv = gmuc->priv; TpHandle myself = TP_GROUP_MIXIN (gmuc)->self_handle; priv->self_role = wocky_muc_role (wmuc); priv->self_affil = wocky_muc_affiliation (wmuc); room_properties_update (gmuc); update_permissions (gmuc); handle_tube_presence (gmuc, myself, stanza); } static void handle_fill_presence (WockyMuc *muc, WockyStanza *stanza, gpointer user_data) { GabbleMucChannel *self = GABBLE_MUC_CHANNEL (user_data); GabbleMucChannelPrivate *priv = self->priv; TpBaseChannel *base = TP_BASE_CHANNEL (self); TpBaseConnection *base_conn = tp_base_channel_get_connection (base); GabbleConnection *conn = GABBLE_CONNECTION (base_conn); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT); TpHandle self_handle; self_handle = tp_handle_ensure (contact_repo, priv->self_jid->str, GUINT_TO_POINTER (GABBLE_JID_ROOM_MEMBER), NULL); gabble_presence_add_status_and_vcard (conn->self_presence, stanza); /* If we are invisible, show us as dnd in muc, since we can't be invisible */ if (conn->self_presence->status == GABBLE_PRESENCE_HIDDEN) wocky_node_add_child_with_content (wocky_stanza_get_top_node (stanza), "show", JABBER_PRESENCE_SHOW_DND); /* Sync the presence we send over the wire with what is in our presence cache */ gabble_presence_cache_update (conn->presence_cache, self_handle, NULL, conn->self_presence->status, conn->self_presence->status_message, 0); tube_pre_presence (self, stanza); g_signal_emit (self, signals[PRE_PRESENCE], 0, (WockyStanza *) stanza); } /* connect to wocky-muc:SIG_NICK_CHANGE, which we will receive when the * * MUC informs us our nick has been changed for some reason */ static void handle_renamed (GObject *source, WockyStanza *stanza, guint codes, gpointer data) { WockyMuc *wmuc = WOCKY_MUC (source); GabbleMucChannel *gmuc = GABBLE_MUC_CHANNEL (data); TpBaseChannel *base = TP_BASE_CHANNEL (gmuc); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (tp_base_channel_get_connection (base), TP_HANDLE_TYPE_CONTACT); TpIntset *old_self = tp_intset_new (); const gchar *me = wocky_muc_jid (wmuc); const gchar *me2 = wocky_muc_user (wmuc); TpHandle myself = tp_handle_ensure (contact_repo, me, GUINT_TO_POINTER (GABBLE_JID_ROOM_MEMBER), NULL); TpHandle userid = tp_handle_ensure (contact_repo, me2, GUINT_TO_POINTER (GABBLE_JID_ROOM_MEMBER), NULL); tp_intset_add (old_self, TP_GROUP_MIXIN (gmuc)->self_handle); tp_group_mixin_change_self_handle (data, myself); tp_group_mixin_add_handle_owner (data, myself, userid); tp_group_mixin_change_members (data, "", NULL, old_self, NULL, NULL, 0, 0); handle_tube_presence (gmuc, myself, stanza); tp_intset_destroy (old_self); } static void update_roster_presence (GabbleMucChannel *gmuc, WockyMucMember *member, TpHandleRepoIface *contact_repo, TpHandleSet *members, TpHandleSet *owners, GHashTable *omap) { TpBaseChannel *base = TP_BASE_CHANNEL (gmuc); GabbleConnection *conn = GABBLE_CONNECTION (tp_base_channel_get_connection (base)); TpHandle owner = 0; TpHandle handle = tp_handle_ensure (contact_repo, member->from, GUINT_TO_POINTER (GABBLE_JID_ROOM_MEMBER), NULL); if (member->jid != NULL) { owner = tp_handle_ensure (contact_repo, member->jid, GUINT_TO_POINTER (GABBLE_JID_GLOBAL), NULL); if (owner == 0) DEBUG ("Invalid owner handle '%s', treating as no owner", member->jid); else tp_handle_set_add (owners, owner); } gabble_presence_parse_presence_message (conn->presence_cache, handle, member->from, (WockyStanza *) member->presence_stanza); tp_handle_set_add (members, handle); g_hash_table_insert (omap, GUINT_TO_POINTER (handle), GUINT_TO_POINTER (owner)); /* make a note of the fact that owner JIDs are visible to us */ /* notify whomever that an identifiable contact joined the MUC */ if (owner != 0) { tp_group_mixin_change_flags (G_OBJECT (gmuc), 0, TP_CHANNEL_GROUP_FLAG_HANDLE_OWNERS_NOT_AVAILABLE); g_signal_emit (gmuc, signals[CONTACT_JOIN], 0, owner); } handle_tube_presence (gmuc, handle, member->presence_stanza); } /* connect to wocky_muc SIG_JOINED which we should receive when we receive * * the final (ie our own) presence in the roster: (note that if our nick was * * changed by the MUC we will already have received a SIG_NICK_CHANGE: */ static void handle_join (WockyMuc *muc, WockyStanza *stanza, guint codes, gpointer data) { GabbleMucChannel *gmuc = GABBLE_MUC_CHANNEL (data); TpBaseChannel *base = TP_BASE_CHANNEL (gmuc); TpBaseConnection *base_conn = tp_base_channel_get_connection (base); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT); TpHandleSet *members = tp_handle_set_new (contact_repo); TpHandleSet *owners = tp_handle_set_new (contact_repo); GHashTable *omap = g_hash_table_new (g_direct_hash, g_direct_equal); GHashTable *member_jids = wocky_muc_members (muc); const gchar *me = wocky_muc_jid (muc); TpHandle myself = tp_handle_ensure (contact_repo, me, GUINT_TO_POINTER (GABBLE_JID_ROOM_MEMBER), NULL); GHashTableIter iter; WockyMucMember *member; g_hash_table_iter_init (&iter, member_jids); while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&member)) update_roster_presence (gmuc, member, contact_repo, members, owners, omap); g_hash_table_insert (omap, GUINT_TO_POINTER (myself), GUINT_TO_POINTER (tp_base_connection_get_self_handle (base_conn))); tp_handle_set_add (members, myself); tp_group_mixin_add_handle_owners (G_OBJECT (gmuc), omap); tp_group_mixin_change_members (G_OBJECT (gmuc), "", tp_handle_set_peek (members), NULL, NULL, NULL, 0, 0); /* accept the config of the room if it was created for us: */ if (codes & WOCKY_MUC_CODE_NEW_ROOM) { WockyStanza *accept = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, gmuc->priv->jid, '(', "query", ':', WOCKY_NS_MUC_OWNER, '(', "x", ':', WOCKY_XMPP_NS_DATA, '@', "type", "submit", ')', ')', NULL); conn_util_send_iq_async (GABBLE_CONNECTION (base_conn), accept, NULL, room_created_submit_reply_cb, NULL); g_object_unref (accept); } g_object_set (gmuc, "state", MUC_STATE_JOINED, NULL); tp_handle_set_destroy (members); tp_handle_set_destroy (owners); g_hash_table_unref (omap); g_hash_table_unref (member_jids); } /* connect to wocky-muc:SIG_PRESENCE, which is fired for presences that are * * NOT our own after the initial roster has been received: */ static void handle_presence (GObject *source, WockyStanza *stanza, guint codes, WockyMucMember *who, gpointer data) { GabbleMucChannel *gmuc = GABBLE_MUC_CHANNEL (data); #ifdef ENABLE_VOIP GabbleMucChannelPrivate *priv = gmuc->priv; #endif TpBaseChannel *base = TP_BASE_CHANNEL (gmuc); TpBaseConnection *base_conn = tp_base_channel_get_connection (base); GabbleConnection *conn = GABBLE_CONNECTION (base_conn); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT); TpHandle owner = 0; TpHandle handle = tp_handle_ensure (contact_repo, who->from, GUINT_TO_POINTER (GABBLE_JID_ROOM_MEMBER), NULL); TpHandleSet *handles = tp_handle_set_new (contact_repo); /* is the 'real' jid field of the presence set? If so, use it: */ if (who->jid != NULL) { owner = tp_handle_ensure (contact_repo, who->jid, GUINT_TO_POINTER (GABBLE_JID_GLOBAL), NULL); if (owner == 0) { DEBUG ("Invalid owner handle '%s' ignored", who->jid); } else /* note that JIDs are known to us in this MUC */ { tp_group_mixin_change_flags (G_OBJECT (data), 0, TP_CHANNEL_GROUP_FLAG_HANDLE_OWNERS_NOT_AVAILABLE); } } gabble_presence_parse_presence_message (conn->presence_cache, handle, who->from, (WockyStanza *) who->presence_stanza); /* add the member in quesion */ tp_handle_set_add (handles, handle); tp_group_mixin_change_members (data, "", tp_handle_set_peek (handles), NULL, NULL, NULL, 0, 0); /* record the owner (0 for no owner) */ tp_group_mixin_add_handle_owner (data, handle, owner); handle_tube_presence (gmuc, handle, stanza); #ifdef ENABLE_VOIP if (!priv->call_initiating && priv->call == NULL) { WockyNode *m; /* Check for muji nodes */ m = wocky_node_get_child_ns ( wocky_stanza_get_top_node (stanza), "muji", NS_MUJI); if (m != NULL && wocky_node_get_child_ns (m, "content", NS_MUJI) != NULL) { DEBUG ("Detected a muji call in progress, starting a call channel!"); gabble_muc_channel_start_call_creation (gmuc, NULL); } } #endif tp_handle_set_destroy (handles); } /* ************************************************************************ */ /* message signal handlers */ static void handle_message (GObject *source, WockyStanza *stanza, WockyMucMsgType type, const gchar *xmpp_id, GDateTime *datetime, WockyMucMember *who, const gchar *text, const gchar *subject, WockyMucMsgState state, gpointer data) { GabbleMucChannel *gmuc = GABBLE_MUC_CHANNEL (data); TpBaseChannel *base = TP_BASE_CHANNEL (gmuc); TpBaseConnection *conn = tp_base_channel_get_connection (base); gboolean from_member = (who != NULL); TpChannelTextMessageType msg_type; TpHandleRepoIface *repo; TpHandleType handle_type; TpHandle from; if (from_member) { handle_type = TP_HANDLE_TYPE_CONTACT; repo = tp_base_connection_get_handles (conn, handle_type); from = tp_handle_ensure (repo, who->from, GUINT_TO_POINTER (GABBLE_JID_ROOM_MEMBER), NULL); if (from == 0) { DEBUG ("Message from MUC member with no handle, discarding."); return; } } else /* directly from MUC itself */ { handle_type = TP_HANDLE_TYPE_ROOM; repo = tp_base_connection_get_handles (conn, handle_type); from = tp_base_channel_get_target_handle (base); } switch (type) { case WOCKY_MUC_MSG_NORMAL: msg_type = TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL; break; case WOCKY_MUC_MSG_ACTION: msg_type = TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION; break; default: msg_type = TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE; } if (text != NULL) _gabble_muc_channel_receive (gmuc, msg_type, handle_type, from, datetime, xmpp_id, text, stanza, NULL, TP_DELIVERY_STATUS_DELIVERED); if (from_member && state != WOCKY_MUC_MSG_STATE_NONE) { TpChannelChatState tp_msg_state; switch (state) { case WOCKY_MUC_MSG_STATE_ACTIVE: tp_msg_state = TP_CHANNEL_CHAT_STATE_ACTIVE; break; case WOCKY_MUC_MSG_STATE_COMPOSING: tp_msg_state = TP_CHANNEL_CHAT_STATE_COMPOSING; break; case WOCKY_MUC_MSG_STATE_INACTIVE: tp_msg_state = TP_CHANNEL_CHAT_STATE_INACTIVE; break; case WOCKY_MUC_MSG_STATE_PAUSED: tp_msg_state = TP_CHANNEL_CHAT_STATE_PAUSED; break; default: tp_msg_state = TP_CHANNEL_CHAT_STATE_ACTIVE; } tp_message_mixin_change_chat_state ((GObject *) gmuc, from, tp_msg_state); } if (subject != NULL) _gabble_muc_channel_handle_subject (gmuc, handle_type, from, datetime, subject, stanza, NULL); } static void handle_errmsg (GObject *source, WockyStanza *stanza, WockyMucMsgType type, const gchar *xmpp_id, GDateTime *datetime, WockyMucMember *who, const gchar *text, WockyXmppErrorType etype, const GError *error, gpointer data) { GabbleMucChannel *gmuc = GABBLE_MUC_CHANNEL (data); GabbleMucChannelPrivate *priv = gmuc->priv; TpBaseChannel *base = TP_BASE_CHANNEL (gmuc); TpBaseConnection *conn = tp_base_channel_get_connection (base); gboolean from_member = (who != NULL); TpDeliveryStatus ds = TP_DELIVERY_STATUS_DELIVERED; TpHandleRepoIface *repo = NULL; TpHandleType handle_type; TpHandle from = 0; const gchar *subject; if (from_member) { handle_type = TP_HANDLE_TYPE_CONTACT; repo = tp_base_connection_get_handles (conn, handle_type); from = tp_handle_ensure (repo, who->from, GUINT_TO_POINTER (GABBLE_JID_ROOM_MEMBER), NULL); if (from == 0) { DEBUG ("Message from MUC member with no handle, discarding."); return; } } else /* directly from MUC itself */ { handle_type = TP_HANDLE_TYPE_ROOM; repo = tp_base_connection_get_handles (conn, handle_type); from = tp_base_channel_get_target_handle (base); } if (etype == WOCKY_XMPP_ERROR_TYPE_WAIT) { ds = TP_DELIVERY_STATUS_TEMPORARILY_FAILED; /* Some MUCs have very strict rate limiting like "at most one stanza per * second". Since chat state notifications count towards this, if the * user types a message very quickly then the typing notification is * accepted but then the stanza containing the actual message is * rejected. * * So: if we ever get rate-limited, let's just stop sending chat states. * * https://bugs.freedesktop.org/show_bug.cgi?id=43166 */ DEBUG ("got , disabling chat state notifications"); priv->have_received_error_type_wait = TRUE; } else { ds = TP_DELIVERY_STATUS_PERMANENTLY_FAILED; } if (text != NULL) _gabble_muc_channel_receive (gmuc, TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE, handle_type, from, datetime, xmpp_id, text, stanza, error, ds); /* FIXME: this is stupid. WockyMuc gives us the subject for non-errors, but * doesn't bother for errors. */ subject = wocky_node_get_content_from_child ( wocky_stanza_get_top_node (stanza), "subject"); /* The server is under no obligation to echo the element back if it * sends us an error. Fortunately, it should preserve the id='' element so we * can check for that instead. */ if (subject != NULL || (priv->set_subject_stanza_id != NULL && !tp_strdiff (xmpp_id, priv->set_subject_stanza_id))) _gabble_muc_channel_handle_subject (gmuc, handle_type, from, datetime, subject, stanza, error); } /* ************************************************************************* */ /** * _gabble_muc_channel_handle_subject: handle room subject updates */ void _gabble_muc_channel_handle_subject (GabbleMucChannel *chan, TpHandleType handle_type, TpHandle sender, GDateTime *datetime, const gchar *subject, WockyStanza *msg, const GError *error) { GabbleMucChannelPrivate *priv; const gchar *actor; gint64 timestamp = datetime != NULL ? g_date_time_to_unix (datetime) : G_MAXINT64; g_assert (GABBLE_IS_MUC_CHANNEL (chan)); priv = chan->priv; if (error != NULL) { if (priv->set_subject_context != NULL) { GError *tp_error = NULL; gabble_set_tp_error_from_wocky (error, &tp_error); if (tp_str_empty (tp_error->message)) g_prefix_error (&tp_error, "failed to change subject"); return_from_set_subject (chan, tp_error); g_clear_error (&tp_error); /* Get the properties into a consistent state. */ room_properties_update (chan); } return; } /* Channel.Interface.Subject properties */ if (handle_type == TP_HANDLE_TYPE_CONTACT) { TpHandleRepoIface *contact_handles = tp_base_connection_get_handles ( tp_base_channel_get_connection (TP_BASE_CHANNEL (chan)), handle_type); actor = tp_handle_inspect (contact_handles, sender); } else { actor = ""; } g_free (priv->subject); g_free (priv->subject_actor); priv->subject = g_strdup (subject); priv->subject_actor = g_strdup (actor); priv->subject_timestamp = timestamp; DEBUG ("Subject changed to '%s' by '%s' at %" G_GINT64_FORMAT "", subject, actor, timestamp); /* Emit signals */ emit_subject_changed (chan); if (priv->set_subject_context != NULL) return_from_set_subject (chan, NULL); } /** * _gabble_muc_channel_receive: receive MUC messages */ static void _gabble_muc_channel_receive (GabbleMucChannel *chan, TpChannelTextMessageType msg_type, TpHandleType sender_handle_type, TpHandle sender, GDateTime *datetime, const gchar *id, const gchar *text, WockyStanza *msg, const GError *send_error, TpDeliveryStatus error_status) { TpBaseChannel *base; TpBaseConnection *base_conn; TpMessage *message; TpHandle muc_self_handle; gboolean is_echo; gboolean is_error; gchar *tmp; gint64 timestamp = datetime != NULL ? g_date_time_to_unix (datetime): 0; g_assert (GABBLE_IS_MUC_CHANNEL (chan)); base = TP_BASE_CHANNEL (chan); base_conn = tp_base_channel_get_connection (base); muc_self_handle = chan->group.self_handle; /* Is this an error report? */ is_error = (send_error != NULL); if (is_error && sender == muc_self_handle) { /* So this is a . I can only think * that this would happen if we send an error stanza and the MUC reflects * it back at us, so let's just ignore it. */ STANZA_DEBUG (msg, "ignoring error stanza from ourself"); return; } /* Is this an echo from the MUC of a message we just sent? */ is_echo = ((sender == muc_self_handle) && (timestamp == 0)); /* Having excluded the "error from ourself" case, is_error and is_echo are * mutually exclusive. */ /* Ignore messages from the channel. The only such messages I have seen in * practice have been on devel@conference.pidgin.im, which sends useful * messages like "foo has set the subject to: ..." and "This room is not * anonymous". */ if (!is_echo && !is_error && sender_handle_type == TP_HANDLE_TYPE_ROOM) { STANZA_DEBUG (msg, "ignoring message from muc"); return; } /* are we actually hidden? */ if (!tp_base_channel_is_registered (base)) { DEBUG ("making MUC channel reappear!"); tp_base_channel_reopened_with_requested (base, FALSE, sender); } /* let's not autoclose now */ chan->priv->autoclose = FALSE; message = tp_cm_message_new (base_conn, 2); /* Header common to normal message and delivery-echo */ if (msg_type != TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL) tp_message_set_uint32 (message, 0, "message-type", msg_type); if (timestamp != 0) tp_message_set_int64 (message, 0, "message-sent", timestamp); /* Body */ tp_message_set_string (message, 1, "content-type", "text/plain"); tp_message_set_string (message, 1, "content", text); if (is_error || is_echo) { /* Error reports and echos of our own messages are represented as * delivery reports. */ TpMessage *delivery_report = tp_cm_message_new (base_conn, 1); TpDeliveryStatus status = is_error ? error_status : TP_DELIVERY_STATUS_DELIVERED; tmp = gabble_generate_id (); tp_message_set_string (delivery_report, 0, "message-token", tmp); g_free (tmp); tp_message_set_uint32 (delivery_report, 0, "message-type", TP_CHANNEL_TEXT_MESSAGE_TYPE_DELIVERY_REPORT); tp_message_set_uint32 (delivery_report, 0, "delivery-status", status); if (id != NULL) tp_message_set_string (delivery_report, 0, "delivery-token", id); if (send_error != NULL) { tp_message_set_uint32 (delivery_report, 0, "delivery-error", gabble_tp_send_error_from_wocky_xmpp_error (send_error->code)); if (!tp_str_empty (send_error->message)) { guint body_part_number = tp_message_append_part (delivery_report); tp_message_set_string (delivery_report, body_part_number, "content-type", "text/plain"); tp_message_set_string (delivery_report, body_part_number, "content", send_error->message); } } /* We do not set a message-sender on the report: the intended recipient * of the original message was the MUC, so the spec says we should omit * it. * * The sender of the echo, however, is ourself. (Unless we get errors * for messages that we didn't send, which would be odd.) */ tp_cm_message_set_sender (message, muc_self_handle); /* If we sent the message whose delivery has succeeded or failed, we * trust the id='' attribute. */ if (id != NULL) tp_message_set_string (message, 0, "message-token", id); tp_cm_message_take_message (delivery_report, 0, "delivery-echo", message); tp_message_mixin_take_received (G_OBJECT (chan), delivery_report); } else { /* Messages from the MUC itself should have no sender. */ if (sender_handle_type == TP_HANDLE_TYPE_CONTACT) tp_cm_message_set_sender (message, sender); if (timestamp != 0) tp_message_set_boolean (message, 0, "scrollback", TRUE); if (id != NULL) tp_message_set_string (message, 0, "message-token", id); tp_message_mixin_take_received (G_OBJECT (chan), message); } } static void gabble_muc_channel_close (TpBaseChannel *base) { GabbleMucChannel *self = GABBLE_MUC_CHANNEL (base); close_channel (self, NULL, TRUE, 0, 0); } /** * gabble_muc_channel_get_password_flags * * Implements D-Bus method GetPasswordFlags * on interface org.freedesktop.Telepathy.Channel.Interface.Password */ static void gabble_muc_channel_get_password_flags (TpSvcChannelInterfacePassword *iface, DBusGMethodInvocation *context) { GabbleMucChannel *self = GABBLE_MUC_CHANNEL (iface); GabbleMucChannelPrivate *priv; g_assert (GABBLE_IS_MUC_CHANNEL (self)); priv = self->priv; tp_svc_channel_interface_password_return_from_get_password_flags (context, priv->must_provide_password ? TP_CHANNEL_PASSWORD_FLAG_PROVIDE : 0); } /** * gabble_muc_channel_provide_password * * Implements D-Bus method ProvidePassword * on interface org.freedesktop.Telepathy.Channel.Interface.Password * * @context: The D-Bus invocation context to use to return values * or throw an error. */ static void gabble_muc_channel_provide_password (TpSvcChannelInterfacePassword *iface, const gchar *password, DBusGMethodInvocation *context) { GabbleMucChannel *self = GABBLE_MUC_CHANNEL (iface); GabbleMucChannelPrivate *priv; g_assert (GABBLE_IS_MUC_CHANNEL (self)); priv = self->priv; if (!priv->must_provide_password || priv->password_ctx != NULL) { GError error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE, "password cannot be provided in the current state" }; dbus_g_method_return_error (context, &error); } else { g_object_set (priv->wmuc, "password", password, NULL); send_join_request (self); priv->password_ctx = context; } } static void _gabble_muc_channel_message_sent_cb (GObject *source, GAsyncResult *res, gpointer user_data) { WockyPorter *porter = WOCKY_PORTER (source); _GabbleMUCSendMessageCtx *context = user_data; GabbleMucChannel *chan = context->channel; TpMessage *message = context->message; GError *error = NULL; if (wocky_porter_send_finish (porter, res, &error)) { tp_message_mixin_sent ((GObject *) chan, message, TP_MESSAGE_SENDING_FLAG_REPORT_DELIVERY, context->token, NULL); } else { tp_message_mixin_sent ((GObject *) chan, context->message, TP_MESSAGE_SENDING_FLAG_REPORT_DELIVERY, NULL, error); g_free (error); } g_object_unref (context->channel); g_object_unref (context->message); g_free (context->token); g_slice_free (_GabbleMUCSendMessageCtx, context); } /** * gabble_muc_channel_send * * Indirectly implements (via TpMessageMixin) D-Bus method Send on interface * org.freedesktop.Telepathy.Channel.Type.Text and D-Bus method SendMessage on * Channel.Interface.Messages */ static void gabble_muc_channel_send (GObject *obj, TpMessage *message, TpMessageSendingFlags flags) { GabbleMucChannel *self = GABBLE_MUC_CHANNEL (obj); TpBaseChannel *base = TP_BASE_CHANNEL (self); GabbleMucChannelPrivate *priv = self->priv; TpBaseConnection *base_conn; GabbleConnection *gabble_conn; _GabbleMUCSendMessageCtx *context = NULL; WockyStanza *stanza = NULL; WockyPorter *porter = NULL; GError *error = NULL; gchar *id = NULL; base_conn = tp_base_channel_get_connection (base); gabble_conn = GABBLE_CONNECTION (base_conn); tp_message_mixin_change_chat_state (obj, tp_base_channel_get_self_handle (base), TP_CHANNEL_CHAT_STATE_ACTIVE); stanza = gabble_message_util_build_stanza (message, gabble_conn, WOCKY_STANZA_SUB_TYPE_GROUPCHAT, TP_CHANNEL_CHAT_STATE_ACTIVE, priv->jid, FALSE, &id, &error); if (stanza != NULL) { context = g_slice_new0 (_GabbleMUCSendMessageCtx); context->channel = g_object_ref (obj); context->message = g_object_ref (message); context->token = id; porter = gabble_connection_dup_porter (gabble_conn); wocky_porter_send_async (porter, stanza, NULL, _gabble_muc_channel_message_sent_cb, context); g_object_unref (stanza); g_object_unref (porter); } else { tp_message_mixin_sent (obj, message, flags, NULL, error); g_error_free (error); } } gboolean gabble_muc_channel_send_invite (GabbleMucChannel *self, const gchar *jid, const gchar *message, gboolean continue_, GError **error) { TpBaseChannel *base = TP_BASE_CHANNEL (self); GabbleMucChannelPrivate *priv = self->priv; WockyStanza *msg; WockyNode *invite_node; gboolean result; g_signal_emit (self, signals[PRE_INVITE], 0, jid); msg = wocky_stanza_build ( WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, priv->jid, '(', "x", ':', NS_MUC_USER, '(', "invite", '@', "to", jid, '*', &invite_node, ')', ')', NULL); if (message != NULL && *message != '\0') { wocky_node_add_child_with_content (invite_node, "reason", message); } if (continue_) { wocky_node_add_child (invite_node, "continue"); } DEBUG ("sending MUC invitation for room %s to contact %s with reason " "\"%s\"", priv->jid, jid, message); result = _gabble_connection_send ( GABBLE_CONNECTION (tp_base_channel_get_connection (base)), msg, error); g_object_unref (msg); return result; } static gboolean gabble_muc_channel_add_member (GObject *obj, TpHandle handle, const gchar *message, GError **error) { GabbleMucChannel *self = GABBLE_MUC_CHANNEL (obj); TpBaseChannel *base = TP_BASE_CHANNEL (self); GabbleMucChannelPrivate *priv = self->priv; TpGroupMixin *mixin; const gchar *jid; mixin = TP_GROUP_MIXIN (obj); if (handle == mixin->self_handle) { TpBaseConnection *conn = tp_base_channel_get_connection (base); TpIntset *set_remove_members, *set_remote_pending; GArray *arr_members; /* are we already a member or in remote pending? */ if (tp_handle_set_is_member (mixin->members, handle) || tp_handle_set_is_member (mixin->remote_pending, handle)) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "already a member or in remote pending"); return FALSE; } /* add ourself to remote pending and remove the inviter's * main jid from the member list */ set_remove_members = tp_intset_new (); set_remote_pending = tp_intset_new (); arr_members = tp_handle_set_to_array (mixin->members); if (arr_members->len > 0) { tp_intset_add (set_remove_members, g_array_index (arr_members, guint, 0)); } g_array_unref (arr_members); tp_intset_add (set_remote_pending, handle); tp_group_mixin_add_handle_owner (obj, mixin->self_handle, tp_base_connection_get_self_handle (conn)); tp_group_mixin_change_members (obj, "", NULL, set_remove_members, NULL, set_remote_pending, 0, priv->invited ? TP_CHANNEL_GROUP_CHANGE_REASON_INVITED : TP_CHANNEL_GROUP_CHANGE_REASON_NONE); tp_intset_destroy (set_remove_members); tp_intset_destroy (set_remote_pending); /* seek to enter the room */ send_join_request (self); g_object_set (obj, "state", MUC_STATE_INITIATED, NULL); /* deny adding */ tp_group_mixin_change_flags (obj, 0, TP_CHANNEL_GROUP_FLAG_CAN_ADD); return TRUE; } /* check that we're indeed a member when attempting to invite others */ if (priv->state < MUC_STATE_JOINED) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "channel membership is required for inviting others"); return FALSE; } jid = tp_handle_inspect (TP_GROUP_MIXIN (self)->handle_repo, handle); return gabble_muc_channel_send_invite (self, jid, message, FALSE, error); } static void kick_request_reply_cb (GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg, GObject *object, gpointer user_data) { if (wocky_stanza_extract_errors (reply_msg, NULL, NULL, NULL, NULL)) { DEBUG ("Failed to kick user %s from room", (const char *) user_data); } } static gboolean gabble_muc_channel_remove_member (GObject *obj, TpHandle handle, const gchar *message, GError **error) { GabbleMucChannel *chan = GABBLE_MUC_CHANNEL (obj); TpBaseChannel *base = TP_BASE_CHANNEL (chan); GabbleMucChannelPrivate *priv = chan->priv; TpGroupMixin *group = TP_GROUP_MIXIN (chan); WockyStanza *msg; WockyNode *item_node; const gchar *jid, *nick; gboolean result; if (handle == group->self_handle) { /* User wants to leave the MUC */ close_channel (chan, message, TRUE, group->self_handle, TP_CHANNEL_GROUP_CHANGE_REASON_NONE); return TRUE; } /* Otherwise, the user wants to kick someone. */ msg = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, priv->jid, '(', "query", ':', NS_MUC_ADMIN, '(', "item", '*', &item_node, ')', ')', NULL); jid = tp_handle_inspect (TP_GROUP_MIXIN (obj)->handle_repo, handle); nick = strchr (jid, '/'); if (nick != NULL) nick++; wocky_node_set_attributes (item_node, "nick", nick, "role", "none", NULL); if (*message != '\0') { wocky_node_add_child_with_content (item_node, "reason", message); } DEBUG ("sending MUC kick request for contact %u (%s) to room %s with reason " "\"%s\"", handle, jid, priv->jid, message); result = _gabble_connection_send_with_reply ( GABBLE_CONNECTION (tp_base_channel_get_connection (base)), msg, kick_request_reply_cb, obj, (gpointer) jid, error); g_object_unref (msg); return result; } static void request_config_form_reply_cb ( GObject *source, GAsyncResult *result, gpointer user_data); void gabble_muc_channel_update_configuration_async ( GabbleMucChannel *self, GHashTable *validated_properties, GAsyncReadyCallback callback, gpointer user_data) { GabbleMucChannelPrivate *priv = self->priv; TpBaseChannel *base = (TpBaseChannel *) self; GabbleConnection *conn = GABBLE_CONNECTION (tp_base_channel_get_connection (base)); WockyStanza *stanza; GSimpleAsyncResult *result = g_simple_async_result_new ((GObject *) self, callback, user_data, gabble_muc_channel_update_configuration_async); g_assert (priv->properties_being_updated == NULL); stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, priv->jid, '(', "query", ':', WOCKY_NS_MUC_OWNER, ')', NULL); conn_util_send_iq_async (conn, stanza, NULL, request_config_form_reply_cb, result); g_object_unref (stanza); priv->properties_being_updated = g_hash_table_ref (validated_properties); } gboolean gabble_muc_channel_update_configuration_finish ( GabbleMucChannel *self, GAsyncResult *result, GError **error) { wocky_implement_finish_void (self, gabble_muc_channel_update_configuration_async); } typedef const gchar * (*MapFieldFunc) (const GValue *value); typedef struct { const gchar *var; TpBaseRoomConfigProperty prop_id; MapFieldFunc map; } ConfigFormMapping; static const gchar * map_bool (const GValue *value) { return g_value_get_boolean (value) ? "1" : "0"; } static const gchar * map_bool_inverted (const GValue *value) { return g_value_get_boolean (value) ? "0" : "1"; } static const gchar * map_roomconfig_whois (const GValue *value) { return g_value_get_boolean (value) ? "moderators" : "anyone"; } static const gchar * map_owner_whois (const GValue *value) { return g_value_get_boolean (value) ? "admins" : "anyone"; } static ConfigFormMapping form_mappings[] = { { "anonymous", TP_BASE_ROOM_CONFIG_ANONYMOUS, map_bool }, { "muc#roomconfig_whois", TP_BASE_ROOM_CONFIG_ANONYMOUS, map_roomconfig_whois }, { "muc#owner_whois", TP_BASE_ROOM_CONFIG_ANONYMOUS, map_owner_whois }, { "members_only", TP_BASE_ROOM_CONFIG_INVITE_ONLY, map_bool }, { "muc#roomconfig_membersonly", TP_BASE_ROOM_CONFIG_INVITE_ONLY, map_bool }, { "muc#owner_inviteonly", TP_BASE_ROOM_CONFIG_INVITE_ONLY, map_bool }, { "moderated", TP_BASE_ROOM_CONFIG_MODERATED, map_bool }, { "muc#roomconfig_moderatedroom", TP_BASE_ROOM_CONFIG_MODERATED, map_bool }, { "muc#owner_moderatedroom", TP_BASE_ROOM_CONFIG_MODERATED, map_bool }, { "title", TP_BASE_ROOM_CONFIG_TITLE, g_value_get_string }, { "muc#roomconfig_roomname", TP_BASE_ROOM_CONFIG_TITLE, g_value_get_string }, { "muc#owner_roomname", TP_BASE_ROOM_CONFIG_TITLE, g_value_get_string }, { "muc#roomconfig_roomdesc", TP_BASE_ROOM_CONFIG_DESCRIPTION, g_value_get_string }, { "muc#owner_roomdesc", TP_BASE_ROOM_CONFIG_DESCRIPTION, g_value_get_string }, { "password", TP_BASE_ROOM_CONFIG_PASSWORD, g_value_get_string }, { "muc#roomconfig_roomsecret", TP_BASE_ROOM_CONFIG_PASSWORD, g_value_get_string }, { "muc#owner_roomsecret", TP_BASE_ROOM_CONFIG_PASSWORD, g_value_get_string }, { "password_protected", TP_BASE_ROOM_CONFIG_PASSWORD_PROTECTED, map_bool }, { "muc#roomconfig_passwordprotectedroom", TP_BASE_ROOM_CONFIG_PASSWORD_PROTECTED, map_bool }, { "muc#owner_passwordprotectedroom", TP_BASE_ROOM_CONFIG_PASSWORD_PROTECTED, map_bool }, { "persistent", TP_BASE_ROOM_CONFIG_PERSISTENT, map_bool }, { "muc#roomconfig_persistentroom", TP_BASE_ROOM_CONFIG_PERSISTENT, map_bool }, { "muc#owner_persistentroom", TP_BASE_ROOM_CONFIG_PERSISTENT, map_bool }, { "public", TP_BASE_ROOM_CONFIG_PRIVATE, map_bool_inverted }, { "muc#roomconfig_publicroom", TP_BASE_ROOM_CONFIG_PRIVATE, map_bool_inverted }, { "muc#owner_publicroom", TP_BASE_ROOM_CONFIG_PRIVATE, map_bool_inverted }, { NULL } }; static ConfigFormMapping * lookup_config_form_field (const gchar *var) { ConfigFormMapping *f; for (f = form_mappings; f->var != NULL; f++) if (strcmp (var, f->var) == 0) return f; DEBUG ("unknown field %s", var); return NULL; } static void request_config_form_submit_reply_cb ( GObject *source, GAsyncResult *result, gpointer user_data); static void request_config_form_reply_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { GabbleConnection *conn = GABBLE_CONNECTION (source); GSimpleAsyncResult *update_result = G_SIMPLE_ASYNC_RESULT (user_data); GabbleMucChannel *chan = GABBLE_MUC_CHANNEL ( g_async_result_get_source_object ((GAsyncResult *) update_result)); GabbleMucChannelPrivate *priv = chan->priv; GHashTable *properties = priv->properties_being_updated; WockyStanza *reply = NULL; WockyStanza *submit_iq = NULL; WockyNode *form_node, *submit_node, *child; GError *error = NULL; guint i, props_left; WockyNodeIter j; if (!conn_util_send_iq_finish (conn, result, &reply, &error)) { g_prefix_error (&error, "failed to request configuration form: "); goto OUT; } form_node = config_form_get_form_node (reply); if (form_node == NULL) { g_set_error (&error, TP_ERROR, TP_ERROR_SERVICE_CONFUSED, "MUC configuration form didn't actually contain a form"); goto OUT; } /* initialize */ submit_iq = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, priv->jid, '(', "query", ':', WOCKY_NS_MUC_OWNER, '(', "x", ':', WOCKY_XMPP_NS_DATA, '@', "type", "submit", '*', &submit_node, ')', ')', NULL); /* we assume that the number of props will fit in a guint on all supported * platforms, so fail at compile time if this is no longer the case */ #if TP_NUM_BASE_ROOM_CONFIG_PROPERTIES > 32 #error GabbleMUCChannel request_config_form_reply_cb needs porting to TpIntset #endif props_left = 0; for (i = 0; i < TP_NUM_BASE_ROOM_CONFIG_PROPERTIES; i++) { if (g_hash_table_lookup (properties, GUINT_TO_POINTER (i)) != NULL) props_left |= 1 << i; } wocky_node_iter_init (&j, form_node, "field", NULL); while (wocky_node_iter_next (&j, &child)) { const gchar *var, *type_str; WockyNode *field_node; ConfigFormMapping *f; GValue *value = NULL; var = wocky_node_get_attribute (child, "var"); if (var == NULL) { DEBUG ("skipping node '%s' because of lacking var attribute", child->name); continue; } f = lookup_config_form_field (var); /* add the corresponding field node to the reply message */ field_node = wocky_node_add_child (submit_node, "field"); wocky_node_set_attribute (field_node, "var", var); type_str = wocky_node_get_attribute (child, "type"); if (type_str != NULL) { wocky_node_set_attribute (field_node, "type", type_str); } if (f != NULL) value = g_hash_table_lookup (properties, GUINT_TO_POINTER (f->prop_id)); if (value != NULL) { const gchar *val_str; /* Known property and we have a value to set */ DEBUG ("transforming %s...", wocky_enum_to_nick (TP_TYPE_BASE_ROOM_CONFIG_PROPERTY, f->prop_id)); g_assert (f->map != NULL); val_str = f->map (value); /* add the corresponding value node(s) to the reply message */ DEBUG ("Setting value %s for %s", val_str, var); wocky_node_add_child_with_content (field_node, "value", val_str); props_left &= ~(1 << f->prop_id); } else { /* Copy all the nodes */ WockyNodeIter k; WockyNode *value_node; wocky_node_iter_init (&k, child, "value", NULL); while (wocky_node_iter_next (&k, &value_node)) wocky_node_add_child_with_content (field_node, "value", value_node->content); } } if (props_left != 0) { GString *unsubstituted = g_string_new (""); printf ("\n%s: the following properties were not substituted:\n", G_STRFUNC); for (i = 0; i < TP_NUM_BASE_ROOM_CONFIG_PROPERTIES; i++) { if ((props_left & (1 << i)) != 0) { const gchar *name = wocky_enum_to_nick ( TP_TYPE_BASE_ROOM_CONFIG_PROPERTY, i); printf (" %s\n", name); if (unsubstituted->len > 0) g_string_append (unsubstituted, ", "); g_string_append (unsubstituted, name); } } printf ("\nthis is a MUC server compatibility bug in gabble, please " "report it with a full debug log attached (running gabble " "with WOCKY_DEBUG=xmpp)\n\n"); fflush (stdout); error = g_error_new (TP_ERROR, TP_ERROR_SERVICE_CONFUSED, "Couldn't find fields corresponding to %s in the muc#owner form. " "This is a MUC server compatibility bug in Gabble.", unsubstituted->str); g_string_free (unsubstituted, TRUE); goto OUT; } conn_util_send_iq_async (conn, submit_iq, NULL, request_config_form_submit_reply_cb, update_result); OUT: if (error != NULL) { g_simple_async_result_set_from_error (update_result, error); g_simple_async_result_complete (update_result); g_object_unref (update_result); tp_clear_pointer (&priv->properties_being_updated, g_hash_table_unref); g_clear_error (&error); } tp_clear_object (&reply); tp_clear_object (&submit_iq); g_object_unref (chan); } static void request_config_form_submit_reply_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { GSimpleAsyncResult *update_result = G_SIMPLE_ASYNC_RESULT (user_data); GabbleMucChannel *chan = GABBLE_MUC_CHANNEL ( g_async_result_get_source_object ((GAsyncResult *) update_result)); GabbleMucChannelPrivate *priv = chan->priv; GError *error = NULL; if (!conn_util_send_iq_finish (GABBLE_CONNECTION (source), result, NULL, &error)) { g_prefix_error (&error, "submitted configuration form was rejected: "); g_simple_async_result_set_from_error (update_result, error); g_clear_error (&error); } g_simple_async_result_complete (update_result); tp_clear_pointer (&priv->properties_being_updated, g_hash_table_unref); /* Get the properties into a consistent state. */ room_properties_update (chan); g_object_unref (chan); g_object_unref (update_result); } static gboolean gabble_muc_channel_send_chat_state (GObject *object, TpChannelChatState state, GError **error) { GabbleMucChannel *self = GABBLE_MUC_CHANNEL (object); GabbleMucChannelPrivate *priv = self->priv; TpBaseChannel *base = TP_BASE_CHANNEL (self); if (priv->have_received_error_type_wait) return TRUE; return gabble_message_util_send_chat_state (G_OBJECT (self), GABBLE_CONNECTION (tp_base_channel_get_connection (base)), WOCKY_STANZA_SUB_TYPE_GROUPCHAT, state, priv->jid, error); } void gabble_muc_channel_send_presence (GabbleMucChannel *self) { GabbleMucChannelPrivate *priv = self->priv; TpBaseChannel *base = TP_BASE_CHANNEL (self); WockyStanza *stanza; /* do nothing if we havn't actually joined yet */ if (priv->state < MUC_STATE_INITIATED) return; stanza = wocky_muc_create_presence (priv->wmuc, WOCKY_STANZA_SUB_TYPE_NONE, NULL); _gabble_connection_send ( GABBLE_CONNECTION (tp_base_channel_get_connection (base)), stanza, NULL); g_object_unref (stanza); } #ifdef ENABLE_VOIP GabbleCallMucChannel * gabble_muc_channel_get_call (GabbleMucChannel *gmuc) { return gmuc->priv->call; } GList * gabble_muc_channel_get_call_channels (GabbleMucChannel *self) { return self->priv->calls; } static void muc_channel_call_state_changed_cb (GabbleCallMucChannel *muc, TpCallState state, TpCallFlags flags, GValueArray *reason, GHashTable *details, GabbleMucChannel *gmuc) { GabbleMucChannelPrivate *priv = gmuc->priv; if (state != TP_CALL_STATE_ENDED) return; if (priv->call == muc) priv->call = NULL; } static void muc_channel_call_closed_cb (GabbleCallMucChannel *muc, gpointer user_data) { GabbleMucChannel *gmuc = GABBLE_MUC_CHANNEL (user_data); GabbleMucChannelPrivate *priv = gmuc->priv; g_assert (g_list_find (priv->calls, muc) != NULL); /* closed the active muc */ if (priv->call == muc) priv->call = NULL; priv->calls = g_list_remove (priv->calls, muc); g_object_unref (muc); } static void muc_call_channel_finish_requests (GabbleMucChannel *self, GabbleCallMucChannel *call, GError *error) { GList *l; if (call != NULL) { GSList *requests = NULL; DEBUG ("Call channel created"); for (l = self->priv->call_requests ; l != NULL; l = g_list_next (l)) requests = g_slist_append (requests, g_simple_async_result_get_op_res_gpointer ( G_SIMPLE_ASYNC_RESULT(l->data))); g_signal_emit (self, signals[NEW_CALL], 0, call, requests); g_slist_free (requests); } else { DEBUG ("Failed to create call channel: %s", error->message); } for (l = self->priv->call_requests ; l != NULL; l = g_list_next (l)) { GSimpleAsyncResult *r = G_SIMPLE_ASYNC_RESULT (l->data); if (error != NULL) g_simple_async_result_set_from_error (r, error); g_simple_async_result_complete (r); g_object_unref (r); } g_list_free (self->priv->call_requests); self->priv->call_requests = NULL; } static void muc_channel_call_channel_done_cb (GObject *source, GAsyncResult *result, gpointer user_data) { GabbleMucChannel *gmuc = GABBLE_MUC_CHANNEL (user_data); GabbleMucChannelPrivate *priv = gmuc->priv; GError *error = NULL; g_assert (priv->call == NULL); if (tp_base_channel_is_destroyed (TP_BASE_CHANNEL (gmuc))) goto out; priv->call_initiating = FALSE; priv->call = gabble_call_muc_channel_new_finish (source, result, &error); if (priv->call == NULL) goto error; priv->calls = g_list_prepend (priv->calls, priv->call); g_signal_connect (priv->call, "closed", G_CALLBACK (muc_channel_call_closed_cb), gmuc); g_signal_connect (priv->call, "call-state-changed", G_CALLBACK (muc_channel_call_state_changed_cb), gmuc); error: muc_call_channel_finish_requests (gmuc, priv->call, error); g_clear_error (&error); out: /* we kept ourselves reffed while the call channel was being created */ g_object_unref (gmuc); } static void gabble_muc_channel_start_call_creation (GabbleMucChannel *gmuc, GHashTable *request) { GabbleMucChannelPrivate *priv = gmuc->priv; TpBaseChannel *base = TP_BASE_CHANNEL (gmuc); TpBaseConnection *base_conn = tp_base_channel_get_connection (base); const gchar *prefix; g_assert (!priv->call_initiating); g_assert (priv->call == NULL); priv->call_initiating = TRUE; /* We want to put the call channel "under" ourself, but let it decide its * exact path. TpBaseChannel makes this a little awkward — the vfunc for * picking your own path is supposed to return the suffix, and the base class * pastes on the connection's path before that. * * So... we pass the bit of our own path that's after the connection's path * to the call channel; it builds its suffix based on that and its own * address; and finally TpBaseChannel pastes the connection path back on. :) */ prefix = tp_base_channel_get_object_path (base) + strlen (tp_base_connection_get_object_path (base_conn)) + 1 /* for the slash */; /* Keep ourselves reffed while call channels are created */ g_object_ref (gmuc); gabble_call_muc_channel_new_async ( GABBLE_CONNECTION (base_conn), priv->requests_cancellable, prefix, gmuc, tp_base_channel_get_target_handle (base), request, muc_channel_call_channel_done_cb, gmuc); } void gabble_muc_channel_request_call (GabbleMucChannel *gmuc, GHashTable *request, gboolean require_new, gpointer token, GAsyncReadyCallback callback, gpointer user_data) { GabbleMucChannelPrivate *priv = gmuc->priv; GSimpleAsyncResult *res; /* FIXME: Ponder whether this function should even be used when the call * already exists and to have the return indicate that it was already * satisfied (instead of a newly created channel) */ g_assert (priv->call == NULL); if (require_new && priv->call_initiating) { g_simple_async_report_error_in_idle (G_OBJECT (gmuc), callback, user_data, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "A request for a call is already in progress"); return; } if (!priv->call_initiating) gabble_muc_channel_start_call_creation (gmuc, request); res = g_simple_async_result_new (G_OBJECT (gmuc), callback, user_data, gabble_muc_channel_request_call_finish); g_simple_async_result_set_op_res_gpointer (res, token, NULL); priv->call_requests = g_list_append (priv->call_requests, res); } gboolean gabble_muc_channel_request_call_finish (GabbleMucChannel *gmuc, GAsyncResult *result, GError **error) { if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) return FALSE; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (gmuc), gabble_muc_channel_request_call_finish), FALSE); return TRUE; } gboolean gabble_muc_channel_handle_jingle_session (GabbleMucChannel *self, WockyJingleSession *session) { GabbleMucChannelPrivate *priv = self->priv; /* No Muji no need to handle call sessions */ if (priv->call == NULL) return FALSE; gabble_call_muc_channel_incoming_session (priv->call, session); return TRUE; } #endif void gabble_muc_channel_teardown (GabbleMucChannel *gmuc) { close_channel (gmuc, NULL, FALSE, 0, 0); } static void sent_subject_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { GabbleMucChannel *self = GABBLE_MUC_CHANNEL (user_data); GabbleMucChannelPrivate *priv = self->priv; GError *error = NULL; if (!wocky_porter_send_finish (WOCKY_PORTER (source), result, &error)) { DEBUG ("buh, failed to send a to change the subject: %s", error->message); if (priv->set_subject_context != NULL) { GError *tp_error = NULL; gabble_set_tp_error_from_wocky (error, &tp_error); return_from_set_subject (self, tp_error); g_clear_error (&tp_error); } g_clear_error (&error); } /* otherwise, we wait for a reply! */ g_object_unref (self); } static void gabble_muc_channel_set_subject (TpSvcChannelInterfaceSubject *iface, const gchar *subject, DBusGMethodInvocation *context) { GabbleMucChannel *self = GABBLE_MUC_CHANNEL (iface); GabbleMucChannelPrivate *priv = self->priv; GabbleConnection *conn = GABBLE_CONNECTION (tp_base_channel_get_connection ( TP_BASE_CHANNEL (self))); WockyPorter *porter = wocky_session_get_porter (conn->session); if (priv->state < MUC_STATE_JOINED) { GError error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE, "Steady on. You're not in the room yet" }; dbus_g_method_return_error (context, &error); } else if (priv->state > MUC_STATE_JOINED || priv->closing) { GError error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE, "Already left/leaving the room" }; dbus_g_method_return_error (context, &error); } else if (priv->set_subject_context != NULL) { GError error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE, "Hey! Stop changing the subject! (Your last request is still in " "flight.)" }; dbus_g_method_return_error (context, &error); } else { WockyXmppConnection *xmpp_conn; WockyStanza *stanza; g_assert (priv->set_subject_stanza_id == NULL); g_object_get (porter, "connection", &xmpp_conn, NULL); priv->set_subject_stanza_id = wocky_xmpp_connection_new_id (xmpp_conn); g_object_unref (xmpp_conn); stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_GROUPCHAT, NULL, priv->jid, '@', "id", priv->set_subject_stanza_id, '(', "subject", '$', subject, ')', NULL); priv->set_subject_context = context; wocky_porter_send_async (porter, stanza, NULL, sent_subject_cb, g_object_ref (self)); g_object_unref (stanza); } } static void password_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcChannelInterfacePasswordClass *klass = (TpSvcChannelInterfacePasswordClass *) g_iface; #define IMPLEMENT(x) tp_svc_channel_interface_password_implement_##x (\ klass, gabble_muc_channel_##x) IMPLEMENT(get_password_flags); IMPLEMENT(provide_password); #undef IMPLEMENT } static void subject_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcChannelInterfaceSubjectClass *klass = (TpSvcChannelInterfaceSubjectClass *) g_iface; #define IMPLEMENT(x) tp_svc_channel_interface_subject_implement_##x (\ klass, gabble_muc_channel_##x) IMPLEMENT(set_subject); #undef IMPLEMENT } telepathy-gabble-0.18.3/src/call-member.c0000664000175000017500000004106712223562023021316 0ustar00cassidycassidy00000000000000/* * call-member.c - Source for CallMember * Copyright (C) 2010 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include "connection.h" #include "call-member.h" #include "base-call-channel.h" #include "util.h" #include "namespaces.h" #define DEBUG_FLAG GABBLE_DEBUG_MEDIA #include "debug.h" G_DEFINE_TYPE(GabbleCallMember, gabble_call_member, G_TYPE_OBJECT) /* signal enum */ enum { FLAGS_CHANGED, CONTENT_ADDED, CONTENT_REMOVED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; /* properties */ enum { PROP_CALL = 1, PROP_TARGET, PROP_SESSION }; /* private structure */ struct _GabbleCallMemberPrivate { TpHandle target; GabbleBaseCallChannel *call; TpCallMemberFlags flags; WockyJingleSession *session; GList *contents; gchar *transport_ns; gboolean accepted; gboolean dispose_has_run; }; #define GABBLE_CALL_MEMBER_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), GABBLE_TYPE_CALL_MEMBER, \ GabbleCallMemberPrivate)) static void gabble_call_member_init (GabbleCallMember *self) { GabbleCallMemberPrivate *priv = GABBLE_CALL_MEMBER_GET_PRIVATE (self); self->priv = priv; priv->accepted = FALSE; } static void gabble_call_member_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleCallMember *self = GABBLE_CALL_MEMBER (object); GabbleCallMemberPrivate *priv = self->priv; switch (property_id) { case PROP_CALL: g_value_set_object (value, gabble_call_member_get_connection (self)); break; case PROP_SESSION: g_value_set_object (value, priv->session); break; case PROP_TARGET: g_value_set_uint (value, priv->target); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_call_member_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleCallMember *self = GABBLE_CALL_MEMBER (object); GabbleCallMemberPrivate *priv = self->priv; switch (property_id) { case PROP_CALL: priv->call = g_value_get_object (value); g_assert (priv->call != NULL); break; case PROP_SESSION: gabble_call_member_set_session (self, WOCKY_JINGLE_SESSION (g_value_get_object (value))); break; case PROP_TARGET: priv->target = g_value_get_uint (value); g_assert (priv->target != 0); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_call_member_dispose (GObject *object); static void gabble_call_member_finalize (GObject *object); static void gabble_call_member_class_init ( GabbleCallMemberClass *gabble_call_member_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_call_member_class); GParamSpec *param_spec; g_type_class_add_private (gabble_call_member_class, sizeof (GabbleCallMemberPrivate)); object_class->dispose = gabble_call_member_dispose; object_class->finalize = gabble_call_member_finalize; object_class->get_property = gabble_call_member_get_property; object_class->set_property = gabble_call_member_set_property; param_spec = g_param_spec_object ("call", "Call", "The base call object that contains this member", GABBLE_TYPE_BASE_CALL_CHANNEL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CALL, param_spec); param_spec = g_param_spec_object ("session", "Session", "The jingle session below this call", WOCKY_TYPE_JINGLE_SESSION, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SESSION, param_spec); param_spec = g_param_spec_uint ("target", "Target", "the target handle of member", 0, G_MAXUINT, 0, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_TARGET, param_spec); signals[FLAGS_CHANGED] = g_signal_new ("flags-changed", G_OBJECT_CLASS_TYPE (gabble_call_member_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals[CONTENT_ADDED] = g_signal_new ("content-added", G_OBJECT_CLASS_TYPE (gabble_call_member_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); signals[CONTENT_REMOVED] = g_signal_new ("content-removed", G_OBJECT_CLASS_TYPE (gabble_call_member_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); } void gabble_call_member_dispose (GObject *object) { GabbleCallMember *self = GABBLE_CALL_MEMBER (object); GabbleCallMemberPrivate *priv = self->priv; GList *l; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; tp_clear_object (&priv->session); for (l = priv->contents ; l != NULL; l = g_list_next (l)) g_object_unref (l->data); tp_clear_pointer (&priv->contents, g_list_free); /* release any references held by the object here */ if (G_OBJECT_CLASS (gabble_call_member_parent_class)->dispose) G_OBJECT_CLASS (gabble_call_member_parent_class)->dispose (object); } void gabble_call_member_finalize (GObject *object) { GabbleCallMember *self = GABBLE_CALL_MEMBER (object); GabbleCallMemberPrivate *priv = self->priv; g_free (priv->transport_ns); priv->transport_ns = NULL; G_OBJECT_CLASS (gabble_call_member_parent_class)->finalize (object); } static void remote_state_changed_cb (WockyJingleSession *session, gpointer user_data) { GabbleCallMember *self = GABBLE_CALL_MEMBER (user_data); GabbleCallMemberPrivate *priv = self->priv; TpCallMemberFlags newflags = 0; if (wocky_jingle_session_get_remote_ringing (session)) newflags |= TP_CALL_MEMBER_FLAG_RINGING; if (wocky_jingle_session_get_remote_hold (session)) newflags |= TP_CALL_MEMBER_FLAG_HELD; if (priv->flags == newflags) return; priv->flags = newflags; DEBUG ("Call members flags changed to: %d", priv->flags); g_signal_emit (self, signals[FLAGS_CHANGED], 0, priv->flags); } static void member_content_removed_cb (GabbleCallMemberContent *mcontent, gpointer user_data) { GabbleCallMember *self = GABBLE_CALL_MEMBER (user_data); GabbleCallMemberPrivate *priv = self->priv; priv->contents = g_list_remove (priv->contents, mcontent); g_signal_emit (self, signals[CONTENT_REMOVED], 0, mcontent); g_object_unref (mcontent); } static void gabble_call_member_add_member_content (GabbleCallMember *self, GabbleCallMemberContent *content) { GabbleCallMemberPrivate *priv = self->priv; priv->contents = g_list_prepend (priv->contents, content); gabble_signal_connect_weak (content, "removed", G_CALLBACK (member_content_removed_cb), G_OBJECT (self)); g_signal_emit (self, signals[CONTENT_ADDED], 0, content); } /* This function handles additional contents added by the remote side */ static void new_content_cb (WockyJingleSession *session, WockyJingleContent *c, gpointer user_data) { GabbleCallMember *self = GABBLE_CALL_MEMBER (user_data); GabbleCallMemberContent *content = NULL; if (wocky_jingle_content_is_created_by_us (c)) return; content = gabble_call_member_content_from_jingle_content (c, self); gabble_call_member_add_member_content (self, content); } static gboolean call_member_update_existing_content (GabbleCallMember *self, WockyJingleContent *content) { GList *l; for (l = self->priv->contents; l != NULL ; l = g_list_next (l)) { GabbleCallMemberContent *mcontent = GABBLE_CALL_MEMBER_CONTENT (l->data); if (gabble_call_member_content_has_jingle_content (mcontent)) continue; if (!tp_strdiff (gabble_call_member_content_get_name (mcontent), wocky_jingle_content_get_name (content))) { gabble_call_member_content_set_jingle_content (mcontent, content); return TRUE; } } return FALSE; } void gabble_call_member_set_session (GabbleCallMember *self, WockyJingleSession *session) { GabbleCallMemberPrivate *priv = self->priv; GList *c, *contents; g_assert (priv->session == NULL); g_assert (session != NULL); DEBUG ("Setting session: %p -> %p\n", self, session); priv->session = g_object_ref (session); contents = wocky_jingle_session_get_contents (session); for (c = contents ; c != NULL; c = g_list_next (c)) { WockyJingleContent *content = WOCKY_JINGLE_CONTENT (c->data); if (priv->transport_ns == NULL) { g_object_get (content, "transport-ns", &priv->transport_ns, NULL); } if (!call_member_update_existing_content (self, content)) { GabbleCallMemberContent *mcontent = gabble_call_member_content_from_jingle_content (content, self); gabble_call_member_add_member_content (self, mcontent); } } g_object_notify (G_OBJECT (self), "session"); gabble_signal_connect_weak (priv->session, "remote-state-changed", G_CALLBACK (remote_state_changed_cb), G_OBJECT (self)); gabble_signal_connect_weak (priv->session, "new-content", G_CALLBACK (new_content_cb), G_OBJECT (self)); if (priv->accepted) gabble_call_member_accept (self); g_list_free (contents); } WockyJingleSession * gabble_call_member_get_session (GabbleCallMember *self) { return self->priv->session; } TpCallMemberFlags gabble_call_member_get_flags (GabbleCallMember *self) { return self->priv->flags; } TpHandle gabble_call_member_get_handle ( GabbleCallMember *self) { return self->priv->target; } GList * gabble_call_member_get_contents (GabbleCallMember *self) { GabbleCallMemberPrivate *priv = self->priv; return priv->contents; } GabbleCallMemberContent * gabble_call_member_ensure_content (GabbleCallMember *self, const gchar *name, WockyJingleMediaType mtype) { GabbleCallMemberPrivate *priv = self->priv; GList *l; GabbleCallMemberContent *content = NULL; for (l = priv->contents ; l != NULL; l = g_list_next (l)) { GabbleCallMemberContent *c = GABBLE_CALL_MEMBER_CONTENT (l->data); if (gabble_call_member_content_get_media_type (c) == mtype && !tp_strdiff (gabble_call_member_content_get_name (c), name)) { content = c; break; } } if (content == NULL) { content = gabble_call_member_content_new (name, mtype, self); gabble_call_member_add_member_content (self, content); } return content; } GabbleCallMemberContent * gabble_call_member_create_content (GabbleCallMember *self, const gchar *name, WockyJingleMediaType mtype, WockyJingleContentSenders senders, GError **error) { GabbleCallMemberPrivate *priv = self->priv; const gchar *content_ns; WockyJingleContent *c; GabbleCallMemberContent *content; const gchar *peer_resource; g_assert (priv->session != NULL); peer_resource = wocky_jingle_session_get_peer_resource (priv->session); DEBUG ("Creating new content %s, type %d", name, mtype); if (peer_resource != NULL) DEBUG ("existing call, using peer resource %s", peer_resource); else DEBUG ("existing call, using bare JID"); content_ns = jingle_pick_best_content_type (gabble_call_member_get_connection (self), priv->target, peer_resource, mtype); if (content_ns == NULL) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "Content type %d not available for this resource", mtype); return NULL; } DEBUG ("Creating new jingle content with ns %s : %s", content_ns, priv->transport_ns); c = wocky_jingle_session_add_content (priv->session, mtype, senders, name, content_ns, priv->transport_ns); g_assert (c != NULL); content = gabble_call_member_content_from_jingle_content (c, self); gabble_call_member_add_member_content (self, content); return content; } void gabble_call_member_accept (GabbleCallMember *self) { self->priv->accepted = TRUE; if (self->priv->session != NULL) wocky_jingle_session_accept (self->priv->session); } /** * Start a new session using the existing contents for this member. For now * assumes we're using the latest jingle dialect and ice-udp * FIXME: make dialect and transport selection more dynamic? */ gboolean gabble_call_member_open_session (GabbleCallMember *self, GError **error) { GabbleCallMemberPrivate *priv = self->priv; GabbleConnection *conn = gabble_call_member_get_connection (self); WockyJingleFactory *jf; WockyJingleSession *session; gchar *jid; jid = gabble_peer_to_jid (conn, priv->target, NULL); jf = gabble_jingle_mint_get_factory (conn->jingle_mint); g_return_val_if_fail (jf != NULL, FALSE); session = wocky_jingle_factory_create_session (jf, jid, WOCKY_JINGLE_DIALECT_V032, FALSE); DEBUG ("Created a jingle session: %p", session); priv->transport_ns = g_strdup (NS_JINGLE_TRANSPORT_ICEUDP); gabble_call_member_set_session (self, session); g_free (jid); return TRUE; } gboolean gabble_call_member_start_session (GabbleCallMember *self, const gchar *audio_name, const gchar *video_name, GError **error) { GabbleCallMemberPrivate *priv = self->priv; TpBaseChannel *base_channel = TP_BASE_CHANNEL (priv->call); TpHandle target = tp_base_channel_get_target_handle (base_channel); const gchar *resource; WockyJingleDialect dialect; gchar *jid; const gchar *transport; WockyJingleFactory *jf; WockyJingleSession *session; /* FIXME might need to wait on capabilities, also don't need transport * and dialect already */ if (!jingle_pick_best_resource (gabble_call_member_get_connection (self), target, audio_name != NULL, video_name != NULL, &transport, &dialect, &resource)) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_CAPABLE, "member does not have the desired audio/video capabilities"); return FALSE; } jid = gabble_peer_to_jid (gabble_call_member_get_connection (self), target, resource); jf = gabble_jingle_mint_get_factory ( gabble_call_member_get_connection (self)->jingle_mint); g_return_val_if_fail (jf != NULL, FALSE); session = wocky_jingle_factory_create_session (jf, jid, dialect, FALSE); g_free (jid); gabble_call_member_set_session (self, session); priv->transport_ns = g_strdup (transport); if (audio_name != NULL) gabble_call_member_create_content (self, audio_name, WOCKY_JINGLE_MEDIA_TYPE_AUDIO, WOCKY_JINGLE_CONTENT_SENDERS_BOTH, NULL); if (video_name != NULL) gabble_call_member_create_content (self, video_name, WOCKY_JINGLE_MEDIA_TYPE_VIDEO, WOCKY_JINGLE_CONTENT_SENDERS_BOTH, NULL); return TRUE; } GabbleConnection * gabble_call_member_get_connection (GabbleCallMember *self) { TpBaseChannel *base_chan = TP_BASE_CHANNEL (self->priv->call); return GABBLE_CONNECTION (tp_base_channel_get_connection (base_chan)); } const gchar * gabble_call_member_get_transport_ns (GabbleCallMember *self) { return self->priv->transport_ns; } void gabble_call_member_shutdown (GabbleCallMember *self) { GabbleCallMemberPrivate *priv = self->priv; if (priv->session != NULL) { wocky_jingle_session_terminate (priv->session, WOCKY_JINGLE_REASON_UNKNOWN, NULL, NULL); } /* removing the content will remove it from our list */ while (priv->contents != NULL) gabble_call_member_content_remove ( GABBLE_CALL_MEMBER_CONTENT (priv->contents->data)); } telepathy-gabble-0.18.3/src/base-call-channel.h0000664000175000017500000000641412223562023022371 0ustar00cassidycassidy00000000000000/* * base-call-channel.h - Header for GabbleBaseCallChannel * Copyright © 2009–2010 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_BASE_CALL_CHANNEL_H__ #define __GABBLE_BASE_CALL_CHANNEL_H__ #include #include #include #include #include "call-member.h" #include "call-content.h" G_BEGIN_DECLS typedef struct _GabbleBaseCallChannel GabbleBaseCallChannel; typedef struct _GabbleBaseCallChannelPrivate GabbleBaseCallChannelPrivate; typedef struct _GabbleBaseCallChannelClass GabbleBaseCallChannelClass; struct _GabbleBaseCallChannelClass { TpBaseMediaCallChannelClass parent_class; }; struct _GabbleBaseCallChannel { TpBaseMediaCallChannel parent; GabbleBaseCallChannelPrivate *priv; }; GType gabble_base_call_channel_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_BASE_CALL_CHANNEL \ (gabble_base_call_channel_get_type ()) #define GABBLE_BASE_CALL_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ GABBLE_TYPE_BASE_CALL_CHANNEL, GabbleBaseCallChannel)) #define GABBLE_BASE_CALL_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), \ GABBLE_TYPE_BASE_CALL_CHANNEL, GabbleBaseCallChannelClass)) #define GABBLE_IS_BASE_CALL_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_BASE_CALL_CHANNEL)) #define GABBLE_IS_BASE_CALL_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_BASE_CALL_CHANNEL)) #define GABBLE_BASE_CALL_CHANNEL_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ GABBLE_TYPE_BASE_CALL_CHANNEL, GabbleBaseCallChannelClass)) GabbleCallMember *gabble_base_call_channel_ensure_member ( GabbleBaseCallChannel *self, const gchar *jid); void gabble_base_call_channel_remove_member (GabbleBaseCallChannel *self, GabbleCallMember *member); GabbleCallMember *gabble_base_call_channel_ensure_member_from_handle ( GabbleBaseCallChannel *self, TpHandle handle); GabbleCallMember * gabble_base_call_channel_get_member_from_handle ( GabbleBaseCallChannel *self, TpHandle handle); GabbleCallContent * gabble_base_call_channel_add_content ( GabbleBaseCallChannel *self, const gchar *name, WockyJingleMediaType mtype, TpCallContentDisposition disposition); void gabble_base_call_channel_remove_content (GabbleBaseCallChannel *self, GabbleCallContent *content); GHashTable *gabble_base_call_channel_get_members (GabbleBaseCallChannel *self); G_END_DECLS #endif /* #ifndef __GABBLE_BASE_CALL_CHANNEL_H__*/ telepathy-gabble-0.18.3/src/jingle-share.h0000664000175000017500000000536412223562023021513 0ustar00cassidycassidy00000000000000/* * jingle-share.h - Header for GabbleJingleShare * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __JINGLE_SHARE_H__ #define __JINGLE_SHARE_H__ #include #include G_BEGIN_DECLS typedef struct _GabbleJingleShareClass GabbleJingleShareClass; GType gabble_jingle_share_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_JINGLE_SHARE \ (gabble_jingle_share_get_type ()) #define GABBLE_JINGLE_SHARE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_JINGLE_SHARE, \ GabbleJingleShare)) #define GABBLE_JINGLE_SHARE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_JINGLE_SHARE, \ GabbleJingleShareClass)) #define GABBLE_IS_JINGLE_SHARE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_JINGLE_SHARE)) #define GABBLE_IS_JINGLE_SHARE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_JINGLE_SHARE)) #define GABBLE_JINGLE_SHARE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_JINGLE_SHARE, \ GabbleJingleShareClass)) struct _GabbleJingleShareClass { WockyJingleContentClass parent_class; }; typedef struct _GabbleJingleSharePrivate GabbleJingleSharePrivate; typedef struct _GabbleJingleShare GabbleJingleShare; struct _GabbleJingleShare { WockyJingleContent parent; GabbleJingleSharePrivate *priv; }; typedef struct { gboolean folder; gboolean image; guint64 size; gchar *name; guint image_width; guint image_height; } GabbleJingleShareManifestEntry; typedef struct { gchar *source_url; gchar *preview_url; /* a list of g_slice_new (GabbleJingleShareManifestEntry) */ GList *entries; } GabbleJingleShareManifest; void jingle_share_register (WockyJingleFactory *factory); gchar *gabble_jingle_share_get_source_url (GabbleJingleShare *content); gchar *gabble_jingle_share_get_preview_url (GabbleJingleShare *content); GabbleJingleShareManifest *gabble_jingle_share_get_manifest ( GabbleJingleShare *content); #endif /* __JINGLE_SHARE_H__ */ telepathy-gabble-0.18.3/src/media-channel-hold.c0000664000175000017500000003166512332441362022555 0ustar00cassidycassidy00000000000000/* * media-channel-hold.c - Hold and CallState interface implementations * Copyright © 2006–2009 Collabora Ltd. * Copyright © 2006–2009 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "media-channel.h" #include "media-channel-internal.h" #include #define DEBUG_FLAG GABBLE_DEBUG_MEDIA #include "debug.h" #include "util.h" /* * Implementation of Channel.Interface.Hold, which deals with placing the peer * on and off hold. */ static void stream_hold_state_changed (GabbleMediaStream *stream G_GNUC_UNUSED, GParamSpec *unused G_GNUC_UNUSED, gpointer data) { GabbleMediaChannel *self = data; GabbleMediaChannelPrivate *priv = self->priv; gboolean all_held = TRUE, any_held = FALSE; guint i; for (i = 0; i < priv->streams->len; i++) { gboolean its_hold; g_object_get (g_ptr_array_index (priv->streams, i), "local-hold", &its_hold, NULL); DEBUG ("Stream at index %u has local-hold=%u", i, (guint) its_hold); all_held = all_held && its_hold; any_held = any_held || its_hold; } DEBUG ("all_held=%u, any_held=%u", (guint) all_held, (guint) any_held); if (all_held && !any_held) { /* There are no streams, move to the desired state immediately */ switch (priv->hold_state) { case TP_LOCAL_HOLD_STATE_PENDING_HOLD: DEBUG ("no streams, moving from pending hold to held"); priv->hold_state = TP_LOCAL_HOLD_STATE_HELD; /* No need to touch the session: send_held (TRUE) is called as soon * as Hold is requested. */ break; case TP_LOCAL_HOLD_STATE_PENDING_UNHOLD: DEBUG ("no streams, moving from pending unhold to unheld"); priv->hold_state = TP_LOCAL_HOLD_STATE_UNHELD; if (priv->session != NULL) wocky_jingle_session_set_local_hold (priv->session, FALSE); break; default: /* nothing to change */ return; } } else if (all_held) { /* Move to state HELD */ switch (priv->hold_state) { case TP_LOCAL_HOLD_STATE_HELD: /* nothing changed */ return; case TP_LOCAL_HOLD_STATE_PENDING_UNHOLD: /* This can happen if the user asks us to hold, then changes their * mind. We make no particular guarantees about stream states when * in PENDING_UNHOLD state, so keep claiming to be in that state */ return; case TP_LOCAL_HOLD_STATE_PENDING_HOLD: /* We wanted to hold, and indeed we have. Yay! Keep whatever * reason code we used for going to PENDING_HOLD */ priv->hold_state = TP_LOCAL_HOLD_STATE_HELD; break; case TP_LOCAL_HOLD_STATE_UNHELD: /* We were previously UNHELD. So why have we gone on hold now? */ DEBUG ("Unexpectedly entered HELD state!"); priv->hold_state = TP_LOCAL_HOLD_STATE_HELD; priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_NONE; break; } } else if (any_held) { switch (priv->hold_state) { case TP_LOCAL_HOLD_STATE_UNHELD: /* The streaming client has spontaneously changed its stream * state. Why? We just don't know */ DEBUG ("Unexpectedly entered PENDING_UNHOLD state!"); priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_UNHOLD; priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_NONE; break; case TP_LOCAL_HOLD_STATE_HELD: /* Likewise */ DEBUG ("Unexpectedly entered PENDING_HOLD state!"); priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_HOLD; priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_NONE; break; default: /* nothing particularly interesting - we're trying to change hold * state already, so nothing to signal */ return; } } else { /* Move to state UNHELD */ switch (priv->hold_state) { case TP_LOCAL_HOLD_STATE_UNHELD: /* nothing changed */ return; case TP_LOCAL_HOLD_STATE_PENDING_HOLD: /* This can happen if the user asks us to unhold, then changes their * mind. We make no particular guarantees about stream states when * in PENDING_HOLD state, so keep claiming to be in that state */ return; case TP_LOCAL_HOLD_STATE_PENDING_UNHOLD: /* We wanted to hold, and indeed we have. Yay! Keep whatever * reason code we used for going to PENDING_UNHOLD */ priv->hold_state = TP_LOCAL_HOLD_STATE_UNHELD; break; case TP_LOCAL_HOLD_STATE_HELD: /* We were previously HELD. So why have we gone off hold now? */ DEBUG ("Unexpectedly entered UNHELD state!"); priv->hold_state = TP_LOCAL_HOLD_STATE_UNHELD; priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_NONE; break; } /* Tell the peer what's happened. */ if (priv->session != NULL) wocky_jingle_session_set_local_hold (priv->session, FALSE); } tp_svc_channel_interface_hold_emit_hold_state_changed (self, priv->hold_state, priv->hold_state_reason); } static void stream_unhold_failed (GabbleMediaStream *stream, gpointer data) { GabbleMediaChannel *self = data; GabbleMediaChannelPrivate *priv = self->priv; guint i; DEBUG ("%p: %p", self, stream); /* Unholding failed - let's roll back to Hold state */ priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_HOLD; priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_RESOURCE_NOT_AVAILABLE; tp_svc_channel_interface_hold_emit_hold_state_changed (self, priv->hold_state, priv->hold_state_reason); /* The stream's state may have changed from unheld to held, so re-poll. * It's possible that all streams are now held, in which case we can stop. */ stream_hold_state_changed (stream, NULL, self); if (priv->hold_state == TP_LOCAL_HOLD_STATE_HELD) return; /* There should be no need to notify the peer, who already thinks they're * on hold, so just tell the streaming client what to do. */ for (i = 0; i < priv->streams->len; i++) { gabble_media_stream_hold (g_ptr_array_index (priv->streams, i), TRUE); } } void gabble_media_channel_hold_stream_closed (GabbleMediaChannel *chan, GabbleMediaStream *stream) { /* A stream closing might cause the "total" hold state to change: * if there's one held and one unheld, and the unheld one closes, * then our state changes from indeterminate to held. */ stream_hold_state_changed (stream, NULL, chan); } /* Implements RequestHold on Telepathy.Channel.Interface.Hold */ static void gabble_media_channel_request_hold (TpSvcChannelInterfaceHold *iface, gboolean hold, DBusGMethodInvocation *context) { GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (iface); GabbleMediaChannelPrivate *priv = self->priv; WockyJingleSession *session = priv->session; guint i; TpLocalHoldState old_state = priv->hold_state; DEBUG ("%p: RequestHold(%u)", self, !!hold); if (hold) { if (priv->hold_state == TP_LOCAL_HOLD_STATE_HELD) { DEBUG ("No-op"); tp_svc_channel_interface_hold_return_from_request_hold (context); return; } if (priv->hold_state == TP_LOCAL_HOLD_STATE_UNHELD && session != NULL) wocky_jingle_session_set_local_hold (session, TRUE); priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_HOLD; } else { if (priv->hold_state == TP_LOCAL_HOLD_STATE_UNHELD) { DEBUG ("No-op"); tp_svc_channel_interface_hold_return_from_request_hold (context); return; } priv->hold_state = TP_LOCAL_HOLD_STATE_PENDING_UNHOLD; } if (old_state != priv->hold_state || priv->hold_state_reason != TP_LOCAL_HOLD_STATE_REASON_REQUESTED) { tp_svc_channel_interface_hold_emit_hold_state_changed (self, priv->hold_state, TP_LOCAL_HOLD_STATE_REASON_REQUESTED); priv->hold_state_reason = TP_LOCAL_HOLD_STATE_REASON_REQUESTED; } if (priv->streams->len == 0) { /* No streams yet! We can go straight to the desired state. */ stream_hold_state_changed (NULL, NULL, self); } else { /* Tell streaming client to release or reacquire resources */ for (i = 0; i < priv->streams->len; i++) { gabble_media_stream_hold (g_ptr_array_index (priv->streams, i), hold); } } tp_svc_channel_interface_hold_return_from_request_hold (context); } /* Implements GetHoldState on Telepathy.Channel.Interface.Hold */ static void gabble_media_channel_get_hold_state (TpSvcChannelInterfaceHold *iface, DBusGMethodInvocation *context) { GabbleMediaChannel *self = (GabbleMediaChannel *) iface; GabbleMediaChannelPrivate *priv = self->priv; tp_svc_channel_interface_hold_return_from_get_hold_state (context, priv->hold_state, priv->hold_state_reason); } void gabble_media_channel_hold_iface_init (gpointer g_iface, gpointer iface_data G_GNUC_UNUSED) { TpSvcChannelInterfaceHoldClass *klass = g_iface; #define IMPLEMENT(x) tp_svc_channel_interface_hold_implement_##x (\ klass, gabble_media_channel_##x) IMPLEMENT(get_hold_state); IMPLEMENT(request_hold); #undef IMPLEMENT } /* * Implementation of Channel.Interface.CallState, which indicates call states * from the peer (such as being put on or off hold, or that the peer's client * is ringing. */ static void remote_state_changed_cb (WockyJingleSession *session, GabbleMediaChannel *self) { GabbleMediaChannelPrivate *priv = self->priv; TpChannelCallStateFlags call_state = 0; if (wocky_jingle_session_get_remote_hold (session)) call_state |= TP_CHANNEL_CALL_STATE_HELD; if (wocky_jingle_session_get_remote_ringing (session)) call_state |= TP_CHANNEL_CALL_STATE_RINGING; DEBUG ("Call state changed to %u (current state %u)", call_state, priv->call_state); if (call_state == priv->call_state) return; priv->call_state = call_state; tp_svc_channel_interface_call_state_emit_call_state_changed (self, priv->peer, call_state); } /* Implements GetCallStates on Channel.Interface.CallState */ static void gabble_media_channel_get_call_states (TpSvcChannelInterfaceCallState *iface, DBusGMethodInvocation *context) { GabbleMediaChannel *self = (GabbleMediaChannel *) iface; GabbleMediaChannelPrivate *priv = self->priv; GHashTable *states = g_hash_table_new (g_direct_hash, g_direct_equal); if (priv->peer != 0) { g_hash_table_insert (states, GUINT_TO_POINTER (priv->peer), GUINT_TO_POINTER (priv->call_state)); } tp_svc_channel_interface_call_state_return_from_get_call_states (context, states); g_hash_table_unref (states); } void gabble_media_channel_call_state_iface_init (gpointer g_iface, gpointer iface_data G_GNUC_UNUSED) { TpSvcChannelInterfaceCallStateClass *klass = g_iface; #define IMPLEMENT(x) tp_svc_channel_interface_call_state_implement_##x (\ klass, gabble_media_channel_##x) IMPLEMENT(get_call_states); #undef IMPLEMENT } /* Called by construct_stream to allow the Hold code to hook itself up to a new * stream. */ void gabble_media_channel_hold_new_stream (GabbleMediaChannel *chan, GabbleMediaStream *stream, WockyJingleMediaRtp *content) { GObject *chan_o = (GObject *) chan; gabble_signal_connect_weak (stream, "unhold-failed", (GCallback) stream_unhold_failed, chan_o); gabble_signal_connect_weak (stream, "notify::local-hold", (GCallback) stream_hold_state_changed, chan_o); /* A stream being added might cause the "total" hold state to change */ stream_hold_state_changed (stream, NULL, chan); } /* Called by _latch_to_session to allow the CallState code to hook itself up to * a new session. */ void gabble_media_channel_hold_latch_to_session (GabbleMediaChannel *chan) { g_assert (chan->priv->session != NULL); /* Watch the active/ringing/held state of the session so we can keep the call * state up to date. */ gabble_signal_connect_weak (chan->priv->session, "remote-state-changed", (GCallback) remote_state_changed_cb, (GObject *) chan); } telepathy-gabble-0.18.3/src/legacy-caps.c0000664000175000017500000000251612332441362021325 0ustar00cassidycassidy00000000000000/* * legacy-caps.c - Connection.Interface.Capabilities constants and utilities * Copyright (C) 2005 Collabora Ltd. * Copyright (C) 2005 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "legacy-caps.h" #include #define DEBUG_FLAG GABBLE_DEBUG_PRESENCE #include "debug.h" #ifdef ENABLE_VOIP #include "media-factory.h" #endif const CapabilityConversionData capabilities_conversions[] = { #ifdef ENABLE_VOIP { TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA, _gabble_media_factory_typeflags_to_caps, _gabble_media_factory_caps_to_typeflags }, #endif { NULL, NULL, NULL} }; telepathy-gabble-0.18.3/src/media-stream.h0000664000175000017500000001000112332441362021476 0ustar00cassidycassidy00000000000000/* * gabble-media-stream.h - Header for GabbleMediaStream * Copyright (C) 2006 Collabora Ltd. * Copyright (C) 2006 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_MEDIA_STREAM_H__ #define __GABBLE_MEDIA_STREAM_H__ #include #include #include G_BEGIN_DECLS typedef enum { STREAM_SIG_STATE_NEW, STREAM_SIG_STATE_SENT, STREAM_SIG_STATE_ACKNOWLEDGED, STREAM_SIG_STATE_REMOVING } StreamSignallingState; typedef guint32 CombinedStreamDirection; typedef struct _GabbleMediaStream GabbleMediaStream; typedef struct _GabbleMediaStreamClass GabbleMediaStreamClass; typedef struct _GabbleMediaStreamPrivate GabbleMediaStreamPrivate; struct _GabbleMediaStreamClass { GObjectClass parent_class; TpDBusPropertiesMixinClass props_class; }; struct _GabbleMediaStream { GObject parent; gchar *name; TpMediaStreamState connection_state; CombinedStreamDirection combined_direction; gboolean playing; GabbleMediaStreamPrivate *priv; }; GType gabble_media_stream_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_MEDIA_STREAM \ (gabble_media_stream_get_type ()) #define GABBLE_MEDIA_STREAM(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_MEDIA_STREAM, \ GabbleMediaStream)) #define GABBLE_MEDIA_STREAM_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_MEDIA_STREAM, \ GabbleMediaStreamClass)) #define GABBLE_IS_MEDIA_STREAM(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_MEDIA_STREAM)) #define GABBLE_IS_MEDIA_STREAM_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_MEDIA_STREAM)) #define GABBLE_MEDIA_STREAM_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_MEDIA_STREAM, \ GabbleMediaStreamClass)) #define COMBINED_DIRECTION_GET_DIRECTION(d) \ ((TpMediaStreamDirection) ((d) & TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL)) #define COMBINED_DIRECTION_GET_PENDING_SEND(d) \ ((TpMediaStreamPendingSend) ((d) >> 2)) #define MAKE_COMBINED_DIRECTION(d, p) \ ((CombinedStreamDirection) ((d) | ((p) << 2))) gboolean gabble_media_stream_error (GabbleMediaStream *self, guint errnum, const gchar *message, GError **error); void gabble_media_stream_close (GabbleMediaStream *close); void gabble_media_stream_hold (GabbleMediaStream *stream, gboolean hold); gboolean gabble_media_stream_change_direction (GabbleMediaStream *stream, guint requested_dir, GError **error); void gabble_media_stream_accept_pending_local_send (GabbleMediaStream *stream); GabbleMediaStream *gabble_media_stream_new ( TpDBusDaemon *dbus_daemon, const gchar *object_path, WockyJingleContent *content, const gchar *name, guint id, const gchar *nat_traversal, const GPtrArray *relay_info, gboolean local_hold); TpMediaStreamType gabble_media_stream_get_media_type (GabbleMediaStream *self); void gabble_media_stream_add_dtmf_player (GabbleMediaStream *self, TpDTMFPlayer *dtmf_player); WockyJingleMediaRtp *gabble_media_stream_get_content (GabbleMediaStream *self); void gabble_media_stream_start_telephony_event (GabbleMediaStream *self, guchar event); void gabble_media_stream_stop_telephony_event (GabbleMediaStream *self); G_END_DECLS #endif /* #ifndef __GABBLE_MEDIA_STREAM_H__*/ telepathy-gabble-0.18.3/src/addressing-util.c0000664000175000017500000003176112332440117022234 0ustar00cassidycassidy00000000000000/* * addressing-util.c - Source for Gabble addressing utility functions * Copyright (C) 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "addressing-util.h" #include #include #include #include #include "connection.h" #include "util.h" static const gchar *addressable_vcard_fields[] = {"x-jabber", "x-facebook-id", NULL}; static const gchar *addressable_uri_schemes[] = {"xmpp", NULL}; const gchar * const * gabble_get_addressable_uri_schemes () { return addressable_uri_schemes; } const gchar * const * gabble_get_addressable_vcard_fields () { return addressable_vcard_fields; } gchar * gabble_normalize_contact_uri (const gchar *uri, GError **error) { gchar *scheme = NULL; gchar *normalized_jid = NULL; gchar *normalized_uri = NULL; g_return_val_if_fail (uri != NULL, NULL); normalized_jid = gabble_uri_to_jid (uri, error); if (normalized_jid == NULL) { goto OUT; } scheme = g_uri_parse_scheme (uri); normalized_uri = gabble_jid_to_uri (scheme, normalized_jid, error); OUT: g_free (scheme); g_free (normalized_jid); return normalized_uri; } gchar * gabble_uri_to_jid (const gchar *uri, GError **error) { gchar *scheme; gchar *normalized_jid = NULL; g_return_val_if_fail (uri != NULL, NULL); scheme = g_uri_parse_scheme (uri); if (scheme == NULL) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "'%s' is not a valid URI", uri); goto OUT; } else if (g_ascii_strcasecmp (scheme, "xmpp") == 0) { gchar *node = NULL; gchar *domain = NULL; gchar *resource = NULL; if (!gabble_parse_xmpp_uri (uri, &node, &domain, &resource, error)) goto OUT; normalized_jid = gabble_encode_jid (node, domain, resource); g_free (node); g_free (domain); g_free (resource); } else { g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "'%s' URI scheme is not supported by this protocol", scheme); goto OUT; } OUT: g_free (scheme); return normalized_jid; } gchar * gabble_jid_to_uri (const gchar *scheme, const gchar *jid, GError **error) { gchar *normalized_uri = NULL; gchar *node = NULL; gchar *domain = NULL; gchar *resource = NULL; gchar *escaped_node = NULL; gchar *escaped_domain = NULL; gchar *escaped_resource = NULL; gchar *escaped_jid = NULL; gchar *normalized_scheme = NULL; g_return_val_if_fail (scheme != NULL, NULL); if (!wocky_decode_jid (jid, &node, &domain, &resource)) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "'%s' is not a valid JID", jid); return NULL; } /* convert from "foo?" to "foo%3F" */ if (node) escaped_node = g_uri_escape_string (node, NULL, TRUE); g_assert (domain != NULL); escaped_domain = g_uri_escape_string (domain, NULL, TRUE); if (resource) escaped_resource = g_uri_escape_string (resource, NULL, TRUE); escaped_jid = gabble_encode_jid (escaped_node, escaped_domain, escaped_resource); normalized_scheme = g_ascii_strdown (scheme, -1); normalized_uri = g_strdup_printf ("%s:%s", normalized_scheme, escaped_jid); g_free (node); g_free (domain); g_free (resource); g_free (escaped_node); g_free (escaped_domain); g_free (escaped_resource); g_free (escaped_jid); g_free (normalized_scheme); return normalized_uri; } TpHandle gabble_ensure_handle_from_uri (TpHandleRepoIface *repo, const gchar *uri, GError **error) { TpHandle handle; gchar *jid = gabble_uri_to_jid (uri, error); if (jid == NULL) return 0; handle = tp_handle_ensure (repo, jid, NULL, error); g_free (jid); return handle; } gchar * gabble_normalize_vcard_address (const gchar *vcard_field, const gchar *vcard_address, GError **error) { gchar *normalized_jid = NULL; gchar *normalized_address = NULL; g_return_val_if_fail (vcard_field != NULL, NULL); g_return_val_if_fail (vcard_address != NULL, NULL); normalized_jid = gabble_vcard_address_to_jid (vcard_field, vcard_address, error); if (normalized_jid == NULL) { goto OUT; } normalized_address = gabble_jid_to_vcard_address (vcard_field, normalized_jid, error); OUT: g_free (normalized_jid); return normalized_address; } gchar * gabble_vcard_address_to_jid (const gchar *vcard_field, const gchar *vcard_address, GError **error) { gchar *normalized_jid = NULL; g_return_val_if_fail (vcard_field != NULL, NULL); g_return_val_if_fail (vcard_address != NULL, NULL); if (g_ascii_strcasecmp (vcard_field, "x-jabber") == 0) { GError *gabble_error = NULL; normalized_jid = gabble_normalize_contact (NULL, vcard_address, GUINT_TO_POINTER (GABBLE_JID_GLOBAL), &gabble_error); if (gabble_error != NULL) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "'%s' is an invalid address: %s", vcard_address, gabble_error->message); g_error_free (gabble_error); } } else if (g_ascii_strcasecmp (vcard_field, "x-facebook-id") == 0) { const gchar *s; s = vcard_address; while (*s && (g_ascii_isdigit (*s))) s++; if (G_UNLIKELY (*s != '\0')) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "'%s' is an invalid facebook chat address", vcard_address); goto OUT; } normalized_jid = g_strdup_printf ("-%s@chat.facebook.com", vcard_address); } else { g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "'%s' vCard field is not supported by this protocol", vcard_field); } OUT: return normalized_jid; } gchar * gabble_jid_to_vcard_address (const gchar *vcard_field, const gchar *jid, GError **error) { gchar *normalized_address = NULL; g_return_val_if_fail (vcard_field != NULL, NULL); g_return_val_if_fail (jid != NULL, NULL); if (g_ascii_strcasecmp (vcard_field, "x-jabber") == 0) { GError *gabble_error = NULL; normalized_address = gabble_normalize_contact (NULL, jid, GUINT_TO_POINTER (GABBLE_JID_GLOBAL), &gabble_error); if (gabble_error != NULL) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "'%s' is an invalid address: %s", jid, gabble_error->message); g_error_free (gabble_error); } } else if (g_ascii_strcasecmp (vcard_field, "x-facebook-id") == 0) { gchar *address = g_ascii_strdown (jid, -1); if (address[0] == '-' && g_str_has_suffix (address, "@chat.facebook.com")) { const gchar *at = strchr (address, '@'); const gchar *start_of_number = address + 1; const gchar *s; g_assert (at != NULL); normalized_address = g_strndup (start_of_number, (int) (at - start_of_number)); s = normalized_address; while (*s && (g_ascii_isdigit (*s))) s++; if (G_UNLIKELY (*s != '\0')) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "'%s' is an invalid facebook chat address", jid); } } else { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "'%s' is an invalid facebook chat address", jid); } g_free (address); } else { g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "'%s' vCard field is not supported by this protocol", vcard_field); } return normalized_address; } TpHandle gabble_ensure_handle_from_vcard_address (TpHandleRepoIface *repo, const gchar *vcard_field, const gchar *vcard_address, GError **error) { gchar *normalized_jid; TpHandle handle; normalized_jid = gabble_vcard_address_to_jid (vcard_field, vcard_address, error); if (normalized_jid == NULL) return 0; handle = tp_handle_ensure (repo, normalized_jid, NULL, error); g_free (normalized_jid); return handle; } gchar ** gabble_uris_for_handle (TpHandleRepoIface *contact_repo, TpHandle contact) { GPtrArray *uris = g_ptr_array_new (); for (const gchar * const *scheme = addressable_uri_schemes; *scheme != NULL; scheme++) { gchar *uri = gabble_uri_for_handle (contact_repo, *scheme, contact); if (uri != NULL) { g_ptr_array_add (uris, uri); } } g_ptr_array_add (uris, NULL); return (gchar **) g_ptr_array_free (uris, FALSE); } GHashTable * gabble_vcard_addresses_for_handle (TpHandleRepoIface *contact_repo, TpHandle contact) { GHashTable *addresses = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_free); for (const gchar * const *field = addressable_vcard_fields; *field != NULL; field++) { gchar *vcard_address = gabble_vcard_address_for_handle (contact_repo, *field, contact); if (vcard_address != NULL) { g_hash_table_insert (addresses, (gpointer) *field, vcard_address); } } return addresses; } gchar * gabble_vcard_address_for_handle (TpHandleRepoIface *contact_repo, const gchar *vcard_field, TpHandle contact) { const gchar *identifier = tp_handle_inspect (contact_repo, contact); return gabble_jid_to_vcard_address (vcard_field, identifier, NULL); } gchar * gabble_uri_for_handle (TpHandleRepoIface *contact_repo, const gchar *scheme, TpHandle contact) { const gchar *identifier = tp_handle_inspect (contact_repo, contact); return gabble_jid_to_uri (scheme, identifier, NULL); } gboolean gabble_parse_xmpp_uri (const gchar *uri, gchar **node, gchar **domain, gchar **resource, GError **error) { gboolean ret = FALSE; gchar *scheme; const gchar *jid; gchar *tmp_node = NULL; gchar *tmp_domain = NULL; gchar *tmp_resource = NULL; gchar *unescaped_node = NULL; gchar *unescaped_domain = NULL; gchar *unescaped_resource = NULL; gchar *unescaped_jid = NULL; gchar *normalized_jid = NULL; GError *gabble_error = NULL; g_return_val_if_fail (uri != NULL, FALSE); g_return_val_if_fail (domain != NULL, FALSE); scheme = g_uri_parse_scheme (uri); if (scheme == NULL) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "'%s' is not a valid URI", uri); goto OUT; } jid = uri + strlen (scheme) + 1; /* Strip the scheme */ if (!wocky_decode_jid (jid, &tmp_node, &tmp_domain, &tmp_resource)) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "'%s' is not a valid XMPP URI", uri); goto OUT; } /* convert from "foo%3F" to "foo?" */ if (tmp_node) { unescaped_node = g_uri_unescape_string (tmp_node, NULL); if (unescaped_node == NULL) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "'%s' is not a valid XMPP URI", uri); goto OUT; } } g_assert (tmp_domain); unescaped_domain = g_uri_unescape_string (tmp_domain, NULL); if (unescaped_domain == NULL) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "'%s' is not a valid XMPP URI", uri); goto OUT; } if (tmp_resource) { unescaped_resource = g_uri_unescape_string (tmp_resource, NULL); if (unescaped_resource == NULL) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "'%s' is not a valid XMPP URI", uri); goto OUT; } } unescaped_jid = gabble_encode_jid (unescaped_node, unescaped_domain, unescaped_resource); normalized_jid = gabble_normalize_contact (NULL, unescaped_jid, GUINT_TO_POINTER (GABBLE_JID_GLOBAL), &gabble_error); if (gabble_error != NULL) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "'%s' is not a valid XMPP URI: %s", uri, gabble_error->message); g_error_free (gabble_error); goto OUT; } if (!wocky_decode_jid (normalized_jid, node, domain, resource)) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "'%s' is not a valid XMPP URI", uri); goto OUT; } ret = TRUE; OUT: g_free (scheme); g_free (tmp_node); g_free (tmp_domain); g_free (tmp_resource); g_free (unescaped_node); g_free (unescaped_domain); g_free (unescaped_resource); g_free (unescaped_jid); g_free (normalized_jid); return ret; } telepathy-gabble-0.18.3/src/bytestream-iface.h0000664000175000017500000000656111720700311022362 0ustar00cassidycassidy00000000000000/* * bytestream-iface.h - Header for GabbleBytestream interface * Copyright (C) 2007 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_BYTESTREAM_IFACE_H__ #define __GABBLE_BYTESTREAM_IFACE_H__ #include #include G_BEGIN_DECLS typedef enum { /* Received a SI request, response not yet sent */ GABBLE_BYTESTREAM_STATE_LOCAL_PENDING = 0, /* We accepted SI request. * bytestream specific init steps not yet performed */ GABBLE_BYTESTREAM_STATE_ACCEPTED, /* Remote contact accepted the SI request. * bytestream specific initiation started */ GABBLE_BYTESTREAM_STATE_INITIATING, /* Bytestream open */ GABBLE_BYTESTREAM_STATE_OPEN, GABBLE_BYTESTREAM_STATE_CLOSING, GABBLE_BYTESTREAM_STATE_CLOSED, NUM_GABBLE_BYTESTREAM_STATES, } GabbleBytestreamState; typedef void (* GabbleBytestreamAugmentSiAcceptReply) ( WockyNode *si, gpointer user_data); typedef struct _GabbleBytestreamIface GabbleBytestreamIface; typedef struct _GabbleBytestreamIfaceClass GabbleBytestreamIfaceClass; struct _GabbleBytestreamIfaceClass { GTypeInterface parent; gboolean (*initiate) (GabbleBytestreamIface *bytestream); gboolean (*send) (GabbleBytestreamIface *bytestream, guint len, const gchar *data); void (*close) (GabbleBytestreamIface *bytestream, GError *error); void (*accept) (GabbleBytestreamIface *bytestream, GabbleBytestreamAugmentSiAcceptReply func, gpointer user_data); void (*block_reading) (GabbleBytestreamIface *bytestream, gboolean block); }; GType gabble_bytestream_iface_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_BYTESTREAM_IFACE \ (gabble_bytestream_iface_get_type ()) #define GABBLE_BYTESTREAM_IFACE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_BYTESTREAM_IFACE, \ GabbleBytestreamIface)) #define GABBLE_IS_BYTESTREAM_IFACE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_BYTESTREAM_IFACE)) #define GABBLE_BYTESTREAM_IFACE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GABBLE_TYPE_BYTESTREAM_IFACE,\ GabbleBytestreamIfaceClass)) gboolean gabble_bytestream_iface_initiate (GabbleBytestreamIface *bytestream); gboolean gabble_bytestream_iface_send (GabbleBytestreamIface *bytestream, guint len, const gchar *data); void gabble_bytestream_iface_close (GabbleBytestreamIface *bytestream, GError *error); void gabble_bytestream_iface_accept (GabbleBytestreamIface *bytestream, GabbleBytestreamAugmentSiAcceptReply func, gpointer user_data); void gabble_bytestream_iface_block_reading (GabbleBytestreamIface *bytestream, gboolean block); G_END_DECLS #endif /* #ifndef __GABBLE_BYTESTREAM_IFACE_H__ */ telepathy-gabble-0.18.3/src/caps-hash.h0000664000175000017500000000206311720700311020776 0ustar00cassidycassidy00000000000000/* * caps-hash.h - Headers for computing verification string hash (XEP-0115 v1.5) * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __CAPS_HASH_H__ #define __CAPS_HASH_H__ #include "connection.h" #include "gabble/caps-hash.h" gchar *caps_hash_compute_from_self_presence ( GabbleConnection *self); #endif /* __CAPS_HASH_H__ */ telepathy-gabble-0.18.3/src/util.c0000664000175000017500000010240112332440117020101 0ustar00cassidycassidy00000000000000/* * util.c - Source for Gabble utility functions * Copyright (C) 2006-2007 Collabora Ltd. * Copyright (C) 2006-2007 Nokia Corporation * @author Robert McQueen * @author Simon McVittie * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "util.h" #include #include #include #include #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_JID #include "conn-aliasing.h" #include "connection.h" #include "debug.h" #include "namespaces.h" #include "presence-cache.h" gchar * sha1_hex (const gchar *bytes, guint len) { gchar *hex = g_compute_checksum_for_string (G_CHECKSUM_SHA1, bytes, len); guint i; for (i = 0; i < SHA1_HASH_SIZE * 2; i++) { g_assert (hex[i] != '\0'); hex[i] = g_ascii_tolower (hex[i]); } g_assert (hex[SHA1_HASH_SIZE * 2] == '\0'); return hex; } void sha1_bin (const gchar *bytes, guint len, guchar out[SHA1_HASH_SIZE]) { GChecksum *checksum = g_checksum_new (G_CHECKSUM_SHA1); gsize out_len = SHA1_HASH_SIZE; g_assert (g_checksum_type_get_length (G_CHECKSUM_SHA1) == SHA1_HASH_SIZE); g_checksum_update (checksum, (const guchar *) bytes, len); g_checksum_get_digest (checksum, out, &out_len); g_assert (out_len == SHA1_HASH_SIZE); g_checksum_free (checksum); } /** gabble_generate_id: * * RFC4122 version 4 compliant random UUIDs generator. * * Returns: A string with RFC41122 version 4 random UUID, must be freed with * g_free(). */ gchar * gabble_generate_id (void) { GRand *grand; gchar *str; struct { guint32 time_low; guint16 time_mid; guint16 time_hi_and_version; guint8 clock_seq_hi_and_rsv; guint8 clock_seq_low; guint16 node_hi; guint32 node_low; } uuid; /* Fill with random. Every new GRand are seede with 128 bit read from * /dev/urandom (or the current time on non-unix systems). This makes the * random source good enough for our usage, but may not be suitable for all * situation outside Gabble. */ grand = g_rand_new (); uuid.time_low = g_rand_int (grand); uuid.time_mid = (guint16) g_rand_int_range (grand, 0, G_MAXUINT16); uuid.time_hi_and_version = (guint16) g_rand_int_range (grand, 0, G_MAXUINT16); uuid.clock_seq_hi_and_rsv = (guint8) g_rand_int_range (grand, 0, G_MAXUINT8); uuid.clock_seq_low = (guint8) g_rand_int_range (grand, 0, G_MAXUINT8); uuid.node_hi = (guint16) g_rand_int_range (grand, 0, G_MAXUINT16); uuid.node_low = g_rand_int (grand); g_rand_free (grand); /* Set the two most significant bits (bits 6 and 7) of the * clock_seq_hi_and_rsv to zero and one, respectively. */ uuid.clock_seq_hi_and_rsv = (uuid.clock_seq_hi_and_rsv & 0x3F) | 0x80; /* Set the four most significant bits (bits 12 through 15) of the * time_hi_and_version field to 4 */ uuid.time_hi_and_version = (uuid.time_hi_and_version & 0x0fff) | 0x4000; str = g_strdup_printf ("%08x-%04x-%04x-%02x%02x-%04x%08x", uuid.time_low, uuid.time_mid, uuid.time_hi_and_version, uuid.clock_seq_hi_and_rsv, uuid.clock_seq_low, uuid.node_hi, uuid.node_low); return str; } void lm_message_node_add_own_nick (WockyNode *node, GabbleConnection *connection) { gchar *nick; GabbleConnectionAliasSource source; TpBaseConnection *base = (TpBaseConnection *) connection; source = _gabble_connection_get_cached_alias (connection, tp_base_connection_get_self_handle (base), &nick); if (source > GABBLE_CONNECTION_ALIAS_FROM_JID) wocky_node_add_child_with_content_ns_q (node, "nick", nick, g_quark_from_static_string (NS_NICK)); g_free (nick); } /** * gabble_get_room_handle_from_jid: * @room_repo: The %TP_HANDLE_TYPE_ROOM handle repository * @jid: A JID * * Given a JID seen in the from="" attribute on a stanza, work out whether * it's something to do with a MUC, and if so, return its handle. * * Returns: The handle of the MUC, if the JID refers to either a MUC * we're in, or a contact's channel-specific JID inside a MUC. * Returns 0 if the JID is either invalid, or nothing to do with a * known MUC (typically this will mean it's the global JID of a contact). */ TpHandle gabble_get_room_handle_from_jid (TpHandleRepoIface *room_repo, const gchar *jid) { TpHandle handle; gchar *room; room = gabble_remove_resource (jid); if (room == NULL) return 0; handle = tp_handle_lookup (room_repo, room, NULL, NULL); g_free (room); return handle; } #define INVALID_HANDLE(e, f, ...) \ G_STMT_START { \ DEBUG (f, ##__VA_ARGS__); \ g_set_error (e, TP_ERROR, TP_ERROR_INVALID_HANDLE, f, ##__VA_ARGS__);\ } G_STMT_END gchar * gabble_normalize_room (TpHandleRepoIface *repo, const gchar *jid, gpointer context, GError **error) { GabbleConnection *conn; gchar *qualified_name, *resource; /* Only look up the canonical room name if we got a GabbleConnection. * This should only happen in the test-handles test. */ if (context != NULL) { conn = GABBLE_CONNECTION (context); qualified_name = gabble_connection_get_canonical_room_name (conn, jid); if (qualified_name == NULL) { INVALID_HANDLE (error, "requested room handle %s does not specify a server, but we " "have not discovered any local conference servers and no " "fallback was provided", jid); return NULL; } } else { qualified_name = g_strdup (jid); } if (!wocky_decode_jid (qualified_name, NULL, NULL, &resource)) { INVALID_HANDLE (error, "room JID %s is invalid", qualified_name); return NULL; } if (resource != NULL) { INVALID_HANDLE (error, "invalid room JID %s: contains nickname part after '/' too", qualified_name); g_free (qualified_name); g_free (resource); return NULL; } return qualified_name; } gchar * gabble_remove_resource (const gchar *jid) { char *slash = strchr (jid, '/'); gchar *buf; if (slash == NULL) return g_strdup (jid); /* The user and domain parts can't contain '/', assuming it's valid */ buf = g_malloc (slash - jid + 1); strncpy (buf, jid, slash - jid); buf[slash - jid] = '\0'; return buf; } gchar * gabble_encode_jid ( const gchar *node, const gchar *domain, const gchar *resource) { gchar *tmp, *ret; g_return_val_if_fail (domain != NULL, NULL); if (node != NULL && resource != NULL) tmp = g_strdup_printf ("%s@%s/%s", node, domain, resource); else if (node != NULL) tmp = g_strdup_printf ("%s@%s", node, domain); else if (resource != NULL) tmp = g_strdup_printf ("%s/%s", domain, resource); else tmp = g_strdup (domain); ret = g_utf8_normalize (tmp, -1, G_NORMALIZE_NFKC); g_free (tmp); return ret; } /* * gabble_normalize_contact * @repo: The %TP_HANDLE_TYPE_ROOM handle repository or NULL * @jid: A JID * @context: One of %GabbleNormalizeContactJIDMode casted into gpointer * @error: pointer in which to return a GError in case of failure. * * Normalize contact JID. If @repo is provided and the context is not * clear (we don't know for sure whether it's global or room JID), it's * used to try and detect room JIDs. * * Returns: Normalized JID. */ gchar * gabble_normalize_contact (TpHandleRepoIface *repo, const gchar *jid, gpointer context, GError **error) { guint mode = GPOINTER_TO_UINT (context); gchar *username = NULL, *server = NULL, *resource = NULL; gchar *ret = NULL; if (!wocky_decode_jid (jid, &username, &server, &resource) || !username) { INVALID_HANDLE (error, "JID %s is invalid or has no node part", jid); goto OUT; } if (mode == GABBLE_JID_ROOM_MEMBER && resource == NULL) { INVALID_HANDLE (error, "JID %s can't be a room member - it has no resource", jid); goto OUT; } if (mode != GABBLE_JID_GLOBAL && resource != NULL) { ret = gabble_encode_jid (username, server, resource); if (mode == GABBLE_JID_ROOM_MEMBER || (repo != NULL && tp_dynamic_handle_repo_lookup_exact (repo, ret))) { /* either we know from context that it's a room member, or we * already saw that contact in a room. Use ret as our answer */ goto OUT; } else { g_free (ret); } } /* if we get here, we suspect it's a global JID, either because the context * says it is, or because the context isn't sure and we haven't seen it in * use as a room member */ ret = gabble_encode_jid (username, server, NULL); OUT: g_free (username); g_free (server); g_free (resource); return ret; } /** * lm_message_node_extract_properties * * Map a XML node to a properties hash table * (used to parse a subset of the OLPC and tubes protocol) * * Example: * * * prop1_value * 7 * * * lm_message_node_extract_properties (node, "prop"); * * --> { "prop1" : "prop1_value", "prop2" : 7 } * * Returns a hash table mapping names to GValue of the specified type. * Valid types are: str, int, uint, bytes. * */ GHashTable * lm_message_node_extract_properties (WockyNode *node, const gchar *prop) { GHashTable *properties; WockyNodeIter i; WockyNode *child; properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) tp_g_value_slice_free); if (node == NULL) return properties; wocky_node_iter_init (&i, node, prop, NULL); while (wocky_node_iter_next (&i, &child)) { const gchar *name = wocky_node_get_attribute (child, "name"); const gchar *type = wocky_node_get_attribute (child, "type"); const gchar *value = child->content; GValue *gvalue; if (name == NULL || type == NULL || value == NULL) continue; if (0 == strcmp (type, "bytes")) { GArray *arr; guchar *st; gsize outlen; st = g_base64_decode (value, &outlen); if (!st) continue; arr = g_array_new (FALSE, FALSE, sizeof (guchar)); g_array_append_vals (arr, st, outlen); gvalue = g_slice_new0 (GValue); g_value_init (gvalue, DBUS_TYPE_G_UCHAR_ARRAY); g_value_take_boxed (gvalue, arr); g_hash_table_insert (properties, g_strdup (name), gvalue); g_free (st); } else if (0 == strcmp (type, "str")) { gvalue = g_slice_new0 (GValue); g_value_init (gvalue, G_TYPE_STRING); g_value_set_string (gvalue, value); g_hash_table_insert (properties, g_strdup (name), gvalue); } else if (0 == strcmp (type, "int")) { gvalue = g_slice_new0 (GValue); g_value_init (gvalue, G_TYPE_INT); g_value_set_int (gvalue, strtol (value, NULL, 10)); g_hash_table_insert (properties, g_strdup (name), gvalue); } else if (0 == strcmp (type, "uint")) { gvalue = g_slice_new0 (GValue); g_value_init (gvalue, G_TYPE_UINT); g_value_set_uint (gvalue, strtoul (value, NULL, 10)); g_hash_table_insert (properties, g_strdup (name), gvalue); } else if (0 == strcmp (type, "bool")) { gboolean val; if (!tp_strdiff (value, "0") || !tp_strdiff (value, "false")) { val = FALSE; } else if (!tp_strdiff (value, "1") || !tp_strdiff (value, "true")) { val = TRUE; } else { DEBUG ("invalid boolean value: %s", value); continue; } gvalue = g_slice_new0 (GValue); g_value_init (gvalue, G_TYPE_BOOLEAN); g_value_set_boolean (gvalue, val); g_hash_table_insert (properties, g_strdup (name), gvalue); } } return properties; } struct _set_child_from_property_data { WockyNode *node; const gchar *prop; }; static void set_child_from_property (gpointer key, gpointer value, gpointer user_data) { GValue *gvalue = value; struct _set_child_from_property_data *data = (struct _set_child_from_property_data *) user_data; WockyNode *child; const char *type = NULL; if (G_VALUE_TYPE (gvalue) == G_TYPE_STRING) { type = "str"; } else if (G_VALUE_TYPE (gvalue) == DBUS_TYPE_G_UCHAR_ARRAY) { type = "bytes"; } else if (G_VALUE_TYPE (gvalue) == G_TYPE_INT) { type = "int"; } else if (G_VALUE_TYPE (gvalue) == G_TYPE_UINT) { type = "uint"; } else if (G_VALUE_TYPE (gvalue) == G_TYPE_BOOLEAN) { type = "bool"; } else { /* a type we don't know how to handle: ignore it */ DEBUG ("property with unknown type \"%s\"", g_type_name (G_VALUE_TYPE (gvalue))); return; } child = wocky_node_add_child (data->node, data->prop); if (G_VALUE_TYPE (gvalue) == G_TYPE_STRING) { wocky_node_set_content (child, g_value_get_string (gvalue)); } else if (G_VALUE_TYPE (gvalue) == DBUS_TYPE_G_UCHAR_ARRAY) { GArray *arr; gchar *str; type = "bytes"; arr = g_value_get_boxed (gvalue); str = g_base64_encode ((guchar *) arr->data, arr->len); wocky_node_set_content (child, str); g_free (str); } else if (G_VALUE_TYPE (gvalue) == G_TYPE_INT) { gchar *str; str = g_strdup_printf ("%d", g_value_get_int (gvalue)); wocky_node_set_content (child, str); g_free (str); } else if (G_VALUE_TYPE (gvalue) == G_TYPE_UINT) { gchar *str; str = g_strdup_printf ("%u", g_value_get_uint (gvalue)); wocky_node_set_content (child, str); g_free (str); } else if (G_VALUE_TYPE (gvalue) == G_TYPE_BOOLEAN) { /* we output as "0" or "1" despite the canonical representation for * xs:boolean being "false" or "true", for compatibility with older * Gabble versions (OLPC Trial-3) */ wocky_node_set_content (child, g_value_get_boolean (gvalue) ? "1" : "0"); } else { g_assert_not_reached (); } wocky_node_set_attribute (child, "name", key); wocky_node_set_attribute (child, "type", type); } /** * * lm_message_node_set_children_from_properties * * Map a properties hash table to a XML node. * * Example: * * properties = { "prop1" : "prop1_value", "prop2" : 7 } * * lm_message_node_add_children_from_properties (node, properties, "prop"); * * --> * prop1_value * 7 * * */ void lm_message_node_add_children_from_properties (WockyNode *node, GHashTable *properties, const gchar *prop) { struct _set_child_from_property_data data; data.node = node; data.prop = prop; g_hash_table_foreach (properties, set_child_from_property, &data); } typedef struct { GObject *instance; GObject *user_data; gulong handler_id; } WeakHandlerCtx; static WeakHandlerCtx * whc_new (GObject *instance, GObject *user_data) { WeakHandlerCtx *ctx = g_slice_new0 (WeakHandlerCtx); ctx->instance = instance; ctx->user_data = user_data; return ctx; } static void whc_free (WeakHandlerCtx *ctx) { g_slice_free (WeakHandlerCtx, ctx); } static void user_data_destroyed_cb (gpointer, GObject *); static void instance_destroyed_cb (gpointer ctx_, GObject *where_the_instance_was) { WeakHandlerCtx *ctx = ctx_; DEBUG ("instance for %p destroyed; cleaning up", ctx); /* No need to disconnect the signal here, the instance has gone away. */ g_object_weak_unref (ctx->user_data, user_data_destroyed_cb, ctx); whc_free (ctx); } static void user_data_destroyed_cb (gpointer ctx_, GObject *where_the_user_data_was) { WeakHandlerCtx *ctx = ctx_; DEBUG ("user_data for %p destroyed; disconnecting", ctx); g_signal_handler_disconnect (ctx->instance, ctx->handler_id); g_object_weak_unref (ctx->instance, instance_destroyed_cb, ctx); whc_free (ctx); } /** * gabble_signal_connect_weak: * @instance: the instance to connect to. * @detailed_signal: a string of the form "signal-name::detail". * @c_handler: the GCallback to connect. * @user_data: an object to pass as data to c_handler calls. * * Connects a #GCallback function to a signal for a particular object, as if * with g_signal_connect(). Additionally, arranges for the signal handler to be * disconnected if @user_data is destroyed. * * This is intended to be a convenient way for objects to use themselves as * user_data for callbacks without having to explicitly disconnect all the * handlers in their finalizers. */ void gabble_signal_connect_weak (gpointer instance, const gchar *detailed_signal, GCallback c_handler, GObject *user_data) { GObject *instance_obj = G_OBJECT (instance); WeakHandlerCtx *ctx = whc_new (instance_obj, user_data); DEBUG ("connecting to %p:%s with context %p", instance, detailed_signal, ctx); ctx->handler_id = g_signal_connect (instance, detailed_signal, c_handler, user_data); g_object_weak_ref (instance_obj, instance_destroyed_cb, ctx); g_object_weak_ref (user_data, user_data_destroyed_cb, ctx); } typedef struct { GSourceFunc function; GObject *object; guint source_id; } WeakIdleCtx; static void idle_weak_ref_notify (gpointer data, GObject *dead_object) { g_source_remove (GPOINTER_TO_UINT (data)); } static void idle_removed (gpointer data) { WeakIdleCtx *ctx = (WeakIdleCtx *) data; g_slice_free (WeakIdleCtx, ctx); } static gboolean idle_callback (gpointer data) { WeakIdleCtx *ctx = (WeakIdleCtx *) data; if (ctx->function ((gpointer) ctx->object)) { return TRUE; } else { g_object_weak_unref ( ctx->object, idle_weak_ref_notify, GUINT_TO_POINTER (ctx->source_id)); return FALSE; } } /* Like g_idle_add(), but cancel the callback if the provided object is * finalized. */ guint gabble_idle_add_weak (GSourceFunc function, GObject *object) { WeakIdleCtx *ctx; ctx = g_slice_new0 (WeakIdleCtx); ctx->function = function; ctx->object = object; ctx->source_id = g_idle_add_full ( G_PRIORITY_DEFAULT_IDLE, idle_callback, ctx, idle_removed); g_object_weak_ref ( object, idle_weak_ref_notify, GUINT_TO_POINTER (ctx->source_id)); return ctx->source_id; } GPtrArray * gabble_g_ptr_array_copy (GPtrArray *source) { GPtrArray *ret = g_ptr_array_sized_new (source->len); guint i; for (i = 0; i < source->len; i++) g_ptr_array_add (ret, g_ptr_array_index (source, i)); return ret; } WockyBareContact * ensure_bare_contact_from_jid (GabbleConnection *conn, const gchar *jid) { WockyContactFactory *contact_factory; contact_factory = wocky_session_get_contact_factory (conn->session); return wocky_contact_factory_ensure_bare_contact (contact_factory, jid); } TpHandle ensure_handle_from_contact ( GabbleConnection *conn, WockyContact *contact) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); gchar *jid = wocky_contact_dup_jid (contact); GError *error = NULL; TpHandle handle = tp_handle_ensure (contact_repo, jid, NULL, &error); if (handle == 0) { g_critical ("Contact %p has JID '%s' which is not valid: %s", contact, jid, error->message); g_clear_error (&error); } g_free (jid); return handle; } #ifdef ENABLE_VOIP #define TWICE(x) x, x static gboolean jingle_pick_resource_or_bare_jid (GabblePresence *presence, GabbleCapabilitySet *caps, const gchar **resource) { const gchar *ret; if (gabble_presence_has_resources (presence)) { ret = gabble_presence_pick_resource_by_caps (presence, GABBLE_CLIENT_TYPE_PHONE, gabble_capability_set_predicate_at_least, caps); if (resource != NULL) *resource = ret; return (ret != NULL); } else if (gabble_capability_set_at_least ( gabble_presence_peek_caps (presence), caps)) { if (resource != NULL) *resource = NULL; return TRUE; } else { return FALSE; } } gboolean jingle_pick_best_resource (GabbleConnection *conn, TpHandle peer, gboolean want_audio, gboolean want_video, const char **transport_ns, WockyJingleDialect *dialect, const gchar **resource_out) { /* We prefer gtalk-p2p to ice, because it can use tcp and https relays (if * available). */ static const GabbleFeatureFallback transports[] = { { TRUE, TWICE (NS_GOOGLE_TRANSPORT_P2P) }, { TRUE, TWICE (NS_JINGLE_TRANSPORT_ICEUDP) }, { TRUE, TWICE (NS_JINGLE_TRANSPORT_RAWUDP) }, { FALSE, NULL, NULL } }; GabblePresence *presence; GabbleCapabilitySet *caps; const gchar *resource = NULL; gboolean success = FALSE; presence = gabble_presence_cache_get (conn->presence_cache, peer); if (presence == NULL) { DEBUG ("contact %d has no presence available", peer); return FALSE; } *dialect = WOCKY_JINGLE_DIALECT_ERROR; *transport_ns = NULL; g_return_val_if_fail (want_audio || want_video, FALSE); /* from here on, goto FINALLY to free this, instead of returning early */ caps = gabble_capability_set_new (); /* Try newest Jingle standard */ gabble_capability_set_add (caps, NS_JINGLE_RTP); if (want_audio) gabble_capability_set_add (caps, NS_JINGLE_RTP_AUDIO); if (want_video) gabble_capability_set_add (caps, NS_JINGLE_RTP_VIDEO); if (jingle_pick_resource_or_bare_jid (presence, caps, &resource)) { *dialect = WOCKY_JINGLE_DIALECT_V032; goto CHOOSE_TRANSPORT; } /* Else try older Jingle draft */ gabble_capability_set_clear (caps); if (want_audio) gabble_capability_set_add (caps, NS_JINGLE_DESCRIPTION_AUDIO); if (want_video) gabble_capability_set_add (caps, NS_JINGLE_DESCRIPTION_VIDEO); if (jingle_pick_resource_or_bare_jid (presence, caps, &resource)) { *dialect = WOCKY_JINGLE_DIALECT_V015; goto CHOOSE_TRANSPORT; } /* The Google dialects can't do video alone. */ if (!want_audio) { DEBUG ("No resource which supports video alone available"); goto FINALLY; } /* Okay, let's try GTalk 0.3, possibly with video. */ gabble_capability_set_clear (caps); gabble_capability_set_add (caps, NS_GOOGLE_FEAT_VOICE); if (want_video) gabble_capability_set_add (caps, NS_GOOGLE_FEAT_VIDEO); if (jingle_pick_resource_or_bare_jid (presence, caps, &resource)) { *dialect = WOCKY_JINGLE_DIALECT_GTALK3; goto CHOOSE_TRANSPORT; } if (want_video) { DEBUG ("No resource which supports audio+video available"); goto FINALLY; } /* Maybe GTalk 0.4 will save us all... ? */ gabble_capability_set_clear (caps); gabble_capability_set_add (caps, NS_GOOGLE_FEAT_VOICE); gabble_capability_set_add (caps, NS_GOOGLE_TRANSPORT_P2P); if (jingle_pick_resource_or_bare_jid (presence, caps, &resource)) { *dialect = WOCKY_JINGLE_DIALECT_GTALK4; goto CHOOSE_TRANSPORT; } /* Nope, nothing we can do. */ goto FINALLY; CHOOSE_TRANSPORT: if (resource_out != NULL) *resource_out = resource; success = TRUE; if (*dialect == WOCKY_JINGLE_DIALECT_GTALK4 || *dialect == WOCKY_JINGLE_DIALECT_GTALK3) { /* the GTalk dialects only support google p2p as transport protocol. */ *transport_ns = NS_GOOGLE_TRANSPORT_P2P; } else if (resource == NULL) { *transport_ns = gabble_presence_pick_best_feature (presence, transports, gabble_capability_set_predicate_has); } else { *transport_ns = gabble_presence_resource_pick_best_feature (presence, resource, transports, gabble_capability_set_predicate_has); } if (*transport_ns == NULL) success = FALSE; FINALLY: gabble_capability_set_free (caps); return success; } const gchar * jingle_pick_best_content_type (GabbleConnection *conn, TpHandle peer, const gchar *resource, WockyJingleMediaType type) { GabblePresence *presence; const GabbleFeatureFallback content_types[] = { /* if $thing is supported, then use it */ { TRUE, TWICE (NS_JINGLE_RTP) }, { type == WOCKY_JINGLE_MEDIA_TYPE_VIDEO, TWICE (NS_JINGLE_DESCRIPTION_VIDEO) }, { type == WOCKY_JINGLE_MEDIA_TYPE_AUDIO, TWICE (NS_JINGLE_DESCRIPTION_AUDIO) }, /* odd Google ones: if $thing is supported, use $other_thing */ { type == WOCKY_JINGLE_MEDIA_TYPE_AUDIO, NS_GOOGLE_FEAT_VOICE, NS_GOOGLE_SESSION_PHONE }, { type == WOCKY_JINGLE_MEDIA_TYPE_VIDEO, NS_GOOGLE_FEAT_VIDEO, NS_GOOGLE_SESSION_VIDEO }, { FALSE, NULL, NULL } }; presence = gabble_presence_cache_get (conn->presence_cache, peer); if (presence == NULL) { DEBUG ("contact %d has no presence available", peer); return NULL; } if (resource == NULL) { return gabble_presence_pick_best_feature (presence, content_types, gabble_capability_set_predicate_has); } else { return gabble_presence_resource_pick_best_feature (presence, resource, content_types, gabble_capability_set_predicate_has); } } static TpCallStreamCandidateType tp_candidate_type_from_jingle (WockyJingleCandidateType type) { switch (type) { default: /* Consider UNKNOWN as LOCAL/HOST */ case WOCKY_JINGLE_CANDIDATE_TYPE_LOCAL: return TP_CALL_STREAM_CANDIDATE_TYPE_HOST; case WOCKY_JINGLE_CANDIDATE_TYPE_STUN: return TP_CALL_STREAM_CANDIDATE_TYPE_SERVER_REFLEXIVE; case WOCKY_JINGLE_CANDIDATE_TYPE_RELAY: return TP_CALL_STREAM_CANDIDATE_TYPE_RELAY; } } /** * @candidates: (element-type WockyJingleCandidate): candidates * * Returns: (transfer full): a GABBLE_ARRAY_TYPE_CANDIDATE_LIST, i.e. * a(usqa{sv}) */ GPtrArray * gabble_call_candidates_to_array (GList *candidates) { GPtrArray *arr; GList *c; arr = g_ptr_array_sized_new (g_list_length (candidates)); for (c = candidates; c != NULL; c = g_list_next (c)) { WockyJingleCandidate *cand = (WockyJingleCandidate *) c->data; GValueArray *a; GHashTable *info; info = tp_asv_new ( "protocol", G_TYPE_UINT, cand->protocol, "type", G_TYPE_UINT, tp_candidate_type_from_jingle (cand->type), "foundation", G_TYPE_STRING, cand->id, "priority", G_TYPE_UINT, cand->preference, "username", G_TYPE_STRING, cand->username, "password", G_TYPE_STRING, cand->password, NULL); a = tp_value_array_build (4, G_TYPE_UINT, cand->component, G_TYPE_STRING, cand->address, G_TYPE_UINT, cand->port, TP_HASH_TYPE_CANDIDATE_INFO, info, G_TYPE_INVALID); g_ptr_array_add (arr, a); } return arr; } #endif gchar * gabble_peer_to_jid (GabbleConnection *conn, TpHandle peer, const gchar *resource) { TpHandleRepoIface *repo = tp_base_connection_get_handles ( TP_BASE_CONNECTION (conn), TP_HANDLE_TYPE_CONTACT); const gchar *target = tp_handle_inspect (repo, peer); if (resource == NULL) return g_strdup (target); return g_strdup_printf ("%s/%s", target, resource); } /* Like wocky_enum_from_nick, but for GFlagsValues instead. */ gboolean gabble_flag_from_nick (GType flag_type, const gchar *nick, guint *value) { GFlagsClass *klass = g_type_class_ref (flag_type); GFlagsValue *flag_value; g_return_val_if_fail (klass != NULL, FALSE); g_return_val_if_fail (value != NULL, FALSE); flag_value = g_flags_get_value_by_nick (klass, nick); g_type_class_unref (klass); if (flag_value != NULL) { *value = flag_value->value; return TRUE; } else { return FALSE; } } /** * gabble_simple_async_succeed_or_fail_in_idle: * @self: the source object for an asynchronous function * @callback: a callback to call when @todo things have been done * @user_data: user data for the callback * @source_tag: the source tag for a #GSimpleAsyncResult * @error: (allow-none): %NULL to indicate success, or an error on failure * * Create a new #GSimpleAsyncResult and schedule it to call its callback * in an idle. If @error is %NULL, report success with * tp_simple_async_report_success_in_idle(); if @error is non-%NULL, * use g_simple_async_report_gerror_in_idle(). */ void gabble_simple_async_succeed_or_fail_in_idle (gpointer self, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, const GError *error) { if (error == NULL) { tp_simple_async_report_success_in_idle (self, callback, user_data, source_tag); } else { /* not const-correct yet: GNOME #622004 */ g_simple_async_report_gerror_in_idle (self, callback, user_data, (GError *) error); } } /** * gabble_simple_async_countdown_new: * @self: the source object for an asynchronous function * @callback: a callback to call when @todo things have been done * @user_data: user data for the callback * @source_tag: the source tag for a #GSimpleAsyncResult * @todo: number of things to do before calling @callback (at least 1) * * Create a new #GSimpleAsyncResult that will call its callback when a number * of asynchronous operations have happened. * * An internal counter is initialized to @todo, incremented with * gabble_simple_async_countdown_inc() or decremented with * gabble_simple_async_countdown_dec(). * * When that counter reaches zero, if an error has been set with * g_simple_async_result_set_from_error() or similar, the operation fails; * otherwise, it succeeds. * * The caller must not use the operation result functions, such as * g_simple_async_result_get_op_res_gssize() - this async result is only * suitable for "void" async methods which return either success or a #GError, * i.e. the same signature as g_async_initable_init_async(). * * Returns: (transfer full): a counter */ GSimpleAsyncResult * gabble_simple_async_countdown_new (gpointer self, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, gssize todo) { GSimpleAsyncResult *simple; g_return_val_if_fail (todo >= 1, NULL); simple = g_simple_async_result_new (self, callback, user_data, source_tag); /* We (ab)use the op_res member as a count of things to do. When * it reaches zero, the operation completes with any error that has been * set, or with success. */ g_simple_async_result_set_op_res_gssize (simple, todo); /* we keep one extra reference as long as the counter is nonzero */ g_object_ref (simple); return simple; } /** * gabble_simple_async_countdown_inc: * @simple: a result created by gabble_simple_async_countdown_new() * * Increment the counter in @simple, indicating that an additional async * operation has been started. An additional call to * gabble_simple_async_countdown_dec() will be needed to make @simple * call its callback. */ void gabble_simple_async_countdown_inc (GSimpleAsyncResult *simple) { gssize todo = g_simple_async_result_get_op_res_gssize (simple); g_return_if_fail (todo >= 1); g_simple_async_result_set_op_res_gssize (simple, todo + 1); } /** * gabble_simple_async_countdown_dec: * @simple: a result created by gabble_simple_async_countdown_new() * * Decrement the counter in @simple. If the number of things to do has * reached zero, schedule @simple to call its callback in an idle, then * unref it. * * When one of the asynchronous operations needed for @simple succeeds, * this should be signalled by a call to this function. * * When one of the asynchronous operations needed for @simple fails, * this should be signalled by a call to g_simple_async_result_set_from_error() * (or one of the similar functions), followed by a call to this function. * If more than one async operation fails in this way, the #GError from the * last failure will be used. */ void gabble_simple_async_countdown_dec (GSimpleAsyncResult *simple) { gssize todo = g_simple_async_result_get_op_res_gssize (simple); g_simple_async_result_set_op_res_gssize (simple, --todo); if (todo <= 0) { g_simple_async_result_complete_in_idle (simple); g_object_unref (simple); } } telepathy-gabble-0.18.3/src/roomlist-channel.h0000664000175000017500000000473512223562023022422 0ustar00cassidycassidy00000000000000/* * gabble-roomlist-channel.h - Header for GabbleRoomlistChannel * Copyright (C) 2005 Collabora Ltd. * Copyright (C) 2005 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_ROOMLIST_CHANNEL_H__ #define __GABBLE_ROOMLIST_CHANNEL_H__ #include #include #include "connection.h" G_BEGIN_DECLS typedef struct _GabbleRoomlistChannel GabbleRoomlistChannel; typedef struct _GabbleRoomlistChannelPrivate GabbleRoomlistChannelPrivate; typedef struct _GabbleRoomlistChannelClass GabbleRoomlistChannelClass; struct _GabbleRoomlistChannelClass { TpBaseChannelClass parent_class; }; struct _GabbleRoomlistChannel { TpBaseChannel parent; GabbleRoomlistChannelPrivate *priv; }; GType gabble_roomlist_channel_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_ROOMLIST_CHANNEL \ (gabble_roomlist_channel_get_type ()) #define GABBLE_ROOMLIST_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_ROOMLIST_CHANNEL,\ GabbleRoomlistChannel)) #define GABBLE_ROOMLIST_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_ROOMLIST_CHANNEL,\ GabbleRoomlistChannelClass)) #define GABBLE_IS_ROOMLIST_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_ROOMLIST_CHANNEL)) #define GABBLE_IS_ROOMLIST_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_ROOMLIST_CHANNEL)) #define GABBLE_ROOMLIST_CHANNEL_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_ROOMLIST_CHANNEL,\ GabbleRoomlistChannelClass)) GabbleRoomlistChannel *_gabble_roomlist_channel_new (GabbleConnection *conn, const gchar *conference_server); G_END_DECLS #endif /* #ifndef __GABBLE_ROOMLIST_CHANNEL_H__*/ telepathy-gabble-0.18.3/src/conn-power-saving.h0000644000175000017500000000217611570651566022532 0ustar00cassidycassidy00000000000000/* * conn-power-saving.h - Header for Gabble connection code handling power saving * Copyright (C) 2010 Collabora Ltd. * Copyright (C) 2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GABBLE_CONN_SLACKER_H #define GABBLE_CONN_SLACKER_H #include #include "connection.h" G_BEGIN_DECLS void conn_power_saving_iface_init (gpointer g_iface, gpointer iface_data); G_END_DECLS #endif /* GABBLE_CONN_SLACKER_H */ telepathy-gabble-0.18.3/src/private-tubes-factory.c0000664000175000017500000012600212332441362023371 0ustar00cassidycassidy00000000000000/* * private-tubes-factory.c - Source for GabblePrivateTubesFactory * Copyright (C) 2006 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "private-tubes-factory.h" #include #include #include #include #include #include #include "extensions/extensions.h" #define DEBUG_FLAG GABBLE_DEBUG_TUBES #include "bytestream-factory.h" #include "gabble/caps-channel-manager.h" #include "connection.h" #include "debug.h" #include "muc-channel.h" #include "muc-factory.h" #include "namespaces.h" #include "presence-cache.h" #include "tube-dbus.h" #include "tube-stream.h" #include "util.h" static GabbleTubeIface * new_channel_from_stanza (GabblePrivateTubesFactory *self, WockyStanza *stanza, WockyNode *tube_node, guint64 tube_id, GabbleBytestreamIface *bytestream); static gboolean private_tubes_factory_tube_close_cb ( WockyPorter *porter, WockyStanza *msg, gpointer user_data); static gboolean private_tubes_factory_msg_tube_cb ( WockyPorter *porter, WockyStanza *msg, gpointer user_data); static void channel_manager_iface_init (gpointer, gpointer); static void caps_channel_manager_iface_init (gpointer, gpointer); G_DEFINE_TYPE_WITH_CODE (GabblePrivateTubesFactory, gabble_private_tubes_factory, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER, channel_manager_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_CAPS_CHANNEL_MANAGER, caps_channel_manager_iface_init)); /* properties */ enum { PROP_CONNECTION = 1, LAST_PROPERTY }; struct _GabblePrivateTubesFactoryPrivate { GabbleConnection *conn; gulong status_changed_id; guint msg_tube_cb; guint msg_close_cb; /* guint tube ID => (owned) (GabbleTubeIface *) */ GHashTable *tubes; gboolean dispose_has_run; }; #define GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE(obj) ((obj)->priv) static const gchar * const tubes_channel_fixed_properties[] = { TP_PROP_CHANNEL_CHANNEL_TYPE, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL }; static const gchar * const old_tubes_channel_allowed_properties[] = { TP_PROP_CHANNEL_TARGET_HANDLE, TP_PROP_CHANNEL_TARGET_ID, NULL }; gboolean gabble_private_tubes_factory_extract_tube_information ( TpHandleRepoIface *contact_repo, WockyNode *tube_node, TpTubeType *type, TpHandle *initiator_handle, const gchar **service, GHashTable **parameters, guint64 *tube_id) { if (type != NULL) { const gchar *_type; _type = wocky_node_get_attribute (tube_node, "type"); if (!tp_strdiff (_type, "stream")) { *type = TP_TUBE_TYPE_STREAM; } else if (!tp_strdiff (_type, "dbus")) { *type = TP_TUBE_TYPE_DBUS; } else { DEBUG ("Unknown tube type: %s", _type); return FALSE; } } if (initiator_handle != NULL) { const gchar *initiator; initiator = wocky_node_get_attribute (tube_node, "initiator"); if (initiator != NULL) { *initiator_handle = tp_handle_ensure (contact_repo, initiator, GUINT_TO_POINTER (GABBLE_JID_ROOM_MEMBER), NULL); if (*initiator_handle == 0) { DEBUG ("invalid initiator JID %s", initiator); return FALSE; } } else { *initiator_handle = 0; } } if (service != NULL) { *service = wocky_node_get_attribute (tube_node, "service"); } if (parameters != NULL) { WockyNode *node; node = wocky_node_get_child (tube_node, "parameters"); *parameters = lm_message_node_extract_properties (node, "parameter"); } if (tube_id != NULL) { const gchar *str; guint64 tmp; str = wocky_node_get_attribute (tube_node, "id"); if (str == NULL) { DEBUG ("no tube id in SI request"); return FALSE; } tmp = g_ascii_strtoull (str, NULL, 10); if (tmp == 0 || tmp > G_MAXUINT32) { DEBUG ("tube id is non-numeric or out of range: %s", str); return FALSE; } *tube_id = tmp; } return TRUE; } static void gabble_private_tubes_factory_init (GabblePrivateTubesFactory *self) { GabblePrivateTubesFactoryPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_PRIVATE_TUBES_FACTORY, GabblePrivateTubesFactoryPrivate); self->priv = priv; priv->tubes = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_object_unref); priv->conn = NULL; priv->dispose_has_run = FALSE; } static void gabble_private_tubes_factory_close_all ( GabblePrivateTubesFactory *fac); static void porter_available_cb ( GabbleConnection *connection, WockyPorter *porter, gpointer user_data) { GabblePrivateTubesFactory *self = GABBLE_PRIVATE_TUBES_FACTORY (user_data); GabblePrivateTubesFactoryPrivate *priv = self->priv; priv->msg_tube_cb = wocky_porter_register_handler_from_anyone (porter, WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, WOCKY_PORTER_HANDLER_PRIORITY_MAX, private_tubes_factory_msg_tube_cb, self, '(', "tube", ':', NS_TUBES, ')', NULL); priv->msg_close_cb = wocky_porter_register_handler_from_anyone (porter, WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, WOCKY_PORTER_HANDLER_PRIORITY_MAX, private_tubes_factory_tube_close_cb, self, '(', "close", ':', NS_TUBES, ')', NULL); } static void connection_status_changed_cb (GabbleConnection *conn, guint status, guint reason, GabblePrivateTubesFactory *self) { switch (status) { case TP_CONNECTION_STATUS_DISCONNECTED: gabble_private_tubes_factory_close_all (self); break; } } static GObject * gabble_private_tubes_factory_constructor (GType type, guint n_props, GObjectConstructParam *props) { GObject *obj; GabblePrivateTubesFactory *self; GabblePrivateTubesFactoryPrivate *priv; obj = G_OBJECT_CLASS (gabble_private_tubes_factory_parent_class)-> constructor (type, n_props, props); self = GABBLE_PRIVATE_TUBES_FACTORY (obj); priv = GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self); self->priv->status_changed_id = g_signal_connect (self->priv->conn, "status-changed", (GCallback) connection_status_changed_cb, obj); tp_g_signal_connect_object (priv->conn, "porter-available", (GCallback) porter_available_cb, obj, 0); return obj; } static void gabble_private_tubes_factory_dispose (GObject *object) { GabblePrivateTubesFactory *fac = GABBLE_PRIVATE_TUBES_FACTORY (object); GabblePrivateTubesFactoryPrivate *priv = GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (fac); if (priv->dispose_has_run) return; DEBUG ("dispose called"); priv->dispose_has_run = TRUE; gabble_private_tubes_factory_close_all (fac); g_assert (priv->tubes == NULL); if (G_OBJECT_CLASS (gabble_private_tubes_factory_parent_class)->dispose) G_OBJECT_CLASS (gabble_private_tubes_factory_parent_class)->dispose ( object); } static void gabble_private_tubes_factory_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabblePrivateTubesFactory *fac = GABBLE_PRIVATE_TUBES_FACTORY (object); GabblePrivateTubesFactoryPrivate *priv = GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (fac); switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, priv->conn); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_private_tubes_factory_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabblePrivateTubesFactory *fac = GABBLE_PRIVATE_TUBES_FACTORY (object); GabblePrivateTubesFactoryPrivate *priv = GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (fac); switch (property_id) { case PROP_CONNECTION: priv->conn = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_private_tubes_factory_class_init ( GabblePrivateTubesFactoryClass *gabble_private_tubes_factory_class) { GObjectClass *object_class = G_OBJECT_CLASS ( gabble_private_tubes_factory_class); GParamSpec *param_spec; g_type_class_add_private (gabble_private_tubes_factory_class, sizeof (GabblePrivateTubesFactoryPrivate)); object_class->constructor = gabble_private_tubes_factory_constructor; object_class->dispose = gabble_private_tubes_factory_dispose; object_class->get_property = gabble_private_tubes_factory_get_property; object_class->set_property = gabble_private_tubes_factory_set_property; param_spec = g_param_spec_object ( "connection", "GabbleConnection object", "Gabble connection object that owns this Tubes channel manager object.", GABBLE_TYPE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); } static void gabble_private_tubes_factory_close_all (GabblePrivateTubesFactory *fac) { GabblePrivateTubesFactoryPrivate *priv = GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (fac); DEBUG ("closing 1-1 tubes channels"); if (priv->status_changed_id != 0) { g_signal_handler_disconnect (priv->conn, priv->status_changed_id); priv->status_changed_id = 0; } if (priv->msg_tube_cb != 0) { WockyPorter *porter = wocky_session_get_porter (priv->conn->session); wocky_porter_unregister_handler (porter, priv->msg_tube_cb); priv->msg_tube_cb = 0; wocky_porter_unregister_handler (porter, priv->msg_close_cb); priv->msg_close_cb = 0; } tp_clear_pointer (&priv->tubes, g_hash_table_unref); } static void add_service_to_array (const gchar *service, GPtrArray *arr, TpTubeType type, TpHandle handle) { GValue monster = {0, }; GHashTable *fixed_properties; GValue *channel_type_value; GValue *target_handle_type_value; gchar *tube_allowed_properties[] = { TP_PROP_CHANNEL_TARGET_HANDLE, TP_PROP_CHANNEL_TARGET_ID, NULL }; g_assert (type == TP_TUBE_TYPE_STREAM || type == TP_TUBE_TYPE_DBUS); g_value_init (&monster, TP_STRUCT_TYPE_REQUESTABLE_CHANNEL_CLASS); g_value_take_boxed (&monster, dbus_g_type_specialized_construct ( TP_STRUCT_TYPE_REQUESTABLE_CHANNEL_CLASS)); fixed_properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free); channel_type_value = tp_g_value_slice_new (G_TYPE_STRING); if (type == TP_TUBE_TYPE_STREAM) g_value_set_static_string (channel_type_value, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE); else g_value_set_static_string (channel_type_value, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE); g_hash_table_insert (fixed_properties, TP_PROP_CHANNEL_CHANNEL_TYPE, channel_type_value); target_handle_type_value = tp_g_value_slice_new (G_TYPE_UINT); g_value_set_uint (target_handle_type_value, TP_HANDLE_TYPE_CONTACT); g_hash_table_insert (fixed_properties, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, target_handle_type_value); target_handle_type_value = tp_g_value_slice_new (G_TYPE_STRING); g_value_set_string (target_handle_type_value, service); if (type == TP_TUBE_TYPE_STREAM) g_hash_table_insert (fixed_properties, TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE, target_handle_type_value); else g_hash_table_insert (fixed_properties, TP_PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME, target_handle_type_value); dbus_g_type_struct_set (&monster, 0, fixed_properties, 1, tube_allowed_properties, G_MAXUINT); g_hash_table_unref (fixed_properties); g_ptr_array_add (arr, g_value_get_boxed (&monster)); } static void add_generic_tube_caps (GPtrArray *arr) { GValue monster1 = {0,}, monster2 = {0,}; GHashTable *fixed_properties; GValue *channel_type_value; GValue *target_handle_type_value; /* StreamTube */ g_value_init (&monster1, TP_STRUCT_TYPE_REQUESTABLE_CHANNEL_CLASS); g_value_take_boxed (&monster1, dbus_g_type_specialized_construct ( TP_STRUCT_TYPE_REQUESTABLE_CHANNEL_CLASS)); fixed_properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free); channel_type_value = tp_g_value_slice_new (G_TYPE_STRING); g_value_set_static_string (channel_type_value, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE); g_hash_table_insert (fixed_properties, TP_PROP_CHANNEL_CHANNEL_TYPE, channel_type_value); target_handle_type_value = tp_g_value_slice_new (G_TYPE_UINT); g_value_set_uint (target_handle_type_value, TP_HANDLE_TYPE_CONTACT); g_hash_table_insert (fixed_properties, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, target_handle_type_value); dbus_g_type_struct_set (&monster1, 0, fixed_properties, 1, gabble_tube_stream_channel_get_allowed_properties (), G_MAXUINT); g_hash_table_unref (fixed_properties); g_ptr_array_add (arr, g_value_get_boxed (&monster1)); /* DBusTube */ g_value_init (&monster2, TP_STRUCT_TYPE_REQUESTABLE_CHANNEL_CLASS); g_value_take_boxed (&monster2, dbus_g_type_specialized_construct ( TP_STRUCT_TYPE_REQUESTABLE_CHANNEL_CLASS)); fixed_properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free); channel_type_value = tp_g_value_slice_new (G_TYPE_STRING); g_value_set_static_string (channel_type_value, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE); g_hash_table_insert (fixed_properties, TP_PROP_CHANNEL_CHANNEL_TYPE, channel_type_value); target_handle_type_value = tp_g_value_slice_new (G_TYPE_UINT); g_value_set_uint (target_handle_type_value, TP_HANDLE_TYPE_CONTACT); g_hash_table_insert (fixed_properties, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, target_handle_type_value); dbus_g_type_struct_set (&monster2, 0, fixed_properties, 1, gabble_tube_dbus_channel_get_allowed_properties (), G_MAXUINT); g_hash_table_unref (fixed_properties); g_ptr_array_add (arr, g_value_get_boxed (&monster2)); } #define STREAM_CAP_PREFIX (NS_TUBES "/stream#") #define DBUS_CAP_PREFIX (NS_TUBES "/dbus#") typedef struct { gboolean supports_tubes; GPtrArray *arr; TpHandle handle; } GetContactCapsClosure; static void get_contact_caps_foreach (gpointer data, gpointer user_data) { const gchar *ns = data; GetContactCapsClosure *closure = user_data; if (!g_str_has_prefix (ns, NS_TUBES)) return; closure->supports_tubes = TRUE; if (g_str_has_prefix (ns, STREAM_CAP_PREFIX)) add_service_to_array (ns + strlen (STREAM_CAP_PREFIX), closure->arr, TP_TUBE_TYPE_STREAM, closure->handle); else if (g_str_has_prefix (ns, DBUS_CAP_PREFIX)) add_service_to_array (ns + strlen (DBUS_CAP_PREFIX), closure->arr, TP_TUBE_TYPE_DBUS, closure->handle); } static void gabble_private_tubes_factory_get_contact_caps ( GabbleCapsChannelManager *manager, TpHandle handle, const GabbleCapabilitySet *caps, GPtrArray *arr) { GabblePrivateTubesFactory *self = GABBLE_PRIVATE_TUBES_FACTORY (manager); GetContactCapsClosure closure = { FALSE, arr, handle }; TpBaseConnection *base_conn = TP_BASE_CONNECTION (self->priv->conn); /* Always claim that we support tubes. */ closure.supports_tubes = (handle == tp_base_connection_get_self_handle (base_conn)); gabble_capability_set_foreach (caps, get_contact_caps_foreach, &closure); if (closure.supports_tubes) add_generic_tube_caps (arr); } static void gabble_private_tubes_factory_add_cap (GabbleCapsChannelManager *manager, const gchar *client_name, GHashTable *cap, GabbleCapabilitySet *cap_set) { const gchar *channel_type, *service; gchar *ns = NULL; /* capabilities mean being able to RECEIVE said kinds of tubes. hence, * skip Requested=true (locally initiated) channel classes */ if (tp_asv_get_boolean (cap, TP_PROP_CHANNEL_REQUESTED, FALSE)) return; channel_type = tp_asv_get_string (cap, TP_PROP_CHANNEL_CHANNEL_TYPE); /* this channel is not for this factory */ if (tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TUBES) && tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE) && tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE)) return; if (tp_asv_get_uint32 (cap, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL) != TP_HANDLE_TYPE_CONTACT) return; if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE)) { service = tp_asv_get_string (cap, TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE); if (service != NULL) ns = g_strconcat (STREAM_CAP_PREFIX, service, NULL); } else if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE)) { service = tp_asv_get_string (cap, TP_PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME); if (service != NULL) ns = g_strconcat (DBUS_CAP_PREFIX, service, NULL); } if (ns != NULL) { DEBUG ("%s: adding capability %s", client_name, ns); gabble_capability_set_add (cap_set, ns); g_free (ns); } } static void gabble_private_tubes_factory_represent_client ( GabbleCapsChannelManager *manager, const gchar *client_name, const GPtrArray *filters, const gchar * const *cap_tokens, GabbleCapabilitySet *cap_set, GPtrArray *data_forms) { guint i; for (i = 0; i < filters->len; i++) { gabble_private_tubes_factory_add_cap (manager, client_name, g_ptr_array_index (filters, i), cap_set); } } struct _ForeachData { TpExportableChannelFunc foreach; gpointer user_data; }; static void _foreach_slave (gpointer key, gpointer value, gpointer user_data) { struct _ForeachData *data = user_data; TpExportableChannel *chan = TP_EXPORTABLE_CHANNEL (value); data->foreach (chan, data->user_data); } static void gabble_private_tubes_factory_foreach_channel (TpChannelManager *manager, TpExportableChannelFunc foreach, gpointer user_data) { GabblePrivateTubesFactory *fac = GABBLE_PRIVATE_TUBES_FACTORY (manager); GabblePrivateTubesFactoryPrivate *priv = GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (fac); struct _ForeachData data; data.user_data = user_data; data.foreach = foreach; g_hash_table_foreach (priv->tubes, _foreach_slave, &data); } void gabble_private_tubes_factory_handle_si_tube_request ( GabblePrivateTubesFactory *self, GabbleBytestreamIface *bytestream, TpHandle handle, const gchar *stream_id, WockyStanza *msg) { GabblePrivateTubesFactoryPrivate *priv = self->priv; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); WockyNode *si_node, *tube_node; WockyStanzaType stanza_type; WockyStanzaSubType sub_type; guint64 tube_id; GabbleTubeIface *tube; DEBUG ("contact#%u stream %s", handle, stream_id); g_return_if_fail (tp_handle_is_valid (contact_repo, handle, NULL)); wocky_stanza_get_type_info (msg, &stanza_type, &sub_type); g_return_if_fail (stanza_type == WOCKY_STANZA_TYPE_IQ); g_return_if_fail (sub_type == WOCKY_STANZA_SUB_TYPE_SET); si_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "si", NS_SI); g_return_if_fail (si_node != NULL); tube_node = wocky_node_get_child_ns (si_node, "tube", NS_TUBES); g_return_if_fail (tube_node != NULL); if (!gabble_private_tubes_factory_extract_tube_information ( contact_repo, tube_node, NULL, NULL, NULL, NULL, &tube_id)) { GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, " has no id attribute" }; NODE_DEBUG (tube_node, e.message); gabble_bytestream_iface_close (bytestream, &e); return; } tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id)); if (tube != NULL) { GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, "tube ID already in use" }; NODE_DEBUG (tube_node, e.message); gabble_bytestream_iface_close (bytestream, &e); return; } /* New tube */ tube = new_channel_from_stanza (self, msg, tube_node, tube_id, bytestream); } void gabble_private_tubes_factory_handle_si_stream_request ( GabblePrivateTubesFactory *self, GabbleBytestreamIface *bytestream, TpHandle handle, const gchar *stream_id, WockyStanza *msg) { GabblePrivateTubesFactoryPrivate *priv = GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); const gchar *tmp; guint64 tube_id; WockyNode *si_node, *stream_node; GabbleTubeIface *tube; WockyStanzaType stanza_type; WockyStanzaSubType sub_type; DEBUG ("contact#%u stream %s", handle, stream_id); g_return_if_fail (tp_handle_is_valid (contact_repo, handle, NULL)); wocky_stanza_get_type_info (msg, &stanza_type, &sub_type); g_return_if_fail (stanza_type == WOCKY_STANZA_TYPE_IQ); g_return_if_fail (sub_type == WOCKY_STANZA_SUB_TYPE_SET); si_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "si", NS_SI); g_return_if_fail (si_node != NULL); stream_node = wocky_node_get_child_ns (si_node, "stream", NS_TUBES); g_return_if_fail (stream_node != NULL); tmp = wocky_node_get_attribute (stream_node, "tube"); if (tmp == NULL) { GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, " has no tube attribute" }; NODE_DEBUG (stream_node, e.message); gabble_bytestream_iface_close (bytestream, &e); return; } tube_id = g_ascii_strtoull (tmp, NULL, 10); if (tube_id == 0 || tube_id > G_MAXUINT32) { GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, " tube ID attribute non-numeric or out of range" }; DEBUG ("tube id is non-numeric or out of range: %s", tmp); gabble_bytestream_iface_close (bytestream, &e); return; } tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id)); if (tube == NULL) { GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, " tube attribute points to a nonexistent " "tube" }; DEBUG ("tube %" G_GUINT64_FORMAT " doesn't exist", tube_id); gabble_bytestream_iface_close (bytestream, &e); return; } DEBUG ("received new bytestream request for existing tube: %" G_GUINT64_FORMAT, tube_id); gabble_tube_iface_add_bytestream (tube, bytestream); } static gboolean tube_msg_checks (GabblePrivateTubesFactory *self, WockyStanza *msg, WockyNode *node, TpHandle *out_handle, guint64 *out_tube_id) { GabblePrivateTubesFactoryPrivate *priv = GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); const gchar *from, *tmp; TpHandle handle; guint64 tube_id; from = wocky_node_get_attribute ( wocky_stanza_get_top_node (msg), "from"); if (from == NULL) { STANZA_DEBUG (msg, "got a message without a from field"); return FALSE; } handle = tp_handle_lookup (contact_repo, from, NULL, NULL); if (handle == 0) { DEBUG ("Invalid from field"); return FALSE; } tmp = wocky_node_get_attribute (node, "id"); if (tmp == NULL) { DEBUG ("failed to get the tube ID"); return FALSE; } tube_id = g_ascii_strtoull (tmp, NULL, 10); if (tube_id == 0 || tube_id > G_MAXUINT32) { DEBUG ("tube ID is non-numeric or out of range: %s", tmp); return FALSE; } if (out_tube_id != NULL) *out_tube_id = tube_id; if (out_handle != NULL) *out_handle = handle; return TRUE; } static gboolean private_tubes_factory_msg_tube_cb ( WockyPorter *porter, WockyStanza *msg, gpointer user_data) { GabblePrivateTubesFactory *self = GABBLE_PRIVATE_TUBES_FACTORY (user_data); GabblePrivateTubesFactoryPrivate *priv = GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self); WockyNode *node; guint64 tube_id; GabbleTubeIface *channel; TpHandle handle; node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "tube", NS_TUBES); g_return_val_if_fail (node != NULL, FALSE); if (!tube_msg_checks (self, msg, node, &handle, &tube_id)) return FALSE; channel = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id)); if (channel != NULL) { TpHandle tube_handle = 0; g_object_get (channel, "handle", &tube_handle, NULL); DEBUG ("tube ID already in use; do not open the offered tube and close " "the existing tube if it's to the same contact"); /* only close the existing channel if it's the same contact * otherwise contacts could force close unrelated tubes. */ if (handle == tube_handle) gabble_tube_iface_close (channel, FALSE); return TRUE; } channel = new_channel_from_stanza (self, msg, node, tube_id, NULL); return TRUE; } static gboolean private_tubes_factory_tube_close_cb ( WockyPorter *porter, WockyStanza *msg, gpointer user_data) { GabblePrivateTubesFactory *self = GABBLE_PRIVATE_TUBES_FACTORY (user_data); GabblePrivateTubesFactoryPrivate *priv = GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self); WockyNode *node; guint64 tube_id; GabbleTubeIface *channel; TpTubeType type; node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "close", NS_TUBES); g_return_val_if_fail (node != NULL, FALSE); if (!tube_msg_checks (self, msg, node, NULL, &tube_id)) return FALSE; channel = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id)); if (channel == NULL) { DEBUG (" tube attribute points to a nonexistent tube"); return TRUE; } g_object_get (channel, "type", &type, NULL); if (type != TP_TUBE_TYPE_STREAM) { DEBUG ("Only stream tubes can be closed using a close message"); return TRUE; } DEBUG ("tube %" G_GUINT64_FORMAT " was closed by remote peer", tube_id); gabble_tube_iface_close (channel, TRUE); return TRUE; } static GabbleTubeIface * gabble_private_tubes_factory_lookup (GabblePrivateTubesFactory *self, const gchar *type, TpHandle handle, const gchar *service) { GabblePrivateTubesFactoryPrivate *priv = GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self); GHashTableIter iter; gpointer value; g_hash_table_iter_init (&iter, priv->tubes); while (g_hash_table_iter_next (&iter, NULL, &value)) { GabbleTubeIface *tube = value; gboolean match = FALSE; gchar *channel_type, *channel_service; TpHandle channel_handle; g_object_get (tube, "channel-type", &channel_type, "handle", &channel_handle, "service", &channel_service, NULL); if (!tp_strdiff (type, channel_type) && handle == channel_handle && !tp_strdiff (service, channel_service)) match = TRUE; g_free (channel_type); g_free (channel_service); if (match) return tube; } return NULL; } static void channel_closed_cb (GabbleTubeIface *tube, GabblePrivateTubesFactory *self) { GabblePrivateTubesFactoryPrivate *priv = GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self); guint64 id; g_object_get (tube, "id", &id, NULL); tp_channel_manager_emit_channel_closed_for_object (self, TP_EXPORTABLE_CHANNEL (tube)); if (priv->tubes != NULL) g_hash_table_remove (priv->tubes, GUINT_TO_POINTER (id)); } static guint64 generate_tube_id (GabblePrivateTubesFactory *self) { GabblePrivateTubesFactoryPrivate *priv = GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self); guint out; /* probably totally overkill */ do { out = g_random_int_range (1, G_MAXINT32); } while (g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (out)) != NULL); return out; } /* Returns: (transfer none): new tube channel. the channel manager holds * the ref to this channel, so don't unref it! */ static GabbleTubeIface * new_channel_from_request (GabblePrivateTubesFactory *self, GHashTable *request) { GabblePrivateTubesFactoryPrivate *priv = GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self); GabbleTubeIface *tube; TpBaseConnection *base_conn = TP_BASE_CONNECTION (priv->conn); gchar *stream_id; TpHandle handle; const gchar *ctype, *service; TpHandleType handle_type; GHashTable *parameters; guint64 tube_id; ctype = tp_asv_get_string (request, TP_PROP_CHANNEL_CHANNEL_TYPE); handle = tp_asv_get_uint32 (request, TP_PROP_CHANNEL_TARGET_HANDLE, NULL); handle_type = tp_asv_get_uint32 (request, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL); tube_id = generate_tube_id (self); /* requested tubes have an empty parameters dict */ parameters = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) tp_g_value_slice_free); if (!tp_strdiff (ctype, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE)) { service = tp_asv_get_string (request, TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE); tube = GABBLE_TUBE_IFACE (gabble_tube_stream_new (priv->conn, handle, handle_type, tp_base_connection_get_self_handle (base_conn), tp_base_connection_get_self_handle (base_conn), service, parameters, tube_id, NULL, TRUE)); } else if (!tp_strdiff (ctype, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE)) { service = tp_asv_get_string (request, TP_PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME); stream_id = gabble_bytestream_factory_generate_stream_id (); tube = GABBLE_TUBE_IFACE (gabble_tube_dbus_new (priv->conn, handle, handle_type, tp_base_connection_get_self_handle (base_conn), tp_base_connection_get_self_handle (base_conn), service, parameters, stream_id, tube_id, NULL, NULL, TRUE)); g_free (stream_id); } else { g_return_val_if_reached (NULL); } tp_base_channel_register ((TpBaseChannel *) tube); g_signal_connect (tube, "closed", G_CALLBACK (channel_closed_cb), self); g_hash_table_insert (priv->tubes, GUINT_TO_POINTER (tube_id), tube); g_hash_table_unref (parameters); return tube; } static void send_tube_close_msg (GabblePrivateTubesFactory *self, const gchar *jid, guint64 tube_id) { GabblePrivateTubesFactoryPrivate *priv = GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self); WockyPorter *porter; WockyStanza *msg; gchar *id_str; id_str = g_strdup_printf ("%" G_GUINT64_FORMAT, tube_id); porter = gabble_connection_dup_porter (priv->conn); /* Send the close message */ msg = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, jid, '(', "close", ':', NS_TUBES, '@', "tube", id_str, ')', GABBLE_AMP_DO_NOT_STORE_SPEC, NULL); g_free (id_str); wocky_porter_send (porter, msg); g_object_unref (porter); g_object_unref (msg); } /* Returns: (transfer none): new tube channel. the channel manager holds * the ref to this channel, so don't unref it! */ static GabbleTubeIface * new_channel_from_stanza (GabblePrivateTubesFactory *self, WockyStanza *stanza, WockyNode *tube_node, guint64 tube_id, GabbleBytestreamIface *bytestream) { GabblePrivateTubesFactoryPrivate *priv = GABBLE_PRIVATE_TUBES_FACTORY_GET_PRIVATE (self); GabbleTubeIface *tube; TpBaseConnection *base_conn = TP_BASE_CONNECTION (priv->conn); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); TpTubeType type; TpHandle handle; const gchar *service; GHashTable *parameters; /* the validity of this has already been checked by wocky */ handle = tp_handle_ensure (contact_repo, wocky_stanza_get_from (stanza), NULL, NULL); g_return_val_if_fail (handle != 0, NULL); if (!gabble_private_tubes_factory_extract_tube_information ( contact_repo, tube_node, &type, NULL, &service, ¶meters, NULL)) { DEBUG ("can't extract information from message"); send_tube_close_msg (self, wocky_stanza_get_from (stanza), tube_id); return NULL; } if (bytestream == NULL && type != TP_TUBE_TYPE_STREAM) { DEBUG ("Only stream tubes are allowed to be created using messages"); send_tube_close_msg (self, wocky_stanza_get_from (stanza), tube_id); return NULL; } else if (bytestream != NULL && type != TP_TUBE_TYPE_DBUS) { GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_FORBIDDEN, "Only D-Bus tubes are allowed to be created using SI" }; DEBUG ("%s", e.message); gabble_bytestream_iface_close (bytestream, &e); return NULL; } if (type == TP_TUBE_TYPE_STREAM) { tube = GABBLE_TUBE_IFACE (gabble_tube_stream_new (priv->conn, handle, TP_HANDLE_TYPE_CONTACT, tp_base_connection_get_self_handle (base_conn), handle, service, parameters, tube_id, NULL, FALSE)); } else { WockyNode *si_node; const gchar *stream_id; si_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (stanza), "si", NS_SI); g_return_val_if_fail (si_node != NULL, NULL); stream_id = wocky_node_get_attribute (si_node, "id"); g_return_val_if_fail (stream_id != NULL, NULL); tube = GABBLE_TUBE_IFACE (gabble_tube_dbus_new (priv->conn, handle, TP_HANDLE_TYPE_CONTACT, tp_base_connection_get_self_handle (base_conn), handle, service, parameters, stream_id, tube_id, bytestream, NULL, FALSE)); } tp_base_channel_register ((TpBaseChannel *) tube); g_signal_connect (tube, "closed", G_CALLBACK (channel_closed_cb), self); g_hash_table_insert (priv->tubes, GUINT_TO_POINTER (tube_id), tube); g_hash_table_unref (parameters); tp_channel_manager_emit_new_channel (self, TP_EXPORTABLE_CHANNEL (tube), NULL); return tube; } GabblePrivateTubesFactory * gabble_private_tubes_factory_new (GabbleConnection *conn) { g_return_val_if_fail (GABBLE_IS_CONNECTION (conn), NULL); return g_object_new ( GABBLE_TYPE_PRIVATE_TUBES_FACTORY, "connection", conn, NULL); } static void gabble_private_tubes_factory_type_foreach_channel_class (GType type, TpChannelManagerTypeChannelClassFunc func, gpointer user_data) { GHashTable *table; GValue *value; /* 1-1 Channel.Type.StreamTube */ table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free); value = tp_g_value_slice_new (G_TYPE_STRING); g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE); g_hash_table_insert (table, TP_PROP_CHANNEL_CHANNEL_TYPE, value); value = tp_g_value_slice_new (G_TYPE_UINT); g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT); g_hash_table_insert (table, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, value); func (type, table, gabble_tube_stream_channel_get_allowed_properties (), user_data); g_hash_table_unref (table); /* 1-1 Channel.Type.DBusTube */ table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free); value = tp_g_value_slice_new (G_TYPE_STRING); g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE); g_hash_table_insert (table, TP_PROP_CHANNEL_CHANNEL_TYPE, value); value = tp_g_value_slice_new (G_TYPE_UINT); g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT); g_hash_table_insert (table, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, value); func (type, table, gabble_tube_dbus_channel_get_allowed_properties (), user_data); g_hash_table_unref (table); } static gboolean gabble_private_tubes_factory_requestotron (GabblePrivateTubesFactory *self, gpointer request_token, GHashTable *request_properties, gboolean require_new) { TpBaseConnection *base_conn = (TpBaseConnection *) self->priv->conn; TpHandle handle; GError *error = NULL; const gchar *channel_type; GabbleTubeIface *channel; const gchar *service = NULL; if (tp_asv_get_uint32 (request_properties, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL) != TP_HANDLE_TYPE_CONTACT) return FALSE; channel_type = tp_asv_get_string (request_properties, TP_PROP_CHANNEL_CHANNEL_TYPE); if (tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE) && tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE)) return FALSE; if (! tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE)) { if (tp_channel_manager_asv_has_unknown_properties (request_properties, tubes_channel_fixed_properties, gabble_tube_stream_channel_get_allowed_properties (), &error)) goto error; /* "Service" is a mandatory, not-fixed property */ service = tp_asv_get_string (request_properties, TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE); if (service == NULL) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "Request does not contain the mandatory property '%s'", TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE); goto error; } } else if (! tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE)) { GError *err = NULL; if (tp_channel_manager_asv_has_unknown_properties (request_properties, tubes_channel_fixed_properties, gabble_tube_dbus_channel_get_allowed_properties (), &error)) goto error; /* "ServiceName" is a mandatory, not-fixed property */ service = tp_asv_get_string (request_properties, TP_PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME); if (service == NULL) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "Request does not contain the mandatory property '%s'", TP_PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME); goto error; } if (!tp_dbus_check_valid_bus_name (service, TP_DBUS_NAME_TYPE_WELL_KNOWN, &err)) { g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Invalid ServiceName: %s", err->message); g_error_free (err); goto error; } } /* validity already checked by TpBaseConnection */ handle = tp_asv_get_uint32 (request_properties, TP_PROP_CHANNEL_TARGET_HANDLE, NULL); g_assert (handle != 0); /* Don't support opening a channel to our self handle */ if (handle == tp_base_connection_get_self_handle (base_conn)) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "Can't open a channel to your self handle"); goto error; } channel = gabble_private_tubes_factory_lookup (self, channel_type, handle, service); if (channel == NULL) { GSList *request_tokens = NULL; channel = new_channel_from_request (self, request_properties); if (request_token != NULL) request_tokens = g_slist_prepend (NULL, request_token); tp_channel_manager_emit_new_channel (self, TP_EXPORTABLE_CHANNEL (channel), request_tokens); g_slist_free (request_tokens); } else { if (require_new) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "A channel to #%u (service: %s) is already open", handle, service); goto error; } tp_channel_manager_emit_request_already_satisfied (self, request_token, TP_EXPORTABLE_CHANNEL (channel)); } return TRUE; error: tp_channel_manager_emit_request_failed (self, request_token, error->domain, error->code, error->message); g_error_free (error); return TRUE; } static gboolean gabble_private_tubes_factory_create_channel (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties) { GabblePrivateTubesFactory *self = GABBLE_PRIVATE_TUBES_FACTORY (manager); return gabble_private_tubes_factory_requestotron (self, request_token, request_properties, TRUE); } static gboolean gabble_private_tubes_factory_request_channel (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties) { GabblePrivateTubesFactory *self = GABBLE_PRIVATE_TUBES_FACTORY (manager); return gabble_private_tubes_factory_requestotron (self, request_token, request_properties, FALSE); } static gboolean gabble_private_tubes_factory_ensure_channel (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties) { GabblePrivateTubesFactory *self = GABBLE_PRIVATE_TUBES_FACTORY (manager); return gabble_private_tubes_factory_requestotron (self, request_token, request_properties, FALSE); } static void channel_manager_iface_init (gpointer g_iface, gpointer iface_data) { TpChannelManagerIface *iface = g_iface; iface->foreach_channel = gabble_private_tubes_factory_foreach_channel; iface->type_foreach_channel_class = gabble_private_tubes_factory_type_foreach_channel_class; iface->create_channel = gabble_private_tubes_factory_create_channel; iface->request_channel = gabble_private_tubes_factory_request_channel; iface->ensure_channel = gabble_private_tubes_factory_ensure_channel; } static void caps_channel_manager_iface_init (gpointer g_iface, gpointer iface_data) { GabbleCapsChannelManagerInterface *iface = g_iface; iface->get_contact_caps = gabble_private_tubes_factory_get_contact_caps; iface->represent_client = gabble_private_tubes_factory_represent_client; } telepathy-gabble-0.18.3/src/caps-hash.c0000664000175000017500000000704412223562023021002 0ustar00cassidycassidy00000000000000/* * caps-hash.c - Computing verification string hash (XEP-0115 v1.5) * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* Computing verification string hash (XEP-0115 v1.5) * * Gabble does not do anything with dataforms (XEP-0128) included in * capabilities. However, it needs to parse them in order to compute the hash * according to XEP-0115. */ #include "config.h" #include "caps-hash.h" #include #include #define DEBUG_FLAG GABBLE_DEBUG_PRESENCE #include "gabble/capabilities.h" #include "debug.h" #include "namespaces.h" #include "presence-cache.h" #include "presence.h" #include "util.h" static void ptr_array_add_str (gpointer str, gpointer array) { g_ptr_array_add (array, str); } /** * Compute our hash as defined by the XEP-0115. * * Returns: the hash. The called must free the returned hash with g_free(). */ gchar * caps_hash_compute_from_self_presence (GabbleConnection *self) { GabblePresence *presence = self->self_presence; const GabbleCapabilitySet *cap_set; GPtrArray *features = g_ptr_array_new (); GPtrArray *identities = wocky_disco_identity_array_new (); GPtrArray *data_forms; gchar *str; /* XEP-0030 requires at least 1 identity. We don't need more. */ g_ptr_array_add (identities, wocky_disco_identity_new ("client", CLIENT_TYPE, NULL, PACKAGE_STRING)); cap_set = gabble_presence_peek_caps (presence); gabble_capability_set_foreach (cap_set, ptr_array_add_str, features); data_forms = gabble_presence_peek_data_forms (presence); str = wocky_caps_hash_compute_from_lists (features, identities, data_forms); g_ptr_array_unref (features); wocky_disco_identity_array_free (identities); return str; } /** * Compute the hash as defined by the XEP-0115 from a received GabbleCapabilitySet * * Returns: the hash. The called must free the returned hash with g_free(). */ gchar * gabble_caps_hash_compute_full (const GabbleCapabilitySet *cap_set, const GPtrArray *identities, GPtrArray *data_forms) { GPtrArray *features = g_ptr_array_new (); GPtrArray *identities_copy = ((identities == NULL) ? wocky_disco_identity_array_new () : wocky_disco_identity_array_copy (identities)); gchar *str; gabble_capability_set_foreach (cap_set, ptr_array_add_str, features); str = wocky_caps_hash_compute_from_lists (features, identities_copy, data_forms); g_ptr_array_unref (features); wocky_disco_identity_array_free (identities_copy); return str; } /** * Compute the hash as defined by the XEP-0115 from a received GabbleCapabilitySet * * Returns: the hash. The called must free the returned hash with g_free(). */ gchar * gabble_caps_hash_compute (const GabbleCapabilitySet *cap_set, const GPtrArray *identities) { return gabble_caps_hash_compute_full (cap_set, identities, NULL); } telepathy-gabble-0.18.3/src/im-factory.h0000664000175000017500000000402512332440117021206 0ustar00cassidycassidy00000000000000/* * im-factory.h - Header for GabbleImFactory * Copyright (C) 2006 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __IM_FACTORY_H__ #define __IM_FACTORY_H__ #include #include "im-channel.h" G_BEGIN_DECLS typedef struct _GabbleImFactory GabbleImFactory; typedef struct _GabbleImFactoryClass GabbleImFactoryClass; typedef struct _GabbleImFactoryPrivate GabbleImFactoryPrivate; struct _GabbleImFactoryClass { GObjectClass parent_class; }; struct _GabbleImFactory { GObject parent; GabbleImFactoryPrivate *priv; }; GType gabble_im_factory_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_IM_FACTORY \ (gabble_im_factory_get_type ()) #define GABBLE_IM_FACTORY(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_IM_FACTORY, GabbleImFactory)) #define GABBLE_IM_FACTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_IM_FACTORY,\ GabbleImFactoryClass)) #define GABBLE_IS_IM_FACTORY(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_IM_FACTORY)) #define GABBLE_IS_IM_FACTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_IM_FACTORY)) #define GABBLE_IM_FACTORY_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_IM_FACTORY,\ GabbleImFactoryClass)) G_END_DECLS #endif /* #ifndef __IM_FACTORY_H__ */ telepathy-gabble-0.18.3/src/plugin-loader.c0000664000175000017500000002423012332441362021674 0ustar00cassidycassidy00000000000000/* * plugin-loader.c — plugin support for telepathy-gabble * Copyright © 2009 Collabora Ltd. * Copyright © 2009 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "plugin-loader.h" #include #ifdef ENABLE_PLUGINS # include #endif #include #define DEBUG_FLAG GABBLE_DEBUG_PLUGINS #include "debug.h" #include "gabble/plugin.h" G_DEFINE_TYPE(GabblePluginLoader, gabble_plugin_loader, G_TYPE_OBJECT) struct _GabblePluginLoaderPrivate { GPtrArray *plugins; }; #ifdef ENABLE_PLUGINS static void plugin_loader_try_to_load ( GabblePluginLoader *self, const gchar *path) { GModule *m = g_module_open (path, G_MODULE_BIND_LOCAL); gpointer func; GabblePluginCreateImpl create; GabblePlugin *plugin; if (m == NULL) { const gchar *e = g_module_error (); /* the errors often seem to be prefixed by the filename */ if (g_str_has_prefix (e, path)) DEBUG ("%s", e); else DEBUG ("%s: %s", path, e); return; } if (!g_module_symbol (m, "gabble_plugin_create", &func)) { DEBUG ("%s", g_module_error ()); g_module_close (m); return; } /* We're about to try to instantiate an object. This installs the * class with the type system, so we should ensure that this * plug-in is never accidentally unloaded. */ g_module_make_resident (m); /* Here goes nothing... */ create = func; plugin = create (); if (plugin == NULL) { g_warning ("gabble_plugin_create () failed for %s", path); } else { gchar *sidecars = g_strjoinv (", ", (gchar **) gabble_plugin_get_sidecar_interfaces (plugin)); const gchar *version = gabble_plugin_get_version (plugin); if (version == NULL) version = "(unspecified)"; DEBUG ("loaded '%s' version %s (%s), implementing these sidecars: %s", gabble_plugin_get_name (plugin), version, path, sidecars); g_free (sidecars); g_ptr_array_add (self->priv->plugins, plugin); } } static void gabble_plugin_loader_probe (GabblePluginLoader *self) { const gchar *directory_names = g_getenv ("GABBLE_PLUGIN_DIR"); gchar **dir_array; gchar **ptr; GDir *d; const gchar *file; if (!g_module_supported ()) { DEBUG ("modules aren't supported on this platform."); return; } if (directory_names == NULL) directory_names = PLUGIN_DIR; #ifdef G_OS_WIN32 dir_array = g_strsplit (directory_names, ";", 0); #else dir_array = g_strsplit (directory_names, ":", 0); #endif for (ptr = dir_array ; *ptr != NULL ; ptr++) { GError *error = NULL; DEBUG ("probing %s", *ptr); d = g_dir_open (*ptr, 0, &error); if (d == NULL) { DEBUG ("%s", error->message); g_clear_error (&error); continue; } while ((file = g_dir_read_name (d)) != NULL) { gchar *path; if (!g_str_has_suffix (file, G_MODULE_SUFFIX)) continue; path = g_build_filename (*ptr, file, NULL); plugin_loader_try_to_load (self, path); g_free (path); } g_dir_close (d); } g_strfreev (dir_array); } #endif static void gabble_plugin_loader_init (GabblePluginLoader *self) { GabblePluginLoaderPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_PLUGIN_LOADER, GabblePluginLoaderPrivate); self->priv = priv; priv->plugins = g_ptr_array_new_with_free_func (g_object_unref); } static GObject * gabble_plugin_loader_constructor ( GType type, guint n_props, GObjectConstructParam *props) { static gpointer singleton = NULL; if (singleton == NULL) { singleton = G_OBJECT_CLASS (gabble_plugin_loader_parent_class)-> constructor (type, n_props, props); g_object_add_weak_pointer (G_OBJECT (singleton), &singleton); return singleton; } else { return g_object_ref (singleton); } } static void gabble_plugin_loader_constructed (GObject *object) { GabblePluginLoader *self = GABBLE_PLUGIN_LOADER (object); void (*chain_up) (GObject *) = G_OBJECT_CLASS (gabble_plugin_loader_parent_class)->constructed; if (chain_up != NULL) chain_up (object); #ifdef ENABLE_PLUGINS gabble_plugin_loader_probe (self); #else DEBUG ("built without plugin support, not actually loading anything"); (void) self; /* silence unused variable warning. */ #endif } static void gabble_plugin_loader_finalize (GObject *object) { GabblePluginLoader *self = GABBLE_PLUGIN_LOADER (object); void (*chain_up) (GObject *) = G_OBJECT_CLASS (gabble_plugin_loader_parent_class)->finalize; tp_clear_pointer (&self->priv->plugins, g_ptr_array_unref); if (chain_up != NULL) chain_up (object); } static void gabble_plugin_loader_class_init (GabblePluginLoaderClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (GabblePluginLoaderPrivate)); object_class->constructor = gabble_plugin_loader_constructor; object_class->constructed = gabble_plugin_loader_constructed; object_class->finalize = gabble_plugin_loader_finalize; } GabblePluginLoader * gabble_plugin_loader_dup () { return g_object_new (GABBLE_TYPE_PLUGIN_LOADER, NULL); } static void create_sidecar_cb ( GObject *plugin_obj, GAsyncResult *nested_result, gpointer user_data) { GSimpleAsyncResult *result = user_data; GabbleSidecar *sidecar; GError *error = NULL; sidecar = gabble_plugin_create_sidecar_finish (GABBLE_PLUGIN (plugin_obj), nested_result, &error); if (sidecar == NULL) { g_simple_async_result_set_from_error (result, error); g_clear_error (&error); } else { g_simple_async_result_set_op_res_gpointer (result, sidecar, g_object_unref); } g_simple_async_result_complete (result); g_object_unref (result); } void gabble_plugin_loader_create_sidecar ( GabblePluginLoader *self, const gchar *sidecar_interface, GabbleConnection *connection, WockySession *session, GAsyncReadyCallback callback, gpointer user_data) { GabblePluginLoaderPrivate *priv = self->priv; guint i; for (i = 0; i < priv->plugins->len; i++) { GabblePlugin *p = g_ptr_array_index (priv->plugins, i); if (gabble_plugin_implements_sidecar (p, sidecar_interface)) { GSimpleAsyncResult *res = g_simple_async_result_new (G_OBJECT (self), callback, user_data, gabble_plugin_loader_create_sidecar); GabblePluginConnection *gabble_conn = GABBLE_PLUGIN_CONNECTION (connection); gabble_plugin_create_sidecar_async (p, sidecar_interface, gabble_conn, session, create_sidecar_cb, res); return; } } g_simple_async_report_error_in_idle (G_OBJECT (self), callback, user_data, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "No plugin implements sidecar '%s'", sidecar_interface); } GabbleSidecar * gabble_plugin_loader_create_sidecar_finish ( GabblePluginLoader *self, GAsyncResult *result, GError **error) { GabbleSidecar *sidecar; if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) return NULL; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), gabble_plugin_loader_create_sidecar), NULL); sidecar = GABBLE_SIDECAR (g_simple_async_result_get_op_res_gpointer ( G_SIMPLE_ASYNC_RESULT (result))); return g_object_ref (sidecar); } TpPresenceStatusSpec * gabble_plugin_loader_append_statuses ( GabblePluginLoader *self, const TpPresenceStatusSpec *base_statuses) { GabblePluginLoaderPrivate *priv = self->priv; GArray *result = g_array_new (TRUE, TRUE, sizeof (TpPresenceStatusSpec)); guint i; for (i = 0; base_statuses[i].name != NULL; i++) g_array_append_val (result, base_statuses[i]); for (i = 0; i < priv->plugins->len; i++) { GabblePlugin *p = g_ptr_array_index (priv->plugins, i); const TpPresenceStatusSpec *statuses = gabble_plugin_get_custom_presence_statuses (p); if (statuses != NULL) { guint j; for (j = 0; statuses[j].name != NULL; j++) g_array_append_val (result, statuses[j]); } } return (TpPresenceStatusSpec *) g_array_free (result, FALSE); } const gchar * gabble_plugin_loader_presence_status_for_privacy_list ( GabblePluginLoader *loader, const gchar *list_name) { GabblePluginLoaderPrivate *priv = loader->priv; guint i; for (i = 0; i < priv->plugins->len; i++) { GabblePlugin *p = g_ptr_array_index (priv->plugins, i); const gchar *status = gabble_plugin_presence_status_for_privacy_list (p, list_name); if (status != NULL) return status; } return NULL; } static void copy_to_other_array (gpointer data, gpointer user_data) { g_ptr_array_add (user_data, data); } GPtrArray * gabble_plugin_loader_create_channel_managers ( GabblePluginLoader *self, GabblePluginConnection *plugin_connection) { GPtrArray *out = g_ptr_array_new (); guint i; for (i = 0; i < self->priv->plugins->len; i++) { GabblePlugin *plugin = g_ptr_array_index (self->priv->plugins, i); GPtrArray *managers; managers = gabble_plugin_create_channel_managers (plugin, plugin_connection); if (managers == NULL) continue; g_ptr_array_foreach (managers, copy_to_other_array, out); g_ptr_array_unref (managers); } return out; } telepathy-gabble-0.18.3/src/call-member-content.c0000664000175000017500000003216512223562023022765 0ustar00cassidycassidy00000000000000/* * call-member-content.c - Source for GabbleCallMemberContent * Copyright (C) 2010 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include "call-member.h" #include "call-member-content.h" #include "util.h" #include "namespaces.h" #define DEBUG_FLAG GABBLE_DEBUG_MEDIA #include "debug.h" G_DEFINE_TYPE(GabbleCallMemberContent, gabble_call_member_content, G_TYPE_OBJECT) /* properties */ enum { PROP_JINGLE_CONTENT = 1, PROP_CONTENT_NAME, PROP_MEDIA_TYPE, PROP_MEMBER }; /* signal enum */ enum { CODECS_CHANGED, GOT_JINGLE_CONTENT, REMOVED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; /* private structure */ struct _GabbleCallMemberContentPrivate { gboolean dispose_has_run; GabbleCallMember *member; WockyJingleContent *jingle_content; gchar *name; WockyJingleMediaType media_type; GList *remote_codecs; gboolean removed; }; #define GABBLE_CALL_MEMBER_CONTENT_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), GABBLE_TYPE_CALL_MEMBER_CONTENT, \ GabbleCallMemberContentPrivate)) static void gabble_call_member_content_init (GabbleCallMemberContent *self) { GabbleCallMemberContentPrivate *priv = GABBLE_CALL_MEMBER_CONTENT_GET_PRIVATE (self); self->priv = priv; } static void gabble_call_member_content_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleCallMemberContent *self = GABBLE_CALL_MEMBER_CONTENT (object); GabbleCallMemberContentPrivate *priv = self->priv; switch (property_id) { case PROP_MEMBER: g_value_set_object (value, priv->member); break; case PROP_JINGLE_CONTENT: g_value_set_object (value, priv->jingle_content); break; case PROP_CONTENT_NAME: g_value_set_string (value, priv->name); break; case PROP_MEDIA_TYPE: g_value_set_uint (value, priv->media_type); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_call_member_content_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleCallMemberContent *self = GABBLE_CALL_MEMBER_CONTENT (object); GabbleCallMemberContentPrivate *priv = self->priv; switch (property_id) { case PROP_JINGLE_CONTENT: gabble_call_member_content_set_jingle_content (self, g_value_get_object (value)); break; case PROP_MEMBER: priv->member = g_value_get_object (value); break; case PROP_CONTENT_NAME: priv->name = g_value_dup_string (value); g_assert (priv->name != NULL); break; case PROP_MEDIA_TYPE: priv->media_type = g_value_get_uint (value); g_assert (priv->media_type != WOCKY_JINGLE_MEDIA_TYPE_NONE); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_call_member_content_dispose (GObject *object); static void gabble_call_member_content_finalize (GObject *object); void gabble_call_member_content_add_to_session (GabbleCallMemberContent *self) { GabbleCallMemberContentPrivate *priv = self->priv; const gchar *content_ns; WockyJingleSession *session; WockyJingleContent *content; const gchar *peer_resource; const gchar *transport_ns; if (priv->jingle_content != NULL) return; DEBUG ("Session set for: %s (current jingle %p)", priv->name, priv->jingle_content); session = gabble_call_member_get_session (priv->member); transport_ns = gabble_call_member_get_transport_ns (priv->member); content_ns = NS_JINGLE_RTP; g_assert (session != NULL); peer_resource = wocky_jingle_session_get_peer_resource (session); if (peer_resource != NULL) DEBUG ("existing call, using peer resource %s", peer_resource); else DEBUG ("existing call, using bare JID"); DEBUG ("Creating new jingle content with ns %s : %s", content_ns, transport_ns); content = wocky_jingle_session_add_content (session, priv->media_type, WOCKY_JINGLE_CONTENT_SENDERS_BOTH, priv->name, content_ns, transport_ns); gabble_call_member_content_set_jingle_content (self, content); } static void member_got_session_cb (GabbleCallMember *member, GParamSpec *param, gpointer user_data) { gabble_call_member_content_add_to_session ( GABBLE_CALL_MEMBER_CONTENT (user_data)); } static void gabble_call_member_content_constructed (GObject *obj) { GabbleCallMemberContent *self = GABBLE_CALL_MEMBER_CONTENT (obj); GabbleCallMemberContentPrivate *priv = self->priv; gabble_signal_connect_weak (priv->member, "notify::session", G_CALLBACK (member_got_session_cb), G_OBJECT (self)); if (G_OBJECT_CLASS (gabble_call_member_content_parent_class)->constructed != NULL) G_OBJECT_CLASS ( gabble_call_member_content_parent_class)->constructed (obj); } static void gabble_call_member_content_class_init ( GabbleCallMemberContentClass *gabble_call_member_content_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_call_member_content_class); GParamSpec *param_spec; g_type_class_add_private (gabble_call_member_content_class, sizeof (GabbleCallMemberContentPrivate)); object_class->dispose = gabble_call_member_content_dispose; object_class->finalize = gabble_call_member_content_finalize; object_class->get_property = gabble_call_member_content_get_property; object_class->set_property = gabble_call_member_content_set_property; object_class->constructed = gabble_call_member_content_constructed; param_spec = g_param_spec_string ("name", "Name", "The name of this jingle content", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONTENT_NAME, param_spec); param_spec = g_param_spec_uint ("media-type", "MediaType", "The media type of this jingle content", WOCKY_JINGLE_MEDIA_TYPE_NONE, WOCKY_JINGLE_MEDIA_TYPE_VIDEO, WOCKY_JINGLE_MEDIA_TYPE_NONE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_MEDIA_TYPE, param_spec); param_spec = g_param_spec_object ("jingle-content", "JingleContent", "The jingle content corresponding to this members content", WOCKY_TYPE_JINGLE_CONTENT, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_JINGLE_CONTENT, param_spec); param_spec = g_param_spec_object ("member", "CallMember", "The call member that has this as a content", GABBLE_TYPE_CALL_MEMBER, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_MEMBER, param_spec); signals[CODECS_CHANGED] = g_signal_new ("codecs-changed", G_OBJECT_CLASS_TYPE (gabble_call_member_content_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[GOT_JINGLE_CONTENT] = g_signal_new ("got-jingle-content", G_OBJECT_CLASS_TYPE (gabble_call_member_content_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[REMOVED] = g_signal_new ("removed", G_OBJECT_CLASS_TYPE (gabble_call_member_content_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } void gabble_call_member_content_dispose (GObject *object) { GabbleCallMemberContent *self = GABBLE_CALL_MEMBER_CONTENT (object); GabbleCallMemberContentPrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; tp_clear_object (&priv->jingle_content); if (G_OBJECT_CLASS (gabble_call_member_content_parent_class)->dispose) G_OBJECT_CLASS (gabble_call_member_content_parent_class)->dispose (object); } void gabble_call_member_content_finalize (GObject *object) { GabbleCallMemberContent *self = GABBLE_CALL_MEMBER_CONTENT (object); GabbleCallMemberContentPrivate *priv = self->priv; g_free (priv->name); G_OBJECT_CLASS (gabble_call_member_content_parent_class)->finalize (object); } WockyJingleMediaType gabble_call_member_content_get_media_type (GabbleCallMemberContent *self) { return self->priv->media_type; } const gchar * gabble_call_member_content_get_name (GabbleCallMemberContent *self) { return self->priv->name; } WockyJingleContent * gabble_call_member_content_get_jingle_content ( GabbleCallMemberContent *self) { return self->priv->jingle_content; } GabbleCallMemberContent * gabble_call_member_content_new (const gchar *name, WockyJingleMediaType type, GabbleCallMember *member) { return GABBLE_CALL_MEMBER_CONTENT (g_object_new ( GABBLE_TYPE_CALL_MEMBER_CONTENT, "name", name, "media-type", type, "member", member, NULL)); } static void call_member_content_jingle_removed_cb (WockyJingleContent *jingle_content, GabbleCallMemberContent *content) { if (!content->priv->removed) { content->priv->removed = TRUE; g_signal_emit (content, signals[REMOVED], 0); } } static void call_member_content_jingle_media_description_cb (WockyJingleMediaRtp *media, WockyJingleMediaDescription *md, gpointer user_data) { GabbleCallMemberContent *self = GABBLE_CALL_MEMBER_CONTENT (user_data); DEBUG ("New codecs from jingle"); g_signal_emit (self, signals[CODECS_CHANGED], 0); } GabbleCallMemberContent * gabble_call_member_content_from_jingle_content ( WockyJingleContent *jingle_content, GabbleCallMember *member) { GabbleCallMemberContent *content; gchar *name; WockyJingleMediaType mtype; g_object_get (jingle_content, "name", &name, "media-type", &mtype, NULL); content = gabble_call_member_content_new (name, mtype, member); gabble_call_member_content_set_jingle_content (content, jingle_content); g_free (name); return content; } gboolean gabble_call_member_content_has_jingle_content ( GabbleCallMemberContent *self) { return self->priv->jingle_content != NULL; } GList * gabble_call_member_content_get_remote_codecs (GabbleCallMemberContent *self) { GList *jcodecs = NULL; if (self->priv->jingle_content != NULL) { WockyJingleMediaDescription *md; md = wocky_jingle_media_rtp_get_remote_media_description ( WOCKY_JINGLE_MEDIA_RTP (self->priv->jingle_content)); if (md != NULL) jcodecs = md->codecs; } return jcodecs != NULL ? jcodecs : self->priv->remote_codecs; } void gabble_call_member_content_set_remote_codecs (GabbleCallMemberContent *self, GList *codecs) { GabbleCallMemberContentPrivate *priv = self->priv; DEBUG ("New codecs set directly on the member"); if (priv->remote_codecs != NULL) { GList *changed = NULL; if (!jingle_media_rtp_compare_codecs (priv->remote_codecs, codecs, &changed, NULL) || changed == NULL) return; g_list_free (changed); } jingle_media_rtp_free_codecs (priv->remote_codecs); priv->remote_codecs = codecs; g_signal_emit (self, signals[CODECS_CHANGED], 0); } GabbleCallMember * gabble_call_member_content_get_member (GabbleCallMemberContent *self) { return self->priv->member; } void gabble_call_member_content_set_jingle_content (GabbleCallMemberContent *self, WockyJingleContent *content) { g_assert (self->priv->jingle_content == NULL); if (content == NULL) return; self->priv->jingle_content = g_object_ref (content); gabble_signal_connect_weak (content, "removed", G_CALLBACK (call_member_content_jingle_removed_cb), G_OBJECT (self)); gabble_signal_connect_weak (content, "remote-media-description", G_CALLBACK (call_member_content_jingle_media_description_cb), G_OBJECT (self)); g_signal_emit (self, signals[GOT_JINGLE_CONTENT], 0); } void gabble_call_member_content_remove (GabbleCallMemberContent *self) { GabbleCallMemberContentPrivate *priv = self->priv; if (priv->removed) return; priv->removed = TRUE; g_object_ref (self); /* Remove ourselves from the sesison */ if (priv->jingle_content != NULL) wocky_jingle_session_remove_content (priv->jingle_content->session, priv->jingle_content); g_signal_emit (self, signals[REMOVED], 0); g_object_unref (self); } telepathy-gabble-0.18.3/src/disco.c0000664000175000017500000006322312223562023020235 0ustar00cassidycassidy00000000000000/* * disco.c - Source for Gabble service discovery * * Copyright (C) 2006, 2008 Collabora Ltd. * Copyright (C) 2006, 2008 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * -- LET'S DISCO!!! \o/ \o_ _o/ /\o/\ _/o/- -\o\_ -- */ #include "config.h" #include "disco.h" #include #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_DISCO #include "connection.h" #include "debug.h" #include "error.h" #include "namespaces.h" #include "util.h" #include "gabble-signals-marshal.h" #define DEFAULT_REQUEST_TIMEOUT 20 #define DISCO_PIPELINE_SIZE 10 /* signals */ enum { ITEM_FOUND, DONE, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; /* Properties */ enum { PROP_CONNECTION = 1, LAST_PROPERTY }; G_DEFINE_TYPE(GabbleDisco, gabble_disco, G_TYPE_OBJECT); struct _GabbleDiscoPrivate { GabbleConnection *connection; GSList *service_cache; GList *requests; gboolean dispose_has_run; }; struct _GabbleDiscoRequest { GabbleDisco *disco; guint timer_id; GabbleDiscoType type; gchar *jid; gchar *node; GabbleDiscoCb callback; gpointer user_data; GObject *bound_object; }; GQuark gabble_disco_error_quark (void) { static GQuark quark = 0; if (!quark) quark = g_quark_from_static_string ("gabble-disco-error"); return quark; } static void gabble_disco_init (GabbleDisco *obj) { GabbleDiscoPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, GABBLE_TYPE_DISCO, GabbleDiscoPrivate); obj->priv = priv; } static GObject *gabble_disco_constructor (GType type, guint n_props, GObjectConstructParam *props); static void gabble_disco_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec); static void gabble_disco_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec); static void gabble_disco_dispose (GObject *object); static void gabble_disco_finalize (GObject *object); static void gabble_disco_class_init (GabbleDiscoClass *gabble_disco_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_disco_class); GParamSpec *param_spec; g_type_class_add_private (gabble_disco_class, sizeof (GabbleDiscoPrivate)); object_class->constructor = gabble_disco_constructor; object_class->get_property = gabble_disco_get_property; object_class->set_property = gabble_disco_set_property; object_class->dispose = gabble_disco_dispose; object_class->finalize = gabble_disco_finalize; param_spec = g_param_spec_object ("connection", "GabbleConnection object", "Gabble connection object that owns this XMPP Discovery object.", GABBLE_TYPE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); signals[ITEM_FOUND] = g_signal_new ("item-found", G_OBJECT_CLASS_TYPE (gabble_disco_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[DONE] = g_signal_new ("done", G_OBJECT_CLASS_TYPE (gabble_disco_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } static void gabble_disco_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleDisco *chan = GABBLE_DISCO (object); GabbleDiscoPrivate *priv = chan->priv; switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, priv->connection); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_disco_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleDisco *chan = GABBLE_DISCO (object); GabbleDiscoPrivate *priv = chan->priv; switch (property_id) { case PROP_CONNECTION: priv->connection = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_disco_conn_status_changed_cb (GabbleConnection *conn, TpConnectionStatus status, TpConnectionStatusReason reason, gpointer data); static GObject * gabble_disco_constructor (GType type, guint n_props, GObjectConstructParam *props) { GObject *obj; GabbleDisco *disco; GabbleDiscoPrivate *priv; obj = G_OBJECT_CLASS (gabble_disco_parent_class)-> constructor (type, n_props, props); disco = GABBLE_DISCO (obj); priv = disco->priv; g_signal_connect (priv->connection, "status-changed", G_CALLBACK (gabble_disco_conn_status_changed_cb), disco); return obj; } static void cancel_request (GabbleDiscoRequest *request); static void gabble_disco_dispose (GObject *object) { GabbleDisco *self = GABBLE_DISCO (object); GabbleDiscoPrivate *priv = self->priv; GSList *l; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; DEBUG ("dispose called"); /* cancel request removes the element from the list after cancelling */ while (priv->requests) cancel_request (priv->requests->data); for (l = priv->service_cache; l; l = g_slist_next (l)) { GabbleDiscoItem *item = (GabbleDiscoItem *) l->data; g_free ((char *) item->jid); g_free ((char *) item->name); g_free ((char *) item->category); g_free ((char *) item->type); g_hash_table_unref (item->features); g_free (item); } g_slist_free (priv->service_cache); priv->service_cache = NULL; if (G_OBJECT_CLASS (gabble_disco_parent_class)->dispose) G_OBJECT_CLASS (gabble_disco_parent_class)->dispose (object); } static void gabble_disco_finalize (GObject *object) { DEBUG ("called with %p", object); G_OBJECT_CLASS (gabble_disco_parent_class)->finalize (object); } /** * gabble_disco_new: * @conn: The #GabbleConnection to use for service discovery * * Creates an object to use for Jabber service discovery (DISCO) * There should be one of these per connection */ GabbleDisco * gabble_disco_new (GabbleConnection *conn) { GabbleDisco *disco; g_return_val_if_fail (GABBLE_IS_CONNECTION (conn), NULL); disco = GABBLE_DISCO (g_object_new (GABBLE_TYPE_DISCO, "connection", conn, NULL)); return disco; } static void notify_delete_request (gpointer data, GObject *obj); static void delete_request (GabbleDiscoRequest *request) { GabbleDisco *disco = request->disco; GabbleDiscoPrivate *priv; g_assert (NULL != request); g_assert (GABBLE_IS_DISCO (disco)); priv = disco->priv; g_assert (NULL != g_list_find (priv->requests, request)); priv->requests = g_list_remove (priv->requests, request); if (NULL != request->bound_object) { g_object_weak_unref (request->bound_object, notify_delete_request, request); } if (0 != request->timer_id) { g_source_remove (request->timer_id); } g_free (request->jid); g_free (request->node); g_slice_free (GabbleDiscoRequest, request); } static gboolean timeout_request (gpointer data) { GabbleDiscoRequest *request = (GabbleDiscoRequest *) data; GabbleDisco *disco; GError *err = NULL; g_return_val_if_fail (data != NULL, FALSE); err = g_error_new (GABBLE_DISCO_ERROR, GABBLE_DISCO_ERROR_TIMEOUT, "Request for %s on %s timed out", (request->type == GABBLE_DISCO_TYPE_INFO)?"info":"items", request->jid); /* Temporarily ref the disco object to avoid crashing if the callback * destroys us (as seen in test-disco-no-reply.py) */ disco = g_object_ref (request->disco); /* also, we're about to run the callback, so it's too late to cancel it - * avoid crashing if running the callback destroys the bound object */ if (NULL != request->bound_object) { g_object_weak_unref (request->bound_object, notify_delete_request, request); request->bound_object = NULL; } (request->callback)(request->disco, request, request->jid, request->node, NULL, err, request->user_data); g_error_free (err); request->timer_id = 0; delete_request (request); g_object_unref (disco); return FALSE; } static void cancel_request (GabbleDiscoRequest *request) { GError *err = NULL; g_assert (request != NULL); err = g_error_new (GABBLE_DISCO_ERROR, GABBLE_DISCO_ERROR_CANCELLED, "Request for %s on %s cancelled", (request->type == GABBLE_DISCO_TYPE_INFO)?"info":"items", request->jid); (request->callback)(request->disco, request, request->jid, request->node, NULL, err, request->user_data); g_error_free (err); delete_request (request); } static const char * disco_type_to_xmlns (GabbleDiscoType type) { switch (type) { case GABBLE_DISCO_TYPE_INFO: return NS_DISCO_INFO; case GABBLE_DISCO_TYPE_ITEMS: return NS_DISCO_ITEMS; default: g_assert_not_reached (); } return NULL; } static void request_reply_cb (GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg, GObject *object, gpointer user_data) { GabbleDiscoRequest *request = (GabbleDiscoRequest *) user_data; GabbleDisco *disco = GABBLE_DISCO (object); GabbleDiscoPrivate *priv = disco->priv; WockyNode *query_node; GError *err = NULL; g_assert (request); if (!g_list_find (priv->requests, request)) return; query_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (reply_msg), "query", disco_type_to_xmlns (request->type)); if (wocky_stanza_extract_errors (reply_msg, NULL, &err, NULL, NULL)) { /* pass */ } else if (NULL == query_node) { err = g_error_new (GABBLE_DISCO_ERROR, GABBLE_DISCO_ERROR_UNKNOWN, "disco response contained no node"); } request->callback (request->disco, request, request->jid, request->node, query_node, err, request->user_data); delete_request (request); if (err) g_error_free (err); } static void notify_delete_request (gpointer data, GObject *obj) { GabbleDiscoRequest *request = (GabbleDiscoRequest *) data; request->bound_object = NULL; delete_request (request); } /** * gabble_disco_request: * @self: #GabbleDisco object to use for request * @type: type of request * @jid: Jabber ID to request on * @node: node to request on @jid, or NULL * @callback: #GabbleDiscoCb to call on request fullfilment * @object: GObject to bind request to. the callback will not be * called if this object has been unrefed. NULL if not needed * @error: #GError to return a telepathy error in if unable to make * request, NULL if unneeded. * * Make a disco request on the given jid with the default timeout. */ GabbleDiscoRequest * gabble_disco_request (GabbleDisco *self, GabbleDiscoType type, const gchar *jid, const char *node, GabbleDiscoCb callback, gpointer user_data, GObject *object, GError **error) { return gabble_disco_request_with_timeout (self, type, jid, node, DEFAULT_REQUEST_TIMEOUT, callback, user_data, object, error); } /** * gabble_disco_request_with_timeout: * @self: #GabbleDisco object to use for request * @type: type of request * @jid: Jabber ID to request on * @node: node to request on @jid, or NULL * @timeout: the time until the request fails, in seconds * @callback: #GabbleDiscoCb to call on request fullfilment * @object: GObject to bind request to. the callback will not be * called if this object has been unrefed. NULL if not needed * @error: #GError to return a telepathy error in if unable to make * request, NULL if unneeded. * * Make a disco request on the given jid, which will fail unless a reply * is received within the given timeout interval. */ GabbleDiscoRequest * gabble_disco_request_with_timeout (GabbleDisco *self, GabbleDiscoType type, const gchar *jid, const char *node, guint timeout, GabbleDiscoCb callback, gpointer user_data, GObject *object, GError **error) { GabbleDiscoPrivate *priv = self->priv; GabbleDiscoRequest *request; WockyStanza *msg; WockyNode *lm_node; request = g_slice_new0 (GabbleDiscoRequest); request->disco = self; request->type = type; request->jid = g_strdup (jid); if (node) request->node = g_strdup (node); request->callback = callback; request->user_data = user_data; request->bound_object = object; if (NULL != object) g_object_weak_ref (object, notify_delete_request, request); DEBUG ("Creating disco request %p for %s", request, request->jid); priv->requests = g_list_prepend (priv->requests, request); msg = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, jid, '(', "query", ':', disco_type_to_xmlns (type), '*', &lm_node, ')', NULL); if (node) { wocky_node_set_attribute (lm_node, "node", node); } if (! _gabble_connection_send_with_reply (priv->connection, msg, request_reply_cb, G_OBJECT(self), request, error)) { delete_request (request); g_object_unref (msg); return NULL; } else { request->timer_id = g_timeout_add_seconds (timeout, timeout_request, request); g_object_unref (msg); return request; } } void gabble_disco_cancel_request (GabbleDisco *disco, GabbleDiscoRequest *request) { GabbleDiscoPrivate *priv; g_return_if_fail (GABBLE_IS_DISCO (disco)); g_return_if_fail (NULL != request); priv = disco->priv; g_return_if_fail (NULL != g_list_find (priv->requests, request)); cancel_request (request); } /* Disco pipeline */ typedef struct _GabbleDiscoPipeline GabbleDiscoPipeline; struct _GabbleDiscoPipeline { GabbleDisco *disco; gpointer user_data; GabbleDiscoPipelineCb callback; GabbleDiscoEndCb end_callback; GPtrArray *disco_pipeline; GHashTable *remaining_items; GabbleDiscoRequest *list_request; gboolean running; }; static void gabble_disco_fill_pipeline (GabbleDisco *disco, GabbleDiscoPipeline *pipeline); static void item_info_cb (GabbleDisco *disco, GabbleDiscoRequest *request, const gchar *jid, const gchar *node, WockyNode *result, GError *error, gpointer user_data) { WockyNode *identity, *value_node, *feature; const char *category, *type, *var, *name, *value; GHashTable *keys; GabbleDiscoItem item; WockyNodeIter i; GabbleDiscoPipeline *pipeline = (GabbleDiscoPipeline *) user_data; g_ptr_array_remove_fast (pipeline->disco_pipeline, request); if (error) { DEBUG ("got error %s", error->message); goto done; } identity = wocky_node_get_child (result, "identity"); if (NULL == identity) goto done; name = wocky_node_get_attribute (identity, "name"); if (NULL == name) goto done; category = wocky_node_get_attribute (identity, "category"); if (NULL == category) goto done; type = wocky_node_get_attribute (identity, "type"); if (NULL == type) goto done; DEBUG ("got item identity, jid=%s, name=%s, category=%s, type=%s", jid, name, category, type); keys = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); wocky_node_iter_init (&i, result, NULL, NULL); while (wocky_node_iter_next (&i, &feature)) { if (0 == strcmp (feature->name, "feature")) { var = wocky_node_get_attribute (feature, "var"); if (var) g_hash_table_insert (keys, g_strdup (var), NULL); } else if (0 == strcmp (feature->name, "x")) { if (wocky_node_has_ns (feature, NS_X_DATA)) { WockyNodeIter j; WockyNode *field; wocky_node_iter_init (&j, feature, "field", NULL); while (wocky_node_iter_next (&j, &field)) { var = wocky_node_get_attribute (field, "var"); if (NULL == var) continue; value_node = wocky_node_get_child (field, "value"); if (NULL == value_node) continue; value = value_node->content; if (NULL == value) continue; g_hash_table_insert (keys, g_strdup (var), g_strdup (value)); } } } } item.jid = jid; item.name = name; item.category = category; item.type = type; item.features = keys; pipeline->callback (pipeline, &item, pipeline->user_data); g_hash_table_unref (keys); done: gabble_disco_fill_pipeline (disco, pipeline); return; } static gboolean return_true (gpointer key, gpointer value, gpointer data) { return TRUE; } static void gabble_disco_fill_pipeline (GabbleDisco *disco, GabbleDiscoPipeline *pipeline) { if (!pipeline->running) { DEBUG ("pipeline not running, not refilling"); } else { /* send disco requests for the JIDs in the remaining_items hash table * until there are DISCO_PIPELINE_SIZE requests in progress */ while (pipeline->disco_pipeline->len < DISCO_PIPELINE_SIZE) { gchar *jid; GabbleDiscoRequest *request; jid = (gchar *) g_hash_table_find (pipeline->remaining_items, return_true, NULL); if (NULL == jid) break; request = gabble_disco_request (disco, GABBLE_DISCO_TYPE_INFO, jid, NULL, item_info_cb, pipeline, G_OBJECT(disco), NULL); g_ptr_array_add (pipeline->disco_pipeline, request); /* frees jid */ g_hash_table_remove (pipeline->remaining_items, jid); } if (0 == pipeline->disco_pipeline->len) { /* signal that the pipeline has finished */ pipeline->running = FALSE; pipeline->end_callback (pipeline, pipeline->user_data); } } } static void disco_items_cb (GabbleDisco *disco, GabbleDiscoRequest *request, const gchar *jid, const gchar *node, WockyNode *result, GError *error, gpointer user_data) { const char *item_jid; gpointer key, value; GabbleDiscoPipeline *pipeline = (GabbleDiscoPipeline *) user_data; WockyNodeIter i; WockyNode *item; pipeline->list_request = NULL; if (error) { DEBUG ("Got error on items request: %s", error->message); goto out; } wocky_node_iter_init (&i, result, "item", NULL); while (wocky_node_iter_next (&i, &item)) { item_jid = wocky_node_get_attribute (item, "jid"); if (NULL != item_jid && !g_hash_table_lookup_extended (pipeline->remaining_items, item_jid, &key, &value)) { gchar *tmp = g_strdup (item_jid); DEBUG ("discovered service item: %s", tmp); g_hash_table_insert (pipeline->remaining_items, tmp, tmp); } } out: gabble_disco_fill_pipeline (disco, pipeline); } /** * gabble_disco_pipeline_init: * @disco: disco object to use in the pipeline * @callback: GFunc to call on request fullfilment * @user_data: the usual * * Prepares the pipeline for making the ITEM request on the server and * subsequent INFO elements on returned items. * * GabbleDiscoPipeline is opaque structure for the user. */ gpointer gabble_disco_pipeline_init (GabbleDisco *disco, GabbleDiscoPipelineCb callback, GabbleDiscoEndCb end_callback, gpointer user_data) { GabbleDiscoPipeline *pipeline = g_new (GabbleDiscoPipeline, 1); pipeline->user_data = user_data; pipeline->callback = callback; pipeline->end_callback = end_callback; pipeline->disco_pipeline = g_ptr_array_sized_new (DISCO_PIPELINE_SIZE); pipeline->remaining_items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); pipeline->running = TRUE; pipeline->disco = disco; return pipeline; } /** * gabble_disco_pipeline_run: * @self: reference to the pipeline structure * @server: server to query * * Makes ITEMS request on the server, and afterwards queries for INFO * on each item. INFO queries are pipelined. The item properties are stored * in hash table parameter to the callback function. The user is responsible * for destroying the hash table after it's done with. * * Upon returning all the results, the end_callback is called with * reference to the pipeline. */ void gabble_disco_pipeline_run (gpointer self, const char *server) { GabbleDiscoPipeline *pipeline = (GabbleDiscoPipeline *) self; pipeline->running = TRUE; pipeline->list_request = gabble_disco_request (pipeline->disco, GABBLE_DISCO_TYPE_ITEMS, server, NULL, disco_items_cb, pipeline, G_OBJECT (pipeline->disco), NULL); } /** * gabble_disco_pipeline_cancel: * @pipeline: pipeline to cancel * * Flushes the pipeline (cancels all pending disco requests) and * destroys it. */ void gabble_disco_pipeline_destroy (gpointer self) { GabbleDiscoPipeline *pipeline = (GabbleDiscoPipeline *) self; pipeline->running = FALSE; if (pipeline->list_request != NULL) { gabble_disco_cancel_request (pipeline->disco, pipeline->list_request); pipeline->list_request = NULL; } /* iterate using a while loop otherwise we're modifying * the array as we iterate it, and miss things! */ while (pipeline->disco_pipeline->len > 0) { GabbleDiscoRequest *request = g_ptr_array_index (pipeline->disco_pipeline, 0); gabble_disco_cancel_request (pipeline->disco, request); } g_hash_table_unref (pipeline->remaining_items); g_ptr_array_unref (pipeline->disco_pipeline); g_free (pipeline); } static void service_feature_copy_one (gpointer k, gpointer v, gpointer user_data) { char *key = (char *) k; char *value = (char *) v; GHashTable *target = (GHashTable *) user_data; g_hash_table_insert (target, g_strdup (key), g_strdup (value)); } /* Service discovery */ static void services_cb (gpointer pipeline, GabbleDiscoItem *item, gpointer user_data) { GabbleDisco *disco = GABBLE_DISCO (user_data); GabbleDiscoPrivate *priv = disco->priv; GabbleDiscoItem *my_item = g_new0 (GabbleDiscoItem, 1); my_item->jid = g_strdup (item->jid); my_item->name = g_strdup (item->name); my_item->category = g_strdup (item->category); my_item->type = g_strdup (item->type); my_item->features = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); g_hash_table_foreach (item->features, service_feature_copy_one, my_item->features); priv->service_cache = g_slist_prepend (priv->service_cache, my_item); g_signal_emit (G_OBJECT (disco), signals[ITEM_FOUND], 0, my_item); } static void end_cb (gpointer pipeline, gpointer user_data) { GabbleDisco *disco = GABBLE_DISCO (user_data); GabbleDiscoPrivate *priv = disco->priv; gabble_disco_pipeline_destroy (pipeline); priv->service_cache = g_slist_reverse (priv->service_cache); g_signal_emit (G_OBJECT (disco), signals[DONE], 0); } static void gabble_disco_conn_status_changed_cb (GabbleConnection *conn, TpConnectionStatus status, TpConnectionStatusReason reason, gpointer data) { GabbleDisco *disco = GABBLE_DISCO (data); GabbleDiscoPrivate *priv = disco->priv; if (status == TP_CONNECTION_STATUS_CONNECTED) { char *server; gpointer pipeline; g_object_get (priv->connection, "stream-server", &server, NULL); g_assert (server != NULL); DEBUG ("connected, initiating service discovery on %s", server); pipeline = gabble_disco_pipeline_init (disco, services_cb, end_cb, disco); gabble_disco_pipeline_run (pipeline, server); g_free (server); } } const GabbleDiscoItem * gabble_disco_service_find (GabbleDisco *disco, const char *category, const char *type, const char *feature) { GabbleDiscoPrivate *priv; GSList *l; g_assert (GABBLE_IS_DISCO (disco)); priv = disco->priv; for (l = priv->service_cache; l; l = g_slist_next (l)) { GabbleDiscoItem *item = (GabbleDiscoItem *) l->data; if (category != NULL && tp_strdiff (category, item->category)) continue; if (type != NULL && tp_strdiff (type, item->type)) continue; if (feature != NULL && !g_hash_table_lookup_extended (item->features, feature, NULL, NULL)) continue; return item; } return NULL; } telepathy-gabble-0.18.3/src/Makefile.am0000664000175000017500000002051612332441362021025 0ustar00cassidycassidy00000000000000BUILT_SOURCES = \ gabble-signals-marshal.h \ gabble-signals-marshal.c \ gabble-signals-marshal.list \ gabble-enumtypes.h \ gabble-enumtypes.c CLEANFILES = $(BUILT_SOURCES) EXTRA_DIST = libexec_PROGRAMS=telepathy-gabble noinst_PROGRAMS = write-mgr-file libgabble_convenience_la_SOURCES = \ addressing-util.h \ addressing-util.c \ auth-manager.h \ auth-manager.c \ bytestream-factory.h \ bytestream-factory.c \ bytestream-ibb.h \ bytestream-ibb.c \ bytestream-iface.h \ bytestream-iface.c \ bytestream-muc.h \ bytestream-muc.c \ bytestream-multiple.h \ bytestream-multiple.c \ bytestream-socks5.h \ bytestream-socks5.c \ capabilities.c \ caps-hash.h \ caps-hash.c \ caps-channel-manager.c \ conn-addressing.h \ conn-addressing.c \ conn-aliasing.h \ conn-aliasing.c \ conn-avatars.h \ conn-avatars.c \ conn-client-types.h \ conn-client-types.c \ conn-contact-info.h \ conn-contact-info.c \ conn-location.h \ conn-location.c \ conn-olpc.h \ conn-olpc.c \ conn-power-saving.h \ conn-power-saving.c \ conn-presence.h \ conn-presence.c \ conn-sidecars.h \ conn-sidecars.c \ conn-util.h \ conn-util.c \ conn-mail-notif.h \ conn-mail-notif.c \ connection.h \ connection.c \ connection-manager.h \ connection-manager.c \ debug.h \ debug.c \ disco.h \ disco.c \ error.c \ error.h \ gabble.c \ gabble.h \ im-channel.h \ im-channel.c \ im-factory.h \ im-factory.c \ legacy-caps.h \ legacy-caps.c \ message-util.h \ message-util.c \ muc-channel.h \ muc-channel.c \ muc-factory.h \ muc-factory.c \ muc-tube-dbus.h \ muc-tube-dbus.c \ muc-tube-stream.h \ muc-tube-stream.c \ namespaces.h \ olpc-activity.h \ olpc-activity.c \ plugin-loader.h \ plugin-loader.c \ presence.h \ presence.c \ presence-cache.h \ presence-cache.c \ protocol.h \ protocol.c \ private-tubes-factory.h \ private-tubes-factory.c \ request-pipeline.h \ request-pipeline.c \ roster.h \ roster.c \ room-config.h \ room-config.c \ roomlist-channel.h \ roomlist-channel.c \ roomlist-manager.h \ roomlist-manager.c \ search-channel.h \ search-channel.c \ search-manager.h \ search-manager.c \ server-sasl-channel.h \ server-sasl-channel.c \ server-tls-channel.h \ server-tls-channel.c \ server-tls-manager.h \ server-tls-manager.c \ sidecar.c \ tls-certificate.h \ tls-certificate.c \ tube-iface.h \ tube-iface.c \ tube-dbus.h \ tube-dbus.c \ tube-stream.h \ tube-stream.c \ types.h \ util.h \ util.c \ vcard-manager.h \ vcard-manager.c if ENABLE_FILE_TRANSFER libgabble_convenience_la_SOURCES += \ ft-channel.c \ ft-channel.h \ ft-manager.c \ ft-manager.h endif if ENABLE_VOIP libgabble_convenience_la_SOURCES += \ base-call-channel.h \ base-call-channel.c \ call-content.h \ call-content.c \ call-channel.h \ call-channel.c \ call-muc-channel.h \ call-muc-channel.c \ call-member.h \ call-member.c \ call-member-content.h \ call-member-content.c \ call-stream.h \ call-stream.c \ jingle-share.h \ jingle-share.c \ jingle-mint.h \ jingle-mint.c \ jingle-tp-util.h \ jingle-tp-util.c \ media-channel.h \ media-channel-internal.h \ media-channel.c \ media-channel-hold.c \ media-stream.h \ media-stream.c \ media-factory.h \ media-factory.c endif if ENABLE_JINGLE_FILE_TRANSFER libgabble_convenience_la_SOURCES += \ gtalk-file-collection.c \ gtalk-file-collection.h endif enumtype_sources = \ $(top_srcdir)/src/connection.h \ $(top_srcdir)/src/room-config.h \ $(top_srcdir)/src/presence.h libgabble_convenience_la_LIBADD = \ $(top_builddir)/extensions/libgabble-extensions.la \ $(top_builddir)/lib/gibber/libgibber.la \ libgabble-plugins.la \ $(ALL_LIBS) nodist_libgabble_convenience_la_SOURCES = \ $(BUILT_SOURCES) write_mgr_file_SOURCES = write-mgr-file.c write_mgr_file_LDADD = libgabble-convenience.la telepathy_gabble_SOURCES = \ main.c check_c_sources = \ $(telepathy_gabble_SOURCES) \ $(libgabble_convenience_la_SOURCES) \ $(write_mgr_file_SOURCES) include $(top_srcdir)/tools/check-coding-style.mk check-local: check-coding-style telepathy_gabble_LDADD = libgabble-convenience.la telepathy_gabble_LDFLAGS = -export-dynamic noinst_LTLIBRARIES = libgabble-convenience.la pluginexeclib_LTLIBRARIES = libgabble-plugins.la # Gabble's plugin API is not stable yet (it can't be, since neither is Wocky), # so use -release to make the SONAME of the plugin library change with every # Gabble release. libgabble_plugins_la_LDFLAGS = \ -no-undefined \ -release $(VERSION) \ $(NULL) libgabble_plugins_la_LIBADD = \ $(ALL_LIBS) libgabble_plugins_la_SOURCES = \ capabilities.c \ caps-channel-manager.c \ debug.c \ error.c \ plugin.c \ plugin-connection.c \ sidecar.c AM_CFLAGS = $(ERROR_CFLAGS) -I$(top_srcdir) -I$(top_builddir) \ @DBUS_CFLAGS@ @GLIB_CFLAGS@ @WOCKY_CFLAGS@ \ @TP_GLIB_CFLAGS@ \ @SOUP_CFLAGS@ @NICE_CFLAGS@ @GMODULE_CFLAGS@ \ -I $(top_srcdir)/lib -I $(top_builddir)/lib \ -DG_LOG_DOMAIN=\"gabble\" \ -DPLUGIN_DIR=\"$(pluginexecdir)\" # following flag is requied to make getnameinfo work if WINDOWS AM_CFLAGS += -D_WIN32_WINNT=0x0501 endif ALL_LIBS = @DBUS_LIBS@ @GLIB_LIBS@ @WOCKY_LIBS@ @TP_GLIB_LIBS@ \ @SOUP_LIBS@ @NICE_LIBS@ @GMODULE_LIBS@ # build gibber first all: gibber gibber: @${MAKE} -C $(top_builddir)/lib/gibber libgibber.la .PHONY: gibber gabble-signals-marshal.list: $(libgabble_convenience_la_SOURCES) Makefile.am @( cd $(srcdir) && \ sed -n -e 's/.*gabble_marshal_\([[:upper:][:digit:]]*__[[:upper:][:digit:]_]*\).*/\1/p' \ $(libgabble_convenience_la_SOURCES) ) \ | sed -e 's/__/:/' -e 'y/_/,/' | sort -u > $@.tmp @if cmp -s $@.tmp $@; then \ rm $@.tmp; \ else \ mv $@.tmp $@; \ fi %-signals-marshal.h: %-signals-marshal.list Makefile.am $(AM_V_GEN)glib-genmarshal --header --prefix=$(subst -,_,$*)_marshal $< > $@ %-signals-marshal.c: %-signals-marshal.list Makefile.am $(AM_V_GEN){ echo '#include "$*-signals-marshal.h"' && \ glib-genmarshal --body --prefix=$(subst -,_,$*)_marshal $< ; \ } > $@ # rules for making the glib enum objects gabble-enumtypes.h: $(enumtype_sources) Makefile.in $(AM_V_GEN)glib-mkenums \ --fhead "#ifndef __GABBLE_ENUM_TYPES_H__\n#define __GABBLE_ENUM_TYPES_H__\n\n#include \n\nG_BEGIN_DECLS\n" \ --fprod "/* enumerations from \"@filename@\" */\n" \ --vhead "GType @enum_name@_get_type (void);\n#define GABBLE_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ --ftail "G_END_DECLS\n\n#endif /* __GABBLE_ENUM_TYPES_H__ */" \ $(enumtype_sources) > $@ gabble-enumtypes.c: $(enumtype_sources) Makefile.in $(AM_V_GEN)glib-mkenums \ --fhead "#include \"config.h\"\n" \ --fhead "#include <$*.h>" \ --fprod "\n/* enumerations from \"@filename@\" */\n#include \"@filename@\"" \ --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \ $(enumtype_sources) > $@ Android.mk: Makefile.am $(BUILT_SOURCES) androgenizer -:PROJECT telepathy-gabble \ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ -:SHARED gabble-plugins -:TAGS eng debug \ -:SOURCES $(libgabble_plugins_la_SOURCES) \ -:CFLAGS $(DEFS) $(CFLAGS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CFLAGS) \ -:CPPFLAGS $(CPPFLAGS) $(AM_CPPFLAGS) \ -:LDFLAGS $(libgabble_plugins_la_LDFLAGS) \ $(libgabble_plugins_la_LIBADD) \ -:SHARED telepathy-gabble -:TAGS eng debug \ -:SOURCES $(libgabble_convenience_la_SOURCES) \ $(nodist_libgabble_convenience_la_SOURCES) main.c \ -:CFLAGS $(DEFS) $(CFLAGS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CFLAGS) -DBUILD_AS_ANDROID_SERVICE \ -:CPPFLAGS $(CPPFLAGS) $(AM_CPPFLAGS) $(telepathy_gabble_LDFLAGS) \ -:LDFLAGS $(telepathy_gabble_LDADD) $(libgabble_convenience_la_LIBADD) \ $(lib_LTLIBRARIES) \ > $@ telepathy-gabble-0.18.3/src/plugin-connection.c0000664000175000017500000001303412223562023022562 0ustar00cassidycassidy00000000000000/* * plugin-connection.c — API for telepathy-gabble plugins * Copyright © 2012 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "gabble/plugin-connection.h" #include #include #include #include static guint sig_id_porter_available = 0; /** * SECTION: gabble-plugin-connection * @title: GabblePluginConnection * @short_description: Object representing gabble connection, implemented by * Gabble internals. * * This Object represents Gabble Connection. * * Virtual methods in GabblePluginConnectionInterface interface are implemented * by GabbleConnection object. And only Gabble should implement this interface. */ G_DEFINE_INTERFACE (GabblePluginConnection, gabble_plugin_connection, G_TYPE_OBJECT); static void gabble_plugin_connection_default_init (GabblePluginConnectionInterface *iface) { static gsize once = 0; if (g_once_init_enter (&once)) { /** * @self: a connection interface * @porter: a porter * * Emitted when the WockyPorter becomes available. */ sig_id_porter_available = g_signal_new ( "porter-available", G_OBJECT_CLASS_TYPE (iface), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, WOCKY_TYPE_PORTER); g_once_init_leave (&once, 1); } } gchar * gabble_plugin_connection_add_sidecar_own_caps ( GabblePluginConnection *plugin_connection, const GabbleCapabilitySet *cap_set, const GPtrArray *identities) { GabblePluginConnectionInterface *iface = GABBLE_PLUGIN_CONNECTION_GET_IFACE (plugin_connection); g_return_val_if_fail (iface != NULL, NULL); g_return_val_if_fail (iface->add_sidecar_own_caps != NULL, NULL); return iface->add_sidecar_own_caps (plugin_connection, cap_set, identities); } gchar * gabble_plugin_connection_add_sidecar_own_caps_full ( GabblePluginConnection *plugin_connection, const GabbleCapabilitySet *cap_set, const GPtrArray *identities, GPtrArray *data_forms) { GabblePluginConnectionInterface *iface = GABBLE_PLUGIN_CONNECTION_GET_IFACE (plugin_connection); g_return_val_if_fail (iface != NULL, NULL); g_return_val_if_fail (iface->add_sidecar_own_caps_full != NULL, NULL); return iface->add_sidecar_own_caps_full (plugin_connection, cap_set, identities, data_forms); } WockySession * gabble_plugin_connection_get_session ( GabblePluginConnection *plugin_connection) { GabblePluginConnectionInterface *iface = GABBLE_PLUGIN_CONNECTION_GET_IFACE (plugin_connection); g_return_val_if_fail (iface != NULL, NULL); g_return_val_if_fail (iface->get_session != NULL, NULL); return iface->get_session (plugin_connection); } gchar * gabble_plugin_connection_get_full_jid ( GabblePluginConnection *plugin_connection) { GabblePluginConnectionInterface *iface = GABBLE_PLUGIN_CONNECTION_GET_IFACE (plugin_connection); g_return_val_if_fail (iface != NULL, NULL); g_return_val_if_fail (iface->get_full_jid != NULL, NULL); return iface->get_full_jid (plugin_connection); } const gchar * gabble_plugin_connection_get_jid_for_caps ( GabblePluginConnection *plugin_connection, WockyXep0115Capabilities *caps) { GabblePluginConnectionInterface *iface = GABBLE_PLUGIN_CONNECTION_GET_IFACE (plugin_connection); g_return_val_if_fail (iface != NULL, NULL); g_return_val_if_fail (iface->get_jid_for_caps != NULL, NULL); return iface->get_jid_for_caps (plugin_connection, caps); } const gchar * gabble_plugin_connection_pick_best_resource_for_caps ( GabblePluginConnection *plugin_connection, const gchar *jid, GabbleCapabilitySetPredicate predicate, gconstpointer user_data) { GabblePluginConnectionInterface *iface = GABBLE_PLUGIN_CONNECTION_GET_IFACE (plugin_connection); g_return_val_if_fail (iface != NULL, NULL); g_return_val_if_fail (iface->pick_best_resource_for_caps != NULL, NULL); return iface->pick_best_resource_for_caps (plugin_connection, jid, predicate, user_data); } TpBaseContactList * gabble_plugin_connection_get_contact_list ( GabblePluginConnection *plugin_connection) { GabblePluginConnectionInterface *iface = GABBLE_PLUGIN_CONNECTION_GET_IFACE (plugin_connection); g_return_val_if_fail (iface != NULL, NULL); g_return_val_if_fail (iface->get_contact_list != NULL, NULL); return iface->get_contact_list (plugin_connection); } WockyXep0115Capabilities * gabble_plugin_connection_get_caps ( GabblePluginConnection *plugin_connection, TpHandle handle) { GabblePluginConnectionInterface *iface = GABBLE_PLUGIN_CONNECTION_GET_IFACE (plugin_connection); g_return_val_if_fail (iface != NULL, NULL); g_return_val_if_fail (iface->get_contact_list != NULL, NULL); return iface->get_caps (plugin_connection, handle); } telepathy-gabble-0.18.3/src/disco.h0000664000175000017500000001047011720700311020231 0ustar00cassidycassidy00000000000000/* * disco.h - Headers for Gabble service discovery * * Copyright (C) 2006 Collabora Ltd. * Copyright (C) 2006 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * -- LET'S DISCO!!! \o/ \o_ _o/ /\o/\ _/o/- -\o\_ -- */ #ifndef __GABBLE_DISCO_H__ #define __GABBLE_DISCO_H__ #include #include #include "types.h" G_BEGIN_DECLS typedef enum { GABBLE_DISCO_TYPE_INFO, GABBLE_DISCO_TYPE_ITEMS } GabbleDiscoType; typedef struct _GabbleDiscoClass GabbleDiscoClass; typedef struct _GabbleDiscoPrivate GabbleDiscoPrivate; typedef struct _GabbleDiscoRequest GabbleDiscoRequest; /** * GabbleDiscoError: * @GABBLE_DISCO_ERROR_CANCELLED: The DISCO request was cancelled * @GABBLE_DISCO_ERROR_TIMEOUT: The DISCO request timed out * @GABBLE_DISCO_ERROR_UNKNOWN: An unknown error occured */ typedef enum { GABBLE_DISCO_ERROR_CANCELLED, GABBLE_DISCO_ERROR_TIMEOUT, GABBLE_DISCO_ERROR_UNKNOWN } GabbleDiscoError; GQuark gabble_disco_error_quark (void); #define GABBLE_DISCO_ERROR gabble_disco_error_quark () GType gabble_disco_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_DISCO \ (gabble_disco_get_type ()) #define GABBLE_DISCO(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_DISCO, GabbleDisco)) #define GABBLE_DISCO_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_DISCO, GabbleDiscoClass)) #define GABBLE_IS_DISCO(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_DISCO)) #define GABBLE_IS_DISCO_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_DISCO)) #define GABBLE_DISCO_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_DISCO, GabbleDiscoClass)) struct _GabbleDiscoClass { GObjectClass parent_class; }; struct _GabbleDisco { GObject parent; GabbleDiscoPrivate *priv; }; typedef void (*GabbleDiscoCb)(GabbleDisco *self, GabbleDiscoRequest *request, const gchar *jid, const gchar *node, WockyNode *query_result, GError* error, gpointer user_data); GabbleDisco *gabble_disco_new (GabbleConnection *); GabbleDiscoRequest *gabble_disco_request (GabbleDisco *self, GabbleDiscoType type, const gchar *jid, const char *node, GabbleDiscoCb callback, gpointer user_data, GObject *object, GError **error); GabbleDiscoRequest *gabble_disco_request_with_timeout (GabbleDisco *self, GabbleDiscoType type, const gchar *jid, const char *node, guint timeout, GabbleDiscoCb callback, gpointer user_data, GObject *object, GError **error); void gabble_disco_cancel_request (GabbleDisco *, GabbleDiscoRequest *); /* Pipelines */ typedef struct _GabbleDiscoItem GabbleDiscoItem; struct _GabbleDiscoItem { const gchar *jid; const char *name; const char *category; const char *type; GHashTable *features; }; typedef void (*GabbleDiscoPipelineCb)(gpointer pipeline, GabbleDiscoItem *item, gpointer user_data); typedef void (*GabbleDiscoEndCb)(gpointer pipeline, gpointer user_data); gpointer gabble_disco_pipeline_init (GabbleDisco *disco, GabbleDiscoPipelineCb callback, GabbleDiscoEndCb end_callback, gpointer user_data); void gabble_disco_pipeline_run (gpointer self, const char *server); void gabble_disco_pipeline_destroy (gpointer self); /* Service discovery */ const GabbleDiscoItem * gabble_disco_service_find (GabbleDisco *disco, const char *category, const char *type, const char *feature); G_END_DECLS #endif telepathy-gabble-0.18.3/src/error.h0000664000175000017500000000175411720700311020266 0ustar00cassidycassidy00000000000000/* * gabble-error.h - Header for Gabble's error handling API * Copyright (C) 2006-2007 Collabora Ltd. * Copyright (C) 2006 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_ERROR_H__ #define __GABBLE_ERROR_H__ #include #endif /* __GABBLE_ERROR_H__ */ telepathy-gabble-0.18.3/src/conn-client-types.h0000664000175000017500000000220712332440117022507 0ustar00cassidycassidy00000000000000/* * conn-client-types - Gabble client types interface * Copyright (C) 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __CONN_CLIENT_TYPES_H__ #define __CONN_CLIENT_TYPES_H__ #include "connection.h" #include G_BEGIN_DECLS void conn_client_types_iface_init (gpointer g_iface, gpointer iface_data); void conn_client_types_init (GabbleConnection *conn); G_END_DECLS #endif /* __CONN_CLIENT_TYPES_H__ */ telepathy-gabble-0.18.3/src/room-config.h0000664000175000017500000000423312223562023021354 0ustar00cassidycassidy00000000000000/* * room-config.h - header for Channel.I.RoomConfig1 implementation * Copyright ©2011 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GABBLE_ROOM_CONFIG_H #define GABBLE_ROOM_CONFIG_H #include #include typedef struct _GabbleRoomConfig GabbleRoomConfig; typedef struct _GabbleRoomConfigClass GabbleRoomConfigClass; typedef struct _GabbleRoomConfigPrivate GabbleRoomConfigPrivate; struct _GabbleRoomConfigClass { TpBaseRoomConfigClass parent_class; }; struct _GabbleRoomConfig { TpBaseRoomConfig parent; GabbleRoomConfigPrivate *priv; }; GabbleRoomConfig *gabble_room_config_new ( TpBaseChannel *channel); /* TYPE MACROS */ GType gabble_room_config_get_type (void); #define GABBLE_TYPE_ROOM_CONFIG \ (gabble_room_config_get_type ()) #define GABBLE_ROOM_CONFIG(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_ROOM_CONFIG, GabbleRoomConfig)) #define GABBLE_ROOM_CONFIG_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_ROOM_CONFIG,\ GabbleRoomConfigClass)) #define GABBLE_IS_ROOM_CONFIG(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_ROOM_CONFIG)) #define GABBLE_IS_ROOM_CONFIG_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_ROOM_CONFIG)) #define GABBLE_ROOM_CONFIG_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_ROOM_CONFIG, \ GabbleRoomConfigClass)) #endif /* GABBLE_ROOM_CONFIG_H */ telepathy-gabble-0.18.3/src/muc-tube-stream.h0000664000175000017500000000413112223562023022144 0ustar00cassidycassidy00000000000000/* * muc-tube-stream.h - Header for GabbleMucTubeStream * Copyright (C) 2012 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_MUC_TUBE_STREAM_H__ #define __GABBLE_MUC_TUBE_STREAM_H__ #include #include "tube-stream.h" G_BEGIN_DECLS typedef struct _GabbleMucTubeStream GabbleMucTubeStream; typedef struct _GabbleMucTubeStreamClass GabbleMucTubeStreamClass; struct _GabbleMucTubeStreamClass { GabbleTubeStreamClass parent_class; }; struct _GabbleMucTubeStream { GabbleTubeStream parent; }; GType gabble_muc_tube_stream_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_MUC_TUBE_STREAM \ (gabble_muc_tube_stream_get_type ()) #define GABBLE_MUC_TUBE_STREAM(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_MUC_TUBE_STREAM, GabbleMucTubeStream)) #define GABBLE_MUC_TUBE_STREAM_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_MUC_TUBE_STREAM,\ GabbleMucTubeStreamClass)) #define GABBLE_IS_MUC_TUBE_STREAM(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_MUC_TUBE_STREAM)) #define GABBLE_IS_MUC_TUBE_STREAM_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_MUC_TUBE_STREAM)) #define GABBLE_MUC_TUBE_STREAM_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_MUC_TUBE_STREAM,\ GabbleMucTubeStreamClass)) G_END_DECLS #endif /* #ifndef __GABBLE_MUC_TUBE_STREAM_H__ */ telepathy-gabble-0.18.3/src/search-channel.h0000664000175000017500000000445712223562023022020 0ustar00cassidycassidy00000000000000/* * search-channel.h - Header for GabbleSearchChannel * Copyright (C) 2009 Collabora Ltd. * Copyright (C) 2009 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_SEARCH_CHANNEL_H__ #define __GABBLE_SEARCH_CHANNEL_H__ #include #include G_BEGIN_DECLS typedef struct _GabbleSearchChannel GabbleSearchChannel; typedef struct _GabbleSearchChannelClass GabbleSearchChannelClass; typedef struct _GabbleSearchChannelPrivate GabbleSearchChannelPrivate; struct _GabbleSearchChannelClass { TpBaseChannelClass base_class; }; struct _GabbleSearchChannel { TpBaseChannel base; GabbleSearchChannelPrivate *priv; }; GType gabble_search_channel_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_SEARCH_CHANNEL \ (gabble_search_channel_get_type ()) #define GABBLE_SEARCH_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_SEARCH_CHANNEL, GabbleSearchChannel)) #define GABBLE_SEARCH_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_SEARCH_CHANNEL,\ GabbleSearchChannelClass)) #define GABBLE_IS_SEARCH_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_SEARCH_CHANNEL)) #define GABBLE_IS_SEARCH_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_SEARCH_CHANNEL)) #define GABBLE_SEARCH_CHANNEL_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_SEARCH_CHANNEL, \ GabbleSearchChannelClass)) gboolean gabble_search_channel_is_ready (GabbleSearchChannel *chan); G_END_DECLS #endif /* #ifndef __GABBLE_SEARCH_CHANNEL_H__*/ telepathy-gabble-0.18.3/src/presence-cache.c0000664000175000017500000022677412332440117022015 0ustar00cassidycassidy00000000000000/* * gabble-presence-cache.c - Gabble's contact presence cache * Copyright (C) 2005 Collabora Ltd. * Copyright (C) 2005 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "presence-cache.h" #include "vcard-manager.h" #include "gabble-enumtypes.h" #include #include #include /* When five DIFFERENT guys report the same caps for a given bundle, it'll * be enough. But if only ONE guy use the verification string (XEP-0115 v1.5), * it'll be enough too. */ #define CAPABILITY_BUNDLE_ENOUGH_TRUST 5 #define DEBUG_FLAG GABBLE_DEBUG_PRESENCE #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_PRESENCE #include "gabble/capabilities.h" #include "gabble/caps-channel-manager.h" #include "conn-presence.h" #include "debug.h" #include "disco.h" #include "gabble-signals-marshal.h" #include "namespaces.h" #include "util.h" #include "roster.h" #include "types.h" /* Time period from the cache creation in which we're unsure whether we * got initial presence from all the contacts. */ #define UNSURE_PERIOD 5 /* Time period from a de-cloak request in which we're unsure whether the * contact will disclose their presence later, or not at all. */ #define DECLOAK_PERIOD 5 G_DEFINE_TYPE (GabblePresenceCache, gabble_presence_cache, G_TYPE_OBJECT); /* properties */ enum { PROP_CONNECTION = 1, LAST_PROPERTY }; /* signal enum */ enum { PRESENCES_UPDATED, NICKNAME_UPDATE, CAPABILITIES_UPDATE, AVATAR_UPDATE, CAPABILITIES_DISCOVERED, LOCATION_UPDATED, UNSURE_PERIOD_ENDED, CLIENT_TYPES_UPDATED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; struct _GabblePresenceCachePrivate { GabbleConnection *conn; gulong status_changed_cb; guint message_cb; guint presence_cb; GHashTable *presence; TpHandleSet *presence_handles; GHashTable *capabilities; GHashTable *disco_pending; guint caps_serial; guint unsure_id; /* handle => DecloakContext */ GHashTable *decloak_requests; TpHandleSet *decloak_handles; /* The cached contacts' location. * The key is the contact's TpHandle. * The value is a GHashTable of the user's location: * - the key is a gchar* as per XEP-0080 * - the value is a slice allocation GValue, the exact * type depends on the key. */ GHashTable *location; /* Are we resetting the image hash as per XEP-0153 section 4.4 */ gboolean avatar_reset_pending; gboolean dispose_has_run; }; typedef struct _DiscoWaiter DiscoWaiter; struct _DiscoWaiter { TpHandleRepoIface *repo; TpHandle handle; gchar *resource; guint serial; gboolean disco_requested; gchar *hash; gchar *ver; }; /** * disco_waiter_new () */ static DiscoWaiter * disco_waiter_new (TpHandleRepoIface *repo, TpHandle handle, const gchar *resource, const gchar *hash, const gchar *ver, guint serial) { DiscoWaiter *waiter; g_assert (repo); waiter = g_slice_new0 (DiscoWaiter); waiter->repo = repo; waiter->handle = handle; waiter->resource = g_strdup (resource); waiter->hash = g_strdup (hash); waiter->ver = g_strdup (ver); waiter->serial = serial; DEBUG ("created waiter %p for handle %u with serial %u", waiter, handle, serial); return waiter; } static void disco_waiter_free (DiscoWaiter *waiter) { g_assert (NULL != waiter); DEBUG ("freeing waiter %p for handle %u with serial %u", waiter, waiter->handle, waiter->serial); g_free (waiter->resource); g_free (waiter->hash); g_free (waiter->ver); g_slice_free (DiscoWaiter, waiter); } static void disco_waiter_list_free (GSList *list) { GSList *i; DEBUG ("list %p", list); for (i = list; NULL != i; i = i->next) disco_waiter_free ((DiscoWaiter *) i->data); g_slist_free (list); } static guint disco_waiter_list_get_request_count (GSList *list) { guint c = 0; GSList *i; for (i = list; i; i = i->next) { DiscoWaiter *waiter = (DiscoWaiter *) i->data; if (waiter->disco_requested) { if (!tp_strdiff (waiter->hash, "sha-1")) /* One waiter is enough if * 1. the request has a verification string * 2. the hash algorithm is supported */ c += CAPABILITY_BUNDLE_ENOUGH_TRUST; else c++; } } return c; } static GabbleCapabilityInfo * capability_info_get (GabblePresenceCache *cache, const gchar *node) { GabblePresenceCachePrivate *priv = cache->priv; GabbleCapabilityInfo *info = g_hash_table_lookup (priv->capabilities, node); if (NULL == info) { info = g_slice_new0 (GabbleCapabilityInfo); info->cap_set = NULL; info->client_types = 0; info->guys = tp_intset_new (); g_hash_table_insert (priv->capabilities, g_strdup (node), info); } return info; } static void capability_info_free (GabbleCapabilityInfo *info) { if (info->cap_set != NULL) { gabble_capability_set_free (info->cap_set); info->cap_set = NULL; } wocky_disco_identity_array_free (info->identities); info->identities = NULL; if (info->data_forms != NULL) g_ptr_array_unref (info->data_forms); info->data_forms = NULL; tp_intset_destroy (info->guys); g_slice_free (GabbleCapabilityInfo, info); } static void replace_data_forms (GabbleCapabilityInfo *info, GPtrArray *data_forms) { if (data_forms == info->data_forms) return; tp_clear_pointer (&info->data_forms, g_ptr_array_unref); if (data_forms != NULL) info->data_forms = g_ptr_array_ref (data_forms); } static guint capability_info_recvd (GabblePresenceCache *cache, const gchar *node, TpHandle handle, GabbleCapabilitySet *cap_set, guint trust_inc, guint client_types, GPtrArray *data_forms) { GabbleCapabilityInfo *info = capability_info_get (cache, node); if (info->cap_set == NULL || !gabble_capability_set_equals (cap_set, info->cap_set)) { /* The caps are not valid, either because we detected inconsistency * between several contacts using the same node (when the hash is not * used), or because this is the first caps report and the caps were * never set. */ tp_intset_clear (info->guys); if (info->cap_set == NULL) info->cap_set = gabble_capability_set_new (); else gabble_capability_set_clear (info->cap_set); gabble_capability_set_update (info->cap_set, cap_set); info->trust = 0; } if (!tp_intset_is_member (info->guys, handle)) { tp_intset_add (info->guys, handle); info->trust += trust_inc; } info->client_types = client_types; replace_data_forms (info, data_forms); return info->trust; } typedef struct { GabblePresenceCache *cache; TpHandle handle; guint timeout_id; const gchar *reason; } DecloakContext; static DecloakContext * decloak_context_new (GabblePresenceCache *cache, TpHandle handle, const gchar *reason) { DecloakContext *dc = g_slice_new0 (DecloakContext); dc->cache = cache; dc->handle = handle; dc->reason = reason; dc->timeout_id = 0; return dc; } static void decloak_context_free (gpointer data) { DecloakContext *dc = data; tp_handle_set_remove (dc->cache->priv->decloak_handles, dc->handle); if (dc->timeout_id != 0) g_source_remove (dc->timeout_id); g_slice_free (DecloakContext, dc); } static void gabble_presence_cache_init (GabblePresenceCache *presence_cache); static GObject * gabble_presence_cache_constructor (GType type, guint n_props, GObjectConstructParam *props); static void gabble_presence_cache_dispose (GObject *object); static void gabble_presence_cache_finalize (GObject *object); static void gabble_presence_cache_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec); static void gabble_presence_cache_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec); static GabblePresence *_cache_insert (GabblePresenceCache *cache, TpHandle handle); static void gabble_presence_cache_porter_available_cb ( GabbleConnection *conn, WockyPorter *porter, gpointer user_data); static void gabble_presence_cache_status_changed_cb (GabbleConnection *, TpConnectionStatus, TpConnectionStatusReason, gpointer); static gboolean _parse_message_message ( WockyPorter *porter, WockyStanza *message, gpointer user_data); static gboolean gabble_presence_cache_presence_cb ( WockyPorter *porter, WockyStanza *message, gpointer user_data); static void gabble_presence_cache_class_init (GabblePresenceCacheClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GParamSpec *param_spec; g_type_class_add_private (object_class, sizeof (GabblePresenceCachePrivate)); object_class->constructor = gabble_presence_cache_constructor; object_class->dispose = gabble_presence_cache_dispose; object_class->finalize = gabble_presence_cache_finalize; object_class->get_property = gabble_presence_cache_get_property; object_class->set_property = gabble_presence_cache_set_property; param_spec = g_param_spec_object ("connection", "GabbleConnection object", "Gabble connection object that owns this presence cache.", GABBLE_TYPE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); signals[PRESENCES_UPDATED] = g_signal_new ( "presences-updated", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, DBUS_TYPE_G_UINT_ARRAY); signals[NICKNAME_UPDATE] = g_signal_new ( "nickname-update", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals[CAPABILITIES_UPDATE] = g_signal_new ( "capabilities-update", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, gabble_marshal_VOID__UINT_POINTER_POINTER, G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_POINTER, G_TYPE_POINTER); signals[AVATAR_UPDATE] = g_signal_new ( "avatar-update", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT_POINTER, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_POINTER); signals[CAPABILITIES_DISCOVERED] = g_signal_new ( "capabilities-discovered", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals[LOCATION_UPDATED] = g_signal_new ( "location-update", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals[UNSURE_PERIOD_ENDED] = g_signal_new ( "unsure-period-ended", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[CLIENT_TYPES_UPDATED] = g_signal_new ( "client-types-updated", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, TP_TYPE_HANDLE); } static gboolean gabble_presence_cache_end_unsure_period (gpointer data) { GabblePresenceCache *self = GABBLE_PRESENCE_CACHE (data); DEBUG ("%p", data); self->priv->unsure_id = 0; g_signal_emit (self, signals[UNSURE_PERIOD_ENDED], 0); return FALSE; } static void gabble_presence_cache_init (GabblePresenceCache *cache) { GabblePresenceCachePrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (cache, GABBLE_TYPE_PRESENCE_CACHE, GabblePresenceCachePrivate); cache->priv = priv; priv->presence = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref); priv->capabilities = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) capability_info_free); priv->disco_pending = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) disco_waiter_list_free); priv->caps_serial = 1; priv->decloak_requests = g_hash_table_new_full (NULL, NULL, NULL, decloak_context_free); priv->location = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_hash_table_unref); } static void gabble_presence_cache_add_bundle_caps (GabblePresenceCache *cache, const gchar *node, const gchar *ns); static void gabble_presence_cache_add_bundles (GabblePresenceCache *cache) { /* We cache the ext='' bundles Gabble advertises: older Gabbles * advertise these and don't support hashed caps, and we shouldn't * need to disco them. */ gabble_presence_cache_add_bundle_caps (cache, NS_GABBLE_CAPS "#" BUNDLE_VOICE_V1, NS_GOOGLE_FEAT_VOICE); gabble_presence_cache_add_bundle_caps (cache, NS_GABBLE_CAPS "#" BUNDLE_VIDEO_V1, NS_GOOGLE_FEAT_VIDEO); gabble_presence_cache_add_bundle_caps (cache, NS_GABBLE_CAPS "#" BUNDLE_SHARE_V1, NS_GOOGLE_FEAT_SHARE); gabble_presence_cache_add_bundle_caps (cache, NS_GABBLE_CAPS "#" BUNDLE_CAMERA_V1, NS_GOOGLE_FEAT_CAMERA); } static GObject * gabble_presence_cache_constructor (GType type, guint n_props, GObjectConstructParam *props) { GObject *obj; GabblePresenceCachePrivate *priv; obj = G_OBJECT_CLASS (gabble_presence_cache_parent_class)-> constructor (type, n_props, props); priv = GABBLE_PRESENCE_CACHE (obj)->priv; g_assert (priv->conn != NULL); g_assert (priv->presence_handles != NULL); g_assert (priv->decloak_handles != NULL); gabble_presence_cache_add_bundles ((GabblePresenceCache *) obj); priv->status_changed_cb = g_signal_connect (priv->conn, "status-changed", G_CALLBACK (gabble_presence_cache_status_changed_cb), obj); tp_g_signal_connect_object (priv->conn, "porter-available", G_CALLBACK (gabble_presence_cache_porter_available_cb), obj, 0); return obj; } static void gabble_presence_cache_dispose (GObject *object) { GabblePresenceCache *self = GABBLE_PRESENCE_CACHE (object); GabblePresenceCachePrivate *priv = self->priv; if (priv->dispose_has_run) return; DEBUG ("dispose called"); priv->dispose_has_run = TRUE; if (priv->unsure_id != 0) { g_source_remove (priv->unsure_id); priv->unsure_id = 0; } tp_clear_pointer (&priv->decloak_requests, g_hash_table_unref); tp_clear_pointer (&priv->decloak_handles, tp_handle_set_destroy); g_assert (priv->message_cb == 0); g_assert (priv->presence_cb == 0); g_signal_handler_disconnect (priv->conn, priv->status_changed_cb); tp_clear_pointer (&priv->presence, g_hash_table_unref); tp_clear_pointer (&priv->capabilities, g_hash_table_unref); tp_clear_pointer (&priv->disco_pending, g_hash_table_unref); tp_clear_pointer (&priv->presence_handles, tp_handle_set_destroy); tp_clear_pointer (&priv->location, g_hash_table_unref); if (G_OBJECT_CLASS (gabble_presence_cache_parent_class)->dispose) G_OBJECT_CLASS (gabble_presence_cache_parent_class)->dispose (object); } static void gabble_presence_cache_finalize (GObject *object) { DEBUG ("called with %p", object); G_OBJECT_CLASS (gabble_presence_cache_parent_class)->finalize (object); } static void gabble_presence_cache_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabblePresenceCache *cache = GABBLE_PRESENCE_CACHE (object); GabblePresenceCachePrivate *priv = cache->priv; switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, priv->conn); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_presence_cache_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabblePresenceCache *cache = GABBLE_PRESENCE_CACHE (object); GabblePresenceCachePrivate *priv = cache->priv; TpHandleRepoIface *contact_repo; switch (property_id) { case PROP_CONNECTION: g_assert (priv->conn == NULL); /* construct-only */ g_assert (priv->presence_handles == NULL); /* construct-only */ g_assert (priv->decloak_handles == NULL); /* construct-only */ priv->conn = g_value_get_object (value); contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); priv->presence_handles = tp_handle_set_new (contact_repo); priv->decloak_handles = tp_handle_set_new (contact_repo); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_presence_cache_porter_available_cb ( GabbleConnection *conn, WockyPorter *porter, gpointer user_data) { GabblePresenceCache *cache = GABBLE_PRESENCE_CACHE (user_data); GabblePresenceCachePrivate *priv = cache->priv; priv->message_cb = wocky_porter_register_handler_from_anyone (porter, WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, WOCKY_PORTER_HANDLER_PRIORITY_MAX, _parse_message_message, cache, NULL); priv->presence_cb = wocky_porter_register_handler_from_anyone (porter, WOCKY_STANZA_TYPE_PRESENCE, WOCKY_STANZA_SUB_TYPE_NONE, WOCKY_PORTER_HANDLER_PRIORITY_MIN, gabble_presence_cache_presence_cb, cache, NULL); } static void gabble_presence_cache_status_changed_cb (GabbleConnection *conn, TpConnectionStatus status, TpConnectionStatusReason reason, gpointer data) { GabblePresenceCache *cache = GABBLE_PRESENCE_CACHE (data); GabblePresenceCachePrivate *priv = cache->priv; g_assert (conn == priv->conn); switch (status) { case TP_CONNECTION_STATUS_CONNECTING: break; case TP_CONNECTION_STATUS_CONNECTED: /* After waiting UNSURE_PERIOD seconds for initial presences to trickle * in, the "unsure period" ends. */ priv->unsure_id = g_timeout_add_seconds (UNSURE_PERIOD, gabble_presence_cache_end_unsure_period, cache); break; case TP_CONNECTION_STATUS_DISCONNECTED: if (conn->session != NULL) { WockyPorter *porter = wocky_session_get_porter (conn->session); if (priv->message_cb != 0) wocky_porter_unregister_handler (porter, priv->message_cb); if (priv->presence_cb != 0) wocky_porter_unregister_handler (porter, priv->presence_cb); priv->message_cb = 0; priv->presence_cb = 0; } break; default: g_assert_not_reached (); } } static GabblePresenceId _presence_node_get_status (WockyNode *pres_node) { const gchar *presence_show = wocky_node_get_content_from_child (pres_node, "show"); if (!presence_show) { /* NODE_DEBUG (pres_node, "empty tag received from server, " "setting presence to available"); */ return GABBLE_PRESENCE_AVAILABLE; } if (0 == strcmp (presence_show, JABBER_PRESENCE_SHOW_AWAY)) return GABBLE_PRESENCE_AWAY; else if (0 == strcmp (presence_show, JABBER_PRESENCE_SHOW_CHAT)) return GABBLE_PRESENCE_CHAT; else if (0 == strcmp (presence_show, JABBER_PRESENCE_SHOW_DND)) return GABBLE_PRESENCE_DND; else if (0 == strcmp (presence_show, JABBER_PRESENCE_SHOW_XA)) return GABBLE_PRESENCE_XA; else { NODE_DEBUG (pres_node, "unrecognised value received from server, " "setting presence to available"); return GABBLE_PRESENCE_AVAILABLE; } } static void _grab_nickname (GabblePresenceCache *cache, TpHandle handle, const gchar *from, WockyNode *node) { const gchar *nickname; GabblePresence *presence; node = wocky_node_get_child_ns (node, "nick", NS_NICK); if (NULL == node) return; presence = gabble_presence_cache_get (cache, handle); if (NULL == presence) return; nickname = node->content; DEBUG ("got nickname \"%s\" for %s", nickname, from); if (tp_strdiff (presence->nickname, nickname)) { g_free (presence->nickname); presence->nickname = g_strdup (nickname); g_signal_emit (cache, signals[NICKNAME_UPDATE], 0, handle); } } static void self_vcard_request_cb (GabbleVCardManager *self, GabbleVCardManagerRequest *request, TpHandle handle, WockyNode *vcard, GError *error, gpointer user_data) { GabblePresenceCache *cache = user_data; GabblePresenceCachePrivate *priv = cache->priv; gchar *sha1 = NULL; priv->avatar_reset_pending = FALSE; if (vcard != NULL) { sha1 = vcard_get_avatar_sha1 (vcard); /* FIXME: presence->avatar_sha1 is resetted in * self_avatar_resolve_conflict() and the following signal set it in * conn-avatars.c. Doing that in 2 different files is confusing. */ g_signal_emit (cache, signals[AVATAR_UPDATE], 0, handle, sha1); g_free (sha1); } DEBUG ("End of avatar conflict resolution"); } static void self_avatar_resolve_conflict (GabblePresenceCache *cache) { GabblePresenceCachePrivate *priv = cache->priv; TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn; GabblePresence *presence = priv->conn->self_presence; GError *error = NULL; if (tp_base_connection_get_status (base_conn) != TP_CONNECTION_STATUS_CONNECTED) { DEBUG ("no longer connected"); return; } /* We don't want recursive image resetting * * FIXME: There is a race here: if the other resource sends us first the * hash 'hash1', and then 'hash2' while the vCard request generated for * 'hash1' is still pending, the current code doesn't send a new vCard * request, although it should because Gabble cannot know whether the reply * will be for hash1 or hash2. The good solution would be to store the * received hash and each time the hash is different, cancel the previous * vCard request and send a new one. However, this is tricky, so we don't * implement it. * * This race is not so bad: the only bad consequence is if the other Jabber * client changes the avatar twice quickly, we may get only the first one. * The real contacts should still get the last avatar. */ if (priv->avatar_reset_pending) { DEBUG ("There is already an avatar conflict resolution pending."); return; } /* according to XEP-0153 section 4.3-2. 3rd bullet: * if we receive a photo from another resource, then we MUST * immediately send a presence update with an empty update child * element (no photo node), then re-download our own vCard; * when that arrives, we may start setting the photo node in our * presence again. */ DEBUG ("Reset our avatar, signal our presence without an avatar and request" " our own vCard."); priv->avatar_reset_pending = TRUE; g_free (presence->avatar_sha1); presence->avatar_sha1 = NULL; if (!conn_presence_signal_own_presence (priv->conn, NULL, &error)) { DEBUG ("failed to send own presence: %s", error->message); g_error_free (error); } gabble_vcard_manager_invalidate_cache (priv->conn->vcard_manager, tp_base_connection_get_self_handle (base_conn)); gabble_vcard_manager_request (priv->conn->vcard_manager, tp_base_connection_get_self_handle (base_conn), 0, self_vcard_request_cb, cache, NULL); } static void _grab_avatar_sha1 (GabblePresenceCache *cache, TpHandle handle, const gchar *from, WockyNode *node) { GabblePresenceCachePrivate *priv = cache->priv; TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn; const gchar *sha1; WockyNode *x_node, *photo_node; GabblePresence *presence; if (handle == tp_base_connection_get_self_handle (base_conn)) presence = priv->conn->self_presence; else presence = gabble_presence_cache_get (cache, handle); if (NULL == presence) return; x_node = wocky_node_get_child_ns (node, "x", NS_VCARD_TEMP_UPDATE); if (NULL == x_node) { /* If (handle == base_conn->self_handle), then this means * that one of our other resources does not support XEP-0153. According * to that XEP, we MUST now stop advertising the image hash, at least * until all instances of non-conforming resources have gone offline, by * setting presence->avatar_sha1 to NULL. * * However, this would mean that logging in (e.g.) with an old version * of Gabble would disable avatars in this newer version, which is * quite a silly failure mode. As a result, we ignore this * requirement and hope that non-conforming clients won't alter the * , which should in practice be true. * * If handle != self_handle, then in any case we want to ignore this * message for vCard purposes. */ return; } photo_node = wocky_node_get_child (x_node, "photo"); /* If there is no photo node, the resource supports XEP-0153, but has * nothing in particular to say about the avatar. */ if (NULL == photo_node) return; sha1 = photo_node->content; /* "" means we know there is no avatar. NULL means we don't know what is the * avatar. In this case, there is a node. */ if (sha1 == NULL) sha1 = ""; if (tp_strdiff (presence->avatar_sha1, sha1)) { if (handle == tp_base_connection_get_self_handle (base_conn)) { DEBUG ("Avatar conflict! Received hash '%s' and our cache is '%s'", sha1, presence->avatar_sha1 == NULL ? "" : presence->avatar_sha1); self_avatar_resolve_conflict (cache); } else if (tp_base_connection_get_status (base_conn) == TP_CONNECTION_STATUS_CONNECTED) { g_free (presence->avatar_sha1); presence->avatar_sha1 = g_strdup (sha1); gabble_vcard_manager_invalidate_cache (priv->conn->vcard_manager, handle); g_signal_emit (cache, signals[AVATAR_UPDATE], 0, handle, sha1); } } } static GSList * _parse_cap_bundles ( WockyNode *lm_node, const gchar **hash, const gchar **ver, const gchar **node) { const gchar *ext; GSList *uris = NULL; WockyNode *cap_node; *hash = NULL; *ver = NULL; cap_node = wocky_node_get_child_ns (lm_node, "c", NS_CAPS); if (NULL == cap_node) return NULL; *hash = wocky_node_get_attribute (cap_node, "hash"); *node = wocky_node_get_attribute (cap_node, "node"); if (NULL == *node) return NULL; *ver = wocky_node_get_attribute (cap_node, "ver"); if (NULL != *ver) uris = g_slist_prepend (uris, g_strdup (*ver)); /* If there is a hash, the remote contact uses XEP-0115 v1.5 and the 'ext' * attribute MUST be ignored. */ if (NULL != *hash) return uris; ext = wocky_node_get_attribute (cap_node, "ext"); if (NULL != ext) { gchar **exts, **i; exts = g_strsplit (ext, " ", 0); for (i = exts; NULL != *i; i++) uris = g_slist_prepend (uris, g_strdup (*i)); g_strfreev (exts); } return uris; } static void _parse_node (GabblePresence *presence, WockyNode *lm_node, const gchar *resource, guint serial) { WockyNode *cap_node; const gchar *node; cap_node = wocky_node_get_child_ns (lm_node, "c", NS_CAPS); if (NULL == cap_node) return; node = wocky_node_get_attribute (cap_node, "node"); if (!tp_strdiff (node, "http://mail.google.com/xmpp/client/caps")) { GabbleCapabilitySet *cap_set = gabble_capability_set_new (); DEBUG ("Client is Google Web Client"); gabble_capability_set_add (cap_set, QUIRK_GOOGLE_WEBMAIL_CLIENT); gabble_capability_set_add (cap_set, QUIRK_OMITS_CONTENT_CREATORS); gabble_presence_set_capabilities (presence, resource, cap_set, NULL, serial); gabble_capability_set_free (cap_set); } if (!tp_strdiff (node, "http://www.android.com/gtalk/client/caps") || !tp_strdiff (node, "http://www.android.com/gtalk/client/caps2")) { GabbleCapabilitySet *cap_set = gabble_capability_set_new (); DEBUG ("Client is Android GTalk Client"); gabble_capability_set_add (cap_set, QUIRK_ANDROID_GTALK_CLIENT); gabble_presence_set_capabilities (presence, resource, cap_set, NULL, serial); gabble_capability_set_free (cap_set); } } static void _caps_disco_cb (GabbleDisco *disco, GabbleDiscoRequest *request, const gchar *jid, const gchar *node, WockyNode *query_result, GError *error, gpointer user_data); static void redisco (GabblePresenceCache *cache, GabbleDisco *disco, DiscoWaiter *waiter, const gchar *node) { const gchar *waiter_jid; gchar *full_jid; waiter_jid = tp_handle_inspect (waiter->repo, waiter->handle); if (waiter->resource != NULL) full_jid = g_strdup_printf ("%s/%s", waiter_jid, waiter->resource); else full_jid = g_strdup (waiter_jid); gabble_disco_request (disco, GABBLE_DISCO_TYPE_INFO, full_jid, node, _caps_disco_cb, cache, G_OBJECT (cache), NULL); waiter->disco_requested = TRUE; g_free (full_jid); } static void disco_failed (GabblePresenceCache *cache, GabbleDisco *disco, const gchar *node, GSList *waiters) { GabblePresenceCachePrivate *priv = cache->priv; GSList *i; DiscoWaiter *waiter = NULL; gchar *full_jid = NULL; for (i = waiters; NULL != i; i = i->next) { waiter = (DiscoWaiter *) i->data; if (!waiter->disco_requested) { redisco (cache, disco, waiter, node); break; } } if (NULL != i) { DEBUG ("sent a retry disco request to %s for URI %s", full_jid, node); } else { /* The contact sends us an error and we don't have any other * contacts to send the discovery request on the same node. We * cannot get the caps for this node. */ DEBUG ("failed to find a suitable candidate to retry disco " "request for URI %s", node); g_hash_table_remove (priv->disco_pending, node); } g_free (full_jid); } static DiscoWaiter * find_matching_waiter (GSList *waiters, TpHandle godot, const gchar *resource) { GSList *i; for (i = waiters; NULL != i; i = i->next) { DiscoWaiter *waiter = i->data; if (waiter->handle == godot && !tp_strdiff (waiter->resource, resource)) return waiter; } return NULL; } static void emit_capabilities_update (GabblePresenceCache *cache, TpHandle handle, const GabbleCapabilitySet *old_cap_set, const GabbleCapabilitySet *new_cap_set) { if (gabble_capability_set_equals (old_cap_set, new_cap_set)) { DEBUG ("no change in caps for handle %u", handle); } else { if (DEBUGGING) { gchar *diff = gabble_capability_set_dump_diff (old_cap_set, new_cap_set, " "); DEBUG ("Emitting caps update for handle %u\n%s", handle, diff); g_free (diff); } g_signal_emit (cache, signals[CAPABILITIES_UPDATE], 0, handle, old_cap_set, new_cap_set); } } /** * set_caps_for: * * Sets caps for @waiter to (@caps, @cap_set), having received * a trusted reply from @responder_{handle,jid}. */ static void set_caps_for (DiscoWaiter *waiter, GabblePresenceCache *cache, GabbleCapabilitySet *cap_set, guint client_types, GPtrArray *data_forms, TpHandle responder_handle, const gchar *responder_jid) { GabblePresence *presence = gabble_presence_cache_get (cache, waiter->handle); GabbleCapabilitySet *old_cap_set; const GabbleCapabilitySet *new_cap_set; if (presence == NULL) return; old_cap_set = gabble_presence_dup_caps (presence); DEBUG ("setting caps for %d (thanks to %d %s)", waiter->handle, responder_handle, responder_jid); gabble_presence_set_capabilities (presence, waiter->resource, cap_set, data_forms, waiter->serial); new_cap_set = gabble_presence_peek_caps (presence); emit_capabilities_update (cache, waiter->handle, old_cap_set, new_cap_set); gabble_capability_set_free (old_cap_set); if (gabble_presence_update_client_types (presence, waiter->resource, client_types)) g_signal_emit (cache, signals[CLIENT_TYPES_UPDATED], 0, waiter->handle); } static void emit_capabilities_discovered (GabblePresenceCache *cache, TpHandle handle) { g_signal_emit (cache, signals[CAPABILITIES_DISCOVERED], 0, handle); } static guint client_types_from_message (TpHandle handle, WockyNode *lm_node, const gchar *resource) { WockyNode *identity, *query_result = (WockyNode *) lm_node; WockyNodeIter iter; guint client_types = 0; /* Find all identity nodes in the result. */ wocky_node_iter_init (&iter, query_result, "identity", NS_DISCO_INFO); while (wocky_node_iter_next (&iter, &identity)) { const gchar *category = wocky_node_get_attribute (identity, "category"); const gchar *type = wocky_node_get_attribute (identity, "type"); guint value; if (category == NULL || type == NULL) continue; /* So, turns out if you disco a specific resource of a gtalk contact, the Google servers will reply with the identity node as if you disco'd the bare jid, so will get something like: which is just great. So, let's special case android phones as their resources will start with "android" and let's just say they're phones. */ if (!tp_strdiff (category, "account") && (resource != NULL && g_str_has_prefix (resource, "android")) && !tp_strdiff (type, "registered")) { client_types |= GABBLE_CLIENT_TYPE_PHONE; } else if (!tp_strdiff (category, "client") && gabble_flag_from_nick (GABBLE_TYPE_CLIENT_TYPE, type, &value)) { DEBUG ("Got type for %u: %s (%u)", handle, type, value); client_types |= value; } } return client_types; } static GPtrArray * data_forms_from_message (WockyNode *node) { GPtrArray *out = g_ptr_array_new_with_free_func (g_object_unref); WockyNodeIter iter; WockyNode *x_node = NULL; wocky_node_iter_init (&iter, node, "x", WOCKY_XMPP_NS_DATA); while (wocky_node_iter_next (&iter, &x_node)) { WockyDataForm *form = wocky_data_form_new_from_node (x_node, NULL); /* we've already parsed the reply to check the hash matches, so * we can already guarantee these data forms will be parsed * fine */ if (G_LIKELY (form != NULL)) g_ptr_array_add (out, form); } return out; } static void _signal_presences_updated (GabblePresenceCache *cache, TpHandle handle) { GArray *handles; handles = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), 1); g_array_append_val (handles, handle); g_signal_emit (cache, signals[PRESENCES_UPDATED], 0, handles); g_array_unref (handles); } static void _caps_disco_cb (GabbleDisco *disco, GabbleDiscoRequest *request, const gchar *jid, const gchar *node, WockyNode *query_result, GError *error, gpointer user_data) { GSList *waiters, *i; DiscoWaiter *waiter_self; GabblePresenceCache *cache; GabblePresenceCachePrivate *priv; TpHandleRepoIface *contact_repo; GabbleCapabilitySet *cap_set; guint trust; TpHandle handle = 0; gboolean bad_hash = FALSE; TpBaseConnection *base_conn; gchar *resource; gboolean jid_is_valid; gpointer key; guint client_types = 0; GPtrArray *data_forms = NULL; cache = GABBLE_PRESENCE_CACHE (user_data); priv = cache->priv; base_conn = TP_BASE_CONNECTION (priv->conn); contact_repo = tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT); if (NULL == node) { DEBUG ("got disco response with NULL node, ignoring"); return; } waiters = g_hash_table_lookup (priv->disco_pending, node); if (NULL != error) { DEBUG ("disco query failed: %s", error->message); disco_failed (cache, disco, node, waiters); return; } handle = tp_handle_ensure (contact_repo, jid, NULL, NULL); if (handle == 0) { DEBUG ("Ignoring presence from invalid JID %s", jid); return; } /* If tp_handle_ensure () was happy with the jid, it's valid. */ jid_is_valid = wocky_decode_jid (jid, NULL, NULL, &resource); g_assert (jid_is_valid); waiter_self = find_matching_waiter (waiters, handle, resource); g_free (resource); if (NULL == waiter_self) { DEBUG ("Ignoring non requested disco reply from %s", jid); return; } /* Now onto caps */ cap_set = gabble_capability_set_new_from_stanza (query_result); client_types = client_types_from_message (handle, query_result, waiter_self->resource); data_forms = data_forms_from_message (query_result); /* Only 'sha-1' is mandatory to implement by XEP-0115. If the remote contact * uses another hash algorithm, don't check the hash and fallback to the old * method. The hash method is not included in the discovery request nor * response but we saved it in disco_pending when we received the presence * stanza. */ if (!tp_strdiff (waiter_self->hash, "sha-1")) { gchar *computed_hash; computed_hash = wocky_caps_hash_compute_from_node (query_result); if (computed_hash == NULL) { DEBUG ("Unable to compute caps hash for '%s'.", jid); trust = 0; bad_hash = TRUE; } else if (g_str_equal (waiter_self->ver, computed_hash)) { trust = capability_info_recvd (cache, node, handle, cap_set, CAPABILITY_BUNDLE_ENOUGH_TRUST, client_types, data_forms); } else { DEBUG ("The verification string '%s' announced by '%s' does not " "match our hash of their disco reply '%s'.", waiter_self->ver, jid, computed_hash); trust = 0; bad_hash = TRUE; } g_free (computed_hash); } else { trust = capability_info_recvd (cache, node, handle, cap_set, 1, client_types, data_forms); } /* Remove the node from the hash table without freeing the key or list of * waiters. * * In the 'enough trust' case, this needs to be done before emitting the * signal, so that when recipients of the capabilities-discovered signal ask * whether we're unsure about the handle, there is no pending disco request * that would make us unsure. * * In the 'not enough trust' branch, we re-use 'key' when updating the table. */ if (!g_hash_table_lookup_extended (priv->disco_pending, node, &key, NULL)) g_assert_not_reached (); g_hash_table_steal (priv->disco_pending, node); if (trust >= CAPABILITY_BUNDLE_ENOUGH_TRUST) { WockyNodeTree *query_node = wocky_node_tree_new_from_node (query_result); WockyCapsCache *caps_cache = wocky_caps_cache_dup_shared (); if (DEBUGGING) { gchar *tmp = gabble_capability_set_dump (cap_set, " "); DEBUG ("trusting %s to mean:\n%s", node, tmp); g_free (tmp); } /* Update external cache. */ wocky_caps_cache_insert (caps_cache, node, query_node); g_object_unref (caps_cache); g_object_unref (query_node); /* We trust this caps node. Serve all its waiters. */ for (i = waiters; NULL != i; i = i->next) { DiscoWaiter *waiter = (DiscoWaiter *) i->data; set_caps_for (waiter, cache, cap_set, client_types, data_forms, handle, jid); emit_capabilities_discovered (cache, waiter->handle); } g_free (key); disco_waiter_list_free (waiters); } else { /* We don't trust this yet (either the hash was bad, or we haven't had * enough responses, as appropriate). */ /* Set caps for the contact that replied (if the hash was correct) and * remove them from the list of waiters. * FIXME I think we should respect the caps, even if the hash is wrong, * for the jid that answered the query. */ if (!bad_hash) { if (DEBUGGING) { gchar *tmp = gabble_capability_set_dump (cap_set, " "); DEBUG ("%s not yet fully trusted to mean:\n%s", node, tmp); g_free (tmp); } set_caps_for (waiter_self, cache, cap_set, client_types, data_forms, handle, jid); } waiters = g_slist_remove (waiters, waiter_self); g_hash_table_insert (priv->disco_pending, key, waiters); emit_capabilities_discovered (cache, waiter_self->handle); disco_waiter_free (waiter_self); /* Ensure that we have enough pending requests to get enough trust for * this node. */ for (i = waiters; i != NULL; i = i->next) { DiscoWaiter *waiter = (DiscoWaiter *) i->data; if (trust + disco_waiter_list_get_request_count (waiters) >= CAPABILITY_BUNDLE_ENOUGH_TRUST) break; if (!waiter->disco_requested) redisco (cache, disco, waiter, node); } } gabble_capability_set_free (cap_set); g_ptr_array_unref (data_forms); } static gboolean get_google_cap (const gchar *fragment, const gchar **ns) { if (!tp_strdiff (fragment, "voice-v1")) { *ns = NS_GOOGLE_FEAT_VOICE; return TRUE; } else if (!tp_strdiff (fragment, "video-v1")) { *ns = NS_GOOGLE_FEAT_VIDEO; return TRUE; } else if (!tp_strdiff (fragment, "share-v1")) { *ns = NS_GOOGLE_FEAT_SHARE; return TRUE; } else if (!tp_strdiff (fragment, "sms-v1")) { *ns = NULL; return TRUE; } else if (!tp_strdiff (fragment, "pmuc-v1")) { *ns = NULL; return TRUE; } else if (!tp_strdiff (fragment, "camera-v1")) { *ns = NULL; return TRUE; } return FALSE; } static void _process_caps_uri (GabblePresenceCache *cache, const gchar *from, const gchar *node, const gchar *fragment, const gchar *hash, const gchar *ver, TpHandle handle, const gchar *resource, guint serial) { GabbleCapabilityInfo *info; WockyNodeTree *cached_query_reply; GabbleCapabilitySet *cached_caps = NULL; GabblePresenceCachePrivate *priv; TpHandleRepoIface *contact_repo; WockyCapsCache *caps_cache; gchar *uri = g_strdup_printf ("%s#%s", node, fragment); const gchar *ns = NULL; priv = cache->priv; contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); info = capability_info_get (cache, uri); caps_cache = wocky_caps_cache_dup_shared (); cached_query_reply = wocky_caps_cache_lookup (caps_cache, uri); if (cached_query_reply != NULL) { WockyNode *query = wocky_node_tree_get_top_node (cached_query_reply); cached_caps = gabble_capability_set_new_from_stanza (query); if (cached_caps == NULL) { gchar *query_str = wocky_node_to_string (query); g_warning ("couldn't re-parse cached query node, which was: %s", query_str); g_free (query_str); } } g_object_unref (caps_cache); if (cached_caps != NULL || info->trust >= CAPABILITY_BUNDLE_ENOUGH_TRUST || tp_intset_is_member (info->guys, handle)) { GabblePresence *presence = gabble_presence_cache_get (cache, handle); GabbleCapabilitySet *cap_set = cached_caps ? cached_caps : info->cap_set; /* we already have enough trust for this node; apply the cached value to * the (handle, resource) */ DEBUG ("enough trust for URI %s, setting caps for %u (%s)", uri, handle, from); if (presence) { guint types; gabble_presence_set_capabilities ( presence, resource, cap_set, info->data_forms, serial); /* We can only get this information from actual disco replies, * so we depend on having this information from the caps cache. */ if (cached_query_reply != NULL) { WockyNode *query = wocky_node_tree_get_top_node (cached_query_reply); types = client_types_from_message (handle, query, resource); } else { types = info->client_types; } if (gabble_presence_update_client_types (presence, resource, types)) g_signal_emit (cache, signals[CLIENT_TYPES_UPDATED], 0, handle); } else DEBUG ("presence not found"); if (cached_caps != NULL) gabble_capability_set_free (cached_caps); } else if (hash == NULL && get_google_cap (fragment, &ns)) { /* if the hash is NULL then are looking at the ext='...' values, * so this is starting to smell like Google */ GabblePresence *presence = gabble_presence_cache_get (cache, handle); /* we already know about this fragment; apply the known value to * the (handle, resource) */ DEBUG ("we know about fragment %s, setting caps for %u (%s)", fragment, handle, from); if (presence != NULL) { GabbleCapabilitySet *cap_set = gabble_capability_set_new (); if (ns != NULL) gabble_capability_set_add (cap_set, ns); gabble_presence_set_capabilities ( presence, resource, cap_set, NULL, serial); gabble_capability_set_free (cap_set); } else { DEBUG ("presence not found"); } } else { GSList *waiters; DiscoWaiter *waiter; guint possible_trust; gboolean found; gpointer key; gpointer value = NULL; DEBUG ("not enough trust for URI %s", uri); /* Are we already waiting for responses for this URI? */ found = g_hash_table_lookup_extended (priv->disco_pending, uri, &key, &value); waiters = (GSList *) value; waiter = find_matching_waiter (waiters, handle, resource); if (waiter != NULL) { /* We've already asked this jid about this node; just update the * serial. */ DEBUG ("updating serial for waiter (%s, %s) from %u to %u", from, uri, waiter->serial, serial); waiter->serial = serial; goto out; } waiter = disco_waiter_new (contact_repo, handle, resource, hash, ver, serial); waiters = g_slist_prepend (waiters, waiter); /* If the URI was already in the hash table, steal it and re-use the same * URI for the following insertion. Otherwise, make a copy of the URI for * use as a key. */ if (found) g_hash_table_steal (priv->disco_pending, key); else key = g_strdup (uri); g_hash_table_insert (priv->disco_pending, key, waiters); /* When all the responses we're waiting for return, will we have enough * trust? */ possible_trust = disco_waiter_list_get_request_count (waiters); if (info->trust + possible_trust < CAPABILITY_BUNDLE_ENOUGH_TRUST) { /* DISCO */ DEBUG ("only %u trust out of %u possible thus far, sending " "disco for URI %s", info->trust + possible_trust, CAPABILITY_BUNDLE_ENOUGH_TRUST, uri); gabble_disco_request (priv->conn->disco, GABBLE_DISCO_TYPE_INFO, from, uri, _caps_disco_cb, cache, G_OBJECT (cache), NULL); /* enough DISCO for you, buddy */ waiter->disco_requested = TRUE; } } out: if (cached_query_reply != NULL) g_object_unref (cached_query_reply); g_free (uri); } static void _process_caps (GabblePresenceCache *cache, GabblePresence *presence, TpHandle handle, const gchar *from, WockyNode *lm_node) { const gchar *resource; GSList *uris, *i; GabblePresenceCachePrivate *priv; GabbleCapabilitySet *old_cap_set = NULL; guint serial; const gchar *hash, *ver, *node; priv = cache->priv; serial = priv->caps_serial++; resource = strchr (from, '/'); if (resource != NULL) resource++; uris = _parse_cap_bundles (lm_node, &hash, &ver, &node); if (presence) { old_cap_set = gabble_presence_dup_caps (presence); _parse_node (presence, lm_node, resource, serial); } /* XEP-0115 §8.4 allows a server to strip out from presences it relays * to a client if it knows that the hasn't changed since the last time * it relayed one for this resource to the client. Thus, the client MUST NOT * expect to get on every , and shouldn't erase previous caps * in that case. * * If the stanza didn't contain a node at all, then there * will be no iterations of this loop, and hence no calls to * gabble_presence_set_capabilities(), and hence the caps will be preserved. * Not pretty, but it seems to work. */ for (i = uris; NULL != i; i = i->next) { _process_caps_uri (cache, from, node, (gchar *) i->data, hash, ver, handle, resource, serial); g_free (i->data); } if (presence) { const GabbleCapabilitySet *new_cap_set = gabble_presence_peek_caps (presence); emit_capabilities_update (cache, handle, old_cap_set, new_cap_set); } else { DEBUG ("No presence for handle %u, not updating caps", handle); } if (old_cap_set != NULL) gabble_capability_set_free (old_cap_set); g_slist_free (uris); } static void presence_cache_check_for_decloak_request ( GabblePresenceCache *cache, WockyStanza *stanza, TpHandle handle, const gchar *from) { GabblePresenceCachePrivate *priv = cache->priv; WockyNode *presence_node = wocky_stanza_get_top_node (stanza); WockyNode *child_node; /* If we receive (directed or broadcast) presence of any sort from someone, * it counts as a reply to any pending de-cloak request we might have been * tracking */ g_hash_table_remove (priv->decloak_requests, GUINT_TO_POINTER (handle)); child_node = wocky_node_get_child_ns (presence_node, "temppres", NS_TEMPPRES); if (child_node != NULL) { gboolean decloak; const gchar *reason; /* this is a request to de-cloak, i.e. leak a minimal version of our * presence to the peer */ g_object_get (priv->conn, "decloak-automatically", &decloak, NULL); reason = wocky_node_get_attribute (child_node, "reason"); if (reason == NULL) reason = ""; DEBUG ("Considering whether to decloak, reason='%s', conclusion=%d", reason, decloak); conn_decloak_emit_requested (priv->conn, handle, reason, decloak); if (decloak) gabble_connection_send_capabilities (priv->conn, from, NULL); } } /* FIXME: in a cruel twist of fate, this is called by GabbleMucChannel! * Presumably this is because the handler priority here is MIN, so WockyMuc * steals the presence stanza before we can scrape our information out of it? */ gboolean gabble_presence_parse_presence_message ( GabblePresenceCache *cache, TpHandle handle, const gchar *from, WockyStanza *message) { GabblePresenceCachePrivate *priv = cache->priv; const gchar *prio; gint8 priority = 0; const gchar *resource, *status_message = NULL; gchar *my_full_jid; WockyNode *presence_node; WockyStanzaSubType sub_type; GabblePresenceId presence_id; GabblePresence *presence; /* The server should not send back the presence stanza about ourself (same * resource). If it does, we just ignore the received stanza. We want to * avoid any infinite ping-pong with the server due to XEP-0153 4.2-2-3. */ my_full_jid = gabble_connection_get_full_jid (priv->conn); if (!tp_strdiff (from, my_full_jid)) { g_free (my_full_jid); return TRUE; } g_free (my_full_jid); presence_node = wocky_stanza_get_top_node (message); g_assert (0 == strcmp (presence_node->name, "presence")); resource = strchr (from, '/'); if (resource != NULL) resource++; presence = gabble_presence_cache_get (cache, handle); if (NULL != presence) /* Once we've received presence from somebody, we don't need to keep the * presence around when it's unavailable. */ presence->keep_unavailable = FALSE; status_message = wocky_node_get_content_from_child (presence_node, "status"); prio = wocky_node_get_content_from_child (presence_node, "priority"); if (prio != NULL) priority = CLAMP (atoi (prio), G_MININT8, G_MAXINT8); presence_cache_check_for_decloak_request (cache, message, handle, from); wocky_stanza_get_type_info (message, NULL, &sub_type); switch (sub_type) { case WOCKY_STANZA_SUB_TYPE_NONE: case WOCKY_STANZA_SUB_TYPE_AVAILABLE: presence_id = _presence_node_get_status (presence_node); gabble_presence_cache_update (cache, handle, resource, presence_id, status_message, priority); if (!presence) presence = gabble_presence_cache_get (cache, handle); _grab_nickname (cache, handle, from, presence_node); _grab_avatar_sha1 (cache, handle, from, presence_node); _process_caps (cache, presence, handle, from, presence_node); return TRUE; case WOCKY_STANZA_SUB_TYPE_ERROR: { GError *error = NULL; gboolean ret; NODE_DEBUG (presence_node, "Received error presence"); ret = wocky_stanza_extract_errors (message, NULL, &error, NULL, NULL); g_assert (ret); /* If there's a in this presence, it's our own echoed back at * us. So we don't want to use that. Instead, we use the if * there is any, or the name of the error condition if not. */ if (tp_str_empty (error->message)) status_message = wocky_enum_to_nick (WOCKY_TYPE_XMPP_ERROR, error->code); else status_message = error->message; gabble_presence_cache_update (cache, handle, resource, GABBLE_PRESENCE_ERROR, status_message, priority); return TRUE; } case WOCKY_STANZA_SUB_TYPE_UNAVAILABLE: if (gabble_roster_handle_sends_presence_to_us (priv->conn->roster, handle)) presence_id = GABBLE_PRESENCE_OFFLINE; else presence_id = GABBLE_PRESENCE_UNKNOWN; gabble_presence_cache_update (cache, handle, resource, presence_id, status_message, priority); return TRUE; default: return FALSE; } } /* FIXME: this scrapes nicknames out of , and relies on im-channel.c * setting keep_unavailable back to FALSE to make nicknames random peers send * us disappear once we close the accompanying messages. As a side effect, it * makes specifying in MUC messages work, which is questionable * behaviour. See vcard/test-alias-message.py. * * It would be cleaner to make the IM channel stash the nickname if we want it * to go away when the channel closes, rather than relying on this * spooky-action-at-a-distance. */ static gboolean _parse_message_message ( WockyPorter *porter, WockyStanza *message, gpointer user_data) { GabblePresenceCache *cache = GABBLE_PRESENCE_CACHE (user_data); GabblePresenceCachePrivate *priv = cache->priv; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); const gchar *from = wocky_stanza_get_from (message); TpHandle handle; WockyStanzaSubType sub_type; WockyNode *node; GabblePresence *presence; if (NULL == from) { STANZA_DEBUG (message, "message without from attribute, ignoring"); return FALSE; } handle = tp_handle_ensure (contact_repo, from, NULL, NULL); if (0 == handle) { STANZA_DEBUG (message, "ignoring message from malformed jid"); return FALSE; } wocky_stanza_get_type_info (message, NULL, &sub_type); switch (sub_type) { case WOCKY_STANZA_SUB_TYPE_NONE: case WOCKY_STANZA_SUB_TYPE_NORMAL: case WOCKY_STANZA_SUB_TYPE_CHAT: case WOCKY_STANZA_SUB_TYPE_GROUPCHAT: break; default: return FALSE; } presence = gabble_presence_cache_get (cache, handle); if (NULL == presence) { presence = _cache_insert (cache, handle); presence->keep_unavailable = TRUE; } node = wocky_stanza_get_top_node (message); _grab_nickname (cache, handle, from, node); return FALSE; } /* * gabble_presence_cache_presence_cb: * * Called by Wocky when we get an incoming . */ static gboolean gabble_presence_cache_presence_cb ( WockyPorter *porter, WockyStanza *message, gpointer user_data) { GabblePresenceCache *cache = GABBLE_PRESENCE_CACHE (user_data); GabblePresenceCachePrivate *priv = cache->priv; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); const char *from = wocky_stanza_get_from (message); TpHandle handle; if (NULL == from) { STANZA_DEBUG (message, "message without from attribute, ignoring"); return FALSE; } handle = tp_handle_ensure (contact_repo, from, NULL, NULL); if (0 == handle) { STANZA_DEBUG (message, "ignoring message from malformed jid"); return FALSE; } return gabble_presence_parse_presence_message (cache, handle, from, message); } GabblePresenceCache * gabble_presence_cache_new (GabbleConnection *conn) { return g_object_new (GABBLE_TYPE_PRESENCE_CACHE, "connection", conn, NULL); } GabblePresence * gabble_presence_cache_get (GabblePresenceCache *cache, TpHandle handle) { GabblePresenceCachePrivate *priv = cache->priv; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); g_assert (tp_handle_is_valid (contact_repo, handle, NULL)); return g_hash_table_lookup (priv->presence, GUINT_TO_POINTER (handle)); } GabblePresence * gabble_presence_cache_get_for_contact ( GabblePresenceCache *cache, WockyContact *contact) { GabblePresenceCachePrivate *priv = cache->priv; TpHandle handle = ensure_handle_from_contact (priv->conn, contact); return g_hash_table_lookup (priv->presence, GUINT_TO_POINTER (handle)); } void gabble_presence_cache_maybe_remove ( GabblePresenceCache *cache, TpHandle handle) { GabblePresenceCachePrivate *priv = cache->priv; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); GabblePresence *presence; presence = gabble_presence_cache_get (cache, handle); if (NULL == presence) return; if ((presence->status == GABBLE_PRESENCE_OFFLINE || presence->status == GABBLE_PRESENCE_UNKNOWN) && presence->status_message == NULL && !presence->keep_unavailable) { const gchar *jid; jid = tp_handle_inspect (contact_repo, handle); DEBUG ("discarding cached presence for unavailable jid %s", jid); g_hash_table_remove (priv->presence, GUINT_TO_POINTER (handle)); tp_handle_set_remove (priv->presence_handles, handle); } } static GabblePresence * _cache_insert ( GabblePresenceCache *cache, TpHandle handle) { GabblePresenceCachePrivate *priv = cache->priv; GabblePresence *presence; presence = gabble_presence_new (); g_hash_table_insert (priv->presence, GUINT_TO_POINTER (handle), presence); tp_handle_set_add (priv->presence_handles, handle); return presence; } static gboolean gabble_presence_cache_do_update ( GabblePresenceCache *cache, TpHandle handle, const gchar *resource, GabblePresenceId presence_id, const gchar *status_message, gint8 priority, gboolean *update_client_types) { GabblePresenceCachePrivate *priv = cache->priv; GabblePresence *presence; GabbleCapabilitySet *old_cap_set; const GabbleCapabilitySet *new_cap_set; gboolean ret = FALSE; if (DEBUGGING) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); const gchar *jid = tp_handle_inspect (contact_repo, handle); const gchar *presence_name = wocky_enum_to_nick ( GABBLE_TYPE_PRESENCE_ID, presence_id); if (presence_name == NULL) presence_name = "plugin-specific, not an element of GabblePresenceId"; DEBUG ("%s (%d) resource %s prio %d presence %d (%s) message \"%s\"", jid, handle, resource == NULL ? "" : resource, priority, presence_id, presence_name, status_message == NULL ? "" : status_message); } presence = gabble_presence_cache_get (cache, handle); if (presence == NULL) presence = _cache_insert (cache, handle); old_cap_set = gabble_presence_dup_caps (presence); ret = gabble_presence_update (presence, resource, presence_id, status_message, priority, update_client_types, time (NULL)); new_cap_set = gabble_presence_peek_caps (presence); emit_capabilities_update (cache, handle, old_cap_set, new_cap_set); gabble_capability_set_free (old_cap_set); return ret; } void gabble_presence_cache_update ( GabblePresenceCache *cache, TpHandle handle, const gchar *resource, GabblePresenceId presence_id, const gchar *status_message, gint8 priority) { gboolean update_client_types = FALSE; if (gabble_presence_cache_do_update (cache, handle, resource, presence_id, status_message, priority, &update_client_types)) { _signal_presences_updated (cache, handle); } if (update_client_types) g_signal_emit (cache, signals[CLIENT_TYPES_UPDATED], 0, handle); gabble_presence_cache_maybe_remove (cache, handle); } void gabble_presence_cache_update_many ( GabblePresenceCache *cache, const GArray *contact_handles, const gchar *resource, GabblePresenceId presence_id, const gchar *status_message, gint8 priority) { GArray *updated; guint i; updated = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), contact_handles->len); for (i = 0 ; i < contact_handles->len ; i++) { TpHandle handle; handle = g_array_index (contact_handles, TpHandle, i); if (gabble_presence_cache_do_update (cache, handle, resource, presence_id, status_message, priority, NULL)) { g_array_append_val (updated, handle); } } if (updated->len > 0) g_signal_emit (cache, signals[PRESENCES_UPDATED], 0, updated); g_array_unref (updated); for (i = 0 ; i < contact_handles->len ; i++) { TpHandle handle; handle = g_array_index (contact_handles, TpHandle, i); gabble_presence_cache_maybe_remove (cache, handle); } } static void gabble_presence_cache_add_bundle_caps (GabblePresenceCache *cache, const gchar *node, const gchar *namespace) { GabbleCapabilityInfo *info; info = capability_info_get (cache, node); /* The caps are immediately valid, because we already know this bundle */ if (info->cap_set == NULL) info->cap_set = gabble_capability_set_new (); info->trust = CAPABILITY_BUNDLE_ENOUGH_TRUST; if (namespace != NULL) gabble_capability_set_add (info->cap_set, namespace); } void gabble_presence_cache_add_own_caps ( GabblePresenceCache *cache, const gchar *ver, const GabbleCapabilitySet *cap_set, const GPtrArray *identities, GPtrArray *data_forms) { gchar *uri = g_strdup_printf ("%s#%s", NS_GABBLE_CAPS, ver); GabbleCapabilityInfo *info = capability_info_get (cache, uri); TpBaseConnection *base_conn = TP_BASE_CONNECTION (cache->priv->conn); if (info->complete) goto out; DEBUG ("caching our own caps (%s)", uri); /* If this node was already in the cache but not labelled as complete, either * the entry's correct, or someone's poisoning us with a SHA-1 collision. * Let's update the entry just in case. */ if (info->cap_set == NULL) { info->cap_set = gabble_capability_set_copy (cap_set); } else { gabble_capability_set_clear (info->cap_set); gabble_capability_set_update (info->cap_set, cap_set); } wocky_disco_identity_array_free (info->identities); info->identities = NULL; if (identities != NULL) info->identities = wocky_disco_identity_array_copy (identities); info->complete = TRUE; info->trust = CAPABILITY_BUNDLE_ENOUGH_TRUST; tp_intset_add (info->guys, tp_base_connection_get_self_handle (base_conn)); replace_data_forms (info, data_forms); /* FIXME: we should satisfy any waiters for this node now. fd.o bug #24619. */ out: g_free (uri); } /** * gabble_presence_cache_peek_own_caps: * @cache: a presence cache * @ver: a verification string or bundle name * * If the capabilities corresponding to @ver have been added to the cache with * gabble_presence_cache_add_own_caps(), returns a set of those capabilities; * otherwise, returns %NULL. * * Since the cache only records features Gabble understands (omitting unknown * features, identities, and data forms), we can only serve up disco replies * from the cache if we know we once advertised exactly this verification * string ourselves. * * Returns: a set of capabilities, if we know exactly what @ver means. */ const GabbleCapabilityInfo * gabble_presence_cache_peek_own_caps ( GabblePresenceCache *cache, const gchar *ver) { gchar *uri = g_strdup_printf ("%s#%s", NS_GABBLE_CAPS, ver); GabbleCapabilityInfo *info = capability_info_get (cache, uri); g_free (uri); if (info->complete) { g_assert (info->cap_set != NULL); return info; } else { return NULL; } } void gabble_presence_cache_really_remove ( GabblePresenceCache *cache, TpHandle handle) { GabblePresenceCachePrivate *priv = cache->priv; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); const gchar *jid; jid = tp_handle_inspect (contact_repo, handle); DEBUG ("forced to discard cached presence for jid %s", jid); g_hash_table_remove (priv->presence, GUINT_TO_POINTER (handle)); tp_handle_set_remove (priv->presence_handles, handle); } void gabble_presence_cache_contacts_added_to_olpc_view (GabblePresenceCache *self, TpHandleSet *handles) { GArray *tmp, *changed; guint i; tmp = tp_handle_set_to_array (handles); changed = g_array_new (FALSE, FALSE, sizeof (TpHandle)); for (i = 0; i < tmp->len; i++) { TpHandle handle; GabblePresence *presence; handle = g_array_index (tmp, TpHandle, i); presence = gabble_presence_cache_get (self, handle); if (presence == NULL) { presence = _cache_insert (self, handle); } if (gabble_presence_added_to_view (presence)) { g_array_append_val (changed, handle); } } if (changed->len > 0) { g_signal_emit (self, signals[PRESENCES_UPDATED], 0, changed); } g_array_unref (tmp); g_array_unref (changed); } void gabble_presence_cache_contacts_removed_from_olpc_view ( GabblePresenceCache *self, TpHandleSet *handles) { GArray *tmp, *changed; guint i; tmp = tp_handle_set_to_array (handles); changed = g_array_new (FALSE, FALSE, sizeof (TpHandle)); for (i = 0; i < tmp->len; i++) { TpHandle handle; GabblePresence *presence; handle = g_array_index (tmp, TpHandle, i); presence = gabble_presence_cache_get (self, handle); if (presence == NULL) { presence = _cache_insert (self, handle); } if (gabble_presence_removed_from_view (presence)) { g_array_append_val (changed, handle); gabble_presence_cache_maybe_remove (self, handle); } } if (changed->len > 0) { g_signal_emit (self, signals[PRESENCES_UPDATED], 0, changed); } g_array_unref (tmp); g_array_unref (changed); } static gboolean gabble_presence_cache_caps_pending (GabblePresenceCache *cache, TpHandle handle) { GabblePresenceCachePrivate *priv = cache->priv; GList *uris, *li; uris = g_hash_table_get_values (priv->disco_pending); for (li = uris; li != NULL; li = li->next) { GSList *waiters; for (waiters = li->data; waiters != NULL; waiters = waiters->next) { DiscoWaiter *w = waiters->data; if (w->handle == handle) { g_list_free (uris); return TRUE; } } } g_list_free (uris); return FALSE; } /* Return whether we're "unsure" about the capabilities of @handle. * Currently, this means either of: * * - we've connected within the last UNSURE_PERIOD seconds and haven't * received presence for @handle yet * - we know what @handle's caps hash/bundles are, but we're still * performing service discovery to find out what they mean */ gboolean gabble_presence_cache_is_unsure (GabblePresenceCache *cache, TpHandle handle) { GabblePresenceCachePrivate *priv = cache->priv; TpBaseConnection *base_conn = TP_BASE_CONNECTION (priv->conn); /* we might not have had any presence at all - if we're not connected yet, or * are still in the "unsure period", assume we might get initial presence * soon. * * Presences with keep_unavailable are the result of caching someone's * nick from stanzas, so they don't count as real presence - if * someone sends us a , their presence might still follow. */ if (tp_base_connection_get_status (base_conn) != TP_CONNECTION_STATUS_CONNECTED || priv->unsure_id != 0) { GabblePresence *presence = gabble_presence_cache_get (cache, handle); if (presence == NULL || presence->keep_unavailable) { DEBUG ("No presence for %u yet, still waiting for possible initial " "presence burst", handle); return TRUE; } } /* FIXME: if we've had the roster, we can be sure that people who're * not in it won't be sending us an initial presence, so ideally the * above should be roster-aware? */ /* if we don't know what the caps mean, we're unsure */ if (gabble_presence_cache_caps_pending (cache, handle)) { DEBUG ("Still working out what %u's caps hash means", handle); return TRUE; } /* if we're waiting for a de-cloak response, we're unsure */ if (tp_handle_set_is_member (priv->decloak_handles, handle)) { DEBUG ("Waiting to see if %u will decloak", handle); return TRUE; } DEBUG ("No, I'm sure about %u by now", handle); return FALSE; } static gboolean gabble_presence_cache_decloak_timeout_cb (gpointer data) { DecloakContext *dc = data; GabblePresenceCache *self = dc->cache; TpHandle handle = dc->handle; DEBUG ("De-cloak request for %u timed out", handle); /* This frees @dc, do not dereference it afterwards. This needs to be done * before emitting the signal, so that when recipients of the channel ask * whether we're unsure about the handle, there is no pending decloak * request that would make us unsure. */ g_hash_table_remove (self->priv->decloak_requests, GUINT_TO_POINTER (handle)); /* As a side-effect of freeing @dc, this should have happened. */ g_assert (!tp_handle_set_is_member (self->priv->decloak_handles, handle)); /* FIXME: this is an abuse of this signal, but it serves the same * purpose: poking any pending media channels to tell them that @handle * might have left the "unsure" state */ emit_capabilities_discovered (self, handle); return FALSE; } /* @reason must be a statically-allocated string. */ gboolean gabble_presence_cache_request_decloaking (GabblePresenceCache *self, TpHandle handle, const gchar *reason) { DecloakContext *dc; GabblePresence *presence; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_CONTACT); presence = gabble_presence_cache_get (self, handle); if (presence != NULL && presence->status != GABBLE_PRESENCE_OFFLINE && presence->status != GABBLE_PRESENCE_UNKNOWN) { DEBUG ("We know that this contact is online, no point asking for " "decloak"); return FALSE; } /* if we've already asked them to de-cloak for the same reason, do nothing */ if (tp_handle_set_is_member (self->priv->decloak_handles, handle)) { dc = g_hash_table_lookup (self->priv->decloak_requests, GUINT_TO_POINTER (handle)); if (dc != NULL && !tp_strdiff (reason, dc->reason)) { DEBUG ("Already asked %u to decloak for reason '%s'", handle, reason); return TRUE; } } DEBUG ("Asking %u to decloak", handle); dc = decloak_context_new (self, handle, reason); dc->timeout_id = g_timeout_add_seconds (DECLOAK_PERIOD, gabble_presence_cache_decloak_timeout_cb, dc); g_hash_table_insert (self->priv->decloak_requests, GUINT_TO_POINTER (handle), dc); tp_handle_set_add (self->priv->decloak_handles, handle); gabble_connection_request_decloak (self->priv->conn, tp_handle_inspect (contact_repo, handle), reason, NULL); return TRUE; } void gabble_presence_cache_update_location (GabblePresenceCache *cache, TpHandle handle, GHashTable *new_location) { GabblePresenceCachePrivate *priv = cache->priv; g_hash_table_insert (priv->location, GUINT_TO_POINTER (handle), new_location); g_signal_emit (cache, signals[LOCATION_UPDATED], 0, handle); } /* The return value should be g_hash_table_unref'ed. */ GHashTable * gabble_presence_cache_get_location (GabblePresenceCache *cache, TpHandle handle) { GabblePresenceCachePrivate *priv = cache->priv; GHashTable *location = NULL; location = g_hash_table_lookup (priv->location, GUINT_TO_POINTER (handle)); if (location != NULL) { g_hash_table_ref (location); return location; } return NULL; } gboolean gabble_presence_cache_disco_in_progress (GabblePresenceCache *cache, TpHandle handle, const gchar *resource) { GabblePresenceCachePrivate *priv = cache->priv; GList *l, *waiter_list; gboolean in_progress = FALSE; waiter_list = g_hash_table_get_values (priv->disco_pending); for (l = waiter_list; !in_progress && l != NULL; l = l->next) { GList *j; for (j = l->data; !in_progress && j != NULL; j = j->next) { DiscoWaiter *w = j->data; if (w != NULL && w->handle == handle && !tp_strdiff (w->resource, resource)) in_progress = TRUE; } } g_list_free (waiter_list); return in_progress; } TpHandle gabble_presence_cache_get_handle (GabblePresenceCache *cache, GabblePresence *presence) { GHashTableIter iter; gpointer key, val; g_hash_table_iter_init (&iter, cache->priv->presence); while (g_hash_table_iter_next (&iter, &key, &val)) { if (presence == val) return GPOINTER_TO_UINT (key); } return 0; } telepathy-gabble-0.18.3/src/conn-aliasing.h0000664000175000017500000000274612332441362021671 0ustar00cassidycassidy00000000000000/* * conn-aliasing.h - Header for Gabble connection aliasing interface * Copyright (C) 2005-2007 Collabora Ltd. * Copyright (C) 2005-2007 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __CONN_ALIASING_H__ #define __CONN_ALIASING_H__ #include #include "connection.h" G_BEGIN_DECLS void conn_aliasing_init (GabbleConnection *conn); void conn_aliasing_iface_init (gpointer g_iface, gpointer iface_data); void gabble_conn_aliasing_nickname_updated (GObject *object, TpHandle handle, gpointer user_data); void gabble_conn_aliasing_nicknames_updated (GObject *object, GArray *handles, gpointer user_data); GabbleConnectionAliasSource _gabble_connection_get_cached_alias ( GabbleConnection *, TpHandle, gchar **); G_END_DECLS #endif /* __CONN_ALIASING_H__ */ telepathy-gabble-0.18.3/src/call-member.h0000664000175000017500000000655312223562023021324 0ustar00cassidycassidy00000000000000/* * call-member.h - Header for CallMember * Copyright (C) 2010 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_CALL_MEMBER_H__ #define __GABBLE_CALL_MEMBER_H__ #include #include #include #include "types.h" #include "call-member-content.h" G_BEGIN_DECLS typedef struct _GabbleCallMemberPrivate GabbleCallMemberPrivate; typedef struct _GabbleCallMemberClass GabbleCallMemberClass; struct _GabbleCallMemberClass { GObjectClass parent_class; }; struct _GabbleCallMember { GObject parent; GabbleCallMemberPrivate *priv; }; GType gabble_call_member_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_CALL_MEMBER \ (gabble_call_member_get_type ()) #define GABBLE_CALL_MEMBER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_CALL_MEMBER, \ GabbleCallMember)) #define GABBLE_CALL_MEMBER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_CALL_MEMBER, \ GabbleCallMemberClass)) #define GABBLE_IS_CALL_MEMBER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_CALL_MEMBER)) #define GABBLE_IS_CALL_MEMBER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_CALL_MEMBER)) #define GABBLE_CALL_MEMBER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_CALL_MEMBER, \ GabbleCallMemberClass)) void gabble_call_member_set_session (GabbleCallMember *member, WockyJingleSession *session); TpHandle gabble_call_member_get_handle ( GabbleCallMember *self); WockyJingleSession *gabble_call_member_get_session ( GabbleCallMember *self); TpCallMemberFlags gabble_call_member_get_flags ( GabbleCallMember *self); GList *gabble_call_member_get_contents (GabbleCallMember *self); GabbleCallMemberContent * gabble_call_member_ensure_content ( GabbleCallMember *self, const gchar *name, WockyJingleMediaType mtype); GabbleCallMemberContent * gabble_call_member_create_content ( GabbleCallMember *self, const gchar *name, WockyJingleMediaType mtype, WockyJingleContentSenders senders, GError **error); gboolean gabble_call_member_start_session (GabbleCallMember *self, const gchar *audio_name, const gchar *video_name, GError **error); gboolean gabble_call_member_open_session (GabbleCallMember *self, GError **error); void gabble_call_member_accept (GabbleCallMember *self); GabbleConnection * gabble_call_member_get_connection (GabbleCallMember *self); const gchar *gabble_call_member_get_transport_ns (GabbleCallMember *self); void gabble_call_member_shutdown (GabbleCallMember *self); G_END_DECLS #endif /* #ifndef __GABBLE_CALL_MEMBER_H__*/ telepathy-gabble-0.18.3/src/muc-factory.h0000664000175000017500000000520412223562023021365 0ustar00cassidycassidy00000000000000/* * muc-factory.h - Header for GabbleMucFactory * Copyright (C) 2006 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __MUC_FACTORY_H__ #define __MUC_FACTORY_H__ #include "config.h" #include #include #include "bytestream-iface.h" #include "types.h" G_BEGIN_DECLS typedef struct _GabbleMucFactory GabbleMucFactory; typedef struct _GabbleMucFactoryClass GabbleMucFactoryClass; typedef struct _GabbleMucFactoryPrivate GabbleMucFactoryPrivate; struct _GabbleMucFactoryClass { GObjectClass parent_class; }; struct _GabbleMucFactory { GObject parent; GabbleMucFactoryPrivate *priv; }; GType gabble_muc_factory_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_MUC_FACTORY \ (gabble_muc_factory_get_type ()) #define GABBLE_MUC_FACTORY(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_MUC_FACTORY, \ GabbleMucFactory)) #define GABBLE_MUC_FACTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_MUC_FACTORY, \ GabbleMucFactoryClass)) #define GABBLE_IS_MUC_FACTORY(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_MUC_FACTORY)) #define GABBLE_IS_MUC_FACTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_MUC_FACTORY)) #define GABBLE_MUC_FACTORY_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_MUC_FACTORY, \ GabbleMucFactoryClass)) GabbleMucChannel *gabble_muc_factory_find_text_channel (GabbleMucFactory *self, TpHandle handle); void gabble_muc_factory_handle_si_stream_request (GabbleMucFactory *self, GabbleBytestreamIface *bytestream, TpHandle room_handle, const gchar *stream_id, WockyStanza *msg); void gabble_muc_factory_broadcast_presence (GabbleMucFactory *self); #ifdef ENABLE_VOIP gboolean gabble_muc_factory_handle_jingle_session (GabbleMucFactory *self, WockyJingleSession *session); #endif G_END_DECLS #endif /* #ifndef __MUC_FACTORY_H__ */ telepathy-gabble-0.18.3/src/bytestream-factory.h0000664000175000017500000001013512223562023022757 0ustar00cassidycassidy00000000000000/* * bytestream-factory.h - Header for GabbleBytestreamFactory * Copyright (C) 2007 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __BYTESTREAM_FACTORY_H__ #define __BYTESTREAM_FACTORY_H__ #include #include #include "types.h" #include "bytestream-iface.h" #include "bytestream-ibb.h" #include "bytestream-muc.h" #include "bytestream-multiple.h" #include "bytestream-socks5.h" #include "connection.h" G_BEGIN_DECLS typedef struct _GabbleBytestreamFactoryClass GabbleBytestreamFactoryClass; typedef struct _GabbleBytestreamFactoryPrivate GabbleBytestreamFactoryPrivate; struct _GabbleBytestreamFactoryClass { GObjectClass parent_class; }; struct _GabbleBytestreamFactory { GObject parent; GabbleBytestreamFactoryPrivate *priv; }; GType gabble_bytestream_factory_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_BYTESTREAM_FACTORY \ (gabble_bytestream_factory_get_type ()) #define GABBLE_BYTESTREAM_FACTORY(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_BYTESTREAM_FACTORY,\ GabbleBytestreamFactory)) #define GABBLE_BYTESTREAM_FACTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_BYTESTREAM_FACTORY,\ GabbleBytestreamFactoryClass)) #define GABBLE_IS_BYTESTREAM_FACTORY(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_BYTESTREAM_FACTORY)) #define GABBLE_IS_BYTESTREAM_FACTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_BYTESTREAM_FACTORY)) #define GABBLE_BYTESTREAM_FACTORY_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_BYTESTREAM_FACTORY,\ GabbleBytestreamFactoryClass)) typedef struct { gchar *jid; gchar *host; guint16 port; } GabbleSocks5Proxy; typedef void (* GabbleBytestreamFactoryNegotiateReplyFunc) ( GabbleBytestreamIface *bytestream, WockyStanza *msg, GObject *object, gpointer user_data); GabbleBytestreamFactory *gabble_bytestream_factory_new ( GabbleConnection *conn); GabbleBytestreamMuc *gabble_bytestream_factory_create_muc ( GabbleBytestreamFactory *fac, TpHandle peer_handle, const gchar *stream_id, GabbleBytestreamState state); GabbleBytestreamIface *gabble_bytestream_factory_create_from_method ( GabbleBytestreamFactory *self, const gchar *stream_method, TpHandle peer_handle, const gchar *stream_id, const gchar *stream_init_id, const gchar *peer_resource, const gchar *self_jid, GabbleBytestreamState state); WockyStanza *gabble_bytestream_factory_make_stream_init_iq ( const gchar *full_jid, const gchar *stream_id, const gchar *profile); WockyStanza *gabble_bytestream_factory_make_accept_iq (const gchar *full_jid, const gchar *stream_init_id, const gchar *stream_method); WockyStanza *gabble_bytestream_factory_make_multi_accept_iq ( const gchar *full_jid, const gchar *stream_init_id, GList *stream_methods); void gabble_bytestream_factory_negotiate_stream ( GabbleBytestreamFactory *fac, WockyStanza *msg, const gchar *stream_id, GabbleBytestreamFactoryNegotiateReplyFunc func, gpointer user_data, GObject *object); gchar *gabble_bytestream_factory_generate_stream_id (void); GSList *gabble_bytestream_factory_get_socks5_proxies ( GabbleBytestreamFactory *self); void gabble_bytestream_factory_query_socks5_proxies ( GabbleBytestreamFactory *self); G_END_DECLS #endif /* #ifndef __BYTESTREAM_FACTORY_H__ */ telepathy-gabble-0.18.3/src/media-channel.c0000664000175000017500000030044112332441362021620 0ustar00cassidycassidy00000000000000/* * gabble-media-channel.c - Source for GabbleMediaChannel * Copyright (C) 2006 Collabora Ltd. * Copyright (C) 2006 Nokia Corporation * @author Ole Andre Vadla Ravnaas * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "media-channel.h" #include "media-channel-internal.h" #include #include #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_MEDIA #include "connection.h" #include "debug.h" #include "jingle-tp-util.h" #include "media-factory.h" #include "media-stream.h" #include "namespaces.h" #include "presence-cache.h" #include "presence.h" #include "util.h" #define MAX_STREAMS 99 static void channel_iface_init (gpointer, gpointer); static void dtmf_iface_init (gpointer, gpointer); static void media_signalling_iface_init (gpointer, gpointer); static void streamed_media_iface_init (gpointer, gpointer); static void session_handler_iface_init (gpointer, gpointer); G_DEFINE_TYPE_WITH_CODE (GabbleMediaChannel, gabble_media_channel, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_CALL_STATE, gabble_media_channel_call_state_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_DTMF, dtmf_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP, tp_group_mixin_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_HOLD, gabble_media_channel_hold_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_MEDIA_SIGNALLING, media_signalling_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_STREAMED_MEDIA, streamed_media_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_PROPERTIES_INTERFACE, tp_properties_mixin_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, tp_dbus_properties_mixin_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_EXPORTABLE_CHANNEL, NULL); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_MEDIA_SESSION_HANDLER, session_handler_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL)); static const gchar *gabble_media_channel_interfaces[] = { TP_IFACE_CHANNEL_INTERFACE_CALL_STATE, TP_IFACE_CHANNEL_INTERFACE_DTMF, TP_IFACE_CHANNEL_INTERFACE_GROUP, TP_IFACE_CHANNEL_INTERFACE_HOLD, TP_IFACE_CHANNEL_INTERFACE_MEDIA_SIGNALLING, TP_IFACE_PROPERTIES_INTERFACE, TP_IFACE_MEDIA_SESSION_HANDLER, NULL }; /* properties */ enum { PROP_OBJECT_PATH = 1, PROP_CHANNEL_TYPE, PROP_HANDLE_TYPE, PROP_HANDLE, PROP_TARGET_ID, PROP_INITIAL_PEER, PROP_PEER_IN_RP, PROP_PEER, PROP_REQUESTED, PROP_CONNECTION, PROP_CREATOR, PROP_CREATOR_ID, PROP_INTERFACES, PROP_CHANNEL_DESTROYED, PROP_CHANNEL_PROPERTIES, PROP_INITIAL_AUDIO, PROP_INITIAL_VIDEO, PROP_IMMUTABLE_STREAMS, PROP_CURRENTLY_SENDING_TONES, PROP_INITIAL_TONES, PROP_DEFERRED_TONES, /* TP properties (see also below) */ PROP_NAT_TRAVERSAL, PROP_STUN_SERVER, PROP_STUN_PORT, PROP_GTALK_P2P_RELAY_TOKEN, PROP_SESSION, LAST_PROPERTY }; /* TP properties */ enum { CHAN_PROP_NAT_TRAVERSAL = 0, CHAN_PROP_STUN_SERVER, CHAN_PROP_STUN_PORT, CHAN_PROP_GTALK_P2P_RELAY_TOKEN, NUM_CHAN_PROPS, INVALID_CHAN_PROP }; const TpPropertySignature channel_property_signatures[NUM_CHAN_PROPS] = { { "nat-traversal", G_TYPE_STRING }, { "stun-server", G_TYPE_STRING }, { "stun-port", G_TYPE_UINT }, { "gtalk-p2p-relay-token", G_TYPE_STRING } }; typedef struct { GabbleMediaChannel *self; WockyJingleContent *content; gulong removed_id; gchar *name; const gchar *nat_traversal; gboolean initial; } StreamCreationData; struct _delayed_request_streams_ctx { GabbleMediaChannel *chan; gulong caps_disco_id; gulong unsure_period_ended_id; guint contact_handle; GArray *types; GFunc succeeded_cb; GFunc failed_cb; gpointer context; }; static void destroy_request (struct _delayed_request_streams_ctx *ctx, gpointer user_data); static void tones_deferred_cb (GabbleMediaChannel *self, const gchar *tones, TpDTMFPlayer *dtmf_player) { DEBUG ("waiting for user to continue sending '%s'", tones); g_free (self->priv->deferred_tones); self->priv->deferred_tones = g_strdup (tones); tp_svc_channel_interface_dtmf_emit_tones_deferred (self, tones); } static void gabble_media_channel_init (GabbleMediaChannel *self) { GabbleMediaChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_MEDIA_CHANNEL, GabbleMediaChannelPrivate); self->priv = priv; priv->next_stream_id = 1; priv->delayed_request_streams = g_ptr_array_sized_new (1); priv->streams = g_ptr_array_sized_new (1); /* initialize properties mixin */ tp_properties_mixin_init (G_OBJECT (self), G_STRUCT_OFFSET ( GabbleMediaChannel, properties)); priv->dtmf_player = tp_dtmf_player_new (); tp_g_signal_connect_object (priv->dtmf_player, "finished", G_CALLBACK (tp_svc_channel_interface_dtmf_emit_stopped_tones), self, G_CONNECT_SWAPPED); tp_g_signal_connect_object (priv->dtmf_player, "tones-deferred", G_CALLBACK (tones_deferred_cb), self, G_CONNECT_SWAPPED); } static void session_state_changed_cb (WockyJingleSession *session, GParamSpec *arg1, GabbleMediaChannel *channel); static void session_terminated_cb (WockyJingleSession *session, gboolean local_terminator, WockyJingleReason reason, const gchar *text, gpointer user_data); static void session_new_content_cb (WockyJingleSession *session, WockyJingleContent *c, gpointer user_data); static void create_stream_from_content (GabbleMediaChannel *chan, WockyJingleContent *c, gboolean initial); static gboolean contact_is_media_capable (GabbleMediaChannel *chan, TpHandle peer, gboolean *wait, GError **error); static void stream_creation_data_cancel (gpointer p, gpointer unused); static void session_content_rejected_cb (WockyJingleSession *session, WockyJingleContent *c, WockyJingleReason reason, const gchar *message, gpointer user_data); static void create_initial_streams (GabbleMediaChannel *chan) { GabbleMediaChannelPrivate *priv = chan->priv; GList *contents, *li; contents = wocky_jingle_session_get_contents (priv->session); for (li = contents; li; li = li->next) { WockyJingleContent *c = li->data; /* I'm so sorry. */ if (G_OBJECT_TYPE (c) == WOCKY_TYPE_JINGLE_MEDIA_RTP) { guint media_type; g_object_get (c, "media-type", &media_type, NULL); switch (media_type) { case WOCKY_JINGLE_MEDIA_TYPE_AUDIO: priv->initial_audio = TRUE; break; case WOCKY_JINGLE_MEDIA_TYPE_VIDEO: priv->initial_video = TRUE; break; default: /* smell? */ DEBUG ("unknown rtp media type %u", media_type); } } else { g_assert_not_reached (); } create_stream_from_content (chan, c, TRUE); } DEBUG ("initial_audio: %s, initial_video: %s", priv->initial_audio ? "true" : "false", priv->initial_video ? "true" : "false"); g_list_free (contents); } static void _latch_to_session (GabbleMediaChannel *chan) { GabbleMediaChannelPrivate *priv = chan->priv; g_assert (priv->session != NULL); DEBUG ("%p: Latching onto session %p", chan, priv->session); g_signal_connect (priv->session, "notify::state", (GCallback) session_state_changed_cb, chan); g_signal_connect (priv->session, "new-content", (GCallback) session_new_content_cb, chan); g_signal_connect (priv->session, "terminated", (GCallback) session_terminated_cb, chan); g_signal_connect (priv->session, "content-rejected", (GCallback) session_content_rejected_cb, chan); gabble_media_channel_hold_latch_to_session (chan); g_assert (priv->streams->len == 0); tp_svc_channel_interface_media_signalling_emit_new_session_handler ( G_OBJECT (chan), priv->object_path, "rtp"); } static void create_session (GabbleMediaChannel *chan, const gchar *jid, WockyJingleDialect dialect) { GabbleMediaChannelPrivate *priv = chan->priv; gboolean local_hold = (priv->hold_state != TP_LOCAL_HOLD_STATE_UNHELD); WockyJingleFactory *jf; g_assert (priv->session == NULL); DEBUG ("%p: Creating new outgoing session", chan); jf = gabble_jingle_mint_get_factory (priv->conn->jingle_mint); g_return_if_fail (jf != NULL); priv->session = g_object_ref ( wocky_jingle_factory_create_session (jf, jid, dialect, local_hold)); _latch_to_session (chan); } static GObject * gabble_media_channel_constructor (GType type, guint n_props, GObjectConstructParam *props) { GObject *obj; GabbleMediaChannelPrivate *priv; TpBaseConnection *conn; TpDBusDaemon *bus; TpIntset *set; TpHandleRepoIface *contact_handles; WockyJingleInfo *ji; const gchar *relay_token; GList *stun_servers; obj = G_OBJECT_CLASS (gabble_media_channel_parent_class)-> constructor (type, n_props, props); priv = GABBLE_MEDIA_CHANNEL (obj)->priv; conn = (TpBaseConnection *) priv->conn; contact_handles = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT); /* register object on the bus */ bus = tp_base_connection_get_dbus_daemon (conn); tp_dbus_daemon_register_object (bus, priv->object_path, obj); tp_group_mixin_init (obj, G_STRUCT_OFFSET (GabbleMediaChannel, group), contact_handles, tp_base_connection_get_self_handle (conn)); if (priv->session != NULL) { priv->peer = ensure_handle_from_contact (priv->conn, wocky_jingle_session_get_peer_contact (priv->session)); g_return_val_if_fail (priv->peer != 0, NULL); priv->creator = priv->peer; } else { priv->creator = tp_base_connection_get_self_handle (conn); } /* automatically add creator to channel, but also ref them again (because * priv->creator is the InitiatorHandle) */ g_assert (priv->creator != 0); set = tp_intset_new_containing (priv->creator); tp_group_mixin_change_members (obj, "", set, NULL, NULL, NULL, 0, TP_CHANNEL_GROUP_CHANGE_REASON_NONE); tp_intset_destroy (set); /* We implement the 0.17.6 properties correctly, and can include a message * when ending a call. */ tp_group_mixin_change_flags (obj, TP_CHANNEL_GROUP_FLAG_PROPERTIES | TP_CHANNEL_GROUP_FLAG_MESSAGE_REMOVE | TP_CHANNEL_GROUP_FLAG_MESSAGE_REJECT | TP_CHANNEL_GROUP_FLAG_MESSAGE_RESCIND, 0); /* Set up Google relay related properties */ ji = gabble_jingle_mint_get_info (priv->conn->jingle_mint); stun_servers = wocky_jingle_info_get_stun_servers (ji); if (stun_servers != NULL) { WockyStunServer *stun_server = stun_servers->data; g_object_set (obj, "stun-server", stun_server->address, "stun-port", (guint) stun_server->port, NULL); g_list_free (stun_servers); } relay_token = wocky_jingle_info_get_google_relay_token (ji); if (relay_token != NULL) { g_object_set (obj, "gtalk-p2p-relay-token", relay_token, NULL); } if (priv->session != NULL) { /* This is an incoming call; make us local pending and don't set any * group flags (all we can do is add or remove ourselves, which is always * valid per the spec) */ set = tp_intset_new_containing (tp_base_connection_get_self_handle (conn)); tp_group_mixin_change_members (obj, "", NULL, NULL, set, NULL, priv->peer, TP_CHANNEL_GROUP_CHANGE_REASON_INVITED); tp_intset_destroy (set); /* Set up signal callbacks, emit session handler, initialize streams, * figure out InitialAudio and InitialVideo */ _latch_to_session (GABBLE_MEDIA_CHANNEL (obj)); create_initial_streams (GABBLE_MEDIA_CHANNEL (obj)); } else { /* This is an outgoing call. */ if (priv->initial_peer != 0) { if (priv->peer_in_rp) { /* This channel was created with RequestChannel(SM, Contact, h) * so the peer should start out in remote pending. */ set = tp_intset_new_containing (priv->initial_peer); tp_group_mixin_change_members (obj, "", NULL, NULL, NULL, set, tp_base_connection_get_self_handle (conn), TP_CHANNEL_GROUP_CHANGE_REASON_INVITED); tp_intset_destroy (set); } /* else this channel was created with CreateChannel or EnsureChannel, * so don't. */ } else { /* This channel was created with RequestChannel(SM, None, 0). */ /* The peer can't be in remote pending */ g_assert (!priv->peer_in_rp); /* The UI may call AddMembers([h], "") before calling * RequestStreams(h, [...]). */ tp_group_mixin_change_flags (obj, TP_CHANNEL_GROUP_FLAG_CAN_ADD, 0); } } /* If this is a Google session, let's set ImmutableStreams */ if (priv->session != NULL) { priv->immutable_streams = !wocky_jingle_session_can_modify_contents (priv->session); } /* If there's no session yet, but we know who the peer will be, and we have * presence for them, we can set ImmutableStreams using the same algorithm as * for old-style capabilities. If we don't know who the peer will be, then * the client is using an old calling convention and doesn't need to know * this. */ else if (priv->initial_peer != 0) { GabblePresence *presence = gabble_presence_cache_get ( priv->conn->presence_cache, priv->initial_peer); TpChannelMediaCapabilities flags = 0; if (presence != NULL) flags = _gabble_media_factory_caps_to_typeflags ( gabble_presence_peek_caps (presence)); if (flags & TP_CHANNEL_MEDIA_CAPABILITY_IMMUTABLE_STREAMS) priv->immutable_streams = TRUE; } return obj; } static void gabble_media_channel_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleMediaChannel *chan = GABBLE_MEDIA_CHANNEL (object); GabbleMediaChannelPrivate *priv = chan->priv; TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn; const gchar *param_name; guint tp_property_id; switch (property_id) { case PROP_OBJECT_PATH: g_value_set_string (value, priv->object_path); break; case PROP_CHANNEL_TYPE: g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA); break; case PROP_HANDLE_TYPE: /* This is used to implement TargetHandleType, which is immutable. If * the peer was known at channel-creation time, this will be Contact; * otherwise, it must be None even if we subsequently learn who the peer * is. */ if (priv->initial_peer != 0) g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT); else g_value_set_uint (value, TP_HANDLE_TYPE_NONE); break; case PROP_INITIAL_PEER: case PROP_HANDLE: /* As above: TargetHandle is immutable, so non-0 only if the peer handle * was known at creation time. */ g_value_set_uint (value, priv->initial_peer); break; case PROP_TARGET_ID: /* As above. */ if (priv->initial_peer != 0) { TpHandleRepoIface *repo = tp_base_connection_get_handles ( base_conn, TP_HANDLE_TYPE_CONTACT); const gchar *target_id = tp_handle_inspect (repo, priv->initial_peer); g_value_set_string (value, target_id); } else { g_value_set_static_string (value, ""); } break; case PROP_PEER: { TpHandle peer = 0; if (priv->initial_peer != 0) peer = priv->initial_peer; else peer = priv->peer; g_value_set_uint (value, peer); break; } case PROP_CONNECTION: g_value_set_object (value, priv->conn); break; case PROP_CREATOR: g_value_set_uint (value, priv->creator); break; case PROP_CREATOR_ID: { TpHandleRepoIface *repo = tp_base_connection_get_handles ( base_conn, TP_HANDLE_TYPE_CONTACT); g_value_set_string (value, tp_handle_inspect (repo, priv->creator)); } break; case PROP_REQUESTED: g_value_set_boolean (value, (priv->creator == tp_base_connection_get_self_handle (base_conn))); break; case PROP_INTERFACES: g_value_set_boxed (value, gabble_media_channel_interfaces); break; case PROP_CHANNEL_DESTROYED: g_value_set_boolean (value, priv->closed); break; case PROP_CHANNEL_PROPERTIES: g_value_take_boxed (value, tp_dbus_properties_mixin_make_properties_hash (object, TP_IFACE_CHANNEL, "TargetHandle", TP_IFACE_CHANNEL, "TargetHandleType", TP_IFACE_CHANNEL, "ChannelType", TP_IFACE_CHANNEL, "TargetID", TP_IFACE_CHANNEL, "InitiatorHandle", TP_IFACE_CHANNEL, "InitiatorID", TP_IFACE_CHANNEL, "Requested", TP_IFACE_CHANNEL, "Interfaces", TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA, "InitialAudio", TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA, "InitialVideo", TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA, "ImmutableStreams", NULL)); break; case PROP_SESSION: g_value_set_object (value, priv->session); break; case PROP_INITIAL_AUDIO: g_value_set_boolean (value, priv->initial_audio); break; case PROP_INITIAL_VIDEO: g_value_set_boolean (value, priv->initial_video); break; case PROP_IMMUTABLE_STREAMS: g_value_set_boolean (value, priv->immutable_streams); break; case PROP_CURRENTLY_SENDING_TONES: g_value_set_boolean (value, tp_dtmf_player_is_active (priv->dtmf_player)); break; case PROP_INITIAL_TONES: /* FIXME: stub */ g_value_set_static_string (value, ""); break; case PROP_DEFERRED_TONES: if (priv->deferred_tones != NULL) g_value_set_string (value, priv->deferred_tones); else g_value_set_static_string (value, ""); break; default: param_name = g_param_spec_get_name (pspec); if (tp_properties_mixin_has_property (object, param_name, &tp_property_id)) { GValue *tp_property_value = chan->properties.properties[tp_property_id].value; if (tp_property_value) { g_value_copy (tp_property_value, value); return; } } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_media_channel_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleMediaChannel *chan = GABBLE_MEDIA_CHANNEL (object); GabbleMediaChannelPrivate *priv = chan->priv; const gchar *param_name; guint tp_property_id; switch (property_id) { case PROP_OBJECT_PATH: g_free (priv->object_path); priv->object_path = g_value_dup_string (value); break; case PROP_HANDLE_TYPE: case PROP_HANDLE: case PROP_CHANNEL_TYPE: /* these properties are writable in the interface, but not actually * meaningfully changable on this channel, so we do nothing */ break; case PROP_CONNECTION: priv->conn = g_value_get_object (value); break; case PROP_CREATOR: priv->creator = g_value_get_uint (value); break; case PROP_INITIAL_PEER: priv->initial_peer = g_value_get_uint (value); break; case PROP_PEER_IN_RP: priv->peer_in_rp = g_value_get_boolean (value); break; case PROP_SESSION: g_assert (priv->session == NULL); priv->session = g_value_dup_object (value); if (priv->session != NULL) { } break; case PROP_INITIAL_AUDIO: priv->initial_audio = g_value_get_boolean (value); break; case PROP_INITIAL_VIDEO: priv->initial_video = g_value_get_boolean (value); break; default: param_name = g_param_spec_get_name (pspec); if (tp_properties_mixin_has_property (object, param_name, &tp_property_id)) { tp_properties_mixin_change_value (object, tp_property_id, value, NULL); tp_properties_mixin_change_flags (object, tp_property_id, TP_PROPERTY_FLAG_READ, 0, NULL); return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_media_channel_dispose (GObject *object); static void gabble_media_channel_finalize (GObject *object); static gboolean gabble_media_channel_add_member (GObject *obj, TpHandle handle, const gchar *message, GError **error); static gboolean gabble_media_channel_remove_member (GObject *obj, TpHandle handle, const gchar *message, guint reason, GError **error); static void gabble_media_channel_class_init (GabbleMediaChannelClass *gabble_media_channel_class) { static TpDBusPropertiesMixinPropImpl channel_props[] = { { "TargetHandleType", "handle-type", NULL }, { "TargetHandle", "handle", NULL }, { "TargetID", "target-id", NULL }, { "ChannelType", "channel-type", NULL }, { "Interfaces", "interfaces", NULL }, { "Requested", "requested", NULL }, { "InitiatorHandle", "creator", NULL }, { "InitiatorID", "creator-id", NULL }, { NULL } }; static TpDBusPropertiesMixinPropImpl streamed_media_props[] = { { "ImmutableStreams", "immutable-streams", NULL }, { "InitialAudio", "initial-audio", NULL }, { "InitialVideo", "initial-video", NULL }, { NULL } }; static TpDBusPropertiesMixinPropImpl dtmf_props[] = { { "CurrentlySendingTones", "currently-sending-tones", NULL }, { "InitialTones", "initial-tones", NULL }, { "DeferredTones", "deferred-tones", NULL }, { NULL } }; static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { { TP_IFACE_CHANNEL, tp_dbus_properties_mixin_getter_gobject_properties, NULL, channel_props, }, { TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA, tp_dbus_properties_mixin_getter_gobject_properties, NULL, streamed_media_props, }, { TP_IFACE_CHANNEL_INTERFACE_DTMF, tp_dbus_properties_mixin_getter_gobject_properties, NULL, dtmf_props, }, { NULL } }; GObjectClass *object_class = G_OBJECT_CLASS (gabble_media_channel_class); GParamSpec *param_spec; g_type_class_add_private (gabble_media_channel_class, sizeof (GabbleMediaChannelPrivate)); object_class->constructor = gabble_media_channel_constructor; object_class->get_property = gabble_media_channel_get_property; object_class->set_property = gabble_media_channel_set_property; object_class->dispose = gabble_media_channel_dispose; object_class->finalize = gabble_media_channel_finalize; g_object_class_override_property (object_class, PROP_OBJECT_PATH, "object-path"); g_object_class_override_property (object_class, PROP_CHANNEL_TYPE, "channel-type"); g_object_class_override_property (object_class, PROP_HANDLE_TYPE, "handle-type"); g_object_class_override_property (object_class, PROP_HANDLE, "handle"); g_object_class_override_property (object_class, PROP_CHANNEL_DESTROYED, "channel-destroyed"); g_object_class_override_property (object_class, PROP_CHANNEL_PROPERTIES, "channel-properties"); param_spec = g_param_spec_string ("target-id", "Target JID", "Currently empty, because this channel always has handle 0.", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_TARGET_ID, param_spec); param_spec = g_param_spec_uint ("initial-peer", "Other participant", "The TpHandle representing the other participant in the channel if known " "at construct-time; 0 if the other participant was unknown at the time " "of channel creation", 0, G_MAXUINT32, 0, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INITIAL_PEER, param_spec); param_spec = g_param_spec_boolean ("peer-in-rp", "Peer initially in Remote Pending?", "True if the channel was created with the most-deprecated " "RequestChannels form, and so the peer should be in Remote Pending " "before any XML has been sent.", FALSE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_PEER_IN_RP, param_spec); param_spec = g_param_spec_uint ("peer", "Other participant", "The TpHandle representing the other participant in the channel if " "currently known; 0 if this is an anonymous channel on which " "RequestStreams has not yet been called.", 0, G_MAXUINT32, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_PEER, param_spec); param_spec = g_param_spec_object ("connection", "GabbleConnection object", "Gabble connection object that owns this media channel object.", GABBLE_TYPE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); param_spec = g_param_spec_uint ("creator", "Channel creator", "The TpHandle representing the contact who created the channel.", 0, G_MAXUINT32, 0, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CREATOR, param_spec); param_spec = g_param_spec_string ("creator-id", "Creator bare JID", "The bare JID obtained by inspecting the creator handle.", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CREATOR_ID, param_spec); param_spec = g_param_spec_boolean ("requested", "Requested?", "True if this channel was requested by the local user", FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_REQUESTED, param_spec); param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces", "Additional Channel.Interface.* interfaces", G_TYPE_STRV, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INTERFACES, param_spec); param_spec = g_param_spec_string ("nat-traversal", "NAT traversal", "NAT traversal mechanism.", "gtalk-p2p", G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_NAT_TRAVERSAL, param_spec); param_spec = g_param_spec_string ("stun-server", "STUN server", "IP or address of STUN server.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_STUN_SERVER, param_spec); param_spec = g_param_spec_uint ("stun-port", "STUN port", "UDP port of STUN server.", 0, G_MAXUINT16, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_STUN_PORT, param_spec); param_spec = g_param_spec_string ("gtalk-p2p-relay-token", "GTalk P2P Relay Token", "Magic token to authenticate with the Google Talk relay server.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_GTALK_P2P_RELAY_TOKEN, param_spec); param_spec = g_param_spec_object ("session", "WockyJingleSession object", "Jingle session associated with this media channel object.", WOCKY_TYPE_JINGLE_SESSION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_SESSION, param_spec); param_spec = g_param_spec_boolean ("initial-audio", "InitialAudio", "Whether the channel initially contained an audio stream", FALSE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INITIAL_AUDIO, param_spec); param_spec = g_param_spec_boolean ("initial-video", "InitialVideo", "Whether the channel initially contained an video stream", FALSE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INITIAL_VIDEO, param_spec); param_spec = g_param_spec_boolean ("immutable-streams", "ImmutableStreams", "Whether the set of streams on this channel are fixed once requested", FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_IMMUTABLE_STREAMS, param_spec); param_spec = g_param_spec_boolean ("currently-sending-tones", "CurrentlySendingTones", "True if a DTMF tone is being sent", FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CURRENTLY_SENDING_TONES, param_spec); param_spec = g_param_spec_string ("initial-tones", "InitialTones", "Initial DTMF tones to be sent in the first audio stream", "", G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INITIAL_TONES, param_spec); param_spec = g_param_spec_string ("deferred-tones", "DeferredTones", "DTMF tones that followed a 'w' or 'W', to be resumed on user request", "", G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_DEFERRED_TONES, param_spec); tp_properties_mixin_class_init (object_class, G_STRUCT_OFFSET (GabbleMediaChannelClass, properties_class), channel_property_signatures, NUM_CHAN_PROPS, NULL); gabble_media_channel_class->dbus_props_class.interfaces = prop_interfaces; tp_dbus_properties_mixin_class_init (object_class, G_STRUCT_OFFSET (GabbleMediaChannelClass, dbus_props_class)); tp_group_mixin_class_init (object_class, G_STRUCT_OFFSET (GabbleMediaChannelClass, group_class), gabble_media_channel_add_member, NULL); tp_group_mixin_class_set_remove_with_reason_func (object_class, gabble_media_channel_remove_member); tp_group_mixin_class_allow_self_removal (object_class); tp_group_mixin_init_dbus_properties (object_class); } void gabble_media_channel_dispose (GObject *object) { GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (object); GabbleMediaChannelPrivate *priv = self->priv; GList *l; if (priv->dispose_has_run) return; DEBUG ("called"); priv->dispose_has_run = TRUE; if (!priv->closed) gabble_media_channel_close (self); g_assert (priv->closed); g_assert (priv->session == NULL); /* Since the session's dead, all the stream_creation_datas should have been * cancelled (which is indicated by their 'content' being NULL). */ for (l = priv->stream_creation_datas; l != NULL; l = l->next) { StreamCreationData *d = l->data; g_assert (d->content == NULL); } g_list_free (priv->stream_creation_datas); priv->stream_creation_datas = NULL; if (priv->delayed_request_streams != NULL) { g_ptr_array_foreach (priv->delayed_request_streams, (GFunc) destroy_request, NULL); g_ptr_array_unref (priv->delayed_request_streams); priv->delayed_request_streams = NULL; } /* All of the streams should have closed in response to the contents being * removed when the call ended. */ g_assert (priv->streams->len == 0); g_ptr_array_unref (priv->streams); priv->streams = NULL; if (G_OBJECT_CLASS (gabble_media_channel_parent_class)->dispose) G_OBJECT_CLASS (gabble_media_channel_parent_class)->dispose (object); } void gabble_media_channel_finalize (GObject *object) { GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (object); GabbleMediaChannelPrivate *priv = self->priv; g_free (priv->object_path); tp_clear_pointer (&self->priv->deferred_tones, g_free); tp_group_mixin_finalize (object); tp_properties_mixin_finalize (object); G_OBJECT_CLASS (gabble_media_channel_parent_class)->finalize (object); } /** * gabble_media_channel_close_async: * * Implements D-Bus method Close * on interface org.freedesktop.Telepathy.Channel */ static void gabble_media_channel_close_async (TpSvcChannel *iface, DBusGMethodInvocation *context) { GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (iface); if (DEBUGGING) { gchar *caller = dbus_g_method_get_sender (context); DEBUG ("called by %s", caller); g_free (caller); } gabble_media_channel_close (self); tp_svc_channel_return_from_close (context); } void gabble_media_channel_close (GabbleMediaChannel *self) { GabbleMediaChannelPrivate *priv = self->priv; DEBUG ("called on %p", self); if (!priv->closed) { priv->closed = TRUE; if (priv->session != NULL) wocky_jingle_session_terminate (priv->session, WOCKY_JINGLE_REASON_UNKNOWN, NULL, NULL); tp_svc_channel_emit_closed (self); } } /** * gabble_media_channel_get_channel_type * * Implements D-Bus method GetChannelType * on interface org.freedesktop.Telepathy.Channel */ static void gabble_media_channel_get_channel_type (TpSvcChannel *iface, DBusGMethodInvocation *context) { tp_svc_channel_return_from_get_channel_type (context, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA); } /** * gabble_media_channel_get_handle * * Implements D-Bus method GetHandle * on interface org.freedesktop.Telepathy.Channel */ static void gabble_media_channel_get_handle (TpSvcChannel *iface, DBusGMethodInvocation *context) { GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (iface); if (self->priv->initial_peer == 0) tp_svc_channel_return_from_get_handle (context, TP_HANDLE_TYPE_NONE, 0); else tp_svc_channel_return_from_get_handle (context, TP_HANDLE_TYPE_CONTACT, self->priv->initial_peer); } /** * gabble_media_channel_get_interfaces * * Implements D-Bus method GetInterfaces * on interface org.freedesktop.Telepathy.Channel */ static void gabble_media_channel_get_interfaces (TpSvcChannel *iface, DBusGMethodInvocation *context) { tp_svc_channel_return_from_get_interfaces (context, gabble_media_channel_interfaces); } /** * gabble_media_channel_get_session_handlers * * Implements D-Bus method GetSessionHandlers * on interface org.freedesktop.Telepathy.Channel.Interface.MediaSignalling */ static void gabble_media_channel_get_session_handlers (TpSvcChannelInterfaceMediaSignalling *iface, DBusGMethodInvocation *context) { GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (iface); GabbleMediaChannelPrivate *priv; GPtrArray *ret; GType info_type = TP_STRUCT_TYPE_MEDIA_SESSION_HANDLER_INFO; g_assert (GABBLE_IS_MEDIA_CHANNEL (self)); priv = self->priv; if (priv->session) { GValue handler = { 0, }; g_value_init (&handler, info_type); g_value_take_boxed (&handler, dbus_g_type_specialized_construct (info_type)); dbus_g_type_struct_set (&handler, 0, priv->object_path, 1, "rtp", G_MAXUINT); ret = g_ptr_array_sized_new (1); g_ptr_array_add (ret, g_value_get_boxed (&handler)); } else { ret = g_ptr_array_sized_new (0); } tp_svc_channel_interface_media_signalling_return_from_get_session_handlers ( context, ret); g_ptr_array_foreach (ret, (GFunc) g_value_array_free, NULL); g_ptr_array_unref (ret); } /** * make_stream_list: * * Creates an array of MediaStreamInfo structs. * * Precondition: priv->session is non-NULL. */ static GPtrArray * make_stream_list (GabbleMediaChannel *self, guint len, GabbleMediaStream **streams) { GabbleMediaChannelPrivate *priv = self->priv; GPtrArray *ret; guint i; GType info_type = TP_STRUCT_TYPE_MEDIA_STREAM_INFO; g_assert (priv->session != NULL); ret = g_ptr_array_sized_new (len); for (i = 0; i < len; i++) { GValue entry = { 0, }; guint id; TpMediaStreamType type; TpMediaStreamState connection_state; CombinedStreamDirection combined_direction; g_object_get (streams[i], "id", &id, "media-type", &type, "connection-state", &connection_state, "combined-direction", &combined_direction, NULL); g_value_init (&entry, info_type); g_value_take_boxed (&entry, dbus_g_type_specialized_construct (info_type)); dbus_g_type_struct_set (&entry, 0, id, 1, priv->peer, 2, type, 3, connection_state, 4, COMBINED_DIRECTION_GET_DIRECTION (combined_direction), 5, COMBINED_DIRECTION_GET_PENDING_SEND (combined_direction), G_MAXUINT); g_ptr_array_add (ret, g_value_get_boxed (&entry)); } return ret; } /** * gabble_media_channel_list_streams * * Implements D-Bus method ListStreams * on interface org.freedesktop.Telepathy.Channel.Type.StreamedMedia */ static void gabble_media_channel_list_streams (TpSvcChannelTypeStreamedMedia *iface, DBusGMethodInvocation *context) { GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (iface); GabbleMediaChannelPrivate *priv; GPtrArray *ret; g_assert (GABBLE_IS_MEDIA_CHANNEL (self)); priv = self->priv; /* If the session has not yet started, or has ended, return an empty array. */ if (priv->session == NULL) { ret = g_ptr_array_new (); } else { ret = make_stream_list (self, priv->streams->len, (GabbleMediaStream **) priv->streams->pdata); } tp_svc_channel_type_streamed_media_return_from_list_streams (context, ret); g_ptr_array_foreach (ret, (GFunc) g_value_array_free, NULL); g_ptr_array_unref (ret); } static GabbleMediaStream * _find_stream_by_id (GabbleMediaChannel *chan, guint stream_id, GError **error) { GabbleMediaChannelPrivate *priv; guint i; g_assert (GABBLE_IS_MEDIA_CHANNEL (chan)); priv = chan->priv; for (i = 0; i < priv->streams->len; i++) { GabbleMediaStream *stream = g_ptr_array_index (priv->streams, i); guint id; g_object_get (stream, "id", &id, NULL); if (id == stream_id) return stream; } g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "given stream id %u does not exist", stream_id); return NULL; } static GabbleMediaStream * _find_stream_by_content (GabbleMediaChannel *chan, WockyJingleContent *content) { GabbleMediaChannelPrivate *priv; guint i; g_assert (GABBLE_IS_MEDIA_CHANNEL (chan)); priv = chan->priv; for (i = 0; i < priv->streams->len; i++) { GabbleMediaStream *stream = g_ptr_array_index (priv->streams, i); WockyJingleContent *c = WOCKY_JINGLE_CONTENT ( gabble_media_stream_get_content (stream)); if (content == c) return stream; } return NULL; } /** * gabble_media_channel_remove_streams * * Implements DBus method RemoveStreams * on interface org.freedesktop.Telepathy.Channel.Type.StreamedMedia */ static void gabble_media_channel_remove_streams (TpSvcChannelTypeStreamedMedia *iface, const GArray * streams, DBusGMethodInvocation *context) { GabbleMediaChannel *obj = GABBLE_MEDIA_CHANNEL (iface); GabbleMediaChannelPrivate *priv; GPtrArray *stream_objs; GError *error = NULL; guint i; g_assert (GABBLE_IS_MEDIA_CHANNEL (obj)); priv = obj->priv; if (!wocky_jingle_session_can_modify_contents (priv->session)) { GError e = { TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "Streams can't be removed from Google Talk calls" }; dbus_g_method_return_error (context, &e); return; } stream_objs = g_ptr_array_sized_new (streams->len); /* check that all stream ids are valid and at the same time build an array * of stream objects so we don't have to look them up again after verifying * all stream identifiers. */ for (i = 0; i < streams->len; i++) { guint id = g_array_index (streams, guint, i); GabbleMediaStream *stream; guint j; stream = _find_stream_by_id (obj, id, &error); if (stream == NULL) goto OUT; /* make sure we don't allow the client to repeatedly remove the same stream */ for (j = 0; j < stream_objs->len; j++) { GabbleMediaStream *tmp = g_ptr_array_index (stream_objs, j); if (tmp == stream) { stream = NULL; break; } } if (stream != NULL) g_ptr_array_add (stream_objs, stream); } /* groovy, it's all good dude, let's remove them */ if (stream_objs->len > 0) { GabbleMediaStream *stream; WockyJingleMediaRtp *c; for (i = 0; i < stream_objs->len; i++) { stream = g_ptr_array_index (stream_objs, i); c = gabble_media_stream_get_content (stream); /* FIXME: make sure session emits content-removed, on which we can * delete it from the list */ wocky_jingle_session_remove_content (priv->session, (WockyJingleContent *) c); } } OUT: g_ptr_array_unref (stream_objs); if (error) { dbus_g_method_return_error (context, error); g_error_free (error); } else { tp_svc_channel_type_streamed_media_return_from_remove_streams (context); } } /** * gabble_media_channel_request_stream_direction * * Implements D-Bus method RequestStreamDirection * on interface org.freedesktop.Telepathy.Channel.Type.StreamedMedia */ static void gabble_media_channel_request_stream_direction (TpSvcChannelTypeStreamedMedia *iface, guint stream_id, guint stream_direction, DBusGMethodInvocation *context) { GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (iface); GabbleMediaChannelPrivate *priv; GabbleMediaStream *stream; GError *error = NULL; g_assert (GABBLE_IS_MEDIA_CHANNEL (self)); priv = self->priv; if (stream_direction > TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL) { g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "given stream direction %u is not valid", stream_direction); dbus_g_method_return_error (context, error); g_error_free (error); return; } stream = _find_stream_by_id (self, stream_id, &error); if (stream == NULL) { dbus_g_method_return_error (context, error); g_error_free (error); return; } DEBUG ("called (stream %s, direction %u)", stream->name, stream_direction); /* streams with no session? I think not... */ g_assert (priv->session != NULL); if (stream_direction == TP_MEDIA_STREAM_DIRECTION_NONE) { if (wocky_jingle_session_can_modify_contents (priv->session)) { WockyJingleMediaRtp *c; DEBUG ("request for NONE direction; removing stream"); c = gabble_media_stream_get_content (stream); wocky_jingle_session_remove_content (priv->session, (WockyJingleContent *) c); tp_svc_channel_type_streamed_media_return_from_request_stream_direction ( context); } else { GError e = { TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "Stream direction can't be set to None in Google Talk calls" }; DEBUG ("%s", e.message); dbus_g_method_return_error (context, &e); } return; } if (gabble_media_stream_change_direction (stream, stream_direction, &error)) { tp_svc_channel_type_streamed_media_return_from_request_stream_direction ( context); } else { dbus_g_method_return_error (context, error); g_error_free (error); } } typedef struct { /* number of streams requested == number of content objects */ guint len; /* array of @len borrowed pointers */ WockyJingleContent **contents; /* accumulates borrowed pointers to streams. Initially @len NULL pointers; * when the stream for contents[i] is created, it is stored at streams[i]. */ GabbleMediaStream **streams; /* number of non-NULL elements in streams (0 <= satisfied <= contents) */ guint satisfied; /* succeeded_cb(context, GPtrArray) * will be called if the stream request succeeds. */ GFunc succeeded_cb; /* failed_cb(context, GError *) will be called if the stream request fails. */ GFunc failed_cb; gpointer context; } PendingStreamRequest; static PendingStreamRequest * pending_stream_request_new (GPtrArray *contents, GFunc succeeded_cb, GFunc failed_cb, gpointer context) { PendingStreamRequest *p = g_slice_new0 (PendingStreamRequest); g_assert (succeeded_cb); g_assert (failed_cb); p->len = contents->len; p->contents = g_memdup (contents->pdata, contents->len * sizeof (gpointer)); p->streams = g_new0 (GabbleMediaStream *, contents->len); p->satisfied = 0; p->succeeded_cb = succeeded_cb; p->failed_cb = failed_cb; p->context = context; return p; } static gboolean pending_stream_request_maybe_satisfy (PendingStreamRequest *p, GabbleMediaChannel *channel, WockyJingleContent *content, GabbleMediaStream *stream) { guint i; for (i = 0; i < p->len; i++) { if (p->contents[i] == content) { g_assert (p->streams[i] == NULL); p->streams[i] = stream; if (++p->satisfied == p->len && p->context != NULL) { GPtrArray *ret = make_stream_list (channel, p->len, p->streams); p->succeeded_cb (p->context, ret); g_ptr_array_foreach (ret, (GFunc) g_value_array_free, NULL); g_ptr_array_unref (ret); p->context = NULL; return TRUE; } } } return FALSE; } static gboolean pending_stream_request_maybe_fail (PendingStreamRequest *p, GabbleMediaChannel *channel, WockyJingleContent *content) { guint i; for (i = 0; i < p->len; i++) { if (content == p->contents[i]) { GError e = { TP_ERROR, TP_ERROR_NOT_AVAILABLE, "A stream was removed before it could be fully set up" }; /* return early */ p->failed_cb (p->context, &e); p->context = NULL; return TRUE; } } return FALSE; } static void pending_stream_request_free (gpointer data) { PendingStreamRequest *p = data; if (p->context != NULL) { GError e = { TP_ERROR, TP_ERROR_CANCELLED, "The session terminated before the requested streams could be added" }; p->failed_cb (p->context, &e); } g_free (p->contents); g_free (p->streams); g_slice_free (PendingStreamRequest, p); } static gboolean _gabble_media_channel_request_contents (GabbleMediaChannel *chan, TpHandle peer, const GArray *media_types, GPtrArray **ret, GError **error) { GabbleMediaChannelPrivate *priv = chan->priv; gboolean want_audio, want_video; WockyJingleDialect dialect; guint idx; const gchar *peer_resource; const gchar *transport_ns = NULL; DEBUG ("called"); want_audio = want_video = FALSE; for (idx = 0; idx < media_types->len; idx++) { guint media_type = g_array_index (media_types, guint, idx); if (media_type == TP_MEDIA_STREAM_TYPE_AUDIO) { want_audio = TRUE; } else if (media_type == TP_MEDIA_STREAM_TYPE_VIDEO) { want_video = TRUE; } else { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "given media type %u is invalid", media_type); return FALSE; } } /* existing call; the recipient and the mode has already been decided */ if (priv->session != NULL) { peer_resource = wocky_jingle_session_get_peer_resource (priv->session); if (peer_resource[0] != '\0') DEBUG ("existing call, using peer resource %s", peer_resource); else DEBUG ("existing call, using bare JID"); /* is a google call... we have no other option */ if (!wocky_jingle_session_can_modify_contents (priv->session)) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "Streams can't be added to ongoing Google Talk calls"); return FALSE; } /* check if the resource supports it; FIXME - we assume only * one channel type (video or audio) will be added later */ if (NULL == jingle_pick_best_content_type (priv->conn, peer, peer_resource, want_audio ? WOCKY_JINGLE_MEDIA_TYPE_AUDIO : WOCKY_JINGLE_MEDIA_TYPE_VIDEO)) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "member does not have the desired audio/video capabilities"); return FALSE; } /* We assume we already picked the best possible transport ns for the * previous streams, so we just reuse that one */ { GList *contents = wocky_jingle_session_get_contents (priv->session); WockyJingleContent *c; /* If we have a session, we must have at least one content. */ g_assert (contents != NULL); c = contents->data; g_list_free (contents); transport_ns = wocky_jingle_content_get_transport_ns (c); } } /* no existing call; we should choose a recipient and a mode */ else { gchar *jid; DEBUG ("picking the best resource (want audio: %u, want video: %u", want_audio, want_video); g_assert (priv->streams->len == 0); if (!jingle_pick_best_resource (priv->conn, peer, want_audio, want_video, &transport_ns, &dialect, &peer_resource)) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_CAPABLE, "member does not have the desired audio/video capabilities"); return FALSE; } DEBUG ("Picking resource '%s' (transport: %s, dialect: %u)", peer_resource == NULL ? "(null)" : peer_resource, transport_ns, dialect); jid = gabble_peer_to_jid (priv->conn, peer, peer_resource); priv->peer = peer; create_session (chan, jid, dialect); g_free (jid); /* Change nat-traversal if we need to */ if (!tp_strdiff (transport_ns, NS_JINGLE_TRANSPORT_ICEUDP)) { DEBUG ("changing nat-traversal property to ice-udp"); g_object_set (chan, "nat-traversal", "ice-udp", NULL); } else if (!tp_strdiff (transport_ns, NS_JINGLE_TRANSPORT_RAWUDP)) { DEBUG ("changing nat-traversal property to raw-udp"); g_object_set (chan, "nat-traversal", "none", NULL); } } /* check it's not a ridiculous number of streams */ if ((priv->streams->len + media_types->len) > MAX_STREAMS) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "I think that's quite enough streams already"); return FALSE; } /* if we've got here, we're good to make the Jingle contents */ *ret = g_ptr_array_sized_new (media_types->len); for (idx = 0; idx < media_types->len; idx++) { guint media_type = g_array_index (media_types, guint, idx); WockyJingleContent *c; const gchar *content_ns; content_ns = jingle_pick_best_content_type (priv->conn, peer, peer_resource, media_type == TP_MEDIA_STREAM_TYPE_AUDIO ? WOCKY_JINGLE_MEDIA_TYPE_AUDIO : WOCKY_JINGLE_MEDIA_TYPE_VIDEO); /* if we got this far, resource should be capable enough, so we * should not fail in choosing ns */ g_assert (content_ns != NULL); g_assert (transport_ns != NULL); DEBUG ("Creating new jingle content with ns %s : %s", content_ns, transport_ns); c = wocky_jingle_session_add_content (priv->session, media_type == TP_MEDIA_STREAM_TYPE_AUDIO ? WOCKY_JINGLE_MEDIA_TYPE_AUDIO : WOCKY_JINGLE_MEDIA_TYPE_VIDEO, WOCKY_JINGLE_CONTENT_SENDERS_BOTH, NULL, content_ns, transport_ns); /* The stream is created in "new-content" callback, and appended to * priv->streams. This is now guaranteed to happen asynchronously (adding * streams can take time due to the relay info lookup, and if it doesn't, * we use an idle so it does). */ g_assert (c != NULL); g_ptr_array_add (*ret, c); } return TRUE; } /* user_data param is here so we match the GFunc prototype */ static void destroy_request (struct _delayed_request_streams_ctx *ctx, gpointer user_data G_GNUC_UNUSED) { GabbleMediaChannelPrivate *priv = ctx->chan->priv; if (ctx->unsure_period_ended_id) g_signal_handler_disconnect (priv->conn->presence_cache, ctx->unsure_period_ended_id); if (ctx->caps_disco_id) g_signal_handler_disconnect (priv->conn->presence_cache, ctx->caps_disco_id); if (ctx->context != NULL) { GError *error = NULL; g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "cannot add streams: peer has insufficient caps"); ctx->failed_cb (ctx->context, error); g_error_free (error); } g_array_unref (ctx->types); g_slice_free (struct _delayed_request_streams_ctx, ctx); } static void destroy_and_remove_request (struct _delayed_request_streams_ctx *ctx) { GabbleMediaChannelPrivate *priv = ctx->chan->priv; destroy_request (ctx, NULL); g_ptr_array_remove_fast (priv->delayed_request_streams, ctx); } static void media_channel_request_streams (GabbleMediaChannel *self, TpHandle contact_handle, const GArray *types, GFunc succeeded_cb, GFunc failed_cb, gpointer context); static gboolean repeat_request (struct _delayed_request_streams_ctx *ctx) { media_channel_request_streams (ctx->chan, ctx->contact_handle, ctx->types, ctx->succeeded_cb, ctx->failed_cb, ctx->context); ctx->context = NULL; destroy_and_remove_request (ctx); return FALSE; } static void capabilities_discovered_cb (GabblePresenceCache *cache, TpHandle handle, struct _delayed_request_streams_ctx *ctx) { /* If this isn't the contact we're waiting for, ignore the signal. */ if (ctx->contact_handle != handle) return; /* If we're still unsure about this contact (most likely because there are * more cache caps pending), wait for them. */ if (gabble_presence_cache_is_unsure (cache, handle)) return; repeat_request (ctx); } static void delay_stream_request (GabbleMediaChannel *chan, guint contact_handle, const GArray *types, GFunc succeeded_cb, GFunc failed_cb, gpointer context) { GabbleMediaChannelPrivate *priv = chan->priv; struct _delayed_request_streams_ctx *ctx = g_slice_new0 (struct _delayed_request_streams_ctx); ctx->chan = chan; ctx->contact_handle = contact_handle; ctx->succeeded_cb = succeeded_cb; ctx->failed_cb = failed_cb; ctx->context = context; ctx->types = g_array_sized_new (FALSE, FALSE, sizeof (guint), types->len); g_array_append_vals (ctx->types, types->data, types->len); ctx->caps_disco_id = g_signal_connect (priv->conn->presence_cache, "capabilities-discovered", G_CALLBACK (capabilities_discovered_cb), ctx); ctx->unsure_period_ended_id = g_signal_connect_swapped ( priv->conn->presence_cache, "unsure-period-ended", G_CALLBACK (repeat_request), ctx); g_ptr_array_add (priv->delayed_request_streams, ctx); } static void media_channel_request_streams (GabbleMediaChannel *self, TpHandle contact_handle, const GArray *types, GFunc succeeded_cb, GFunc failed_cb, gpointer context) { GabbleMediaChannelPrivate *priv = self->priv; GPtrArray *contents; gboolean wait; PendingStreamRequest *psr; GError *error = NULL; if (types->len == 0) { GPtrArray *empty = g_ptr_array_sized_new (0); DEBUG ("no streams to request"); succeeded_cb (context, empty); g_ptr_array_unref (empty); return; } /* If we know the caps haven't arrived yet, delay stream creation * and check again later. Else, give up. */ if (!contact_is_media_capable (self, contact_handle, &wait, &error)) { if (wait) { DEBUG ("Delaying RequestStreams until we get all caps from contact"); delay_stream_request (self, contact_handle, types, succeeded_cb, failed_cb, context); g_error_free (error); return; } goto error; } if (priv->peer != 0 && priv->peer != contact_handle) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "cannot add streams for %u: this channel's peer is %u", contact_handle, priv->peer); goto error; } if (!_gabble_media_channel_request_contents (self, contact_handle, types, &contents, &error)) goto error; psr = pending_stream_request_new (contents, succeeded_cb, failed_cb, context); priv->pending_stream_requests = g_list_prepend (priv->pending_stream_requests, psr); g_ptr_array_unref (contents); /* signal acceptance */ wocky_jingle_session_accept (priv->session); return; error: DEBUG ("returning error %u: %s", error->code, error->message); failed_cb (context, error); g_error_free (error); } /** * gabble_media_channel_request_streams * * Implements D-Bus method RequestStreams * on interface org.freedesktop.Telepathy.Channel.Type.StreamedMedia */ static void gabble_media_channel_request_streams (TpSvcChannelTypeStreamedMedia *iface, guint contact_handle, const GArray *types, DBusGMethodInvocation *context) { GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (iface); TpBaseConnection *base_conn = (TpBaseConnection *) self->priv->conn; TpHandleRepoIface *contact_handles = tp_base_connection_get_handles ( base_conn, TP_HANDLE_TYPE_CONTACT); GError *error = NULL; if (!tp_handle_is_valid (contact_handles, contact_handle, &error)) { DEBUG ("that's not a handle, sonny! (%u)", contact_handle); dbus_g_method_return_error (context, error); g_error_free (error); return; } else { /* FIXME: disallow this if we've put the peer on hold? */ media_channel_request_streams (self, contact_handle, types, (GFunc) tp_svc_channel_type_streamed_media_return_from_request_streams, (GFunc) dbus_g_method_return_error, context); } } /** * gabble_media_channel_request_initial_streams: * @chan: an outgoing call, which must have just been constructed. * @succeeded_cb: called with arguments @user_data and a GPtrArray of * TP_STRUCT_TYPE_MEDIA_STREAM_INFO if the request succeeds. * @failed_cb: called with arguments @user_data and a GError * if the request * fails. * @user_data: context for the callbacks. * * Request streams corresponding to the values of InitialAudio and InitialVideo * in the channel request. */ void gabble_media_channel_request_initial_streams (GabbleMediaChannel *chan, GFunc succeeded_cb, GFunc failed_cb, gpointer user_data) { GabbleMediaChannelPrivate *priv = chan->priv; GArray *types = g_array_sized_new (FALSE, FALSE, sizeof (guint), 2); guint media_type; TpBaseConnection *base_conn = TP_BASE_CONNECTION (priv->conn); /* This has to be an outgoing call... */ g_assert (priv->creator == tp_base_connection_get_self_handle (base_conn)); /* ...which has just been constructed. */ g_assert (priv->session == NULL); if (priv->initial_peer == 0) { /* This is a ye olde anonymous channel, so InitialAudio/Video should be * impossible. */ g_assert (!priv->initial_audio); g_assert (!priv->initial_video); } if (priv->initial_audio) { media_type = TP_MEDIA_STREAM_TYPE_AUDIO; g_array_append_val (types, media_type); } if (priv->initial_video) { media_type = TP_MEDIA_STREAM_TYPE_VIDEO; g_array_append_val (types, media_type); } media_channel_request_streams (chan, priv->initial_peer, types, succeeded_cb, failed_cb, user_data); g_array_unref (types); } static gboolean contact_is_media_capable (GabbleMediaChannel *chan, TpHandle peer, gboolean *wait_ret, GError **error) { GabbleMediaChannelPrivate *priv = chan->priv; GabblePresence *presence; TpBaseConnection *conn = (TpBaseConnection *) priv->conn; TpHandleRepoIface *contact_handles = tp_base_connection_get_handles ( conn, TP_HANDLE_TYPE_CONTACT); gboolean wait = FALSE; presence = gabble_presence_cache_get (priv->conn->presence_cache, peer); if (presence != NULL) { const GabbleCapabilitySet *caps = gabble_presence_peek_caps (presence); if (gabble_capability_set_has_one (caps, gabble_capabilities_get_any_audio_video ())) return TRUE; } /* Okay, they're not capable (yet). Let's figure out whether we should wait, * and return an appropriate error. */ if (gabble_presence_cache_is_unsure (priv->conn->presence_cache, peer)) { DEBUG ("presence cache is still unsure about handle %u", peer); wait = TRUE; } else if (!priv->tried_decloaking && gabble_presence_cache_request_decloaking (priv->conn->presence_cache, peer, "media")) { /* only ask to decloak at most once per call */ priv->tried_decloaking = TRUE; DEBUG ("asked handle %u to decloak, let's see what they do", peer); wait = TRUE; } if (wait_ret != NULL) *wait_ret = wait; if (presence == NULL) g_set_error (error, TP_ERROR, TP_ERROR_OFFLINE, "contact %d (%s) has no presence available", peer, tp_handle_inspect (contact_handles, peer)); else g_set_error (error, TP_ERROR, TP_ERROR_NOT_CAPABLE, "contact %d (%s) doesn't have sufficient media caps", peer, tp_handle_inspect (contact_handles, peer)); return FALSE; } static gboolean gabble_media_channel_add_member (GObject *obj, TpHandle handle, const gchar *message, GError **error) { GabbleMediaChannel *chan = GABBLE_MEDIA_CHANNEL (obj); GabbleMediaChannelPrivate *priv = chan->priv; TpGroupMixin *mixin = TP_GROUP_MIXIN (obj); TpIntset *set; /* did we create this channel? */ if (priv->creator == mixin->self_handle) { GError *error_ = NULL; gboolean wait; /* yes: check we don't have a peer already, and if not add this one to * remote pending (but don't send an invitation yet). */ if (priv->peer != 0 && priv->peer != handle) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "handle %u cannot be added: this channel's peer is %u", handle, priv->peer); return FALSE; } /* We can't delay the request at this time, but if there's a chance * the caps might be available later, we'll add the contact and * hope for the best. */ if (!contact_is_media_capable (chan, handle, &wait, &error_)) { if (wait) { DEBUG ("contact %u caps still pending, adding anyways", handle); g_error_free (error_); } else { DEBUG ("%u: %s", error_->code, error_->message); g_propagate_error (error, error_); return FALSE; } } /* make the peer remote pending */ set = tp_intset_new_containing (handle); tp_group_mixin_change_members (obj, "", NULL, NULL, NULL, set, mixin->self_handle, TP_CHANNEL_GROUP_CHANGE_REASON_INVITED); tp_intset_destroy (set); /* and remove CanAdd, since it was only here to allow this deprecated * API. */ tp_group_mixin_change_flags (obj, 0, TP_CHANNEL_GROUP_FLAG_CAN_ADD); return TRUE; } else { /* no: has a session been created, is the handle being added ours, * and are we in local pending? (call answer) */ if (priv->session && handle == mixin->self_handle && tp_handle_set_is_member (mixin->local_pending, handle)) { /* is the call on hold? */ if (priv->hold_state != TP_LOCAL_HOLD_STATE_UNHELD) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "Can't answer a call while it's on hold"); return FALSE; } /* make us a member */ set = tp_intset_new_containing (handle); tp_group_mixin_change_members (obj, "", set, NULL, NULL, NULL, handle, TP_CHANNEL_GROUP_CHANGE_REASON_NONE); tp_intset_destroy (set); /* accept any local pending sends */ g_ptr_array_foreach (priv->streams, (GFunc) gabble_media_stream_accept_pending_local_send, NULL); /* signal acceptance */ wocky_jingle_session_accept (priv->session); return TRUE; } } g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "handle %u cannot be added in the current state", handle); return FALSE; } static gboolean gabble_media_channel_remove_member (GObject *obj, TpHandle handle, const gchar *message, TpChannelGroupChangeReason reason, GError **error) { GabbleMediaChannel *chan = GABBLE_MEDIA_CHANNEL (obj); GabbleMediaChannelPrivate *priv = chan->priv; TpGroupMixin *mixin = TP_GROUP_MIXIN (obj); /* We don't set CanRemove, and did allow self removal. So tp-glib should * ensure this. */ g_assert (handle == mixin->self_handle); /* Closing up might make GabbleMediaFactory release its ref. */ g_object_ref (chan); if (priv->session == NULL) { /* The call didn't even start yet; close up. */ gabble_media_channel_close (chan); } else { WockyJingleReason wocky_jingle_reason = WOCKY_JINGLE_REASON_UNKNOWN; switch (reason) { case TP_CHANNEL_GROUP_CHANGE_REASON_NONE: wocky_jingle_reason = WOCKY_JINGLE_REASON_UNKNOWN; break; case TP_CHANNEL_GROUP_CHANGE_REASON_OFFLINE: wocky_jingle_reason = WOCKY_JINGLE_REASON_GONE; break; case TP_CHANNEL_GROUP_CHANGE_REASON_BUSY: wocky_jingle_reason = WOCKY_JINGLE_REASON_BUSY; break; case TP_CHANNEL_GROUP_CHANGE_REASON_ERROR: wocky_jingle_reason = WOCKY_JINGLE_REASON_GENERAL_ERROR; break; case TP_CHANNEL_GROUP_CHANGE_REASON_NO_ANSWER: wocky_jingle_reason = WOCKY_JINGLE_REASON_TIMEOUT; break; default: g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "%u doesn't make sense as a reason to end a call", reason); g_object_unref (chan); return FALSE; } wocky_jingle_session_terminate (priv->session, wocky_jingle_reason, message, error); } /* Remove CanAdd if it was there for the deprecated anonymous channel * semantics, since the channel will go away RSN. */ tp_group_mixin_change_flags (obj, 0, TP_CHANNEL_GROUP_FLAG_CAN_ADD); g_object_unref (chan); return TRUE; } /** * copy_stream_list: * * Returns a copy of priv->streams. This is used when applying a function to * all streams that could result in them being closed, to avoid stream_close_cb * modifying the list being iterated. */ static GPtrArray * copy_stream_list (GabbleMediaChannel *channel) { return gabble_g_ptr_array_copy (channel->priv->streams); } /* return TRUE when the jingle reason is reason enough to raise a * StreamError */ static gboolean extract_media_stream_error_from_jingle_reason (WockyJingleReason wocky_jingle_reason, TpMediaStreamError *stream_error) { TpMediaStreamError _stream_error; /* TODO: Make a better mapping with more distinction of possible errors */ switch (wocky_jingle_reason) { case WOCKY_JINGLE_REASON_CONNECTIVITY_ERROR: _stream_error = TP_MEDIA_STREAM_ERROR_NETWORK_ERROR; break; case WOCKY_JINGLE_REASON_MEDIA_ERROR: _stream_error = TP_MEDIA_STREAM_ERROR_MEDIA_ERROR; break; case WOCKY_JINGLE_REASON_FAILED_APPLICATION: _stream_error = TP_MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED; break; case WOCKY_JINGLE_REASON_GENERAL_ERROR: _stream_error = TP_MEDIA_STREAM_ERROR_UNKNOWN; break; default: { if (stream_error != NULL) *stream_error = TP_MEDIA_STREAM_ERROR_UNKNOWN; return FALSE; } } if (stream_error != NULL) *stream_error = _stream_error; return TRUE; } static WockyJingleReason media_stream_error_to_jingle_reason (TpMediaStreamError stream_error) { switch (stream_error) { case TP_MEDIA_STREAM_ERROR_NETWORK_ERROR: return WOCKY_JINGLE_REASON_CONNECTIVITY_ERROR; case TP_MEDIA_STREAM_ERROR_MEDIA_ERROR: return WOCKY_JINGLE_REASON_MEDIA_ERROR; case TP_MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED: return WOCKY_JINGLE_REASON_FAILED_APPLICATION; default: return WOCKY_JINGLE_REASON_GENERAL_ERROR; } } static TpChannelGroupChangeReason wocky_jingle_reason_to_group_change_reason (WockyJingleReason wocky_jingle_reason) { switch (wocky_jingle_reason) { case WOCKY_JINGLE_REASON_BUSY: return TP_CHANNEL_GROUP_CHANGE_REASON_BUSY; case WOCKY_JINGLE_REASON_GONE: return TP_CHANNEL_GROUP_CHANGE_REASON_OFFLINE; case WOCKY_JINGLE_REASON_TIMEOUT: return TP_CHANNEL_GROUP_CHANGE_REASON_NO_ANSWER; case WOCKY_JINGLE_REASON_CONNECTIVITY_ERROR: case WOCKY_JINGLE_REASON_FAILED_APPLICATION: case WOCKY_JINGLE_REASON_FAILED_TRANSPORT: case WOCKY_JINGLE_REASON_GENERAL_ERROR: case WOCKY_JINGLE_REASON_MEDIA_ERROR: case WOCKY_JINGLE_REASON_SECURITY_ERROR: case WOCKY_JINGLE_REASON_INCOMPATIBLE_PARAMETERS: case WOCKY_JINGLE_REASON_UNSUPPORTED_APPLICATIONS: case WOCKY_JINGLE_REASON_UNSUPPORTED_TRANSPORTS: return TP_CHANNEL_GROUP_CHANGE_REASON_ERROR; default: return TP_CHANNEL_GROUP_CHANGE_REASON_NONE; } } static void session_terminated_cb (WockyJingleSession *session, gboolean local_terminator, WockyJingleReason wocky_jingle_reason, const gchar *text, gpointer user_data) { GabbleMediaChannel *channel = (GabbleMediaChannel *) user_data; GabbleMediaChannelPrivate *priv = channel->priv; TpGroupMixin *mixin = TP_GROUP_MIXIN (channel); guint terminator; WockyJingleState state; TpIntset *set; DEBUG ("called"); g_object_get (session, "state", &state, NULL); if (local_terminator) terminator = mixin->self_handle; else terminator = priv->peer; set = tp_intset_new (); /* remove us and the peer from the member list */ tp_intset_add (set, mixin->self_handle); tp_intset_add (set, priv->peer); tp_group_mixin_change_members ((GObject *) channel, text, NULL, set, NULL, NULL, terminator, wocky_jingle_reason_to_group_change_reason (wocky_jingle_reason)); tp_intset_destroy (set); /* Ignore any Google relay session responses we're waiting for. */ g_list_foreach (priv->stream_creation_datas, stream_creation_data_cancel, NULL); /* any contents that we were waiting for have now lost */ g_list_foreach (priv->pending_stream_requests, (GFunc) pending_stream_request_free, NULL); g_list_free (priv->pending_stream_requests); priv->pending_stream_requests = NULL; { GPtrArray *tmp = copy_stream_list (channel); guint i; TpMediaStreamError stream_error = TP_MEDIA_STREAM_ERROR_UNKNOWN; gboolean is_error = extract_media_stream_error_from_jingle_reason ( wocky_jingle_reason, &stream_error); for (i = 0; i < tmp->len; i++) { GabbleMediaStream *stream = tmp->pdata[i]; if (is_error) { guint id; DEBUG ("emitting stream error"); g_object_get (stream, "id", &id, NULL); tp_svc_channel_type_streamed_media_emit_stream_error (channel, id, stream_error, text); } gabble_media_stream_close (stream); } /* All the streams should have closed. */ g_assert (priv->streams->len == 0); g_ptr_array_unref (tmp); } /* remove the session */ tp_clear_object (&priv->session); /* close us if we aren't already closed */ if (!priv->closed) { DEBUG ("calling media channel close from session terminated cb"); gabble_media_channel_close (channel); } } static void session_state_changed_cb (WockyJingleSession *session, GParamSpec *arg1, GabbleMediaChannel *channel) { GObject *as_object = (GObject *) channel; GabbleMediaChannelPrivate *priv = channel->priv; TpGroupMixin *mixin = TP_GROUP_MIXIN (channel); WockyJingleState state; TpIntset *set; DEBUG ("called"); g_object_get (session, "state", &state, NULL); set = tp_intset_new_containing (priv->peer); if (state >= WOCKY_JINGLE_STATE_PENDING_INITIATE_SENT && state < WOCKY_JINGLE_STATE_ACTIVE && !tp_handle_set_is_member (mixin->members, priv->peer)) { /* The first time we send anything to the other user, they materialise * in remote-pending if necessary */ tp_group_mixin_change_members (as_object, "", NULL, NULL, NULL, set, mixin->self_handle, TP_CHANNEL_GROUP_CHANGE_REASON_INVITED); /* Remove CanAdd if it happened to be there to support deprecated * RequestChannel(..., 0) followed by AddMembers([h], ...) semantics. */ tp_group_mixin_change_flags (as_object, 0, TP_CHANNEL_GROUP_FLAG_CAN_ADD); } if (state == WOCKY_JINGLE_STATE_ACTIVE && priv->creator == mixin->self_handle) { DEBUG ("adding peer to the member list and updating flags"); /* add the peer to the member list */ tp_group_mixin_change_members (as_object, "", set, NULL, NULL, NULL, priv->peer, TP_CHANNEL_GROUP_CHANGE_REASON_NONE); } tp_intset_destroy (set); } static void stream_close_cb (GabbleMediaStream *stream, GabbleMediaChannel *chan) { GabbleMediaChannelPrivate *priv = chan->priv; guint id, i; gboolean still_have_audio = FALSE; g_assert (GABBLE_IS_MEDIA_CHANNEL (chan)); g_object_get (stream, "id", &id, NULL); tp_svc_channel_type_streamed_media_emit_stream_removed (chan, id); if (g_ptr_array_remove (priv->streams, stream)) g_object_unref (stream); else g_warning ("stream %p (%s) removed, but it wasn't in priv->streams!", stream, stream->name); gabble_media_channel_hold_stream_closed (chan, stream); for (i = 0; i < priv->streams->len; i++) { GabbleMediaStream *other = g_ptr_array_index (priv->streams, i); if (gabble_media_stream_get_media_type (other) == TP_MEDIA_STREAM_TYPE_AUDIO) { still_have_audio = TRUE; } } if (priv->have_some_audio && !still_have_audio) { /* the last audio stream just closed */ tp_dtmf_player_cancel (priv->dtmf_player); } priv->have_some_audio = still_have_audio; } static void stream_error_cb (GabbleMediaStream *stream, TpMediaStreamError errno, const gchar *message, GabbleMediaChannel *chan) { GabbleMediaChannelPrivate *priv = chan->priv; WockyJingleMediaRtp *c; GList *contents; guint id; /* emit signal */ g_object_get (stream, "id", &id, NULL); tp_svc_channel_type_streamed_media_emit_stream_error (chan, id, errno, message); contents = wocky_jingle_session_get_contents (priv->session); if (wocky_jingle_session_can_modify_contents (priv->session) && g_list_length (contents) > 1) { /* remove stream from session (removal will be signalled * so we can dispose of the stream) */ c = gabble_media_stream_get_content (stream); if (errno == TP_MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED) wocky_jingle_content_reject ((WockyJingleContent *) c, WOCKY_JINGLE_REASON_FAILED_APPLICATION); else wocky_jingle_session_remove_content (priv->session, (WockyJingleContent *) c); } else { /* We can't remove the content, or it's the only one left; let's * terminate the call. (The alternative is to carry on the call with * only audio/video, which will look or sound bad to the Google * Talk-using peer.) */ DEBUG ("Terminating call in response to stream error"); wocky_jingle_session_terminate (priv->session, media_stream_error_to_jingle_reason (errno), message, NULL); } g_list_free (contents); } static void stream_state_changed_cb (GabbleMediaStream *stream, GParamSpec *pspec, GabbleMediaChannel *chan) { guint id; TpMediaStreamState connection_state; g_object_get (stream, "id", &id, "connection-state", &connection_state, NULL); tp_svc_channel_type_streamed_media_emit_stream_state_changed (chan, id, connection_state); } static void stream_direction_changed_cb (GabbleMediaStream *stream, GParamSpec *pspec, GabbleMediaChannel *chan) { guint id; CombinedStreamDirection combined; TpMediaStreamDirection direction; TpMediaStreamPendingSend pending_send; g_object_get (stream, "id", &id, "combined-direction", &combined, NULL); direction = COMBINED_DIRECTION_GET_DIRECTION (combined); pending_send = COMBINED_DIRECTION_GET_PENDING_SEND (combined); DEBUG ("direction: %u, pending_send: %u", direction, pending_send); tp_svc_channel_type_streamed_media_emit_stream_direction_changed ( chan, id, direction, pending_send); } static void construct_stream (GabbleMediaChannel *chan, WockyJingleContent *c, const gchar *name, const gchar *nat_traversal, const GPtrArray *relays, gboolean initial) { GObject *chan_o = (GObject *) chan; GabbleMediaChannelPrivate *priv = chan->priv; GabbleMediaStream *stream; TpMediaStreamType mtype; guint id; gchar *object_path; gboolean local_hold = (priv->hold_state == TP_LOCAL_HOLD_STATE_HELD || priv->hold_state == TP_LOCAL_HOLD_STATE_PENDING_HOLD); id = priv->next_stream_id++; object_path = g_strdup_printf ("%s/MediaStream%u", priv->object_path, id); stream = gabble_media_stream_new ( tp_base_connection_get_dbus_daemon (TP_BASE_CONNECTION (priv->conn)), object_path, c, name, id, nat_traversal, relays, local_hold); mtype = gabble_media_stream_get_media_type (stream); if (mtype == TP_MEDIA_STREAM_TYPE_AUDIO) { gabble_media_stream_add_dtmf_player (stream, priv->dtmf_player); priv->have_some_audio = TRUE; } DEBUG ("%p: created new MediaStream %p for content '%s'", chan, stream, name); g_ptr_array_add (priv->streams, stream); /* if any RequestStreams call was waiting for a stream to be created for * that content, return from it successfully */ { GList *l = priv->pending_stream_requests; while (l != NULL) { if (pending_stream_request_maybe_satisfy (l->data, chan, c, stream)) { GList *dead = l; pending_stream_request_free (dead->data); l = dead->next; priv->pending_stream_requests = g_list_delete_link ( priv->pending_stream_requests, dead); } else { l = l->next; } } } gabble_signal_connect_weak (stream, "close", (GCallback) stream_close_cb, chan_o); gabble_signal_connect_weak (stream, "error", (GCallback) stream_error_cb, chan_o); gabble_signal_connect_weak (stream, "notify::connection-state", (GCallback) stream_state_changed_cb, chan_o); gabble_signal_connect_weak (stream, "notify::combined-direction", (GCallback) stream_direction_changed_cb, chan_o); if (initial) { /* If we accepted the call, then automagically accept the initial streams * when they pop up */ if (tp_handle_set_is_member (chan->group.members, chan->group.self_handle)) { gabble_media_stream_accept_pending_local_send (stream); } } DEBUG ("emitting StreamAdded with type '%s'", mtype == TP_MEDIA_STREAM_TYPE_AUDIO ? "audio" : "video"); tp_svc_channel_type_streamed_media_emit_stream_added ( chan, id, priv->peer, mtype); /* StreamAdded does not include the stream's direction and pending send * information, so we call the notify::combined-direction handler in order to * emit StreamDirectionChanged for the initial state. */ stream_direction_changed_cb (stream, NULL, chan); gabble_media_channel_hold_new_stream (chan, stream, WOCKY_JINGLE_MEDIA_RTP (c)); if (priv->ready) { /* all of the streams are bidirectional from farsight's point of view, it's * just in the signalling they change */ DEBUG ("emitting MediaSessionHandler:NewStreamHandler signal for stream %d", id); tp_svc_media_session_handler_emit_new_stream_handler (chan, object_path, id, mtype, TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL); } g_free (object_path); } static void stream_creation_data_cancel (gpointer p, gpointer unused) { StreamCreationData *d = p; tp_clear_object (&d->content); } static void stream_creation_data_free (gpointer p) { StreamCreationData *d = p; g_free (d->name); if (d->content != NULL) { g_signal_handler_disconnect (d->content, d->removed_id); g_object_unref (d->content); } if (d->self != NULL) { GabbleMediaChannelPrivate *priv = d->self->priv; g_object_remove_weak_pointer (G_OBJECT (d->self), (gpointer *) &d->self); priv->stream_creation_datas = g_list_remove ( priv->stream_creation_datas, d); } g_slice_free (StreamCreationData, d); } static gboolean construct_stream_later_cb (gpointer user_data) { StreamCreationData *d = user_data; if (d->content != NULL && d->self != NULL) construct_stream (d->self, d->content, d->name, d->nat_traversal, NULL, d->initial); return FALSE; } static void google_relay_session_cb (GPtrArray *relays, gpointer user_data) { StreamCreationData *d = user_data; GPtrArray *tp_relays = gabble_build_tp_relay_info (relays); if (d->content != NULL && d->self != NULL) construct_stream (d->self, d->content, d->name, d->nat_traversal, tp_relays, d->initial); g_ptr_array_unref (tp_relays); stream_creation_data_free (d); } static void content_removed_cb (WockyJingleContent *content, StreamCreationData *d) { if (d->content == NULL) return; if (d->self != NULL) { GList *l = d->self->priv->pending_stream_requests; /* if any RequestStreams call was waiting for a stream to be created for * that content, return from it unsuccessfully */ while (l != NULL) { if (pending_stream_request_maybe_fail (l->data, d->self, d->content)) { GList *dead = l; pending_stream_request_free (dead->data); l = dead->next; d->self->priv->pending_stream_requests = g_list_delete_link ( d->self->priv->pending_stream_requests, dead); } else { l = l->next; } } } g_signal_handler_disconnect (d->content, d->removed_id); g_object_unref (d->content); d->content = NULL; } static void create_stream_from_content (GabbleMediaChannel *self, WockyJingleContent *c, gboolean initial) { gchar *name; StreamCreationData *d; g_object_get (c, "name", &name, NULL); if (G_OBJECT_TYPE (c) != WOCKY_TYPE_JINGLE_MEDIA_RTP) { DEBUG ("ignoring non MediaRtp content '%s'", name); g_free (name); return; } d = g_slice_new0 (StreamCreationData); d->self = self; d->name = name; d->content = g_object_ref (c); d->initial = initial; g_object_add_weak_pointer (G_OBJECT (d->self), (gpointer *) &d->self); /* If the content gets removed before we've finished looking up its * relay, we need to cancel the creation of the stream, * and make any PendingStreamRequests fail */ d->removed_id = g_signal_connect (c, "removed", G_CALLBACK (content_removed_cb), d); self->priv->stream_creation_datas = g_list_prepend ( self->priv->stream_creation_datas, d); switch (wocky_jingle_content_get_transport_type (c)) { case JINGLE_TRANSPORT_GOOGLE_P2P: /* See if our server is Google, and if it is, ask them for a relay. * We ask for enough relays for 2 components (RTP and RTCP) since we * don't yet know whether there will be RTCP. */ d->nat_traversal = "gtalk-p2p"; DEBUG ("Attempting to create Google relay session"); wocky_jingle_info_create_google_relay_session ( gabble_jingle_mint_get_info (self->priv->conn->jingle_mint), 2, google_relay_session_cb, d); return; case JINGLE_TRANSPORT_ICE_UDP: d->nat_traversal = "ice-udp"; break; default: d->nat_traversal = "none"; } /* If we got here, just create the stream (do it asynchronously so that the * behaviour is the same in each case) */ g_idle_add_full (G_PRIORITY_DEFAULT, construct_stream_later_cb, d, stream_creation_data_free); } static void session_content_rejected_cb (WockyJingleSession *session, WockyJingleContent *c, WockyJingleReason reason, const gchar *message, gpointer user_data) { GabbleMediaChannel *chan = GABBLE_MEDIA_CHANNEL (user_data); GabbleMediaStream *stream = _find_stream_by_content (chan, c); TpMediaStreamError stream_error = TP_MEDIA_STREAM_ERROR_UNKNOWN; guint id = 0; DEBUG (" "); g_return_if_fail (stream != NULL); g_object_get (stream, "id", &id, NULL); extract_media_stream_error_from_jingle_reason (reason, &stream_error); tp_svc_channel_type_streamed_media_emit_stream_error (chan, id, stream_error, message); } static void session_new_content_cb (WockyJingleSession *session, WockyJingleContent *c, gpointer user_data) { GabbleMediaChannel *chan = GABBLE_MEDIA_CHANNEL (user_data); DEBUG ("called"); create_stream_from_content (chan, c, FALSE); } static void _emit_new_stream (GabbleMediaChannel *chan, GabbleMediaStream *stream) { gchar *object_path; guint id, media_type; g_object_get (stream, "object-path", &object_path, "id", &id, "media-type", &media_type, NULL); /* all of the streams are bidirectional from farsight's point of view, it's * just in the signalling they change */ DEBUG ("emitting MediaSessionHandler:NewStreamHandler signal for %s stream %d ", media_type == TP_MEDIA_STREAM_TYPE_AUDIO ? "audio" : "video", id); tp_svc_media_session_handler_emit_new_stream_handler (chan, object_path, id, media_type, TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL); g_free (object_path); } static void gabble_media_channel_ready (TpSvcMediaSessionHandler *iface, DBusGMethodInvocation *context) { GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (iface); GabbleMediaChannelPrivate *priv = self->priv; if (priv->session == NULL) { /* This could also be because someone called Ready() before the * SessionHandler was announced. But the fact that the SessionHandler is * actually also the Channel, and thus this method is available before * NewSessionHandler is emitted, is an implementation detail. So the * error message describes the only legitimate situation in which this * could arise. */ GError e = { TP_ERROR, TP_ERROR_NOT_AVAILABLE, "call has already ended" }; DEBUG ("no session, returning an error."); dbus_g_method_return_error (context, &e); return; } if (!priv->ready) { guint i; DEBUG ("emitting NewStreamHandler for each stream"); priv->ready = TRUE; for (i = 0; i < priv->streams->len; i++) _emit_new_stream (self, g_ptr_array_index (priv->streams, i)); } tp_svc_media_session_handler_return_from_ready (context); } static void gabble_media_channel_error (TpSvcMediaSessionHandler *iface, guint errno, const gchar *message, DBusGMethodInvocation *context) { GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (iface); GabbleMediaChannelPrivate *priv; GPtrArray *tmp; guint i; WockyJingleState state; g_assert (GABBLE_IS_MEDIA_CHANNEL (self)); priv = self->priv; if (priv->session == NULL) { /* This could also be because someone called Error() before the * SessionHandler was announced. But the fact that the SessionHandler is * actually also the Channel, and thus this method is available before * NewSessionHandler is emitted, is an implementation detail. So the * error message describes the only legitimate situation in which this * could arise. */ GError e = { TP_ERROR, TP_ERROR_NOT_AVAILABLE, "call has already ended" }; DEBUG ("no session, returning an error."); dbus_g_method_return_error (context, &e); return; } DEBUG ("Media.SessionHandler::Error called, error %u (%s) -- " "emitting error on each stream", errno, message); g_object_get (priv->session, "state", &state, NULL); if (state == WOCKY_JINGLE_STATE_ENDED) { tp_svc_media_session_handler_return_from_error (context); return; } else if (state == WOCKY_JINGLE_STATE_PENDING_CREATED) { /* shortcut to prevent sending remove actions if we haven't sent an * initiate yet */ g_object_set (self, "state", WOCKY_JINGLE_STATE_ENDED, NULL); tp_svc_media_session_handler_return_from_error (context); return; } /* Calling gabble_media_stream_error () on all the streams will ultimately * cause them all to emit 'closed'. In response to 'closed', stream_close_cb * unrefs them, and removes them from priv->streams. So, we copy the stream * list to avoid it being modified from underneath us. */ tmp = copy_stream_list (self); for (i = 0; i < tmp->len; i++) { GabbleMediaStream *stream = g_ptr_array_index (tmp, i); gabble_media_stream_error (stream, errno, message, NULL); } g_ptr_array_unref (tmp); tp_svc_media_session_handler_return_from_error (context); } #define TONE_MS 200 #define GAP_MS 100 #define PAUSE_MS 3000 /* arbitrary limit on the length of a tone started with StartTone */ #define MAX_TONE_SECONDS 10 static void gabble_media_channel_start_tone (TpSvcChannelInterfaceDTMF *iface, guint stream_id G_GNUC_UNUSED, guchar event, DBusGMethodInvocation *context) { GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (iface); gchar tones[2] = { '\0', '\0' }; GError *error = NULL; if (!self->priv->have_some_audio) { GError e = { TP_ERROR, TP_ERROR_NOT_AVAILABLE, "There are no audio streams" }; dbus_g_method_return_error (context, &e); return; } tones[0] = tp_dtmf_event_to_char (event); if (tp_dtmf_player_play (self->priv->dtmf_player, tones, MAX_TONE_SECONDS * 1000, GAP_MS, PAUSE_MS, &error)) { tp_clear_pointer (&self->priv->deferred_tones, g_free); tp_svc_channel_interface_dtmf_emit_sending_tones (self, tones); tp_svc_channel_interface_dtmf_return_from_start_tone (context); } else { dbus_g_method_return_error (context, error); g_clear_error (&error); } } static void gabble_media_channel_stop_tone (TpSvcChannelInterfaceDTMF *iface, guint stream_id, DBusGMethodInvocation *context) { GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (iface); tp_dtmf_player_cancel (self->priv->dtmf_player); tp_svc_channel_interface_dtmf_return_from_stop_tone (context); } static void gabble_media_channel_multiple_tones ( TpSvcChannelInterfaceDTMF *iface, const gchar *dialstring, DBusGMethodInvocation *context) { GabbleMediaChannel *self = GABBLE_MEDIA_CHANNEL (iface); GError *error = NULL; if (!self->priv->have_some_audio) { GError e = { TP_ERROR, TP_ERROR_NOT_AVAILABLE, "There are no audio streams" }; dbus_g_method_return_error (context, &e); return; } if (tp_dtmf_player_play (self->priv->dtmf_player, dialstring, TONE_MS, GAP_MS, PAUSE_MS, &error)) { tp_clear_pointer (&self->priv->deferred_tones, g_free); tp_svc_channel_interface_dtmf_emit_sending_tones (self, dialstring); tp_svc_channel_interface_dtmf_return_from_start_tone (context); } else { dbus_g_method_return_error (context, error); g_clear_error (&error); } } static void channel_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcChannelClass *klass = (TpSvcChannelClass *) g_iface; #define IMPLEMENT(x, suffix) tp_svc_channel_implement_##x (\ klass, gabble_media_channel_##x##suffix) IMPLEMENT(close,_async); IMPLEMENT(get_channel_type,); IMPLEMENT(get_handle,); IMPLEMENT(get_interfaces,); #undef IMPLEMENT } static void dtmf_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcChannelInterfaceDTMFClass *klass = g_iface; #define IMPLEMENT(x) tp_svc_channel_interface_dtmf_implement_##x (\ klass, gabble_media_channel_##x) IMPLEMENT(start_tone); IMPLEMENT(stop_tone); IMPLEMENT(multiple_tones); #undef IMPLEMENT } static void streamed_media_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcChannelTypeStreamedMediaClass *klass = (TpSvcChannelTypeStreamedMediaClass *) g_iface; #define IMPLEMENT(x) tp_svc_channel_type_streamed_media_implement_##x (\ klass, gabble_media_channel_##x) IMPLEMENT(list_streams); IMPLEMENT(remove_streams); IMPLEMENT(request_stream_direction); IMPLEMENT(request_streams); #undef IMPLEMENT } static void media_signalling_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcChannelInterfaceMediaSignallingClass *klass = (TpSvcChannelInterfaceMediaSignallingClass *) g_iface; #define IMPLEMENT(x) tp_svc_channel_interface_media_signalling_implement_##x (\ klass, gabble_media_channel_##x) IMPLEMENT(get_session_handlers); #undef IMPLEMENT } static void session_handler_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcMediaSessionHandlerClass *klass = (TpSvcMediaSessionHandlerClass *) g_iface; #define IMPLEMENT(x) tp_svc_media_session_handler_implement_##x (\ klass, gabble_media_channel_##x) IMPLEMENT(error); IMPLEMENT(ready); #undef IMPLEMENT } telepathy-gabble-0.18.3/src/call-content.c0000664000175000017500000002553012332440117021516 0ustar00cassidycassidy00000000000000/* * gabble-call-content.c - Source for GabbleCallContent * Copyright (C) 2009-2011 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include #include #include "call-member.h" #include "call-content.h" #include "call-stream.h" #include "jingle-tp-util.h" #include "connection.h" #include "util.h" #define DEBUG_FLAG GABBLE_DEBUG_MEDIA #include "debug.h" static void call_content_deinit (TpBaseCallContent *base); static void call_content_local_media_description_updated ( GabbleCallContent *self, TpHandle contact, GHashTable *properties, gpointer data); G_DEFINE_TYPE (GabbleCallContent, gabble_call_content, TP_TYPE_BASE_MEDIA_CALL_CONTENT); /* private structure */ struct _GabbleCallContentPrivate { /* CallMemberContent list */ GList *contents; guint offers; gboolean dispose_has_run; gboolean deinit_has_run; }; static void gabble_call_content_init (GabbleCallContent *self) { GabbleCallContentPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_CALL_CONTENT, GabbleCallContentPrivate); self->priv = priv; g_signal_connect (self, "local-media-description-updated", G_CALLBACK (call_content_local_media_description_updated), NULL); } static void gabble_call_content_dispose (GObject *object); static void gabble_call_content_class_init ( GabbleCallContentClass *gabble_call_content_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_call_content_class); TpBaseCallContentClass *bcc_class = TP_BASE_CALL_CONTENT_CLASS (gabble_call_content_class); g_type_class_add_private (gabble_call_content_class, sizeof (GabbleCallContentPrivate)); object_class->dispose = gabble_call_content_dispose; bcc_class->deinit = call_content_deinit; } static void gabble_call_content_dispose (GObject *object) { GabbleCallContent *self = GABBLE_CALL_CONTENT (object); GabbleCallContentPrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; g_assert (priv->contents == NULL); if (G_OBJECT_CLASS (gabble_call_content_parent_class)->dispose) G_OBJECT_CLASS (gabble_call_content_parent_class)->dispose (object); } static void call_content_deinit (TpBaseCallContent *base) { GabbleCallContent *self = GABBLE_CALL_CONTENT (base); GabbleCallContentPrivate *priv = self->priv; if (priv->deinit_has_run) return; priv->deinit_has_run = TRUE; while (priv->contents != NULL) { GabbleCallMemberContent *c = priv->contents->data; priv->contents = g_list_delete_link (priv->contents, priv->contents); gabble_call_member_content_remove (c); } TP_BASE_CALL_CONTENT_CLASS ( gabble_call_content_parent_class)->deinit (base); } void gabble_call_content_new_offer (GabbleCallContent *self, GabbleCallMemberContent *content) { GabbleCallContentPrivate *priv = self->priv; TpBaseCallContent *base = TP_BASE_CALL_CONTENT (self); TpBaseConnection *conn = tp_base_call_content_get_connection (base); TpCallContentMediaDescription *md; gchar *path; TpHandle handle = 0; path = g_strdup_printf ("%s/Offer%d", tp_base_call_content_get_object_path (base), priv->offers++); if (content != NULL) { handle = gabble_call_member_get_handle ( gabble_call_member_content_get_member (content)); } /* FIXME: no idea... */ md = tp_call_content_media_description_new ( tp_base_connection_get_dbus_daemon (conn), path, handle, (content != NULL), (content == NULL)); if (content != NULL) { GList *codecs, *l; codecs = gabble_call_member_content_get_remote_codecs (content); for (l = codecs; l != NULL; l = g_list_next (l)) { WockyJingleCodec *c = l->data; tp_call_content_media_description_append_codec (md, c->id, c->name, c->clockrate, c->channels, FALSE, /* FIXME: updated?? */ c->params); } } /* FIXME: We have to handle cases where the new codecs are rejected */ tp_base_media_call_content_offer_media_description_async ( TP_BASE_MEDIA_CALL_CONTENT (self), md, NULL, NULL); g_object_unref (md); g_free (path); } WockyJingleMediaType gabble_call_content_get_media_type (GabbleCallContent *self) { TpBaseCallContent *base = TP_BASE_CALL_CONTENT (self); return wocky_jingle_media_type_from_tp ( tp_base_call_content_get_media_type (base)); } static void member_content_codecs_changed (GabbleCallMemberContent *mcontent, gpointer user_data) { GabbleCallContent *self = GABBLE_CALL_CONTENT (user_data); DEBUG ("Preparing new codec offer"); gabble_call_content_new_offer (self, mcontent); } static GList * codec_array_to_list (GPtrArray *codecs) { guint i; GList *l = NULL; if (codecs == NULL) return NULL; for (i = 0; i < codecs->len ; i++) { WockyJingleCodec *c; GValueArray *va; va = g_ptr_array_index (codecs, i); c = jingle_media_rtp_codec_new ( g_value_get_uint (va->values + 0), g_value_get_string (va->values + 1), g_value_get_uint (va->values + 2), g_value_get_uint (va->values + 3), /* g_value_get_boolean (va->values + 4), updated? */ g_value_get_boxed (va->values + 5)); l = g_list_append (l, c); } return l; } static void call_content_local_media_description_updated (GabbleCallContent *self, TpHandle contact, GHashTable *properties, gpointer data) { GList *l; WockyJingleMediaDescription *md = wocky_jingle_media_description_new (); md->codecs = codec_array_to_list (tp_asv_get_boxed (properties, TP_PROP_CALL_CONTENT_MEDIA_DESCRIPTION_CODECS, TP_ARRAY_TYPE_CODEC_LIST)); for (l = self->priv->contents; l != NULL; l = g_list_next (l)) { GabbleCallMemberContent *c = GABBLE_CALL_MEMBER_CONTENT (l->data); WockyJingleContent *j = gabble_call_member_content_get_jingle_content (c); if (j == NULL) continue; /* FIXME react properly on errors ? */ jingle_media_rtp_set_local_media_description (WOCKY_JINGLE_MEDIA_RTP (j), wocky_jingle_media_description_copy (md), TRUE, NULL); } wocky_jingle_media_description_free (md); } static TpStreamTransportType _jingle_to_tp_transport (WockyJingleTransportType jt) { switch (jt) { case JINGLE_TRANSPORT_GOOGLE_P2P: return TP_STREAM_TRANSPORT_TYPE_GTALK_P2P; case JINGLE_TRANSPORT_RAW_UDP: return TP_STREAM_TRANSPORT_TYPE_RAW_UDP; case JINGLE_TRANSPORT_ICE_UDP: return TP_STREAM_TRANSPORT_TYPE_ICE; default: g_return_val_if_reached (G_MAXUINT); } } static void call_content_setup_jingle (GabbleCallContent *self, GabbleCallMemberContent *mcontent) { TpBaseCallContent *base = TP_BASE_CALL_CONTENT (self); WockyJingleContent *jingle; GabbleCallStream *stream; gchar *path; WockyJingleTransportType transport; WockyJingleMediaDescription *md; GHashTable *tp_md; TpHandle contact; jingle = gabble_call_member_content_get_jingle_content (mcontent); if (jingle == NULL) return; transport = wocky_jingle_content_get_transport_type (jingle); path = g_strdup_printf ("%s/Stream%p", tp_base_call_content_get_object_path (base), jingle); stream = g_object_new (GABBLE_TYPE_CALL_STREAM, "object-path", path, "connection", tp_base_call_content_get_connection (base), "jingle-content", jingle, "transport", _jingle_to_tp_transport (transport), NULL); g_free (path); md = wocky_jingle_media_description_new (); /* FIXME: correct??? */ contact = gabble_call_member_get_handle ( gabble_call_member_content_get_member (mcontent)); tp_md = tp_base_media_call_content_get_local_media_description ( TP_BASE_MEDIA_CALL_CONTENT (self), contact); if (tp_md != NULL) { md->codecs = codec_array_to_list (tp_asv_get_boxed (tp_md, TP_PROP_CALL_CONTENT_MEDIA_DESCRIPTION_CODECS, TP_ARRAY_TYPE_CODEC_LIST)); } if (md->codecs != NULL) jingle_media_rtp_set_local_media_description ( WOCKY_JINGLE_MEDIA_RTP (jingle), md, TRUE, NULL); else wocky_jingle_media_description_free (md); tp_base_call_content_add_stream (base, TP_BASE_CALL_STREAM (stream)); gabble_call_stream_update_member_states (stream); g_object_unref (stream); } static void member_content_got_jingle_content_cb (GabbleCallMemberContent *mcontent, gpointer user_data) { GabbleCallContent *self = GABBLE_CALL_CONTENT (user_data); call_content_setup_jingle (self, mcontent); } static void member_content_removed_cb (GabbleCallMemberContent *mcontent, gpointer user_data) { GabbleCallContent *self = GABBLE_CALL_CONTENT (user_data); GabbleCallContentPrivate *priv = self->priv; TpBaseCallContent *base = TP_BASE_CALL_CONTENT (self); WockyJingleContent *content; GList *l; priv->contents = g_list_remove (priv->contents, mcontent); content = gabble_call_member_content_get_jingle_content (mcontent); for (l = tp_base_call_content_get_streams (base); l != NULL; l = l->next) { GabbleCallStream *stream = GABBLE_CALL_STREAM (l->data); if (content == gabble_call_stream_get_jingle_content (stream)) { tp_base_call_content_remove_stream (base, l->data, 0, TP_CALL_STATE_CHANGE_REASON_PROGRESS_MADE, "", ""); break; } } } void gabble_call_content_add_member_content (GabbleCallContent *self, GabbleCallMemberContent *content) { self->priv->contents = g_list_prepend (self->priv->contents, content); call_content_setup_jingle (self, content); gabble_signal_connect_weak (content, "codecs-changed", G_CALLBACK (member_content_codecs_changed), G_OBJECT (self)); gabble_signal_connect_weak (content, "got-jingle-content", G_CALLBACK (member_content_got_jingle_content_cb), G_OBJECT (self)); gabble_signal_connect_weak (content, "removed", G_CALLBACK (member_content_removed_cb), G_OBJECT (self)); gabble_call_content_new_offer (self, content); } GList * gabble_call_content_get_member_contents (GabbleCallContent *self) { return self->priv->contents; } telepathy-gabble-0.18.3/src/legacy-caps.h0000664000175000017500000000265312332441362021334 0ustar00cassidycassidy00000000000000/* * legacy-caps.h - Connection.Interface.Capabilities constants and utilities * Copyright (C) 2005 Collabora Ltd. * Copyright (C) 2005 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_LEGACY_CAPS__H__ #define __GABBLE_LEGACY_CAPS__H__ #include #include "gabble/capabilities.h" typedef void (*TypeFlagsToCapsFunc) (guint typeflags, GabbleCapabilitySet *caps); typedef guint (*CapsToTypeFlagsFunc) (const GabbleCapabilitySet *caps); typedef struct _CapabilityConversionData CapabilityConversionData; struct _CapabilityConversionData { const gchar *iface; TypeFlagsToCapsFunc tf2c_fn; CapsToTypeFlagsFunc c2tf_fn; }; extern const CapabilityConversionData capabilities_conversions[]; #endif telepathy-gabble-0.18.3/src/connection.c0000664000175000017500000037111612332441362021301 0ustar00cassidycassidy00000000000000/* * gabble-connection.c - Source for GabbleConnection * Copyright (C) 2005-2010 Collabora Ltd. * Copyright (C) 2005-2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "connection.h" #include "gabble.h" #include #include #include #include #include #include #include #include #include "extensions/extensions.h" #define DEBUG_FLAG GABBLE_DEBUG_CONNECTION #include #include "bytestream-factory.h" #include "gabble/capabilities.h" #include "gabble/caps-channel-manager.h" #include "gabble/plugin-connection.h" #include "caps-hash.h" #include "auth-manager.h" #include "conn-aliasing.h" #include "conn-avatars.h" #include "conn-client-types.h" #include "conn-contact-info.h" #include "conn-location.h" #include "conn-presence.h" #include "conn-sidecars.h" #include "conn-mail-notif.h" #include "conn-olpc.h" #include "conn-power-saving.h" #include "debug.h" #include "disco.h" #include "im-factory.h" #include "legacy-caps.h" #include "muc-factory.h" #include "namespaces.h" #include "presence-cache.h" #include "presence.h" #include "request-pipeline.h" #include "roomlist-manager.h" #include "roster.h" #include "search-manager.h" #include "server-tls-channel.h" #include "server-tls-manager.h" #include "plugin-loader.h" #include "private-tubes-factory.h" #include "util.h" #include "vcard-manager.h" #include "conn-util.h" #include "conn-addressing.h" #ifdef ENABLE_VOIP #include "media-channel.h" #include "media-factory.h" #endif static guint disco_reply_timeout = 5; #define DISCONNECT_TIMEOUT 5 static void capabilities_service_iface_init (gpointer, gpointer); static void gabble_conn_contact_caps_iface_init (gpointer, gpointer); static void conn_capabilities_fill_contact_attributes (GObject *obj, const GArray *contacts, GHashTable *attributes_hash); static void conn_contact_capabilities_fill_contact_attributes (GObject *obj, const GArray *contacts, GHashTable *attributes_hash); static void gabble_plugin_connection_iface_init ( GabblePluginConnectionInterface *iface, gpointer conn); static gchar *_gabble_plugin_connection_get_full_jid ( GabblePluginConnection *conn); static TpBaseContactList *_gabble_plugin_connection_get_contact_list ( GabblePluginConnection *conn); G_DEFINE_TYPE_WITH_CODE(GabbleConnection, gabble_connection, TP_TYPE_BASE_CONNECTION, G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_ALIASING, conn_aliasing_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_AVATARS, conn_avatars_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_INFO, conn_contact_info_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CAPABILITIES, capabilities_service_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, tp_dbus_properties_mixin_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACTS, tp_contacts_mixin_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_LIST, tp_base_contact_list_mixin_list_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_GROUPS, tp_base_contact_list_mixin_groups_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_BLOCKING, tp_base_contact_list_mixin_blocking_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_SIMPLE_PRESENCE, tp_presence_mixin_simple_presence_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_CONNECTION_INTERFACE_GABBLE_DECLOAK, conn_decloak_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_LOCATION, location_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_OLPC_BUDDY_INFO, olpc_buddy_info_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_OLPC_ACTIVITY_PROPERTIES, olpc_activity_properties_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_CAPABILITIES, gabble_conn_contact_caps_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_CONNECTION_FUTURE, conn_future_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_MAIL_NOTIFICATION, conn_mail_notif_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_CLIENT_TYPES, conn_client_types_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_POWER_SAVING, conn_power_saving_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_CONNECTION_INTERFACE_ADDRESSING, conn_addressing_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_PLUGIN_CONNECTION, gabble_plugin_connection_iface_init); ) /* properties */ enum { PROP_CONNECT_SERVER = 1, PROP_EXPLICIT_SERVER, PROP_PORT, PROP_OLD_SSL, PROP_REQUIRE_ENCRYPTION, PROP_REGISTER, PROP_LOW_BANDWIDTH, PROP_STREAM_SERVER, PROP_USERNAME, PROP_PASSWORD, PROP_RESOURCE, PROP_PRIORITY, PROP_HTTPS_PROXY_SERVER, PROP_HTTPS_PROXY_PORT, PROP_FALLBACK_CONFERENCE_SERVER, PROP_STUN_SERVER, PROP_STUN_PORT, PROP_FALLBACK_STUN_SERVER, PROP_FALLBACK_STUN_PORT, PROP_IGNORE_SSL_ERRORS, PROP_ALIAS, PROP_FALLBACK_SOCKS5_PROXIES, PROP_KEEPALIVE_INTERVAL, PROP_DECLOAK_AUTOMATICALLY, PROP_FALLBACK_SERVERS, PROP_EXTRA_CERTIFICATE_IDENTITIES, PROP_POWER_SAVING, PROP_DOWNLOAD_AT_CONNECTION, LAST_PROPERTY }; /* private structure */ struct _GabbleConnectionPrivate { WockyConnector *connector; WockyPorter *porter; WockyPing *pinger; GCancellable *cancellable; /* connection properties */ gchar *connect_server; gchar *explicit_server; guint port; gboolean old_ssl; gboolean require_encryption; gboolean ignore_ssl_errors; TpConnectionStatusReason ssl_error; gboolean do_register; gboolean low_bandwidth; guint keepalive_interval; gchar *https_proxy_server; guint16 https_proxy_port; gchar *stun_server; guint16 stun_port; gchar *fallback_stun_server; guint16 fallback_stun_port; gchar *fallback_conference_server; GStrv fallback_socks5_proxies; gboolean decloak_automatically; GStrv fallback_servers; guint fallback_server_index; GStrv extra_certificate_identities; gboolean power_saving; /* authentication properties */ gchar *stream_server; gchar *username; gchar *password; gchar *resource; gint8 priority; gchar *alias; /* reference to conference server name */ const gchar *conference_server; /* serial number of current advertised caps */ guint caps_serial; /* Last activity time for XEP-0012 purposes, where "activity" is defined to * mean "sending a message". */ time_t last_activity_time; /* capabilities from various sources: */ /* subscriptions on behalf of the Connection, like PEP "+notify" * namespaces (this one is add-only) */ GabbleCapabilitySet *notify_caps; /* caps provided by Capabilities.AdvertiseCapabilities (tp-spec 0.16) */ GabbleCapabilitySet *legacy_caps; /* additional caps that we advertise until the first call to * AdvertiseCapabilities or UpdateCapabilities, for vague historical * reasons */ GabbleCapabilitySet *bonus_caps; /* sidecar caps set by gabble_connection_update_sidecar_capabilities */ GabbleCapabilitySet *sidecar_caps; /* caps provided via ContactCapabilities.UpdateCapabilities () * gchar * (client name) => GabbleCapabilitySet * */ GHashTable *client_caps; /* the union of the above */ GabbleCapabilitySet *all_caps; /* data forms provided via UpdateCapabilities() * gchar * (client name) => GPtrArray */ GHashTable *client_data_forms; /* auth manager */ GabbleAuthManager *auth_manager; /* server TLS manager */ GabbleServerTLSManager *server_tls_manager; /* IM factory; we need this to add text caps for everyone (even * offline contacts) which is done through the IM factory's * GabbleCapsChannelManagerInterface->get_contact_caps function. */ GabbleImFactory *im_factory; /* stream id returned by the connector */ gchar *stream_id; /* timer used when trying to properly disconnect */ guint disconnect_timer; /* Number of things we are waiting for before changing the connection status * to connected */ guint waiting_connected; /* Used to cancel pending calls to _gabble_connection_send_with_reply(). It * should not be necessary because by the time we get to cancelling this (in * our dispose()) the porter should be long dead and have called back for all * outstanding requests. However... call this paranoia, and a desire to * delete the Loudmouth compatibility layer without spending any more hours * untangling even more old code. */ GCancellable *iq_reply_cancellable; gboolean closing; /* gobject housekeeping */ gboolean dispose_has_run; }; static void connection_capabilities_update_cb (GabblePresenceCache *cache, TpHandle handle, const GabbleCapabilitySet *old_cap_set, const GabbleCapabilitySet *new_cap_set, gpointer user_data); static gboolean gabble_connection_refresh_capabilities (GabbleConnection *self, GabbleCapabilitySet **old_out); static void add_to_array (gpointer data, gpointer user_data) { g_ptr_array_add (user_data, data); } static GPtrArray * _gabble_connection_create_channel_managers (TpBaseConnection *conn) { GabbleConnection *self = GABBLE_CONNECTION (conn); GabblePluginConnection *plugin_connection = GABBLE_PLUGIN_CONNECTION (self); GPtrArray *channel_managers = g_ptr_array_sized_new (10); GabblePluginLoader *loader; GPtrArray *tmp; self->roster = gabble_roster_new (self); g_signal_connect (self->roster, "nicknames-update", G_CALLBACK (gabble_conn_aliasing_nicknames_updated), self); g_ptr_array_add (channel_managers, self->roster); self->priv->im_factory = g_object_new (GABBLE_TYPE_IM_FACTORY, "connection", self, NULL); g_ptr_array_add (channel_managers, self->priv->im_factory); g_ptr_array_add (channel_managers, g_object_new (GABBLE_TYPE_ROOMLIST_MANAGER, "connection", self, NULL)); g_ptr_array_add (channel_managers, g_object_new (GABBLE_TYPE_SEARCH_MANAGER, "connection", self, NULL)); self->priv->auth_manager = g_object_new (GABBLE_TYPE_AUTH_MANAGER, "connection", self, NULL); g_ptr_array_add (channel_managers, self->priv->auth_manager); self->priv->server_tls_manager = g_object_new (GABBLE_TYPE_SERVER_TLS_MANAGER, "connection", self, NULL); g_ptr_array_add (channel_managers, self->priv->server_tls_manager); self->muc_factory = g_object_new (GABBLE_TYPE_MUC_FACTORY, "connection", self, NULL); g_ptr_array_add (channel_managers, self->muc_factory); self->private_tubes_factory = gabble_private_tubes_factory_new (self); g_ptr_array_add (channel_managers, self->private_tubes_factory); #ifdef ENABLE_VOIP self->jingle_mint = gabble_jingle_mint_new (self); g_ptr_array_add (channel_managers, g_object_new (GABBLE_TYPE_MEDIA_FACTORY, "connection", self, NULL)); #endif #ifdef ENABLE_FILE_TRANSFER self->ft_manager = gabble_ft_manager_new (self); g_ptr_array_add (channel_managers, self->ft_manager); #endif /* plugin channel managers */ loader = gabble_plugin_loader_dup (); tmp = gabble_plugin_loader_create_channel_managers (loader, plugin_connection); g_object_unref (loader); g_ptr_array_foreach (tmp, add_to_array, channel_managers); g_ptr_array_unref (tmp); return channel_managers; } static void gabble_plugin_connection_iface_init ( GabblePluginConnectionInterface *iface, gpointer conn) { iface->add_sidecar_own_caps = gabble_connection_add_sidecar_own_caps; iface->add_sidecar_own_caps_full= gabble_connection_add_sidecar_own_caps_full; iface->get_session = gabble_connection_get_session; iface->get_full_jid = _gabble_plugin_connection_get_full_jid; iface->get_jid_for_caps = gabble_connection_get_jid_for_caps; iface->pick_best_resource_for_caps = gabble_connection_pick_best_resource_for_caps; iface->get_contact_list = _gabble_plugin_connection_get_contact_list; iface->get_caps = gabble_connection_get_caps; } static GObject * gabble_connection_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_params) { GabbleConnection *self = GABBLE_CONNECTION ( G_OBJECT_CLASS (gabble_connection_parent_class)->constructor ( type, n_construct_properties, construct_params)); GabbleConnectionPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_CONNECTION, GabbleConnectionPrivate); TpBaseConnection *base = TP_BASE_CONNECTION (self); DEBUG("Post-construction: (GabbleConnection *)%p", self); tp_base_connection_add_possible_client_interest (base, TP_IFACE_QUARK_CONNECTION_INTERFACE_MAIL_NOTIFICATION); self->req_pipeline = gabble_request_pipeline_new (self); self->disco = gabble_disco_new (self); self->vcard_manager = gabble_vcard_manager_new (self); g_signal_connect (self->vcard_manager, "nickname-update", G_CALLBACK (gabble_conn_aliasing_nickname_updated), self); self->presence_cache = gabble_presence_cache_new (self); g_signal_connect (self->presence_cache, "nickname-update", G_CALLBACK (gabble_conn_aliasing_nickname_updated), self); g_signal_connect (self->presence_cache, "capabilities-update", G_CALLBACK (connection_capabilities_update_cb), self); tp_contacts_mixin_init (G_OBJECT (self), G_STRUCT_OFFSET (GabbleConnection, contacts)); tp_base_connection_register_with_contacts_mixin (base); tp_base_contact_list_mixin_register_with_contacts_mixin (base); conn_aliasing_init (self); conn_avatars_init (self); conn_contact_info_init (self); conn_presence_init (self); conn_olpc_activity_properties_init (self); conn_location_init (self); conn_sidecars_init (self); conn_mail_notif_init (self); conn_client_types_init (self); conn_addressing_init (self); tp_contacts_mixin_add_contact_attributes_iface (G_OBJECT (self), TP_IFACE_CONNECTION_INTERFACE_CAPABILITIES, conn_capabilities_fill_contact_attributes); tp_contacts_mixin_add_contact_attributes_iface (G_OBJECT (self), TP_IFACE_CONNECTION_INTERFACE_CONTACT_CAPABILITIES, conn_contact_capabilities_fill_contact_attributes); self->bytestream_factory = gabble_bytestream_factory_new (self); self->avatar_requests = g_hash_table_new (NULL, NULL); self->vcard_requests = g_hash_table_new (NULL, NULL); if (priv->fallback_socks5_proxies == NULL) { /* No proxies have been defined, set the default ones */ gchar *default_socks5_proxies[] = GABBLE_PARAMS_DEFAULT_SOCKS5_PROXIES; g_object_set (self, "fallback-socks5-proxies", default_socks5_proxies, NULL); } priv->all_caps = gabble_capability_set_new (); priv->notify_caps = gabble_capability_set_new (); priv->legacy_caps = gabble_capability_set_new (); priv->sidecar_caps = gabble_capability_set_new (); priv->client_caps = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) gabble_capability_set_free); priv->client_data_forms = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_ptr_array_unref); /* Historically, the optional Jingle transports were in our initial * presence, but could be removed by AdvertiseCapabilities(). Emulate * that here for now. */ priv->bonus_caps = gabble_capability_set_new (); #ifdef ENABLE_VOIP gabble_capability_set_add (priv->bonus_caps, NS_GOOGLE_TRANSPORT_P2P); gabble_capability_set_add (priv->bonus_caps, NS_JINGLE_TRANSPORT_ICEUDP); #endif return (GObject *) self; } static gchar * dup_default_resource (void) { /* This is a once-per-process leak. */ static gchar *default_resource = NULL; if (G_UNLIKELY (default_resource == NULL)) { char *local_machine_id = dbus_get_local_machine_id (); if (local_machine_id == NULL) g_error ("Out of memory getting local machine ID"); default_resource = sha1_hex (local_machine_id, strlen (local_machine_id)); /* Let's keep the resource a maneagable length. */ default_resource[8] = '\0'; dbus_free (local_machine_id); } return g_strdup (default_resource); } static void gabble_connection_constructed (GObject *object) { GabbleConnection *self = GABBLE_CONNECTION (object); GabbleConnectionPrivate *priv = self->priv; void (*chain_up)(GObject *) = G_OBJECT_CLASS (gabble_connection_parent_class)->constructed; if (chain_up != NULL) chain_up (object); if (priv->resource == NULL) { priv->resource = dup_default_resource (); DEBUG ("defaulted resource to %s", priv->resource); } /* set initial presence */ self->self_presence = gabble_presence_new (); g_assert (priv->resource); gabble_presence_update (self->self_presence, priv->resource, GABBLE_PRESENCE_AVAILABLE, NULL, priv->priority, NULL, time (NULL)); } static void gabble_connection_init (GabbleConnection *self) { GError *error = NULL; GabbleConnectionPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_CONNECTION, GabbleConnectionPrivate); DEBUG("Initializing (GabbleConnection *)%p", self); self->daemon = tp_dbus_daemon_dup (&error); if (self->daemon == NULL) { g_error ("Failed to connect to dbus daemon: %s", error->message); } self->priv = priv; priv->iq_reply_cancellable = g_cancellable_new (); priv->caps_serial = 1; priv->last_activity_time = time (NULL); priv->port = 5222; gabble_capabilities_init (self); } static void gabble_connection_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleConnection *self = (GabbleConnection *) object; GabbleConnectionPrivate *priv = self->priv; switch (property_id) { case PROP_CONNECT_SERVER: g_value_set_string (value, priv->connect_server); break; case PROP_EXPLICIT_SERVER: g_value_set_string (value, priv->explicit_server); break; case PROP_STREAM_SERVER: g_value_set_string (value, priv->stream_server); break; case PROP_PORT: g_value_set_uint (value, priv->port); break; case PROP_OLD_SSL: g_value_set_boolean (value, priv->old_ssl); break; case PROP_REQUIRE_ENCRYPTION: g_value_set_boolean (value, priv->require_encryption); break; case PROP_REGISTER: g_value_set_boolean (value, priv->do_register); break; case PROP_LOW_BANDWIDTH: g_value_set_boolean (value, priv->low_bandwidth); break; case PROP_USERNAME: g_value_set_string (value, priv->username); break; case PROP_PASSWORD: g_value_set_string (value, priv->password); break; case PROP_RESOURCE: g_value_set_string (value, priv->resource); break; case PROP_PRIORITY: g_value_set_schar (value, priv->priority); break; case PROP_HTTPS_PROXY_SERVER: g_value_set_string (value, priv->https_proxy_server); break; case PROP_HTTPS_PROXY_PORT: g_value_set_uint (value, priv->https_proxy_port); break; case PROP_FALLBACK_CONFERENCE_SERVER: g_value_set_string (value, priv->fallback_conference_server); break; case PROP_IGNORE_SSL_ERRORS: g_value_set_boolean (value, priv->ignore_ssl_errors); break; case PROP_ALIAS: g_value_set_string (value, priv->alias); break; case PROP_STUN_SERVER: g_value_set_string (value, priv->stun_server); break; case PROP_STUN_PORT: g_value_set_uint (value, priv->stun_port); break; case PROP_FALLBACK_STUN_SERVER: g_value_set_string (value, priv->fallback_stun_server); break; case PROP_FALLBACK_STUN_PORT: g_value_set_uint (value, priv->fallback_stun_port); break; case PROP_FALLBACK_SOCKS5_PROXIES: g_value_set_boxed (value, priv->fallback_socks5_proxies); break; case PROP_KEEPALIVE_INTERVAL: g_value_set_uint (value, priv->keepalive_interval); break; case PROP_DECLOAK_AUTOMATICALLY: g_value_set_boolean (value, priv->decloak_automatically); break; case PROP_FALLBACK_SERVERS: g_value_set_boxed (value, priv->fallback_servers); break; case PROP_EXTRA_CERTIFICATE_IDENTITIES: g_value_set_boxed (value, priv->extra_certificate_identities); break; case PROP_POWER_SAVING: g_value_set_boolean (value, priv->power_saving); break; case PROP_DOWNLOAD_AT_CONNECTION: { gboolean download_at_connection = TRUE; if (self->roster != NULL) { g_object_get (self->roster, "download-at-connection", &download_at_connection, NULL); } else { g_warn_if_reached (); } g_value_set_boolean (value, download_at_connection); break; } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_connection_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleConnection *self = (GabbleConnection *) object; GabbleConnectionPrivate *priv = self->priv; switch (property_id) { case PROP_EXPLICIT_SERVER: g_free (priv->explicit_server); priv->explicit_server = g_value_dup_string (value); if (priv->connect_server == NULL) priv->connect_server = g_value_dup_string (value); break; case PROP_PORT: priv->port = g_value_get_uint (value); break; case PROP_OLD_SSL: priv->old_ssl = g_value_get_boolean (value); break; case PROP_REQUIRE_ENCRYPTION: priv->require_encryption = g_value_get_boolean (value); break; case PROP_REGISTER: priv->do_register = g_value_get_boolean (value); break; case PROP_LOW_BANDWIDTH: priv->low_bandwidth = g_value_get_boolean (value); break; case PROP_STREAM_SERVER: g_free (priv->stream_server); priv->stream_server = g_value_dup_string (value); break; case PROP_USERNAME: g_free (priv->username); priv->username = g_value_dup_string (value); break; case PROP_PASSWORD: g_free (priv->password); priv->password = g_value_dup_string (value); break; case PROP_RESOURCE: if (tp_strdiff (priv->resource, g_value_get_string (value))) { gchar *old_resource = priv->resource; gchar *new_resource = g_value_dup_string (value); time_t now = time (NULL); priv->resource = new_resource; /* Add self presence for new resource... */ gabble_presence_update (self->self_presence, new_resource, self->self_presence->status, self->self_presence->status_message, priv->priority, NULL, now); /* ...and remove it for the old one. */ gabble_presence_update (self->self_presence, old_resource, GABBLE_PRESENCE_OFFLINE, NULL, 0, NULL, now); g_free (old_resource); } break; case PROP_PRIORITY: priv->priority = g_value_get_schar (value); break; case PROP_HTTPS_PROXY_SERVER: g_free (priv->https_proxy_server); priv->https_proxy_server = g_value_dup_string (value); break; case PROP_HTTPS_PROXY_PORT: priv->https_proxy_port = g_value_get_uint (value); break; case PROP_FALLBACK_CONFERENCE_SERVER: g_free (priv->fallback_conference_server); priv->fallback_conference_server = g_value_dup_string (value); break; case PROP_IGNORE_SSL_ERRORS: priv->ignore_ssl_errors = g_value_get_boolean (value); break; case PROP_ALIAS: g_free (priv->alias); priv->alias = g_value_dup_string (value); break; case PROP_STUN_SERVER: g_free (priv->stun_server); priv->stun_server = g_value_dup_string (value); break; case PROP_STUN_PORT: priv->stun_port = g_value_get_uint (value); break; case PROP_FALLBACK_STUN_SERVER: g_free (priv->fallback_stun_server); priv->fallback_stun_server = g_value_dup_string (value); break; case PROP_FALLBACK_STUN_PORT: priv->fallback_stun_port = g_value_get_uint (value); break; case PROP_FALLBACK_SOCKS5_PROXIES: if (priv->fallback_socks5_proxies != NULL) g_strfreev (priv->fallback_socks5_proxies); priv->fallback_socks5_proxies = g_value_dup_boxed (value); break; case PROP_KEEPALIVE_INTERVAL: priv->keepalive_interval = g_value_get_uint (value); if (priv->pinger != NULL) g_object_set (priv->pinger, "ping-interval", priv->keepalive_interval, NULL); break; case PROP_DECLOAK_AUTOMATICALLY: priv->decloak_automatically = g_value_get_boolean (value); break; case PROP_FALLBACK_SERVERS: if (priv->fallback_servers != NULL) g_strfreev (priv->fallback_servers); priv->fallback_servers = g_value_dup_boxed (value); priv->fallback_server_index = 0; break; case PROP_EXTRA_CERTIFICATE_IDENTITIES: if (priv->extra_certificate_identities != NULL) g_strfreev (priv->extra_certificate_identities); priv->extra_certificate_identities = g_value_dup_boxed (value); break; case PROP_POWER_SAVING: priv->power_saving = g_value_get_boolean (value); break; case PROP_DOWNLOAD_AT_CONNECTION: /* Connection parameters are set by TpBaseProtocolClass->new_connection * after the channel managers are created. So at this step self->roster * is not NULL and we pass the property. */ if (self->roster != NULL) g_object_set (self->roster, "download-at-connection", g_value_get_boolean (value), NULL); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_connection_dispose (GObject *object); static void gabble_connection_finalize (GObject *object); static void connection_shut_down (TpBaseConnection *base); static gboolean _gabble_connection_connect (TpBaseConnection *base, GError **error); static gchar * gabble_connection_get_unique_name (TpBaseConnection *self) { GabbleConnectionPrivate *priv = GABBLE_CONNECTION (self)->priv; gchar *unique_name = gabble_encode_jid (priv->username, priv->stream_server, priv->resource); if (priv->username == NULL) { gchar *tmp = unique_name; unique_name = g_strdup_printf ("%s_%p", tmp, self); g_free (tmp); } return unique_name; } /* For the benefit of the unit tests, this will allow the connection to * be NULL */ void _gabble_connection_create_handle_repos (TpBaseConnection *conn, TpHandleRepoIface *repos[NUM_TP_HANDLE_TYPES]) { repos[TP_HANDLE_TYPE_CONTACT] = tp_dynamic_handle_repo_new (TP_HANDLE_TYPE_CONTACT, gabble_normalize_contact, GUINT_TO_POINTER (GABBLE_JID_ANY)); repos[TP_HANDLE_TYPE_ROOM] = tp_dynamic_handle_repo_new (TP_HANDLE_TYPE_ROOM, gabble_normalize_room, conn); } #define TWICE(x) (x), (x) static const gchar *implemented_interfaces[] = { /* conditionally present interfaces */ TP_IFACE_CONNECTION_INTERFACE_MAIL_NOTIFICATION, GABBLE_IFACE_OLPC_ACTIVITY_PROPERTIES, GABBLE_IFACE_OLPC_BUDDY_INFO, /* always present interfaces */ TP_IFACE_CONNECTION_INTERFACE_POWER_SAVING, TP_IFACE_CONNECTION_INTERFACE_ALIASING, TP_IFACE_CONNECTION_INTERFACE_CAPABILITIES, TP_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE, TP_IFACE_CONNECTION_INTERFACE_PRESENCE, TP_IFACE_CONNECTION_INTERFACE_AVATARS, TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO, TP_IFACE_CONNECTION_INTERFACE_CONTACTS, TP_IFACE_CONNECTION_INTERFACE_CONTACT_LIST, TP_IFACE_CONNECTION_INTERFACE_CONTACT_GROUPS, TP_IFACE_CONNECTION_INTERFACE_REQUESTS, TP_IFACE_CONNECTION_INTERFACE_CONTACT_CAPABILITIES, TP_IFACE_CONNECTION_INTERFACE_LOCATION, GABBLE_IFACE_CONNECTION_INTERFACE_GABBLE_DECLOAK, GABBLE_IFACE_CONNECTION_FUTURE, TP_IFACE_CONNECTION_INTERFACE_CLIENT_TYPES, GABBLE_IFACE_CONNECTION_INTERFACE_ADDRESSING, NULL }; static const gchar **interfaces_always_present = implemented_interfaces + 3; const gchar ** gabble_connection_get_implemented_interfaces (void) { return implemented_interfaces; } const gchar ** gabble_connection_get_guaranteed_interfaces (void) { return interfaces_always_present; } static GPtrArray * _gabble_connection_get_interfaces_always_present (TpBaseConnection *base) { GPtrArray *interfaces; const gchar **iter; interfaces = TP_BASE_CONNECTION_CLASS ( gabble_connection_parent_class)->get_interfaces_always_present (base); for (iter = interfaces_always_present; *iter != NULL; iter++) g_ptr_array_add (interfaces, (gchar *) *iter); return interfaces; } static void gabble_connection_class_init (GabbleConnectionClass *gabble_connection_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_connection_class); TpBaseConnectionClass *parent_class = TP_BASE_CONNECTION_CLASS ( gabble_connection_class); static TpDBusPropertiesMixinPropImpl location_props[] = { { "LocationAccessControlTypes", NULL, NULL }, { "LocationAccessControl", NULL, NULL }, { "SupportedLocationFeatures", NULL, NULL }, { NULL } }; static TpDBusPropertiesMixinPropImpl decloak_props[] = { { "DecloakAutomatically", TWICE ("decloak-automatically") }, { NULL } }; static TpDBusPropertiesMixinPropImpl mail_notif_props[] = { { "MailNotificationFlags", NULL, NULL }, { "UnreadMailCount", NULL, NULL }, { "UnreadMails", NULL, NULL }, { "MailAddress", NULL, NULL }, { NULL } }; static TpDBusPropertiesMixinPropImpl power_saving_props[] = { { "PowerSavingActive", "power-saving", NULL }, { NULL } }; static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { /* 0 */ { TP_IFACE_CONNECTION_INTERFACE_LOCATION, conn_location_properties_getter, conn_location_properties_setter, location_props, }, /* 1 */ { TP_IFACE_CONNECTION_INTERFACE_AVATARS, conn_avatars_properties_getter, NULL, NULL, }, /* 2 */ { TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO, conn_contact_info_properties_getter, NULL, NULL, }, /* 3 */ { GABBLE_IFACE_CONNECTION_INTERFACE_GABBLE_DECLOAK, tp_dbus_properties_mixin_getter_gobject_properties, tp_dbus_properties_mixin_setter_gobject_properties, decloak_props, }, { TP_IFACE_CONNECTION_INTERFACE_MAIL_NOTIFICATION, conn_mail_notif_properties_getter, NULL, mail_notif_props, }, { TP_IFACE_CONNECTION_INTERFACE_POWER_SAVING, tp_dbus_properties_mixin_getter_gobject_properties, NULL, power_saving_props, }, { NULL } }; prop_interfaces[1].props = conn_avatars_properties; prop_interfaces[2].props = conn_contact_info_properties; DEBUG("Initializing (GabbleConnectionClass *)%p", gabble_connection_class); object_class->get_property = gabble_connection_get_property; object_class->set_property = gabble_connection_set_property; object_class->constructor = gabble_connection_constructor; object_class->constructed = gabble_connection_constructed; parent_class->create_handle_repos = _gabble_connection_create_handle_repos; parent_class->get_unique_connection_name = gabble_connection_get_unique_name; parent_class->create_channel_factories = NULL; parent_class->create_channel_managers = _gabble_connection_create_channel_managers; parent_class->shut_down = connection_shut_down; parent_class->start_connecting = _gabble_connection_connect; parent_class->get_interfaces_always_present = _gabble_connection_get_interfaces_always_present; g_type_class_add_private (gabble_connection_class, sizeof (GabbleConnectionPrivate)); object_class->dispose = gabble_connection_dispose; object_class->finalize = gabble_connection_finalize; g_object_class_install_property (object_class, PROP_CONNECT_SERVER, g_param_spec_string ( "connect-server", "Hostname or IP of Jabber server", "The server used when establishing a connection.", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); /* * The explicit-server property can be used for verification of a * server certificate. It's important that it comes from the user * and is not the result of any other outside lookup, unlike the * connect-server property. */ g_object_class_install_property (object_class, PROP_EXPLICIT_SERVER, g_param_spec_string ( "explicit-server", "Explicit Hostname or IP of Jabber server", "Server explicitly specified by the user to connect to.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_PORT, g_param_spec_uint ( "port", "Jabber server port", "The port used when establishing a connection.", 1, G_MAXUINT16, 5222, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_OLD_SSL, g_param_spec_boolean ( "old-ssl", "Old-style SSL tunneled connection", "Establish the entire connection to the server within an " "SSL-encrypted tunnel. Note that this is not the same as connecting " "with TLS, which is not yet supported.", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property ( object_class, PROP_REQUIRE_ENCRYPTION, g_param_spec_boolean ( "require-encryption", "Require encryption", "Require the connection to be encrypted, either via old-style SSL, " "or StartTLS mechanisms.", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_REGISTER, g_param_spec_boolean ( "register", "Register account on server", "Register a new account on server.", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_LOW_BANDWIDTH, g_param_spec_boolean ( "low-bandwidth", "Low bandwidth mode", "Determines whether we are in low bandwidth mode. This influences " "polling behaviour.", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_STREAM_SERVER, g_param_spec_string ( "stream-server", "The server name used to initialise the stream.", "The server name used when initialising the stream, which is " "usually the part after the @ in the user's JID.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_USERNAME, g_param_spec_string ( "username", "Jabber username", "The username used when authenticating.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_PASSWORD, g_param_spec_string ( "password", "Jabber password", "The password used when authenticating.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_RESOURCE, g_param_spec_string ( "resource", "Jabber resource", "The Jabber resource used when authenticating.", "Telepathy", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_PRIORITY, g_param_spec_char ( "priority", "Jabber presence priority", "The default priority used when reporting our presence.", G_MININT8, G_MAXINT8, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_HTTPS_PROXY_SERVER, g_param_spec_string ( "https-proxy-server", "The server name used as an HTTPS proxy server", "The server name used as an HTTPS proxy server.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_HTTPS_PROXY_PORT, g_param_spec_uint ( "https-proxy-port", "The HTTP proxy server port", "The HTTP proxy server port.", 0, G_MAXUINT16, GABBLE_PARAMS_DEFAULT_HTTPS_PROXY_PORT, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_FALLBACK_CONFERENCE_SERVER, g_param_spec_string ( "fallback-conference-server", "The conference server used as fallback", "The conference server used as fallback when everything else fails.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_STUN_SERVER, g_param_spec_string ( "stun-server", "STUN server", "STUN server.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_STUN_PORT, g_param_spec_uint ( "stun-port", "STUN port", "STUN port.", 0, G_MAXUINT16, GABBLE_PARAMS_DEFAULT_STUN_PORT, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_FALLBACK_STUN_SERVER, g_param_spec_string ( "fallback-stun-server", "fallback STUN server", "Fallback STUN server.", GABBLE_PARAMS_DEFAULT_FALLBACK_STUN_SERVER, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_FALLBACK_STUN_PORT, g_param_spec_uint ( "fallback-stun-port", "fallback STUN port", "Fallback STUN port.", 0, G_MAXUINT16, GABBLE_PARAMS_DEFAULT_STUN_PORT, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_IGNORE_SSL_ERRORS, g_param_spec_boolean ( "ignore-ssl-errors", "Ignore SSL errors", "Continue connecting even if the server's " "SSL certificate is invalid or missing.", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_ALIAS, g_param_spec_string ( "alias", "Alias/nick for local user", "Alias/nick for local user", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_FALLBACK_SOCKS5_PROXIES, g_param_spec_boxed ( "fallback-socks5-proxies", "fallback SOCKS5 proxies", "Fallback SOCKS5 proxies.", G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_KEEPALIVE_INTERVAL, g_param_spec_uint ( "keepalive-interval", "keepalive interval", "Seconds between keepalive packets, or 0 to disable", 0, G_MAXUINT, 30, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property ( object_class, PROP_DECLOAK_AUTOMATICALLY, g_param_spec_boolean ( "decloak-automatically", "Decloak automatically?", "Leak presence and capabilities when requested", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property ( object_class, PROP_DOWNLOAD_AT_CONNECTION, g_param_spec_boolean ( "download-roster-at-connection", "Download the contact list at connection?", "Download the contact list at connection?", TRUE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_FALLBACK_SERVERS, g_param_spec_boxed ( "fallback-servers", "Fallback servers", "List of servers to fallback to (syntax server[:port][,oldssl]", G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_EXTRA_CERTIFICATE_IDENTITIES, g_param_spec_boxed ( "extra-certificate-identities", "Extra Certificate Reference Identities", "Extra identities to check certificate against. These are present as a " "result of a user choice or configuration.", G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property ( object_class, PROP_POWER_SAVING, g_param_spec_boolean ( "power-saving", "Power saving active?", "Queue remote presence updates server-side for less network chatter", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); gabble_connection_class->properties_class.interfaces = prop_interfaces; tp_dbus_properties_mixin_class_init (object_class, G_STRUCT_OFFSET (GabbleConnectionClass, properties_class)); tp_contacts_mixin_class_init (object_class, G_STRUCT_OFFSET (GabbleConnectionClass, contacts_class)); conn_presence_class_init (gabble_connection_class); conn_contact_info_class_init (gabble_connection_class); tp_base_contact_list_mixin_class_init (parent_class); } static void gabble_connection_dispose (GObject *object) { GabbleConnection *self = GABBLE_CONNECTION (object); TpBaseConnection *base = (TpBaseConnection *) self; GabbleConnectionPrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; DEBUG ("called"); g_assert ((tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_DISCONNECTED) || (tp_base_connection_get_status (base) == TP_INTERNAL_CONNECTION_STATUS_NEW)); tp_clear_object (&self->bytestream_factory); tp_clear_object (&self->disco); tp_clear_object (&self->req_pipeline); tp_clear_object (&self->vcard_manager); #ifdef ENABLE_VOIP tp_clear_object (&self->jingle_mint); #endif /* remove borrowed references before TpBaseConnection unrefs the channel * factories */ self->roster = NULL; self->muc_factory = NULL; self->private_tubes_factory = NULL; priv->auth_manager = NULL; tp_clear_object (&self->self_presence); tp_clear_object (&self->presence_cache); conn_olpc_activity_properties_dispose (self); g_hash_table_unref (self->avatar_requests); g_hash_table_unref (self->vcard_requests); conn_presence_dispose (self); conn_mail_notif_dispose (self); tp_clear_object (&priv->connector); tp_clear_object (&self->session); /* The porter was borrowed from the session. */ priv->porter = NULL; /* Cancel any outstanding _gabble_connection_send_with_reply() requests. */ g_cancellable_cancel (priv->iq_reply_cancellable); tp_clear_object (&priv->iq_reply_cancellable); g_hash_table_unref (priv->client_caps); gabble_capability_set_free (priv->all_caps); gabble_capability_set_free (priv->notify_caps); gabble_capability_set_free (priv->legacy_caps); gabble_capability_set_free (priv->sidecar_caps); gabble_capability_set_free (priv->bonus_caps); g_hash_table_unref (priv->client_data_forms); if (priv->disconnect_timer != 0) { g_source_remove (priv->disconnect_timer); priv->disconnect_timer = 0; } tp_clear_object (&self->pep_location); tp_clear_object (&self->pep_nick); tp_clear_object (&self->pep_olpc_buddy_props); tp_clear_object (&self->pep_olpc_activities); tp_clear_object (&self->pep_olpc_current_act); tp_clear_object (&self->pep_olpc_act_props); conn_sidecars_dispose (self); tp_clear_object (&self->daemon); if (G_OBJECT_CLASS (gabble_connection_parent_class)->dispose) G_OBJECT_CLASS (gabble_connection_parent_class)->dispose (object); } static void gabble_connection_finalize (GObject *object) { GabbleConnection *self = GABBLE_CONNECTION (object); GabbleConnectionPrivate *priv = self->priv; DEBUG ("called with %p", object); g_free (priv->connect_server); g_free (priv->explicit_server); g_free (priv->stream_server); g_free (priv->username); g_free (priv->password); g_free (priv->resource); g_free (priv->https_proxy_server); g_free (priv->stun_server); g_free (priv->fallback_stun_server); g_free (priv->fallback_conference_server); g_strfreev (priv->fallback_socks5_proxies); g_strfreev (priv->fallback_servers); g_strfreev (priv->extra_certificate_identities); g_free (priv->alias); g_free (priv->stream_id); tp_contacts_mixin_finalize (G_OBJECT(self)); conn_presence_finalize (self); conn_contact_info_finalize (self); gabble_capabilities_finalize (self); G_OBJECT_CLASS (gabble_connection_parent_class)->finalize (object); } /** * _gabble_connection_set_properties_from_account * * Parses an account string which may be one of the following forms: * username@server * username@server/resource * and sets the properties for username, stream server and resource * appropriately. Also sets the connect server to the stream server if one has * not yet been specified. */ gboolean _gabble_connection_set_properties_from_account (GabbleConnection *conn, const gchar *account, GError **error) { char *username, *server, *resource; gboolean result; g_assert (GABBLE_IS_CONNECTION (conn)); g_assert (account != NULL); username = server = resource = NULL; result = TRUE; if (!wocky_decode_jid (account, &username, &server, &resource)) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "unable to extract JID from account name"); result = FALSE; goto OUT; } g_object_set (G_OBJECT (conn), "username", username, "stream-server", server, NULL); /* only override the default resource if we actually got one */ if (resource) g_object_set (G_OBJECT (conn), "resource", resource, NULL); OUT: g_free (username); g_free (server); g_free (resource); return result; } /** * gabble_connection_get_full_jid: * * Returns: the full jid (including resource) of this connection, which must be * freed by the caller. */ gchar * gabble_connection_get_full_jid (GabbleConnection *conn) { const gchar *bare_jid = conn_util_get_bare_self_jid (conn); return g_strconcat (bare_jid, "/", conn->priv->resource, NULL); } static gchar * _gabble_plugin_connection_get_full_jid (GabblePluginConnection *plugin_conn) { GabbleConnection *conn = GABBLE_CONNECTION (plugin_conn); return gabble_connection_get_full_jid (conn); } /** * gabble_connection_dup_porter: * * Returns: (transfer full): the #WockyPorter instance driving this connection. */ WockyPorter *gabble_connection_dup_porter (GabbleConnection *conn) { GabbleConnectionPrivate *priv; g_assert (GABBLE_IS_CONNECTION (conn)); priv = conn->priv; if (priv->porter != NULL) return g_object_ref (priv->porter); return NULL; } WockySession * gabble_connection_get_session (GabblePluginConnection *plugin_connection) { GabbleConnection *connection = GABBLE_CONNECTION (plugin_connection); g_return_val_if_fail (GABBLE_IS_CONNECTION (connection), NULL); return connection->session; } /** * _gabble_connection_send * * Send an WockyStanza and trap network errors appropriately. */ gboolean _gabble_connection_send (GabbleConnection *conn, WockyStanza *msg, GError **error) { g_assert (GABBLE_IS_CONNECTION (conn)); if (conn->priv->porter == NULL) { g_set_error_literal (error, TP_ERROR, TP_ERROR_NETWORK_ERROR, "connection is disconnected"); return FALSE; } wocky_porter_send (conn->priv->porter, msg); return TRUE; } void gabble_connection_update_last_use (GabbleConnection *conn) { conn->priv->last_activity_time = time (NULL); } static gdouble gabble_connection_get_last_use (GabbleConnection *conn) { return difftime (time (NULL), conn->priv->last_activity_time); } typedef struct { GabbleConnectionMsgReplyFunc reply_func; GabbleConnection *conn; WockyStanza *sent_msg; gpointer user_data; GObject *object; gboolean object_alive; } GabbleMsgHandlerData; static void message_send_object_destroy_notify_cb (gpointer data, GObject *where_the_object_was) { GabbleMsgHandlerData *handler_data = data; handler_data->object = NULL; handler_data->object_alive = FALSE; } static void msg_handler_data_free (GabbleMsgHandlerData *handler_data) { g_object_unref (handler_data->sent_msg); if (handler_data->object != NULL) { g_object_weak_unref (handler_data->object, message_send_object_destroy_notify_cb, handler_data); } g_slice_free (GabbleMsgHandlerData, handler_data); } static void message_send_reply_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { GabbleMsgHandlerData *handler_data = user_data; if (handler_data->object_alive && handler_data->reply_func != NULL) { WockyPorter *porter = WOCKY_PORTER (source); GError *error = NULL; WockyStanza *stanza = wocky_porter_send_iq_finish (porter, result, &error); if (stanza != NULL) { handler_data->reply_func (handler_data->conn, handler_data->sent_msg, stanza, handler_data->object, handler_data->user_data); g_object_unref (stanza); } else { DEBUG ("send_iq_async failed: %s", error->message); g_error_free (error); } } msg_handler_data_free (handler_data); } /** * _gabble_connection_send_with_reply * * Send a tracked WockyStanza and trap network errors appropriately. * * If object is non-NULL the handler will follow the lifetime of that object, * which means that if the object is destroyed the callback will not be invoked. * * if reply_func is NULL the reply will be ignored. */ gboolean _gabble_connection_send_with_reply (GabbleConnection *conn, WockyStanza *msg, GabbleConnectionMsgReplyFunc reply_func, GObject *object, gpointer user_data, GError **error) { GabbleConnectionPrivate *priv; GabbleMsgHandlerData *handler_data; g_assert (GABBLE_IS_CONNECTION (conn)); priv = conn->priv; if (priv->porter == NULL) { g_set_error_literal (error, TP_ERROR, TP_ERROR_NETWORK_ERROR, "connection is disconnected"); return FALSE; } g_object_ref (msg); handler_data = g_slice_new (GabbleMsgHandlerData); handler_data->reply_func = reply_func; handler_data->conn = conn; handler_data->sent_msg = msg; handler_data->user_data = user_data; handler_data->object = object; handler_data->object_alive = TRUE; if (object != NULL) { g_object_weak_ref (object, message_send_object_destroy_notify_cb, handler_data); } wocky_porter_send_iq_async (priv->porter, msg, priv->iq_reply_cancellable, message_send_reply_cb, handler_data); return TRUE; } static void connect_iq_callbacks (GabbleConnection *conn); static gboolean iq_disco_cb (WockyPorter *, WockyStanza *, gpointer); static gboolean iq_version_cb (WockyPorter *, WockyStanza *, gpointer); static void connection_disco_cb (GabbleDisco *, GabbleDiscoRequest *, const gchar *, const gchar *, WockyNode *, GError *, gpointer); static void decrement_waiting_connected (GabbleConnection *connection); static void connection_initial_presence_cb (GObject *, GAsyncResult *, gpointer); static void gabble_connection_disconnect_with_tp_error (GabbleConnection *self, const GError *tp_error, TpConnectionStatusReason reason) { TpBaseConnection *base = (TpBaseConnection *) self; GHashTable *details = tp_asv_new ( "debug-message", G_TYPE_STRING, tp_error->message, NULL); g_assert (tp_error->domain == TP_ERROR); tp_base_connection_disconnect_with_dbus_error (base, tp_error_get_dbus_name (tp_error->code), details, reason); g_hash_table_unref (details); } static void remote_closed_cb (WockyPorter *porter, GabbleConnection *self) { TpBaseConnection *base = TP_BASE_CONNECTION (self); GError e = { TP_ERROR, TP_ERROR_CONNECTION_LOST, "server closed its XMPP stream" }; if (tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_DISCONNECTED) /* Ignore if we are already disconnecting/disconnected */ return; DEBUG ("server closed its XMPP stream; close ours"); /* Changing the state to Disconnect will call connection_shut_down which * will properly close the porter. */ gabble_connection_disconnect_with_tp_error (self, &e, TP_CONNECTION_STATUS_REASON_NETWORK_ERROR); } static void force_close_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GabbleConnection *self = GABBLE_CONNECTION (user_data); TpBaseConnection *base = TP_BASE_CONNECTION (self); GError *error = NULL; if (!wocky_porter_force_close_finish (WOCKY_PORTER (source), res, &error)) { DEBUG ("force close failed: %s", error->message); g_error_free (error); } else { DEBUG ("connection properly closed (forced)"); } tp_base_connection_finish_shutdown (base); } static void remote_error_cb (WockyPorter *porter, GQuark domain, gint code, gchar *msg, GabbleConnection *self) { TpConnectionStatusReason reason = TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED; TpBaseConnection *base = (TpBaseConnection *) self; GabbleConnectionPrivate *priv = self->priv; GError e = { domain, code, msg }; GError *error = NULL; if (tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_DISCONNECTED) /* Ignore if we are already disconnecting/disconnected */ return; gabble_set_tp_conn_error_from_wocky (&e, tp_base_connection_get_status (base), &reason, &error); g_assert (error->domain == TP_ERROR); DEBUG ("Force closing of the connection %p", self); priv->closing = TRUE; wocky_porter_force_close_async (priv->porter, NULL, force_close_cb, self); gabble_connection_disconnect_with_tp_error (self, error, reason); g_error_free (error); } static void connector_error_disconnect (GabbleConnection *self, GError *error) { GError *tp_error = NULL; TpBaseConnection *base = (TpBaseConnection *) self; TpConnectionStatusReason reason = TP_CONNECTION_STATUS_REASON_NETWORK_ERROR; gchar *dbus_error = NULL; GHashTable *details = NULL; if (error->domain == GABBLE_SERVER_TLS_ERROR) { gabble_server_tls_manager_get_rejection_details ( self->priv->server_tls_manager, &dbus_error, &details, &reason); /* new-style interactive TLS verification error */ DEBUG ("New-style TLS verification error, reason %u, dbus error %s", reason, dbus_error); tp_base_connection_disconnect_with_dbus_error (base, dbus_error, details, reason); tp_clear_pointer (&details, g_hash_table_unref); g_free (dbus_error); return; } if (error->domain == WOCKY_AUTH_ERROR && gabble_auth_manager_get_failure_details (self->priv->auth_manager, &dbus_error, &details, &reason)) { DEBUG ("Interactive authentication error, reason %u, dbus error %s", reason, dbus_error); tp_base_connection_disconnect_with_dbus_error (base, dbus_error, details, reason); tp_clear_pointer (&details, g_hash_table_unref); g_free (dbus_error); return; } gabble_set_tp_conn_error_from_wocky (error, tp_base_connection_get_status (base), &reason, &tp_error); DEBUG ("connection failed: %s", tp_error->message); g_assert (tp_error->domain == TP_ERROR); gabble_connection_disconnect_with_tp_error (self, tp_error, reason); g_error_free (tp_error); } static void bare_jid_disco_cb (GabbleDisco *disco, GabbleDiscoRequest *request, const gchar *jid, const gchar *node, WockyNode *result, GError *disco_error, gpointer user_data) { GabbleConnection *conn = user_data; if (disco_error != NULL) { DEBUG ("Got disco error on bare jid: %s", disco_error->message); } else { WockyNodeIter i; WockyNode *child; wocky_node_iter_init (&i, result, "identity", NULL); while (wocky_node_iter_next (&i, &child)) { const gchar *category = wocky_node_get_attribute (child, "category"); const gchar *type = wocky_node_get_attribute (child, "type"); if (!tp_strdiff (category, "pubsub") && !tp_strdiff (type, "pep")) { DEBUG ("Server advertises PEP support in our jid features"); conn->features |= GABBLE_CONNECTION_FEATURES_PEP; } } } decrement_waiting_connected (conn); } /** * next_fallback_server * * Launch connection using next fallback server if any, return * FALSE if they all have been tried or the error is not * network related (e.g. login failed). */ static gboolean next_fallback_server (GabbleConnection *self, const GError *error) { GabbleConnectionPrivate *priv = self->priv; const gchar *server; gchar **split; guint port = 5222; gboolean old_ssl = FALSE; GNetworkAddress *addr; GError *tmp_error = NULL; /* Only retry on connection failures */ if (error->domain != G_IO_ERROR) return FALSE; if (priv->fallback_servers == NULL || priv->fallback_servers[priv->fallback_server_index] == NULL) return FALSE; server = priv->fallback_servers[priv->fallback_server_index++]; split = g_strsplit (server, ",", 2); if (split[0] == NULL) { g_strfreev (split); return FALSE; } else if (split[1] != NULL && !tp_strdiff (split[1], "oldssl")) { old_ssl = TRUE; port = 5223; } addr = G_NETWORK_ADDRESS ( g_network_address_parse (split[0], port, &tmp_error)); if (!addr) { g_warning ("%s", tmp_error->message); g_error_free (tmp_error); return FALSE; } g_free (priv->connect_server); priv->connect_server = g_strdup (g_network_address_get_hostname (addr)); priv->port = g_network_address_get_port (addr); priv->old_ssl = old_ssl; g_object_notify (G_OBJECT (self), "connect-server"); g_object_notify (G_OBJECT (self), "port"); g_object_notify (G_OBJECT (self), "old-ssl"); g_object_unref (addr); _gabble_connection_connect (TP_BASE_CONNECTION (self), NULL); g_strfreev (split); return TRUE; } /** * connector_connected * * Stage 2 of connecting, this function is called once the connect operation * has finished. It checks if the connection succeeded, creates and starts * the WockyPorter, then sends two discovery requests to find the * server's features (one to the server and one to our bare jid). */ static void connector_connected (GabbleConnection *self, WockyXmppConnection *conn, const gchar *jid, GError *error) { GabbleConnectionPrivate *priv = self->priv; TpBaseConnection *base = (TpBaseConnection *) self; TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); /* cleanup the cancellable */ tp_clear_object (&priv->cancellable); /* We went to closing while we were connecting... drop the connection and * finish the shutdown */ if (priv->closing) { if (conn != NULL) g_object_unref (conn); else g_error_free (error); tp_base_connection_finish_shutdown (base); return; } /* We don't need the connector any more */ tp_clear_object (&priv->connector); if (conn == NULL) { if (!next_fallback_server (self, error)) connector_error_disconnect (self, error); g_error_free (error); return; } DEBUG ("connected (jid: %s)", jid); self->session = wocky_session_new_with_connection (conn, jid); priv->porter = wocky_session_get_porter (self->session); g_assert (WOCKY_IS_C2S_PORTER (priv->porter)); priv->pinger = wocky_ping_new (WOCKY_C2S_PORTER (priv->porter), priv->keepalive_interval); g_signal_connect (priv->porter, "remote-closed", G_CALLBACK (remote_closed_cb), self); g_signal_connect (priv->porter, "remote-error", G_CALLBACK (remote_error_cb), self); g_signal_emit_by_name (self, "porter-available", priv->porter); connect_iq_callbacks (self); wocky_pep_service_start (self->pep_location, self->session); wocky_pep_service_start (self->pep_nick, self->session); wocky_pep_service_start (self->pep_olpc_buddy_props, self->session); wocky_pep_service_start (self->pep_olpc_activities, self->session); wocky_pep_service_start (self->pep_olpc_current_act, self->session); wocky_pep_service_start (self->pep_olpc_act_props, self->session); /* Don't use wocky_session_start as we don't want to start all the * components (Roster, presence-manager, etc) for now */ wocky_porter_start (priv->porter); tp_base_connection_set_self_handle (base, tp_handle_ensure (contact_handles, jid, NULL, &error)); if (tp_base_connection_get_self_handle (base) == 0) { DEBUG ("couldn't get our self handle: %s", error->message); if (error->domain != TP_ERROR) { error->domain = TP_ERROR; error->code = TP_ERROR_INVALID_HANDLE; } gabble_connection_disconnect_with_tp_error (self, error, TP_CONNECTION_STATUS_REASON_NETWORK_ERROR); g_error_free (error); return; } /* update priv->resource and priv->stream_server from the server's JID */ if (!_gabble_connection_set_properties_from_account (self, jid, &error)) { DEBUG ("couldn't parse our own JID: %s", error->message); if (error->domain != TP_ERROR) { error->domain = TP_ERROR; error->code = TP_ERROR_INVALID_ARGUMENT; } gabble_connection_disconnect_with_tp_error (self, error, TP_CONNECTION_STATUS_REASON_NETWORK_ERROR); g_error_free (error); return; } DEBUG ("Created self handle %d, our JID is %s", tp_base_connection_get_self_handle (base), jid); /* set initial capabilities */ gabble_connection_refresh_capabilities (self, NULL); /* Disco server features */ if (!gabble_disco_request_with_timeout (self->disco, GABBLE_DISCO_TYPE_INFO, priv->stream_server, NULL, disco_reply_timeout, connection_disco_cb, self, G_OBJECT (self), &error)) { DEBUG ("sending disco request failed: %s", error->message); if (error->domain != TP_ERROR) { error->domain = TP_ERROR; error->code = TP_ERROR_NETWORK_ERROR; } gabble_connection_disconnect_with_tp_error (self, error, TP_CONNECTION_STATUS_REASON_NETWORK_ERROR); g_error_free (error); } /* Disco our own bare jid to check if PEP is supported */ if (!gabble_disco_request_with_timeout (self->disco, GABBLE_DISCO_TYPE_INFO, conn_util_get_bare_self_jid (self), NULL, disco_reply_timeout, bare_jid_disco_cb, self, G_OBJECT (self), &error)) { DEBUG ("Sending disco request to our own bare jid failed: %s", error->message); if (error->domain != TP_ERROR) { error->domain = TP_ERROR; error->code = TP_ERROR_NETWORK_ERROR; } gabble_connection_disconnect_with_tp_error (self, error, TP_CONNECTION_STATUS_REASON_NETWORK_ERROR); g_error_free (error); } self->priv->waiting_connected = 2; } static void connector_connect_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GabbleConnection *self = GABBLE_CONNECTION (user_data); GabbleConnectionPrivate *priv = self->priv; WockyXmppConnection *conn; GError *error = NULL; gchar *jid = NULL; conn = wocky_connector_connect_finish (WOCKY_CONNECTOR (source), res, &jid, &(priv->stream_id), &error); connector_connected (self, conn, jid, error); g_free (jid); } static void connector_register_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GabbleConnection *self = GABBLE_CONNECTION (user_data); GabbleConnectionPrivate *priv = self->priv; WockyXmppConnection *conn; GError *error = NULL; gchar *jid = NULL; conn = wocky_connector_register_finish (WOCKY_CONNECTOR (source), res, &jid, &(priv->stream_id), &error); connector_connected (self, conn, jid, error); g_free (jid); } static gboolean connection_iq_last_cb ( WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { GabbleConnection *self = GABBLE_CONNECTION (user_data); const gchar *from = wocky_stanza_get_from (stanza); /* Aside from 21 being an appropriate number, 2 ^ 64 is 20 digits long. */ char seconds[21]; /* Check if the peer, if any, is authorized to receive our presence. */ if (from != NULL) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self, TP_HANDLE_TYPE_CONTACT); TpHandle handle = tp_handle_lookup (contact_repo, from, NULL, NULL); /* If there's no handle for them, they're certainly not on the roster. */ if (handle == 0 || !gabble_roster_handle_gets_presence_from_us (self->roster, handle)) { wocky_porter_send_iq_error (porter, stanza, WOCKY_XMPP_ERROR_FORBIDDEN, NULL); return TRUE; } } sprintf (seconds, "%.0f", gabble_connection_get_last_use (self)); wocky_porter_acknowledge_iq (porter, stanza, '(', "query", ':', NS_LAST, '@', "seconds", seconds, ')', NULL); return TRUE; } static void connect_iq_callbacks (GabbleConnection *conn) { GabbleConnectionPrivate *priv = conn->priv; wocky_porter_register_handler_from_anyone (priv->porter, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, iq_disco_cb, conn, '(', "query", ':', NS_DISCO_INFO, ')', NULL); wocky_porter_register_handler_from_anyone (priv->porter, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, iq_version_cb, conn, '(', "query", ':', NS_VERSION, ')', NULL); wocky_porter_register_handler_from_anyone (priv->porter, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, connection_iq_last_cb, conn, '(', "query", ':', NS_LAST, ')', NULL); } /** * _gabble_connection_connect * * Use the stored server & authentication details to commence * the stages for connecting to the server and authenticating. * Will create a WockyConnector. * * Stage 1 is _gabble_connection_connect calling wocky_connector_connect_async * Stage 2 is connector_connected initiating service discovery * Stage 3 is connection_disco_cb processing the server's features, and setting * initial presence * Stage 4 is set_status_to_connected setting the CONNECTED state. */ static gboolean _gabble_connection_connect (TpBaseConnection *base, GError **error) { GabbleConnection *conn = GABBLE_CONNECTION (base); GabbleConnectionPrivate *priv = conn->priv; WockyTLSHandler *tls_handler; char *jid; gboolean interactive_tls; gchar *user_certs_dir; g_assert (priv->connector == NULL); g_assert (priv->port <= G_MAXUINT16); g_assert (priv->stream_server != NULL); g_assert (priv->resource != NULL); jid = gabble_encode_jid (priv->username, priv->stream_server, NULL); tls_handler = WOCKY_TLS_HANDLER (priv->server_tls_manager); priv->connector = wocky_connector_new (jid, priv->password, priv->resource, WOCKY_AUTH_REGISTRY (priv->auth_manager), tls_handler); g_free (jid); #ifdef GTLS_SYSTEM_CA_CERTIFICATES /* system certs */ wocky_tls_handler_add_ca (tls_handler, GTLS_SYSTEM_CA_CERTIFICATES); #endif /* user certs */ user_certs_dir = g_build_filename (g_get_user_config_dir (), "telepathy", "certs", NULL); wocky_tls_handler_add_ca (tls_handler, user_certs_dir); g_free (user_certs_dir); /* If the UI explicitly specified a port or a server, pass them to Loudmouth * rather than letting it do an SRV lookup. * * If the port is 5222 (the default) then unless the UI also specified a * server or old-style SSL, we ignore it and do an SRV lookup anyway. This * means that UIs that blindly pass the default back to Gabble work * correctly. If the user really did mean 5222, then when the SRV lookup * fails we fall back to that anyway. */ if (priv->port != 5222 || priv->connect_server != NULL || priv->old_ssl) { gchar *server; if (priv->connect_server != NULL) server = priv->connect_server; else server = priv->stream_server; DEBUG ("disabling SRV because \"server\" or \"old-ssl\" was specified " "or port was not 5222, will connect to %s", server); g_object_set (priv->connector, "xmpp-server", server, "xmpp-port", priv->port, NULL); } else { DEBUG ("letting SRV lookup decide server and port"); } /* We want to enable interactive TLS verification also in * case encryption is not required, and we don't ignore SSL errors. */ interactive_tls = !conn->priv->ignore_ssl_errors; if (!conn->priv->require_encryption && !conn->priv->ignore_ssl_errors) { DEBUG ("require-encryption is False; flipping ignore_ssl_errors to True"); conn->priv->ignore_ssl_errors = TRUE; } g_object_set (priv->connector, "old-ssl", priv->old_ssl, /* We always wants to support old servers */ "legacy", TRUE, NULL); g_object_set (tls_handler, "interactive-tls", interactive_tls, "ignore-ssl-errors", priv->ignore_ssl_errors, NULL); if (priv->old_ssl) { g_object_set (priv->connector, "tls-required", FALSE, NULL); } else { g_object_set (priv->connector, "tls-required", priv->require_encryption, "plaintext-auth-allowed", !priv->require_encryption, NULL); } priv->cancellable = g_cancellable_new (); if (priv->do_register) { DEBUG ("Start registering"); wocky_connector_register_async (priv->connector, priv->cancellable, connector_register_cb, conn); } else { DEBUG ("Start connecting"); wocky_connector_connect_async (priv->connector, priv->cancellable, connector_connect_cb, conn); } return TRUE; } static void closed_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GabbleConnection *self = GABBLE_CONNECTION (user_data); GabbleConnectionPrivate *priv = self->priv; TpBaseConnection *base = TP_BASE_CONNECTION (self); GError *error = NULL; if (priv->disconnect_timer != 0) { /* stop the timer */ g_source_remove (priv->disconnect_timer); priv->disconnect_timer = 0; } if (!wocky_porter_close_finish (WOCKY_PORTER (source), res, &error)) { DEBUG ("close failed: %s", error->message); if (g_error_matches (error, WOCKY_PORTER_ERROR, WOCKY_PORTER_ERROR_FORCIBLY_CLOSED)) { /* Close operation has been aborted because a force_close operation * has been started. tp_base_connection_finish_shutdown will be * called once this force_close operation is completed so we don't * do it here. */ g_error_free (error); return; } g_error_free (error); } else { DEBUG ("connection properly closed"); } tp_base_connection_finish_shutdown (base); } static gboolean disconnect_timeout_cb (gpointer data) { GabbleConnection *self = GABBLE_CONNECTION (data); GabbleConnectionPrivate *priv = self->priv; DEBUG ("Close operation timed out. Force closing"); priv->disconnect_timer = 0; wocky_porter_force_close_async (priv->porter, NULL, force_close_cb, self); return FALSE; } static void connection_shut_down (TpBaseConnection *base) { GabbleConnection *self = GABBLE_CONNECTION (base); GabbleConnectionPrivate *priv = self->priv; tp_clear_object (&priv->pinger); if (priv->closing) return; priv->closing = TRUE; if (priv->porter != NULL) { DEBUG ("connection may still be open; closing it: %p", base); g_assert (priv->disconnect_timer == 0); priv->disconnect_timer = g_timeout_add_seconds (DISCONNECT_TIMEOUT, disconnect_timeout_cb, self); wocky_porter_close_async (priv->porter, NULL, closed_cb, self); return; } else if (priv->connector != NULL) { DEBUG ("Cancelling the porter connection"); g_cancellable_cancel (priv->cancellable); return; } DEBUG ("neither porter nor connector is alive: clean up the base connection"); tp_base_connection_finish_shutdown (base); } void gabble_connection_fill_in_caps (GabbleConnection *self, WockyStanza *presence_message) { GabblePresence *presence = self->self_presence; WockyNode *node = wocky_stanza_get_top_node (presence_message); gchar *caps_hash; gboolean share_v1, voice_v1, video_v1; GString *ext = g_string_new (""); /* XEP-0115 version 1.5 uses a verification string in the 'ver' attribute */ caps_hash = caps_hash_compute_from_self_presence (self); node = wocky_node_add_child_ns (node, "c", NS_CAPS); wocky_node_set_attributes ( node, "hash", "sha-1", "node", NS_GABBLE_CAPS, "ver", caps_hash, NULL); /* Ensure this set of capabilities is in the cache. */ gabble_presence_cache_add_own_caps (self->presence_cache, caps_hash, gabble_presence_peek_caps (presence), NULL, gabble_presence_peek_data_forms (presence)); /* XEP-0115 deprecates 'ext' feature bundles. But we still need * BUNDLE_VOICE_V1 it for backward-compatibility with Gabble 0.2 */ g_string_append (ext, BUNDLE_PMUC_V1); share_v1 = gabble_presence_has_cap (presence, NS_GOOGLE_FEAT_SHARE); voice_v1 = gabble_presence_has_cap (presence, NS_GOOGLE_FEAT_VOICE); video_v1 = gabble_presence_has_cap (presence, NS_GOOGLE_FEAT_VIDEO); if (share_v1) g_string_append (ext, " " BUNDLE_SHARE_V1); if (voice_v1) g_string_append (ext, " " BUNDLE_VOICE_V1); if (video_v1) g_string_append (ext, " " BUNDLE_VIDEO_V1); if (gabble_presence_has_cap (presence, NS_GOOGLE_FEAT_CAMERA)) g_string_append (ext, " " BUNDLE_CAMERA_V1); wocky_node_set_attribute (node, "ext", ext->str); g_string_free (ext, TRUE); g_free (caps_hash); } gboolean gabble_connection_send_capabilities (GabbleConnection *self, const gchar *recipient, GError **error) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self, TP_HANDLE_TYPE_CONTACT); WockyStanza *message; gboolean ret; TpHandle handle; /* if we don't have a handle allocated for the recipient, they clearly aren't * getting our presence... */ handle = tp_handle_lookup (contact_repo, recipient, NULL, NULL); if (handle != 0 && conn_presence_visible_to (self, handle)) { /* nothing to do, they should already have had our presence */ return TRUE; } /* We deliberately don't include anything except the caps here */ message = wocky_stanza_build ( WOCKY_STANZA_TYPE_PRESENCE, WOCKY_STANZA_SUB_TYPE_AVAILABLE, NULL, recipient, NULL); gabble_connection_fill_in_caps (self, message); ret = _gabble_connection_send (self, message, error); g_object_unref (message); return ret; } gboolean gabble_connection_request_decloak (GabbleConnection *self, const gchar *to, const gchar *reason, GError **error) { GabblePresence *presence = self->self_presence; WockyStanza *message = gabble_presence_as_message (presence, to); WockyNode *decloak; gboolean ret; gabble_connection_fill_in_caps (self, message); decloak = wocky_node_add_child_ns (wocky_stanza_get_top_node (message), "temppres", NS_TEMPPRES); if (reason != NULL && *reason != '\0') { wocky_node_set_attribute (decloak, "reason", reason); } ret = _gabble_connection_send (self, message, error); g_object_unref (message); return ret; } static gboolean gabble_connection_refresh_capabilities (GabbleConnection *self, GabbleCapabilitySet **old_out) { TpBaseConnection *base = (TpBaseConnection *) self; GError *error = NULL; GHashTableIter iter; gpointer k, v; GabbleCapabilitySet *save_set; GPtrArray *data_forms; save_set = self->priv->all_caps; self->priv->all_caps = gabble_capability_set_new (); data_forms = g_ptr_array_new (); gabble_capability_set_update (self->priv->all_caps, gabble_capabilities_get_fixed_caps ()); gabble_capability_set_update (self->priv->all_caps, self->priv->notify_caps); gabble_capability_set_update (self->priv->all_caps, self->priv->legacy_caps); gabble_capability_set_update (self->priv->all_caps, self->priv->sidecar_caps); gabble_capability_set_update (self->priv->all_caps, self->priv->bonus_caps); /* first, normal caps */ g_hash_table_iter_init (&iter, self->priv->client_caps); while (g_hash_table_iter_next (&iter, &k, &v)) { if (DEBUGGING) { gchar *s = gabble_capability_set_dump (v, " "); DEBUG ("incorporating caps for %s:\n%s", (const gchar *) k, s); g_free (s); } gabble_capability_set_update (self->priv->all_caps, v); } /* now data forms */ g_hash_table_iter_init (&iter, self->priv->client_data_forms); /* just borrow the ref, data_forms doesn't have a free func */ while (g_hash_table_iter_next (&iter, &k, &v)) tp_g_ptr_array_extend (data_forms, v); if (self->self_presence != NULL) gabble_presence_set_capabilities (self->self_presence, self->priv->resource, self->priv->all_caps, data_forms, self->priv->caps_serial++); if (gabble_capability_set_equals (self->priv->all_caps, save_set)) { gabble_capability_set_free (save_set); g_ptr_array_unref (data_forms); DEBUG ("nothing to do"); return FALSE; } /* don't signal presence unless we're already CONNECTED */ if (tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTED) { gabble_capability_set_free (save_set); g_ptr_array_unref (data_forms); DEBUG ("not emitting self-presence stanza: not connected yet"); return FALSE; } if (!conn_presence_signal_own_presence (self, NULL, &error)) { gabble_capability_set_free (save_set); g_ptr_array_unref (data_forms); DEBUG ("error sending presence: %s", error->message); g_error_free (error); return FALSE; } if (old_out == NULL) gabble_capability_set_free (save_set); else *old_out = save_set; g_ptr_array_unref (data_forms); return TRUE; } /** * _gabble_connection_send_iq_result * * Function used to acknowledge an IQ stanza. */ void _gabble_connection_acknowledge_set_iq (GabbleConnection *conn, WockyStanza *iq) { wocky_porter_acknowledge_iq (wocky_session_get_porter (conn->session), iq, NULL); } static void add_feature_node (gpointer namespace, gpointer result_query) { WockyNode *feature_node; feature_node = wocky_node_add_child_with_content (result_query, "feature", NULL); wocky_node_set_attribute (feature_node, "var", namespace); } static void add_identity_node (const GabbleDiscoIdentity *identity, gpointer result_query) { WockyNode *identity_node; identity_node = wocky_node_add_child_with_content (result_query, "identity", NULL); wocky_node_set_attribute (identity_node, "category", identity->category); wocky_node_set_attribute (identity_node, "type", identity->type); if (identity->lang) wocky_node_set_attribute (identity_node, "lang", identity->lang); if (identity->name) wocky_node_set_attribute (identity_node, "name", identity->name); } /** * iq_disco_cb * * Called by Wocky when we get an incoming with a * node. This handler handles disco-related IQs. */ static gboolean iq_disco_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { GabbleConnection *self = GABBLE_CONNECTION (user_data); WockyStanza *result; WockyNode *query, *result_query; const gchar *node, *suffix; const GabbleCapabilityInfo *info = NULL; const GabbleCapabilitySet *features = NULL; const GPtrArray *identities = NULL; const GPtrArray *data_forms = NULL; /* query's existence is checked by WockyPorter before this function is called */ query = wocky_node_get_child (wocky_stanza_get_top_node (stanza), "query"); node = wocky_node_get_attribute (query, "node"); if (node && ( 0 != strncmp (node, NS_GABBLE_CAPS "#", strlen (NS_GABBLE_CAPS) + 1) || strlen (node) < strlen (NS_GABBLE_CAPS) + 2)) { STANZA_DEBUG (stanza, "got iq disco query with unexpected node attribute"); return FALSE; } if (node == NULL) suffix = NULL; else suffix = node + strlen (NS_GABBLE_CAPS) + 1; result = wocky_stanza_build_iq_result (stanza, '(', "query", ':', NS_DISCO_INFO, '*', &result_query, ')', NULL); /* If we get an IQ without an id='', there's not much we can do. */ if (result == NULL) return FALSE; if (node) wocky_node_set_attribute (result_query, "node", node); if (node == NULL) { features = gabble_presence_peek_caps (self->self_presence); data_forms = gabble_presence_peek_data_forms (self->self_presence); } else { /* If node is not NULL, it can be either a caps bundle as defined in the * legacy XEP-0115 version 1.3 or an hash as defined in XEP-0115 version * 1.5. Let's see if it's a verification string we've told the cache about. */ info = gabble_presence_cache_peek_own_caps (self->presence_cache, suffix); } if (info) { features = info->cap_set; identities = info->identities; data_forms = info->data_forms; } if (identities && identities->len != 0) { g_ptr_array_foreach ((GPtrArray *) identities, (GFunc) add_identity_node, result_query); } else { /* Every entity MUST have at least one identity (XEP-0030). Gabble publishes * one identity. If you change the identity here, you also need to change * caps_hash_compute_from_self_presence(). */ wocky_node_add_build (result_query, '(', "identity", '@', "category", "client", '@', "name", PACKAGE_STRING, '@', "type", CLIENT_TYPE, ')', NULL); } if (features == NULL) { /* Otherwise, is it one of the caps bundles we advertise? These are not * just shoved into the cache with gabble_presence_cache_add_own_caps() * because capabilities_get_features() always includes a few bonus * features... */ if (!tp_strdiff (suffix, BUNDLE_SHARE_V1)) features = gabble_capabilities_get_bundle_share_v1 (); if (!tp_strdiff (suffix, BUNDLE_VOICE_V1)) features = gabble_capabilities_get_bundle_voice_v1 (); if (!tp_strdiff (suffix, BUNDLE_VIDEO_V1)) features = gabble_capabilities_get_bundle_video_v1 (); if (!tp_strdiff (suffix, BUNDLE_CAMERA_V1)) features = gabble_capabilities_get_bundle_camera_v1 (); } if (data_forms != NULL) { guint i; for (i = 0; i < data_forms->len; i++) { WockyDataForm *form = g_ptr_array_index (data_forms, i); wocky_data_form_add_to_node (form, result_query); } } if (features == NULL && tp_strdiff (suffix, BUNDLE_PMUC_V1)) { wocky_porter_send_iq_error (porter, stanza, WOCKY_XMPP_ERROR_ITEM_NOT_FOUND, NULL); } else { /* Send an empty reply for a pmuc-v1 disco, matching Google's behaviour. */ if (features != NULL) { gabble_capability_set_foreach (features, add_feature_node, result_query); } wocky_porter_send (self->priv->porter, result); } g_object_unref (result); return TRUE; } static gboolean iq_version_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { WockyStanza *result; result = wocky_stanza_build_iq_result (stanza, '(', "query", ':', NS_VERSION, '(', "name", '$', PACKAGE_NAME, ')', '(', "version", '$', PACKAGE_VERSION, ')', ')', NULL); if (result == NULL) return FALSE; wocky_porter_send (porter, result); g_object_unref ((GObject *) result); return TRUE; } /** * set_status_to_connected * * Stage 4 of connecting, this function is called once all the events we were * waiting for happened. * */ static void set_status_to_connected (GabbleConnection *conn) { TpBaseConnection *base = (TpBaseConnection *) conn; if (tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_DISCONNECTED) { /* We already failed to connect, but at the time an async thing was * still pending, and now it has finished. Do nothing special. */ return; } if (conn->features & GABBLE_CONNECTION_FEATURES_PEP) { const gchar *ifaces[] = { GABBLE_IFACE_OLPC_BUDDY_INFO, GABBLE_IFACE_OLPC_ACTIVITY_PROPERTIES, NULL }; tp_base_connection_add_interfaces ((TpBaseConnection *) conn, ifaces); } if (conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_MAIL_NOTIFY) { const gchar *ifaces[] = { TP_IFACE_CONNECTION_INTERFACE_MAIL_NOTIFICATION, NULL }; tp_base_connection_add_interfaces ((TpBaseConnection *) conn, ifaces); } if (tp_base_contact_list_can_block (gabble_connection_get_contact_list (conn))) { const gchar *ifaces[] = { TP_IFACE_CONNECTION_INTERFACE_CONTACT_BLOCKING, NULL }; tp_base_connection_add_interfaces ((TpBaseConnection *) conn, ifaces); } /* go go gadget on-line */ tp_base_connection_change_status (base, TP_CONNECTION_STATUS_CONNECTED, TP_CONNECTION_STATUS_REASON_REQUESTED); } static void decrement_waiting_connected (GabbleConnection *conn) { conn->priv->waiting_connected--; if (conn->priv->waiting_connected == 0) set_status_to_connected (conn); } static void conn_wlm_jid_lookup_cb (GObject *source, GAsyncResult *result, gpointer user_data) { GabbleConnection *conn = (GabbleConnection *) source; GSimpleAsyncResult *my_result = user_data; WockyStanza *iq = NULL; WockyNode *node; const gchar *jid = NULL; GError *error = NULL; if (!conn_util_send_iq_finish (conn, result, &iq, &error)) { g_simple_async_result_take_error (my_result, error); goto out; } node = wocky_node_get_child_ns (wocky_stanza_get_top_node (iq), "getjid", NS_WLM_JID_LOOKUP); if (node != NULL) { jid = wocky_node_get_content_from_child (node, "jid"); } if (!tp_str_empty (jid)) { g_simple_async_result_set_op_res_gpointer (my_result, g_strdup (jid), g_free); } else { g_simple_async_result_set_error (my_result, TP_ERROR, TP_ERROR_INVALID_HANDLE, "jid not found in getjid reply"); } out: g_simple_async_result_complete (my_result); g_object_unref (my_result); } static void conn_wlm_jid_lookup_async (TpHandleRepoIface *repo, TpBaseConnection *base, const gchar *id, gpointer context, GAsyncReadyCallback callback, gpointer user_data) { GabbleConnection *self = GABBLE_CONNECTION (base); WockyStanza *iq; GSimpleAsyncResult *result; gchar *normal_id; GError *error = NULL; result = g_simple_async_result_new ((GObject *) repo, callback, user_data, conn_wlm_jid_lookup_async); /* First, do local normalization */ normal_id = gabble_normalize_contact (repo, id, context, &error); if (normal_id == NULL) { g_simple_async_result_take_error (result, error); g_simple_async_result_complete_in_idle (result); g_object_unref (result); return; } /* If it is already a WLM jid, return it */ if (g_str_has_suffix (normal_id, "@messenger.live.com")) { g_simple_async_result_set_op_res_gpointer (result, normal_id, g_free); g_simple_async_result_complete_in_idle (result); g_object_unref (result); return; } /* Ask the server to give a WLM jid */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, conn_util_get_bare_self_jid (self), normal_id, '(', "getjid", ':', NS_WLM_JID_LOOKUP, ')', NULL); conn_util_send_iq_async (self, iq, NULL, conn_wlm_jid_lookup_cb, result); g_object_unref (iq); g_free (normal_id); } static gchar * conn_wlm_jid_lookup_finish (TpHandleRepoIface *repo, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple = (GSimpleAsyncResult *) result; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (repo), conn_wlm_jid_lookup_async), NULL); if (g_simple_async_result_propagate_error (simple, error)) return NULL; return g_strdup (g_simple_async_result_get_op_res_gpointer (simple)); } static void connection_disco_cb (GabbleDisco *disco, GabbleDiscoRequest *request, const gchar *jid, const gchar *node, WockyNode *result, GError *disco_error, gpointer user_data) { GabbleConnection *conn = GABBLE_CONNECTION (user_data); TpBaseConnection *base = (TpBaseConnection *) conn; if (tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTING) { g_assert (tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_DISCONNECTED); return; } if (disco_error) { DEBUG ("got disco error, setting no features: %s", disco_error->message); if (disco_error->code == GABBLE_DISCO_ERROR_TIMEOUT) { DEBUG ("didn't receive a response to our disco request: disconnect"); goto ERROR; } } else { WockyNodeIter i; WockyNode *child; NODE_DEBUG (result, "got"); wocky_node_iter_init (&i, result, NULL, NULL); while (wocky_node_iter_next (&i, &child)) { if (0 == strcmp (child->name, "identity")) { const gchar *category = wocky_node_get_attribute (child, "category"); const gchar *type = wocky_node_get_attribute (child, "type"); if (!tp_strdiff (category, "pubsub") && !tp_strdiff (type, "pep")) { DEBUG ("Server advertises PEP support in its features"); conn->features |= GABBLE_CONNECTION_FEATURES_PEP; } } else if (0 == strcmp (child->name, "feature")) { const gchar *var = wocky_node_get_attribute (child, "var"); if (var == NULL) continue; if (0 == strcmp (var, NS_GOOGLE_ROSTER)) conn->features |= GABBLE_CONNECTION_FEATURES_GOOGLE_ROSTER; #ifdef ENABLE_VOIP else if (0 == strcmp (var, NS_GOOGLE_JINGLE_INFO)) conn->features |= GABBLE_CONNECTION_FEATURES_GOOGLE_JINGLE_INFO; #endif else if (0 == strcmp (var, NS_PRESENCE_INVISIBLE)) conn->features |= GABBLE_CONNECTION_FEATURES_PRESENCE_INVISIBLE; else if (0 == strcmp (var, NS_PRIVACY)) conn->features |= GABBLE_CONNECTION_FEATURES_PRIVACY; else if (0 == strcmp (var, NS_INVISIBLE)) conn->features |= GABBLE_CONNECTION_FEATURES_INVISIBLE; else if (0 == strcmp (var, NS_GOOGLE_MAIL_NOTIFY)) conn->features |= GABBLE_CONNECTION_FEATURES_GOOGLE_MAIL_NOTIFY; else if (0 == strcmp (var, NS_GOOGLE_SHARED_STATUS)) conn->features |= GABBLE_CONNECTION_FEATURES_GOOGLE_SHARED_STATUS; else if (0 == strcmp (var, NS_GOOGLE_QUEUE)) conn->features |= GABBLE_CONNECTION_FEATURES_GOOGLE_QUEUE; else if (0 == strcmp (var, NS_GOOGLE_SETTING)) conn->features |= GABBLE_CONNECTION_FEATURES_GOOGLE_SETTING; else if (0 == strcmp (var, NS_WLM_JID_LOOKUP)) conn->features |= GABBLE_CONNECTION_FEATURES_WLM_JID_LOOKUP; } } DEBUG ("set features flags to %d", conn->features); } if ((conn->features & GABBLE_CONNECTION_FEATURES_WLM_JID_LOOKUP) != 0) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); tp_dynamic_handle_repo_set_normalize_async ( (TpDynamicHandleRepo *) contact_repo, conn_wlm_jid_lookup_async, conn_wlm_jid_lookup_finish); } conn_presence_set_initial_presence_async (conn, connection_initial_presence_cb, NULL); return; ERROR: tp_base_connection_change_status (base, TP_CONNECTION_STATUS_DISCONNECTED, TP_CONNECTION_STATUS_REASON_NETWORK_ERROR); return; } /** * connection_initial_presence_cb * * Stage 4 of connecting, this function is called after our initial presence * has been set (or has failed unrecoverably). It marks the connection as * online (or failed, as appropriate); the former triggers the roster being * retrieved. */ static void connection_initial_presence_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GabbleConnection *self = (GabbleConnection *) source_object; TpBaseConnection *base = (TpBaseConnection *) self; GError *error = NULL; if (!conn_presence_set_initial_presence_finish (self, res, &error)) { DEBUG ("error setting up initial presence: %s", error->message); if (tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_DISCONNECTED) tp_base_connection_change_status (base, TP_CONNECTION_STATUS_DISCONNECTED, TP_CONNECTION_STATUS_REASON_NETWORK_ERROR); g_error_free (error); } else { decrement_waiting_connected (self); } } /**************************************************************************** * D-BUS EXPORTED METHODS * ****************************************************************************/ static void gabble_free_rcc_list (GPtrArray *rccs) { g_boxed_free (TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST, rccs); } /** * gabble_connection_build_contact_caps: * @handle: a contact * @caps: @handle's XMPP capabilities * * Returns: an array containing the channel classes corresponding to @caps. */ static GPtrArray * gabble_connection_build_contact_caps ( GabbleConnection *self, TpHandle handle, const GabbleCapabilitySet *caps) { TpBaseConnection *base_conn = TP_BASE_CONNECTION (self); TpChannelManagerIter iter; TpChannelManager *manager; GPtrArray *ret = g_ptr_array_new (); tp_base_connection_channel_manager_iter_init (&iter, base_conn); while (tp_base_connection_channel_manager_iter_next (&iter, &manager)) { if (GABBLE_IS_CAPS_CHANNEL_MANAGER (manager)) { gabble_caps_channel_manager_get_contact_capabilities ( GABBLE_CAPS_CHANNEL_MANAGER (manager), handle, caps, ret); } } return ret; } static void _emit_capabilities_changed (GabbleConnection *conn, TpHandle handle, const GabbleCapabilitySet *old_set, const GabbleCapabilitySet *new_set) { GPtrArray *caps_arr; const CapabilityConversionData *ccd; GHashTable *hash; guint i; if (gabble_capability_set_equals (old_set, new_set)) return; /* o.f.T.C.Capabilities */ caps_arr = g_ptr_array_new (); for (ccd = capabilities_conversions; NULL != ccd->iface; ccd++) { guint old_specific = ccd->c2tf_fn (old_set); guint new_specific = ccd->c2tf_fn (new_set); if (old_specific != 0 || new_specific != 0) { GValue caps_monster_struct = {0, }; guint old_generic = old_specific ? TP_CONNECTION_CAPABILITY_FLAG_CREATE | TP_CONNECTION_CAPABILITY_FLAG_INVITE : 0; guint new_generic = new_specific ? TP_CONNECTION_CAPABILITY_FLAG_CREATE | TP_CONNECTION_CAPABILITY_FLAG_INVITE : 0; if (0 == (old_specific ^ new_specific)) continue; g_value_init (&caps_monster_struct, TP_STRUCT_TYPE_CAPABILITY_CHANGE); g_value_take_boxed (&caps_monster_struct, dbus_g_type_specialized_construct (TP_STRUCT_TYPE_CAPABILITY_CHANGE)); dbus_g_type_struct_set (&caps_monster_struct, 0, handle, 1, ccd->iface, 2, old_generic, 3, new_generic, 4, old_specific, 5, new_specific, G_MAXUINT); g_ptr_array_add (caps_arr, g_value_get_boxed (&caps_monster_struct)); } } if (caps_arr->len) tp_svc_connection_interface_capabilities_emit_capabilities_changed ( conn, caps_arr); for (i = 0; i < caps_arr->len; i++) { g_boxed_free (TP_STRUCT_TYPE_CAPABILITY_CHANGE, g_ptr_array_index (caps_arr, i)); } g_ptr_array_unref (caps_arr); /* o.f.T.C.ContactCapabilities */ caps_arr = gabble_connection_build_contact_caps (conn, handle, new_set); hash = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) gabble_free_rcc_list); g_hash_table_insert (hash, GUINT_TO_POINTER (handle), caps_arr); tp_svc_connection_interface_contact_capabilities_emit_contact_capabilities_changed ( conn, hash); g_hash_table_unref (hash); } static const GabbleCapabilitySet * empty_caps_set (void) { static GabbleCapabilitySet *empty = NULL; if (G_UNLIKELY (empty == NULL)) empty = gabble_capability_set_new (); return empty; } /* * gabble_connection_get_handle_contact_capabilities: * * Returns: an array of channel classes representing @handle's capabilities */ static GPtrArray * gabble_connection_get_handle_contact_capabilities ( GabbleConnection *self, TpHandle handle) { TpBaseConnection *base = TP_BASE_CONNECTION (self); GabblePresence *p; const GabbleCapabilitySet *caps; if (handle == tp_base_connection_get_self_handle (base)) p = self->self_presence; else p = gabble_presence_cache_get (self->presence_cache, handle); if (p == NULL) caps = empty_caps_set (); else caps = gabble_presence_peek_caps (p); return gabble_connection_build_contact_caps (self, handle, caps); } static void connection_capabilities_update_cb (GabblePresenceCache *cache, TpHandle handle, const GabbleCapabilitySet *old_cap_set, const GabbleCapabilitySet *new_cap_set, gpointer user_data) { GabbleConnection *conn = GABBLE_CONNECTION (user_data); _emit_capabilities_changed (conn, handle, old_cap_set, new_cap_set); } /** * gabble_connection_advertise_capabilities * * Implements D-Bus method AdvertiseCapabilities * on interface org.freedesktop.Telepathy.Connection.Interface.Capabilities * * @error: Used to return a pointer to a GError detailing any error * that occurred, D-Bus will throw the error only if this * function returns FALSE. * * Returns: TRUE if successful, FALSE if an error was thrown. */ static void gabble_connection_advertise_capabilities (TpSvcConnectionInterfaceCapabilities *iface, const GPtrArray *add, const gchar **del, DBusGMethodInvocation *context) { GabbleConnection *self = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) self; guint i; GabbleConnectionPrivate *priv = self->priv; const CapabilityConversionData *ccd; GPtrArray *ret; GabbleCapabilitySet *save_set; GabbleCapabilitySet *add_set, *remove_set; TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); /* Now that someone has told us our *actual* capabilities, we can stop * advertising spurious caps in initial presence */ gabble_capability_set_clear (self->priv->bonus_caps); add_set = gabble_capability_set_new (); remove_set = gabble_capability_set_new (); for (i = 0; i < add->len; i++) { GValue iface_flags_pair = {0, }; gchar *channel_type; guint flags; g_value_init (&iface_flags_pair, TP_STRUCT_TYPE_CAPABILITY_PAIR); g_value_set_static_boxed (&iface_flags_pair, g_ptr_array_index (add, i)); dbus_g_type_struct_get (&iface_flags_pair, 0, &channel_type, 1, &flags, G_MAXUINT); for (ccd = capabilities_conversions; NULL != ccd->iface; ccd++) if (g_str_equal (channel_type, ccd->iface)) ccd->tf2c_fn (flags, add_set); g_free (channel_type); } for (i = 0; NULL != del[i]; i++) { for (ccd = capabilities_conversions; NULL != ccd->iface; ccd++) if (g_str_equal (del[i], ccd->iface)) ccd->tf2c_fn (~0, remove_set); } gabble_capability_set_update (priv->legacy_caps, add_set); gabble_capability_set_exclude (priv->legacy_caps, remove_set); if (DEBUGGING) { gchar *add_str = gabble_capability_set_dump (add_set, " "); gchar *remove_str = gabble_capability_set_dump (remove_set, " "); DEBUG ("caps to add:\n%s", add_str); DEBUG ("caps to remove:\n%s", remove_str); g_free (add_str); g_free (remove_str); } gabble_capability_set_free (add_set); gabble_capability_set_free (remove_set); if (gabble_connection_refresh_capabilities (self, &save_set)) { _emit_capabilities_changed (self, tp_base_connection_get_self_handle (base), save_set, priv->all_caps); gabble_capability_set_free (save_set); } ret = g_ptr_array_new (); for (ccd = capabilities_conversions; NULL != ccd->iface; ccd++) { guint tp_caps = ccd->c2tf_fn (self->priv->all_caps); if (tp_caps != 0) { GValue iface_flags_pair = {0, }; g_value_init (&iface_flags_pair, TP_STRUCT_TYPE_CAPABILITY_PAIR); g_value_take_boxed (&iface_flags_pair, dbus_g_type_specialized_construct ( TP_STRUCT_TYPE_CAPABILITY_PAIR)); dbus_g_type_struct_set (&iface_flags_pair, 0, ccd->iface, 1, tp_caps, G_MAXUINT); g_ptr_array_add (ret, g_value_get_boxed (&iface_flags_pair)); } } tp_svc_connection_interface_capabilities_return_from_advertise_capabilities ( context, ret); g_ptr_array_foreach (ret, (GFunc) g_value_array_free, NULL); g_ptr_array_unref (ret); } static const gchar * get_form_type (WockyDataForm *form) { WockyDataFormField *field; field = g_hash_table_lookup (form->fields, "FORM_TYPE"); g_assert (field != NULL); return field->raw_value_contents[0]; } static const gchar * check_form_is_unique (GabbleConnection *self, const gchar *form_type) { GHashTableIter iter; gpointer key, value; g_hash_table_iter_init (&iter, self->priv->client_data_forms); while (g_hash_table_iter_next (&iter, &key, &value)) { const gchar *manager = key; GPtrArray *data_forms = value; guint i; if (data_forms == NULL || data_forms->len == 0) continue; for (i = 0; i < data_forms->len; i++) { WockyDataForm *form = g_ptr_array_index (data_forms, i); if (!tp_strdiff (get_form_type (form), form_type)) return manager; } } return NULL; } static gboolean check_data_form_in_list (GPtrArray *array, const gchar *form_type) { guint i; for (i = 0; i < array->len; i++) { WockyDataForm *form = g_ptr_array_index (array, i); if (!tp_strdiff (get_form_type (form), form_type)) return TRUE; } return FALSE; } static gboolean check_data_form_is_valid (GabbleConnection *self, WockyDataForm *form, GPtrArray *existing_forms) { WockyDataFormField *field; const gchar *form_type, *other_client; /* We want rid of forms with no FORM_TYPE quickly. */ field = g_hash_table_lookup (form->fields, "FORM_TYPE"); if (field == NULL || tp_str_empty (field->raw_value_contents[0])) { WARNING ("data form with no FORM_TYPE field; ignoring"); return FALSE; } form_type = field->raw_value_contents[0]; /* We'll get warnings (potentially bad) if two clients cause a * channel manager to create two data forms with the same FORM_TYPE, * or if multiple channel managers create two data forms with the * same FORM_TYPE, for the same client. This is probably not a * problem in practice given hardly anyone uses data forms in entity * capabilities anyway. */ /* We don't want the same data form from another caps channel * manager for this client either */ if (check_data_form_in_list (existing_forms, form_type)) { WARNING ("duplicate data form '%s' from another channel " "manager; ignoring", form_type); return FALSE; } /* And lastly we don't want a form we're already advertising. */ other_client = check_form_is_unique (self, form_type); if (other_client != NULL) { WARNING ("Data form '%s' already provided by client " "%s; ignoring", form_type, other_client); return FALSE; } return TRUE; } /** * gabble_connection_update_capabilities * * Implements D-Bus method UpdateCapabilities * on interface * org.freedesktop.Telepathy.Connection.Interface.ContactCapabilities */ static void gabble_connection_update_capabilities ( TpSvcConnectionInterfaceContactCapabilities *iface, const GPtrArray *clients, DBusGMethodInvocation *context) { GabbleConnection *self = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) self; GabbleCapabilitySet *old_caps = NULL; guint i; /* Now that someone has told us our *actual* capabilities, we can stop * advertising spurious caps in initial presence */ gabble_capability_set_clear (self->priv->bonus_caps); DEBUG ("enter"); for (i = 0; i < clients->len; i++) { GValueArray *va = g_ptr_array_index (clients, i); const gchar *client_name = g_value_get_string (va->values + 0); const GPtrArray *filters = g_value_get_boxed (va->values + 1); const gchar * const * cap_tokens = g_value_get_boxed (va->values + 2); GabbleCapabilitySet *cap_set; GPtrArray *data_forms; TpChannelManagerIter iter; TpChannelManager *manager; g_hash_table_remove (self->priv->client_caps, client_name); g_hash_table_remove (self->priv->client_data_forms, client_name); if ((cap_tokens == NULL || cap_tokens[0] == NULL) && filters->len == 0) { /* no capabilities */ DEBUG ("client %s can't do anything", client_name); continue; } cap_set = gabble_capability_set_new (); data_forms = g_ptr_array_new_with_free_func ( (GDestroyNotify) g_object_unref); tp_base_connection_channel_manager_iter_init (&iter, base); while (tp_base_connection_channel_manager_iter_next (&iter, &manager)) { if (GABBLE_IS_CAPS_CHANNEL_MANAGER (manager)) { GPtrArray *forms = g_ptr_array_new_with_free_func ( (GDestroyNotify) g_object_unref); guint j; /* First, represent the client... */ gabble_caps_channel_manager_represent_client ( GABBLE_CAPS_CHANNEL_MANAGER (manager), client_name, filters, cap_tokens, cap_set, forms); /* Now check the forms... */ for (j = 0; j < forms->len; j++) { WockyDataForm *form = g_ptr_array_index (forms, j); if (check_data_form_is_valid (self, form, data_forms)) g_ptr_array_add (data_forms, g_object_ref (form)); } g_ptr_array_unref (forms); } } /* first deal with normal caps */ if (gabble_capability_set_size (cap_set) > 0) { if (DEBUGGING) { gchar *s = gabble_capability_set_dump (cap_set, " "); DEBUG ("client %s contributes:\n%s", client_name, s); g_free (s); } g_hash_table_insert (self->priv->client_caps, g_strdup (client_name), cap_set); } else { DEBUG ("client %s has no interesting capabilities", client_name); gabble_capability_set_free (cap_set); } /* now data forms */ if (data_forms->len > 0) { guint j; /* now print out what forms we have here */ DEBUG ("client %s contributes %u data form%s:", client_name, data_forms->len, data_forms->len > 1 ? "s" : ""); for (j = 0; j < data_forms->len; j++) DEBUG (" - %s", get_form_type (g_ptr_array_index (data_forms, j))); g_hash_table_insert (self->priv->client_data_forms, g_strdup (client_name), data_forms); } else { DEBUG ("client %s has no interesting data forms", client_name); g_ptr_array_unref (data_forms); } } if (gabble_connection_refresh_capabilities (self, &old_caps)) { _emit_capabilities_changed (self, tp_base_connection_get_self_handle (base), old_caps, self->priv->all_caps); gabble_capability_set_free (old_caps); } tp_svc_connection_interface_contact_capabilities_return_from_update_capabilities ( context); } static const gchar *assumed_caps[] = { TP_IFACE_CHANNEL_TYPE_TEXT, NULL }; /** * gabble_connection_get_handle_capabilities * * Add capabilities of handle to the given GPtrArray */ static void gabble_connection_get_handle_capabilities (GabbleConnection *self, TpHandle handle, GPtrArray *arr) { TpBaseConnection *base = (TpBaseConnection *) self; GabblePresence *pres; const CapabilityConversionData *ccd; guint typeflags; const gchar **assumed; if (0 == handle) { /* obsolete request for the connection's capabilities, do nothing */ return; } if (handle == tp_base_connection_get_self_handle (base)) pres = self->self_presence; else pres = gabble_presence_cache_get (self->presence_cache, handle); if (NULL != pres) { const GabbleCapabilitySet *cap_set = gabble_presence_peek_caps (pres); for (ccd = capabilities_conversions; NULL != ccd->iface; ccd++) { typeflags = ccd->c2tf_fn (cap_set); if (typeflags) { GValue monster = {0, }; g_value_init (&monster, TP_STRUCT_TYPE_CONTACT_CAPABILITY); g_value_take_boxed (&monster, dbus_g_type_specialized_construct ( TP_STRUCT_TYPE_CONTACT_CAPABILITY)); dbus_g_type_struct_set (&monster, 0, handle, 1, ccd->iface, 2, TP_CONNECTION_CAPABILITY_FLAG_CREATE | TP_CONNECTION_CAPABILITY_FLAG_INVITE, 3, typeflags, G_MAXUINT); g_ptr_array_add (arr, g_value_get_boxed (&monster)); } } } for (assumed = assumed_caps; NULL != *assumed; assumed++) { GValue monster = {0, }; g_value_init (&monster, TP_STRUCT_TYPE_CONTACT_CAPABILITY); g_value_take_boxed (&monster, dbus_g_type_specialized_construct ( TP_STRUCT_TYPE_CONTACT_CAPABILITY)); dbus_g_type_struct_set (&monster, 0, handle, 1, *assumed, 2, TP_CONNECTION_CAPABILITY_FLAG_CREATE | TP_CONNECTION_CAPABILITY_FLAG_INVITE, 3, 0, G_MAXUINT); g_ptr_array_add (arr, g_value_get_boxed (&monster)); } } static void conn_capabilities_fill_contact_attributes (GObject *obj, const GArray *contacts, GHashTable *attributes_hash) { GabbleConnection *self = GABBLE_CONNECTION (obj); guint i; GPtrArray *array = NULL; for (i = 0; i < contacts->len; i++) { TpHandle handle = g_array_index (contacts, TpHandle, i); if (array == NULL) array = g_ptr_array_new (); gabble_connection_get_handle_capabilities (self, handle, array); if (array->len > 0) { GValue *val = tp_g_value_slice_new ( TP_ARRAY_TYPE_CONTACT_CAPABILITY_LIST); g_value_take_boxed (val, array); tp_contacts_mixin_set_contact_attribute (attributes_hash, handle, TP_IFACE_CONNECTION_INTERFACE_CAPABILITIES"/caps", val); array = NULL; } } if (array != NULL) g_ptr_array_unref (array); } static void conn_contact_capabilities_fill_contact_attributes (GObject *obj, const GArray *contacts, GHashTable *attributes_hash) { GabbleConnection *self = GABBLE_CONNECTION (obj); guint i; for (i = 0; i < contacts->len; i++) { TpHandle handle = g_array_index (contacts, TpHandle, i); GValue *val = tp_g_value_slice_new_take_boxed ( TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST, gabble_connection_get_handle_contact_capabilities (self, handle)); tp_contacts_mixin_set_contact_attribute (attributes_hash, handle, TP_IFACE_CONNECTION_INTERFACE_CONTACT_CAPABILITIES"/capabilities", val); } } /** * gabble_connection_get_capabilities * * Implements D-Bus method GetCapabilities * on interface org.freedesktop.Telepathy.Connection.Interface.Capabilities */ static void gabble_connection_get_capabilities (TpSvcConnectionInterfaceCapabilities *iface, const GArray *handles, DBusGMethodInvocation *context) { GabbleConnection *self = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) self; TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); guint i; GPtrArray *ret; GError *error = NULL; TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); if (!tp_handles_are_valid (contact_handles, handles, TRUE, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); return; } ret = g_ptr_array_new (); for (i = 0; i < handles->len; i++) { TpHandle handle = g_array_index (handles, TpHandle, i); gabble_connection_get_handle_capabilities (self, handle, ret); } tp_svc_connection_interface_capabilities_return_from_get_capabilities ( context, ret); for (i = 0; i < ret->len; i++) { g_value_array_free (g_ptr_array_index (ret, i)); } g_ptr_array_unref (ret); } /** * gabble_connection_get_contact_capabilities * * Implements D-Bus method GetContactCapabilities * on interface * org.freedesktop.Telepathy.Connection.Interface.ContactCapabilities */ static void gabble_connection_get_contact_capabilities ( TpSvcConnectionInterfaceContactCapabilities *iface, const GArray *handles, DBusGMethodInvocation *context) { GabbleConnection *self = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) self; TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); guint i; GHashTable *ret; GError *error = NULL; TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); if (!tp_handles_are_valid (contact_handles, handles, FALSE, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); return; } ret = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) gabble_free_rcc_list); for (i = 0; i < handles->len; i++) { TpHandle handle = g_array_index (handles, TpHandle, i); GPtrArray *arr; arr = gabble_connection_get_handle_contact_capabilities (self, handle); g_hash_table_insert (ret, GUINT_TO_POINTER (handle), arr); } tp_svc_connection_interface_contact_capabilities_return_from_get_contact_capabilities (context, ret); g_hash_table_unref (ret); } const char * _gabble_connection_find_conference_server (GabbleConnection *conn) { GabbleConnectionPrivate *priv; g_assert (GABBLE_IS_CONNECTION (conn)); priv = conn->priv; if (priv->conference_server == NULL) { /* Find first server that has NS_MUC feature */ const GabbleDiscoItem *item = gabble_disco_service_find (conn->disco, "conference", "text", NS_MUC); if (item != NULL) priv->conference_server = item->jid; } if (priv->conference_server == NULL) priv->conference_server = priv->fallback_conference_server; return priv->conference_server; } gchar * gabble_connection_get_canonical_room_name (GabbleConnection *conn, const gchar *name) { const gchar *server; g_assert (GABBLE_IS_CONNECTION (conn)); if (strchr (name, '@')) return g_strdup (name); server = _gabble_connection_find_conference_server (conn); if (server == NULL) return NULL; return gabble_encode_jid (name, server, NULL); } void gabble_connection_ensure_capabilities (GabbleConnection *self, const GabbleCapabilitySet *ensured) { gabble_capability_set_update (self->priv->notify_caps, ensured); gabble_connection_refresh_capabilities (self, NULL); } gboolean gabble_connection_send_presence (GabbleConnection *conn, WockyStanzaSubType sub_type, const gchar *contact, const gchar *status, GError **error) { WockyStanza *message; gboolean result; message = wocky_stanza_build (WOCKY_STANZA_TYPE_PRESENCE, sub_type, NULL, contact, NULL); if (WOCKY_STANZA_SUB_TYPE_SUBSCRIBE == sub_type) lm_message_node_add_own_nick ( wocky_stanza_get_top_node (message), conn); if (!tp_str_empty (status)) wocky_node_add_child_with_content ( wocky_stanza_get_top_node (message), "status", status); result = _gabble_connection_send (conn, message, error); g_object_unref (message); return result; } static void capabilities_service_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcConnectionInterfaceCapabilitiesClass *klass = (TpSvcConnectionInterfaceCapabilitiesClass *) g_iface; #define IMPLEMENT(x) tp_svc_connection_interface_capabilities_implement_##x (\ klass, gabble_connection_##x) IMPLEMENT(advertise_capabilities); IMPLEMENT(get_capabilities); #undef IMPLEMENT } static void gabble_conn_contact_caps_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcConnectionInterfaceContactCapabilitiesClass *klass = g_iface; #define IMPLEMENT(x) \ tp_svc_connection_interface_contact_capabilities_implement_##x (\ klass, gabble_connection_##x) IMPLEMENT(get_contact_capabilities); IMPLEMENT(update_capabilities); #undef IMPLEMENT } /* For unit tests only */ void gabble_connection_set_disco_reply_timeout (guint timeout) { disco_reply_timeout = timeout; } void gabble_connection_update_sidecar_capabilities (GabbleConnection *self, const GabbleCapabilitySet *add_set, const GabbleCapabilitySet *remove_set) { TpBaseConnection *base = TP_BASE_CONNECTION (self); GabbleConnectionPrivate *priv = self->priv; GabbleCapabilitySet *save_set; if (add_set == NULL && remove_set == NULL) return; if (add_set != NULL) gabble_capability_set_update (priv->sidecar_caps, add_set); if (remove_set != NULL) gabble_capability_set_exclude (priv->sidecar_caps, remove_set); if (DEBUGGING) { if (add_set != NULL) { gchar *add_str = gabble_capability_set_dump (add_set, " "); DEBUG ("sidecar caps to add:\n%s", add_str); g_free (add_str); } if (remove_set != NULL) { gchar *remove_str = gabble_capability_set_dump (remove_set, " "); DEBUG ("sidecar caps to remove:\n%s", remove_str); g_free (remove_str); } } if (gabble_connection_refresh_capabilities (self, &save_set)) { _emit_capabilities_changed (self, tp_base_connection_get_self_handle (base), save_set, priv->all_caps); gabble_capability_set_free (save_set); } } /* identities is actually a WockyDiscoIdentityArray */ gchar * gabble_connection_add_sidecar_own_caps_full (GabblePluginConnection *self, const GabbleCapabilitySet *cap_set, const GPtrArray *identities, GPtrArray *data_forms) { GabbleConnection *conn = GABBLE_CONNECTION (self); GPtrArray *identities_copy = ((identities == NULL) ? wocky_disco_identity_array_new () : wocky_disco_identity_array_copy (identities)); gchar *ver; /* XEP-0030 requires at least 1 identity. We don't need more. */ if (identities_copy->len == 0) g_ptr_array_add (identities_copy, wocky_disco_identity_new ("client", CLIENT_TYPE, NULL, PACKAGE_STRING)); ver = gabble_caps_hash_compute_full (cap_set, identities_copy, data_forms); gabble_presence_cache_add_own_caps (conn->presence_cache, ver, cap_set, identities_copy, data_forms); wocky_disco_identity_array_free (identities_copy); return ver; } gchar * gabble_connection_add_sidecar_own_caps (GabblePluginConnection *self, const GabbleCapabilitySet *cap_set, const GPtrArray *identities) { return gabble_connection_add_sidecar_own_caps_full (self, cap_set, identities, NULL); } const gchar * gabble_connection_get_jid_for_caps (GabblePluginConnection *plugin_conn, WockyXep0115Capabilities *caps) { TpHandle handle; TpBaseConnection *base; TpHandleRepoIface *contact_handles; GabbleConnection *conn = GABBLE_CONNECTION (plugin_conn); g_return_val_if_fail (GABBLE_IS_CONNECTION (conn), NULL); g_return_val_if_fail (GABBLE_IS_PRESENCE (caps), NULL); base = (TpBaseConnection *) conn; if ((GabblePresence *) caps == conn->self_presence) { handle = tp_base_connection_get_self_handle (base); } else { handle = gabble_presence_cache_get_handle (conn->presence_cache, (GabblePresence *) caps); } contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); return tp_handle_inspect (contact_handles, handle); } const gchar * gabble_connection_pick_best_resource_for_caps ( GabblePluginConnection *plugin_connection, const gchar *jid, GabbleCapabilitySetPredicate predicate, gconstpointer user_data) { TpBaseConnection *base; TpHandleRepoIface *contact_handles; TpHandle handle; GabbleConnection *connection = GABBLE_CONNECTION (plugin_connection); GabblePresence *presence; g_return_val_if_fail (GABBLE_IS_CONNECTION (connection), NULL); g_return_val_if_fail (!tp_str_empty (jid), NULL); base = (TpBaseConnection *) connection; contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); handle = tp_handle_ensure (contact_handles, jid, NULL, NULL); if (handle == 0) return NULL; presence = gabble_presence_cache_get (connection->presence_cache, handle); if (presence == NULL) return NULL; return gabble_presence_pick_resource_by_caps (presence, 0, predicate, user_data); } TpBaseContactList * gabble_connection_get_contact_list (GabbleConnection *connection) { g_return_val_if_fail (GABBLE_IS_CONNECTION (connection), NULL); return (TpBaseContactList *) connection->roster; } static TpBaseContactList * _gabble_plugin_connection_get_contact_list ( GabblePluginConnection *plugin_connection) { GabbleConnection *connection = GABBLE_CONNECTION (plugin_connection); return gabble_connection_get_contact_list (connection); } WockyXep0115Capabilities * gabble_connection_get_caps (GabblePluginConnection *plugin_connection, TpHandle handle) { GabblePresence *presence; GabbleConnection *connection = GABBLE_CONNECTION (plugin_connection); g_return_val_if_fail (GABBLE_IS_CONNECTION (connection), NULL); g_return_val_if_fail (handle > 0, NULL); presence = gabble_presence_cache_get (connection->presence_cache, handle); return (WockyXep0115Capabilities *) presence; } telepathy-gabble-0.18.3/src/message-util.h0000664000175000017500000000410712223562023021534 0ustar00cassidycassidy00000000000000/* * message-util.h - Header for Messages interface utility functions * Copyright (C) 2008 Collabora Ltd. * Copyright (C) 2008 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_MESSAGE_UTIL_H__ #define __GABBLE_MESSAGE_UTIL_H__ #include #include #include #include "connection.h" G_BEGIN_DECLS void gabble_message_util_add_chat_state (WockyStanza *stanza, TpChannelChatState state); WockyStanza * gabble_message_util_build_stanza (TpMessage *message, GabbleConnection *conn, WockyStanzaSubType subtype, TpChannelChatState state, const char *recipient, gboolean send_nick, gchar **token, GError **error); gboolean gabble_message_util_send_chat_state (GObject *obj, GabbleConnection *conn, WockyStanzaSubType subtype, TpChannelChatState state, const char *recipient, GError **error); #define GABBLE_TEXT_CHANNEL_SEND_NO_ERROR ((TpChannelTextSendError)-1) gboolean gabble_message_util_parse_incoming_message (WockyStanza *message, const gchar **from, time_t *stamp, TpChannelTextMessageType *msgtype, const gchar **id, const gchar **body_ret, gint *state, TpChannelTextSendError *send_error, TpDeliveryStatus *delivery_status); TpChannelTextSendError gabble_tp_send_error_from_wocky_xmpp_error (WockyXmppError err); G_END_DECLS #endif /* #ifndef __GABBLE_MESSAGE_UTIL_H__ */ telepathy-gabble-0.18.3/src/types.h0000664000175000017500000000354312223562023020304 0ustar00cassidycassidy00000000000000/* * gabble-types.h - Header for Gabble type definitions * * Copyright (C) 2006 Collabora Ltd. * Copyright (C) 2006 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_TYPES_H__ #define __GABBLE_TYPES_H__ #include "config.h" #include #include "gabble/types.h" G_BEGIN_DECLS typedef struct _GabbleDisco GabbleDisco; typedef struct _GabbleMucChannel GabbleMucChannel; typedef struct _GabblePresence GabblePresence; typedef struct _GabblePresenceCache GabblePresenceCache; typedef struct _GabbleRoster GabbleRoster; typedef struct _GabbleRosterChannel GabbleRosterChannel; typedef struct _GabbleVCardManager GabbleVCardManager; typedef struct _GabbleBytestreamFactory GabbleBytestreamFactory; typedef struct _GabblePrivateTubesFactory GabblePrivateTubesFactory; typedef struct _GabbleRequestPipeline GabbleRequestPipeline; typedef struct _GabbleTubesChannel GabbleTubesChannel; typedef struct _GabbleCallMember GabbleCallMember; typedef struct _GabbleCallMemberContent GabbleCallMemberContent; struct _GabbleDiscoIdentity { gchar *category; gchar *type; gchar *lang; gchar *name; }; G_END_DECLS #endif telepathy-gabble-0.18.3/src/auth-manager.h0000664000175000017500000000454012332440117021507 0ustar00cassidycassidy00000000000000/* * auth-manager.h - Header for GabbleAuthManager * Copyright (C) 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __AUTH_MANAGER_H__ #define __AUTH_MANAGER_H__ #include #include #include #include G_BEGIN_DECLS typedef struct _GabbleAuthManager GabbleAuthManager; typedef struct _GabbleAuthManagerClass GabbleAuthManagerClass; typedef struct _GabbleAuthManagerPrivate GabbleAuthManagerPrivate; struct _GabbleAuthManagerClass { WockyAuthRegistryClass parent_class; }; struct _GabbleAuthManager { WockyAuthRegistry parent; GabbleAuthManagerPrivate *priv; }; GType gabble_auth_manager_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_AUTH_MANAGER \ (gabble_auth_manager_get_type ()) #define GABBLE_AUTH_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_AUTH_MANAGER, GabbleAuthManager)) #define GABBLE_AUTH_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_AUTH_MANAGER,\ GabbleAuthManagerClass)) #define GABBLE_IS_AUTH_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_AUTH_MANAGER)) #define GABBLE_IS_AUTH_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_AUTH_MANAGER)) #define GABBLE_AUTH_MANAGER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_AUTH_MANAGER,\ GabbleAuthManagerClass)) gboolean gabble_auth_manager_get_failure_details (GabbleAuthManager *self, gchar **dbus_error, GHashTable **details, TpConnectionStatusReason *reason); G_END_DECLS #endif /* #ifndef __AUTH_MANAGER_H__ */ telepathy-gabble-0.18.3/src/tube-iface.h0000664000175000017500000000444212332441362021146 0ustar00cassidycassidy00000000000000/* * tube-iface.h - Header for GabbleTube interface * Copyright (C) 2007-2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_TUBE_IFACE_H__ #define __GABBLE_TUBE_IFACE_H__ #include #include #include "bytestream-iface.h" G_BEGIN_DECLS typedef struct _GabbleTubeIface GabbleTubeIface; typedef struct _GabbleTubeIfaceClass GabbleTubeIfaceClass; struct _GabbleTubeIfaceClass { GTypeInterface parent; gboolean (*accept) (GabbleTubeIface *tube, GError **error); void (*close) (GabbleTubeIface *tube, gboolean closed_remotely); void (*add_bytestream) (GabbleTubeIface *tube, GabbleBytestreamIface *bytestream); }; GType gabble_tube_iface_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_TUBE_IFACE \ (gabble_tube_iface_get_type ()) #define GABBLE_TUBE_IFACE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_TUBE_IFACE, GabbleTubeIface)) #define GABBLE_IS_TUBE_IFACE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_TUBE_IFACE)) #define GABBLE_TUBE_IFACE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GABBLE_TYPE_TUBE_IFACE,\ GabbleTubeIfaceClass)) gboolean gabble_tube_iface_accept (GabbleTubeIface *tube, GError **error); void gabble_tube_iface_close (GabbleTubeIface *tube, gboolean closed_remotely); void gabble_tube_iface_add_bytestream (GabbleTubeIface *tube, GabbleBytestreamIface *bytestream); void gabble_tube_iface_publish_in_node (GabbleTubeIface *tube, TpBaseConnection *conn, WockyNode *node); G_END_DECLS #endif /* #ifndef __GABBLE_TUBE_IFACE_H__ */ telepathy-gabble-0.18.3/src/conn-avatars.h0000664000175000017500000000251112332441362021531 0ustar00cassidycassidy00000000000000/* * conn-avatars.h - Header for Gabble connection avatar interface * Copyright (C) 2005-2007 Collabora Ltd. * Copyright (C) 2005-2007 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __CONN_AVATARS_H__ #define __CONN_AVATARS_H__ #include "connection.h" G_BEGIN_DECLS void conn_avatars_init (GabbleConnection *conn); void conn_avatars_iface_init (gpointer g_iface, gpointer iface_data); extern TpDBusPropertiesMixinPropImpl *conn_avatars_properties; void conn_avatars_properties_getter (GObject *object, GQuark interface, GQuark name, GValue *value, gpointer getter_data); G_END_DECLS #endif /* __CONN_AVATARS_H__ */ telepathy-gabble-0.18.3/src/search-manager.c0000664000175000017500000004024012332440117022003 0ustar00cassidycassidy00000000000000/* * search-manager.c - TpChannelManager implementation for ContactSearch channels * Copyright (C) 2009 Collabora Ltd. * Copyright (C) 2009 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "search-manager.h" #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_SEARCH #include "gabble/caps-channel-manager.h" #include "connection.h" #include "debug.h" #include "disco.h" #include "search-channel.h" #include "util.h" static void channel_manager_iface_init (gpointer, gpointer); static void caps_channel_manager_iface_init (gpointer, gpointer); G_DEFINE_TYPE_WITH_CODE (GabbleSearchManager, gabble_search_manager, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER, channel_manager_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_CAPS_CHANNEL_MANAGER, caps_channel_manager_iface_init)); static void new_search_channel (GabbleSearchManager *self, const gchar *server, gpointer request_token); /* properties */ enum { PROP_CONNECTION = 1, LAST_PROPERTY }; struct _GabbleSearchManagerPrivate { GabbleConnection *conn; /* Used to represent a set of channels. * Keys are GabbleSearchChannel *, values are an arbitrary non-NULL pointer. */ GHashTable *channels; gchar *default_jud; gboolean disco_done; /* List of request tokens (gpointer) waiting that the disco process is * completed. */ GSList *requests_waiting_disco; gboolean dispose_has_run; }; static void gabble_search_manager_init (GabbleSearchManager *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_SEARCH_MANAGER, GabbleSearchManagerPrivate); self->priv->channels = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL); self->priv->conn = NULL; self->priv->dispose_has_run = FALSE; self->priv->disco_done = FALSE; self->priv->requests_waiting_disco = NULL; } static void gabble_search_manager_close_all (GabbleSearchManager *self) { GList *chans, *l; DEBUG ("closing channels"); /* We can't use a GHashTableIter as closing the channel while remove it from * the hash table and we can't modify a hash table while iterating on it. */ chans = g_hash_table_get_keys (self->priv->channels); for (l = chans; l != NULL; l = g_list_next (l)) tp_base_channel_close (TP_BASE_CHANNEL (l->data)); g_list_free (chans); /* base-connection cancels all the pending requests when disconnecting so we * don't have to do anything. */ g_slist_free (self->priv->requests_waiting_disco); self->priv->requests_waiting_disco = NULL; } static void disco_item_found_cb (GabbleDisco *disco, GabbleDiscoItem *item, GabbleSearchManager *self) { if (tp_strdiff (item->category, "directory") || tp_strdiff (item->type, "user")) return; DEBUG ("Found contact directory: %s\n", item->jid); g_free (self->priv->default_jud); self->priv->default_jud = g_strdup (item->jid); } static void disco_done_cb (GabbleDisco *disco, GabbleSearchManager *self) { GSList *l; DEBUG ("Disco is done; complete pending requests"); self->priv->disco_done = TRUE; for (l = self->priv->requests_waiting_disco; l != NULL; l = g_slist_next (l)) { gpointer request_token = l->data; if (self->priv->default_jud != NULL) { new_search_channel (self, self->priv->default_jud, request_token); } else { tp_channel_manager_emit_request_failed (self, request_token, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "No Server has been specified and no server has been " "discovered on the connection"); } } g_slist_free (self->priv->requests_waiting_disco); self->priv->requests_waiting_disco = NULL; } static void connection_status_changed_cb (GabbleConnection *conn, guint status, guint reason, GabbleSearchManager *self) { switch (status) { case TP_CONNECTION_STATUS_CONNECTING: /* Track Search server available on the connection. * * The GabbleDisco object is created after the channel manager so we * can connect this signal in our constructor. */ gabble_signal_connect_weak (self->priv->conn->disco, "item-found", G_CALLBACK (disco_item_found_cb), G_OBJECT (self)); gabble_signal_connect_weak (self->priv->conn->disco, "done", G_CALLBACK (disco_done_cb), G_OBJECT (self)); break; case TP_CONNECTION_STATUS_DISCONNECTED: gabble_search_manager_close_all (self); break; default: return; } } static GObject * gabble_search_manager_constructor (GType type, guint n_props, GObjectConstructParam *props) { GObject *obj = G_OBJECT_CLASS (gabble_search_manager_parent_class)-> constructor (type, n_props, props); GabbleSearchManager *self = GABBLE_SEARCH_MANAGER (obj); gabble_signal_connect_weak (self->priv->conn, "status-changed", G_CALLBACK (connection_status_changed_cb), G_OBJECT (obj)); return obj; } static void gabble_search_manager_dispose (GObject *object) { GabbleSearchManager *fac = GABBLE_SEARCH_MANAGER (object); GabbleSearchManagerPrivate *priv = fac->priv; if (priv->dispose_has_run) return; DEBUG ("dispose called"); priv->dispose_has_run = TRUE; gabble_search_manager_close_all (fac); if (G_OBJECT_CLASS (gabble_search_manager_parent_class)->dispose) G_OBJECT_CLASS (gabble_search_manager_parent_class)->dispose (object); } static void gabble_search_manager_finalize (GObject *object) { GabbleSearchManager *fac = GABBLE_SEARCH_MANAGER (object); GabbleSearchManagerPrivate *priv = fac->priv; g_free (priv->default_jud); /* close_all removed all the channels from the hash table */ g_assert_cmpuint (g_hash_table_size (priv->channels), ==, 0); g_hash_table_unref (priv->channels); if (G_OBJECT_CLASS (gabble_search_manager_parent_class)->finalize) G_OBJECT_CLASS (gabble_search_manager_parent_class)->finalize (object); } static void gabble_search_manager_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleSearchManager *self = GABBLE_SEARCH_MANAGER (object); switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, self->priv->conn); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_search_manager_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleSearchManager *self = GABBLE_SEARCH_MANAGER (object); switch (property_id) { case PROP_CONNECTION: self->priv->conn = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_search_manager_class_init (GabbleSearchManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GParamSpec *param_spec; g_type_class_add_private (klass, sizeof (GabbleSearchManagerPrivate)); object_class->constructor = gabble_search_manager_constructor; object_class->dispose = gabble_search_manager_dispose; object_class->finalize = gabble_search_manager_finalize; object_class->get_property = gabble_search_manager_get_property; object_class->set_property = gabble_search_manager_set_property; param_spec = g_param_spec_object ("connection", "GabbleConnection object", "Gabble connection object that owns this ContactSearch manager.", GABBLE_TYPE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); } static void gabble_search_manager_foreach_channel (TpChannelManager *manager, TpExportableChannelFunc func, gpointer user_data) { GabbleSearchManager *self = GABBLE_SEARCH_MANAGER (manager); GHashTableIter iter; gpointer chan; g_hash_table_iter_init (&iter, self->priv->channels); while (g_hash_table_iter_next (&iter, &chan, NULL)) { /* Don't list channels which are not ready as they have not been * announced in NewChannels yet.*/ if (gabble_search_channel_is_ready (GABBLE_SEARCH_CHANNEL (chan))) func (chan, user_data); } } static const gchar * const search_channel_fixed_properties[] = { TP_IFACE_CHANNEL ".ChannelType", NULL }; static const gchar * const search_channel_allowed_properties[] = { TP_IFACE_CHANNEL_TYPE_CONTACT_SEARCH ".Server", NULL }; static void gabble_search_manager_type_foreach_channel_class (GType type, TpChannelManagerTypeChannelClassFunc func, gpointer user_data) { GHashTable *table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free); GValue *value; value = tp_g_value_slice_new_string ( TP_IFACE_CHANNEL_TYPE_CONTACT_SEARCH); g_hash_table_insert (table, (gchar *) search_channel_fixed_properties[0], value); func (type, table, search_channel_allowed_properties, user_data); g_hash_table_unref (table); } static void remove_search_channel (GabbleSearchManager *self, GabbleSearchChannel *chan) { g_hash_table_remove (self->priv->channels, chan); } static void search_channel_closed_cb (GabbleSearchChannel *chan, GabbleSearchManager *self) { tp_channel_manager_emit_channel_closed_for_object (self, (TpExportableChannel *) chan); remove_search_channel (self, chan); } typedef struct { GabbleSearchManager *self; gpointer request_token; gchar *server; } RequestContext; static RequestContext * request_context_new (GabbleSearchManager *self, gpointer request_token, const gchar *server) { RequestContext *ctx = g_slice_new (RequestContext); ctx->self = g_object_ref (self); ctx->request_token = request_token; ctx->server = g_strdup (server); return ctx; } static void request_context_free (RequestContext *ctx) { g_object_unref (ctx->self); g_free (ctx->server); g_slice_free (RequestContext, ctx); } static void search_channel_ready_or_not_cb (GabbleSearchChannel *chan, GQuark domain, gint code, const gchar *message, RequestContext *ctx) { if (domain == 0) { GSList *request_tokens = g_slist_prepend (NULL, ctx->request_token); tp_channel_manager_emit_new_channel (ctx->self, (TpExportableChannel *) chan, request_tokens); g_slist_free (request_tokens); } else { if (domain == WOCKY_XMPP_ERROR) { domain = TP_ERROR; switch (code) { case WOCKY_XMPP_ERROR_FORBIDDEN: code = TP_ERROR_PERMISSION_DENIED; break; case WOCKY_XMPP_ERROR_JID_MALFORMED: code = TP_ERROR_INVALID_ARGUMENT; break; default: code = TP_ERROR_NOT_AVAILABLE; } } else { g_assert (domain == TP_ERROR); } tp_channel_manager_emit_request_failed (ctx->self, ctx->request_token, domain, code, message); remove_search_channel (ctx->self, chan); } request_context_free (ctx); } static void new_search_channel (GabbleSearchManager *self, const gchar *server, gpointer request_token) { GabbleSearchManagerPrivate *priv = self->priv; GabbleSearchChannel *chan; TpBaseConnection *base_conn = TP_BASE_CONNECTION (priv->conn); g_assert (server != NULL); chan = g_object_new (GABBLE_TYPE_SEARCH_CHANNEL, "connection", priv->conn, "server", server, "initiator-handle", tp_base_connection_get_self_handle (base_conn), NULL); g_hash_table_insert (priv->channels, chan, priv->channels); g_signal_connect (chan, "closed", (GCallback) search_channel_closed_cb, self); g_signal_connect (chan, "ready-or-not", (GCallback) search_channel_ready_or_not_cb, request_context_new (self, request_token, server)); } static gboolean gabble_search_manager_create_channel (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties) { GabbleSearchManager *self = GABBLE_SEARCH_MANAGER (manager); GError *error = NULL; const gchar *channel_type; const gchar *server; channel_type = tp_asv_get_string (request_properties, TP_IFACE_CHANNEL ".ChannelType"); if (tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_CONTACT_SEARCH)) return FALSE; if (tp_channel_manager_asv_has_unknown_properties (request_properties, search_channel_fixed_properties, search_channel_allowed_properties, &error)) goto error; server = tp_asv_get_string (request_properties, TP_IFACE_CHANNEL_TYPE_CONTACT_SEARCH ".Server"); if (tp_str_empty (server)) { /* Treat an empty server as equivalent to omitting the server entirely. */ server = NULL; } else if (!wocky_decode_jid (server, NULL, NULL, NULL)) { /* On the other hand, if the JID's invalid, blow up. */ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Specified server '%s' is not a valid JID", server); goto error; } if (server == NULL) { if (self->priv->default_jud == NULL) { if (self->priv->disco_done) { error = g_error_new (TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "No Server has been specified and no server has been " "discovered on the connection"); goto error; } /* Wait until disco is finished as we still have a chance to * discover a search server. */ DEBUG ("No Server has been specified; wait for the end of " "the disco process"); self->priv->requests_waiting_disco = g_slist_append ( self->priv->requests_waiting_disco, request_token); return TRUE; } DEBUG ("No Server specified; use %s as default", self->priv->default_jud); server = self->priv->default_jud; } new_search_channel (self, server, request_token); return TRUE; error: tp_channel_manager_emit_request_failed (self, request_token, error->domain, error->code, error->message); g_error_free (error); return TRUE; } static void channel_manager_iface_init (gpointer g_iface, gpointer iface_data) { TpChannelManagerIface *iface = g_iface; iface->foreach_channel = gabble_search_manager_foreach_channel; iface->type_foreach_channel_class = gabble_search_manager_type_foreach_channel_class; iface->create_channel = gabble_search_manager_create_channel; iface->request_channel = gabble_search_manager_create_channel; /* Ensuring these channels doesn't really make much sense. */ iface->ensure_channel = NULL; } static void caps_channel_manager_iface_init (gpointer g_iface, gpointer iface_data) { /* Leave everything unimplemented. */ } telepathy-gabble-0.18.3/src/server-sasl-channel.h0000664000175000017500000000751412332440117023016 0ustar00cassidycassidy00000000000000/* * server-sasl-channel.h - Header for GabbleServerSaslChannel * Copyright (C) 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_SERVER_SASL_CHANNEL_H__ #define __GABBLE_SERVER_SASL_CHANNEL_H__ #include #include #include #include "types.h" G_BEGIN_DECLS #define X_TELEPATHY_PASSWORD "X-TELEPATHY-PASSWORD" typedef struct _GabbleServerSaslChannelPrivate GabbleServerSaslChannelPrivate; typedef struct _GabbleServerSaslChannelClass GabbleServerSaslChannelClass; typedef struct _GabbleServerSaslChannel GabbleServerSaslChannel; struct _GabbleServerSaslChannelClass { TpBaseChannelClass parent_class; TpDBusPropertiesMixinClass dbus_props_class; }; struct _GabbleServerSaslChannel { TpBaseChannel parent; GabbleServerSaslChannelPrivate *priv; }; GType gabble_server_sasl_channel_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_SERVER_SASL_CHANNEL \ (gabble_server_sasl_channel_get_type ()) #define GABBLE_SERVER_SASL_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_SERVER_SASL_CHANNEL,\ GabbleServerSaslChannel)) #define GABBLE_SERVER_SASL_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_SERVER_SASL_CHANNEL,\ GabbleServerSaslChannelClass)) #define GABBLE_IS_SERVER_SASL_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_SERVER_SASL_CHANNEL)) #define GABBLE_IS_SERVER_SASL_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_SERVER_SASL_CHANNEL)) #define GABBLE_SERVER_SASL_CHANNEL_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_SERVER_SASL_CHANNEL,\ GabbleServerSaslChannelClass)) GabbleServerSaslChannel *gabble_server_sasl_channel_new ( GabbleConnection *conn, GStrv available_mechanisms, gboolean secure, const gchar *session_id); void gabble_server_sasl_channel_start_auth_async ( GabbleServerSaslChannel *self, GAsyncReadyCallback callback, gpointer user_data); gboolean gabble_server_sasl_channel_start_auth_finish ( GabbleServerSaslChannel *self, GAsyncResult *result, WockyAuthRegistryStartData **start_data, GError **error); void gabble_server_sasl_channel_challenge_async (GabbleServerSaslChannel *self, const GString *challenge_data, GAsyncReadyCallback callback, gpointer user_data); gboolean gabble_server_sasl_channel_challenge_finish ( GabbleServerSaslChannel *self, GAsyncResult *result, GString **response, GError **error); void gabble_server_sasl_channel_success_async (GabbleServerSaslChannel *self, GAsyncReadyCallback callback, gpointer user_data); gboolean gabble_server_sasl_channel_success_finish ( GabbleServerSaslChannel *self, GAsyncResult *result, GError **error); void gabble_server_sasl_channel_fail (GabbleServerSaslChannel *self, const GError *error); gboolean gabble_server_sasl_channel_get_failure_details ( GabbleServerSaslChannel *self, gchar **dbus_error, GHashTable **details, TpConnectionStatusReason *reason, GError **error); G_END_DECLS #endif /* #ifndef __GABBLE_SERVER_SASL_CHANNEL_H__*/ telepathy-gabble-0.18.3/src/caps-channel-manager.c0000664000175000017500000000614112225273037023102 0ustar00cassidycassidy00000000000000/* * caps-channel-manager.c - interface holding capabilities functions for * channel managers * * Copyright (C) 2008 Collabora Ltd. * Copyright (C) 2008 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "gabble/caps-channel-manager.h" #include #define DEBUG_FLAG GABBLE_DEBUG_PRESENCE #include "debug.h" G_DEFINE_INTERFACE (GabbleCapsChannelManager, gabble_caps_channel_manager, TP_TYPE_CHANNEL_MANAGER); /* stub function needed for the G_DEFINE_INTERFACE macro above */ static void gabble_caps_channel_manager_default_init ( GabbleCapsChannelManagerInterface *interface) { } /* Virtual-method wrappers */ void gabble_caps_channel_manager_get_contact_capabilities ( GabbleCapsChannelManager *caps_manager, TpHandle handle, const GabbleCapabilitySet *caps, GPtrArray *arr) { GabbleCapsChannelManagerInterface *iface = GABBLE_CAPS_CHANNEL_MANAGER_GET_INTERFACE (caps_manager); GabbleCapsChannelManagerGetContactCapsFunc method = iface->get_contact_caps; if (method != NULL) { method (caps_manager, handle, caps, arr); } /* ... else assume there are no caps for this kind of channel */ } /** * gabble_caps_channel_manager_represent_client: * @self: a channel manager * @client_name: the name of the client, for any debug messages * @filters: the channel classes accepted by the client, as an array of * GHashTable with string keys and GValue values * @cap_tokens: the handler capability tokens supported by the client * @cap_set: a set into which to merge additional XMPP capabilities * @data_forms: a #GPtrArray of #WockyDataForm objects * * Convert the capabilities of a Telepathy client into XMPP capabilities to be * advertised. * * (The actual XMPP capabilities advertised will be the union of the XMPP * capabilities of every installed client.) */ void gabble_caps_channel_manager_represent_client ( GabbleCapsChannelManager *caps_manager, const gchar *client_name, const GPtrArray *filters, const gchar * const *cap_tokens, GabbleCapabilitySet *cap_set, GPtrArray *data_forms) { GabbleCapsChannelManagerInterface *iface = GABBLE_CAPS_CHANNEL_MANAGER_GET_INTERFACE (caps_manager); GabbleCapsChannelManagerRepresentClientFunc method = iface->represent_client; if (method != NULL) { method (caps_manager, client_name, filters, cap_tokens, cap_set, data_forms); } } telepathy-gabble-0.18.3/src/conn-addressing.c0000664000175000017500000001273512332441362022217 0ustar00cassidycassidy00000000000000/* * conn-addressing.h - Header for Gabble connection code handling addressing. * Copyright (C) 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "conn-addressing.h" #include #include #include #include "extensions/extensions.h" #include "addressing-util.h" #include "namespaces.h" #include "util.h" static const char *assumed_interfaces[] = { TP_IFACE_CONNECTION, GABBLE_IFACE_CONNECTION_INTERFACE_ADDRESSING, NULL }; static void _fill_contact_attributes (TpHandleRepoIface *contact_repo, TpHandle contact, GHashTable *attributes_hash) { gchar **uris = gabble_uris_for_handle (contact_repo, contact); GHashTable *addresses = gabble_vcard_addresses_for_handle (contact_repo, contact); tp_contacts_mixin_set_contact_attribute (attributes_hash, contact, GABBLE_IFACE_CONNECTION_INTERFACE_ADDRESSING"/uris", tp_g_value_slice_new_take_boxed (G_TYPE_STRV, uris)); tp_contacts_mixin_set_contact_attribute (attributes_hash, contact, GABBLE_IFACE_CONNECTION_INTERFACE_ADDRESSING"/addresses", tp_g_value_slice_new_take_boxed (TP_HASH_TYPE_STRING_STRING_MAP, addresses)); } static void conn_addressing_fill_contact_attributes (GObject *obj, const GArray *contacts, GHashTable *attributes_hash) { guint i; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) obj, TP_HANDLE_TYPE_CONTACT); for (i = 0; i < contacts->len; i++) { TpHandle contact = g_array_index (contacts, TpHandle, i); _fill_contact_attributes (contact_repo, contact, attributes_hash); } } static void conn_addressing_get_contacts_by_uri (GabbleSvcConnectionInterfaceAddressing *iface, const gchar **uris, const gchar **interfaces, DBusGMethodInvocation *context) { const gchar **uri; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) iface, TP_HANDLE_TYPE_CONTACT); GHashTable *attributes; GHashTable *requested = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); GArray *handles = g_array_sized_new (TRUE, TRUE, sizeof (TpHandle), g_strv_length ((gchar **) uris)); gchar *sender = dbus_g_method_get_sender (context); for (uri = uris; *uri != NULL; uri++) { TpHandle h = gabble_ensure_handle_from_uri (contact_repo, *uri, NULL); if (h == 0) continue; g_hash_table_insert (requested, g_strdup (*uri), GUINT_TO_POINTER (h)); g_array_append_val (handles, h); } attributes = tp_contacts_mixin_get_contact_attributes (G_OBJECT (iface), handles, interfaces, assumed_interfaces, sender); gabble_svc_connection_interface_addressing_return_from_get_contacts_by_uri ( context, requested, attributes); g_array_unref (handles); g_hash_table_unref (requested); g_hash_table_unref (attributes); g_free (sender); } static void conn_addressing_get_contacts_by_vcard_field (GabbleSvcConnectionInterfaceAddressing *iface, const gchar *field, const gchar **addresses, const gchar **interfaces, DBusGMethodInvocation *context) { const gchar **address; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) iface, TP_HANDLE_TYPE_CONTACT); GHashTable *attributes; GHashTable *requested = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); GArray *handles = g_array_sized_new (TRUE, TRUE, sizeof (TpHandle), g_strv_length ((gchar **) addresses)); gchar *sender = dbus_g_method_get_sender (context); for (address = addresses; *address != NULL; address++) { TpHandle h = gabble_ensure_handle_from_vcard_address (contact_repo, field, *address, NULL); if (h == 0) continue; g_hash_table_insert (requested, g_strdup (*address), GUINT_TO_POINTER (h)); g_array_append_val (handles, h); } attributes = tp_contacts_mixin_get_contact_attributes (G_OBJECT (iface), handles, interfaces, assumed_interfaces, sender); gabble_svc_connection_interface_addressing_return_from_get_contacts_by_vcard_field ( context, requested, attributes); g_array_unref (handles); g_hash_table_unref (requested); g_hash_table_unref (attributes); g_free (sender); } void conn_addressing_init (GabbleConnection *self) { tp_contacts_mixin_add_contact_attributes_iface (G_OBJECT (self), GABBLE_IFACE_CONNECTION_INTERFACE_ADDRESSING, conn_addressing_fill_contact_attributes); } void conn_addressing_iface_init (gpointer g_iface, gpointer iface_data) { #define IMPLEMENT(x) \ gabble_svc_connection_interface_addressing_implement_##x (\ g_iface, conn_addressing_##x) IMPLEMENT (get_contacts_by_uri); IMPLEMENT (get_contacts_by_vcard_field); #undef IMPLEMENT } telepathy-gabble-0.18.3/src/conn-presence.c0000664000175000017500000017240712332440117021700 0ustar00cassidycassidy00000000000000/* * conn-presence - Gabble connection presence interface * Copyright (C) 2005-2007 Collabora Ltd. * Copyright (C) 2005-2007 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "conn-presence.h" #include "namespaces.h" #include #include #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_CONNECTION #include "extensions/extensions.h" /* for Decloak */ #include "connection.h" #include "debug.h" #include "plugin-loader.h" #include "presence-cache.h" #include "presence.h" #include "roster.h" #include "conn-util.h" #include "util.h" #define GOOGLE_SHARED_STATUS_VERSION "2" typedef enum { INVISIBILITY_METHOD_NONE = 0, INVISIBILITY_METHOD_PRESENCE_INVISIBLE, /* presence type=invisible */ INVISIBILITY_METHOD_PRIVACY, INVISIBILITY_METHOD_INVISIBLE_COMMAND, INVISIBILITY_METHOD_SHARED_STATUS } InvisibilityMethod; struct _GabbleConnectionPresencePrivate { InvisibilityMethod invisibility_method; guint iq_list_push_id; gchar *invisible_list_name; /* Mapping between status "show" strings, and shared statuses */ GHashTable *shared_statuses; /* Map of presence statuses backed by privacy lists. This * will be NULL until we receive a (possibly empty) list of * all lists in get_existing_privacy_lists_cb(). * * gchar *presence_status_name → gchar *privacy_list */ GHashTable *privacy_statuses; /* Are all of the connected resources complying to version 2 */ gboolean shared_status_compat; /* Max length of status message */ gint max_status_message_length; /* Max statuses in a shared status list */ gint max_shared_statuses; /* The shared status IQ handler */ guint iq_shared_status_cb; /* The previous presence when using shared status */ GabblePresenceId previous_shared_status; }; static const TpPresenceStatusOptionalArgumentSpec gabble_status_arguments[] = { { "message", "s", NULL, NULL }, { "priority", "n", NULL, NULL }, { NULL, NULL, NULL, NULL } }; /* order must match PresenceId enum in connection.h */ /* in increasing order of presence */ static const TpPresenceStatusSpec gabble_base_statuses[] = { { "offline", TP_CONNECTION_PRESENCE_TYPE_OFFLINE, FALSE, gabble_status_arguments, NULL, NULL }, { "unknown", TP_CONNECTION_PRESENCE_TYPE_UNKNOWN, FALSE, gabble_status_arguments, NULL, NULL }, { "error", TP_CONNECTION_PRESENCE_TYPE_ERROR, FALSE, gabble_status_arguments, NULL, NULL }, { "hidden", TP_CONNECTION_PRESENCE_TYPE_HIDDEN, TRUE, gabble_status_arguments, NULL, NULL }, { "xa", TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY, TRUE, gabble_status_arguments, NULL, NULL }, { "away", TP_CONNECTION_PRESENCE_TYPE_AWAY, TRUE, gabble_status_arguments, NULL, NULL }, { "dnd", TP_CONNECTION_PRESENCE_TYPE_BUSY, TRUE, gabble_status_arguments, NULL, NULL }, { "available", TP_CONNECTION_PRESENCE_TYPE_AVAILABLE, TRUE, gabble_status_arguments, NULL, NULL }, { "chat", TP_CONNECTION_PRESENCE_TYPE_AVAILABLE, TRUE, gabble_status_arguments, NULL, NULL }, { NULL, 0, FALSE, NULL, NULL, NULL } }; static TpPresenceStatusSpec *gabble_statuses = NULL; /* prototypes */ static void set_xep0186_invisible_cb ( GObject *source, GAsyncResult *set_result, gpointer user_data); static void activate_current_privacy_list_cb ( GObject *source, GAsyncResult *activate_result, gpointer user_data); static void setup_invisible_privacy_list_async (GabbleConnection *self, GAsyncReadyCallback callback, gpointer user_data); static gboolean iq_privacy_list_push_cb ( WockyPorter *porter, WockyStanza *message, gpointer user_data); static void verify_invisible_privacy_list_cb ( GObject *source, GAsyncResult *verify_result, gpointer user_data); static void toggle_presence_visibility_async (GabbleConnection *self, GAsyncReadyCallback callback, gpointer user_data); static gboolean toggle_presence_visibility_finish (GabbleConnection *self, GAsyncResult *result, GError **error); static void toggle_initial_presence_visibility_cb (GObject *source_object, GAsyncResult *result, gpointer user_data); static void activate_current_privacy_list (GabbleConnection *self, GSimpleAsyncResult *result); /* actual code! */ GQuark conn_presence_error_quark (void) { static GQuark quark = 0; if (!quark) quark = g_quark_from_static_string ("conn-presence-error"); return quark; } static GHashTable * construct_contact_statuses_cb (GObject *obj, const GArray *contact_handles, GError **error) { GabbleConnection *self = GABBLE_CONNECTION (obj); TpBaseConnection *base = (TpBaseConnection *) self; guint i; TpHandle handle; GHashTable *contact_statuses, *parameters; TpPresenceStatus *contact_status; GValue *message; GabblePresence *presence; GabblePresenceId status; const gchar *status_message; TpHandleRepoIface *handle_repo = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); if (!tp_handles_are_valid (handle_repo, contact_handles, FALSE, error)) return NULL; contact_statuses = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) tp_presence_status_free); for (i = 0; i < contact_handles->len; i++) { handle = g_array_index (contact_handles, TpHandle, i); if (handle == tp_base_connection_get_self_handle (base)) presence = self->self_presence; else presence = gabble_presence_cache_get (self->presence_cache, handle); if (presence) { status = presence->status; status_message = presence->status_message; } else { if (gabble_roster_handle_sends_presence_to_us (self->roster, handle)) status = GABBLE_PRESENCE_OFFLINE; else status = GABBLE_PRESENCE_UNKNOWN; status_message = NULL; } parameters = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free); if (status_message != NULL) { message = tp_g_value_slice_new (G_TYPE_STRING); g_value_set_static_string (message, status_message); g_hash_table_insert (parameters, "message", message); } contact_status = tp_presence_status_new (status, parameters); g_hash_table_unref (parameters); g_hash_table_insert (contact_statuses, GUINT_TO_POINTER (handle), contact_status); } return contact_statuses; } /** * conn_presence_emit_presence_update: * @self: A #GabbleConnection * @contact_handles: A zero-terminated array of #TpHandle for * the contacts to emit presence for * * Emits the Telepathy PresenceUpdate signal with the current * stored presence information for the given contact. */ void conn_presence_emit_presence_update ( GabbleConnection *self, const GArray *contact_handles) { GHashTable *contact_statuses; contact_statuses = construct_contact_statuses_cb ((GObject *) self, contact_handles, NULL); tp_presence_mixin_emit_presence_update ((GObject *) self, contact_statuses); g_hash_table_unref (contact_statuses); } /* * emit_presences_changed_for_self: * @self: A #GabbleConnection * * Convenience function for emitting presence update signals on D-Bus for our * self handle. */ static void emit_presences_changed_for_self (GabbleConnection *self) { TpBaseConnection *base = TP_BASE_CONNECTION (self); GArray *handles = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), 1); TpHandle self_handle; self_handle = tp_base_connection_get_self_handle (base); g_array_insert_val (handles, 0, self_handle); conn_presence_emit_presence_update (self, handles); g_array_unref (handles); } static WockyStanza * build_shared_status_stanza (GabbleConnection *self) { GabblePresence *presence = self->self_presence; GabbleConnectionPresencePrivate *priv = self->presence_priv; const gchar *bare_jid = conn_util_get_bare_self_jid (self); gpointer key, value; GHashTableIter iter; WockyNode *query_node = NULL; WockyStanza *iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, bare_jid, '(', "query", ':', NS_GOOGLE_SHARED_STATUS, '*', &query_node, '@', "version", GOOGLE_SHARED_STATUS_VERSION, '(', "status", '$', presence->status_message, ')', '(', "show", '$', presence->status == GABBLE_PRESENCE_DND ? "dnd" : "default", ')', ')', NULL); g_hash_table_iter_init (&iter, priv->shared_statuses); while (g_hash_table_iter_next (&iter, &key, &value)) { gchar **status_iter; gchar **statuses = (gchar **) value; WockyNode *list_node = wocky_node_add_child (query_node, "status-list"); wocky_node_set_attribute (list_node, "show", (const gchar *) key); for (status_iter = statuses; *status_iter != NULL; status_iter++) wocky_node_add_child_with_content (list_node, "status", *status_iter); } wocky_node_set_attribute (wocky_node_add_child (query_node, "invisible"), "value", presence->status == GABBLE_PRESENCE_HIDDEN ? "true" : "false"); return iq; } static gboolean is_presence_away (GabblePresenceId status) { return status == GABBLE_PRESENCE_AWAY || status == GABBLE_PRESENCE_XA; } static void set_shared_status_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); GabbleConnection *self = GABBLE_CONNECTION (source_object); GabbleConnectionPresencePrivate *priv = self->presence_priv; GabblePresence *presence = self->self_presence; GError *error = NULL; if (!conn_util_send_iq_finish (self, res, NULL, &error)) { g_simple_async_result_set_error (result, CONN_PRESENCE_ERROR, CONN_PRESENCE_ERROR_SET_SHARED_STATUS, "error setting Google shared status: %s", error->message); } else { gabble_muc_factory_broadcast_presence (self->muc_factory); if (is_presence_away (priv->previous_shared_status)) { /* To use away and xa we need to send a to the server, * but then GTalk also expects us to leave the status using * too. */ conn_presence_signal_own_presence (self, NULL, &error); } else if (priv->previous_shared_status == GABBLE_PRESENCE_HIDDEN && is_presence_away (presence->status)) { /* We sent the shared status change to leave the invisibility, so * now we can actually go to away / xa. */ conn_presence_signal_own_presence (self, NULL, &error); emit_presences_changed_for_self (self); } priv->previous_shared_status = presence->status; } g_simple_async_result_complete (result); g_object_unref (result); if (error != NULL) g_error_free (error); } static void insert_presence_to_shared_statuses (GabbleConnection *self) { GabbleConnectionPresencePrivate *priv = self->presence_priv; GabblePresence *presence = self->self_presence; const gchar *show = presence->status == GABBLE_PRESENCE_DND ? "dnd" : "default"; gchar **statuses = g_hash_table_lookup (priv->shared_statuses, show); if (presence->status_message == NULL || is_presence_away (presence->status)) return; if (statuses == NULL) { statuses = g_new0 (gchar *, 2); statuses[0] = g_strdup (presence->status_message); g_hash_table_insert (priv->shared_statuses, g_strdup (show), statuses); } else { guint i; guint list_len = MIN (priv->max_shared_statuses, (gint) g_strv_length (statuses) + 1); gchar **new_statuses = g_new0 (gchar *, list_len + 1); new_statuses[0] = g_strdup (presence->status_message); for (i = 1; i < list_len; i++) new_statuses[i] = g_strdup (statuses[i - 1]); g_hash_table_insert (priv->shared_statuses, g_strdup (show), new_statuses); } } static void set_shared_status (GabbleConnection *self, GSimpleAsyncResult *result) { GabbleConnectionPresencePrivate *priv = self->presence_priv; GabblePresence *presence = self->self_presence; g_object_ref (result); /* Away is treated like idleness in GTalk; it's per connection and not * global. To set the presence as away we use the traditional , * but, if we were invisible, we need to first leave invisibility. */ if (!is_presence_away (presence->status) || priv->previous_shared_status == GABBLE_PRESENCE_HIDDEN) { WockyStanza *iq; DEBUG ("shared status invisibility is %savailable", priv->shared_status_compat ? "" : "un"); if (presence->status == GABBLE_PRESENCE_HIDDEN && !priv->shared_status_compat) presence->status = GABBLE_PRESENCE_DND; insert_presence_to_shared_statuses (self); iq = build_shared_status_stanza (self); conn_util_send_iq_async (self, iq, NULL, set_shared_status_cb, result); g_object_unref (iq); } else { gboolean retval; GError *error = NULL; DEBUG ("not updating shared status as it's not supported for away"); retval = conn_presence_signal_own_presence (self, NULL, &error); if (!retval) { g_simple_async_result_set_from_error (result, error); g_error_free (error); } emit_presences_changed_for_self (self); priv->previous_shared_status = presence->status; g_simple_async_result_complete_in_idle (result); g_object_unref (result); } } static void set_shared_status_async (GabbleConnection *self, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, set_shared_status_async); set_shared_status (self, result); g_object_unref (result); } static gboolean set_shared_status_finish (GabbleConnection *self, GAsyncResult *result, GError **error) { wocky_implement_finish_void (self, set_shared_status_async); } static void set_xep0186_invisible (GabbleConnection *self, gboolean invisible, GSimpleAsyncResult *result) { TpBaseConnection *base = (TpBaseConnection *) self; GabbleConnectionPresencePrivate *priv = self->presence_priv; GError *error = NULL; g_object_ref (result); if (!invisible && tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTED) { if (priv->privacy_statuses != NULL) { /* A plugin might need to activate a privacy list */ activate_current_privacy_list (self, result); g_object_unref (result); } else { conn_presence_signal_own_presence (self, NULL, &error); g_simple_async_result_complete_in_idle (result); g_object_unref (result); } } else { const gchar *element = invisible ? "invisible" : "visible"; WockyStanza *iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL, '(', element, ':', NS_INVISIBLE, ')', NULL); conn_util_send_iq_async (self, iq, NULL, set_xep0186_invisible_cb, result); g_object_unref (iq); } } static void set_xep0186_invisible_cb ( GObject *source, GAsyncResult *set_result, gpointer user_data) { GabbleConnection *conn = GABBLE_CONNECTION (source); GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); GError *error = NULL; if (!conn_util_send_iq_finish (conn, set_result, NULL, &error)) { g_simple_async_result_set_error (result, CONN_PRESENCE_ERROR, CONN_PRESENCE_ERROR_SET_INVISIBLE, "error setting XEP-0186 (in)visiblity: %s", error->message); g_clear_error (&error); } else { /* If we've become visible, broadcast our new presence and update our MUC * presences. * * If we've become invisible, we only need to do the latter, but the * server will block the former in any case, so let's not bother adding * complexity. */ conn_presence_signal_own_presence (conn, NULL, &error); } if (error != NULL) { g_simple_async_result_set_from_error (result, error); g_error_free (error); } g_simple_async_result_complete (result); g_object_unref (result); } static void activate_current_privacy_list (GabbleConnection *self, GSimpleAsyncResult *result) { GabbleConnectionPresencePrivate *priv = self->presence_priv; TpBaseConnection *base = (TpBaseConnection *) self; WockyStanza *iq; const gchar *list_name = NULL; gboolean invisible; GabblePresence *presence = self->self_presence; GError *error = NULL; WockyNode *active_node; g_assert (priv->privacy_statuses != NULL); list_name = g_hash_table_lookup (priv->privacy_statuses, gabble_statuses[presence->status].name); invisible = (gabble_statuses[presence->status].presence_type == TP_CONNECTION_PRESENCE_TYPE_HIDDEN); DEBUG ("Privacy status %s, backed by %s", gabble_statuses[presence->status].name, list_name ? list_name : "(no list)"); g_object_ref (result); if (tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_CONNECTED && invisible) { if (!gabble_connection_send_presence (self, WOCKY_STANZA_SUB_TYPE_UNAVAILABLE, NULL, NULL, &error)) goto ERROR; } /* If we're still connecting and there's no list to be set, we don't * need to bother with removing the active list; just shortcut to * signalling our presence. */ else if (list_name == NULL && tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTED) { if (!conn_presence_signal_own_presence (self, NULL, &error)) goto ERROR; g_simple_async_result_complete_in_idle (result); g_object_unref (result); return; } iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL, '(', "query", ':', NS_PRIVACY, '(', "active", '*', &active_node, ')', ')', NULL); if (list_name != NULL) wocky_node_set_attribute (active_node, "name", list_name); conn_util_send_iq_async (self, iq, NULL, activate_current_privacy_list_cb, result); g_object_unref (iq); return; ERROR: if (error != NULL) { g_simple_async_result_set_from_error (result, error); g_simple_async_result_complete_in_idle (result); g_error_free (error); g_object_unref (result); } } static void activate_current_privacy_list_cb ( GObject *source, GAsyncResult *activate_result, gpointer user_data) { GabbleConnection *conn = GABBLE_CONNECTION (source); GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); GError *error = NULL; if (!conn_util_send_iq_finish (conn, activate_result, NULL, &error)) { g_simple_async_result_set_error (result, CONN_PRESENCE_ERROR, CONN_PRESENCE_ERROR_SET_PRIVACY_LIST, "error setting requested privacy list: %s", error->message); g_clear_error (&error); } else { /* Whether we were becoming invisible or visible, we now need to * re-broadcast our presence. */ conn_presence_signal_own_presence (conn, NULL, &error); emit_presences_changed_for_self (conn); } if (error != NULL) { g_simple_async_result_set_from_error (result, error); g_error_free (error); } g_simple_async_result_complete (result); g_object_unref (result); } static void disable_invisible_privacy_list (GabbleConnection *self) { GabbleConnectionPresencePrivate *priv = self->presence_priv; if (priv->invisibility_method == INVISIBILITY_METHOD_PRIVACY) { if (self->features & GABBLE_CONNECTION_FEATURES_PRESENCE_INVISIBLE) priv->invisibility_method = INVISIBILITY_METHOD_PRESENCE_INVISIBLE; else priv->invisibility_method = INVISIBILITY_METHOD_NONE; DEBUG ("Set invisibility method to %s", (priv->invisibility_method == INVISIBILITY_METHOD_PRESENCE_INVISIBLE) ? "presence-invisible" : "none"); } } static void create_invisible_privacy_list_reply_cb ( GObject *source, GAsyncResult *create_result, gpointer user_data) { GabbleConnection *conn = GABBLE_CONNECTION (source); GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); GError *error = NULL; if (!conn_util_send_iq_finish (conn, create_result, NULL, &error)) g_simple_async_result_take_error (result, error); g_simple_async_result_complete (result); g_object_unref (result); } static void create_invisible_privacy_list_async (GabbleConnection *self, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, create_invisible_privacy_list_async); WockyStanza *iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL, '(', "query", ':', NS_PRIVACY, '(', "list", '@', "name", self->presence_priv->invisible_list_name, '(', "item", '@', "action", "deny", '@', "order", "1", '(', "presence-out", ')', ')', ')', ')', NULL); DEBUG ("Creating '%s'", self->presence_priv->invisible_list_name); conn_util_send_iq_async (self, iq, NULL, create_invisible_privacy_list_reply_cb, result); g_object_unref (iq); } static gboolean create_invisible_privacy_list_finish (GabbleConnection *self, GAsyncResult *result, GError **error) { wocky_implement_finish_void (self, create_invisible_privacy_list_async); } static void create_invisible_privacy_list_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { GabbleConnection *self = GABBLE_CONNECTION (source_object); GabbleConnectionPresencePrivate *priv = self->presence_priv; GError *error = NULL; if (!create_invisible_privacy_list_finish (self, result, &error)) { DEBUG ("Error creating privacy list: %s", error->message); disable_invisible_privacy_list (self); g_error_free (error); } g_assert (priv->privacy_statuses != NULL); /* "hidden" presence status will be backed by the invisible list */ g_hash_table_insert (priv->privacy_statuses, g_strdup ("hidden"), g_strdup (priv->invisible_list_name)); toggle_presence_visibility_async (self, toggle_initial_presence_visibility_cb, user_data); } static gboolean store_shared_statuses (GabbleConnection *self, WockyNode *query_node) { GabbleConnectionPresencePrivate *priv = self->presence_priv; TpBaseConnection *base = TP_BASE_CONNECTION (self); GabblePresenceId presence_id = self->self_presence->status; const gchar *status_message = NULL; const gchar *min_version = wocky_node_get_attribute (query_node, "status-min-ver"); WockyNodeIter iter; gchar *resource; guint8 prio; gboolean rv; WockyNode *node; gboolean dnd = FALSE; gboolean invisible = FALSE; DEBUG ("status-min-ver %s", min_version); g_object_get (self, "resource", &resource, "priority", &prio, NULL); if (priv->shared_statuses != NULL) g_hash_table_unref (priv->shared_statuses); priv->shared_statuses = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_strfreev); wocky_node_iter_init (&iter, query_node, NULL, NULL); while (wocky_node_iter_next (&iter, &node)) { if (g_strcmp0 (node->name, "status-list") == 0) { WockyNodeIter list_iter; WockyNode *list_item; GPtrArray *statuses; const gchar *show = wocky_node_get_attribute (node, "show"); if (show == NULL) continue; statuses = g_ptr_array_new (); wocky_node_iter_init (&list_iter, node, "status", NULL); while (wocky_node_iter_next (&list_iter, &list_item)) g_ptr_array_add (statuses, g_strdup (list_item->content)); g_ptr_array_add (statuses, NULL); g_hash_table_insert (priv->shared_statuses, g_strdup (show), g_ptr_array_free (statuses, FALSE)); } else if (g_strcmp0 (node->name, "status") == 0) { status_message = node->content; } else if (g_strcmp0 (node->name, "show") == 0) { dnd = g_strcmp0 (node->content, "dnd") == 0; } else if (g_strcmp0 (node->name, "invisible") == 0) { invisible = g_strcmp0 (wocky_node_get_attribute (node, "value"), "true") == 0; } } /* - status-min-ver == 0 means that at least one resource doesn't support * Google shared status, so we fallback to "dnd". * - status-min-ver == 1 means that all the resources support shared * status, but at least one doesn't support invisibility; we have to fall * fall back to "dnd". * - status-miv-ver == 2 means that all the resources support shared status * with invisibility. * - any other value means that the other resources will have to fall back * to version 2 for us. */ priv->shared_status_compat = (g_strcmp0 (min_version, "0") != 0 && g_strcmp0 (min_version, "1") != 0); if (invisible) { if (priv->shared_status_compat) presence_id = GABBLE_PRESENCE_HIDDEN; else presence_id = GABBLE_PRESENCE_DND; } else if (dnd) { presence_id = GABBLE_PRESENCE_DND; } else { if (presence_id == GABBLE_PRESENCE_DND || presence_id == GABBLE_PRESENCE_HIDDEN) presence_id = GABBLE_PRESENCE_AVAILABLE; } if (tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTED) { /* Not connected, override with the local status. */ rv = TRUE; } else if (is_presence_away (self->self_presence->status)) { /* Away presence is not overridden with remote presence because it's * per connection. */ rv = FALSE; } else { /* Update with the remote presence */ rv = gabble_presence_update (self->self_presence, resource, presence_id, status_message, prio, NULL, time (NULL)); } g_free (resource); return rv; } static gboolean iq_shared_status_changed_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { GabbleConnection *self = GABBLE_CONNECTION (user_data); WockyNode *query_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (stanza), "query", NS_GOOGLE_SHARED_STATUS); if (store_shared_statuses (self, query_node)) emit_presences_changed_for_self (self); wocky_porter_acknowledge_iq (porter, stanza, NULL); return TRUE; } static gboolean iq_privacy_list_push_cb ( WockyPorter *porter, WockyStanza *message, gpointer user_data) { GabbleConnection *conn = GABBLE_CONNECTION (user_data); WockyNode *list_node, *query_node, *iq; const gchar *list_name; wocky_porter_acknowledge_iq (wocky_session_get_porter (conn->session), message, NULL); iq = wocky_stanza_get_top_node (message); query_node = wocky_node_get_first_child (iq); list_node = wocky_node_get_child (query_node, "list"); list_name = wocky_node_get_attribute (list_node, "name"); if (g_strcmp0 (list_name, conn->presence_priv->invisible_list_name) == 0) setup_invisible_privacy_list_async (conn, NULL, NULL); return TRUE; } /********************************************************************** * get_existing_privacy_lists_async * ↓ * privacy_lists_loaded_cb * ↓ * ↓ inv_list_name = "invisible" unless set to something else by plugins * ↓ * setup_invisible_privacy_list_async * ↓ * verify_invisible_privacy_list_cb─────────────────────────────────────┐ * | | | | * |success | |n/a failure| * | | | | * | | ↓ | * ├────────+─presence_create_invisible_privacy_list(inv_list_name)─────| * | | | * | |invalid | * | ↓ | * ├────────presence_create_invisible_privacy_list("invisible-gabble")──| * | | * | ↓ * | disable_invisible_privacy_list * | | * ├─────────────────────────────────────────────────────────┘ * ↓ * toggle_presence_visibility_async * ↓ * ... **********************************************************************/ static void get_shared_status_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GabbleConnection *self = GABBLE_CONNECTION (source_object); GabbleConnectionPresencePrivate *priv = self->presence_priv; GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); WockyStanza *iq = NULL; GError *error = NULL; DEBUG (" "); if (!conn_util_send_iq_finish (self, res, &iq, &error)) { DEBUG ("Error getting shared status: %s", error->message); g_simple_async_result_set_from_error (result, error); g_error_free (error); } else { WockyNode *query_node = wocky_node_get_child_ns (wocky_stanza_get_top_node (iq), "query", NS_GOOGLE_SHARED_STATUS); if (query_node != NULL) { const gchar *max_status_message = wocky_node_get_attribute (query_node, "status-max"); const gchar *max_shared = wocky_node_get_attribute (query_node, "status-list-contents-max"); if (max_status_message != NULL) priv->max_status_message_length = (gint) g_ascii_strtoll ( max_status_message, NULL, 10); else priv->max_status_message_length = 0; /* no limit */ if (max_shared != NULL) priv->max_shared_statuses = (gint) g_ascii_strtoll (max_shared, NULL, 10); else priv->max_shared_statuses = 5; /* Safe bet */ store_shared_statuses (self, query_node); } else { g_simple_async_result_set_error (result, CONN_PRESENCE_ERROR, CONN_PRESENCE_ERROR_SET_SHARED_STATUS, "Error retrieving shared status, received empty reply"); } g_object_unref (iq); } g_simple_async_result_complete_in_idle (result); g_object_unref (result); } static void get_shared_status_async (GabbleConnection *self, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, get_shared_status_async); WockyStanza *iq; DEBUG (" "); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, conn_util_get_bare_self_jid (self), '(', "query", ':', NS_GOOGLE_SHARED_STATUS, '@', "version", GOOGLE_SHARED_STATUS_VERSION, ')', NULL); conn_util_send_iq_async (self, iq, NULL, get_shared_status_cb, result); /* We cannot use the chat status with GTalk's shared status. */ if (self->self_presence->status == GABBLE_PRESENCE_CHAT) self->self_presence->status = GABBLE_PRESENCE_AVAILABLE; g_object_unref (iq); } static gboolean get_shared_status_finish (GabbleConnection *self, GAsyncResult *result, GError **error) { wocky_implement_finish_void (self, get_shared_status_async); } static void get_existing_privacy_lists_cb ( GObject *source, GAsyncResult *get_result, gpointer user_data) { GabbleConnection *conn = GABBLE_CONNECTION (source); GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); WockyStanza *reply_msg = NULL; WockyNode *query_node; GError *error = NULL; if (!conn_util_send_iq_finish (conn, get_result, &reply_msg, &error)) { DEBUG ("Error getting privacy lists: %s", error->message); g_simple_async_result_set_from_error (result, error); g_error_free (error); goto out; } query_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (reply_msg), "query", NS_PRIVACY); if (query_node == NULL) { g_simple_async_result_set_error (result, TP_ERROR, TP_ERROR_NETWORK_ERROR, "no node in 'list privacy lists' reply"); } else { GabbleConnectionPresencePrivate *priv = conn->presence_priv; WockyNode *list_node; WockyNodeIter iter; GabblePluginLoader *loader = gabble_plugin_loader_dup (); /* As we're called only once, privacy_statuses couldn't have been * already initialised. */ g_assert (priv->privacy_statuses == NULL); priv->privacy_statuses = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, g_free); wocky_node_iter_init (&iter, query_node, "list", NULL); while (wocky_node_iter_next (&iter, &list_node)) { const gchar *list_name = wocky_node_get_attribute (list_node, "name"); const gchar *status_name; status_name = gabble_plugin_loader_presence_status_for_privacy_list (loader, list_name); if (status_name) { DEBUG ("Presence status %s backed by privacy list %s", status_name, list_name); g_hash_table_replace (priv->privacy_statuses, g_strdup (status_name), g_strdup (list_name)); } } } out: g_simple_async_result_complete (result); g_object_unref (result); g_clear_object (&reply_msg); } static void get_existing_privacy_lists_async (GabbleConnection *self, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, get_existing_privacy_lists_async); WockyStanza *iq; iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, NULL, '(', "query", ':', NS_PRIVACY, ')', NULL); conn_util_send_iq_async (self, iq, NULL, get_existing_privacy_lists_cb, result); g_object_unref (iq); } static gboolean get_existing_privacy_lists_finish (GabbleConnection *self, GAsyncResult *result, GError **error) { wocky_implement_finish_void (self, get_existing_privacy_lists_async); } static void setup_invisible_privacy_list_async (GabbleConnection *self, GAsyncReadyCallback callback, gpointer user_data) { GabbleConnectionPresencePrivate *priv = self->presence_priv; GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, setup_invisible_privacy_list_async); WockyStanza *iq; if (priv->invisible_list_name == NULL) priv->invisible_list_name = g_strdup ("invisible"); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, NULL, '(', "query", ':', NS_PRIVACY, '(', "list", '@', "name", self->presence_priv->invisible_list_name, ')', ')', NULL); wocky_porter_send_iq_async (wocky_session_get_porter (self->session), iq, NULL, verify_invisible_privacy_list_cb, result); g_object_unref (iq); } static gboolean setup_invisible_privacy_list_finish (GabbleConnection *self, GAsyncResult *result, GError **error) { wocky_implement_finish_void (self, setup_invisible_privacy_list_async); } static gboolean is_valid_invisible_list (WockyNode *list_node) { WockyNode *top_node = NULL; WockyNode *child; WockyNodeIter i; guint top_order = G_MAXUINT; wocky_node_iter_init (&i, list_node, "item", NULL); while (wocky_node_iter_next (&i, &child)) { const gchar *order_str; guint order; gchar *end; order_str = wocky_node_get_attribute (child, "order"); if (order_str == NULL) continue; order = strtoul (order_str, &end, 10); if (*end != '\0') continue; if (order < top_order) { top_order = order; top_node = child; } } if (top_node != NULL) { const gchar *value = wocky_node_get_attribute (top_node, "value"); const gchar *action = wocky_node_get_attribute (top_node, "action"); WockyNode *presence_out = wocky_node_get_child (top_node, "presence-out"); return (value == NULL && g_strcmp0 (action, "deny") == 0 && presence_out != NULL); } return FALSE; } static void verify_invisible_privacy_list_cb ( GObject *source, GAsyncResult *verify_result, gpointer user_data) { GabbleConnection *conn = GABBLE_CONNECTION ( g_async_result_get_source_object (G_ASYNC_RESULT (user_data))); GabbleConnectionPresencePrivate *priv = conn->presence_priv; WockyStanza *reply_msg = NULL; WockyNode *query_node = NULL, *list_node = NULL; GError *error = NULL; reply_msg = wocky_porter_send_iq_finish (WOCKY_PORTER (source), verify_result, &error); if (reply_msg != NULL) query_node = wocky_node_get_child_ns (wocky_stanza_get_top_node (reply_msg), "query", NS_PRIVACY); if (query_node != NULL) list_node = wocky_node_get_child (query_node, "list"); if (reply_msg != NULL && !wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL)) { if (list_node == NULL || !is_valid_invisible_list (list_node)) { g_free (priv->invisible_list_name); priv->invisible_list_name = g_strdup ("invisible-gabble"); create_invisible_privacy_list_async (conn, create_invisible_privacy_list_cb, user_data); } else { /* "hidden" presence status can be backed by this list */ g_hash_table_insert (conn->presence_priv->privacy_statuses, g_strdup ("hidden"), g_strdup (priv->invisible_list_name)); toggle_presence_visibility_async (conn, toggle_initial_presence_visibility_cb, user_data); } } else if (error->domain == WOCKY_XMPP_ERROR && error->code == WOCKY_XMPP_ERROR_ITEM_NOT_FOUND) { create_invisible_privacy_list_async (conn, create_invisible_privacy_list_cb, user_data); } else { disable_invisible_privacy_list (conn); toggle_presence_visibility_async (conn, toggle_initial_presence_visibility_cb, user_data); } if (error != NULL) g_error_free (error); g_clear_object (&reply_msg); g_clear_object (&conn); } static void initial_presence_setup_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { GabbleConnection *self = GABBLE_CONNECTION (source_object); GabbleConnectionPresencePrivate *priv = self->presence_priv; GSimpleAsyncResult *external_result = G_SIMPLE_ASYNC_RESULT (user_data); GError *error = NULL; if (!setup_invisible_privacy_list_finish (self, result, &error)) { g_simple_async_result_set_from_error (external_result, error); g_error_free (error); } if (priv->invisibility_method == INVISIBILITY_METHOD_PRIVACY && self->session != NULL) { priv->iq_list_push_id = wocky_c2s_porter_register_handler_from_server ( WOCKY_C2S_PORTER (wocky_session_get_porter (self->session)), WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, iq_privacy_list_push_cb, self, '(', "query", ':', NS_PRIVACY, '(', "list", ')', ')', NULL); } g_simple_async_result_complete_in_idle (external_result); g_object_unref (external_result); } static void toggle_initial_presence_visibility_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { GabbleConnection *self = GABBLE_CONNECTION (source_object); GSimpleAsyncResult *external_result = G_SIMPLE_ASYNC_RESULT (user_data); GError *error = NULL; if (!toggle_presence_visibility_finish (self, result, &error)) { self->self_presence->status = GABBLE_PRESENCE_DND; g_clear_error (&error); if (!conn_presence_signal_own_presence (self, NULL, &error)) { g_simple_async_result_set_from_error (external_result, error); g_error_free (error); } } g_simple_async_result_complete_in_idle (external_result); g_object_unref (external_result); } static void privacy_lists_loaded_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { GabbleConnection *self = GABBLE_CONNECTION (source_object); GabbleConnectionPresencePrivate *priv = self->presence_priv; GError *error = NULL; if (get_existing_privacy_lists_finish (self, result, &error)) { /* if the above call succeeded, the server supports privacy * lists, so this should be initialised. */ g_assert (priv->privacy_statuses != NULL); /* If anyone/plugins already set up "hidden" status backing * by a specific list, try to use that instead. If that list * is inadequate, we'll create gabble-specific one. */ priv->invisible_list_name = g_strdup (g_hash_table_lookup (priv->privacy_statuses, "hidden")); if (priv->invisibility_method == INVISIBILITY_METHOD_NONE) priv->invisibility_method = INVISIBILITY_METHOD_PRIVACY; } if (priv->invisibility_method == INVISIBILITY_METHOD_PRIVACY) setup_invisible_privacy_list_async (self, initial_presence_setup_cb, user_data); else toggle_presence_visibility_async (self, toggle_initial_presence_visibility_cb, user_data); } static void shared_status_toggle_initial_presence_visibility_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { GabbleConnection *self = GABBLE_CONNECTION (source_object); GSimpleAsyncResult *external_result = G_SIMPLE_ASYNC_RESULT (user_data); GError *error = NULL; if (!toggle_presence_visibility_finish (self, result, &error)) { g_simple_async_result_set_from_error (external_result, error); g_clear_error (&error); } else if (self->self_presence->status != GABBLE_PRESENCE_AWAY && self->self_presence->status != GABBLE_PRESENCE_XA) { /* With shared status we send the normal only with away and * extended away, but for initial status we need to send as * it also contains the caps. */ if (!conn_presence_signal_own_presence (self, NULL, &error)) { g_simple_async_result_set_from_error (external_result, error); g_error_free (error); } } g_simple_async_result_complete_in_idle (external_result); g_object_unref (external_result); } static void shared_status_setup_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { GError *error = NULL; GabbleConnection *self = GABBLE_CONNECTION (source_object); GabbleConnectionPresencePrivate *priv = self->presence_priv; if (get_shared_status_finish (self, result, &error)) { WockyPorter *porter = wocky_session_get_porter (self->session); priv->invisibility_method = INVISIBILITY_METHOD_SHARED_STATUS; priv->iq_shared_status_cb = wocky_c2s_porter_register_handler_from_server ( WOCKY_C2S_PORTER (porter), WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, iq_shared_status_changed_cb, self, '(', "query", ':', NS_GOOGLE_SHARED_STATUS, ')', NULL); } else { DEBUG ("failed: %s", error->message); g_error_free (error); } toggle_presence_visibility_async (self, shared_status_toggle_initial_presence_visibility_cb, user_data); } void conn_presence_set_initial_presence_async (GabbleConnection *self, GAsyncReadyCallback callback, gpointer user_data) { GabbleConnectionPresencePrivate *priv = self->presence_priv; GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, conn_presence_set_initial_presence_async); if (self->features & GABBLE_CONNECTION_FEATURES_INVISIBLE) priv->invisibility_method = INVISIBILITY_METHOD_INVISIBLE_COMMAND; if (self->features & GABBLE_CONNECTION_FEATURES_GOOGLE_SHARED_STATUS) get_shared_status_async (self, shared_status_setup_cb, result); else get_existing_privacy_lists_async (self, privacy_lists_loaded_cb, result); } gboolean conn_presence_set_initial_presence_finish (GabbleConnection *self, GAsyncResult *result, GError **error) { wocky_implement_finish_void (self, conn_presence_set_initial_presence_async); } /** * conn_presence_statuses: * * Used to retrieve the list of presence statuses supported by connections * consisting of the basic statuses followed by any statuses defined by * plugins. * * Returns: an array of #TpPresenceStatusSpec terminated by a 0 filled member * The array is owned by te connection presence implementation and must not * be altered or freed by anyone else. **/ const TpPresenceStatusSpec * conn_presence_statuses (void) { if (gabble_statuses == NULL) { GabblePluginLoader *loader = gabble_plugin_loader_dup (); gabble_statuses = gabble_plugin_loader_append_statuses ( loader, gabble_base_statuses); g_object_unref (loader); } return gabble_statuses; } static guint get_maximum_status_message_length_cb (GObject *obj) { GabbleConnection *conn = GABBLE_CONNECTION (obj); GabbleConnectionPresencePrivate *priv = conn->presence_priv; return priv->max_status_message_length; } /** * conn_presence_signal_own_presence: * @self: A #GabbleConnection * @to: bare or full JID for directed presence, or NULL * @error: pointer in which to return a GError in case of failure. * * Signal the user's stored presence to @to, or to the jabber server * * Retuns: FALSE if an error occurred */ gboolean conn_presence_signal_own_presence (GabbleConnection *self, const gchar *to, GError **error) { GabbleConnectionPresencePrivate *priv = self->presence_priv; GabblePresence *presence = self->self_presence; TpBaseConnection *base = (TpBaseConnection *) self; WockyStanza *message = gabble_presence_as_message (presence, to); gboolean ret; if (presence->status == GABBLE_PRESENCE_HIDDEN && to == NULL) { if (priv->invisibility_method == INVISIBILITY_METHOD_PRESENCE_INVISIBLE) wocky_node_set_attribute (wocky_stanza_get_top_node (message), "type", "invisible"); /* FIXME: or if sending directed presence, should we add * away? */ } gabble_connection_fill_in_caps (self, message); ret = _gabble_connection_send (self, message, error); g_object_unref (message); /* FIXME: if sending broadcast presence, should we echo it to everyone we * previously sent directed presence to? (Perhaps also GC them after a * while?) */ if (to == NULL && tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_CONNECTED) gabble_muc_factory_broadcast_presence (self->muc_factory); return ret; } gboolean conn_presence_visible_to (GabbleConnection *self, TpHandle recipient) { if (self->self_presence->status == GABBLE_PRESENCE_HIDDEN) return FALSE; if (!gabble_roster_handle_gets_presence_from_us (self->roster, recipient)) return FALSE; /* FIXME: other reasons they might not be able to see our presence? */ return TRUE; } static void activate_current_privacy_list_async (GabbleConnection *self, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, activate_current_privacy_list_async); activate_current_privacy_list (self, result); g_object_unref (result); } static void toggle_presence_visibility_async (GabbleConnection *self, GAsyncReadyCallback callback, gpointer user_data) { GabbleConnectionPresencePrivate *priv = self->presence_priv; GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, toggle_presence_visibility_async); gboolean set_invisible = (self->self_presence->status == GABBLE_PRESENCE_HIDDEN); switch (priv->invisibility_method) { case INVISIBILITY_METHOD_SHARED_STATUS: set_shared_status (self, result); break; case INVISIBILITY_METHOD_INVISIBLE_COMMAND: set_xep0186_invisible (self, set_invisible, result); break; case INVISIBILITY_METHOD_PRIVACY: activate_current_privacy_list (self, result); break; default: { GError *error = NULL; /* If we don't even support XEP-0018, revert to DND */ if (priv->invisibility_method == INVISIBILITY_METHOD_NONE && set_invisible) self->self_presence->status = GABBLE_PRESENCE_DND; if (!conn_presence_signal_own_presence (self, NULL, &error)) { g_simple_async_result_set_from_error (result, error); g_error_free (error); } g_simple_async_result_complete_in_idle (result); } } g_object_unref (result); } static gboolean toggle_presence_visibility_finish ( GabbleConnection *self, GAsyncResult *result, GError **error) { wocky_implement_finish_void (self, toggle_presence_visibility_async); } static void set_shared_status_presence_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GabbleConnection *self = GABBLE_CONNECTION (source_object); GError *error = NULL; DEBUG (" "); if (!set_shared_status_finish (self, res, &error)) { DEBUG ("Error setting shared status %s", error->message); g_error_free (error); error = NULL; } emit_presences_changed_for_self (self); } static void toggle_presence_visibility_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GabbleConnection *self = GABBLE_CONNECTION (source_object); GError *error = NULL; DEBUG (" "); if (!toggle_presence_visibility_finish (self, res, &error)) { DEBUG ("Error setting visibility, falling back to dnd: %s", error->message); g_error_free (error); error = NULL; self->self_presence->status = GABBLE_PRESENCE_DND; if (!conn_presence_signal_own_presence (self, NULL, &error)) { DEBUG ("Failed to set fallback status: %s", error->message); g_error_free (error); } } emit_presences_changed_for_self (self); } static gboolean set_own_status_cb (GObject *obj, const TpPresenceStatus *status, GError **error) { GabbleConnection *conn = GABBLE_CONNECTION (obj); GabbleConnectionPresencePrivate *priv = conn->presence_priv; TpBaseConnection *base = (TpBaseConnection *) conn; GabblePresenceId i = GABBLE_PRESENCE_AVAILABLE; const gchar *message_str = NULL; gchar *message_truncated = NULL; gchar *resource; gint8 prio; gboolean retval = TRUE; GabblePresenceId prev_status = conn->self_presence->status; g_object_get (conn, "resource", &resource, "priority", &prio, NULL); if (status) { GHashTable *args = status->optional_arguments; GValue *message = NULL, *priority = NULL; i = status->index; /* Workaround for tp-glib not checking whether we support setting * a particular status (can be removed once we depend on tp-glib * with the check enabled). Assumes PresenceId value ordering. */ if (i < GABBLE_PRESENCE_HIDDEN) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Status '%s' can not be requested in this connection", gabble_statuses[i].name); retval = FALSE; goto OUT; } if (args != NULL) { message = g_hash_table_lookup (args, "message"); priority = g_hash_table_lookup (args, "priority"); } if (message) { if (!G_VALUE_HOLDS_STRING (message)) { DEBUG ("got a status message which was not a string"); g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Status argument 'message' requires a string"); retval = FALSE; goto OUT; } message_str = g_value_get_string (message); } if (priority) { if (!G_VALUE_HOLDS_INT (priority)) { DEBUG ("got a priority value which was not a signed integer"); g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Status argument 'priority' requires a signed integer"); retval = FALSE; goto OUT; } prio = CLAMP (g_value_get_int (priority), G_MININT8, G_MAXINT8); } } if (message_str && priv->max_status_message_length > 0 && priv->shared_statuses != NULL) { message_truncated = g_strndup (message_str, priv->max_status_message_length); message_str = message_truncated; } if (gabble_presence_update (conn->self_presence, resource, i, message_str, prio, NULL, time (NULL))) { if (tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTED) { retval = TRUE; } else if (prev_status != i && (prev_status == GABBLE_PRESENCE_HIDDEN || i == GABBLE_PRESENCE_HIDDEN)) { toggle_presence_visibility_async (conn, toggle_presence_visibility_cb, NULL); } /* if privacy lists are supported, make sure we update the current * list as needed, before signalling own presence */ else if (priv->privacy_statuses != NULL) { activate_current_privacy_list_async (conn, NULL, NULL); } else if (priv->shared_statuses != NULL) { set_shared_status_async (conn, set_shared_status_presence_cb, NULL); } else { retval = conn_presence_signal_own_presence (conn, NULL, error); emit_presences_changed_for_self (conn); } } OUT: g_free (message_truncated); g_free (resource); return retval; } static void connection_presences_updated_cb ( GabblePresenceCache *cache, const GArray *handles, gpointer user_data) { GabbleConnection *conn = GABBLE_CONNECTION (user_data); conn_presence_emit_presence_update (conn, handles); } static void connection_status_changed_cb ( GabbleConnection *conn, TpConnectionStatus status, TpConnectionStatusReason reason, gpointer user_data) { if (status == TP_CONNECTION_STATUS_CONNECTED) emit_presences_changed_for_self (conn); } static gboolean status_available_cb (GObject *obj, guint status) { GabbleConnection *conn = GABBLE_CONNECTION (obj); TpBaseConnection *base = (TpBaseConnection *) conn; GabbleConnectionPresencePrivate *priv = conn->presence_priv; TpConnectionPresenceType presence_type = gabble_statuses[status].presence_type; if (tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTED) { /* we just don't know yet */ return TRUE; } /* This relies on the fact the first entries in the statuses table * are from gabble_base_statuses. If index to the statuses table is outside * the gabble_base_statuses table, the status is provided by a plugin. */ if (status >= G_N_ELEMENTS (gabble_base_statuses)) { /* At the moment, plugins can only implement statuses via privacy * lists, so any extra status should be backed by one. If it's not * (or if privacy lists are not supported by the server at all) * by the time we're connected, it's not available. */ if (priv->privacy_statuses != NULL && g_hash_table_lookup (priv->privacy_statuses, gabble_statuses[status].name)) { return TRUE; } else { return FALSE; } } if (presence_type == TP_CONNECTION_PRESENCE_TYPE_HIDDEN && priv->invisibility_method == INVISIBILITY_METHOD_NONE) { /* If we've gone online and found that the server doesn't support * invisible, reject it. */ return FALSE; } else if (status == GABBLE_PRESENCE_CHAT && priv->shared_statuses != NULL) { /* We cannot use the chat status with GTalk's shared status. */ return FALSE; } else { return TRUE; } } TpConnectionPresenceType conn_presence_get_type (GabblePresence *presence) { return gabble_statuses[presence->status].presence_type; } /* We should update this when telepathy-glib supports setting * statuses at constructor time (see * https://bugs.freedesktop.org/show_bug.cgi?id=12896 ). * Until then, gabble_statuses is leaked. */ void conn_presence_class_init (GabbleConnectionClass *klass) { TpPresenceMixinClass *mixin_cls; tp_presence_mixin_class_init ((GObjectClass *) klass, G_STRUCT_OFFSET (GabbleConnectionClass, presence_class), status_available_cb, construct_contact_statuses_cb, set_own_status_cb, conn_presence_statuses ()); mixin_cls = TP_PRESENCE_MIXIN_CLASS (klass); mixin_cls->get_maximum_status_message_length = get_maximum_status_message_length_cb; tp_presence_mixin_simple_presence_init_dbus_properties ( (GObjectClass *) klass); } void conn_presence_init (GabbleConnection *conn) { conn->presence_priv = g_slice_new0 (GabbleConnectionPresencePrivate); conn->presence_priv->previous_shared_status = GABBLE_PRESENCE_UNKNOWN; g_signal_connect (conn->presence_cache, "presences-updated", G_CALLBACK (connection_presences_updated_cb), conn); g_signal_connect (conn, "status-changed", G_CALLBACK (connection_status_changed_cb), conn); conn->presence_priv->invisible_list_name = g_strdup ("invisible"); conn->presence_priv->privacy_statuses = NULL; tp_presence_mixin_init ((GObject *) conn, G_STRUCT_OFFSET (GabbleConnection, presence)); tp_presence_mixin_simple_presence_register_with_contacts_mixin ( G_OBJECT (conn)); } void conn_presence_dispose (GabbleConnection *self) { GabbleConnectionPresencePrivate *priv = self->presence_priv; WockyPorter *porter; if (self->session == NULL) return; porter = wocky_session_get_porter (self->session); if (priv->iq_shared_status_cb != 0) { wocky_porter_unregister_handler (porter, priv->iq_shared_status_cb); priv->iq_shared_status_cb = 0; } if (priv->iq_list_push_id != 0) { wocky_porter_unregister_handler (porter, priv->iq_list_push_id); priv->iq_list_push_id = 0; } } void conn_presence_finalize (GabbleConnection *conn) { GabbleConnectionPresencePrivate *priv = conn->presence_priv; g_free (priv->invisible_list_name); if (priv->privacy_statuses != NULL) g_hash_table_unref (priv->privacy_statuses); if (priv->shared_statuses != NULL) g_hash_table_unref (priv->shared_statuses); g_slice_free (GabbleConnectionPresencePrivate, priv); tp_presence_mixin_finalize ((GObject *) conn); } static void conn_presence_send_directed_presence ( GabbleSvcConnectionInterfaceGabbleDecloak *conn, guint contact, gboolean full, DBusGMethodInvocation *context) { GabbleConnection *self = GABBLE_CONNECTION (conn); TpBaseConnection *base = TP_BASE_CONNECTION (conn); TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); const gchar *jid = tp_handle_inspect (contact_handles, contact); gboolean ok; GError *error = NULL; g_return_if_fail (jid != NULL); /* We don't strictly respect @full - we'll always send full presence to * people we think ought to be receiving it anyway, because if we didn't, * you could confuse them by sending directed presence that was less * informative than the broadcast presence they already saw. */ if (full || conn_presence_visible_to (self, contact)) { ok = conn_presence_signal_own_presence (self, jid, &error); } else { ok = gabble_connection_send_capabilities (self, jid, &error); } if (ok) { gabble_svc_connection_interface_gabble_decloak_return_from_send_directed_presence (context); } else { dbus_g_method_return_error (context, error); g_error_free (error); } } void conn_decloak_emit_requested (GabbleConnection *conn, TpHandle contact, const gchar *reason, gboolean decloaked) { gabble_svc_connection_interface_gabble_decloak_emit_decloak_requested (conn, contact, reason, decloaked); } void conn_decloak_iface_init (gpointer g_iface, gpointer iface_data) { #define IMPLEMENT(x) \ gabble_svc_connection_interface_gabble_decloak_implement_##x (\ g_iface, conn_presence_##x) IMPLEMENT (send_directed_presence); #undef IMPLEMENT } telepathy-gabble-0.18.3/src/error.c0000664000175000017500000003421612223562023020265 0ustar00cassidycassidy00000000000000/* * gabble-error.c - Source for Gabble's error handling API * Copyright (C) 2006-2007 Collabora Ltd. * Copyright (C) 2006 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "error.h" #include #include #include "namespaces.h" #include "util.h" #include static inline TpError set_conn_reason (TpConnectionStatusReason *p, TpConnectionStatusReason r, TpError e) { if (p != NULL) *p = r; return e; } #define set_easy_conn_reason(p, suffix) \ set_conn_reason (p, TP_CONNECTION_STATUS_REASON_ ## suffix, \ TP_ERROR_ ## suffix) static TpError map_wocky_xmpp_error (const GError *error, TpConnectionStatusReason *conn_reason) { g_return_val_if_fail (error->domain == WOCKY_XMPP_ERROR, TP_ERROR_NOT_AVAILABLE); switch (error->code) { case WOCKY_XMPP_ERROR_REDIRECT: case WOCKY_XMPP_ERROR_GONE: /* FIXME: wild guess at the right error */ return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED, TP_ERROR_DOES_NOT_EXIST); case WOCKY_XMPP_ERROR_BAD_REQUEST: case WOCKY_XMPP_ERROR_UNEXPECTED_REQUEST: /* probably an internal error in Gabble/Wocky */ return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_NETWORK_ERROR, TP_ERROR_CONFUSED); case WOCKY_XMPP_ERROR_JID_MALFORMED: return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_NETWORK_ERROR, TP_ERROR_INVALID_HANDLE); case WOCKY_XMPP_ERROR_NOT_AUTHORIZED: case WOCKY_XMPP_ERROR_PAYMENT_REQUIRED: case WOCKY_XMPP_ERROR_FORBIDDEN: /* FIXME: the closest we've got for these, I think? */ return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED, TP_ERROR_PERMISSION_DENIED); case WOCKY_XMPP_ERROR_ITEM_NOT_FOUND: return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED, TP_ERROR_DOES_NOT_EXIST); case WOCKY_XMPP_ERROR_RECIPIENT_UNAVAILABLE: return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED, TP_ERROR_OFFLINE); case WOCKY_XMPP_ERROR_REMOTE_SERVER_NOT_FOUND: /* FIXME: or NetworkError? */ return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED, TP_ERROR_DOES_NOT_EXIST); case WOCKY_XMPP_ERROR_NOT_ALLOWED: case WOCKY_XMPP_ERROR_NOT_ACCEPTABLE: case WOCKY_XMPP_ERROR_REGISTRATION_REQUIRED: case WOCKY_XMPP_ERROR_SUBSCRIPTION_REQUIRED: /* FIXME: the closest we've got for all these, I think? */ return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED, TP_ERROR_PERMISSION_DENIED); case WOCKY_XMPP_ERROR_REMOTE_SERVER_TIMEOUT: return set_easy_conn_reason (conn_reason, NETWORK_ERROR); case WOCKY_XMPP_ERROR_CONFLICT: /* this is the best we can do in general - callers should * special-case according to their domain knowledge, * to turn it into RegistrationExists, ConnectionReplaced, etc. */ return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_NAME_IN_USE, TP_ERROR_NOT_AVAILABLE); case WOCKY_XMPP_ERROR_INTERNAL_SERVER_ERROR: return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED, TP_ERROR_SERVICE_CONFUSED); case WOCKY_XMPP_ERROR_RESOURCE_CONSTRAINT: /* FIXME: Telepathy's ServiceBusy means the server, but the remote * client can also raise */ return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED, TP_ERROR_SERVICE_BUSY); case WOCKY_XMPP_ERROR_FEATURE_NOT_IMPLEMENTED: case WOCKY_XMPP_ERROR_SERVICE_UNAVAILABLE: return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED, TP_ERROR_NOT_AVAILABLE); case WOCKY_XMPP_ERROR_UNDEFINED_CONDITION: default: return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED, TP_ERROR_NOT_AVAILABLE); } } static TpError map_wocky_auth_error (const GError *error, TpConnectionStatusReason *conn_reason) { g_return_val_if_fail (error->domain == WOCKY_AUTH_ERROR, TP_ERROR_NOT_AVAILABLE); switch (error->code) { case WOCKY_AUTH_ERROR_CONNRESET: return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_NETWORK_ERROR, TP_ERROR_CONNECTION_LOST); case WOCKY_AUTH_ERROR_NETWORK: case WOCKY_AUTH_ERROR_STREAM: return set_easy_conn_reason (conn_reason, NETWORK_ERROR); case WOCKY_AUTH_ERROR_RESOURCE_CONFLICT: return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_NAME_IN_USE, TP_ERROR_ALREADY_CONNECTED); case WOCKY_AUTH_ERROR_NOT_SUPPORTED: case WOCKY_AUTH_ERROR_NO_SUPPORTED_MECHANISMS: return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED, TP_ERROR_NOT_IMPLEMENTED); case WOCKY_AUTH_ERROR_INVALID_REPLY: return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED, TP_ERROR_SERVICE_CONFUSED); case WOCKY_AUTH_ERROR_INIT_FAILED: case WOCKY_AUTH_ERROR_NO_CREDENTIALS: case WOCKY_AUTH_ERROR_NOT_AUTHORIZED: case WOCKY_AUTH_ERROR_FAILURE: default: return set_easy_conn_reason (conn_reason, AUTHENTICATION_FAILED); } } static TpError map_wocky_connector_error (const GError *error, TpConnectionStatusReason *conn_reason) { g_return_val_if_fail (error->domain == WOCKY_CONNECTOR_ERROR, TP_ERROR_NOT_AVAILABLE); switch (error->code) { case WOCKY_CONNECTOR_ERROR_SESSION_DENIED: return set_easy_conn_reason (conn_reason, AUTHENTICATION_FAILED); case WOCKY_CONNECTOR_ERROR_BIND_CONFLICT: return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_NAME_IN_USE, TP_ERROR_ALREADY_CONNECTED); case WOCKY_CONNECTOR_ERROR_REGISTRATION_CONFLICT: return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_NAME_IN_USE, TP_ERROR_REGISTRATION_EXISTS); case WOCKY_CONNECTOR_ERROR_REGISTRATION_REJECTED: /* AuthenticationFailed is the closest ConnectionStatusReason to * "I tried but couldn't register you an account." */ return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED, TP_ERROR_PERMISSION_DENIED); case WOCKY_CONNECTOR_ERROR_REGISTRATION_UNSUPPORTED: return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED, TP_ERROR_NOT_AVAILABLE); default: return set_easy_conn_reason (conn_reason, NETWORK_ERROR); } } static TpError map_wocky_stream_error (const GError *error, TpConnectionStatus previous_status, TpConnectionStatusReason *conn_reason) { g_return_val_if_fail (error->domain == WOCKY_XMPP_STREAM_ERROR, TP_ERROR_NOT_AVAILABLE); switch (error->code) { case WOCKY_XMPP_STREAM_ERROR_HOST_UNKNOWN: /* If we get this while we're logging in, it's because we're trying * to connect to foo@bar.com but the server doesn't know about * bar.com, probably because the user entered a non-GTalk JID into * a GTalk profile that forces the server. */ return set_easy_conn_reason (conn_reason, AUTHENTICATION_FAILED); case WOCKY_XMPP_STREAM_ERROR_CONFLICT: if (previous_status == TP_CONNECTION_STATUS_CONNECTED) { return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_NAME_IN_USE, TP_ERROR_CONNECTION_REPLACED); } else { return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_NAME_IN_USE, TP_ERROR_ALREADY_CONNECTED); } default: return set_easy_conn_reason (conn_reason, NETWORK_ERROR); } } static TpError map_wocky_tls_cert_error (const GError *error, TpConnectionStatusReason *conn_reason) { g_return_val_if_fail (error->domain == WOCKY_TLS_CERT_ERROR, TP_ERROR_NOT_AVAILABLE); switch (error->code) { case WOCKY_TLS_CERT_NO_CERTIFICATE: return set_easy_conn_reason (conn_reason, CERT_NOT_PROVIDED); case WOCKY_TLS_CERT_INSECURE: case WOCKY_TLS_CERT_SIGNER_UNKNOWN: case WOCKY_TLS_CERT_SIGNER_UNAUTHORISED: case WOCKY_TLS_CERT_REVOKED: case WOCKY_TLS_CERT_MAYBE_DOS: return set_easy_conn_reason (conn_reason, CERT_UNTRUSTED); case WOCKY_TLS_CERT_EXPIRED: return set_easy_conn_reason (conn_reason, CERT_EXPIRED); case WOCKY_TLS_CERT_NOT_ACTIVE: return set_easy_conn_reason (conn_reason, CERT_NOT_ACTIVATED); case WOCKY_TLS_CERT_NAME_MISMATCH: return set_easy_conn_reason (conn_reason, CERT_HOSTNAME_MISMATCH); case WOCKY_TLS_CERT_INTERNAL_ERROR: case WOCKY_TLS_CERT_UNKNOWN_ERROR: default: return set_conn_reason (conn_reason, TP_CONNECTION_STATUS_REASON_CERT_OTHER_ERROR, TP_ERROR_ENCRYPTION_ERROR); } } static TpError map_connection_error (const GError *error) { switch (error->code) { case WOCKY_XMPP_CONNECTION_ERROR_EOS: case WOCKY_XMPP_CONNECTION_ERROR_CLOSED: return TP_ERROR_CANCELLED; case WOCKY_XMPP_CONNECTION_ERROR_NOT_OPEN: case WOCKY_XMPP_CONNECTION_ERROR_IS_CLOSED: case WOCKY_XMPP_CONNECTION_ERROR_IS_OPEN: default: return TP_ERROR_DISCONNECTED; } } static const gchar * get_error_prefix (GEnumClass *klass, gint code, const gchar *fallback) { GEnumValue *value; if (klass == NULL) return fallback; value = g_enum_get_value (klass, code); if (value == NULL || value->value_name == NULL) return fallback; return value->value_name; } void gabble_set_tp_conn_error_from_wocky (const GError *wocky_error, TpConnectionStatus previous_status, TpConnectionStatusReason *conn_reason, GError **error) { GEnumClass *klass; const gchar *name; if (conn_reason != NULL) *conn_reason = TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED; g_return_if_fail (wocky_error != NULL); if (wocky_error->domain == WOCKY_XMPP_ERROR) { klass = g_type_class_ref (WOCKY_TYPE_XMPP_ERROR); name = get_error_prefix (klass, wocky_error->code, "unknown WockyXmppError code"); g_set_error (error, TP_ERROR, map_wocky_xmpp_error (wocky_error, conn_reason), "%s (#%d): %s", name, wocky_error->code, wocky_error->message); g_type_class_unref (klass); } else if (wocky_error->domain == G_IO_ERROR) { klass = g_type_class_ref (G_TYPE_IO_ERROR_ENUM); name = get_error_prefix (klass, wocky_error->code, "unknown GIOError code"); /* FIXME: is it safe to assume that every GIOError we encounter from * Wocky is a NetworkError? */ g_set_error (error, TP_ERROR, TP_ERROR_NETWORK_ERROR, "%s (#%d): %s", name, wocky_error->code, wocky_error->message); g_type_class_unref (klass); if (conn_reason != NULL) *conn_reason = TP_CONNECTION_STATUS_REASON_NETWORK_ERROR; } else if (wocky_error->domain == WOCKY_AUTH_ERROR) { klass = g_type_class_ref (WOCKY_TYPE_AUTH_ERROR); name = get_error_prefix (klass, wocky_error->code, "unknown WockyAuthError code"); g_set_error (error, TP_ERROR, map_wocky_auth_error (wocky_error, conn_reason), "%s (#%d): %s", name, wocky_error->code, wocky_error->message); g_type_class_unref (klass); } else if (wocky_error->domain == WOCKY_CONNECTOR_ERROR) { klass = g_type_class_ref (WOCKY_TYPE_CONNECTOR_ERROR); name = get_error_prefix (klass, wocky_error->code, "unknown WockyConnectorError code"); g_set_error (error, TP_ERROR, map_wocky_connector_error (wocky_error, conn_reason), "%s (#%d): %s", name, wocky_error->code, wocky_error->message); g_type_class_unref (klass); } else if (wocky_error->domain == WOCKY_XMPP_STREAM_ERROR) { klass = g_type_class_ref (WOCKY_TYPE_XMPP_STREAM_ERROR); name = get_error_prefix (klass, wocky_error->code, "unknown WockyXmppStreamError code"); g_set_error (error, TP_ERROR, map_wocky_stream_error (wocky_error, previous_status, conn_reason), "%s (#%d): %s", name, wocky_error->code, wocky_error->message); g_type_class_unref (klass); } else if (wocky_error->domain == WOCKY_TLS_CERT_ERROR) { klass = g_type_class_ref (WOCKY_TYPE_TLS_CERT_STATUS); name = get_error_prefix (klass, wocky_error->code, "unknown WockyTLSCertStatus code"); g_set_error (error, TP_ERROR, map_wocky_tls_cert_error (wocky_error, conn_reason), "%s (#%d): %s", name, wocky_error->code, wocky_error->message); g_type_class_unref (klass); } else if (wocky_error->domain == WOCKY_XMPP_CONNECTION_ERROR) { /* FIXME: there's no GEnum for WockyXmppConnectionError. */ g_set_error_literal (error, TP_ERROR, map_connection_error (wocky_error), wocky_error->message); } else { /* best we can do... */ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "%s (#%d): %s", g_quark_to_string (wocky_error->domain), wocky_error->code, wocky_error->message); } } void gabble_set_tp_error_from_wocky (const GError *wocky_error, GError **error) { gabble_set_tp_conn_error_from_wocky (wocky_error, TP_CONNECTION_STATUS_CONNECTED, NULL, error); } telepathy-gabble-0.18.3/src/im-channel.c0000664000175000017500000005240212332440117021144 0ustar00cassidycassidy00000000000000/* * gabble-im-channel.c - Source for GabbleIMChannel * Copyright (C) 2005 Collabora Ltd. * Copyright (C) 2005 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "im-channel.h" #include #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_IM #include "connection.h" #include "debug.h" #include "disco.h" #include "message-util.h" #include "namespaces.h" #include "presence.h" #include "presence-cache.h" #include "roster.h" #include "util.h" static void destroyable_iface_init (gpointer, gpointer); G_DEFINE_TYPE_WITH_CODE (GabbleIMChannel, gabble_im_channel, TP_TYPE_BASE_CHANNEL, G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_TEXT, tp_message_mixin_text_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_MESSAGES, tp_message_mixin_messages_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_CHAT_STATE, tp_message_mixin_chat_state_iface_init) G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_DESTROYABLE, destroyable_iface_init)); static void _gabble_im_channel_send_message (GObject *object, TpMessage *message, TpMessageSendingFlags flags); static void gabble_im_channel_close (TpBaseChannel *base_chan); static gboolean _gabble_im_channel_send_chat_state (GObject *object, TpChannelChatState state, GError **error); /* private structure */ typedef enum { CHAT_STATES_UNKNOWN, CHAT_STATES_SUPPORTED, CHAT_STATES_NOT_SUPPORTED } ChatStateSupport; struct _GabbleIMChannelPrivate { gchar *peer_jid; gboolean send_nick; ChatStateSupport chat_states_supported; gboolean dispose_has_run; }; typedef struct { GabbleIMChannel *channel; TpMessage *message; gchar *token; TpMessageSendingFlags flags; } _GabbleIMSendMessageCtx; static GPtrArray * gabble_im_channel_get_interfaces (TpBaseChannel *base) { GPtrArray *interfaces; interfaces = TP_BASE_CHANNEL_CLASS ( gabble_im_channel_parent_class)->get_interfaces (base); g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_CHAT_STATE); g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_MESSAGES); g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_DESTROYABLE); return interfaces; } static void gabble_im_channel_init (GabbleIMChannel *self) { GabbleIMChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_IM_CHANNEL, GabbleIMChannelPrivate); self->priv = priv; } static void gabble_im_channel_constructed (GObject *obj) { GabbleIMChannel *self = GABBLE_IM_CHANNEL (obj); TpBaseChannel *base = TP_BASE_CHANNEL (self); GabbleIMChannelPrivate *priv = self->priv; TpBaseConnection *base_conn = tp_base_channel_get_connection (base); GabbleConnection *conn = GABBLE_CONNECTION (base_conn); TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT); TpHandle target = tp_base_channel_get_target_handle (base); TpChannelTextMessageType types[] = { TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION, TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE, }; const gchar * supported_content_types[] = { "text/plain", NULL }; void (*chain_up) (GObject *) = ((GObjectClass *) gabble_im_channel_parent_class)->constructed; if (chain_up != NULL) chain_up (obj); priv->peer_jid = g_strdup (tp_handle_inspect (contact_handles, target)); if (gabble_roster_handle_gets_presence_from_us (conn->roster, target)) priv->send_nick = FALSE; else priv->send_nick = TRUE; tp_message_mixin_init (obj, G_STRUCT_OFFSET (GabbleIMChannel, message_mixin), base_conn); /* We deliberately do not include * TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_SUCCESSES here, even though we * support requesting receipts, because XEP-0184 provides no guarantees. */ tp_message_mixin_implement_sending (obj, _gabble_im_channel_send_message, G_N_ELEMENTS (types), types, 0, TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_FAILURES, supported_content_types); priv->chat_states_supported = CHAT_STATES_UNKNOWN; tp_message_mixin_implement_send_chat_state (obj, _gabble_im_channel_send_chat_state); } static void gabble_im_channel_dispose (GObject *object); static void gabble_im_channel_finalize (GObject *object); static void gabble_im_channel_fill_immutable_properties (TpBaseChannel *chan, GHashTable *properties) { TpBaseChannelClass *cls = TP_BASE_CHANNEL_CLASS ( gabble_im_channel_parent_class); cls->fill_immutable_properties (chan, properties); tp_dbus_properties_mixin_fill_properties_hash ( G_OBJECT (chan), properties, TP_IFACE_CHANNEL_INTERFACE_MESSAGES, "MessagePartSupportFlags", TP_IFACE_CHANNEL_INTERFACE_MESSAGES, "DeliveryReportingSupport", TP_IFACE_CHANNEL_INTERFACE_MESSAGES, "SupportedContentTypes", TP_IFACE_CHANNEL_INTERFACE_MESSAGES, "MessageTypes", NULL); } static gchar * gabble_im_channel_get_object_path_suffix (TpBaseChannel *chan) { return g_strdup_printf ("ImChannel%u", tp_base_channel_get_target_handle (chan)); } static void gabble_im_channel_class_init (GabbleIMChannelClass *gabble_im_channel_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_im_channel_class); TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (gabble_im_channel_class); g_type_class_add_private (gabble_im_channel_class, sizeof (GabbleIMChannelPrivate)); object_class->constructed = gabble_im_channel_constructed; object_class->dispose = gabble_im_channel_dispose; object_class->finalize = gabble_im_channel_finalize; base_class->channel_type = TP_IFACE_CHANNEL_TYPE_TEXT; base_class->get_interfaces = gabble_im_channel_get_interfaces; base_class->target_handle_type = TP_HANDLE_TYPE_CONTACT; base_class->close = gabble_im_channel_close; base_class->fill_immutable_properties = gabble_im_channel_fill_immutable_properties; base_class->get_object_path_suffix = gabble_im_channel_get_object_path_suffix; tp_message_mixin_init_dbus_properties (object_class); } static gboolean chat_states_supported (GabbleIMChannel *self, gboolean include_unknown) { GabbleIMChannelPrivate *priv = self->priv; TpBaseChannel *base = (TpBaseChannel *) self; GabbleConnection *conn = GABBLE_CONNECTION (tp_base_channel_get_connection (base)); GabblePresence *presence; presence = gabble_presence_cache_get (conn->presence_cache, tp_base_channel_get_target_handle (base)); if (presence != NULL && gabble_presence_has_cap (presence, NS_CHAT_STATES)) return TRUE; switch (priv->chat_states_supported) { case CHAT_STATES_UNKNOWN: return include_unknown; case CHAT_STATES_SUPPORTED: return TRUE; case CHAT_STATES_NOT_SUPPORTED: return FALSE; default: g_assert_not_reached (); return FALSE; } } static gboolean receipts_conceivably_supported ( GabbleIMChannel *self) { TpBaseChannel *base = (TpBaseChannel *) self; GabbleConnection *conn = GABBLE_CONNECTION (tp_base_channel_get_connection (base)); GabblePresence *presence; presence = gabble_presence_cache_get (conn->presence_cache, tp_base_channel_get_target_handle (base)); /* ...except it's never null because _parse_message_message() in * presence-cache.c. I hate this exactly as much as I did when I wrote the * FIXME on that function. */ if (presence != NULL) return gabble_presence_has_cap (presence, NS_RECEIPTS); /* Otherwise ... who knows. Why not ask for one? */ return TRUE; } static void gabble_im_channel_dispose (GObject *object) { GabbleIMChannel *self = GABBLE_IM_CHANNEL (object); TpBaseChannel *base = (TpBaseChannel *) self; GabbleIMChannelPrivate *priv = self->priv; GabbleConnection *conn = GABBLE_CONNECTION (tp_base_channel_get_connection (base)); TpHandle target = tp_base_channel_get_target_handle (base); if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; if (!gabble_roster_handle_sends_presence_to_us (conn->roster, target)) { GabblePresence *presence = gabble_presence_cache_get ( conn->presence_cache, target); if (NULL != presence) { presence->keep_unavailable = FALSE; gabble_presence_cache_maybe_remove (conn->presence_cache, target); } } tp_message_mixin_maybe_send_gone (object); if (G_OBJECT_CLASS (gabble_im_channel_parent_class)->dispose) G_OBJECT_CLASS (gabble_im_channel_parent_class)->dispose (object); } static void gabble_im_channel_finalize (GObject *object) { GabbleIMChannel *self = GABBLE_IM_CHANNEL (object); GabbleIMChannelPrivate *priv = self->priv; /* free any data held directly by the object here */ DEBUG ("%p", object); g_free (priv->peer_jid); tp_message_mixin_finalize (object); G_OBJECT_CLASS (gabble_im_channel_parent_class)->finalize (object); } static void _gabble_im_channel_message_sent_cb (GObject *source, GAsyncResult *res, gpointer user_data) { WockyPorter *porter = WOCKY_PORTER (source); GError *error = NULL; _GabbleIMSendMessageCtx *context = user_data; GabbleIMChannel *chan = context->channel; TpMessage *message = context->message; if (wocky_porter_send_finish (porter, res, &error)) { tp_message_mixin_sent ((GObject *) chan, message, context->flags, context->token, NULL); } else { tp_message_mixin_sent ((GObject *) chan, context->message, 0, NULL, error); } g_object_unref (context->channel); g_object_unref (context->message); g_free (context->token); g_slice_free (_GabbleIMSendMessageCtx, context); } static void _gabble_im_channel_send_message (GObject *object, TpMessage *message, TpMessageSendingFlags flags) { GabbleIMChannel *self = GABBLE_IM_CHANNEL (object); TpBaseChannel *base = (TpBaseChannel *) self; TpBaseConnection *base_conn; GabbleConnection *gabble_conn; GabbleIMChannelPrivate *priv; TpChannelChatState state = -1; WockyStanza *stanza = NULL; gchar *id = NULL; GError *error = NULL; WockyPorter *porter; _GabbleIMSendMessageCtx *context; g_assert (GABBLE_IS_IM_CHANNEL (self)); priv = self->priv; base_conn = tp_base_channel_get_connection (base); gabble_conn = GABBLE_CONNECTION (base_conn); if (chat_states_supported (self, TRUE)) { state = TP_CHANNEL_CHAT_STATE_ACTIVE; tp_message_mixin_change_chat_state (object, tp_base_connection_get_self_handle (base_conn), state); } stanza = gabble_message_util_build_stanza (message, gabble_conn, 0, state, priv->peer_jid, priv->send_nick, &id, &error); if (stanza != NULL) { if ((flags & TP_MESSAGE_SENDING_FLAG_REPORT_DELIVERY) && receipts_conceivably_supported (self)) { wocky_node_add_child_ns (wocky_stanza_get_top_node (stanza), "request", NS_RECEIPTS); flags = TP_MESSAGE_SENDING_FLAG_REPORT_DELIVERY; } else { flags = 0; } porter = gabble_connection_dup_porter (gabble_conn); context = g_slice_new0 (_GabbleIMSendMessageCtx); context->channel = g_object_ref (base); context->message = g_object_ref (message); context->token = id; context->flags = flags; wocky_porter_send_async (porter, stanza, NULL, _gabble_im_channel_message_sent_cb, context); g_object_unref (porter); g_object_unref (stanza); } else { tp_message_mixin_sent (object, message, 0, NULL, error); g_error_free (error); } if (priv->send_nick) priv->send_nick = FALSE; } static TpMessage * build_message ( GabbleIMChannel *self, TpChannelTextMessageType type, time_t timestamp, const char *text) { TpBaseChannel *base_chan = (TpBaseChannel *) self; TpBaseConnection *base_conn = tp_base_channel_get_connection (base_chan); TpMessage *msg = tp_cm_message_new (base_conn, 2); if (type != TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL) tp_message_set_uint32 (msg, 0, "message-type", type); if (timestamp != 0) tp_message_set_int64 (msg, 0, "message-sent", timestamp); /* Body */ tp_message_set_string (msg, 1, "content-type", "text/plain"); tp_message_set_string (msg, 1, "content", text); return msg; } static void maybe_send_delivery_report ( GabbleIMChannel *self, WockyStanza *message, const gchar *jid, const gchar *id) { TpBaseChannel *base = TP_BASE_CHANNEL (self); TpHandle target = tp_base_channel_get_target_handle (base); TpBaseConnection *base_conn = tp_base_channel_get_connection (base); GabbleConnection *conn = GABBLE_CONNECTION (base_conn); WockyStanza *report; if (id == NULL) return; if (wocky_node_get_child_ns (wocky_stanza_get_top_node (message), "request", NS_RECEIPTS) == NULL) return; if (conn->self_presence->status == GABBLE_PRESENCE_HIDDEN || !gabble_roster_handle_gets_presence_from_us (conn->roster, target)) return; report = wocky_stanza_build ( WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, jid, '(', "received", ':', NS_RECEIPTS, '@', "id", id, ')', NULL); _gabble_connection_send (conn, report, NULL); g_object_unref (report); } /* * _gabble_im_channel_receive: * @chan: a channel * @message: the stanza, from which all the following arguments were * extracted. * @type: the message type * @from: the full JID we received the message from * @timestamp: the time at which the message was sent (not the time it was * received) * @id: the id='' attribute from the stanza, if any * @text: the plaintext body of the message * @state: a #TpChannelChatState, or -1 if there was no chat state in the * message. * * Shoves an incoming message into @chan, possibly updating the chat state at * the same time. */ void _gabble_im_channel_receive (GabbleIMChannel *chan, WockyStanza *message, TpChannelTextMessageType type, const char *from, time_t timestamp, const gchar *id, const char *text, gint state) { GabbleIMChannelPrivate *priv; TpBaseChannel *base_chan; TpHandle peer; TpMessage *msg; g_assert (GABBLE_IS_IM_CHANNEL (chan)); priv = chan->priv; base_chan = (TpBaseChannel *) chan; peer = tp_base_channel_get_target_handle (base_chan); /* update peer's full JID if it's changed */ if (tp_strdiff (from, priv->peer_jid)) { g_free (priv->peer_jid); priv->peer_jid = g_strdup (from); } if (state == -1) priv->chat_states_supported = CHAT_STATES_NOT_SUPPORTED; else _gabble_im_channel_state_receive (chan, state); msg = build_message (chan, type, timestamp, text); tp_cm_message_set_sender (msg, peer); tp_message_set_int64 (msg, 0, "message-received", time (NULL)); if (id != NULL) tp_message_set_string (msg, 0, "message-token", id); tp_message_mixin_take_received (G_OBJECT (chan), msg); maybe_send_delivery_report (chan, message, from, id); } void _gabble_im_channel_report_delivery ( GabbleIMChannel *self, TpChannelTextMessageType type, time_t timestamp, const gchar *id, const char *text, TpChannelTextSendError send_error, TpDeliveryStatus delivery_status) { GabbleIMChannelPrivate *priv; TpBaseChannel *base_chan = (TpBaseChannel *) self; TpBaseConnection *base_conn; TpHandle peer; TpMessage *delivery_report; gchar *tmp; g_return_if_fail (GABBLE_IS_IM_CHANNEL (self)); priv = self->priv; peer = tp_base_channel_get_target_handle (base_chan); base_conn = tp_base_channel_get_connection (base_chan); if (send_error != GABBLE_TEXT_CHANNEL_SEND_NO_ERROR) { /* strip off the resource (if any), since we just failed to send to it */ char *slash = strchr (priv->peer_jid, '/'); if (slash != NULL) *slash = '\0'; priv->chat_states_supported = CHAT_STATES_UNKNOWN; } delivery_report = tp_cm_message_new (base_conn, 1); tp_message_set_uint32 (delivery_report, 0, "message-type", TP_CHANNEL_TEXT_MESSAGE_TYPE_DELIVERY_REPORT); tp_cm_message_set_sender (delivery_report, peer); tp_message_set_int64 (delivery_report, 0, "message-received", time (NULL)); tmp = gabble_generate_id (); tp_message_set_string (delivery_report, 0, "message-token", tmp); g_free (tmp); tp_message_set_uint32 (delivery_report, 0, "delivery-status", delivery_status); tp_message_set_uint32 (delivery_report, 0, "delivery-error", send_error); if (id != NULL) tp_message_set_string (delivery_report, 0, "delivery-token", id); if (text != NULL) { TpMessage *msg = build_message (self, type, timestamp, text); /* This is a delivery report, so the original sender of the echoed message * must be us! */ tp_cm_message_set_sender (msg, tp_base_connection_get_self_handle (base_conn)); /* Since this is a delivery report, we can trust the id on the message. */ if (id != NULL) tp_message_set_string (msg, 0, "message-token", id); tp_cm_message_take_message (delivery_report, 0, "delivery-echo", msg); } tp_message_mixin_take_received (G_OBJECT (self), delivery_report); } /** * _gabble_im_channel_state_receive * * Send the D-BUS signal ChatStateChanged * on org.freedesktop.Telepathy.Channel.Interface.ChatState */ void _gabble_im_channel_state_receive (GabbleIMChannel *chan, TpChannelChatState state) { GabbleIMChannelPrivate *priv; TpBaseChannel *base_chan; g_assert (GABBLE_IS_IM_CHANNEL (chan)); base_chan = (TpBaseChannel *) chan; priv = chan->priv; priv->chat_states_supported = CHAT_STATES_SUPPORTED; tp_message_mixin_change_chat_state ((GObject *) chan, tp_base_channel_get_target_handle (base_chan), state); } void gabble_im_channel_receive_receipt ( GabbleIMChannel *self, const gchar *receipt_id) { _gabble_im_channel_report_delivery (self, TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, 0, receipt_id, NULL, GABBLE_TEXT_CHANNEL_SEND_NO_ERROR, TP_DELIVERY_STATUS_DELIVERED); } static void gabble_im_channel_close (TpBaseChannel *base_chan) { GabbleIMChannel *self = GABBLE_IM_CHANNEL (base_chan); tp_message_mixin_maybe_send_gone ((GObject *) self); /* The IM factory will resurrect the channel if we have pending * messages. When we're resurrected, we want the initiator * to be the contact who sent us those messages, if it isn't already */ if (tp_message_mixin_has_pending_messages ((GObject *) self, NULL)) { DEBUG ("Not really closing, I still have pending messages"); tp_message_mixin_set_rescued ((GObject *) self); tp_base_channel_reopened (base_chan, tp_base_channel_get_target_handle (base_chan)); } else { DEBUG ("Actually closing, I have no pending messages"); tp_base_channel_destroyed (base_chan); } } /** * gabble_im_channel_destroy * * Implements D-Bus method Destroy * on interface org.freedesktop.Telepathy.Channel.Interface.Destroyable */ static void gabble_im_channel_destroy (TpSvcChannelInterfaceDestroyable *iface, DBusGMethodInvocation *context) { g_assert (GABBLE_IS_IM_CHANNEL (iface)); DEBUG ("called on %p, clearing pending messages", iface); tp_message_mixin_clear ((GObject *) iface); gabble_im_channel_close (TP_BASE_CHANNEL (iface)); tp_svc_channel_interface_destroyable_return_from_destroy (context); } static gboolean _gabble_im_channel_send_chat_state (GObject *object, TpChannelChatState state, GError **error) { GabbleIMChannel *self = GABBLE_IM_CHANNEL (object); GabbleIMChannelPrivate *priv = self->priv; TpBaseChannel *base = (TpBaseChannel *) self; TpBaseConnection *base_conn = tp_base_channel_get_connection (base); /* Only send anything to the peer if we actually know they support chat * states. */ if (!chat_states_supported (self, FALSE)) return TRUE; return gabble_message_util_send_chat_state (G_OBJECT (self), GABBLE_CONNECTION (base_conn), WOCKY_STANZA_SUB_TYPE_CHAT, state, priv->peer_jid, error); } static void destroyable_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcChannelInterfaceDestroyableClass *klass = g_iface; #define IMPLEMENT(x) tp_svc_channel_interface_destroyable_implement_##x (\ klass, gabble_im_channel_##x) IMPLEMENT(destroy); #undef IMPLEMENT } telepathy-gabble-0.18.3/src/gtalk-file-collection.c0000664000175000017500000015325412223562023023310 0ustar00cassidycassidy00000000000000/* * gtalk-file-collection.c - Source for GTalkFileCollection * * Copyright (C) 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "gtalk-file-collection.h" #include #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_SHARE #include "debug.h" #include "jingle-share.h" #include "namespaces.h" #include "util.h" #include /* * This GTalk compatible file transfer protocol is a bit complicated, so here * is an explanation on how it works : * * A pseudo-good initial source of information is available here : * http://code.google.com/apis/talk/libjingle/file_share.html * * The current object interaction is like this : * * GabbleFileTransferChannelManager * | * | * | * | * * ref * GabbleFileTransferChannel * weakref * * * / \ * / \ * / \ * / \ * / \ * / \ * / \ * ref / \ * GTalkFileCollection \ * | \ * | \ * ref | \ * WockyJingleSession \ * | \ (one at a time) * | \ * ref | \ * GabbleJingleShare ------------------*- ShareChannel -------- NiceAgent * | | * | | * ref | ref | * GabbleTransportGoogle ----------------*- WockyJingleCandidate PseudoTCP * * The protocol works like this : * Once you receive an invitation, the manifest will contain a number of files * and folders. Some files might have image attributes (width/height) that help * specify that they are images. * If there are images in the invitation, a new ShareChannel gets created and * connectivity must be established. Then on that stream, an HTTP GET request * is sent for each image being transfered with the URL as : * GET /filename?width=X&height=Y * where X and Y are the thumbnail's requested width and height. * The peer should at this point scale down the image to the requested width and * height and send the thumbnail for showing the preview of the image in the FT * UI. * Once the invitation is accepted, a new ShareChannel is created, which will * cause a new NiceAgent to be created and connectivity to be established on that * ShareChannel. The resulting stream is then used as an HTTP server/client to * request files on it using the as prefix to the URL. * Simple files are being transferred normally, while directories will be * transferred as a tarball with 'chuncked' Transfer-Encoding since the resulting * size of the tarball isn't known in advance. * Once a file is completely transferred, then the next file is requested on the * same ShareChannel. If all files are transferred, then the info * action is being sent through the jingle signaling, and the session can then * be terminated safely. * * Since telepathy doesn't currently support image previews, so the 'preview' * ShareChannel is never created with gabble. * Also note that we only create one ShareChannel and we serialize the file * transfers one after the other, they do not each get one ShareChannel and they * cannot be downloaded in parallel. * */ static gboolean test_mode = FALSE; void gtalk_file_collection_set_test_mode (void) { test_mode = TRUE; } G_DEFINE_TYPE (GTalkFileCollection, gtalk_file_collection, G_TYPE_OBJECT); /* properties */ enum { PROP_TOKEN = 1, LAST_PROPERTY }; typedef enum { HTTP_SERVER_IDLE, HTTP_SERVER_HEADERS, HTTP_SERVER_SEND, HTTP_CLIENT_IDLE, HTTP_CLIENT_RECEIVE, HTTP_CLIENT_HEADERS, HTTP_CLIENT_CHUNK_SIZE, HTTP_CLIENT_CHUNK_END, HTTP_CLIENT_CHUNK_FINAL, HTTP_CLIENT_BODY, } HttpStatus; typedef struct { NiceAgent *agent; guint stream_id; guint component_id; gboolean agent_attached; GabbleJingleShare *content; guint share_channel_id; HttpStatus http_status; gchar *status_line; gboolean is_chunked; guint64 content_length; gchar *write_buffer; guint write_len; gchar *read_buffer; guint read_len; } ShareChannel; typedef enum { GTALK_FT_STATUS_PENDING, GTALK_FT_STATUS_INITIATED, GTALK_FT_STATUS_ACCEPTED, GTALK_FT_STATUS_TRANSFERRING, GTALK_FT_STATUS_WAITING, GTALK_FT_STATUS_TERMINATED } GtalkFtStatus; struct _GTalkFileCollectionPrivate { gboolean dispose_has_run; GtalkFtStatus status; /* GList of weakreffed GabbleFileTransferChannel */ GList *channels; /* GHashTable of GabbleFileTransferChannel => GINT_TO_POINTER (gboolean) */ /* the weakref to the channel here is held through the GList *channels */ GHashTable *channels_reading; /* GHashTable of GabbleFileTransferChannel => GINT_TO_POINTER (gboolean) */ /* the weakref to the channel here is held through the GList *channels */ GHashTable *channels_usable; GabbleFileTransferChannel *current_channel; WockyJingleFactory *jingle_factory; WockyJingleSession *jingle; /* ICE component id to jingle share channel association GINT_TO_POINTER (candidate->component) => g_slice_new (ShareChannel) */ GHashTable *share_channels; gboolean requested; gchar *token; }; static void free_share_channel (gpointer data); static void nice_data_received_cb (NiceAgent *agent, guint stream_id, guint component_id, guint len, gchar *buffer, gpointer user_data); static void set_current_channel (GTalkFileCollection *self, GabbleFileTransferChannel *channel); static void channel_disposed (gpointer data, GObject *where_the_object_was); static void gtalk_file_collection_init (GTalkFileCollection *self) { GTalkFileCollectionPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTALK_TYPE_FILE_COLLECTION, GTalkFileCollectionPrivate); gchar buf[16]; guint32 *uint_buf = (guint32 *) buf; guint i; DEBUG ("GTalk file collection init called"); self->priv = priv; self->priv->status = GTALK_FT_STATUS_PENDING; self->priv->channels_reading = g_hash_table_new_full (NULL, NULL, NULL, NULL); self->priv->channels_usable = g_hash_table_new_full (NULL, NULL, NULL, NULL); self->priv->share_channels = g_hash_table_new_full (NULL, NULL, NULL, free_share_channel); for (i = 0; i < sizeof (buf); i++) buf[i] = g_random_int_range (0, 256); self->priv->token = g_strdup_printf ("%x%x%x%x", uint_buf[0], uint_buf[1], uint_buf[2], uint_buf[3]); /* FIXME: we should start creating a nice agent already and have it start the candidate gathering.. but we don't know which jingle-share transport channel name to assign it to... */ priv->dispose_has_run = FALSE; } static void gtalk_file_collection_dispose (GObject *object) { GTalkFileCollection *self = GTALK_FILE_COLLECTION (object); GList *i; if (self->priv->dispose_has_run) return; DEBUG ("dispose called"); self->priv->dispose_has_run = TRUE; if (self->priv->jingle != NULL) wocky_jingle_session_terminate (self->priv->jingle, WOCKY_JINGLE_REASON_UNKNOWN, NULL, NULL); tp_clear_object (&self->priv->jingle); set_current_channel (self, NULL); tp_clear_pointer (&self->priv->channels_reading, g_hash_table_unref); tp_clear_pointer (&self->priv->channels_usable, g_hash_table_unref); tp_clear_pointer (&self->priv->share_channels, g_hash_table_unref); for (i = self->priv->channels; i; i = i->next) { GabbleFileTransferChannel *channel = i->data; g_object_weak_unref (G_OBJECT (channel), channel_disposed, self); } g_list_free (self->priv->channels); g_free (self->priv->token); if (G_OBJECT_CLASS (gtalk_file_collection_parent_class)->dispose) G_OBJECT_CLASS (gtalk_file_collection_parent_class)->dispose (object); } static void gtalk_file_collection_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GTalkFileCollection *self = GTALK_FILE_COLLECTION (object); switch (property_id) { case PROP_TOKEN: g_value_set_string (value, self->priv->token); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gtalk_file_collection_class_init (GTalkFileCollectionClass *cls) { GObjectClass *object_class = G_OBJECT_CLASS (cls); g_type_class_add_private (cls, sizeof (GTalkFileCollectionPrivate)); object_class->get_property = gtalk_file_collection_get_property; object_class->dispose = gtalk_file_collection_dispose; g_object_class_install_property (object_class, PROP_TOKEN, g_param_spec_string ( "token", "Unique token identifiying the FileCollection", "Token identifying a collection of files", "", G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); } static ShareChannel * get_share_channel (GTalkFileCollection *self, NiceAgent *agent) { GHashTableIter iter; gpointer key, value; ShareChannel *ret = NULL; g_hash_table_iter_init (&iter, self->priv->share_channels); while (g_hash_table_iter_next (&iter, &key, &value)) { ShareChannel *share_channel = (ShareChannel *) value; if (share_channel->agent == agent) { ret = share_channel; break; } } return ret; } static GabbleFileTransferChannel * get_channel_by_filename (GTalkFileCollection *self, gchar *filename) { GList *i; for (i = self->priv->channels; i; i = i->next) { GabbleFileTransferChannel *channel = i->data; gchar *file = NULL; g_object_get (channel, "filename", &file, NULL); if (strcmp (file, filename) == 0) return channel; } return NULL; } static void set_current_channel (GTalkFileCollection *self, GabbleFileTransferChannel *channel) { self->priv->current_channel = channel; if (channel != NULL) { gboolean reading = FALSE; gabble_file_transfer_channel_gtalk_file_collection_state_changed ( channel, GTALK_FILE_COLLECTION_STATE_OPEN, FALSE); reading = GPOINTER_TO_INT (g_hash_table_lookup ( self->priv->channels_reading, channel)); gtalk_file_collection_block_reading (self, channel, !reading); } } static gboolean channel_exists (GTalkFileCollection * self, GabbleFileTransferChannel *channel) { GList *i; for (i = self->priv->channels; i; i = i->next) { if (channel == i->data) return TRUE; } return FALSE; } static void add_channel (GTalkFileCollection * self, GabbleFileTransferChannel *channel) { self->priv->channels = g_list_append (self->priv->channels, channel); g_hash_table_replace (self->priv->channels_reading, channel, GINT_TO_POINTER (FALSE)); g_object_weak_ref (G_OBJECT (channel), channel_disposed, self); } static void del_channel (GTalkFileCollection * self, GabbleFileTransferChannel *channel) { g_return_if_fail (channel_exists (self, channel)); self->priv->channels = g_list_remove (self->priv->channels, channel); g_hash_table_remove (self->priv->channels_reading, channel); g_hash_table_remove (self->priv->channels_usable, channel); g_object_weak_unref (G_OBJECT (channel), channel_disposed, self); if (self->priv->current_channel == channel) set_current_channel (self, NULL); } static void jingle_session_state_changed_cb (WockyJingleSession *session, GParamSpec *arg1, GTalkFileCollection *self) { WockyJingleState state; GList *i; DEBUG ("called"); g_object_get (session, "state", &state, NULL); switch (state) { case WOCKY_JINGLE_STATE_INVALID: case WOCKY_JINGLE_STATE_PENDING_CREATED: break; case WOCKY_JINGLE_STATE_PENDING_INITIATE_SENT: case WOCKY_JINGLE_STATE_PENDING_INITIATED: for (i = self->priv->channels; i;) { GabbleFileTransferChannel *channel = i->data; i = i->next; gabble_file_transfer_channel_gtalk_file_collection_state_changed ( channel, GTALK_FILE_COLLECTION_STATE_PENDING, FALSE); } break; case WOCKY_JINGLE_STATE_PENDING_ACCEPT_SENT: case WOCKY_JINGLE_STATE_ACTIVE: /* Do not set the channels to OPEN unless we're ready to send/receive data from them */ if (self->priv->status == GTALK_FT_STATUS_INITIATED) self->priv->status = GTALK_FT_STATUS_ACCEPTED; for (i = self->priv->channels; i;) { GabbleFileTransferChannel *channel = i->data; gboolean usable; i = i->next; usable = GPOINTER_TO_INT (g_hash_table_lookup ( self->priv->channels_usable, channel)); if (usable) gabble_file_transfer_channel_gtalk_file_collection_state_changed ( channel, GTALK_FILE_COLLECTION_STATE_ACCEPTED, FALSE); } break; case WOCKY_JINGLE_STATE_ENDED: /* Do nothing, let the terminated signal set the correct state depending on the termination reason */ default: break; } } static void jingle_session_terminated_cb (WockyJingleSession *session, gboolean local_terminator, WockyJingleReason reason, const gchar *text, gpointer user_data) { GTalkFileCollection *self = GTALK_FILE_COLLECTION (user_data); GList *i; g_assert (session == self->priv->jingle); self->priv->status = GTALK_FT_STATUS_TERMINATED; for (i = self->priv->channels; i;) { GabbleFileTransferChannel *channel = i->data; i = i->next; gabble_file_transfer_channel_gtalk_file_collection_state_changed ( channel, GTALK_FILE_COLLECTION_STATE_TERMINATED, local_terminator); } } static void content_new_remote_candidates_cb (WockyJingleContent *content, GList *clist, gpointer user_data) { GTalkFileCollection *self = GTALK_FILE_COLLECTION (user_data); GList *li; DEBUG ("Got new remote candidates : %d", g_list_length (clist)); for (li = clist; li; li = li->next) { WockyJingleCandidate *candidate = li->data; NiceCandidate *cand = NULL; ShareChannel *share_channel = NULL; GSList *candidates = NULL; if (candidate->protocol != WOCKY_JINGLE_TRANSPORT_PROTOCOL_UDP) { DEBUG ("Ignoring candidate %s because of non-UDP protocol : %d", candidate->username, candidate->protocol); continue; } share_channel = g_hash_table_lookup (self->priv->share_channels, GINT_TO_POINTER (candidate->component)); if (share_channel == NULL) { DEBUG ("Ignoring candidate %s because of unknown component id %d", candidate->id, candidate->component); continue; } cand = nice_candidate_new ( candidate->type == WOCKY_JINGLE_CANDIDATE_TYPE_LOCAL? NICE_CANDIDATE_TYPE_HOST: candidate->type == WOCKY_JINGLE_CANDIDATE_TYPE_STUN? NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE: NICE_CANDIDATE_TYPE_RELAYED); cand->transport = WOCKY_JINGLE_TRANSPORT_PROTOCOL_UDP; nice_address_init (&cand->addr); if (!nice_address_set_from_string (&cand->addr, candidate->address)) { DEBUG ("invalid address '%s' in candidate, skipping", candidate->address ? candidate->address : ""); nice_candidate_free (cand); continue; } nice_address_set_port (&cand->addr, candidate->port); cand->priority = candidate->preference * 1000; cand->stream_id = share_channel->stream_id; cand->component_id = share_channel->component_id; /* if (c->id == NULL) candidate_id = g_strdup_printf ("R%d", ++priv->remote_candidate_count); else candidate_id = c->id;*/ if (candidate->id != NULL) strncpy (cand->foundation, candidate->id, NICE_CANDIDATE_MAX_FOUNDATION - 1); else if (candidate->username != NULL) strncpy (cand->foundation, candidate->username, NICE_CANDIDATE_MAX_FOUNDATION - 1); cand->username = g_strdup (candidate->username?candidate->username:""); cand->password = g_strdup (candidate->password?candidate->password:""); candidates = g_slist_append (candidates, cand); nice_agent_set_remote_candidates (share_channel->agent, share_channel->stream_id, share_channel->component_id, candidates); g_slist_foreach (candidates, (GFunc)nice_candidate_free, NULL); g_slist_free (candidates); } } static void nice_candidate_gathering_done (NiceAgent *agent, guint stream_id, gpointer user_data) { GTalkFileCollection *self = GTALK_FILE_COLLECTION (user_data); ShareChannel *share_channel = get_share_channel (self, agent); WockyJingleContent *content = WOCKY_JINGLE_CONTENT (share_channel->content); GList *candidates = NULL; GList *remote_candidates = NULL; GSList *local_candidates; GSList *li; DEBUG ("libnice candidate gathering done!!!!"); /* Send remote candidates to libnice and listen to new signal */ remote_candidates = wocky_jingle_content_get_remote_candidates (content); content_new_remote_candidates_cb (content, remote_candidates, self); gabble_signal_connect_weak (content, "new-candidates", (GCallback) content_new_remote_candidates_cb, G_OBJECT (self)); /* Send gathered local candidates to the content */ local_candidates = nice_agent_get_local_candidates (agent, stream_id, share_channel->component_id); for (li = local_candidates; li; li = li->next) { NiceCandidate *cand = li->data; WockyJingleCandidate *candidate; gchar ip[NICE_ADDRESS_STRING_LEN]; nice_address_to_string (&cand->addr, ip); candidate = wocky_jingle_candidate_new ( /* protocol */ cand->transport == NICE_CANDIDATE_TRANSPORT_UDP? WOCKY_JINGLE_TRANSPORT_PROTOCOL_UDP: WOCKY_JINGLE_TRANSPORT_PROTOCOL_TCP, /* candidate type */ cand->type == NICE_CANDIDATE_TYPE_HOST? WOCKY_JINGLE_CANDIDATE_TYPE_LOCAL: cand->type == NICE_CANDIDATE_TYPE_RELAYED? WOCKY_JINGLE_CANDIDATE_TYPE_RELAY: WOCKY_JINGLE_CANDIDATE_TYPE_STUN, /* id */ cand->foundation, /* component */ share_channel->share_channel_id, /* address */ ip, /* port */ nice_address_get_port (&cand->addr), /* generation */ 0, /* preference */ (gfloat) cand->priority / 1000.0, /* username */ cand->username?cand->username:"", /* password */ cand->password?cand->password:"", /* network */ 0); candidates = g_list_prepend (candidates, candidate); } wocky_jingle_content_add_candidates (content, candidates); } static void nice_component_state_changed (NiceAgent *agent, guint stream_id, guint component_id, guint state, gpointer user_data) { GTalkFileCollection *self = GTALK_FILE_COLLECTION (user_data); ShareChannel *share_channel = get_share_channel (self, agent); WockyJingleContent *content = WOCKY_JINGLE_CONTENT (share_channel->content); WockyJingleTransportState ts = WOCKY_JINGLE_TRANSPORT_STATE_DISCONNECTED; DEBUG ("libnice component state changed %d!!!!", state); switch (state) { case NICE_COMPONENT_STATE_DISCONNECTED: case NICE_COMPONENT_STATE_GATHERING: ts = WOCKY_JINGLE_TRANSPORT_STATE_DISCONNECTED; break; case NICE_COMPONENT_STATE_CONNECTING: ts = WOCKY_JINGLE_TRANSPORT_STATE_CONNECTING; break; case NICE_COMPONENT_STATE_CONNECTED: case NICE_COMPONENT_STATE_READY: ts = WOCKY_JINGLE_TRANSPORT_STATE_CONNECTED; break; case NICE_COMPONENT_STATE_FAILED: { GList *i; for (i = self->priv->channels; i;) { GabbleFileTransferChannel *channel = i->data; i = i->next; gabble_file_transfer_channel_gtalk_file_collection_state_changed ( channel, GTALK_FILE_COLLECTION_STATE_CONNECTION_FAILED, TRUE); } /* return because we don't want to use the content after it has been destroyed.. */ return; } } wocky_jingle_content_set_transport_state (content, ts); } static void get_next_manifest_entry (GTalkFileCollection *self, ShareChannel *share_channel, gboolean error) { GabbleJingleShareManifest *manifest = NULL; GabbleJingleShareManifestEntry *entry = NULL; GabbleFileTransferChannel *channel = NULL; GList *i; DEBUG ("called"); if (self->priv->current_channel != NULL) { if (g_list_length (self->priv->channels) == 1) { WockyJingleContent *content = \ WOCKY_JINGLE_CONTENT (share_channel->content); DEBUG ("Received all the files. Transfer is complete"); wocky_jingle_content_send_complete (content); } g_hash_table_replace (self->priv->channels_usable, self->priv->current_channel, GINT_TO_POINTER (FALSE)); gabble_file_transfer_channel_gtalk_file_collection_state_changed ( self->priv->current_channel, error ? GTALK_FILE_COLLECTION_STATE_ERROR: GTALK_FILE_COLLECTION_STATE_COMPLETED, FALSE); set_current_channel (self, NULL); } manifest = gabble_jingle_share_get_manifest (share_channel->content); for (i = manifest->entries; i; i = i->next) { gchar *filename = NULL; gboolean usable; entry = i->data; filename = g_strdup_printf ("%s%s", entry->name, (entry->folder ? ".tar" : "")); channel = get_channel_by_filename (self, filename); g_free (filename); if (channel != NULL) { usable = GPOINTER_TO_INT (g_hash_table_lookup ( self->priv->channels_usable, channel)); if (usable) break; } entry = NULL; } self->priv->status = GTALK_FT_STATUS_WAITING; if (entry != NULL) { gchar *buffer = NULL; gchar *source_url = manifest->source_url; guint url_len = (source_url != NULL? strlen (source_url) : 0); gchar *separator = ""; gchar *filename = NULL; if (source_url != NULL && source_url[url_len -1] != '/') separator = "/"; self->priv->status = GTALK_FT_STATUS_TRANSFERRING; filename = g_uri_escape_string (entry->name, NULL, TRUE); /* The session initiator will always be the full JID of the peer */ buffer = g_strdup_printf ("GET %s%s%s HTTP/1.1\r\n" "Connection: Keep-Alive\r\n" "Content-Length: 0\r\n" "Host: %s:0\r\n" /* e.g. alice@example.com/Empathy:0 */ "User-Agent: %s\r\n\r\n", (source_url != NULL ? source_url : ""), separator, filename, wocky_jingle_session_get_initiator (self->priv->jingle), PACKAGE_STRING); g_free (filename); /* FIXME: check for success */ nice_agent_send (share_channel->agent, share_channel->stream_id, share_channel->component_id, strlen (buffer), buffer); g_free (buffer); share_channel->http_status = HTTP_CLIENT_RECEIVE; /* Block or unblock accordingly */ set_current_channel (self, channel); } } static void nice_component_writable (NiceAgent *agent, guint stream_id, guint component_id, gpointer user_data) { GTalkFileCollection *self = GTALK_FILE_COLLECTION (user_data); ShareChannel *share_channel = get_share_channel (self, agent); if (share_channel->http_status == HTTP_CLIENT_IDLE) { get_next_manifest_entry (self, share_channel, FALSE); } else if (share_channel->http_status == HTTP_SERVER_SEND) { if (self->priv->current_channel == NULL) { GList *i; DEBUG ("Unexpected current_channel == NULL!"); for (i = self->priv->channels; i;) { GabbleFileTransferChannel *channel = i->data; i = i->next; gabble_file_transfer_channel_gtalk_file_collection_state_changed ( channel, GTALK_FILE_COLLECTION_STATE_ERROR, FALSE); } return; } gabble_file_transfer_channel_gtalk_file_collection_write_blocked ( self->priv->current_channel, FALSE); if (share_channel->write_buffer != NULL) { gint ret = nice_agent_send (agent, stream_id, component_id, share_channel->write_len, share_channel->write_buffer); if (ret < 0 || (guint) ret < share_channel->write_len) { gchar *to_free = share_channel->write_buffer; if (ret < 0) ret = 0; share_channel->write_buffer = g_memdup ( share_channel->write_buffer + ret, share_channel->write_len - ret); share_channel->write_len = share_channel->write_len - ret; g_free (to_free); gabble_file_transfer_channel_gtalk_file_collection_write_blocked ( self->priv->current_channel, TRUE); } else { g_free (share_channel->write_buffer); share_channel->write_buffer = NULL; share_channel->write_len = 0; } } } } typedef struct { union { gpointer ptr; GTalkFileCollection *self; } u; ShareChannel *share_channel; } GoogleRelaySessionData; static const NiceRelayType relay_type_map[] = { /* WOCKY_JINGLE_RELAY_TYPE_UDP */ NICE_RELAY_TYPE_TURN_UDP, /* WOCKY_JINGLE_RELAY_TYPE_TCP */ NICE_RELAY_TYPE_TURN_TCP, /* WOCKY_JINGLE_RELAY_TYPE_TLS */ NICE_RELAY_TYPE_TURN_TLS, }; static void set_relay_info (gpointer item, gpointer user_data) { GoogleRelaySessionData *data = user_data; WockyJingleRelay *relay = item; NiceRelayType type; g_return_if_fail (relay->type < WOCKY_N_JINGLE_RELAY_TYPES); type = relay_type_map[relay->type]; nice_agent_set_relay_info (data->share_channel->agent, data->share_channel->stream_id, data->share_channel->component_id, relay->ip, relay->port, relay->username, relay->password, type); } static void google_relay_session_cb (GPtrArray *relays, gpointer user_data) { GoogleRelaySessionData *data = user_data; if (data->u.self == NULL) { DEBUG ("Received relay session callback but self got destroyed"); g_slice_free (GoogleRelaySessionData, data); return; } if (relays != NULL) g_ptr_array_foreach (relays, set_relay_info, user_data); nice_agent_gather_candidates (data->share_channel->agent, data->share_channel->stream_id); g_object_remove_weak_pointer (G_OBJECT (data->u.self), &data->u.ptr); g_slice_free (GoogleRelaySessionData, data); } static void content_new_share_channel_cb (WockyJingleContent *content, const gchar *name, guint share_channel_id, gpointer user_data) { GTalkFileCollection *self = GTALK_FILE_COLLECTION (user_data); ShareChannel *share_channel = g_slice_new0 (ShareChannel); NiceAgent *agent = nice_agent_new_reliable (g_main_context_default (), NICE_COMPATIBILITY_GOOGLE); guint stream_id = nice_agent_add_stream (agent, 1); GList *stun_servers; GoogleRelaySessionData *relay_data = NULL; DEBUG ("New Share channel %s was created and linked to id %d", name, share_channel_id); if (test_mode) g_object_set (agent, "upnp", FALSE, NULL); share_channel->agent = agent; share_channel->stream_id = stream_id; share_channel->component_id = NICE_COMPONENT_TYPE_RTP; share_channel->content = GABBLE_JINGLE_SHARE (content); share_channel->share_channel_id = share_channel_id; if (self->priv->requested) share_channel->http_status = HTTP_SERVER_IDLE; else share_channel->http_status = HTTP_CLIENT_IDLE; gabble_signal_connect_weak (agent, "candidate-gathering-done", G_CALLBACK (nice_candidate_gathering_done), G_OBJECT (self)); gabble_signal_connect_weak (agent, "component-state-changed", G_CALLBACK (nice_component_state_changed), G_OBJECT (self)); gabble_signal_connect_weak (agent, "reliable-transport-writable", G_CALLBACK (nice_component_writable), G_OBJECT (self)); /* Add the agent to the hash table before gathering candidates in case the gathering finishes synchronously, and the callback tries to add local candidates to the content, it needs to find the share channel id.. */ g_hash_table_insert (self->priv->share_channels, GINT_TO_POINTER (share_channel_id), share_channel); share_channel->agent_attached = TRUE; nice_agent_attach_recv (agent, stream_id, share_channel->component_id, g_main_context_default (), nice_data_received_cb, self); stun_servers = wocky_jingle_info_get_stun_servers ( wocky_jingle_factory_get_jingle_info (self->priv->jingle_factory)); if (stun_servers != NULL) { WockyStunServer *stun_server = stun_servers->data; g_object_set (agent, "stun-server", stun_server->address, "stun-server-port", (guint) stun_server->port, NULL); g_list_free (stun_servers); } relay_data = g_slice_new0 (GoogleRelaySessionData); relay_data->u.self = self; relay_data->share_channel = share_channel; g_object_add_weak_pointer (G_OBJECT (relay_data->u.self), &relay_data->u.ptr); wocky_jingle_info_create_google_relay_session ( wocky_jingle_factory_get_jingle_info (self->priv->jingle_factory), 1, google_relay_session_cb, relay_data); } static void content_completed (WockyJingleContent *content, gpointer user_data) { GTalkFileCollection *self = GTALK_FILE_COLLECTION (user_data); GList *i; DEBUG ("Received content completed"); for (i = self->priv->channels; i;) { GabbleFileTransferChannel *channel = i->data; i = i->next; gabble_file_transfer_channel_gtalk_file_collection_state_changed ( channel, GTALK_FILE_COLLECTION_STATE_COMPLETED, FALSE); } } static void free_share_channel (gpointer data) { ShareChannel *share_channel = (ShareChannel *) data; DEBUG ("Freeing jingle Share channel"); tp_clear_pointer (&share_channel->write_buffer, g_free); tp_clear_pointer (&share_channel->read_buffer, g_free); g_object_unref (share_channel->agent); g_slice_free (ShareChannel, share_channel); } /* If buffer contains a line ending, 0-terminate the first line and * return a pointer to the beginning of the next line. Otherwise * return NULL. */ static gchar * http_read_line (gchar *buffer, guint len) { gchar *p = memchr (buffer, '\n', len); if (p != NULL) { *p = 0; if (p > buffer && *(p-1) == '\r') *(p-1) = '\0'; p++; } return p; } static guint http_data_received (GTalkFileCollection *self, ShareChannel *share_channel, gchar *buffer, guint len) { switch (share_channel->http_status) { case HTTP_SERVER_IDLE: { gchar *headers = http_read_line (buffer, len); if (headers == NULL) return 0; share_channel->http_status = HTTP_SERVER_HEADERS; share_channel->status_line = g_strdup (buffer); if (self->priv->current_channel != NULL) { DEBUG ("Received status line with current channel set"); gabble_file_transfer_channel_gtalk_file_collection_state_changed ( self->priv->current_channel, GTALK_FILE_COLLECTION_STATE_COMPLETED, FALSE); set_current_channel (self, NULL); } return headers - buffer; } break; case HTTP_SERVER_HEADERS: { gchar *line = buffer; gchar *next_line = http_read_line (buffer, len); if (next_line == NULL) return 0; DEBUG ("Found server headers line (%" G_GSIZE_FORMAT ") : %s", strlen (line), line); /* FIXME: how about content-length and an actual body ? */ if (line[0] == '\0') { gchar *response = NULL; gchar *get_line = NULL; GabbleJingleShareManifest *manifest = NULL; gchar *source_url = NULL; guint url_len; gchar *separator = ""; gchar *filename = NULL; GabbleFileTransferChannel *channel = NULL; g_assert (self->priv->current_channel == NULL); DEBUG ("Found empty line, received request : %s ", share_channel->status_line); manifest = gabble_jingle_share_get_manifest ( share_channel->content); source_url = manifest->source_url; url_len = (source_url != NULL? strlen (source_url) : 0); if (source_url != NULL && source_url[url_len -1] != '/') separator = "/"; get_line = g_strdup_printf ("GET %s%s%%s HTTP/1.1", (source_url != NULL ? source_url : ""), separator); filename = g_malloc (strlen (share_channel->status_line)); if (sscanf (share_channel->status_line, get_line, filename) == 1) { gchar *unescaped = g_uri_unescape_string (filename, NULL); g_free (filename); filename = unescaped; channel = get_channel_by_filename (self, filename); } if (channel != NULL) { guint64 size; g_object_get (channel, "size", &size, NULL); DEBUG ("Found valid filename, result : 200"); share_channel->http_status = HTTP_SERVER_SEND; response = g_strdup_printf ("HTTP/1.1 200\r\n" "Connection: Keep-Alive\r\n" "Content-Length: %" G_GUINT64_FORMAT "\r\n" "Content-Type: application/octet-stream\r\n\r\n", size); } else { DEBUG ("Unable to find valid filename (%s), result : 404", (filename != NULL? filename : "")); share_channel->http_status = HTTP_SERVER_IDLE; response = g_strdup_printf ("HTTP/1.1 404\r\n" "Connection: Keep-Alive\r\n" "Content-Length: 0\r\n\r\n"); } /* FIXME: check for success of nice_agent_send */ nice_agent_send (share_channel->agent, share_channel->stream_id, share_channel->component_id, strlen (response), response); g_free (response); g_free (filename); g_free (get_line); /* Now that we sent our response, we can assign the current channel which sets it to OPEN (if non NULL) so data can start flowing */ self->priv->status = GTALK_FT_STATUS_TRANSFERRING; set_current_channel (self, channel); } return next_line - buffer; } break; case HTTP_SERVER_SEND: DEBUG ("received data when we're supposed to be sending data.. " "not supposed to happen"); break; case HTTP_CLIENT_IDLE: DEBUG ("received data when we're supposed to be sending the GET.. " "not supposed to happen"); break; case HTTP_CLIENT_RECEIVE: { gchar *headers = http_read_line (buffer, len); if (headers == NULL) return 0; share_channel->http_status = HTTP_CLIENT_HEADERS; share_channel->status_line = g_strdup (buffer); return headers - buffer; } case HTTP_CLIENT_HEADERS: { gchar *line = buffer; gchar *next_line = http_read_line (buffer, len); if (next_line == NULL) return 0; DEBUG ("Found client headers line (%" G_GSIZE_FORMAT ") : %s", strlen (line), line); if (line[0] == '\0') { DEBUG ("Found empty line, GET response : %s", share_channel->status_line); if (g_str_has_prefix (share_channel->status_line, "HTTP/1.1 200")) { if (share_channel->is_chunked) { share_channel->http_status = HTTP_CLIENT_CHUNK_SIZE; } else { share_channel->http_status = HTTP_CLIENT_BODY; if (share_channel->content_length == 0) get_next_manifest_entry (self, share_channel, FALSE); } } else { /* We expect content-length to be 0 and no chunks for non-200 statuses (404 error) */ if (share_channel->is_chunked || share_channel->content_length != 0) { GList *i; DEBUG ("Unexpected body for non-200 error!"); for (i = self->priv->channels; i;) { GabbleFileTransferChannel *channel = i->data; i = i->next; gabble_file_transfer_channel_gtalk_file_collection_state_changed ( channel, GTALK_FILE_COLLECTION_STATE_ERROR, FALSE); } } else { get_next_manifest_entry (self, share_channel, TRUE); } } } else if (!g_ascii_strncasecmp (line, "Content-Length: ", 16)) { share_channel->is_chunked = FALSE; /* Check strtoull read all the length */ share_channel->content_length = g_ascii_strtoull (line + 16, NULL, 10); DEBUG ("Found data length : %" G_GUINT64_FORMAT, share_channel->content_length); } else if (!g_ascii_strcasecmp (line, "Transfer-Encoding: chunked")) { share_channel->is_chunked = TRUE; share_channel->content_length = 0; DEBUG ("Found file is chunked"); } return next_line - buffer; } break; case HTTP_CLIENT_CHUNK_SIZE: { gchar *line = buffer; gchar *next_line = http_read_line (buffer, len); if (next_line == NULL) return 0; /* FIXME : check validity of strtoul */ share_channel->content_length = strtoul (line, NULL, 16); if (share_channel->content_length > 0) share_channel->http_status = HTTP_CLIENT_BODY; else share_channel->http_status = HTTP_CLIENT_CHUNK_FINAL; return next_line - buffer; } break; case HTTP_CLIENT_BODY: { guint consumed = 0; if (len >= share_channel->content_length) { if (self->priv->current_channel == NULL) { GList *i; DEBUG ("Unexpected current_channel == NULL!"); for (i = self->priv->channels; i;) { GabbleFileTransferChannel *channel = i->data; i = i->next; gabble_file_transfer_channel_gtalk_file_collection_state_changed ( channel, GTALK_FILE_COLLECTION_STATE_ERROR, FALSE); } /* FIXME: Who knows what might happen here if we got destroyed It shouldn't crash since our object isn't dereferences anymore, but.. */ return len; } consumed = share_channel->content_length; gabble_file_transfer_channel_gtalk_file_collection_data_received ( self->priv->current_channel, buffer, consumed); share_channel->content_length = 0; if (share_channel->is_chunked) share_channel->http_status = HTTP_CLIENT_CHUNK_END; else get_next_manifest_entry (self, share_channel, FALSE); } else { consumed = len; share_channel->content_length -= len; gabble_file_transfer_channel_gtalk_file_collection_data_received ( self->priv->current_channel, buffer, consumed); } return consumed; } break; case HTTP_CLIENT_CHUNK_END: { gchar *chunk = http_read_line (buffer, len); if (chunk == NULL) return 0; share_channel->http_status = HTTP_CLIENT_CHUNK_SIZE; return chunk - buffer; } break; case HTTP_CLIENT_CHUNK_FINAL: { gchar *end = http_read_line (buffer, len); if (end == NULL) return 0; share_channel->http_status = HTTP_CLIENT_IDLE; get_next_manifest_entry (self, share_channel, FALSE); return end - buffer; } break; } return 0; } static void nice_data_received_cb (NiceAgent *agent, guint stream_id, guint component_id, guint len, gchar *buffer, gpointer user_data) { GTalkFileCollection *self = GTALK_FILE_COLLECTION (user_data); ShareChannel *share_channel = get_share_channel (self, agent); gchar *free_buffer = NULL; if (share_channel->read_buffer != NULL) { gchar *tmp = g_malloc (share_channel->read_len + len); memcpy (tmp, share_channel->read_buffer, share_channel->read_len); memcpy (tmp + share_channel->read_len, buffer, len); free_buffer = buffer = tmp; len += share_channel->read_len; g_free (share_channel->read_buffer); share_channel->read_buffer = NULL; share_channel->read_len = 0; } while (len > 0) { guint consumed = http_data_received (self, share_channel, buffer, len); if (consumed == 0) { share_channel->read_buffer = g_memdup (buffer, len); share_channel->read_len = len; break; } else { /* we assume http_data_received never returns consumed > len */ g_assert (consumed <= len); len -= consumed; buffer += consumed; } } if (free_buffer != NULL) g_free (free_buffer); } static void set_session (GTalkFileCollection * self, WockyJingleSession *session, WockyJingleContent *content) { self->priv->jingle = g_object_ref (session); gabble_signal_connect_weak (session, "notify::state", (GCallback) jingle_session_state_changed_cb, G_OBJECT (self)); gabble_signal_connect_weak (session, "terminated", (GCallback) jingle_session_terminated_cb, G_OBJECT (self)); gabble_signal_connect_weak (content, "new-share-channel", (GCallback) content_new_share_channel_cb, G_OBJECT (self)); gabble_signal_connect_weak (content, "completed", (GCallback) content_completed, G_OBJECT (self)); self->priv->status = GTALK_FT_STATUS_PENDING; } GTalkFileCollection * gtalk_file_collection_new (GabbleFileTransferChannel *channel, WockyJingleFactory *jingle_factory, TpHandle handle, const gchar *jid) { GTalkFileCollection * self = g_object_new (GTALK_TYPE_FILE_COLLECTION, NULL); WockyJingleSession *session = NULL; WockyJingleContent *content = NULL; gchar *filename; guint64 size; self->priv->jingle_factory = jingle_factory; self->priv->requested = TRUE; session = wocky_jingle_factory_create_session (jingle_factory, jid, WOCKY_JINGLE_DIALECT_GTALK4, FALSE); if (session == NULL) { g_object_unref (self); return NULL; } content = wocky_jingle_session_add_content (session, WOCKY_JINGLE_MEDIA_TYPE_NONE, WOCKY_JINGLE_CONTENT_SENDERS_BOTH, "share", NS_GOOGLE_SESSION_SHARE, NS_GOOGLE_TRANSPORT_P2P); if (content == NULL) { g_object_unref (self); g_object_unref (session); return NULL; } g_object_get (channel, "filename", &filename, "size", &size, NULL); g_object_set (content, "filename", filename, "filesize", size, NULL); set_session (self, session, content); add_channel (self, channel); return self; } GTalkFileCollection * gtalk_file_collection_new_from_session (WockyJingleFactory *jingle_factory, WockyJingleSession *session) { GTalkFileCollection * self = NULL; WockyJingleContent *content = NULL; GList *cs; if (wocky_jingle_session_get_content_type (session) != GABBLE_TYPE_JINGLE_SHARE) return NULL; cs = wocky_jingle_session_get_contents (session); if (cs != NULL) { content = WOCKY_JINGLE_CONTENT (cs->data); g_list_free (cs); } if (content == NULL) return NULL; self = g_object_new (GTALK_TYPE_FILE_COLLECTION, NULL); self->priv->jingle_factory = jingle_factory; self->priv->requested = FALSE; set_session (self, session, content); return self; } void gtalk_file_collection_add_channel (GTalkFileCollection *self, GabbleFileTransferChannel *channel) { add_channel (self, channel); } void gtalk_file_collection_initiate (GTalkFileCollection *self, GabbleFileTransferChannel * channel) { if (channel_exists (self, channel)) { g_hash_table_replace (self->priv->channels_reading, channel, GINT_TO_POINTER (TRUE)); g_hash_table_replace (self->priv->channels_usable, channel, GINT_TO_POINTER (TRUE)); } if (self->priv->status == GTALK_FT_STATUS_PENDING) { wocky_jingle_session_accept (self->priv->jingle); self->priv->status = GTALK_FT_STATUS_INITIATED; } else { gabble_file_transfer_channel_gtalk_file_collection_state_changed ( channel, GTALK_FILE_COLLECTION_STATE_ACCEPTED, FALSE); } } void gtalk_file_collection_accept (GTalkFileCollection *self, GabbleFileTransferChannel * channel) { GList *cs = wocky_jingle_session_get_contents (self->priv->jingle); DEBUG ("called"); if (channel_exists (self, channel)) { g_hash_table_replace (self->priv->channels_usable, channel, GINT_TO_POINTER (TRUE)); } if (self->priv->status == GTALK_FT_STATUS_PENDING) { if (cs != NULL) { WockyJingleContent *content = WOCKY_JINGLE_CONTENT (cs->data); guint initial_id = 0; guint share_channel_id; wocky_jingle_session_accept (self->priv->jingle); self->priv->status = GTALK_FT_STATUS_ACCEPTED; /* The new-share-channel signal will take care of the rest.. */ do { gchar *share_channel_name = NULL; share_channel_name = g_strdup_printf ("gabble-%d", ++initial_id); share_channel_id = wocky_jingle_content_create_share_channel ( content, share_channel_name); g_free (share_channel_name); } while (share_channel_id == 0 && initial_id < 10); /* FIXME: not assert but actually cancel the FT? */ g_assert (share_channel_id > 0); g_list_free (cs); } } else { gabble_file_transfer_channel_gtalk_file_collection_state_changed ( channel, GTALK_FILE_COLLECTION_STATE_ACCEPTED, FALSE); } if (self->priv->status == GTALK_FT_STATUS_WAITING) { /* FIXME: this and other lookups should not check for channel '1' */ ShareChannel *share_channel = g_hash_table_lookup ( self->priv->share_channels, GINT_TO_POINTER (1)); get_next_manifest_entry (self, share_channel, FALSE); } } gboolean gtalk_file_collection_send_data (GTalkFileCollection *self, GabbleFileTransferChannel *channel, const gchar *data, guint length) { ShareChannel *share_channel = g_hash_table_lookup (self->priv->share_channels, GINT_TO_POINTER (1)); gint ret; g_return_val_if_fail (self->priv->current_channel == channel, FALSE); ret = nice_agent_send (share_channel->agent, share_channel->stream_id, share_channel->component_id, length, data); if (ret < 0 || (guint) ret < length) { if (ret < 0) ret = 0; share_channel->write_buffer = g_memdup (data + ret, length - ret); share_channel->write_len = length - ret; gabble_file_transfer_channel_gtalk_file_collection_write_blocked (channel, TRUE); } return TRUE; } void gtalk_file_collection_block_reading (GTalkFileCollection *self, GabbleFileTransferChannel *channel, gboolean block) { ShareChannel *share_channel = g_hash_table_lookup (self->priv->share_channels, GINT_TO_POINTER (1)); g_assert (channel_exists (self, channel)); if (self->priv->status != GTALK_FT_STATUS_TRANSFERRING) DEBUG ("Channel %p %s reading ", channel, block?"blocks":"unblocks" ); g_hash_table_replace (self->priv->channels_reading, channel, GINT_TO_POINTER (!block)); if (channel == self->priv->current_channel) { if (block) { if (share_channel && share_channel->agent_attached) { nice_agent_attach_recv (share_channel->agent, share_channel->stream_id, share_channel->component_id, NULL, NULL, NULL); share_channel->agent_attached = FALSE; } } else { if (share_channel && !share_channel->agent_attached) { share_channel->agent_attached = TRUE; nice_agent_attach_recv (share_channel->agent, share_channel->stream_id, share_channel->component_id, g_main_context_default (), nice_data_received_cb, self); } } } } void gtalk_file_collection_completed (GTalkFileCollection *self, GabbleFileTransferChannel * channel) { ShareChannel *share_channel = g_hash_table_lookup (self->priv->share_channels, GINT_TO_POINTER (1)); DEBUG ("called"); g_return_if_fail (self->priv->current_channel == channel); /* We shouldn't set the FT to completed until we receive the 'complete' info or we receive a new HTTP request otherwise we might terminate the session and cause a race condition where the peer thinks it got canceled before it completed. */ share_channel->http_status = HTTP_SERVER_IDLE; self->priv->status = GTALK_FT_STATUS_WAITING; } void gtalk_file_collection_terminate (GTalkFileCollection *self, GabbleFileTransferChannel * channel) { DEBUG ("called"); if (!channel_exists (self, channel)) return; if (self->priv->current_channel == channel) { del_channel (self, channel); /* Cancel the whole thing if we terminate the current channel */ if (self->priv->status == GTALK_FT_STATUS_TRANSFERRING) { /* The terminate should call our terminated_cb callback which should terminate all channels which should unref us which will unref the jingle session */ self->priv->status = GTALK_FT_STATUS_TERMINATED; wocky_jingle_session_terminate (self->priv->jingle, WOCKY_JINGLE_REASON_UNKNOWN, NULL, NULL); return; } return; } else { del_channel (self, channel); /* If this was the last channel, it will cause it to unref us and the dispose will be called, which will call wocky_jingle_session_terminate */ gabble_file_transfer_channel_gtalk_file_collection_state_changed (channel, GTALK_FILE_COLLECTION_STATE_TERMINATED, TRUE); } } static void channel_disposed (gpointer data, GObject *object) { GTalkFileCollection *self = data; GabbleFileTransferChannel *channel = (GabbleFileTransferChannel *) object; DEBUG ("channel %p got destroyed", channel); g_return_if_fail (channel_exists (self, channel)); if (self->priv->current_channel == channel) { del_channel (self, channel); /* Cancel the whole thing if we terminate the current channel */ if (self->priv->status == GTALK_FT_STATUS_TRANSFERRING) { /* The terminate should call our terminated_cb callback which should terminate all channels which should unref us which will unref the jingle session */ self->priv->status = GTALK_FT_STATUS_TERMINATED; wocky_jingle_session_terminate (self->priv->jingle, WOCKY_JINGLE_REASON_UNKNOWN, NULL, NULL); return; } } else { del_channel (self, channel); } } telepathy-gabble-0.18.3/src/protocol.h0000664000175000017500000000453212223562023021000 0ustar00cassidycassidy00000000000000/* * protocol.h - header for GabbleJabberProtocol * Copyright (C) 2007-2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef JABBER_PROTOCOL_H #define JABBER_PROTOCOL_H #include #include G_BEGIN_DECLS typedef struct _GabbleJabberProtocol GabbleJabberProtocol; typedef struct _GabbleJabberProtocolPrivate GabbleJabberProtocolPrivate; typedef struct _GabbleJabberProtocolClass GabbleJabberProtocolClass; typedef struct _GabbleJabberProtocolClassPrivate GabbleJabberProtocolClassPrivate; struct _GabbleJabberProtocolClass { TpBaseProtocolClass parent_class; GabbleJabberProtocolClassPrivate *priv; }; struct _GabbleJabberProtocol { TpBaseProtocol parent; GabbleJabberProtocolPrivate *priv; }; GType gabble_jabber_protocol_get_type (void); #define GABBLE_TYPE_JABBER_PROTOCOL \ (gabble_jabber_protocol_get_type ()) #define GABBLE_JABBER_PROTOCOL(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ GABBLE_TYPE_JABBER_PROTOCOL, \ GabbleJabberProtocol)) #define GABBLE_JABBER_PROTOCOL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), \ GABBLE_TYPE_JABBER_PROTOCOL, \ GabbleJabberProtocolClass)) #define GABBLE_IS_JABBER_PROTOCOL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), \ GABBLE_TYPE_JABBER_PROTOCOL)) #define GABBLE_JABBER_PROTOCOL_GET_CLASS(klass) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ GABBLE_TYPE_JABBER_PROTOCOL, \ GabbleJabberProtocolClass)) gchar *gabble_jabber_protocol_normalize_contact (const gchar *id, GError **error); TpBaseProtocol *gabble_jabber_protocol_new (void); G_END_DECLS #endif telepathy-gabble-0.18.3/src/conn-olpc.h0000664000175000017500000000301312332440117021020 0ustar00cassidycassidy00000000000000/* * conn-olpc.h - Header for Gabble OLPC BuddyInfo and ActivityProperties interfaces * Copyright (C) 2007 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __CONN_OLPC_H__ #define __CONN_OLPC_H__ #include #include "connection.h" void olpc_buddy_info_iface_init (gpointer g_iface, gpointer iface_data); void olpc_activity_properties_iface_init (gpointer g_iface, gpointer iface_data); void conn_olpc_activity_properties_init (GabbleConnection *conn); void conn_olpc_activity_properties_dispose (GabbleConnection *conn); gboolean conn_olpc_process_activity_properties_message (GabbleConnection *conn, WockyStanza *msg, const gchar *from); gboolean conn_olpc_process_activity_uninvite_message (GabbleConnection *conn, WockyStanza *msg, const gchar *from); #endif /* __CONN_OLPC_H__ */ telepathy-gabble-0.18.3/src/server-tls-manager.c0000664000175000017500000004054512332441362022657 0ustar00cassidycassidy00000000000000/* * server-tls-manager.c - Source for GabbleServerTLSManager * Copyright (C) 2010 Collabora Ltd. * @author Cosimo Cecchi * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "server-tls-manager.h" #include #include #define DEBUG_FLAG GABBLE_DEBUG_TLS #include "debug.h" #include "gabble/caps-channel-manager.h" #include "connection.h" #include "server-tls-channel.h" #include "util.h" #include "extensions/extensions.h" #include static void channel_manager_iface_init (gpointer, gpointer); G_DEFINE_TYPE_WITH_CODE (GabbleServerTLSManager, gabble_server_tls_manager, WOCKY_TYPE_TLS_HANDLER, G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER, channel_manager_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_CAPS_CHANNEL_MANAGER, NULL)); enum { PROP_CONNECTION = 1, PROP_INTERACTIVE_TLS, NUM_PROPERTIES }; struct _GabbleServerTLSManagerPrivate { /* Properties */ GabbleConnection *connection; gboolean interactive_tls; /* Current operation data */ gchar *peername; GStrv reference_identities; WockyTLSSession *tls_session; GabbleServerTLSChannel *channel; GSimpleAsyncResult *async_result; /* List of owned TpBaseChannel not yet closed by the client */ GList *completed_channels; gboolean dispose_has_run; }; #define chainup ((WockyTLSHandlerClass *) \ gabble_server_tls_manager_parent_class) static void gabble_server_tls_manager_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleServerTLSManager *self = GABBLE_SERVER_TLS_MANAGER (object); switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, self->priv->connection); break; case PROP_INTERACTIVE_TLS: g_value_set_boolean (value, self->priv->interactive_tls); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_server_tls_manager_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleServerTLSManager *self = GABBLE_SERVER_TLS_MANAGER (object); switch (property_id) { case PROP_CONNECTION: self->priv->connection = g_value_dup_object (value); break; case PROP_INTERACTIVE_TLS: self->priv->interactive_tls = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void close_all (GabbleServerTLSManager *self) { GList *l; if (self->priv->channel != NULL) tp_base_channel_close (TP_BASE_CHANNEL (self->priv->channel)); l = self->priv->completed_channels; while (l != NULL) { /* use a temporary variable as the ::closed callback will delete * the link from the list. */ GList *next = l->next; tp_base_channel_close (l->data); l = next; } } static void connection_status_changed_cb (GabbleConnection *conn, guint status, guint reason, gpointer user_data) { GabbleServerTLSManager *self = user_data; DEBUG ("Connection status changed, now %d", status); if (status == TP_CONNECTION_STATUS_DISCONNECTED) { close_all (self); tp_clear_object (&self->priv->connection); } } static void complete_verify (GabbleServerTLSManager *self) { /* Move channel to a list until a client Close() it */ if (self->priv->channel != NULL) { self->priv->completed_channels = g_list_prepend ( self->priv->completed_channels, g_object_ref (self->priv->channel)); } g_simple_async_result_complete (self->priv->async_result); /* Reset to initial state */ tp_clear_pointer (&self->priv->peername, g_free); tp_clear_pointer (&self->priv->reference_identities, g_strfreev); g_clear_object (&self->priv->tls_session); g_clear_object (&self->priv->channel); g_clear_object (&self->priv->async_result); } static void verify_fallback_cb (GObject *source, GAsyncResult *result, gpointer user_data) { GabbleServerTLSManager *self = (GabbleServerTLSManager *) source; GError *error = NULL; if (!chainup->verify_finish_func (WOCKY_TLS_HANDLER (self), result, &error)) g_simple_async_result_take_error (self->priv->async_result, error); complete_verify (self); } static void server_tls_channel_closed_cb (GabbleServerTLSChannel *channel, gpointer user_data) { GabbleServerTLSManager *self = user_data; DEBUG ("Server TLS channel closed."); if (channel == self->priv->channel) { /* fallback to the old-style non interactive TLS verification */ DEBUG ("Channel closed, but unhandled, falling back..."); chainup->verify_async_func (WOCKY_TLS_HANDLER (self), self->priv->tls_session, self->priv->peername, self->priv->reference_identities, verify_fallback_cb, NULL); self->priv->channel = NULL; } else { GList *l; l = g_list_find (self->priv->completed_channels, channel); g_assert (l != NULL); self->priv->completed_channels = g_list_delete_link ( self->priv->completed_channels, l); } tp_channel_manager_emit_channel_closed_for_object (self, TP_EXPORTABLE_CHANNEL (channel)); g_object_unref (channel); } GQuark gabble_server_tls_error_quark (void) { static GQuark quark = 0; if (!quark) quark = g_quark_from_static_string ("server-tls-error"); return quark; } static void tls_certificate_accepted_cb (GabbleTLSCertificate *certificate, gpointer user_data) { GabbleServerTLSManager *self = user_data; DEBUG ("TLS certificate accepted"); complete_verify (self); } static void tls_certificate_rejected_cb (GabbleTLSCertificate *certificate, GPtrArray *rejections, gpointer user_data) { GabbleServerTLSManager *self = user_data; DEBUG ("TLS certificate rejected with rejections %p, length %u.", rejections, rejections->len); g_simple_async_result_set_error (self->priv->async_result, GABBLE_SERVER_TLS_ERROR, 0, "TLS certificate rejected"); complete_verify (self); } static void extend_string_ptr_array (GPtrArray *array, GStrv new_elements) { gint i; if (new_elements != NULL) { for (i = 0; new_elements[i] != NULL; i++) { if (!tp_str_empty (new_elements[i])) g_ptr_array_add (array, g_strdup (new_elements[i])); } } } static void fill_reference_identities (GabbleServerTLSManager *self, const gchar *peername, GStrv original_extra_identities) { GPtrArray *identities; gchar *connect_server = NULL; gchar *explicit_server = NULL; GStrv extra_certificate_identities = NULL; g_return_if_fail (self->priv->reference_identities == NULL); g_object_get (self->priv->connection, "connect-server", &connect_server, "explicit-server", &explicit_server, "extra-certificate-identities", &extra_certificate_identities, NULL); identities = g_ptr_array_new (); /* The peer name, i.e, the domain part of the JID */ g_ptr_array_add (identities, g_strdup (peername)); /* The extra identities that the caller of verify_async() passed */ extend_string_ptr_array (identities, original_extra_identities); /* The explicitly overridden server (if in use) */ if (!tp_str_empty (explicit_server) && !tp_strdiff (connect_server, explicit_server)) { g_ptr_array_add (identities, g_strdup (explicit_server)); } /* Extra identities added to the account as a result of user choices */ extend_string_ptr_array (identities, extra_certificate_identities); /* Null terminate, since this is a gchar** */ g_ptr_array_add (identities, NULL); self->priv->reference_identities = (GStrv) g_ptr_array_free (identities, FALSE); g_strfreev (extra_certificate_identities); g_free (explicit_server); g_free (connect_server); } static void gabble_server_tls_manager_verify_async (WockyTLSHandler *handler, WockyTLSSession *tls_session, const gchar *peername, GStrv extra_identities, GAsyncReadyCallback callback, gpointer user_data) { GabbleServerTLSManager *self = GABBLE_SERVER_TLS_MANAGER (handler); GabbleTLSCertificate *certificate; GSimpleAsyncResult *result; g_return_if_fail (self->priv->async_result == NULL); DEBUG ("verify_async() called on the GabbleServerTLSManager."); result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, gabble_server_tls_manager_verify_async); if (self->priv->connection == NULL) { DEBUG ("connection already went away; failing immediately"); g_simple_async_result_set_error (result, TP_ERROR, TP_ERROR_CANCELLED, "The Telepathy connection has already been disconnected"); g_simple_async_result_complete_in_idle (result); g_object_unref (result); return; } self->priv->async_result = result; fill_reference_identities (self, peername, extra_identities); if (!self->priv->interactive_tls) { DEBUG ("ignore-ssl-errors is set, fallback to non-interactive " "verification."); chainup->verify_async_func (WOCKY_TLS_HANDLER (self), tls_session, peername, self->priv->reference_identities, verify_fallback_cb, NULL); return; } self->priv->tls_session = g_object_ref (tls_session); self->priv->peername = g_strdup (peername); self->priv->channel = g_object_new (GABBLE_TYPE_SERVER_TLS_CHANNEL, "connection", self->priv->connection, "tls-session", tls_session, "hostname", peername, "reference-identities", self->priv->reference_identities, NULL); g_signal_connect (self->priv->channel, "closed", G_CALLBACK (server_tls_channel_closed_cb), self); certificate = gabble_server_tls_channel_get_certificate (self->priv->channel); g_signal_connect (certificate, "accepted", G_CALLBACK (tls_certificate_accepted_cb), self); g_signal_connect (certificate, "rejected", G_CALLBACK (tls_certificate_rejected_cb), self); /* emit NewChannel on the ChannelManager iface */ tp_channel_manager_emit_new_channel (self, (TpExportableChannel *) self->priv->channel, NULL); } static gboolean gabble_server_tls_manager_verify_finish (WockyTLSHandler *self, GAsyncResult *result, GError **error) { wocky_implement_finish_void (self, gabble_server_tls_manager_verify_async); } static void gabble_server_tls_manager_init (GabbleServerTLSManager *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_SERVER_TLS_MANAGER, GabbleServerTLSManagerPrivate); } static void gabble_server_tls_manager_dispose (GObject *object) { GabbleServerTLSManager *self = GABBLE_SERVER_TLS_MANAGER (object); DEBUG ("%p", self); if (self->priv->dispose_has_run) return; self->priv->dispose_has_run = TRUE; tp_clear_object (&self->priv->tls_session); tp_clear_object (&self->priv->connection); G_OBJECT_CLASS (gabble_server_tls_manager_parent_class)->dispose (object); } static void gabble_server_tls_manager_finalize (GObject *object) { GabbleServerTLSManager *self = GABBLE_SERVER_TLS_MANAGER (object); DEBUG ("%p", self); close_all (self); g_free (self->priv->peername); g_strfreev (self->priv->reference_identities); G_OBJECT_CLASS (gabble_server_tls_manager_parent_class)->finalize (object); } static void gabble_server_tls_manager_constructed (GObject *object) { GabbleServerTLSManager *self = GABBLE_SERVER_TLS_MANAGER (object); void (*chain_up) (GObject *) = G_OBJECT_CLASS (gabble_server_tls_manager_parent_class)->constructed; if (chain_up != NULL) chain_up (object); DEBUG ("Server TLS Manager constructed"); gabble_signal_connect_weak (self->priv->connection, "status-changed", G_CALLBACK (connection_status_changed_cb), object); } static void gabble_server_tls_manager_class_init (GabbleServerTLSManagerClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); WockyTLSHandlerClass *hclass = WOCKY_TLS_HANDLER_CLASS (klass); GParamSpec *pspec; g_type_class_add_private (klass, sizeof (GabbleServerTLSManagerPrivate)); oclass->dispose = gabble_server_tls_manager_dispose; oclass->finalize = gabble_server_tls_manager_finalize; oclass->constructed = gabble_server_tls_manager_constructed; oclass->set_property = gabble_server_tls_manager_set_property; oclass->get_property = gabble_server_tls_manager_get_property; hclass->verify_async_func = gabble_server_tls_manager_verify_async; hclass->verify_finish_func = gabble_server_tls_manager_verify_finish; pspec = g_param_spec_object ("connection", "GabbleConnection object", "Gabble connection object that owns this manager.", GABBLE_TYPE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (oclass, PROP_CONNECTION, pspec); pspec = g_param_spec_boolean ("interactive-tls", "Interactive TLS setting", "Whether interactive TLS certificate verification is enabled.", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (oclass, PROP_INTERACTIVE_TLS, pspec); } static void gabble_server_tls_manager_foreach_channel (TpChannelManager *manager, TpExportableChannelFunc func, gpointer user_data) { GabbleServerTLSManager *self = GABBLE_SERVER_TLS_MANAGER (manager); GList *l; if (self->priv->channel != NULL) func (TP_EXPORTABLE_CHANNEL (self->priv->channel), user_data); for (l = self->priv->completed_channels; l != NULL; l = l->next) { func (l->data, user_data); } } static void channel_manager_iface_init (gpointer g_iface, gpointer iface_data) { TpChannelManagerIface *iface = g_iface; iface->foreach_channel = gabble_server_tls_manager_foreach_channel; /* these channels are not requestable. */ iface->ensure_channel = NULL; iface->create_channel = NULL; iface->request_channel = NULL; iface->foreach_channel_class = NULL; } static TpConnectionStatusReason cert_reject_reason_to_conn_reason (TpTLSCertificateRejectReason tls_reason) { #define EASY_CASE(x) \ case TP_TLS_CERTIFICATE_REJECT_REASON_ ## x: \ return TP_CONNECTION_STATUS_REASON_CERT_ ## x; switch (tls_reason) { EASY_CASE (UNTRUSTED); EASY_CASE (EXPIRED); EASY_CASE (NOT_ACTIVATED); EASY_CASE (FINGERPRINT_MISMATCH); EASY_CASE (HOSTNAME_MISMATCH); EASY_CASE (SELF_SIGNED); EASY_CASE (REVOKED); EASY_CASE (INSECURE); EASY_CASE (LIMIT_EXCEEDED); case TP_TLS_CERTIFICATE_REJECT_REASON_UNKNOWN: default: return TP_CONNECTION_STATUS_REASON_CERT_OTHER_ERROR; } #undef EASY_CASE } void gabble_server_tls_manager_get_rejection_details (GabbleServerTLSManager *self, gchar **dbus_error, GHashTable **details, TpConnectionStatusReason *reason) { GabbleTLSCertificate *certificate; GPtrArray *rejections; GValueArray *rejection; TpTLSCertificateRejectReason tls_reason; /* We probably want the rejection details of last completed operation */ g_return_if_fail (self->priv->completed_channels != NULL); certificate = gabble_server_tls_channel_get_certificate ( self->priv->completed_channels->data); g_object_get (certificate, "rejections", &rejections, NULL); /* we return 'Invalid_Argument' if Reject() is called with zero * reasons, so if this fails something bad happened. */ g_assert (rejections->len >= 1); rejection = g_ptr_array_index (rejections, 0); tls_reason = g_value_get_uint (g_value_array_get_nth (rejection, 0)); *dbus_error = g_value_dup_string (g_value_array_get_nth (rejection, 1)); *details = g_value_dup_boxed (g_value_array_get_nth (rejection, 2)); *reason = cert_reject_reason_to_conn_reason (tls_reason); tp_clear_boxed (TP_ARRAY_TYPE_TLS_CERTIFICATE_REJECTION_LIST, &rejections); } telepathy-gabble-0.18.3/src/media-factory.h0000664000175000017500000000537712332441362021676 0ustar00cassidycassidy00000000000000/* * media-factory.h - Header for GabbleMediaFactory * Copyright (C) 2006 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __MEDIA_FACTORY_H__ #define __MEDIA_FACTORY_H__ #include #include "media-channel.h" G_BEGIN_DECLS typedef struct _GabbleMediaFactory GabbleMediaFactory; typedef struct _GabbleMediaFactoryClass GabbleMediaFactoryClass; typedef struct _GabbleMediaFactoryPrivate GabbleMediaFactoryPrivate; struct _GabbleMediaFactoryClass { GObjectClass parent_class; }; struct _GabbleMediaFactory { GObject parent; GabbleMediaFactoryPrivate *priv; }; GType gabble_media_factory_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_MEDIA_FACTORY \ (gabble_media_factory_get_type ()) #define GABBLE_MEDIA_FACTORY(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_MEDIA_FACTORY,\ GabbleMediaFactory)) #define GABBLE_MEDIA_FACTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_MEDIA_FACTORY,\ GabbleMediaFactoryClass)) #define GABBLE_IS_MEDIA_FACTORY(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_MEDIA_FACTORY)) #define GABBLE_IS_MEDIA_FACTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_MEDIA_FACTORY)) #define GABBLE_MEDIA_FACTORY_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_MEDIA_FACTORY,\ GabbleMediaFactoryClass)) const gchar * _gabble_media_factory_allocate_sid (GabbleMediaFactory *fac, GabbleMediaChannel *chan); const gchar * _gabble_media_factory_register_sid (GabbleMediaFactory *fac, const gchar *sid, GabbleMediaChannel *chan); void _gabble_media_factory_free_sid (GabbleMediaFactory *fac, const gchar *sid); void _gabble_media_factory_typeflags_to_caps (TpChannelMediaCapabilities flags, GabbleCapabilitySet *caps); TpChannelMediaCapabilities _gabble_media_factory_caps_to_typeflags (const GabbleCapabilitySet *caps); const gchar * const * gabble_media_factory_call_channel_allowed_properties ( void); G_END_DECLS #endif /* #ifndef __MEDIA_FACTORY_H__ */ telepathy-gabble-0.18.3/src/muc-channel.h0000664000175000017500000001101412332440117021322 0ustar00cassidycassidy00000000000000/* * gabble-muc-channel.h - Header for GabbleMucChannel * Copyright (C) 2006 Collabora Ltd. * Copyright (C) 2006 Nokia Corporation * @author Ole Andre Vadla Ravnaas * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_MUC_CHANNEL_H__ #define __GABBLE_MUC_CHANNEL_H__ #include "config.h" #include #include #include #include "types.h" #ifdef ENABLE_VOIP #include "call-muc-channel.h" #endif #include "tube-iface.h" G_BEGIN_DECLS typedef enum { MUC_STATE_CREATED = 0, MUC_STATE_INITIATED, MUC_STATE_AUTH, MUC_STATE_JOINED, MUC_STATE_ENDED, } GabbleMucState; typedef struct _GabbleMucChannelClass GabbleMucChannelClass; typedef struct _GabbleMucChannelPrivate GabbleMucChannelPrivate; struct _GabbleMucChannelClass { TpBaseChannelClass parent_class; TpGroupMixinClass group_class; TpDBusPropertiesMixinClass dbus_props_class; }; struct _GabbleMucChannel { TpBaseChannel parent; TpGroupMixin group; TpMessageMixin message_mixin; GabbleMucChannelPrivate *priv; }; GType gabble_muc_channel_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_MUC_CHANNEL \ (gabble_muc_channel_get_type ()) #define GABBLE_MUC_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_MUC_CHANNEL, \ GabbleMucChannel)) #define GABBLE_MUC_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_MUC_CHANNEL,\ GabbleMucChannelClass)) #define GABBLE_IS_MUC_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_MUC_CHANNEL)) #define GABBLE_IS_MUC_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_MUC_CHANNEL)) #define GABBLE_MUC_CHANNEL_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_MUC_CHANNEL,\ GabbleMucChannelClass)) gboolean _gabble_muc_channel_is_ready (GabbleMucChannel *chan); void gabble_muc_channel_set_autoclose (GabbleMucChannel *chan, gboolean autoclose); gboolean gabble_muc_channel_get_autoclose (GabbleMucChannel *chan); gboolean gabble_muc_channel_can_be_closed (GabbleMucChannel *chan); void gabble_muc_channel_send_presence (GabbleMucChannel *chan); gboolean gabble_muc_channel_send_invite (GabbleMucChannel *self, const gchar *jid, const gchar *message, gboolean continue_, GError **error); GabbleTubeIface * gabble_muc_channel_tube_request (GabbleMucChannel *self, gpointer request_token, GHashTable *request_properties, gboolean require_new); void gabble_muc_channel_foreach_tubes (GabbleMucChannel *gmuc, TpExportableChannelFunc foreach, gpointer user_data); void gabble_muc_channel_handle_si_stream_request (GabbleMucChannel *self, GabbleBytestreamIface *bytestream, const gchar *stream_id, WockyStanza *msg); #ifdef ENABLE_VOIP GabbleCallMucChannel * gabble_muc_channel_get_call (GabbleMucChannel *gmuc); GList * gabble_muc_channel_get_call_channels (GabbleMucChannel *self); void gabble_muc_channel_request_call (GabbleMucChannel *gmuc, GHashTable *request, gboolean require_new, gpointer token, GAsyncReadyCallback callback, gpointer user_data); gboolean gabble_muc_channel_request_call_finish (GabbleMucChannel *gmuc, GAsyncResult *result, GError **error); gboolean gabble_muc_channel_handle_jingle_session (GabbleMucChannel *channel, WockyJingleSession *session); #endif void gabble_muc_channel_update_configuration_async ( GabbleMucChannel *self, GHashTable *validated_properties, GAsyncReadyCallback callback, gpointer user_data); gboolean gabble_muc_channel_update_configuration_finish ( GabbleMucChannel *self, GAsyncResult *result, GError **error); void gabble_muc_channel_teardown (GabbleMucChannel *gmuc); G_END_DECLS #endif /* #ifndef __GABBLE_MUC_CHANNEL_H__*/ telepathy-gabble-0.18.3/src/plugin-loader.h0000664000175000017500000000615212223562023021701 0ustar00cassidycassidy00000000000000/* * plugin-loader.h — plugin support for telepathy-gabble * Copyright © 2009 Collabora Ltd. * Copyright © 2009 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __PLUGIN_LOADER_H__ #define __PLUGIN_LOADER_H__ #include #include #include #include #include "gabble/sidecar.h" #include "gabble/plugin-connection.h" typedef struct _GabblePluginLoader GabblePluginLoader; typedef struct _GabblePluginLoaderClass GabblePluginLoaderClass; typedef struct _GabblePluginLoaderPrivate GabblePluginLoaderPrivate; struct _GabblePluginLoaderClass { GObjectClass parent_class; }; struct _GabblePluginLoader { GObject parent; GabblePluginLoaderPrivate *priv; }; GType gabble_plugin_loader_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_PLUGIN_LOADER \ (gabble_plugin_loader_get_type ()) #define GABBLE_PLUGIN_LOADER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_PLUGIN_LOADER, \ GabblePluginLoader)) #define GABBLE_PLUGIN_LOADER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_PLUGIN_LOADER, \ GabblePluginLoaderClass)) #define GABBLE_IS_PLUGIN_LOADER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_PLUGIN_LOADER)) #define GABBLE_IS_PLUGIN_LOADER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_PLUGIN_LOADER)) #define GABBLE_PLUGIN_LOADER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_PLUGIN_LOADER, \ GabblePluginLoaderClass)) GabblePluginLoader *gabble_plugin_loader_dup (void); void gabble_plugin_loader_create_sidecar ( GabblePluginLoader *self, const gchar *sidecar_interface, GabbleConnection *connection, WockySession *session, GAsyncReadyCallback callback, gpointer user_data); GabbleSidecar *gabble_plugin_loader_create_sidecar_finish ( GabblePluginLoader *self, GAsyncResult *result, GError **error); TpPresenceStatusSpec *gabble_plugin_loader_append_statuses ( GabblePluginLoader *self, const TpPresenceStatusSpec *base_statuses); const gchar *gabble_plugin_loader_presence_status_for_privacy_list ( GabblePluginLoader *loader, const gchar *list_name); GPtrArray * gabble_plugin_loader_create_channel_managers ( GabblePluginLoader *self, GabblePluginConnection *plugin_connection); #endif /* #ifndef __PLUGIN_LOADER_H__ */ telepathy-gabble-0.18.3/src/bytestream-factory.c0000664000175000017500000020372612332440117022764 0ustar00cassidycassidy00000000000000/* * bytestream-factory.c - Source for GabbleBytestreamFactory * Copyright (C) 2007-2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "bytestream-factory.h" #include #include #include #include #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_BYTESTREAM #include "bytestream-ibb.h" #include "bytestream-iface.h" #include "bytestream-muc.h" #include "bytestream-multiple.h" #include "bytestream-socks5.h" #include "connection.h" #include "conn-util.h" #include "debug.h" #include "disco.h" #include "namespaces.h" #include "presence-cache.h" #include "private-tubes-factory.h" #include "util.h" G_DEFINE_TYPE (GabbleBytestreamFactory, gabble_bytestream_factory, G_TYPE_OBJECT); /* The number of proxy we'll try to have at a minimum in the cache. */ #define NB_MIN_SOCKS5_PROXIES 3 #define FALLBACK_PROXY_CACHE_SIZE 5 #define SOCKS5_PROXY_TIMEOUT 10 #define TELEPATHY_PROXIES_SERVICE "proxies.telepathy.im" /* The life time (in seconds) of the proxies list discovered using * TELEPATHY_PROXIES_SERVICE */ /* 6 hours */ #define PROXIES_LIST_LIFE_TIME 6 * 60 * 60 /* properties */ enum { PROP_CONNECTION = 1, LAST_PROPERTY }; typedef struct { gchar *jid; gchar *stream; } BytestreamIdentifier; typedef struct { const gchar *jid; const gchar *stream; } ConstBytestreamIdentifier; static gboolean bytestream_id_equal (gconstpointer v1, gconstpointer v2) { const ConstBytestreamIdentifier *left = v1; const ConstBytestreamIdentifier *right = v2; return (!tp_strdiff (left->jid, right->jid)) && (!tp_strdiff (left->stream, right->stream)); } static guint bytestream_id_hash (gconstpointer v) { const ConstBytestreamIdentifier *bsid = v; return g_str_hash (bsid->jid) ^ g_str_hash (bsid->stream); } static BytestreamIdentifier * bytestream_id_new (GabbleBytestreamIface *bytestream) { BytestreamIdentifier *bsid = g_slice_new (BytestreamIdentifier); g_object_get (bytestream, "stream-id", &(bsid->stream), "peer-jid", &(bsid->jid), NULL); return bsid; } static void bytestream_id_free (gpointer v) { BytestreamIdentifier *bsid = v; g_free (bsid->jid); g_free (bsid->stream); g_slice_free (BytestreamIdentifier, bsid); } static GabbleSocks5Proxy * gabble_socks5_proxy_new (const gchar *jid, const gchar *host, guint16 port) { GabbleSocks5Proxy *proxy; proxy = g_slice_new (GabbleSocks5Proxy); proxy->jid = g_strdup (jid); proxy->host = g_strdup (host); proxy->port = port; return proxy; } static void gabble_socks5_proxy_free (GabbleSocks5Proxy *proxy) { g_free (proxy->jid); g_free (proxy->host); g_slice_free (GabbleSocks5Proxy, proxy); } struct _GabbleBytestreamFactoryPrivate { GabbleConnection *conn; guint iq_si_cb; guint iq_ibb_cb; guint iq_socks5_cb; guint msg_data_cb; /* SI-initiated bytestreams - data sent by normal messages, IQs used to * open and close. * * BytestreamIdentifier -> GabbleBytestreamIBB */ GHashTable *ibb_bytestreams; /* BytestreamIdentifier -> GabbleBytestreamSocks5 */ GHashTable *socks5_bytestreams; /* MUC pseudo-IBB - data sent by groupchat messages, IQs not allowed. * * BytestreamIdentifier -> GabbleBytestreamMuc */ GHashTable *muc_bytestreams; /* SI-initiated bytestreams - real data sent through another bytestream. * * BytestreamIdentifier -> GabbleBytestreamMultiple */ GHashTable *multiple_bytestreams; /* List of GabbleSocks5Proxy discovered on the connection */ GSList *socks5_proxies; /* List of GabbleSocks5Proxy found using the fallback-socks5-proxies param */ GSList *socks5_fallback_proxies; /* List of SOCKS5's jids that have not been queried yet */ GSList *socks5_potential_proxies; /* Next proxy on socks5_potential_proxies that we'll query */ GSList *next_query; /* Time stamp of the proxies list received from TELEPATHY_PROXIES_SERVICE */ GTimeVal proxies_list_stamp; gboolean dispose_has_run; }; #define GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE(obj) ((obj)->priv) static gboolean bytestream_factory_msg_data_cb ( WockyPorter *porter, WockyStanza *msg, gpointer user_data); static gboolean bytestream_factory_iq_si_cb ( WockyPorter *porter, WockyStanza *msg, gpointer user_data); static gboolean bytestream_factory_iq_ibb_cb ( WockyPorter *porter, WockyStanza *msg, gpointer user_data); static gboolean handle_socks5_query_iq ( WockyPorter *porter, WockyStanza *msg, gpointer user_data); static void query_proxies (GabbleBytestreamFactory *self, guint nb_proxies_needed); static GSList * randomize_g_slist (GSList *list); static void gabble_bytestream_factory_init (GabbleBytestreamFactory *self) { GabbleBytestreamFactoryPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_BYTESTREAM_FACTORY, GabbleBytestreamFactoryPrivate); self->priv = priv; priv->ibb_bytestreams = g_hash_table_new_full (bytestream_id_hash, bytestream_id_equal, bytestream_id_free, g_object_unref); priv->muc_bytestreams = g_hash_table_new_full (bytestream_id_hash, bytestream_id_equal, bytestream_id_free, g_object_unref); priv->socks5_bytestreams = g_hash_table_new_full (bytestream_id_hash, bytestream_id_equal, bytestream_id_free, g_object_unref); priv->multiple_bytestreams = g_hash_table_new_full (bytestream_id_hash, bytestream_id_equal, bytestream_id_free, g_object_unref); memset (&priv->proxies_list_stamp, 0, sizeof (GTimeVal)); } static gint cmp_proxy (gconstpointer a, gconstpointer b) { GabbleSocks5Proxy *proxy_a = (GabbleSocks5Proxy *) a; GabbleSocks5Proxy *proxy_b = (GabbleSocks5Proxy *) b; /* Streamhost are identified by their jid */ return strcmp (proxy_a->jid, proxy_b->jid); } static void add_proxy_to_list (GabbleBytestreamFactory *self, GabbleSocks5Proxy *proxy, gboolean fallback) { GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE ( self); GSList **list; GSList *found; if (fallback) { list = &priv->socks5_fallback_proxies; } else { list = &priv->socks5_proxies; } found = g_slist_find_custom (*list, proxy, cmp_proxy); if (found != NULL) { DEBUG ("%s SOCKS5 proxy (%s %s:%d) is already known; " "move it to the head of the list", fallback ? "Fallback": "Discovered", proxy->jid, proxy->host, proxy->port); *list = g_slist_delete_link (*list, found); } else { DEBUG ("Add %s SOCKS5 proxy: %s %s:%d", fallback ? "fallback": "discovered", proxy->jid, proxy->host, proxy->port); if (fallback && g_slist_length (*list) >= FALLBACK_PROXY_CACHE_SIZE) { GSList *last; GabbleSocks5Proxy *oldest; last = g_slist_last (*list); oldest = last->data; DEBUG ("Proxy cache is full, remove the oldest entry (%s)", oldest->jid); *list = g_slist_delete_link (*list, last); gabble_socks5_proxy_free (oldest); } } *list = g_slist_prepend (*list, proxy); } static void socks5_proxy_query_reply_cb (GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg, GObject *obj, gpointer user_data) { GabbleBytestreamFactory *self = GABBLE_BYTESTREAM_FACTORY (obj); GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE ( self); WockyNode *query, *streamhost; const gchar *from; const gchar *jid, *host, *portstr; gint64 port; GabbleSocks5Proxy *proxy; gboolean fallback = GPOINTER_TO_INT (user_data); GSList *found = NULL; from = wocky_node_get_attribute ( wocky_stanza_get_top_node (reply_msg), "from"); if (from == NULL) goto fail; if (wocky_stanza_extract_errors (reply_msg, NULL, NULL, NULL, NULL)) goto fail; query = wocky_node_get_child_ns ( wocky_stanza_get_top_node (reply_msg), "query", NS_BYTESTREAMS); if (query == NULL) goto fail; streamhost = wocky_node_get_child (query, "streamhost"); if (streamhost == NULL) goto fail; jid = wocky_node_get_attribute (streamhost, "jid"); host = wocky_node_get_attribute (streamhost, "host"); portstr = wocky_node_get_attribute (streamhost, "port"); if (jid == NULL || host == NULL || portstr == NULL) goto fail; port = g_ascii_strtoll (portstr, NULL, 10); if (port <= 0 || port > G_MAXUINT16) goto fail; proxy = gabble_socks5_proxy_new (jid, host, port); add_proxy_to_list (self , proxy, fallback); return; fail: if (fallback && from != NULL) { /* Remove the buggy proxy so we won't query it anymore */ found = g_slist_find_custom (priv->socks5_potential_proxies, from, (GCompareFunc) strcmp); if (found != NULL) { DEBUG ("remove proxy %s", from); g_free (found->data); priv->socks5_potential_proxies = g_slist_delete_link ( priv->socks5_potential_proxies, found); } } /* Try to get another proxy as this one failed */ query_proxies (self, 1); } static void send_proxy_query (GabbleBytestreamFactory *self, const gchar *jid, gboolean fallback) { GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE ( self); WockyStanza *query; DEBUG ("send SOCKS5 query to %s", jid); query = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, jid, '(', "query", ':', NS_BYTESTREAMS, ')', NULL); _gabble_connection_send_with_reply (priv->conn, query, socks5_proxy_query_reply_cb, G_OBJECT (self), GINT_TO_POINTER (fallback), NULL); g_object_unref (query); } static void disco_item_found_cb (GabbleDisco *disco, GabbleDiscoItem *item, GabbleBytestreamFactory *self) { if (tp_strdiff (item->category, "proxy") || tp_strdiff (item->type, "bytestreams")) return; send_proxy_query (self, item->jid, FALSE); } static void query_proxies (GabbleBytestreamFactory *self, guint nb_proxies_needed) { GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE ( self); guint i; /* We don't want to query more than once the same proxy */ nb_proxies_needed = MIN (nb_proxies_needed, g_slist_length (priv->socks5_potential_proxies)); for (i = 0; i < nb_proxies_needed; i++) { gchar *jid; if (priv->next_query == NULL) priv->next_query = priv->socks5_potential_proxies; jid = priv->next_query->data; send_proxy_query (self, jid, TRUE); priv->next_query = g_slist_next (priv->next_query); } } static void proxies_disco_cb (GabbleDisco *disco, GabbleDiscoRequest *request, const gchar *j, const gchar *n, WockyNode *query_result, GError *error, gpointer user_data) { GabbleBytestreamFactory *self = GABBLE_BYTESTREAM_FACTORY (user_data); GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE ( self); WockyNodeIter i; WockyNode *node; GSList *new_list = NULL; if (error != NULL) { DEBUG ("disco failed: %s", error->message); return; } wocky_node_iter_init (&i, query_result, "item", NULL); while (wocky_node_iter_next (&i, &node)) { const gchar *jid = wocky_node_get_attribute (node, "jid"); if (jid == NULL) continue; DEBUG ("Discovered proxy %s", jid); new_list = g_slist_prepend (new_list, g_strdup (jid)); } g_get_current_time (&priv->proxies_list_stamp); if (new_list == NULL) return; /* replace the old list by the new one */ g_slist_foreach (priv->socks5_potential_proxies, (GFunc) g_free, NULL); g_slist_free (priv->socks5_potential_proxies); /* randomize the list to not always use the same proxies */ priv->socks5_potential_proxies = randomize_g_slist (new_list); priv->next_query = priv->socks5_potential_proxies; gabble_bytestream_factory_query_socks5_proxies (self); } /* Query TELEPATHY_PROXIES_SERVICE to get a list of proxies */ static void get_proxies_list (GabbleBytestreamFactory *self) { GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE ( self); DEBUG ("Ask %s for proxies", TELEPATHY_PROXIES_SERVICE); gabble_disco_request (priv->conn->disco, GABBLE_DISCO_TYPE_ITEMS, TELEPATHY_PROXIES_SERVICE, NULL, proxies_disco_cb, self, G_OBJECT (self), NULL); } /* ask to the factory to try to find more proxies if needed */ void gabble_bytestream_factory_query_socks5_proxies (GabbleBytestreamFactory *self) { GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE ( self); guint nb_proxies_found; guint nb_proxies_needed; GTimeVal now; if (priv->socks5_potential_proxies == NULL) { DEBUG ("No proxies list; request one"); get_proxies_list (self); return; } g_get_current_time (&now); if (now.tv_sec - priv->proxies_list_stamp.tv_sec > PROXIES_LIST_LIFE_TIME) { DEBUG ("Proxies list has expired; request a new one"); get_proxies_list (self); } nb_proxies_found = g_slist_length (priv->socks5_proxies) + g_slist_length (priv->socks5_fallback_proxies); if (nb_proxies_found >= NB_MIN_SOCKS5_PROXIES) { DEBUG ("we already have discovered enough proxies (%u); " "request just one to refresh our cache", nb_proxies_found); nb_proxies_needed = 1; } else { nb_proxies_needed = NB_MIN_SOCKS5_PROXIES - nb_proxies_found; DEBUG ("Need %u more proxies", nb_proxies_needed); } query_proxies (self, nb_proxies_needed); } static GSList * randomize_g_slist (GSList *list) { guint len; guint i; GSList *new_head, *new_tail; len = g_slist_length (list); if (len <= 1) return list; i = g_random_int_range (0, len); if (i == 0) return list; /* Cut the list at the i th position and make it the new head of the * list */ new_tail = g_slist_nth (list, i - 1); g_assert (new_tail != NULL); new_head = new_tail->next; g_assert (new_head != NULL); new_tail->next = NULL; return g_slist_concat (new_head, list); } static void porter_available_cb ( GabbleConnection *conn, WockyPorter *porter, gpointer user_data) { GabbleBytestreamFactory *self = GABBLE_BYTESTREAM_FACTORY (user_data); GabbleBytestreamFactoryPrivate *priv = self->priv; priv->msg_data_cb = wocky_porter_register_handler_from_anyone (porter, WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, WOCKY_PORTER_HANDLER_PRIORITY_MAX, bytestream_factory_msg_data_cb, self, NULL); priv->iq_si_cb = wocky_porter_register_handler_from_anyone (porter, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, bytestream_factory_iq_si_cb, self, '(', "si", ':', NS_SI, ')', NULL); priv->iq_ibb_cb = wocky_porter_register_handler_from_anyone (porter, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, WOCKY_PORTER_HANDLER_PRIORITY_MAX, bytestream_factory_iq_ibb_cb, self, NULL); priv->iq_socks5_cb = wocky_porter_register_handler_from_anyone (porter, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, handle_socks5_query_iq, self, '(', "query", ':', NS_BYTESTREAMS, ')', NULL); } static void conn_status_changed_cb (GabbleConnection *conn, TpConnectionStatus status, TpConnectionStatusReason reason, gpointer user_data) { GabbleBytestreamFactory *self = GABBLE_BYTESTREAM_FACTORY (user_data); GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE ( self); if (status == TP_CONNECTION_STATUS_CONNECTED) { GStrv jids; guint i; /* we can't intialize socks5_potential_proxies in the constructor * because Connection's properties are not set yet at this point */ g_object_get (priv->conn, "fallback-socks5-proxies", &jids, NULL); for (i = 0; jids != NULL && jids[i] != NULL; i++) { priv->socks5_potential_proxies = g_slist_prepend ( priv->socks5_potential_proxies, g_strdup (jids[i])); } /* randomize the list to not always use the same proxies */ priv->socks5_potential_proxies = randomize_g_slist ( priv->socks5_potential_proxies); priv->next_query = priv->socks5_potential_proxies; g_strfreev (jids); } } static GObject * gabble_bytestream_factory_constructor (GType type, guint n_props, GObjectConstructParam *props) { GObject *obj; GabbleBytestreamFactory *self; GabbleBytestreamFactoryPrivate *priv; obj = G_OBJECT_CLASS (gabble_bytestream_factory_parent_class)-> constructor (type, n_props, props); self = GABBLE_BYTESTREAM_FACTORY (obj); priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (self); /* Track SOCKS5 proxy available on the connection */ gabble_signal_connect_weak (priv->conn->disco, "item-found", G_CALLBACK (disco_item_found_cb), G_OBJECT (self)); gabble_signal_connect_weak (priv->conn, "status-changed", G_CALLBACK (conn_status_changed_cb), G_OBJECT (self)); tp_g_signal_connect_object (priv->conn, "porter-available", G_CALLBACK (porter_available_cb), self, 0); return obj; } static void gabble_bytestream_factory_dispose (GObject *object) { GabbleBytestreamFactory *self = GABBLE_BYTESTREAM_FACTORY (object); GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (self); GSList *proxies, *l; if (priv->dispose_has_run) return; DEBUG ("dispose called"); priv->dispose_has_run = TRUE; if (priv->msg_data_cb != 0) { WockyPorter *porter = wocky_session_get_porter (priv->conn->session); wocky_porter_unregister_handler (porter, priv->msg_data_cb); wocky_porter_unregister_handler (porter, priv->iq_si_cb); wocky_porter_unregister_handler (porter, priv->iq_ibb_cb); wocky_porter_unregister_handler (porter, priv->iq_socks5_cb); } g_hash_table_unref (priv->ibb_bytestreams); priv->ibb_bytestreams = NULL; g_hash_table_unref (priv->muc_bytestreams); priv->muc_bytestreams = NULL; g_hash_table_unref (priv->socks5_bytestreams); priv->socks5_bytestreams = NULL; g_hash_table_unref (priv->multiple_bytestreams); priv->multiple_bytestreams = NULL; proxies = g_slist_concat (priv->socks5_proxies, priv->socks5_fallback_proxies); for (l = proxies; l != NULL; l = g_slist_next (l)) { GabbleSocks5Proxy *proxy = (GabbleSocks5Proxy *) l->data; gabble_socks5_proxy_free (proxy); } g_slist_free (proxies); priv->socks5_proxies = NULL; priv->socks5_fallback_proxies = NULL; g_slist_foreach (priv->socks5_potential_proxies, (GFunc) g_free, NULL); g_slist_free (priv->socks5_potential_proxies); priv->socks5_potential_proxies = NULL; if (G_OBJECT_CLASS (gabble_bytestream_factory_parent_class)->dispose) G_OBJECT_CLASS (gabble_bytestream_factory_parent_class)->dispose (object); } static void gabble_bytestream_factory_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleBytestreamFactory *self = GABBLE_BYTESTREAM_FACTORY (object); GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (self); switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, priv->conn); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_bytestream_factory_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleBytestreamFactory *self = GABBLE_BYTESTREAM_FACTORY (object); GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (self); switch (property_id) { case PROP_CONNECTION: priv->conn = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_bytestream_factory_class_init ( GabbleBytestreamFactoryClass *gabble_bytestream_factory_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_bytestream_factory_class); GParamSpec *param_spec; g_type_class_add_private (gabble_bytestream_factory_class, sizeof (GabbleBytestreamFactoryPrivate)); object_class->constructor = gabble_bytestream_factory_constructor; object_class->dispose = gabble_bytestream_factory_dispose; object_class->get_property = gabble_bytestream_factory_get_property; object_class->set_property = gabble_bytestream_factory_set_property; param_spec = g_param_spec_object ( "connection", "GabbleConnection object", "Gabble connection object that owns this bytestream factory object.", GABBLE_TYPE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); } static void remove_bytestream (GabbleBytestreamFactory *self, GabbleBytestreamIface *bytestream) { GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (self); BytestreamIdentifier bsid = { NULL, NULL }; guint handle_type; GHashTable *table = NULL; g_object_get (bytestream, "stream-id", &(bsid.stream), "peer-jid", &(bsid.jid), "peer-handle-type", &handle_type, NULL); if (handle_type == TP_HANDLE_TYPE_ROOM) { table = priv->muc_bytestreams; } else { if (GABBLE_IS_BYTESTREAM_IBB (bytestream)) table = priv->ibb_bytestreams; else if (GABBLE_IS_BYTESTREAM_SOCKS5 (bytestream)) table = priv->socks5_bytestreams; else if (GABBLE_IS_BYTESTREAM_MULTIPLE (bytestream)) table = priv->multiple_bytestreams; } if (table == NULL) return; DEBUG ("removing bytestream: <%s> from <%s>", bsid.stream, bsid.jid); g_hash_table_remove (table, &bsid); g_free (bsid.stream); g_free (bsid.jid); } /** * streaminit_parse_request * * Parses a SI request, or returns FALSE if it can't be parsed. * * The items in the linked list of stream methods are borrowed * from the message; their lifetime is only as long as that of the * message. */ static gboolean streaminit_parse_request (WockyStanza *message, WockyNode *si, const gchar **profile, const gchar **from, const gchar **stream_id, const gchar **stream_init_id, const gchar **mime_type, GSList **stream_methods, gboolean *multiple) { WockyNode *iq = wocky_stanza_get_top_node (message); WockyNode *feature, *x, *si_multiple, *field; WockyNodeIter i, j; *stream_init_id = wocky_node_get_attribute (iq, "id"); *from = wocky_node_get_attribute (iq, "from"); if (*from == NULL) { STANZA_DEBUG (message, "got a message without a from field"); return FALSE; } /* Parse */ *stream_id = wocky_node_get_attribute (si, "id"); if (*stream_id == NULL) { STANZA_DEBUG (message, "got a SI request without a stream id field"); return FALSE; } *mime_type = wocky_node_get_attribute (si, "mime-type"); /* if no mime_type is defined, XEP-0095 says to assume "binary/octect-stream" * which is presumably a typo for "application/octet-stream" */ *profile = wocky_node_get_attribute (si, "profile"); if (*profile == NULL) { STANZA_DEBUG (message, "got a SI request without a profile field"); return FALSE; } /* Parse */ feature = wocky_node_get_child_ns (si, "feature", NS_FEATURENEG); if (feature == NULL) { STANZA_DEBUG (message, "got a SI request without a feature field"); return FALSE; } x = wocky_node_get_child_ns (feature, "x", NS_X_DATA); if (x == NULL) { STANZA_DEBUG (message, "got a SI request without a X data field"); return FALSE; } wocky_node_iter_init (&i, x, NULL, NULL); while (wocky_node_iter_next (&i, &field)) { WockyNode *stream_method; if (tp_strdiff (wocky_node_get_attribute (field, "var"), "stream-method")) /* some future field, ignore it */ continue; if (tp_strdiff (wocky_node_get_attribute (field, "type"), "list-single")) { STANZA_DEBUG (message, "SI request's stream-method field was " "not of type list-single"); return FALSE; } /* Get the stream methods offered */ *stream_methods = NULL; wocky_node_iter_init (&j, field, NULL, NULL); while (wocky_node_iter_next (&j, &stream_method)) { WockyNode *value; const gchar *stream_method_str; value = wocky_node_get_child (stream_method, "value"); if (value == NULL) continue; stream_method_str = value->content; if (!tp_strdiff (stream_method_str, "")) continue; DEBUG ("Got stream-method %s", stream_method_str); /* Append to the stream_methods list */ *stream_methods = g_slist_append (*stream_methods, (gchar *) stream_method_str); } /* no need to parse the rest of the fields, we've found the one we * wanted */ break; } if (*stream_methods == NULL) { STANZA_DEBUG (message, "got a SI request without stream method proposed"); return FALSE; } si_multiple = wocky_node_get_child_ns (si, "si-multiple", NS_SI_MULTIPLE); if (si_multiple == NULL) *multiple = FALSE; else *multiple = TRUE; return TRUE; } /** * gabble_bytestream_factory_make_stream_init_iq * * @full_jid: the full jid of the contact to whom we want to offer the stream * @stream_id: the stream ID of the new stream * @profile: the profile associated with the stream * * Create a SI request IQ as described in XEP-0095. * * The MIME type is not set - the receiving client will assume * application/octet-stream unless the caller sets a MIME type explicitly. */ WockyStanza * gabble_bytestream_factory_make_stream_init_iq (const gchar *full_jid, const gchar *stream_id, const gchar *profile) { return wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, full_jid, '(', "si", ':', NS_SI, '@', "id", stream_id, '@', "profile", profile, '(', "feature", ':', NS_FEATURENEG, '(', "x", ':', NS_X_DATA, '@', "type", "form", '(', "field", '@', "var", "stream-method", '@', "type", "list-single", '(', "option", '(', "value", '$', NS_BYTESTREAMS, ')', ')', '(', "option", '(', "value", '$', NS_IBB, ')', ')', ')', ')', ')', '(', "si-multiple", ':', NS_SI_MULTIPLE, ')', ')', NULL); } static gboolean stream_method_supported (const gchar *stream_method) { /* IBB */ if (!tp_strdiff (stream_method, NS_IBB)) return TRUE; /* Sock5 */ if (!tp_strdiff (stream_method, NS_BYTESTREAMS)) return TRUE; return FALSE; } static GabbleBytestreamMultiple *gabble_bytestream_factory_create_multiple ( GabbleBytestreamFactory *self, TpHandle peer_handle, const gchar *stream_id, const gchar *stream_init_id, const gchar *peer_resource, const gchar *self_jid, GabbleBytestreamState state); static GabbleBytestreamIBB *gabble_bytestream_factory_create_ibb ( GabbleBytestreamFactory *fac, TpHandle peer_handle, const gchar *stream_id, const gchar *stream_init_id, const gchar *peer_resource, GabbleBytestreamState state); static GabbleBytestreamSocks5 *gabble_bytestream_factory_create_socks5 ( GabbleBytestreamFactory *fac, TpHandle peer_handle, const gchar *stream_id, const gchar *stream_init_id, const gchar *peer_resource, const gchar *self_jid, GabbleBytestreamState state); static void si_tube_received (GabbleBytestreamFactory *self, WockyStanza *msg, WockyNode *si, GabbleBytestreamIface *bytestream, TpHandle peer_handle, TpHandle room_handle, const gchar *stream_id) { GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (self); /* A Tubes SI request can be: * - a 1-1 new tube offer * - a 1-1 tube extra bytestream offer * - a muc tube extra bytestream offer */ if (wocky_node_get_child_ns (si, "tube", NS_TUBES) != NULL) { /* The SI request is a tube offer */ gabble_private_tubes_factory_handle_si_tube_request ( priv->conn->private_tubes_factory, bytestream, peer_handle, stream_id, msg); } else if (wocky_node_get_child_ns (si, "stream", NS_TUBES) != NULL) { /* The SI request is an extra bytestream for a 1-1 tube */ gabble_private_tubes_factory_handle_si_stream_request ( priv->conn->private_tubes_factory, bytestream, peer_handle, stream_id, msg); } else if (wocky_node_get_child_ns (si, "muc-stream", NS_TUBES) != NULL) { /* The SI request is an extra bytestream for a muc tube */ if (room_handle == 0) { GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, " is only valid in a MUC context" }; gabble_bytestream_iface_close (bytestream, &e); } else { gabble_muc_factory_handle_si_stream_request (priv->conn->muc_factory, bytestream, room_handle, stream_id, msg); } } else { GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, "Invalid tube SI request: expected , or " "" }; /* Invalid tube SI request */ STANZA_DEBUG (msg, e.message); gabble_bytestream_iface_close (bytestream, &e); } } /** * bytestream_factory_iq_si_cb: * * Called by Wocky when we get an incoming . This handler is concerned * with Stream Initiation requests (XEP-0095). * */ static gboolean bytestream_factory_iq_si_cb ( WockyPorter *porter, WockyStanza *msg, gpointer user_data) { GabbleBytestreamFactory *self = GABBLE_BYTESTREAM_FACTORY (user_data); GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (self); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_ROOM); WockyNode *si; TpHandle peer_handle = 0, room_handle; GabbleBytestreamIface *bytestream = NULL; GSList *l; const gchar *profile, *from, *stream_id, *stream_init_id, *mime_type; GSList *stream_methods = NULL; gboolean multiple; gchar *peer_resource = NULL; gchar *self_jid = NULL; si = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "si", NS_SI); g_return_val_if_fail (si != NULL, FALSE); /* after this point, the message is for us, so in all cases we either handle * it or send an error reply */ if (!streaminit_parse_request (msg, si, &profile, &from, &stream_id, &stream_init_id, &mime_type, &stream_methods, &multiple)) { wocky_porter_send_iq_error (porter, msg, WOCKY_XMPP_ERROR_BAD_REQUEST, "failed to parse SI request"); goto out; } DEBUG ("received a SI request"); room_handle = gabble_get_room_handle_from_jid (room_repo, from); if (room_handle == 0) { /* jid is not a muc jid so we need contact's resource */ if (!wocky_decode_jid (from, NULL, NULL, &peer_resource)) { DEBUG ("Got an SI IQ response from a bad JID. Ignoring."); goto out; } if (!peer_resource) { DEBUG ("Got an SI IQ response from a JID without a resource." "Ignoring."); goto out; } peer_handle = tp_handle_ensure (contact_repo, from, NULL, NULL); /* we are not in a muc so our own jid is the one in the 'to' attribute */ self_jid = g_strdup (wocky_node_get_attribute ( wocky_stanza_get_top_node (msg), "to")); } else { /* we are in a muc so need to get our muc jid */ GabbleMucChannel *muc; peer_handle = tp_handle_ensure (contact_repo, from, GUINT_TO_POINTER (GABBLE_JID_ROOM_MEMBER), NULL); muc = gabble_muc_factory_find_text_channel (priv->conn->muc_factory, room_handle); if (muc == NULL) { DEBUG ("Got an IQ from a muc in which we are not. Ignoring."); goto out; } g_object_get (muc, "self-jid", &self_jid, NULL); } if (peer_handle == 0) { wocky_porter_send_iq_error (porter, msg, WOCKY_XMPP_ERROR_JID_MALFORMED, NULL); goto out; } if (multiple) { DEBUG ("Receiver supports multi bytestreams"); bytestream = (GabbleBytestreamIface *) gabble_bytestream_factory_create_multiple (self, peer_handle, stream_id, stream_init_id, peer_resource, self_jid, GABBLE_BYTESTREAM_STATE_LOCAL_PENDING); } /* check stream method */ for (l = stream_methods; l != NULL; l = l->next) { if (multiple) { if (stream_method_supported (l->data)) { DEBUG ("add %s to multi-bytestream methods", (const gchar *) l->data); gabble_bytestream_multiple_add_stream_method ( GABBLE_BYTESTREAM_MULTIPLE (bytestream), l->data); } else { DEBUG ("skip unsupported stream method: %s", (const gchar *) l->data); } } else { /* We create the stream according the stream method chosen. * User has to accept it */ DEBUG ("Receiver doesn't support multi bytestreams. He chose %s", (const gchar *) l->data); bytestream = gabble_bytestream_factory_create_from_method (self, l->data, peer_handle, stream_id, stream_init_id, peer_resource, self_jid, GABBLE_BYTESTREAM_STATE_LOCAL_PENDING); if (bytestream != NULL) break; } } if (bytestream == NULL) { GError error = { WOCKY_SI_ERROR, WOCKY_SI_ERROR_NO_VALID_STREAMS, "" }; DEBUG ("SI request doesn't contain any supported stream methods."); wocky_porter_send_iq_gerror (porter, msg, &error); goto out; } if (multiple) { /* Is there at least one stream method? */ if (!gabble_bytestream_multiple_has_stream_method ( GABBLE_BYTESTREAM_MULTIPLE (bytestream))) { GError e = { WOCKY_SI_ERROR, WOCKY_SI_ERROR_NO_VALID_STREAMS, "" }; DEBUG ("No valid stream method in the multi bytestream. Closing"); gabble_bytestream_iface_close (bytestream, &e); goto out; } } /* Now that we have a bytestream, it's responsible for declining the IQ * if needed. */ /* We inform the right factory we received a SI request */ if (!tp_strdiff (profile, NS_TUBES)) { si_tube_received (self, msg, si, bytestream, peer_handle, room_handle, stream_id); } #ifdef ENABLE_FILE_TRANSFER else if (!tp_strdiff (profile, NS_FILE_TRANSFER)) { gabble_ft_manager_handle_si_request (priv->conn->ft_manager, bytestream, peer_handle, stream_id, msg); } #endif else { GError e = { WOCKY_SI_ERROR, WOCKY_SI_ERROR_BAD_PROFILE, "" }; DEBUG ("SI profile unsupported: %s", profile); gabble_bytestream_iface_close (bytestream, &e); } out: g_slist_free (stream_methods); g_free (peer_resource); g_free (self_jid); return TRUE; } static gboolean handle_ibb_open_iq (GabbleBytestreamFactory *self, WockyStanza *msg) { GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (self); WockyPorter *porter = wocky_session_get_porter (priv->conn->session); GabbleBytestreamIBB *bytestream; WockyNode *open_node; ConstBytestreamIdentifier bsid = { NULL, NULL }; const gchar *tmp; guint state; WockyStanzaSubType sub_type; wocky_stanza_get_type_info (msg, NULL, &sub_type); if (sub_type != WOCKY_STANZA_SUB_TYPE_SET) return FALSE; open_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "open", NS_IBB); if (open_node == NULL) return FALSE; bsid.jid = wocky_node_get_attribute ( wocky_stanza_get_top_node (msg), "from"); if (bsid.jid == NULL) { DEBUG ("got a message without a from field"); wocky_porter_send_iq_error (porter, msg, WOCKY_XMPP_ERROR_BAD_REQUEST, NULL); return TRUE; } bsid.stream = wocky_node_get_attribute (open_node, "sid"); if (bsid.stream == NULL) { DEBUG ("IBB open stanza doesn't contain stream id"); wocky_porter_send_iq_error (porter, msg, WOCKY_XMPP_ERROR_BAD_REQUEST, NULL); return TRUE; } bytestream = g_hash_table_lookup (priv->ibb_bytestreams, &bsid); if (bytestream == NULL) { /* We don't accept streams not previously announced using SI */ DEBUG ("unknown stream: <%s> from <%s>", bsid.stream, bsid.jid); wocky_porter_send_iq_error (porter, msg, WOCKY_XMPP_ERROR_BAD_REQUEST, NULL); return TRUE; } g_object_get (bytestream, "state", &state, NULL); if (state != GABBLE_BYTESTREAM_STATE_ACCEPTED) { /* We don't accept streams not previously accepted using SI */ DEBUG ("unaccepted stream: <%s> from <%s>", bsid.stream, bsid.jid); wocky_porter_send_iq_error (porter, msg, WOCKY_XMPP_ERROR_BAD_REQUEST, NULL); return TRUE; } tmp = wocky_node_get_attribute (open_node, "block-size"); if (tmp != NULL) { guint block_size = strtoul (tmp, NULL, 10); if (block_size > 0) g_object_set (bytestream, "block-size", block_size, NULL); } g_object_set (bytestream, "state", GABBLE_BYTESTREAM_STATE_OPEN, NULL); wocky_porter_acknowledge_iq (porter, msg, NULL); return TRUE; } static gboolean handle_ibb_close_iq (GabbleBytestreamFactory *self, WockyStanza *msg) { GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (self); WockyPorter *porter = wocky_session_get_porter (priv->conn->session); ConstBytestreamIdentifier bsid = { NULL, NULL }; GabbleBytestreamIBB *bytestream; WockyNode *close_node; WockyStanzaSubType sub_type; wocky_stanza_get_type_info (msg, NULL, &sub_type); if (sub_type != WOCKY_STANZA_SUB_TYPE_SET) return FALSE; close_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "close", NS_IBB); if (close_node == NULL) return FALSE; bsid.jid = wocky_node_get_attribute (wocky_stanza_get_top_node (msg), "from"); if (bsid.jid == NULL) { DEBUG ("got a message without a from field"); wocky_porter_send_iq_error (porter, msg, WOCKY_XMPP_ERROR_BAD_REQUEST, "IBB has no 'from' attribute"); return TRUE; } bsid.stream = wocky_node_get_attribute (close_node, "sid"); if (bsid.stream == NULL) { DEBUG ("IBB close stanza doesn't contain stream id"); wocky_porter_send_iq_error (porter, msg, WOCKY_XMPP_ERROR_BAD_REQUEST, "IBB has no stream ID"); return TRUE; } bytestream = g_hash_table_lookup (priv->ibb_bytestreams, &bsid); if (bytestream == NULL) { DEBUG ("unknown stream: <%s> from <%s>", bsid.stream, bsid.jid); wocky_porter_send_iq_error (porter, msg, WOCKY_XMPP_ERROR_ITEM_NOT_FOUND, NULL); } else { gabble_bytestream_ibb_close_received (bytestream, msg); } return TRUE; } /* IBB can be transported over either IQs or messages, so msg can either be * an or a . If it's an we need to reply to it. * * Return TRUE if we take responsibility for this message. */ static gboolean handle_ibb_data (GabbleBytestreamFactory *self, WockyStanza *msg, gboolean is_iq) { GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (self); WockyPorter *porter = wocky_session_get_porter (priv->conn->session); GabbleBytestreamIBB *bytestream = NULL; WockyNode *data; ConstBytestreamIdentifier bsid = { NULL, NULL }; WockyStanzaSubType sub_type; priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (self); wocky_stanza_get_type_info (msg, NULL, &sub_type); if (is_iq && sub_type != WOCKY_STANZA_SUB_TYPE_SET) return FALSE; data = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "data", NS_IBB); if (data == NULL) return FALSE; bsid.jid = wocky_node_get_attribute (wocky_stanza_get_top_node (msg), "from"); if (bsid.jid == NULL) { DEBUG ("got a message without a from field"); if (is_iq) wocky_porter_send_iq_error (porter, msg, WOCKY_XMPP_ERROR_BAD_REQUEST, "IBB has no 'from' attribute"); return TRUE; } bsid.stream = wocky_node_get_attribute (data, "sid"); if (bsid.stream == NULL) { DEBUG ("got a IBB message data without a stream id field"); if (is_iq) wocky_porter_send_iq_error (porter, msg, WOCKY_XMPP_ERROR_BAD_REQUEST, "IBB needs a stream ID"); return TRUE; } bytestream = g_hash_table_lookup (priv->ibb_bytestreams, &bsid); if (bytestream == NULL) { DEBUG ("unknown stream: <%s> from <%s>", bsid.stream, bsid.jid); if (is_iq) wocky_porter_send_iq_error (porter, msg, WOCKY_XMPP_ERROR_BAD_REQUEST, "IBB has unknown stream ID"); return TRUE; } gabble_bytestream_ibb_receive (bytestream, msg, is_iq); return TRUE; } static gboolean handle_muc_data (GabbleBytestreamFactory *self, WockyStanza *msg) { GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (self); GabbleBytestreamMuc *bytestream = NULL; WockyNode *data; ConstBytestreamIdentifier bsid = { NULL, NULL }; gchar *room_name; const gchar *from; priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (self); data = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "data", NS_MUC_BYTESTREAM); if (data == NULL) return FALSE; from = wocky_node_get_attribute ( wocky_stanza_get_top_node (msg), "from"); if (from == NULL) { DEBUG ("got a message without a from field"); return TRUE; } bsid.stream = wocky_node_get_attribute (data, "sid"); if (bsid.stream == NULL) { DEBUG ("got a pseudo IBB muc message data without a stream id field"); return TRUE; } room_name = gabble_remove_resource (from); bsid.jid = room_name; bytestream = g_hash_table_lookup (priv->muc_bytestreams, &bsid); if (bytestream == NULL) { DEBUG ("unknown muc stream: <%s> from <%s>", bsid.stream, bsid.jid); g_free (room_name); return TRUE; } g_assert (GABBLE_IS_BYTESTREAM_MUC (bytestream)); gabble_bytestream_muc_receive (bytestream, msg); g_free (room_name); return TRUE; } /** * bytestream_factory_iq_ibb_cb: * * Called by Wocky when we get an incoming . * This handler is concerned with IBB iq's. * */ static gboolean bytestream_factory_iq_ibb_cb ( WockyPorter *porter, WockyStanza *msg, gpointer user_data) { GabbleBytestreamFactory *self = GABBLE_BYTESTREAM_FACTORY (user_data); if (handle_ibb_open_iq (self, msg)) return TRUE; if (handle_ibb_close_iq (self, msg)) return TRUE; if (handle_ibb_data (self, msg, TRUE)) return TRUE; return FALSE; } /** * bytestream_factory_msg_data_cb * * Called by Wocky when we get an incoming . * This handler handles IBB data and pseudo IBB Muc data. */ static gboolean bytestream_factory_msg_data_cb ( WockyPorter *porter, WockyStanza *msg, gpointer user_data) { GabbleBytestreamFactory *self = user_data; if (handle_ibb_data (self, msg, FALSE)) return TRUE; if (handle_muc_data (self, msg)) return TRUE; return FALSE; } static gboolean handle_socks5_query_iq ( WockyPorter *porter, WockyStanza *msg, gpointer user_data) { GabbleBytestreamFactory *self = GABBLE_BYTESTREAM_FACTORY (user_data); GabbleBytestreamFactoryPrivate *priv = self->priv; GabbleBytestreamSocks5 *bytestream; WockyNode *query_node, *child_node; ConstBytestreamIdentifier bsid = { NULL, NULL }; const gchar *tmp; WockyNodeIter i; query_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "query", NS_BYTESTREAMS); g_return_val_if_fail (query_node != NULL, FALSE); bsid.jid = wocky_node_get_attribute ( wocky_stanza_get_top_node (msg), "from"); if (bsid.jid == NULL) { DEBUG ("got a message without a from field"); wocky_porter_send_iq_error (porter, msg, WOCKY_XMPP_ERROR_BAD_REQUEST, "SOCKS5 has no 'from' attribute"); return TRUE; } bsid.stream = wocky_node_get_attribute (query_node, "sid"); if (bsid.stream == NULL) { DEBUG ("SOCKS5 query stanza doesn't contain stream id"); wocky_porter_send_iq_error (porter, msg, WOCKY_XMPP_ERROR_BAD_REQUEST, "SOCKS5 has no stream ID"); return TRUE; } bytestream = g_hash_table_lookup (priv->socks5_bytestreams, &bsid); if (bytestream == NULL) { /* We don't accept streams not previously announced using SI */ DEBUG ("unknown stream: <%s> from <%s>", bsid.stream, bsid.jid); wocky_porter_send_iq_error (porter, msg, WOCKY_XMPP_ERROR_ITEM_NOT_FOUND, "SOCKS5 has an unknown stream ID"); return TRUE; } tmp = wocky_node_get_attribute (query_node, "mode"); /* If this attribute is missing, the default value of "tcp" MUST be assumed */ if (tmp != NULL && tp_strdiff (tmp, "tcp")) { DEBUG ("non-TCP SOCKS5 bytestreams are not supported"); wocky_porter_send_iq_error (porter, msg, WOCKY_XMPP_ERROR_BAD_REQUEST, "SOCKS5 non-TCP bytestreams are not supported"); return TRUE; } wocky_node_iter_init (&i, query_node, "streamhost", NULL); while (wocky_node_iter_next (&i, &child_node)) { gabble_bytestream_socks5_add_streamhost (bytestream, child_node); } gabble_bytestream_socks5_connect_to_streamhost (bytestream, msg); return TRUE; } GabbleBytestreamFactory * gabble_bytestream_factory_new (GabbleConnection *conn) { GabbleBytestreamFactory *factory; g_return_val_if_fail (GABBLE_IS_CONNECTION (conn), NULL); factory = GABBLE_BYTESTREAM_FACTORY ( g_object_new (GABBLE_TYPE_BYTESTREAM_FACTORY, "connection", conn, NULL)); return factory; } static void bytestream_state_changed_cb (GabbleBytestreamIface *bytestream, GabbleBytestreamState state, gpointer user_data) { GabbleBytestreamFactory *self = GABBLE_BYTESTREAM_FACTORY (user_data); GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE ( self); if (priv->dispose_has_run) return; if (state == GABBLE_BYTESTREAM_STATE_CLOSED) { remove_bytestream (self, bytestream); } } gchar * gabble_bytestream_factory_generate_stream_id (void) { gchar *stream_id; stream_id = g_strdup_printf ("%lu-%u", (unsigned long) time (NULL), g_random_int ()); return stream_id; } GabbleBytestreamIface * gabble_bytestream_factory_create_from_method (GabbleBytestreamFactory *self, const gchar *stream_method, TpHandle peer_handle, const gchar *stream_id, const gchar *stream_init_id, const gchar *peer_resource, const gchar *self_jid, GabbleBytestreamState state) { GabbleBytestreamIface *bytestream = NULL; if (!tp_strdiff (stream_method, NS_IBB)) { bytestream = GABBLE_BYTESTREAM_IFACE ( gabble_bytestream_factory_create_ibb (self, peer_handle, stream_id, stream_init_id, peer_resource, state)); } else if (!tp_strdiff (stream_method, NS_BYTESTREAMS)) { bytestream = GABBLE_BYTESTREAM_IFACE ( gabble_bytestream_factory_create_socks5 (self, peer_handle, stream_id, stream_init_id, peer_resource, self_jid, state)); } return bytestream; } static GabbleBytestreamIBB * gabble_bytestream_factory_create_ibb (GabbleBytestreamFactory *self, TpHandle peer_handle, const gchar *stream_id, const gchar *stream_init_id, const gchar *peer_resource, GabbleBytestreamState state) { GabbleBytestreamFactoryPrivate *priv; GabbleBytestreamIBB *ibb; BytestreamIdentifier *id; g_return_val_if_fail (GABBLE_IS_BYTESTREAM_FACTORY (self), NULL); priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (self); ibb = g_object_new (GABBLE_TYPE_BYTESTREAM_IBB, "connection", priv->conn, "peer-handle", peer_handle, "stream-id", stream_id, "state", state, "stream-init-id", stream_init_id, "peer-resource", peer_resource, NULL); gabble_signal_connect_weak (ibb, "state-changed", G_CALLBACK (bytestream_state_changed_cb), G_OBJECT (self)); id = bytestream_id_new (GABBLE_BYTESTREAM_IFACE (ibb)); DEBUG ("add IBB bytestream <%s> from <%s>", id->stream, id->jid); g_hash_table_insert (priv->ibb_bytestreams, id, ibb); return ibb; } GabbleBytestreamMuc * gabble_bytestream_factory_create_muc (GabbleBytestreamFactory *self, TpHandle peer_handle, const gchar *stream_id, GabbleBytestreamState state) { GabbleBytestreamFactoryPrivate *priv; GabbleBytestreamMuc *bytestream; BytestreamIdentifier *id; g_return_val_if_fail (GABBLE_IS_BYTESTREAM_FACTORY (self), NULL); priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (self); bytestream = g_object_new (GABBLE_TYPE_BYTESTREAM_MUC, "connection", priv->conn, "peer-handle", peer_handle, "stream-id", stream_id, "state", state, NULL); gabble_signal_connect_weak (bytestream, "state-changed", G_CALLBACK (bytestream_state_changed_cb), G_OBJECT (self)); id = bytestream_id_new (GABBLE_BYTESTREAM_IFACE (bytestream)); DEBUG ("add muc bytestream <%s> from <%s>", id->stream, id->jid); g_hash_table_insert (priv->muc_bytestreams, id, bytestream); return bytestream; } static GabbleBytestreamSocks5 * gabble_bytestream_factory_create_socks5 (GabbleBytestreamFactory *self, TpHandle peer_handle, const gchar *stream_id, const gchar *stream_init_id, const gchar *peer_resource, const gchar *self_jid, GabbleBytestreamState state) { GabbleBytestreamFactoryPrivate *priv; GabbleBytestreamSocks5 *socks5; BytestreamIdentifier *id; g_return_val_if_fail (GABBLE_IS_BYTESTREAM_FACTORY (self), NULL); priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (self); socks5 = g_object_new (GABBLE_TYPE_BYTESTREAM_SOCKS5, "connection", priv->conn, "peer-handle", peer_handle, "stream-id", stream_id, "state", state, "stream-init-id", stream_init_id, "peer-resource", peer_resource, "self-jid", self_jid, NULL); gabble_signal_connect_weak (socks5, "state-changed", G_CALLBACK (bytestream_state_changed_cb), G_OBJECT (self)); id = bytestream_id_new (GABBLE_BYTESTREAM_IFACE (socks5)); DEBUG ("add SOCKS5 bytestream <%s> from <%s>", id->stream, id->jid); g_hash_table_insert (priv->socks5_bytestreams, id, socks5); return socks5; } static GabbleBytestreamMultiple * gabble_bytestream_factory_create_multiple (GabbleBytestreamFactory *self, TpHandle peer_handle, const gchar *stream_id, const gchar *stream_init_id, const gchar *peer_resource, const gchar *self_jid, GabbleBytestreamState state) { GabbleBytestreamFactoryPrivate *priv; GabbleBytestreamMultiple *multiple; BytestreamIdentifier *id; g_return_val_if_fail (GABBLE_IS_BYTESTREAM_FACTORY (self), NULL); priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (self); multiple = g_object_new (GABBLE_TYPE_BYTESTREAM_MULTIPLE, "connection", priv->conn, "peer-handle", peer_handle, "stream-id", stream_id, "state", state, "stream-init-id", stream_init_id, "peer-resource", peer_resource, "factory", self, "self-jid", self_jid, NULL); gabble_signal_connect_weak (multiple, "state-changed", G_CALLBACK (bytestream_state_changed_cb), G_OBJECT (self)); id = bytestream_id_new (GABBLE_BYTESTREAM_IFACE (multiple)); DEBUG ("add multi bytestream <%s> from <%s>", id->stream, id->jid); g_hash_table_insert (priv->multiple_bytestreams, id, multiple); return multiple; } static GabbleBytestreamIface * streaminit_get_multiple_bytestream (GabbleBytestreamFactory *self, WockyStanza *reply_msg, WockyNode *si, const gchar *stream_id, TpHandle peer_handle, const gchar *peer_resource, const gchar *self_jid) { /* If the other client supports si-multiple we have directly a list of * supported methods inside tags */ WockyNode *si_multi; const gchar *stream_method; GabbleBytestreamMultiple *bytestream = NULL; WockyNode *value; WockyNodeIter i; si_multi = wocky_node_get_child_ns (si, "si-multiple", NS_SI_MULTIPLE); if (si_multi == NULL) return NULL; bytestream = gabble_bytestream_factory_create_multiple (self, peer_handle, stream_id, NULL, peer_resource, self_jid, GABBLE_BYTESTREAM_STATE_INITIATING); wocky_node_iter_init (&i, si_multi, "value", NULL); while (wocky_node_iter_next (&i, &value)) { stream_method = value->content; if (!stream_method_supported (stream_method)) { DEBUG ("got a si-multiple reply with an unsupported " "stream method: %s", stream_method); continue; } gabble_bytestream_multiple_add_stream_method (bytestream, stream_method); } return GABBLE_BYTESTREAM_IFACE (bytestream); } static GabbleBytestreamIface * streaminit_get_bytestream (GabbleBytestreamFactory *self, WockyStanza *reply_msg, WockyNode *si, const gchar *stream_id, TpHandle peer_handle, const gchar *peer_resource, const gchar *self_jid) { WockyNode *feature, *x, *value, *field; GabbleBytestreamIface *bytestream = NULL; const gchar *stream_method; WockyNodeIter i; feature = wocky_node_get_child_ns (si, "feature", NS_FEATURENEG); if (feature == NULL) { STANZA_DEBUG (reply_msg, "got a SI reply without a feature field"); return NULL; } x = wocky_node_get_child_ns (feature, "x", NS_X_DATA); if (x == NULL) { STANZA_DEBUG (reply_msg, "got a SI reply without a x field"); return NULL; } wocky_node_iter_init (&i, x, NULL, NULL); while (wocky_node_iter_next (&i, &field)) { if (tp_strdiff (wocky_node_get_attribute (field, "var"), "stream-method")) /* some future field, ignore it */ continue; value = wocky_node_get_child (field, "value"); if (value == NULL) { STANZA_DEBUG (reply_msg, "SI reply's stream-method field " "doesn't contain stream-method value"); return NULL; } stream_method = value->content; bytestream = gabble_bytestream_factory_create_from_method (self, stream_method, peer_handle, stream_id, NULL, peer_resource, self_jid, GABBLE_BYTESTREAM_STATE_INITIATING); /* no need to parse the rest of the fields, we've found the one we * wanted */ break; } return bytestream; } struct _streaminit_reply_cb_data { GabbleBytestreamFactory *self; gchar *stream_id; GabbleBytestreamFactoryNegotiateReplyFunc func; TpWeakRef *weak_object; }; /* Called when we receive the reply of a SI request */ static void streaminit_reply_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { GabbleConnection *conn = GABBLE_CONNECTION (source); struct _streaminit_reply_cb_data *data = user_data; GabbleBytestreamFactory *self = data->self; GabbleBytestreamFactoryPrivate *priv = self->priv; GabbleBytestreamIface *bytestream = NULL; gchar *peer_resource = NULL; WockyNode *si; const gchar *from; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_ROOM); TpHandle peer_handle = 0; TpHandle room_handle; gboolean success = FALSE; gchar *self_jid = NULL; GObject *object = tp_weak_ref_dup_object (data->weak_object); WockyStanza *reply_msg = NULL; if (object == NULL) { DEBUG ("Object which requested the bytestream was disposed. Ignoring"); goto END; } if (!conn_util_send_iq_finish (conn, result, &reply_msg, NULL)) { DEBUG ("stream %s declined", data->stream_id); goto END; } /* stream accepted */ from = wocky_node_get_attribute ( wocky_stanza_get_top_node (reply_msg), "from"); if (from == NULL) { STANZA_DEBUG (reply_msg, "got a message without a from field"); goto END; } peer_handle = tp_handle_ensure (contact_repo, from, NULL, NULL); room_handle = gabble_get_room_handle_from_jid (room_repo, from); if (room_handle == 0) { /* jid is not a muc jid so we need contact's resource */ if (!wocky_decode_jid (from, NULL, NULL, &peer_resource)) { DEBUG ("Got an SI request with a bad JID"); goto END; } if (peer_resource == NULL) { DEBUG ("Got an SI request from a JID without a resource; ignoring"); goto END; } /* we are not in a muc so our own jid is the one in the 'to' attribute */ self_jid = g_strdup (wocky_node_get_attribute ( wocky_stanza_get_top_node (reply_msg), "to")); } else { /* we are in a muc so need to get our muc jid */ GabbleMucChannel *muc; muc = gabble_muc_factory_find_text_channel (priv->conn->muc_factory, room_handle); if (muc == NULL) { DEBUG ("Got an IQ from a muc in which we are not. Ignoring"); goto END; } g_object_get (muc, "self-jid", &self_jid, NULL); } si = wocky_node_get_child_ns ( wocky_stanza_get_top_node (reply_msg), "si", NS_SI); if (si == NULL) { STANZA_DEBUG (reply_msg, "got a SI reply without a si field"); goto END; } /* Try to build a multiple bytestream with fallback methods */ bytestream = streaminit_get_multiple_bytestream (self, reply_msg, si, data->stream_id, peer_handle, peer_resource, self_jid); /* FIXME: check if there is at least one stream method */ if (bytestream == NULL) /* The other client doesn't suppport si-multiple, use the normal XEP-095 * method */ bytestream = streaminit_get_bytestream (self, reply_msg, si, data->stream_id, peer_handle, peer_resource, self_jid); if (bytestream == NULL) goto END; DEBUG ("stream %s accepted", data->stream_id); /* Let's start the initiation of the stream */ if (gabble_bytestream_iface_initiate (bytestream)) { /* FIXME: we should really only "succeed" when our succeeds. * It only really matters from the point of view of the data->func */ success = TRUE; } END: if (!success && bytestream != NULL) { remove_bytestream (self, bytestream); bytestream = NULL; } /* user callback */ if (object != NULL) { data->func (bytestream, reply_msg, object, tp_weak_ref_get_user_data (data->weak_object)); g_clear_object (&object); } if (peer_resource != NULL) g_free (peer_resource); g_clear_object (&reply_msg); g_clear_object (&data->self); g_free (self_jid); g_free (data->stream_id); tp_weak_ref_destroy (data->weak_object); g_slice_free (struct _streaminit_reply_cb_data, data); } /* * gabble_bytestream_factory_negotiate_stream: * * @msg: the SI negotiation IQ (created using * gabble_bytestream_factory_make_stream_init_iq) * @stream_id: the stream identifier * @func: the callback to call when we receive the answser of the request * @user_data: user data to pass to the callback * @object: the handler will follow the lifetime of this object, * which means that if the object is destroyed the callback will not be invoked. * * Send a Stream Initiation (XEP-0095) request. */ void gabble_bytestream_factory_negotiate_stream (GabbleBytestreamFactory *self, WockyStanza *msg, const gchar *stream_id, GabbleBytestreamFactoryNegotiateReplyFunc func, gpointer user_data, GObject *object) { GabbleBytestreamFactoryPrivate *priv; struct _streaminit_reply_cb_data *data; g_assert (GABBLE_IS_BYTESTREAM_FACTORY (self)); g_assert (stream_id != NULL); g_assert (func != NULL); g_assert (object != NULL); priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE (self); data = g_slice_new (struct _streaminit_reply_cb_data); data->self = g_object_ref (self); data->stream_id = g_strdup (stream_id); data->func = func; data->weak_object = tp_weak_ref_new (object, user_data, NULL); conn_util_send_iq_async (priv->conn, msg, NULL, streaminit_reply_cb, data); } /* * gabble_bytestream_factory_make_accept_iq * * @full_jid: the full jid of the stream initiator * @stream_init_id: the id of the SI request * @stream_method: the stream method chosen (one of them proposed * in the SI request) * * Create an IQ stanza accepting a stream in response to * a SI request (XEP-0095). * */ WockyStanza * gabble_bytestream_factory_make_accept_iq (const gchar *full_jid, const gchar *stream_init_id, const gchar *stream_method) { return wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, full_jid, '@', "id", stream_init_id, '(', "si", ':', NS_SI, '(', "feature", ':', NS_FEATURENEG, '(', "x", ':', NS_X_DATA, '@', "type", "submit", '(', "field", '@', "var", "stream-method", '(', "value", '$', stream_method, ')', ')', ')', ')', ')', NULL); } /* * gabble_bytestream_factory_make_multi_accept_iq * * @full_jid: the full jid of the stream initiator * @stream_init_id: the id of the SI request * @stream_methods: a list of the accepted string methods * * Create an IQ stanza accepting a stream in response to * a si-multiple SI request. * */ WockyStanza * gabble_bytestream_factory_make_multi_accept_iq (const gchar *full_jid, const gchar *stream_init_id, GList *stream_methods) { WockyStanza *msg; WockyNode *multi_node; GList *l; msg = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, full_jid, '@', "id", stream_init_id, '(', "si", ':', NS_SI, '(', "si-multiple", ':', NS_SI_MULTIPLE, '*', &multi_node, ')', ')', NULL); for (l = stream_methods; l != NULL; l = l->next) { wocky_node_add_child_with_content (multi_node, "value", l->data); } return msg; } GSList * gabble_bytestream_factory_get_socks5_proxies (GabbleBytestreamFactory *self) { GabbleBytestreamFactoryPrivate *priv = GABBLE_BYTESTREAM_FACTORY_GET_PRIVATE ( self); return g_slist_concat (g_slist_copy (priv->socks5_proxies), g_slist_copy (priv->socks5_fallback_proxies)); } telepathy-gabble-0.18.3/src/request-pipeline.c0000664000175000017500000003023012223562023022417 0ustar00cassidycassidy00000000000000/* * request-pipeline.c - Pipeline logic for XMPP requests * * Copyright (C) 2007 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "request-pipeline.h" #include #define DEBUG_FLAG GABBLE_DEBUG_PIPELINE #include "connection.h" #include "debug.h" #include "util.h" #define DEFAULT_REQUEST_TIMEOUT 180 #define REQUEST_PIPELINE_SIZE 10 /* Properties */ enum { PROP_CONNECTION = 1, LAST_PROPERTY }; G_DEFINE_TYPE (GabbleRequestPipeline, gabble_request_pipeline, G_TYPE_OBJECT); struct _GabbleRequestPipelineItem { GabbleRequestPipeline *pipeline; WockyStanza *message; guint timer_id; guint timeout; gboolean in_flight; gboolean zombie; GabbleRequestPipelineCb callback; gpointer user_data; }; struct _GabbleRequestPipelinePrivate { GabbleConnection *connection; GSList *pending_items; GSList *items_in_flight; /* Zombie storage (items which were cancelled while the IQ was in flight) */ GSList *crypt_items; gboolean dispose_has_run; }; GQuark gabble_request_pipeline_error_quark (void) { static GQuark quark = 0; if (!quark) quark = g_quark_from_static_string ("gabble-request-pipeline-error"); return quark; } #define GABBLE_REQUEST_PIPELINE_GET_PRIVATE(o) ((o)->priv) static void gabble_request_pipeline_init (GabbleRequestPipeline *obj) { GabbleRequestPipelinePrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, GABBLE_TYPE_REQUEST_PIPELINE, GabbleRequestPipelinePrivate); obj->priv = priv; } static void gabble_request_pipeline_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec); static void gabble_request_pipeline_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec); static void gabble_request_pipeline_dispose (GObject *object); static void gabble_request_pipeline_finalize (GObject *object); static void gabble_request_pipeline_go (GabbleRequestPipeline *pipeline); static void gabble_request_pipeline_class_init (GabbleRequestPipelineClass *cls) { GObjectClass *object_class = G_OBJECT_CLASS (cls); GParamSpec *param_spec; g_type_class_add_private (cls, sizeof (GabbleRequestPipelinePrivate)); object_class->get_property = gabble_request_pipeline_get_property; object_class->set_property = gabble_request_pipeline_set_property; object_class->dispose = gabble_request_pipeline_dispose; object_class->finalize = gabble_request_pipeline_finalize; param_spec = g_param_spec_object ("connection", "GabbleConnection object", "Gabble connection object that owns this request pipeline helper " "object.", GABBLE_TYPE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); } static void gabble_request_pipeline_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleRequestPipeline *chan = GABBLE_REQUEST_PIPELINE (object); GabbleRequestPipelinePrivate *priv = GABBLE_REQUEST_PIPELINE_GET_PRIVATE (chan); switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, priv->connection); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_request_pipeline_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleRequestPipeline *chan = GABBLE_REQUEST_PIPELINE (object); GabbleRequestPipelinePrivate *priv = GABBLE_REQUEST_PIPELINE_GET_PRIVATE (chan); switch (property_id) { case PROP_CONNECTION: priv->connection = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } GabbleRequestPipeline * gabble_request_pipeline_new (GabbleConnection *conn) { GabbleRequestPipeline *self; g_return_val_if_fail (GABBLE_IS_CONNECTION (conn), NULL); self = GABBLE_REQUEST_PIPELINE (g_object_new (GABBLE_TYPE_REQUEST_PIPELINE, "connection", conn, NULL)); return self; } static void delete_item (GabbleRequestPipelineItem *item) { GabbleRequestPipelinePrivate *priv; g_assert (GABBLE_IS_REQUEST_PIPELINE (item->pipeline)); priv = GABBLE_REQUEST_PIPELINE_GET_PRIVATE (item->pipeline); DEBUG ("deleting item %p", item); if (item->zombie) { priv->crypt_items = g_slist_remove (priv->crypt_items, item); } else if (item->in_flight) { priv->items_in_flight = g_slist_remove (priv->items_in_flight, item); } else { priv->pending_items = g_slist_remove (priv->pending_items, item); } if (item->timer_id) g_source_remove (item->timer_id); tp_clear_pointer (&item->message, g_object_unref); g_slice_free (GabbleRequestPipelineItem, item); } static void gabble_request_pipeline_create_zombie (GabbleRequestPipeline *pipeline, GabbleRequestPipelineItem *item, GError *error) { GabbleRequestPipelinePrivate *priv = pipeline->priv; g_assert (!item->zombie); if (item->timer_id != 0) { g_source_remove (item->timer_id); item->timer_id = 0; } (item->callback) (priv->connection, NULL, item->user_data, error); if (item->in_flight) { item->zombie = TRUE; priv->items_in_flight = g_slist_remove (priv->items_in_flight, item); priv->crypt_items = g_slist_prepend (priv->crypt_items, item); gabble_request_pipeline_go (pipeline); } else { delete_item (item); } } void gabble_request_pipeline_item_cancel (GabbleRequestPipelineItem *item) { GError cancelled = { GABBLE_REQUEST_PIPELINE_ERROR, GABBLE_REQUEST_PIPELINE_ERROR_CANCELLED, "Request cancelled" }; gabble_request_pipeline_create_zombie (item->pipeline, item, &cancelled); } static void gabble_request_pipeline_flush (GabbleRequestPipeline *self, GSList **list) { GabbleRequestPipelineItem *item; GError disconnected = { TP_ERROR, TP_ERROR_DISCONNECTED, "Request failed because connection became disconnected" }; while (*list != NULL) { item = (*list)->data; if (!item->zombie) (item->callback) (self->priv->connection, NULL, item->user_data, &disconnected); delete_item (item); } } static void gabble_request_pipeline_dispose (GObject *object) { GabbleRequestPipeline *self = GABBLE_REQUEST_PIPELINE (object); GabbleRequestPipelinePrivate *priv = GABBLE_REQUEST_PIPELINE_GET_PRIVATE (self); if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; DEBUG ("disposing request-pipeline"); gabble_request_pipeline_flush (self, &priv->items_in_flight); gabble_request_pipeline_flush (self, &priv->pending_items); gabble_request_pipeline_flush (self, &priv->crypt_items); g_idle_remove_by_data (self); if (G_OBJECT_CLASS (gabble_request_pipeline_parent_class)->dispose) G_OBJECT_CLASS (gabble_request_pipeline_parent_class)->dispose (object); } static void gabble_request_pipeline_finalize (GObject *object) { G_OBJECT_CLASS (gabble_request_pipeline_parent_class)->finalize (object); } static void response_cb (GabbleConnection *conn, WockyStanza *sent, WockyStanza *reply, GObject *object, gpointer user_data) { GabbleRequestPipelineItem *item = (GabbleRequestPipelineItem *) user_data; GabbleRequestPipeline *pipeline = item->pipeline; GabbleRequestPipelinePrivate *priv; g_assert (GABBLE_IS_REQUEST_PIPELINE (pipeline)); priv = GABBLE_REQUEST_PIPELINE_GET_PRIVATE (pipeline); DEBUG ("got reply for request %p", item); if (NULL == g_slist_find (priv->items_in_flight, item)) return; g_assert (item->in_flight); priv->items_in_flight = g_slist_remove (priv->items_in_flight, item); if (!item->zombie) { GError *error = NULL; wocky_stanza_extract_errors (reply, NULL, &error, NULL, NULL); item->callback (priv->connection, reply, item->user_data, error); g_clear_error (&error); } else { DEBUG ("ignoring zombie connection reply"); } delete_item (item); gabble_request_pipeline_go (pipeline); } static gboolean timeout_cb (gpointer data) { GabbleRequestPipelineItem *item = (GabbleRequestPipelineItem *) data; GError timed_out = { GABBLE_REQUEST_PIPELINE_ERROR, GABBLE_REQUEST_PIPELINE_ERROR_TIMEOUT, "Request timed out" }; gabble_request_pipeline_create_zombie (item->pipeline, item, &timed_out); return FALSE; } static void send_next_request (GabbleRequestPipeline *pipeline) { GabbleRequestPipelinePrivate *priv = GABBLE_REQUEST_PIPELINE_GET_PRIVATE (pipeline); GabbleRequestPipelineItem *item; GError *error = NULL; if (priv->pending_items == NULL) return; item = priv->pending_items->data; DEBUG ("processing request %p", item); g_assert (item->in_flight == FALSE); priv->pending_items = g_slist_remove (priv->pending_items, item); if (!_gabble_connection_send_with_reply (priv->connection, item->message, response_cb, G_OBJECT (pipeline), item, &error)) { item->callback (priv->connection, NULL, item->user_data, error); delete_item (item); send_next_request (pipeline); } else { priv->items_in_flight = g_slist_prepend (priv->items_in_flight, item); item->in_flight = TRUE; item->timer_id = g_timeout_add_seconds (item->timeout, timeout_cb, item); } } static void gabble_request_pipeline_go (GabbleRequestPipeline *pipeline) { GabbleRequestPipelinePrivate *priv = GABBLE_REQUEST_PIPELINE_GET_PRIVATE (pipeline); DEBUG ("called; %d pending items, %d items in flight", g_slist_length (priv->pending_items), g_slist_length (priv->items_in_flight)); while (priv->pending_items && (g_slist_length (priv->items_in_flight) < REQUEST_PIPELINE_SIZE)) { send_next_request (pipeline); } } static gboolean delayed_run_pipeline (gpointer user_data) { GabbleRequestPipeline *pipeline = (GabbleRequestPipeline *) user_data; gabble_request_pipeline_go (pipeline); return FALSE; } GabbleRequestPipelineItem * gabble_request_pipeline_enqueue (GabbleRequestPipeline *pipeline, WockyStanza *msg, guint timeout, GabbleRequestPipelineCb callback, gpointer user_data) { GabbleRequestPipelinePrivate *priv = GABBLE_REQUEST_PIPELINE_GET_PRIVATE (pipeline); GabbleRequestPipelineItem *item = g_slice_new0 (GabbleRequestPipelineItem); g_return_val_if_fail (callback != NULL, NULL); item->pipeline = pipeline; item->message = msg; if (timeout == 0) timeout = DEFAULT_REQUEST_TIMEOUT; item->timeout = timeout; item->in_flight = FALSE; item->callback = callback; item->user_data = user_data; g_object_ref (msg); priv->pending_items = g_slist_append (priv->pending_items, item); DEBUG ("enqueued new request as item %p", item); DEBUG ("number of items in flight: %d", g_slist_length (priv->items_in_flight)); /* If the pipeline isn't full, schedule a run. Run it delayed so that if * there's an error, the callback will be called after this function returns. */ if (g_slist_length (priv->items_in_flight) < REQUEST_PIPELINE_SIZE) gabble_idle_add_weak (delayed_run_pipeline, G_OBJECT (pipeline)); return item; } telepathy-gabble-0.18.3/src/bytestream-socks5.c0000664000175000017500000016173612332440117022530 0ustar00cassidycassidy00000000000000/* * bytestream-socks5.c - Source for GabbleBytestreamSocks5 * Copyright (C) 2006 Youness Alaoui * Copyright (C) 2007-2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "bytestream-socks5.h" #include #include /* on Darwin, net/if.h requires sys/sockets.h, which is included by * gibber-sockets.h; so this must come after that header */ #ifdef HAVE_NET_IF_H # include #endif #include #include #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_IFADDRS_H #include #endif #include #include #include #include #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_BYTESTREAM #include "bytestream-factory.h" #include "bytestream-iface.h" #include "connection.h" #include "conn-util.h" #include "debug.h" #include "disco.h" #include "gabble-signals-marshal.h" #include "namespaces.h" #include "util.h" static void bytestream_iface_init (gpointer g_iface, gpointer iface_data); G_DEFINE_TYPE_WITH_CODE (GabbleBytestreamSocks5, gabble_bytestream_socks5, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GABBLE_TYPE_BYTESTREAM_IFACE, bytestream_iface_init)); /* properties */ enum { PROP_CONNECTION = 1, PROP_PEER_HANDLE, PROP_PEER_HANDLE_TYPE, PROP_STREAM_ID, PROP_STREAM_INIT_ID, PROP_PEER_JID, PROP_PEER_RESOURCE, PROP_STATE, PROP_PROTOCOL, PROP_SELF_JID, LAST_PROPERTY }; enum _Socks5State { SOCKS5_STATE_INVALID, SOCKS5_STATE_TARGET_TRYING_CONNECT, SOCKS5_STATE_TARGET_AUTH_REQUEST_SENT, SOCKS5_STATE_TARGET_CONNECT_REQUESTED, SOCKS5_STATE_CONNECTED, SOCKS5_STATE_INITIATOR_OFFER_SENT, SOCKS5_STATE_INITIATOR_AWAITING_AUTH_REQUEST, SOCKS5_STATE_INITIATOR_AWAITING_COMMAND, SOCKS5_STATE_INITIATOR_TRYING_CONNECT, SOCKS5_STATE_INITIATOR_AUTH_REQUEST_SENT, SOCKS5_STATE_INITIATOR_CONNECT_REQUESTED, SOCKS5_STATE_INITIATOR_ACTIVATION_SENT, SOCKS5_STATE_ERROR }; typedef enum _Socks5State Socks5State; /* SOCKS5 commands */ #define SOCKS5_VERSION 0x05 #define SOCKS5_CMD_CONNECT 0x01 #define SOCKS5_RESERVED 0x00 #define SOCKS5_ATYP_DOMAIN 0x03 #define SOCKS5_STATUS_OK 0x00 #define SOCKS5_AUTH_NONE 0x00 #define SHA1_LENGTH 40 #define SOCKS5_CONNECT_LENGTH (7 + SHA1_LENGTH) /* VER + CMD/REP + RSV + ATYP + PORT (2) */ #define SOCKS5_MIN_LENGTH 6 #define CONNECT_REPLY_TIMEOUT 30 #define CONNECT_TIMEOUT 10 struct _Streamhost { gchar *jid; gchar *host; guint16 port; }; typedef struct _Streamhost Streamhost; static Streamhost * streamhost_new (const gchar *jid, const gchar *host, guint16 port) { Streamhost *streamhost; g_return_val_if_fail (jid != NULL, NULL); g_return_val_if_fail (host != NULL, NULL); streamhost = g_slice_new0 (Streamhost); streamhost->jid = g_strdup (jid); streamhost->host = g_strdup (host); streamhost->port = port; return streamhost; } static void streamhost_free (Streamhost *streamhost) { if (streamhost == NULL) return; g_free (streamhost->jid); g_free (streamhost->host); g_slice_free (Streamhost, streamhost); } struct _GabbleBytestreamSocks5Private { GabbleConnection *conn; TpHandle peer_handle; gchar *stream_id; gchar *stream_init_id; gchar *peer_resource; GabbleBytestreamState bytestream_state; gchar *peer_jid; gchar *self_full_jid; gchar *proxy_jid; /* TRUE if the peer of this bytestream is a muc contact */ gboolean muc_contact; /* List of Streamhost */ GSList *streamhosts; /* Connections to streamhosts are async, so we keep the IQ set message * around */ WockyStanza *msg_for_acknowledge_connection; Socks5State socks5_state; GibberTransport *transport; gboolean write_blocked; gboolean read_blocked; GibberListener *listener; guint timer_id; GString *read_buffer; gboolean dispose_has_run; }; #define GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE(obj) ((obj)->priv) static void socks5_connect (GabbleBytestreamSocks5 *self); static void gabble_bytestream_socks5_close (GabbleBytestreamIface *iface, GError *error); static void socks5_error (GabbleBytestreamSocks5 *self); static void transport_handler (GibberTransport *transport, GibberBuffer *data, gpointer user_data); static void gabble_bytestream_socks5_init (GabbleBytestreamSocks5 *self) { GabbleBytestreamSocks5Private *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_BYTESTREAM_SOCKS5, GabbleBytestreamSocks5Private); self->priv = priv; } static void stop_timer (GabbleBytestreamSocks5 *self) { GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE ( self); if (priv->timer_id == 0) return; g_source_remove (priv->timer_id); priv->timer_id = 0; } static void gabble_bytestream_socks5_dispose (GObject *object) { GabbleBytestreamSocks5 *self = GABBLE_BYTESTREAM_SOCKS5 (object); GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; stop_timer (self); if (priv->bytestream_state != GABBLE_BYTESTREAM_STATE_CLOSED) { gabble_bytestream_iface_close (GABBLE_BYTESTREAM_IFACE (self), NULL); } tp_clear_object (&priv->transport); tp_clear_object (&priv->listener); G_OBJECT_CLASS (gabble_bytestream_socks5_parent_class)->dispose (object); } static void gabble_bytestream_socks5_finalize (GObject *object) { GabbleBytestreamSocks5 *self = GABBLE_BYTESTREAM_SOCKS5 (object); GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); g_free (priv->stream_id); g_free (priv->stream_init_id); g_free (priv->peer_resource); g_free (priv->peer_jid); g_free (priv->self_full_jid); g_free (priv->proxy_jid); g_slist_foreach (priv->streamhosts, (GFunc) streamhost_free, NULL); g_slist_free (priv->streamhosts); G_OBJECT_CLASS (gabble_bytestream_socks5_parent_class)->finalize (object); } static void gabble_bytestream_socks5_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleBytestreamSocks5 *self = GABBLE_BYTESTREAM_SOCKS5 (object); GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, priv->conn); break; case PROP_PEER_HANDLE: g_value_set_uint (value, priv->peer_handle); break; case PROP_PEER_HANDLE_TYPE: g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT); break; case PROP_STREAM_ID: g_value_set_string (value, priv->stream_id); break; case PROP_STREAM_INIT_ID: g_value_set_string (value, priv->stream_init_id); break; case PROP_PEER_RESOURCE: g_value_set_string (value, priv->peer_resource); break; case PROP_PEER_JID: g_value_set_string (value, priv->peer_jid); break; case PROP_STATE: g_value_set_uint (value, priv->bytestream_state); break; case PROP_PROTOCOL: g_value_set_string (value, NS_BYTESTREAMS); break; case PROP_SELF_JID: g_value_set_string (value, priv->self_full_jid); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_bytestream_socks5_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleBytestreamSocks5 *self = GABBLE_BYTESTREAM_SOCKS5 (object); GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); switch (property_id) { case PROP_CONNECTION: priv->conn = g_value_get_object (value); break; case PROP_PEER_HANDLE: priv->peer_handle = g_value_get_uint (value); break; case PROP_STREAM_ID: g_free (priv->stream_id); priv->stream_id = g_value_dup_string (value); break; case PROP_STREAM_INIT_ID: g_free (priv->stream_init_id); priv->stream_init_id = g_value_dup_string (value); break; case PROP_PEER_RESOURCE: g_free (priv->peer_resource); priv->peer_resource = g_value_dup_string (value); break; case PROP_STATE: if (priv->bytestream_state != g_value_get_uint (value)) { priv->bytestream_state = g_value_get_uint (value); g_signal_emit_by_name (object, "state-changed", priv->bytestream_state); } break; case PROP_SELF_JID: g_free (priv->self_full_jid); priv->self_full_jid = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static GObject * gabble_bytestream_socks5_constructor (GType type, guint n_props, GObjectConstructParam *props) { GObject *obj; GabbleBytestreamSocks5Private *priv; TpBaseConnection *base_conn; TpHandleRepoIface *contact_repo, *room_repo; const gchar *jid; obj = G_OBJECT_CLASS (gabble_bytestream_socks5_parent_class)-> constructor (type, n_props, props); priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (GABBLE_BYTESTREAM_SOCKS5 (obj)); g_assert (priv->conn != NULL); g_assert (priv->peer_handle != 0); g_assert (priv->stream_id != NULL); base_conn = TP_BASE_CONNECTION (priv->conn); contact_repo = tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT); room_repo = tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_ROOM); jid = tp_handle_inspect (contact_repo, priv->peer_handle); if (priv->peer_resource != NULL) priv->peer_jid = g_strdup_printf ("%s/%s", jid, priv->peer_resource); else priv->peer_jid = g_strdup (jid); g_assert (priv->self_full_jid != NULL); priv->muc_contact = (gabble_get_room_handle_from_jid (room_repo, priv->peer_jid) != 0); return obj; } static void gabble_bytestream_socks5_class_init ( GabbleBytestreamSocks5Class *gabble_bytestream_socks5_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_bytestream_socks5_class); GParamSpec *param_spec; g_type_class_add_private (gabble_bytestream_socks5_class, sizeof (GabbleBytestreamSocks5Private)); object_class->dispose = gabble_bytestream_socks5_dispose; object_class->finalize = gabble_bytestream_socks5_finalize; object_class->get_property = gabble_bytestream_socks5_get_property; object_class->set_property = gabble_bytestream_socks5_set_property; object_class->constructor = gabble_bytestream_socks5_constructor; g_object_class_override_property (object_class, PROP_CONNECTION, "connection"); g_object_class_override_property (object_class, PROP_PEER_HANDLE, "peer-handle"); g_object_class_override_property (object_class, PROP_PEER_HANDLE_TYPE, "peer-handle-type"); g_object_class_override_property (object_class, PROP_STREAM_ID, "stream-id"); g_object_class_override_property (object_class, PROP_PEER_JID, "peer-jid"); g_object_class_override_property (object_class, PROP_STATE, "state"); g_object_class_override_property (object_class, PROP_PROTOCOL, "protocol"); param_spec = g_param_spec_string ( "peer-resource", "Peer resource", "the resource used by the remote peer during the SI, if any", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_PEER_RESOURCE, param_spec); param_spec = g_param_spec_string ( "stream-init-id", "stream init ID", "the iq ID of the SI request, if any", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_STREAM_INIT_ID, param_spec); param_spec = g_param_spec_string ( "self-jid", "Our self jid", "Either a contact full jid or a muc jid", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SELF_JID, param_spec); } static gboolean write_to_transport (GabbleBytestreamSocks5 *self, const gchar *data, guint len, GError **error) { GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); if (!gibber_transport_send (priv->transport, (const guint8 *) data, len, error)) { return FALSE; } return TRUE; } static void transport_connected_cb (GibberTransport *transport, GabbleBytestreamSocks5 *self) { GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); stop_timer (self); if (priv->socks5_state == SOCKS5_STATE_TARGET_TRYING_CONNECT || priv->socks5_state == SOCKS5_STATE_INITIATOR_TRYING_CONNECT) { gchar msg[3]; DEBUG ("transport is connected. Sending auth request"); msg[0] = SOCKS5_VERSION; /* Number of auth methods we are offering, we support just * SOCKS5_AUTH_NONE */ msg[1] = 1; msg[2] = SOCKS5_AUTH_NONE; write_to_transport (self, msg, 3, NULL); if (priv->socks5_state == SOCKS5_STATE_TARGET_TRYING_CONNECT) priv->socks5_state = SOCKS5_STATE_TARGET_AUTH_REQUEST_SENT; else priv->socks5_state = SOCKS5_STATE_INITIATOR_AUTH_REQUEST_SENT; } } static void transport_disconnected_cb (GibberTransport *transport, GabbleBytestreamSocks5 *self) { stop_timer (self); DEBUG ("Sock5 transport disconnected"); socks5_error (self); } static void change_write_blocked_state (GabbleBytestreamSocks5 *self, gboolean blocked) { GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); if (priv->write_blocked == blocked) return; priv->write_blocked = blocked; g_signal_emit_by_name (self, "write-blocked", blocked); } static void socks5_close_transport (GabbleBytestreamSocks5 *self) { GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); if (priv->read_buffer != NULL) { g_string_free (priv->read_buffer, TRUE); priv->read_buffer = NULL; } if (priv->transport == NULL) return; g_signal_handlers_disconnect_matched (priv->transport, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self); tp_clear_object (&priv->transport); } static void bytestream_closed (GabbleBytestreamSocks5 *self) { socks5_close_transport (self); g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_CLOSED, NULL); } static void transport_buffer_empty_cb (GibberTransport *transport, GabbleBytestreamSocks5 *self) { GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); if (priv->bytestream_state == GABBLE_BYTESTREAM_STATE_CLOSING) { DEBUG ("buffer is now empty. Bytestream can be closed"); bytestream_closed (self); } else if (priv->write_blocked) { change_write_blocked_state (self, FALSE); } } static void set_transport (GabbleBytestreamSocks5 *self, GibberTransport *transport) { GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); priv->transport = g_object_ref (transport); g_assert (priv->read_buffer == NULL); priv->read_buffer = g_string_sized_new (4096); gibber_transport_set_handler (transport, transport_handler, self); g_signal_connect (transport, "connected", G_CALLBACK (transport_connected_cb), self); g_signal_connect (transport, "disconnected", G_CALLBACK (transport_disconnected_cb), self); g_signal_connect (priv->transport, "buffer-empty", G_CALLBACK (transport_buffer_empty_cb), self); } static void socks5_error (GabbleBytestreamSocks5 *self) { GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); WockyPorter *porter = wocky_session_get_porter (priv->conn->session); Socks5State previous_state; stop_timer (self); previous_state = priv->socks5_state; priv->socks5_state = SOCKS5_STATE_ERROR; switch (previous_state) { case SOCKS5_STATE_TARGET_TRYING_CONNECT: case SOCKS5_STATE_TARGET_AUTH_REQUEST_SENT: case SOCKS5_STATE_TARGET_CONNECT_REQUESTED: /* The attempt for connect to the streamhost failed */ socks5_close_transport (self); if (priv->streamhosts != NULL) { /* Remove the failed streamhost */ streamhost_free (priv->streamhosts->data); priv->streamhosts = g_slist_delete_link (priv->streamhosts, priv->streamhosts); } if (priv->streamhosts != NULL) { DEBUG ("connection to streamhost failed, trying the next one"); socks5_connect (self); return; } DEBUG ("no more streamhosts to try"); g_signal_emit_by_name (self, "connection-error"); g_assert (priv->msg_for_acknowledge_connection != NULL); wocky_porter_send_iq_error (porter, priv->msg_for_acknowledge_connection, WOCKY_XMPP_ERROR_ITEM_NOT_FOUND, "impossible to connect to any streamhost"); g_object_unref (priv->msg_for_acknowledge_connection); priv->msg_for_acknowledge_connection = NULL; break; case SOCKS5_STATE_INITIATOR_AWAITING_AUTH_REQUEST: case SOCKS5_STATE_INITIATOR_AWAITING_COMMAND: DEBUG ("Something goes wrong during SOCKS5 negotiation. Don't close " "the bytestream yet as the target can still try other streamhosts"); break; default: DEBUG ("error, closing the connection\n"); gabble_bytestream_socks5_close (GABBLE_BYTESTREAM_IFACE (self), NULL); } } static gchar * compute_domain (const gchar *sid, const gchar *initiator, const gchar *target) { gchar *unhashed_domain; gchar *domain; unhashed_domain = g_strconcat (sid, initiator, target, NULL); domain = sha1_hex (unhashed_domain, strlen (unhashed_domain)); g_free (unhashed_domain); return domain; } static gboolean check_domain (const gchar *domain, guint8 len, const gchar *expected) { if (len != SHA1_LENGTH || strncmp (domain, expected, SHA1_LENGTH) != 0) { DEBUG ("Wrong domain hash: %s (expected: %s)", domain, expected); return FALSE; } return TRUE; } static gboolean socks5_timer_cb (gpointer data) { GabbleBytestreamSocks5 *self = GABBLE_BYTESTREAM_SOCKS5 (data); DEBUG ("Timed out; closing SOCKS5 connection"); socks5_error (self); return FALSE; } static void start_timer (GabbleBytestreamSocks5 *self, guint seconds) { GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE ( self); g_assert (priv->timer_id == 0); priv->timer_id = g_timeout_add_seconds (seconds, socks5_timer_cb, self); } static void target_got_connect_reply (GabbleBytestreamSocks5 *self) { GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE ( self); WockyPorter *porter = wocky_session_get_porter (priv->conn->session); Streamhost *current_streamhost; DEBUG ("Received CONNECT reply. Socks5 stream connected. " "Bytestream is now open"); priv->socks5_state = SOCKS5_STATE_CONNECTED; g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_OPEN, NULL); /* Acknowledge the connection */ current_streamhost = priv->streamhosts->data; wocky_porter_acknowledge_iq (porter, priv->msg_for_acknowledge_connection, '(', "query", ':', NS_BYTESTREAMS, /* streamhost-used informs the other end of the streamhost we * decided to use. In case of a direct connetion this is useless * but if we are using an external proxy we need to know which * one was selected */ '(', "streamhost-used", '@', "jid", current_streamhost->jid, ')', ')', NULL); if (priv->read_blocked) { DEBUG ("reading has been blocked. Blocking now as the socks5 " "negotiation is done"); gibber_transport_block_receiving (priv->transport, TRUE); } } static void socks5_activation_reply_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { TpWeakRef *weak_ref = user_data; GabbleBytestreamSocks5 *self = tp_weak_ref_dup_object (weak_ref); GabbleBytestreamSocks5Private *priv; WockyStanza *reply_msg = NULL; tp_weak_ref_destroy (weak_ref); if (self == NULL) return; priv = self->priv; if (!conn_util_send_iq_finish (GABBLE_CONNECTION (source), result, &reply_msg, NULL)) { DEBUG ("Activation failed"); goto activation_failed; } if (priv->socks5_state != SOCKS5_STATE_INITIATOR_ACTIVATION_SENT) { DEBUG ("We are not waiting for an activation reply (state: %u)", priv->socks5_state); goto activation_failed; } DEBUG ("Proxy activated the bytestream. It's now open"); priv->socks5_state = SOCKS5_STATE_CONNECTED; g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_OPEN, NULL); /* We can read data from the sock5 socket now */ gibber_transport_block_receiving (priv->transport, FALSE); goto out; activation_failed: g_signal_emit_by_name (self, "connection-error"); g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_CLOSED, NULL); out: g_clear_object (&reply_msg); g_object_unref (self); } static void initiator_got_connect_reply (GabbleBytestreamSocks5 *self) { GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE ( self); WockyStanza *iq; DEBUG ("Got CONNECT reply. SOCKS5 negotiation with proxy is done. " "Sending activation IQ"); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, priv->proxy_jid, '(', "query", ':', NS_BYTESTREAMS, '@', "sid", priv->stream_id, '(', "activate", '$', priv->peer_jid, ')', ')', NULL); priv->socks5_state = SOCKS5_STATE_INITIATOR_ACTIVATION_SENT; /* Block reading while waiting for the activation reply */ gibber_transport_block_receiving (priv->transport, TRUE); conn_util_send_iq_async (priv->conn, iq, NULL, socks5_activation_reply_cb, tp_weak_ref_new (self, NULL, NULL)); g_object_unref (iq); } /* Process the received data and returns the number of bytes that have been * used */ static gssize socks5_handle_received_data (GabbleBytestreamSocks5 *self, GString *string) { GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); gchar msg[SOCKS5_CONNECT_LENGTH]; guint auth_len; guint i; gchar *domain; /* the length of the BND.ADDR field */ guint8 addr_len; gsize len; switch (priv->socks5_state) { case SOCKS5_STATE_TARGET_AUTH_REQUEST_SENT: case SOCKS5_STATE_INITIATOR_AUTH_REQUEST_SENT: /* We sent an authorization request and we are awaiting for a * response, the response is 2 bytes-long */ if (string->len < 2) return 0; if (string->str[0] != SOCKS5_VERSION || string->str[1] != SOCKS5_STATUS_OK) { DEBUG ("Authentication failed"); socks5_error (self); return -1; } /* We have been authorized, let's send a CONNECT command */ DEBUG ("Received auth reply. Sending CONNECT command"); if (priv->socks5_state == SOCKS5_STATE_TARGET_AUTH_REQUEST_SENT) { domain = compute_domain (priv->stream_id, priv->peer_jid, priv->self_full_jid); } else { /* SOCKS5_STATE_INITIATOR_AUTH_REQUEST_SENT */ domain = compute_domain (priv->stream_id, priv->self_full_jid, priv->peer_jid); } msg[0] = SOCKS5_VERSION; msg[1] = SOCKS5_CMD_CONNECT; msg[2] = SOCKS5_RESERVED; msg[3] = SOCKS5_ATYP_DOMAIN; /* Length of a hex SHA1 */ msg[4] = 40; /* Domain name: SHA-1(sid + initiator + target) */ memcpy (&msg[5], domain, 40); /* Port: 0 */ msg[45] = 0x00; msg[46] = 0x00; g_free (domain); write_to_transport (self, msg, SOCKS5_CONNECT_LENGTH, NULL); if (priv->socks5_state == SOCKS5_STATE_TARGET_AUTH_REQUEST_SENT) priv->socks5_state = SOCKS5_STATE_TARGET_CONNECT_REQUESTED; else /* SOCKS5_STATE_INITIATOR_AUTH_REQUEST_SENT */ priv->socks5_state = SOCKS5_STATE_INITIATOR_CONNECT_REQUESTED; /* Older version of Gabble (pre 0.7.22) are bugged and just send 2 * bytes as CONNECT reply. We set a timer to not wait the full reply * forever if we are connected to such Gabble. * Once timed out, the SOCKS5 negotiation will fail and Gabble * will switch to IBB as a fallback. */ start_timer (self, CONNECT_REPLY_TIMEOUT); return 2; case SOCKS5_STATE_TARGET_CONNECT_REQUESTED: case SOCKS5_STATE_INITIATOR_CONNECT_REQUESTED: /* We sent a CONNECT request and are awaiting for the response */ if (string->len < SOCKS5_MIN_LENGTH) return 0; if (string->str[0] != SOCKS5_VERSION || string->str[1] != SOCKS5_STATUS_OK || string->str[2] != SOCKS5_RESERVED) { DEBUG ("Connection refused"); socks5_error (self); return -1; } if (string->str[3] == SOCKS5_ATYP_DOMAIN) { /* correct domain. The first byte of the domain contains its * length */ addr_len = (guint8) string->str[4]; addr_len += 1; } else if (string->str[3] == 0x00) { DEBUG ("Got 0x00 as domain. Pretend it's ok to be able to interop " "with ejabberd < 2.0.2"); addr_len = 0; } else { DEBUG ("Wrong domain"); socks5_error (self); return -1; } if ((guint8) string->len < SOCKS5_MIN_LENGTH + addr_len) /* We didn't receive the full packet yet */ return 0; stop_timer (self); if ( /* first half of the port number */ string->str[4 + addr_len] != 0 || /* second half of the port number */ string->str[5 + addr_len] != 0) { DEBUG ("Connection refused"); socks5_error (self); return -1; } if (priv->socks5_state == SOCKS5_STATE_TARGET_CONNECT_REQUESTED) { domain = compute_domain (priv->stream_id, priv->peer_jid, priv->self_full_jid); } else { /* SOCKS5_STATE_INITIATOR_CONNECT_REQUESTED */ domain = compute_domain (priv->stream_id, priv->self_full_jid, priv->peer_jid); } if (addr_len > 0) { if (!check_domain (&string->str[5], addr_len - 1, domain)) { /* Thanks Pidgin... */ DEBUG ("Ignoring to interop with buggy implementations"); } } g_free (domain); if (priv->socks5_state == SOCKS5_STATE_TARGET_CONNECT_REQUESTED) target_got_connect_reply (self); else /* SOCKS5_STATE_INITIATOR_CONNECT_REQUESTED */ initiator_got_connect_reply (self); return SOCKS5_MIN_LENGTH + addr_len; case SOCKS5_STATE_INITIATOR_AWAITING_AUTH_REQUEST: /* A client connected to us and we are awaiting for the authorization * request (at least 2 bytes) */ if (string->len < 2) return 0; if (string->str[0] != SOCKS5_VERSION) { DEBUG ("Authentication failed"); socks5_error (self); return -1; } /* The auth request string is SOCKS5_VERSION + # of methods + methods */ auth_len = string->str[1] + 2; if (string->len < auth_len) /* We are still receiving some auth method */ return 0; for (i = 2; i < auth_len; i++) { if (string->str[i] == SOCKS5_AUTH_NONE) { /* Authorize the connection */ msg[0] = SOCKS5_VERSION; msg[1] = SOCKS5_AUTH_NONE; DEBUG ("Received auth request. Sending auth reply"); write_to_transport (self, msg, 2, NULL); priv->socks5_state = SOCKS5_STATE_INITIATOR_AWAITING_COMMAND; return auth_len; } } DEBUG ("Unauthenticated access is not supported by the streamhost"); socks5_error (self); return -1; case SOCKS5_STATE_INITIATOR_AWAITING_COMMAND: /* The client has been authorized and we are waiting for a command, * the only one supported by the SOCKS5 bytestreams XEP is * CONNECT with: * - ATYP = DOMAIN * - PORT = 0 * - DOMAIN = SHA1(sid + initiator + target) */ if (string->len < SOCKS5_MIN_LENGTH) return 0; addr_len = (guint8) string->str[4]; /* the first byte is the length */ addr_len += 1; if ((guint8) string->len < SOCKS5_MIN_LENGTH + addr_len) /* We didn't receive the full packet yet */ return 0; if (string->str[0] != SOCKS5_VERSION || string->str[1] != SOCKS5_CMD_CONNECT || string->str[2] != SOCKS5_RESERVED || string->str[3] != SOCKS5_ATYP_DOMAIN || /* first half of the port number */ string->str[4 + addr_len] != 0 || /* second half of the port number */ string->str[5 + addr_len] != 0) { DEBUG ("Invalid SOCKS5 connect message"); socks5_error (self); return -1; } domain = compute_domain (priv->stream_id, priv->self_full_jid, priv->peer_jid); if (!check_domain (&string->str[5], addr_len - 1, domain)) { DEBUG ("Reject connection to prevent spoofing"); socks5_close_transport (self); socks5_error (self); g_free (domain); return -1; } msg[0] = SOCKS5_VERSION; msg[1] = SOCKS5_STATUS_OK; msg[2] = SOCKS5_RESERVED; msg[3] = SOCKS5_ATYP_DOMAIN; msg[4] = SHA1_LENGTH; /* Domain name: SHA-1(sid + initiator + target) */ memcpy (&msg[5], domain, 40); /* Port: 0 */ msg[45] = 0x00; msg[46] = 0x00; g_free (domain); DEBUG ("Received CONNECT cmd. Sending CONNECT reply"); write_to_transport (self, msg, 47, NULL); priv->socks5_state = SOCKS5_STATE_CONNECTED; /* Sock5 is connected but the bytestream is not open yet as we need * to wait for the IQ reply. Stop reading until the bytestream * is open to avoid data loss. */ gibber_transport_block_receiving (priv->transport, TRUE); DEBUG ("sock5 stream connected. Stop to listen for connections"); g_assert (priv->listener != NULL); tp_clear_object (&priv->listener); return SOCKS5_MIN_LENGTH + addr_len; case SOCKS5_STATE_CONNECTED: /* We are connected, everything we receive now is data */ /* store the buffer len because if something went wront in the * data-received callback, the bytestream could be freed and so the * priv->read_buffer */ len = string->len; g_signal_emit_by_name (G_OBJECT (self), "data-received", priv->peer_handle, string); return len; case SOCKS5_STATE_ERROR: /* An error occurred and the channel will be closed in an idle * callback, so let's just throw away the data we receive */ DEBUG ("An error occurred, throwing away received data"); return string->len; case SOCKS5_STATE_TARGET_TRYING_CONNECT: case SOCKS5_STATE_INITIATOR_TRYING_CONNECT: DEBUG ("Impossible to receive data when not yet connected to the " "socket"); break; case SOCKS5_STATE_INITIATOR_OFFER_SENT: DEBUG ("Shouldn't receive data when we just sent the offer"); break; case SOCKS5_STATE_INITIATOR_ACTIVATION_SENT: DEBUG ("Shouldn't receive data before we received activation reply"); break; case SOCKS5_STATE_INVALID: DEBUG ("Invalid SOCKS5 state"); break; } g_assert_not_reached (); return string->len; } static void transport_handler (GibberTransport *transport, GibberBuffer *data, gpointer user_data) { GabbleBytestreamSocks5 *self = GABBLE_BYTESTREAM_SOCKS5 (user_data); GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); gssize used_bytes; g_assert (priv->read_buffer != NULL); g_string_append_len (priv->read_buffer, (const gchar *) data->data, data->length); /* If something goes wrong in socks5_handle_received_data, the bytestream * could be closed and disposed. Ref it to artificially keep this bytestream * object alive while we are in this function. */ g_object_ref (self); do { /* socks5_handle_received_data() processes the data and returns the * number of bytes that have been used. 0 means that there is not enough * data to do anything, so we just wait for more data from the socket */ used_bytes = socks5_handle_received_data (self, priv->read_buffer); if (priv->read_buffer == NULL) /* If something did wrong in socks5_handle_received_data, the * bytestream can be closed and so destroyed. */ break; g_string_erase (priv->read_buffer, 0, used_bytes); } while (used_bytes > 0 && priv->read_buffer->len > 0); g_object_unref (self); } static void socks5_connect (GabbleBytestreamSocks5 *self) { GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); Streamhost* streamhost; GibberTCPTransport *transport; priv->socks5_state = SOCKS5_STATE_TARGET_TRYING_CONNECT; if (priv->streamhosts != NULL) { streamhost = priv->streamhosts->data; } else { DEBUG ("No more streamhosts to try, closing"); socks5_error (self); return; } DEBUG ("Trying streamhost %s on port %d", streamhost->host, streamhost->port); transport = gibber_tcp_transport_new (); set_transport (self, GIBBER_TRANSPORT (transport)); g_object_unref (transport); /* We don't wait to wait for the TCP timeout is the host is unreachable */ start_timer (self, CONNECT_TIMEOUT); gibber_tcp_transport_connect (transport, streamhost->host, streamhost->port); /* We'll send the auth request once the transport is connected */ } /** * gabble_bytestream_socks5_add_streamhost * * Adds the streamhost as a candidate for connection. */ void gabble_bytestream_socks5_add_streamhost (GabbleBytestreamSocks5 *self, WockyNode *streamhost_node) { GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); const gchar *zeroconf; const gchar *jid; const gchar *host; const gchar *portstr; gint64 port; Streamhost *streamhost; g_return_if_fail (!tp_strdiff (streamhost_node->name, "streamhost")); zeroconf = wocky_node_get_attribute (streamhost_node, "zeroconf"); if (zeroconf != NULL) { /* TODO: add suppport for zeroconf */ DEBUG ("zeroconf streamhosts are not supported"); return; } jid = wocky_node_get_attribute (streamhost_node, "jid"); if (jid == NULL) { DEBUG ("streamhost doesn't contain a JID"); return; } host = wocky_node_get_attribute (streamhost_node, "host"); if (host == NULL) { DEBUG ("streamhost doesn't contain a host"); return; } portstr = wocky_node_get_attribute (streamhost_node, "port"); if (portstr == NULL) { DEBUG ("streamhost doesn't contain a port"); return; } port = g_ascii_strtoll (portstr, NULL, 10); if (port <= 0 || port > G_MAXUINT16) { DEBUG ("Invalid port: %s", portstr); return; } if (tp_strdiff (jid, priv->peer_jid) && priv->muc_contact) { DEBUG ("skip streamhost %s (%s:%"G_GINT64_FORMAT "); we don't support relay with muc contact", jid, host, port); return; } DEBUG ("streamhost with jid %s, host %s and port %"G_GINT64_FORMAT" added", jid, host, port); streamhost = streamhost_new (jid, host, port); priv->streamhosts = g_slist_append (priv->streamhosts, streamhost); } /** * gabble_bytestream_socks5_connect_to_streamhost * * Try to connect to a streamhost. */ void gabble_bytestream_socks5_connect_to_streamhost (GabbleBytestreamSocks5 *self, WockyStanza *msg) { GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); priv->msg_for_acknowledge_connection = g_object_ref (msg); socks5_connect (self); } /* * gabble_bytestream_socks5_send * * Implements gabble_bytestream_iface_send on GabbleBytestreamIface */ static gboolean gabble_bytestream_socks5_send (GabbleBytestreamIface *iface, guint len, const gchar *str) { GabbleBytestreamSocks5 *self = GABBLE_BYTESTREAM_SOCKS5 (iface); GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); GError *error = NULL; if (priv->bytestream_state != GABBLE_BYTESTREAM_STATE_OPEN) { DEBUG ("can't send data through a not open bytestream (state: %d)", priv->bytestream_state); return FALSE; } /* if something goes wrong during the sending, the bytestream could be * closed and so disposed by the bytestream factory. Ref it to keep it * artifically alive if such case happen. */ g_object_ref (self); if (!write_to_transport (self, str, len, &error)) { DEBUG ("sending failed: %s", error->message); g_error_free (error); gabble_bytestream_iface_close (GABBLE_BYTESTREAM_IFACE (self), NULL); g_object_unref (self); return FALSE; } /* If something wennt wrong during the writting, the transport has been closed * and so set to NULL. */ if (priv->transport == NULL) { g_object_unref (self); return FALSE; } /* At this point we know that the bytestream has not been closed */ g_object_unref (self); if (!gibber_transport_buffer_is_empty (priv->transport)) { /* We >don't want to send more data while the buffer isn't empty */ change_write_blocked_state (self, TRUE); } return TRUE; } /* * gabble_bytestream_socks5_accept * * Implements gabble_bytestream_iface_accept on GabbleBytestreamIface */ static void gabble_bytestream_socks5_accept (GabbleBytestreamIface *iface, GabbleBytestreamAugmentSiAcceptReply func, gpointer user_data) { GabbleBytestreamSocks5 *self = GABBLE_BYTESTREAM_SOCKS5 (iface); GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); WockyStanza *msg; WockyNode *si; if (priv->bytestream_state != GABBLE_BYTESTREAM_STATE_LOCAL_PENDING) { /* The stream was previoulsy or automatically accepted */ return; } msg = gabble_bytestream_factory_make_accept_iq (priv->peer_jid, priv->stream_init_id, NS_BYTESTREAMS); si = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "si", NS_SI); g_assert (si != NULL); if (func != NULL) { /* let the caller add his profile specific data */ func (si, user_data); } if (_gabble_connection_send (priv->conn, msg, NULL)) { DEBUG ("stream %s with %s is now accepted", priv->stream_id, priv->peer_jid); g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_ACCEPTED, NULL); } g_object_unref (msg); } static void gabble_bytestream_socks5_decline (GabbleBytestreamSocks5 *self, GError *error) { GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); WockyStanza *msg; g_return_if_fail (priv->bytestream_state == GABBLE_BYTESTREAM_STATE_LOCAL_PENDING); msg = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, NULL, priv->peer_jid, '@', "id", priv->stream_init_id, NULL); if (error != NULL) { wocky_stanza_error_to_node (error, wocky_stanza_get_top_node (msg)); } else { GError fallback = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_FORBIDDEN, "Offer Declined" }; wocky_stanza_error_to_node (&fallback, wocky_stanza_get_top_node (msg)); } _gabble_connection_send (priv->conn, msg, NULL); g_object_unref (msg); g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_CLOSED, NULL); } /* * gabble_bytestream_socks5_close * * Implements gabble_bytestream_iface_close on GabbleBytestreamIface */ static void gabble_bytestream_socks5_close (GabbleBytestreamIface *iface, GError *error) { GabbleBytestreamSocks5 *self = GABBLE_BYTESTREAM_SOCKS5 (iface); GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); if (priv->bytestream_state == GABBLE_BYTESTREAM_STATE_CLOSED) /* bytestream already closed, do nothing */ return; if (priv->bytestream_state == GABBLE_BYTESTREAM_STATE_LOCAL_PENDING) { /* Stream was created using SI so we decline the request */ gabble_bytestream_socks5_decline (self, error); } else { g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_CLOSING, NULL); if (priv->transport != NULL && !gibber_transport_buffer_is_empty (priv->transport)) { DEBUG ("Wait transport buffer is empty before close the bytestream"); } else { DEBUG ("Transport buffer is empty, we can close the bytestream"); bytestream_closed (self); } } } static void initiator_connected_to_proxy (GabbleBytestreamSocks5 *self) { GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE ( self); GSList *proxies, *l; GabbleSocks5Proxy *proxy = NULL; GibberTCPTransport *transport; proxies = gabble_bytestream_factory_get_socks5_proxies ( priv->conn->bytestream_factory); for (l = proxies; l != NULL; l = g_slist_next (l)) { proxy = (GabbleSocks5Proxy *) l->data; if (!tp_strdiff (proxy->jid, priv->proxy_jid)) break; proxy = NULL; } g_slist_free (proxies); if (proxy == NULL) { DEBUG ("Unknown proxy: %s. Closing the bytestream", priv->proxy_jid); g_signal_emit_by_name (self, "connection-error"); g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_CLOSED, NULL); return; } DEBUG ("connect to proxy: %s (%s:%d)", proxy->jid, proxy->host, proxy->port); priv->socks5_state = SOCKS5_STATE_INITIATOR_TRYING_CONNECT; transport = gibber_tcp_transport_new (); set_transport (self, GIBBER_TRANSPORT (transport)); g_object_unref (transport); gibber_tcp_transport_connect (transport, proxy->host, proxy->port); } static void socks5_init_reply_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { TpWeakRef *weak_ref = user_data; GabbleBytestreamSocks5 *self = tp_weak_ref_dup_object (weak_ref); GabbleBytestreamSocks5Private *priv; WockyStanza *reply_msg = NULL; tp_weak_ref_destroy (weak_ref); if (self == NULL) return; priv = self->priv; if (conn_util_send_iq_finish (GABBLE_CONNECTION (source), result, &reply_msg, NULL)) { WockyNode *query, *streamhost = NULL; const gchar *jid; query = wocky_node_get_child_ns ( wocky_stanza_get_top_node (reply_msg), "query", NS_BYTESTREAMS); if (query != NULL) streamhost = wocky_node_get_child (query, "streamhost-used"); if (streamhost == NULL) { DEBUG ("no streamhost-used has been defined. Closing the bytestream"); goto socks5_init_error; } jid = wocky_node_get_attribute (streamhost, "jid"); if (jid == NULL) { DEBUG ("no jid attribute in streamhost. Closing the bytestream"); goto socks5_init_error; } if (tp_strdiff (jid, priv->self_full_jid)) { DEBUG ("Target is connected to proxy: %s", jid); if (priv->socks5_state != SOCKS5_STATE_INITIATOR_OFFER_SENT) { DEBUG ("We are already in the negotiation process (state: %u). " "Closing the bytestream", priv->socks5_state); goto socks5_init_error; } priv->proxy_jid = g_strdup (jid); initiator_connected_to_proxy (self); goto out; } /* No proxy used */ DEBUG ("Target is connected to us"); if (priv->socks5_state != SOCKS5_STATE_CONNECTED) { DEBUG ("Target claims that the bytestream is open but SOCKS5 is not " "connected (state: %u). Closing the bytestream", priv->socks5_state); goto socks5_init_error; } /* yeah, stream initiated */ DEBUG ("Socks5 stream initiated using stream: %s", jid); g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_OPEN, NULL); /* We can read data from the sock5 socket now */ gibber_transport_block_receiving (priv->transport, FALSE); goto out; } socks5_init_error: DEBUG ("error during Socks5 initiation"); g_signal_emit_by_name (self, "connection-error"); g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_CLOSED, NULL); out: g_clear_object (&reply_msg); g_object_unref (self); } #ifdef G_OS_WIN32 static GSList * get_local_interfaces_ips (void) { gint sockfd; INTERFACE_INFO *iflist = NULL; gsize size = 0; int ret; int error; gsize bytes; gsize num; gsize i; struct sockaddr_in *sa; GSList *ips = NULL; /* FIXME: add IPv6 addresses */ if ((sockfd = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP)) == (int) INVALID_SOCKET) { DEBUG ("Cannot open socket to retrieve interface list"); return NULL; } /* Loop and get each interface the system has, one by one... */ do { size += sizeof (INTERFACE_INFO); /* realloc buffer size until no overflow occurs */ if (NULL == (iflist = realloc (iflist, size))) { DEBUG ("Out of memory while allocation interface configuration" " structure"); closesocket (sockfd); return NULL; } ret = WSAIoctl (sockfd, SIO_GET_INTERFACE_LIST, NULL, 0, iflist, size, (LPDWORD) &bytes, NULL, NULL); error = WSAGetLastError (); if (ret == SOCKET_ERROR && error != WSAEFAULT) { DEBUG ("Cannot retrieve interface list"); closesocket (sockfd); free (iflist); return NULL; } } while (ret == SOCKET_ERROR); num = bytes / sizeof (INTERFACE_INFO); /* Loop throught the interface list and get the IP address of each IF */ for (i = 0; i < num; i++) { /* no ip address from interface that is down */ if ((iflist[i].iiFlags & IFF_UP) == 0) continue; if ((iflist[i].iiFlags & IFF_LOOPBACK) == IFF_LOOPBACK) { DEBUG ("Ignoring loopback interface"); continue; } sa = (struct sockaddr_in *) &(iflist[i].iiAddress); ips = g_slist_prepend (ips, g_strdup (inet_ntoa (sa->sin_addr))); DEBUG ("IP Address: %s", inet_ntoa (sa->sin_addr)); } closesocket (sockfd); free (iflist); return ips; } #else /* get_local_interfaces_ips original code from Farsight 2 (function * fs_interfaces_get_local_ips in /gst-libs/gst/farsight/fs-interfaces.c). * Copyright (C) 2006 Youness Alaoui * Copyright (C) 2007 Collabora */ #ifdef HAVE_GETIFADDRS static GSList * get_local_interfaces_ips (void) { struct ifaddrs *ifa, *results; GSList *ips = NULL; if (getifaddrs (&results) < 0) return NULL; /* Loop through the interface list and get the IP address of each IF */ for (ifa = results; ifa; ifa = ifa->ifa_next) { char straddr[INET6_ADDRSTRLEN]; /* no ip address from interface that is down */ if ((ifa->ifa_flags & IFF_UP) == 0) continue; if (ifa->ifa_addr == NULL) continue; if ((ifa->ifa_flags & IFF_LOOPBACK) == IFF_LOOPBACK) { DEBUG ("Ignoring loopback interface"); continue; } if (ifa->ifa_addr->sa_family == AF_INET) { struct sockaddr_in *sa = (struct sockaddr_in *) ifa->ifa_addr; inet_ntop (AF_INET, &sa->sin_addr, straddr, sizeof (straddr)); /* Add IPv4 addresses to the end of the list */ ips = g_slist_append (ips, g_strdup (straddr)); } else if (ifa->ifa_addr->sa_family == AF_INET6) { struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) ifa->ifa_addr; inet_ntop (AF_INET6, &sa6->sin6_addr, straddr, sizeof (straddr)); if (IN6_IS_ADDR_LINKLOCAL (&sa6->sin6_addr)) { DEBUG ("Ignoring link-local address: %s", straddr); continue; } /* Add IPv6 addresss to the begin of the list */ ips = g_slist_prepend (ips, g_strdup (straddr)); } else { continue; } DEBUG ("Interface: %s", ifa->ifa_name); DEBUG ("IP Address: %s", straddr); } freeifaddrs (results); return ips; } #else /* ! HAVE_GETIFADDRS */ static GSList * get_local_interfaces_ips (void) { gint sockfd; gint size = 0; struct ifreq *ifr; struct ifconf ifc; struct sockaddr_in *sa; GSList *ips = NULL; /* FIXME: add IPv6 addresses */ if ((sockfd = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) { DEBUG ("Cannot open socket to retreive interface list"); return NULL; } ifc.ifc_len = 0; ifc.ifc_req = NULL; /* Loop and get each interface the system has, one by one... */ do { size += sizeof (struct ifreq); /* realloc buffer size until no overflow occurs */ if (NULL == (ifc.ifc_req = realloc (ifc.ifc_req, size))) { DEBUG ("Out of memory while allocation interface configuration" " structure"); close (sockfd); return NULL; } ifc.ifc_len = size; if (ioctl (sockfd, SIOCGIFCONF, &ifc)) { DEBUG ("ioctl SIOCFIFCONF"); close (sockfd); free (ifc.ifc_req); return NULL; } } while (size <= ifc.ifc_len); /* Loop throught the interface list and get the IP address of each IF */ for (ifr = ifc.ifc_req; (gchar *) ifr < (gchar *) ifc.ifc_req + ifc.ifc_len; ++ifr) { if (ioctl (sockfd, SIOCGIFFLAGS, ifr)) { DEBUG ("Unable to get IP information for interface %s. Skipping...", ifr->ifr_name); continue; /* failed to get flags, skip it */ } sa = (struct sockaddr_in *) &ifr->ifr_addr; DEBUG ("Interface: %s", ifr->ifr_name); DEBUG ("IP Address: %s", inet_ntoa (sa->sin_addr)); if ((ifr->ifr_flags & IFF_LOOPBACK) == IFF_LOOPBACK) { DEBUG ("Ignoring loopback interface"); } else { ips = g_slist_prepend (ips, g_strdup (inet_ntoa (sa->sin_addr))); } } close (sockfd); free (ifc.ifc_req); return ips; } #endif /* ! HAVE_GETIFADDRS */ #endif /* ! G_OS_WIN32 */ static void new_connection_cb (GibberListener *listener, GibberTransport *transport, struct sockaddr *addr, guint size, gpointer user_data) { GabbleBytestreamSocks5 *self = GABBLE_BYTESTREAM_SOCKS5 (user_data); GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); DEBUG ("New connection..."); priv->socks5_state = SOCKS5_STATE_INITIATOR_AWAITING_AUTH_REQUEST; set_transport (self, transport); } /* * Consumes @ips. */ static void send_streamhosts ( GabbleBytestreamSocks5 *self, GSList *ips, gint port_num) { GabbleBytestreamSocks5Private *priv = self->priv; gchar *port; WockyStanza *msg; WockyNode *query_node; port = g_strdup_printf ("%d", port_num); msg = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, priv->peer_jid, '(', "query", ':', NS_BYTESTREAMS, '@', "sid", priv->stream_id, '@', "mode", "tcp", '*', &query_node, ')', NULL); for (; port_num != 0 && ips != NULL; ips = g_slist_delete_link (ips, ips)) { WockyNode *node = wocky_node_add_child (query_node, "streamhost"); wocky_node_set_attributes (node, "jid", priv->self_full_jid, "host", ips->data, "port", port, NULL); g_free (ips->data); } g_slist_free (ips); g_free (port); if (!priv->muc_contact) { GSList *proxies, *l; proxies = gabble_bytestream_factory_get_socks5_proxies ( priv->conn->bytestream_factory); for (l = proxies; l != NULL; l = g_slist_next (l)) { WockyNode *node = wocky_node_add_child (query_node, "streamhost"); gchar *portstr; GabbleSocks5Proxy *proxy = (GabbleSocks5Proxy *) l->data; portstr = g_strdup_printf ("%d", proxy->port); wocky_node_set_attributes (node, "jid", proxy->jid, "host", proxy->host, "port", portstr, NULL); g_free (portstr); } g_slist_free (proxies); } else { DEBUG ("don't propose to use SOCKS5 relays as we are offering bytestream " "to a muc contact"); } priv->socks5_state = SOCKS5_STATE_INITIATOR_OFFER_SENT; conn_util_send_iq_async (priv->conn, msg, NULL, socks5_init_reply_cb, tp_weak_ref_new (self, NULL, NULL)); g_object_unref (msg); } /* * gabble_bytestream_socks5_initiate * * Implements gabble_bytestream_iface_initiate on GabbleBytestreamIface */ static gboolean gabble_bytestream_socks5_initiate (GabbleBytestreamIface *iface) { GabbleBytestreamSocks5 *self = GABBLE_BYTESTREAM_SOCKS5 (iface); GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); GSList *ips; guint port_num = 0; if (priv->bytestream_state != GABBLE_BYTESTREAM_STATE_INITIATING) { DEBUG ("bytestream is not is the initiating state (state %d)", priv->bytestream_state); return FALSE; } ips = get_local_interfaces_ips (); if (ips == NULL) { DEBUG ("Can't get IP addresses; will send empty offer."); } else { g_assert (priv->listener == NULL); priv->listener = gibber_listener_new (); g_signal_connect (priv->listener, "new-connection", G_CALLBACK (new_connection_cb), self); if (!gibber_listener_listen_tcp (priv->listener, 0, NULL)) { DEBUG ("can't listen for incoming connection; will send empty offer."); g_slist_foreach (ips, (GFunc) g_free, NULL); g_slist_free (ips); ips = NULL; } port_num = gibber_listener_get_port (priv->listener); } send_streamhosts (self, ips, port_num); return TRUE; } static void gabble_bytestream_socks5_block_reading (GabbleBytestreamIface *iface, gboolean block) { GabbleBytestreamSocks5 *self = GABBLE_BYTESTREAM_SOCKS5 (iface); GabbleBytestreamSocks5Private *priv = GABBLE_BYTESTREAM_SOCKS5_GET_PRIVATE (self); if (priv->read_blocked == block) return; priv->read_blocked = block; if (priv->transport != NULL) gibber_transport_block_receiving (priv->transport, block); } static void bytestream_iface_init (gpointer g_iface, gpointer iface_data) { GabbleBytestreamIfaceClass *klass = (GabbleBytestreamIfaceClass *) g_iface; klass->initiate = gabble_bytestream_socks5_initiate; klass->send = gabble_bytestream_socks5_send; klass->close = gabble_bytestream_socks5_close; klass->accept = gabble_bytestream_socks5_accept; klass->block_reading = gabble_bytestream_socks5_block_reading; } telepathy-gabble-0.18.3/src/message-util.c0000664000175000017500000003705412332441362021541 0ustar00cassidycassidy00000000000000/* * message-util.c - Messages interface utility functions * Copyright (C) 2006-2008 Collabora Ltd. * Copyright (C) 2006-2008 Nokia Corporation * @author Ole Andre Vadla Ravnaas * @author Robert McQueen * @author Senko Rasic * @author Will Thompson * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "message-util.h" #include #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_IM #include "debug.h" #include "namespaces.h" #include "util.h" void gabble_message_util_add_chat_state (WockyStanza *stanza, TpChannelChatState state) { WockyNode *n = wocky_stanza_get_top_node (stanza); const gchar *node_name = NULL; switch (state) { case TP_CHANNEL_CHAT_STATE_GONE: node_name = "gone"; break; case TP_CHANNEL_CHAT_STATE_INACTIVE: node_name = "inactive"; break; case TP_CHANNEL_CHAT_STATE_ACTIVE: node_name = "active"; break; case TP_CHANNEL_CHAT_STATE_PAUSED: node_name = "paused"; break; case TP_CHANNEL_CHAT_STATE_COMPOSING: node_name = "composing"; break; } if (node_name != NULL) wocky_node_add_child_ns_q (n, node_name, g_quark_from_static_string (NS_CHAT_STATES)); } /** * gabble_message_util_build_stanza * @message: the message to be sent * @conn: the connection owning this channel * @subtype: the Loudmouth message subtype * @state: the Telepathy chat state, or -1 if unknown or not applicable * @recipient: the recipient's JID * @send_nick: whether to include our own nick in the message * @token: return the message id * @error: return the error if operation failed * * Returns: The wocky stanza for the message */ WockyStanza * gabble_message_util_build_stanza (TpMessage *message, GabbleConnection *conn, WockyStanzaSubType subtype, TpChannelChatState state, const char *recipient, gboolean send_nick, gchar **token, GError **error) { const GHashTable *part; WockyStanza *stanza = NULL; WockyNode *node; guint type = TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL; gboolean result = TRUE; const gchar *content_type, *text; gchar *id = NULL; guint n_parts; #define RETURN_INVALID_ARGUMENT(msg, ...) \ G_STMT_START { \ DEBUG (msg , ## __VA_ARGS__); \ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, \ msg , ## __VA_ARGS__); \ return NULL; \ } G_STMT_END part = tp_message_peek (message, 0); if (tp_asv_lookup (part, "message-type") != NULL) type = tp_asv_get_uint32 (part, "message-type", &result); if (!result) RETURN_INVALID_ARGUMENT ("message-type must be a 32-bit unsigned integer"); if (type >= NUM_TP_CHANNEL_TEXT_MESSAGE_TYPES) RETURN_INVALID_ARGUMENT ("invalid message type: %u", type); n_parts = tp_message_count_parts (message); if (n_parts != 2) RETURN_INVALID_ARGUMENT ("message must contain exactly 1 part, not %u", (n_parts - 1)); part = tp_message_peek (message, 1); content_type = tp_asv_get_string (part, "content-type"); text = tp_asv_get_string (part, "content"); if (content_type == NULL || tp_strdiff (content_type, "text/plain")) RETURN_INVALID_ARGUMENT ("message must be text/plain"); if (text == NULL) RETURN_INVALID_ARGUMENT ("content must be a UTF-8 string"); if (!subtype) { switch (type) { case TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL: case TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION: subtype = WOCKY_STANZA_SUB_TYPE_CHAT; break; case TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE: subtype = WOCKY_STANZA_SUB_TYPE_NORMAL; break; } } /* Generate a UUID for the message */ id = gabble_generate_id (); tp_message_set_string (message, 0, "message-token", id); stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, subtype, NULL, recipient, '@', "id", id, '*', &node, NULL); if (send_nick) lm_message_node_add_own_nick (node, conn); if (type == TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION) { gchar *tmp; tmp = g_strconcat ("/me ", text, NULL); wocky_node_add_child_with_content (node, "body", tmp); g_free (tmp); } else { wocky_node_add_child_with_content (node, "body", text); } gabble_message_util_add_chat_state (stanza, state); if (token != NULL) *token = id; else g_free (id); gabble_connection_update_last_use (conn); return stanza; } /** * gabble_message_util_send_chat_state: * @obj: a channel implementation featuring TpMessageMixin * @conn: the connection owning this channel * @subtype: the Loudmouth message subtype * @state: the Telepathy chat state * @recipient: the recipient's JID * @error: pointer in which to return a GError in case of failure. * * Returns: %TRUE if the message was sent successfully; %FALSE otherwise. */ gboolean gabble_message_util_send_chat_state (GObject *obj, GabbleConnection *conn, WockyStanzaSubType subtype, TpChannelChatState state, const char *recipient, GError **error) { WockyStanza *msg = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, subtype, NULL, recipient, NULL); gboolean result; gabble_message_util_add_chat_state (msg, state); result = _gabble_connection_send (conn, msg, error); g_object_unref (msg); return result; } TpChannelTextSendError gabble_tp_send_error_from_wocky_xmpp_error (WockyXmppError err) { switch (err) { /* Note: Google replies with if you send a * message to someone you're not subscribed to. But * http://xmpp.org/rfcs/rfc3921.html#rules explicitly says that means * the user is offline and doesn't have offline storage. I think Google * should be returning or . --wjt */ case WOCKY_XMPP_ERROR_SERVICE_UNAVAILABLE: case WOCKY_XMPP_ERROR_RECIPIENT_UNAVAILABLE: return TP_CHANNEL_TEXT_SEND_ERROR_OFFLINE; case WOCKY_XMPP_ERROR_ITEM_NOT_FOUND: case WOCKY_XMPP_ERROR_JID_MALFORMED: case WOCKY_XMPP_ERROR_REMOTE_SERVER_TIMEOUT: return TP_CHANNEL_TEXT_SEND_ERROR_INVALID_CONTACT; case WOCKY_XMPP_ERROR_FORBIDDEN: case WOCKY_XMPP_ERROR_NOT_AUTHORIZED: case WOCKY_XMPP_ERROR_POLICY_VIOLATION: return TP_CHANNEL_TEXT_SEND_ERROR_PERMISSION_DENIED; case WOCKY_XMPP_ERROR_RESOURCE_CONSTRAINT: return TP_CHANNEL_TEXT_SEND_ERROR_TOO_LONG; case WOCKY_XMPP_ERROR_FEATURE_NOT_IMPLEMENTED: return TP_CHANNEL_TEXT_SEND_ERROR_NOT_IMPLEMENTED; default: return TP_CHANNEL_TEXT_SEND_ERROR_UNKNOWN; } } static TpChannelTextSendError _tp_send_error_from_xmpp_error ( WockyXmppErrorType error_type, GError *error, TpDeliveryStatus *delivery_status) { /* The thing calling us should have got this back from * wocky_stanza_extract_errors(). */ g_assert (error->domain == WOCKY_XMPP_ERROR); DEBUG ("got xmpp error: %s (type=%u): '%s'", wocky_xmpp_stanza_error_to_string (error), error_type, error->message); if (error_type == WOCKY_XMPP_ERROR_TYPE_WAIT) *delivery_status = TP_DELIVERY_STATUS_TEMPORARILY_FAILED; else *delivery_status = TP_DELIVERY_STATUS_PERMANENTLY_FAILED; /* these are based on descriptions of errors, and some testing */ switch (error->code) { /* Note: Google replies with if you send a * message to someone you're not subscribed to. But * http://xmpp.org/rfcs/rfc3921.html#rules explicitly says that means * the user is offline and doesn't have offline storage. I think Google * should be returning or . --wjt */ case WOCKY_XMPP_ERROR_SERVICE_UNAVAILABLE: case WOCKY_XMPP_ERROR_RECIPIENT_UNAVAILABLE: return TP_CHANNEL_TEXT_SEND_ERROR_OFFLINE; case WOCKY_XMPP_ERROR_ITEM_NOT_FOUND: case WOCKY_XMPP_ERROR_JID_MALFORMED: case WOCKY_XMPP_ERROR_REMOTE_SERVER_TIMEOUT: return TP_CHANNEL_TEXT_SEND_ERROR_INVALID_CONTACT; case WOCKY_XMPP_ERROR_FORBIDDEN: case WOCKY_XMPP_ERROR_NOT_AUTHORIZED: return TP_CHANNEL_TEXT_SEND_ERROR_PERMISSION_DENIED; case WOCKY_XMPP_ERROR_RESOURCE_CONSTRAINT: return TP_CHANNEL_TEXT_SEND_ERROR_TOO_LONG; case WOCKY_XMPP_ERROR_FEATURE_NOT_IMPLEMENTED: return TP_CHANNEL_TEXT_SEND_ERROR_NOT_IMPLEMENTED; default: return TP_CHANNEL_TEXT_SEND_ERROR_UNKNOWN; } } static gint _tp_chat_state_from_message (WockyStanza *message) { WockyNode *node; #define MAP_TO(str, state) \ node = wocky_node_get_child_ns ( \ wocky_stanza_get_top_node (message), str, \ NS_CHAT_STATES); \ if (node != NULL) \ return state; MAP_TO ("active", TP_CHANNEL_CHAT_STATE_ACTIVE); MAP_TO ("composing", TP_CHANNEL_CHAT_STATE_COMPOSING); MAP_TO ("inactive", TP_CHANNEL_CHAT_STATE_INACTIVE); MAP_TO ("paused", TP_CHANNEL_CHAT_STATE_PAUSED); MAP_TO ("gone", TP_CHANNEL_CHAT_STATE_GONE); #undef MAP_TO return -1; } /** * gabble_message_util_parse_incoming_message: * @message: an incoming XMPP message * @from: will be set to the message sender's jid. * @stamp: will be set to the message's timestamp if it's a delayed message, or * to 0 otherwise. * @msgtype: will be set to the message's type. * @body_ret: will be set to the contents of the message's body, or %NULL if it * had no body. * @state: will be set to the %TpChannelChatState of the message, or -1 if * there was no chat state in the message. * @send_error: set to the relevant send error if the message contained an * error node, or to %GABBLE_TEXT_CHANNEL_SEND_NO_ERROR otherwise. * @delivery_status: set to TemporarilyFailed if an is * encountered, to PermanentlyFailed if any other is * encountered, and to Unknown otherwise. * * Parses an incoming stanza, producing various bits of the message * as various out parameters. * * Returns: %TRUE if the was successfully parsed, even if it * contained no body, chat state or send error; %FALSE otherwise. */ gboolean gabble_message_util_parse_incoming_message (WockyStanza *message, const gchar **from, time_t *stamp, TpChannelTextMessageType *msgtype, const gchar **id, const gchar **body_ret, gint *state, TpChannelTextSendError *send_error, TpDeliveryStatus *delivery_status) { const gchar *type, *body; WockyNode *node; WockyXmppErrorType error_type; GError *error = NULL; *send_error = GABBLE_TEXT_CHANNEL_SEND_NO_ERROR; *delivery_status = TP_DELIVERY_STATUS_UNKNOWN; if (wocky_stanza_extract_errors (message, &error_type, &error, NULL, NULL)) { *send_error = _tp_send_error_from_xmpp_error (error_type, error, delivery_status); g_clear_error (&error); } *id = wocky_node_get_attribute (wocky_stanza_get_top_node (message), "id"); *from = wocky_node_get_attribute (wocky_stanza_get_top_node (message), "from"); if (*from == NULL) { STANZA_DEBUG (message, "got a message without a from field"); return FALSE; } type = wocky_node_get_attribute (wocky_stanza_get_top_node (message), "type"); /* * Parse timestamp of delayed messages. For non-delayed, it's * 0 and the channel code should set the current timestamp. */ *stamp = 0; node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (message), "x", NS_X_DELAY); if (node != NULL) { const gchar *stamp_str; /* These timestamps do not contain a timezone, but are understood to be * in GMT. They're in the format yyyymmddThhmmss, so if we append 'Z' * we'll get (one of the many valid syntaxes for) an ISO-8601 timestamp. */ stamp_str = wocky_node_get_attribute (node, "stamp"); if (stamp_str != NULL) { GTimeVal timeval = { 0, 0 }; gchar *stamp_dup = g_strdup_printf ("%sZ", stamp_str); if (g_time_val_from_iso8601 (stamp_dup, &timeval)) { *stamp = timeval.tv_sec; } else { DEBUG ("%s: malformed date string '%s' for jabber:x:delay", G_STRFUNC, stamp_str); } g_free (stamp_dup); } } /* * Parse body if it exists. */ node = wocky_node_get_child (wocky_stanza_get_top_node (message), "body"); if (node) { body = node->content; } else { body = NULL; } /* Messages starting with /me are ACTION messages, and the /me should be * removed. type="chat" messages are NORMAL. everything else is * something that doesn't necessarily expect a reply or ongoing * conversation ("normal") or has been auto-sent, so we make it NOTICE in * all other cases. */ *msgtype = TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE; *body_ret = body; if (body != NULL) { if (wocky_node_get_child_ns ( wocky_stanza_get_top_node (message), "google-rbc-announcement", "google:metadata") != NULL) { /* Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=36647 */ return FALSE; } if (type == NULL && wocky_node_get_child_ns ( wocky_stanza_get_top_node (message), "time", "google:timestamp") != NULL && wocky_node_get_child_ns ( wocky_stanza_get_top_node (message), "x", "jabber:x:delay") != NULL) { /* Google servers send offline messages without a type. Work around * this. */ *msgtype = TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL; } else if (0 == strncmp (body, "/me ", 4)) { *msgtype = TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION; *body_ret = body + 4; } else if (type != NULL && (0 == strcmp (type, "chat") || 0 == strcmp (type, "groupchat"))) { *msgtype = TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL; *body_ret = body; } } /* Parse chat state if it exists. */ *state = _tp_chat_state_from_message (message); return TRUE; } telepathy-gabble-0.18.3/src/tube-stream.c0000664000175000017500000021177012332441362021371 0ustar00cassidycassidy00000000000000/* * tube-stream.c - Source for GabbleTubeStream * Copyright (C) 2007-2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "tube-stream.h" #include #include #include #include #ifdef HAVE_UNISTD_H # include #endif #include #include #include #include "extensions/extensions.h" #define DEBUG_FLAG GABBLE_DEBUG_TUBES #include #include #include #include #include #include #include "bytestream-factory.h" #include "bytestream-iface.h" #include "connection.h" #include "debug.h" #include "disco.h" #include "gabble-signals-marshal.h" #include "muc-channel.h" #include "muc-tube-stream.h" #include "namespaces.h" #include "presence-cache.h" #include "presence.h" #include "tube-iface.h" #include "util.h" static void tube_iface_init (gpointer g_iface, gpointer iface_data); static void streamtube_iface_init (gpointer g_iface, gpointer iface_data); G_DEFINE_TYPE_WITH_CODE (GabbleTubeStream, gabble_tube_stream, TP_TYPE_BASE_CHANNEL, G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, tp_dbus_properties_mixin_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_TUBE_IFACE, tube_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_STREAM_TUBE, streamtube_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_TUBE, NULL); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP, tp_external_group_mixin_iface_init); ); static const gchar * const gabble_tube_stream_channel_allowed_properties[] = { TP_IFACE_CHANNEL ".TargetHandle", TP_IFACE_CHANNEL ".TargetID", TP_IFACE_CHANNEL_TYPE_STREAM_TUBE ".Service", NULL }; /* Linux glibc bits/socket.h suggests that struct sockaddr_storage is * not guaranteed to be big enough for AF_UNIX addresses */ typedef union { #ifdef GIBBER_TYPE_UNIX_TRANSPORT /* we'd call this unix, but gcc predefines that. Thanks, gcc */ struct sockaddr_un un; #endif struct sockaddr_in ipv4; struct sockaddr_in6 ipv6; } SockAddr; /* signals */ enum { OPENED, NEW_CONNECTION, CLOSED, OFFERED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; /* properties */ enum { PROP_SELF_HANDLE = 1, PROP_ID, PROP_TYPE, PROP_SERVICE, PROP_PARAMETERS, PROP_STATE, PROP_ADDRESS_TYPE, PROP_ADDRESS, PROP_ACCESS_CONTROL, PROP_ACCESS_CONTROL_PARAM, PROP_SUPPORTED_SOCKET_TYPES, PROP_MUC, LAST_PROPERTY }; struct _GabbleTubeStreamPrivate { TpHandle self_handle; guint64 id; /* Bytestreams for tubes. One tube can have several bytestreams. The * mapping between the tube bytestream and the transport to the local * application is stored in the transport_to_bytestream and * bytestream_to_transport fields. This is used both on initiator-side and * on recipient-side. */ /* (GabbleBytestreamIface *) -> (GibberTransport *) * * The (b->t) is inserted as soon as they are created. On initiator side, * we receive an incoming bytestream, create a transport and insert (b->t). * On recipient side, we receive an incoming transport, create a bytestream * and insert (b->t). */ GHashTable *bytestream_to_transport; /* (GibberTransport *) -> (GabbleBytestreamIface *) * * The (t->b) is also inserted as soon as they are created. */ GHashTable *transport_to_bytestream; /* (GibberTransport *) -> guint */ GHashTable *transport_to_id; guint last_connection_id; gchar *service; GHashTable *parameters; TpTubeChannelState state; TpSocketAddressType address_type; GValue *address; TpSocketAccessControl access_control; GValue *access_control_param; /* listen for connections from local applications */ GibberListener *local_listener; GabbleMucChannel *muc; gboolean dispose_has_run; }; static GPtrArray * gabble_tube_stream_get_interfaces (TpBaseChannel *base) { GPtrArray *interfaces; interfaces = TP_BASE_CHANNEL_CLASS ( gabble_tube_stream_parent_class)->get_interfaces (base); g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_TUBE); return interfaces; } typedef struct { GabbleTubeStream *self; TpHandle contact; } transport_connected_data; static void data_received_cb (GabbleBytestreamIface *ibb, TpHandle sender, GString *data, gpointer user_data); static void transport_connected_cb (GibberTransport *transport, transport_connected_data *data); #ifdef GIBBER_TYPE_UNIX_TRANSPORT static void generate_ascii_string (guint len, gchar *buf) { const gchar *chars = "0123456789" "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "_-"; guint i; for (i = 0; i < len; i++) buf[i] = chars[g_random_int_range (0, 64)]; } #endif static void transport_handler (GibberTransport *transport, GibberBuffer *data, gpointer user_data) { GabbleTubeStream *self = GABBLE_TUBE_STREAM (user_data); GabbleTubeStreamPrivate *priv = self->priv; GabbleBytestreamIface *bytestream; bytestream = g_hash_table_lookup (priv->transport_to_bytestream, transport); if (bytestream == NULL) { DEBUG ("no open bytestream associated with this transport"); return; } gabble_bytestream_iface_send (bytestream, data->length, (const gchar *) data->data); } static void fire_connection_closed (GabbleTubeStream *self, GibberTransport *transport, const gchar *error, const gchar *debug_msg) { GabbleTubeStreamPrivate *priv = self->priv; guint connection_id; connection_id = GPOINTER_TO_UINT (g_hash_table_lookup (priv->transport_to_id, transport)); if (connection_id == 0) { DEBUG ("ConnectionClosed has already been fired for this connection"); return; } /* remove the ID so we are sure we won't fire ConnectionClosed twice for the * same connection. */ g_hash_table_remove (priv->transport_to_id, transport); tp_svc_channel_type_stream_tube_emit_connection_closed (self, connection_id, error, debug_msg); } static void transport_disconnected_cb (GibberTransport *transport, GabbleTubeStream *self) { GabbleTubeStreamPrivate *priv = self->priv; GabbleBytestreamIface *bytestream; fire_connection_closed (self, transport, TP_ERROR_STR_CANCELLED, "local socket has been disconnected"); bytestream = g_hash_table_lookup (priv->transport_to_bytestream, transport); if (bytestream == NULL) return; DEBUG ("transport disconnected. close the extra bytestream"); gabble_bytestream_iface_close (bytestream, NULL); } static void remove_transport (GabbleTubeStream *self, GabbleBytestreamIface *bytestream, GibberTransport *transport) { GabbleTubeStreamPrivate *priv = self->priv; DEBUG ("disconnect and remove transport"); g_signal_handlers_disconnect_matched (transport, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self); /* The callback on the "connected" signal doesn't match the above * disconnection as it receives a transport_connected_data as user_data * and not the self pointer. */ g_signal_handlers_disconnect_matched (transport, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, G_CALLBACK (transport_connected_cb), NULL); gibber_transport_disconnect (transport); fire_connection_closed (self, transport, TP_ERROR_STR_CONNECTION_LOST, "bytestream has been broken"); g_hash_table_remove (priv->transport_to_bytestream, transport); g_hash_table_remove (priv->bytestream_to_transport, bytestream); g_hash_table_remove (priv->transport_to_id, transport); } static void transport_buffer_empty_cb (GibberTransport *transport, GabbleTubeStream *self) { GabbleTubeStreamPrivate *priv = self->priv; GabbleBytestreamIface *bytestream; GabbleBytestreamState state; bytestream = g_hash_table_lookup (priv->transport_to_bytestream, transport); g_assert (bytestream != NULL); g_object_get (bytestream, "state", &state, NULL); if (state == GABBLE_BYTESTREAM_STATE_CLOSED) { DEBUG ("buffer is now empty. Transport can be removed"); remove_transport (self, bytestream, transport); return; } /* Buffer is empty so we can unblock the buffer if it was blocked */ gabble_bytestream_iface_block_reading (bytestream, FALSE); } static void add_transport (GabbleTubeStream *self, GibberTransport *transport, GabbleBytestreamIface *bytestream) { gibber_transport_set_handler (transport, transport_handler, self); g_signal_connect (transport, "disconnected", G_CALLBACK (transport_disconnected_cb), self); g_signal_connect (transport, "buffer-empty", G_CALLBACK (transport_buffer_empty_cb), self); /* We can transfer transport's data; unblock it. */ gibber_transport_block_receiving (transport, FALSE); } static void bytestream_write_blocked_cb (GabbleBytestreamIface *bytestream, gboolean blocked, GabbleTubeStream *self) { GabbleTubeStreamPrivate *priv = self->priv; GibberTransport *transport; transport = g_hash_table_lookup (priv->bytestream_to_transport, bytestream); g_assert (transport != NULL); gibber_transport_block_receiving (transport, blocked); } static void extra_bytestream_state_changed_cb (GabbleBytestreamIface *bytestream, GabbleBytestreamState state, gpointer user_data) { GabbleTubeStream *self = GABBLE_TUBE_STREAM (user_data); GabbleTubeStreamPrivate *priv = self->priv; DEBUG ("Called."); if (state == GABBLE_BYTESTREAM_STATE_OPEN) { GibberTransport *transport; DEBUG ("extra bytestream open"); g_signal_connect (bytestream, "data-received", G_CALLBACK (data_received_cb), self); g_signal_connect (bytestream, "write-blocked", G_CALLBACK (bytestream_write_blocked_cb), self); transport = g_hash_table_lookup (priv->bytestream_to_transport, bytestream); g_assert (transport != NULL); add_transport (self, transport, bytestream); } else if (state == GABBLE_BYTESTREAM_STATE_CLOSED) { GibberTransport *transport; DEBUG ("extra bytestream closed"); transport = g_hash_table_lookup (priv->bytestream_to_transport, bytestream); if (transport != NULL) { if (gibber_transport_buffer_is_empty (transport)) { DEBUG ("Buffer is empty, we can remove the transport"); remove_transport (self, bytestream, transport); } else { DEBUG ("Wait buffer is empty before disconnect the transport"); } } } } static void extra_bytestream_negotiate_cb (GabbleBytestreamIface *bytestream, WockyStanza *msg, GObject *object, gpointer user_data) { GabbleTubeStream *self = GABBLE_TUBE_STREAM (object); GabbleTubeStreamPrivate *priv = self->priv; GibberTransport *transport = GIBBER_TRANSPORT (user_data); if (bytestream == NULL) { DEBUG ("initiator refused new bytestream"); fire_connection_closed (self, transport, TP_ERROR_STR_CONNECTION_REFUSED, "connection has been refused"); g_object_unref (transport); return; } DEBUG ("extra bytestream accepted"); /* transport has been refed in start_stream_initiation () */ g_assert (gibber_transport_get_state (transport) == GIBBER_TRANSPORT_CONNECTED); g_hash_table_insert (priv->bytestream_to_transport, g_object_ref (bytestream), transport); g_hash_table_insert (priv->transport_to_bytestream, g_object_ref (transport), g_object_ref (bytestream)); g_signal_connect (bytestream, "state-changed", G_CALLBACK (extra_bytestream_state_changed_cb), self); } static gboolean start_stream_initiation (GabbleTubeStream *self, GibberTransport *transport, GError **error) { GabbleTubeStreamPrivate *priv = self->priv; TpBaseChannel *base = TP_BASE_CHANNEL (self); TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base); TpBaseConnection *base_conn = tp_base_channel_get_connection (base); GabbleConnection *conn = GABBLE_CONNECTION (base_conn); TpHandle initiator = tp_base_channel_get_initiator (base); WockyNode *node, *si_node; WockyStanza *msg; TpHandleRepoIface *contact_repo; const gchar *jid; gchar *full_jid, *stream_id, *id_str; contact_repo = tp_base_connection_get_handles ( base_conn, TP_HANDLE_TYPE_CONTACT); jid = tp_handle_inspect (contact_repo, initiator); if (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT) { /* Private tube */ GabblePresence *presence; const gchar *resource; presence = gabble_presence_cache_get (conn->presence_cache, initiator); if (presence == NULL) { DEBUG ("can't find initiator's presence"); g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "can't find initiator's presence"); return FALSE; } resource = gabble_presence_pick_resource_by_caps (presence, 0, gabble_capability_set_predicate_has, NS_TUBES); if (resource == NULL) { DEBUG ("initiator doesn't have tubes capabilities"); g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "initiator doesn't have tubes capabilities"); return FALSE; } full_jid = g_strdup_printf ("%s/%s", jid, resource); } else { /* Muc tube */ full_jid = g_strdup (jid); } stream_id = gabble_bytestream_factory_generate_stream_id (); msg = gabble_bytestream_factory_make_stream_init_iq (full_jid, stream_id, NS_TUBES); si_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "si", NS_SI); g_assert (si_node != NULL); id_str = g_strdup_printf ("%" G_GUINT64_FORMAT, priv->id); if (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT) { node = wocky_node_add_child_ns (si_node, "stream", NS_TUBES); } else { node = wocky_node_add_child_ns (si_node, "muc-stream", NS_TUBES); } wocky_node_set_attribute (node, "tube", id_str); gabble_bytestream_factory_negotiate_stream ( conn->bytestream_factory, msg, stream_id, extra_bytestream_negotiate_cb, g_object_ref (transport), G_OBJECT (self)); /* FIXME: data and one ref on data->transport are leaked if the tube is * closed before we got the SI reply. */ g_object_unref (msg); g_free (stream_id); g_free (full_jid); g_free (id_str); return TRUE; } static guint generate_connection_id (GabbleTubeStream *self, GibberTransport *transport) { GabbleTubeStreamPrivate *priv = self->priv; priv->last_connection_id++; g_hash_table_insert (priv->transport_to_id, transport, GUINT_TO_POINTER (priv->last_connection_id)); return priv->last_connection_id; } static void fire_new_local_connection (GabbleTubeStream *self, GibberTransport *transport) { guint connection_id; connection_id = generate_connection_id (self, transport); tp_svc_channel_type_stream_tube_emit_new_local_connection (self, connection_id); } #ifdef GIBBER_TYPE_UNIX_TRANSPORT static void credentials_received_cb (GibberUnixTransport *transport, GibberBuffer *buffer, GibberCredentials *credentials, GError *error, gpointer user_data) { GabbleTubeStream *self = GABBLE_TUBE_STREAM (user_data); /* Credentials received; reblock the transport */ gibber_transport_block_receiving (GIBBER_TRANSPORT (transport), TRUE); if (error != NULL) { DEBUG ("Didn't receive credentials (%s). Closing transport", error->message); goto credentials_received_cb_out; } g_assert (credentials != NULL); if (buffer->length != 1) { DEBUG ("Got more than one byte (%" G_GSIZE_FORMAT "). Rejecting", buffer->length); goto credentials_received_cb_out; } if (credentials->uid != getuid ()) { DEBUG ("Wrong uid (%u). Rejecting", credentials->uid); goto credentials_received_cb_out; } DEBUG ("Connection properly authentificated"); if (!start_stream_initiation (self, GIBBER_TRANSPORT (transport), NULL)) { DEBUG ("SI failed. Closing connection"); } else { fire_new_local_connection (self, GIBBER_TRANSPORT (transport)); } credentials_received_cb_out: /* start_stream_initiation reffed the transport if everything went fine */ g_object_unref (transport); } #endif static gboolean check_incoming_connection (GabbleTubeStream *self, GibberTransport *transport) { GabbleTubeStreamPrivate *priv = self->priv; if (priv->access_control == TP_SOCKET_ACCESS_CONTROL_LOCALHOST) { return TRUE; } #ifdef GIBBER_TYPE_UNIX_TRANSPORT else if (priv->access_control == TP_SOCKET_ACCESS_CONTROL_CREDENTIALS) { if (!gibber_unix_transport_recv_credentials ( GIBBER_UNIX_TRANSPORT (transport), credentials_received_cb, self)) { DEBUG ("Can't receive credentials. Closing transport"); return FALSE; } /* Temporarly unblock the transport to be able to receive credentials */ gibber_transport_block_receiving (transport, FALSE); /* We ref the transport so it won't be destroyed by GibberListener */ g_object_ref (transport); /* Returns FALSE as we are waiting for credentials so SI can't be * started yet. */ return FALSE; } #endif else if (priv->access_control == TP_SOCKET_ACCESS_CONTROL_PORT) { struct sockaddr_storage addr; socklen_t len = sizeof (addr); int ret; char peer_host[NI_MAXHOST]; char peer_port[NI_MAXSERV]; guint port; gchar *host; gchar *tmp; if (!gibber_transport_get_peeraddr (transport, &addr, &len)) { DEBUG ("gibber_transport_get_peeraddr failed"); return FALSE; } gibber_normalize_address (&addr); g_assert (addr.ss_family == AF_INET || addr.ss_family == AF_INET6); ret = getnameinfo ((struct sockaddr *) &addr, len, peer_host, NI_MAXHOST, peer_port, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV); if (ret != 0) { DEBUG ("getnameinfo failed: %s", gai_strerror(ret)); return FALSE; } dbus_g_type_struct_get (priv->access_control_param, 0, &host, 1, &port, G_MAXUINT); if (tp_strdiff (host, peer_host)) { DEBUG ("Wrong ip: %s (%s was expected)", peer_host, host); g_free (host); return FALSE; } g_free (host); tmp = g_strdup_printf ("%u", port); if (tp_strdiff (tmp, peer_port)) { DEBUG ("Wrong port: %s (%u was expected)", peer_port, port); g_free (tmp); return FALSE; } g_free (tmp); return TRUE; } else { /* access_control has already been checked when accepting the tube */ g_assert_not_reached (); } return FALSE; } /* callback for listening connections from the local application */ static void local_new_connection_cb (GibberListener *listener, GibberTransport *transport, struct sockaddr_storage *addr, guint size, gpointer user_data) { GabbleTubeStream *self = GABBLE_TUBE_STREAM (user_data); /* Block the transport while there is no open bytestream to transfer * its data. */ gibber_transport_block_receiving (transport, TRUE); if (!check_incoming_connection (self, transport)) { /* We didn't ref the connection so it will be destroyed by the * GibberListener if needed. */ return; } /* Streams in stream tubes are established with stream initiation (XEP-0095). * We use SalutSiBytestreamManager. */ if (!start_stream_initiation (self, transport, NULL)) { DEBUG ("closing new client connection"); } else { fire_new_local_connection (self, transport); } } #ifdef GIBBER_TYPE_UNIX_TRANSPORT static gboolean set_credentials_access_control_param (GValue *access_control_param, GibberTransport *transport) { guint8 credentials; credentials = g_random_int_range (0, G_MAXUINT8); /* The Credentials access control would have be rejected earlier if the * socket type wasn't UNIX. */ if (!gibber_unix_transport_send_credentials ( GIBBER_UNIX_TRANSPORT (transport), &credentials, sizeof (guint8))) { DEBUG ("send_credentials failed"); return FALSE; } g_value_init (access_control_param, G_TYPE_UCHAR); g_value_set_uchar (access_control_param, credentials); return TRUE; } #endif static gboolean set_port_access_control_param (GValue *access_control_param, GibberTransport *transport) { struct sockaddr_storage addr; socklen_t addrlen = sizeof (struct sockaddr_storage); char host[NI_MAXHOST]; char port_str[NI_MAXSERV]; int ret; guint16 port; unsigned long tmp; gchar *endptr; if (!gibber_transport_get_sockaddr (transport, &addr, &addrlen)) { DEBUG ("Failed to get connection address"); return FALSE; } ret = getnameinfo ((struct sockaddr *) &addr, addrlen, host, NI_MAXHOST, port_str, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV); if (ret != 0) { DEBUG ("getnameinfo failed: %s", g_strerror (ret)); return FALSE; } tmp = strtoul (port_str, &endptr, 10); if (!endptr || *endptr || tmp > G_MAXUINT16) { DEBUG ("invalid port: %s", port_str); return FALSE; } port = (guint16) tmp; g_value_init (access_control_param, TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV4); g_value_take_boxed (access_control_param, dbus_g_type_specialized_construct ( TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV4)); dbus_g_type_struct_set (access_control_param, 0, host, 1, port, G_MAXUINT); return TRUE; } static transport_connected_data * transport_connected_data_new (GabbleTubeStream *self, TpHandle contact) { transport_connected_data *data = g_slice_new (transport_connected_data); data->self = self; data->contact = contact; return data; } static void transport_connected_data_free (transport_connected_data *data) { g_slice_free (transport_connected_data, data); } static void fire_new_remote_connection (GabbleTubeStream *self, GibberTransport *transport, TpHandle contact) { GabbleTubeStreamPrivate *priv = self->priv; GValue access_control_param = {0,}; guint connection_id; #ifdef GIBBER_TYPE_UNIX_TRANSPORT if (priv->access_control == TP_SOCKET_ACCESS_CONTROL_CREDENTIALS) { if (!set_credentials_access_control_param (&access_control_param, transport)) { gibber_transport_disconnect (transport); return; } } else #endif if (priv->access_control == TP_SOCKET_ACCESS_CONTROL_PORT) { if (!set_port_access_control_param (&access_control_param, transport)) { gibber_transport_disconnect (transport); return; } } else { /* set a dummy value */ g_value_init (&access_control_param, G_TYPE_INT); g_value_set_int (&access_control_param, 0); } /* fire NewConnection D-Bus signal */ connection_id = GPOINTER_TO_UINT (g_hash_table_lookup (priv->transport_to_id, transport)); g_assert (connection_id != 0); tp_svc_channel_type_stream_tube_emit_new_remote_connection (self, contact, &access_control_param, connection_id); g_value_unset (&access_control_param); } static void transport_connected_cb (GibberTransport *transport, transport_connected_data *data) { GabbleTubeStreamPrivate *priv = data->self->priv; GabbleBytestreamIface *bytestream; fire_new_remote_connection (data->self, transport, data->contact); bytestream = g_hash_table_lookup (priv->transport_to_bytestream, transport); if (bytestream == NULL) return; gabble_bytestream_iface_block_reading (bytestream, FALSE); } static GibberTransport * new_connection_to_socket (GabbleTubeStream *self, GabbleBytestreamIface *bytestream, TpHandle contact) { GabbleTubeStreamPrivate *priv = self->priv; TpBaseChannel *base = TP_BASE_CHANNEL (self); GibberTransport *transport; DEBUG ("Called."); g_assert (tp_base_channel_is_requested (base)); #ifdef GIBBER_TYPE_UNIX_TRANSPORT if (priv->address_type == TP_SOCKET_ADDRESS_TYPE_UNIX) { GArray *array; array = g_value_get_boxed (priv->address); DEBUG ("Will try to connect to socket: %s", (const gchar *) array->data); transport = GIBBER_TRANSPORT (gibber_unix_transport_new ()); gibber_unix_transport_connect (GIBBER_UNIX_TRANSPORT (transport), array->data, NULL); } else #endif if (priv->address_type == TP_SOCKET_ADDRESS_TYPE_IPV4 || priv->address_type == TP_SOCKET_ADDRESS_TYPE_IPV6) { gchar *ip; guint port; dbus_g_type_struct_get (priv->address, 0, &ip, 1, &port, G_MAXUINT); transport = GIBBER_TRANSPORT (gibber_tcp_transport_new ()); gibber_tcp_transport_connect (GIBBER_TCP_TRANSPORT (transport), ip, port); g_free (ip); } else { g_assert_not_reached (); } /* Block the transport while there is no open bytestream to transfer * its data. */ gibber_transport_block_receiving (transport, TRUE); generate_connection_id (self, transport); gabble_bytestream_iface_block_reading (bytestream, TRUE); g_hash_table_insert (priv->bytestream_to_transport, g_object_ref (bytestream), g_object_ref (transport)); g_hash_table_insert (priv->transport_to_bytestream, g_object_ref (transport), g_object_ref (bytestream)); g_signal_connect (bytestream, "state-changed", G_CALLBACK (extra_bytestream_state_changed_cb), self); g_object_unref (transport); return transport; } static gboolean tube_stream_open (GabbleTubeStream *self, GError **error) { GabbleTubeStreamPrivate *priv = self->priv; TpBaseChannel *base = TP_BASE_CHANNEL (self); DEBUG ("called"); if (tp_base_channel_is_requested (base)) /* Nothing to do if we are the initiator of this tube. * We'll connect to the socket each time request a new bytestream. */ return TRUE; /* We didn't create this tube so it doesn't have * a socket associated with it. Let's create one */ g_assert (priv->address == NULL); g_assert (priv->local_listener == NULL); priv->local_listener = gibber_listener_new (); g_signal_connect (priv->local_listener, "new-connection", G_CALLBACK (local_new_connection_cb), self); #ifdef GIBBER_TYPE_UNIX_TRANSPORT if (priv->address_type == TP_SOCKET_ADDRESS_TYPE_UNIX) { GArray *array; gchar suffix[8]; gchar *path; int ret; generate_ascii_string (8, suffix); path = g_strdup_printf ("/tmp/stream-gabble-%.8s", suffix); DEBUG ("create socket: %s", path); array = g_array_sized_new (TRUE, FALSE, sizeof (gchar), strlen (path)); g_array_insert_vals (array, 0, path, strlen (path)); priv->address = tp_g_value_slice_new (DBUS_TYPE_G_UCHAR_ARRAY); g_value_set_boxed (priv->address, array); g_array_unref (array); ret = gibber_listener_listen_socket (priv->local_listener, path, FALSE, error); if (ret != TRUE) { g_assert (error != NULL && *error != NULL); DEBUG ("Error listening on socket %s: %s", path, (*error)->message); g_free (path); return FALSE; } if (priv->access_control == TP_SOCKET_ACCESS_CONTROL_LOCALHOST) { /* Everyone can use the socket */ chmod (path, 0777); } g_free (path); } else #endif if (priv->address_type == TP_SOCKET_ADDRESS_TYPE_IPV4) { int ret; ret = gibber_listener_listen_tcp_loopback_af (priv->local_listener, 0, GIBBER_AF_IPV4, error); if (!ret) { g_assert (error != NULL && *error != NULL); DEBUG ("Error listening on socket: %s", (*error)->message); return FALSE; } priv->address = tp_g_value_slice_new ( TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV4); g_value_take_boxed (priv->address, dbus_g_type_specialized_construct ( TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV4)); dbus_g_type_struct_set (priv->address, 0, "127.0.0.1", 1, gibber_listener_get_port (priv->local_listener), G_MAXUINT); } else if (priv->address_type == TP_SOCKET_ADDRESS_TYPE_IPV6) { int ret; ret = gibber_listener_listen_tcp_loopback_af (priv->local_listener, 0, GIBBER_AF_IPV6, error); if (!ret) { g_assert (error != NULL && *error != NULL); DEBUG ("Error listening on socket: %s", (*error)->message); return FALSE; } priv->address = tp_g_value_slice_new ( TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV6); g_value_take_boxed (priv->address, dbus_g_type_specialized_construct ( TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV6)); dbus_g_type_struct_set (priv->address, 0, "::1", 1, gibber_listener_get_port (priv->local_listener), G_MAXUINT); } else { g_assert_not_reached (); } return TRUE; } static void gabble_tube_stream_init (GabbleTubeStream *self) { GabbleTubeStreamPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_TUBE_STREAM, GabbleTubeStreamPrivate); self->priv = priv; priv->transport_to_bytestream = g_hash_table_new_full (g_direct_hash, g_direct_equal, (GDestroyNotify) g_object_unref, (GDestroyNotify) g_object_unref); priv->bytestream_to_transport = g_hash_table_new_full (g_direct_hash, g_direct_equal, (GDestroyNotify) g_object_unref, (GDestroyNotify) g_object_unref); priv->transport_to_id = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); priv->last_connection_id = 0; priv->address_type = TP_SOCKET_ADDRESS_TYPE_UNIX; priv->address = NULL; priv->access_control = TP_SOCKET_ACCESS_CONTROL_LOCALHOST; priv->access_control_param = NULL; priv->dispose_has_run = FALSE; } static gboolean close_each_extra_bytestream (gpointer key, gpointer value, gpointer user_data) { GabbleTubeStream *self = GABBLE_TUBE_STREAM (user_data); GabbleTubeStreamPrivate *priv = self->priv; GibberTransport *transport = (GibberTransport *) value; GabbleBytestreamIface *bytestream = (GabbleBytestreamIface *) key; /* We are iterating over priv->fd_to_bytestreams so we can't modify it. * Disconnect signals so extra_bytestream_state_changed_cb won't be * called */ g_signal_handlers_disconnect_matched (bytestream, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self); g_signal_handlers_disconnect_matched (transport, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self); /* The callback on the "connected" signal doesn't match the above * disconnection as it receives a transport_connected_data as user_data * and not the self pointer. */ g_signal_handlers_disconnect_matched (transport, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, G_CALLBACK (transport_connected_cb), NULL); gabble_bytestream_iface_close (bytestream, NULL); gibber_transport_disconnect (transport); fire_connection_closed (self, transport, TP_ERROR_STR_CANCELLED, "tube is closing"); g_hash_table_remove (priv->transport_to_bytestream, transport); return TRUE; } static void gabble_tube_stream_dispose (GObject *object) { GabbleTubeStream *self = GABBLE_TUBE_STREAM (object); GabbleTubeStreamPrivate *priv = self->priv; TpBaseChannel *base = (TpBaseChannel *) self; if (priv->dispose_has_run) return; gabble_tube_iface_close (GABBLE_TUBE_IFACE (self), TRUE); if (tp_base_channel_is_requested (base) && priv->address_type == TP_SOCKET_ADDRESS_TYPE_UNIX && priv->address != NULL) { /* We created a new UNIX socket. Let's delete it */ GArray *array; GString *path; array = g_value_get_boxed (priv->address); path = g_string_new_len (array->data, array->len); if (g_unlink (path->str) != 0) { DEBUG ("unlink of %s failed: %s", path->str, g_strerror (errno)); } g_string_free (path, TRUE); } tp_clear_pointer (&priv->transport_to_bytestream, g_hash_table_unref); tp_clear_pointer (&priv->bytestream_to_transport, g_hash_table_unref); tp_clear_pointer (&priv->transport_to_id, g_hash_table_unref); tp_clear_object (&priv->local_listener); if (priv->muc != NULL) { tp_external_group_mixin_finalize (object); } priv->dispose_has_run = TRUE; if (G_OBJECT_CLASS (gabble_tube_stream_parent_class)->dispose) G_OBJECT_CLASS (gabble_tube_stream_parent_class)->dispose (object); } static void gabble_tube_stream_finalize (GObject *object) { GabbleTubeStream *self = GABBLE_TUBE_STREAM (object); GabbleTubeStreamPrivate *priv = self->priv; g_free (priv->service); g_hash_table_unref (priv->parameters); if (priv->address != NULL) { tp_g_value_slice_free (priv->address); priv->address = NULL; } if (priv->access_control_param != NULL) { tp_g_value_slice_free (priv->access_control_param); priv->access_control_param = NULL; } G_OBJECT_CLASS (gabble_tube_stream_parent_class)->finalize (object); } static void gabble_tube_stream_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleTubeStream *self = GABBLE_TUBE_STREAM (object); GabbleTubeStreamPrivate *priv = self->priv; switch (property_id) { case PROP_SELF_HANDLE: g_value_set_uint (value, priv->self_handle); break; case PROP_ID: g_value_set_uint64 (value, priv->id); break; case PROP_TYPE: g_value_set_uint (value, TP_TUBE_TYPE_STREAM); break; case PROP_SERVICE: g_value_set_string (value, priv->service); break; case PROP_PARAMETERS: g_value_set_boxed (value, priv->parameters); break; case PROP_STATE: g_value_set_uint (value, priv->state); break; case PROP_ADDRESS_TYPE: g_value_set_uint (value, priv->address_type); break; case PROP_ADDRESS: g_value_set_pointer (value, priv->address); break; case PROP_ACCESS_CONTROL: g_value_set_uint (value, priv->access_control); break; case PROP_ACCESS_CONTROL_PARAM: g_value_set_pointer (value, priv->access_control_param); break; case PROP_SUPPORTED_SOCKET_TYPES: g_value_take_boxed (value, gabble_tube_stream_get_supported_socket_types ()); break; case PROP_MUC: g_value_set_object (value, priv->muc); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_tube_stream_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleTubeStream *self = GABBLE_TUBE_STREAM (object); GabbleTubeStreamPrivate *priv = self->priv; switch (property_id) { case PROP_SELF_HANDLE: priv->self_handle = g_value_get_uint (value); break; case PROP_ID: priv->id = g_value_get_uint64 (value); break; case PROP_SERVICE: g_free (priv->service); priv->service = g_value_dup_string (value); break; case PROP_PARAMETERS: if (priv->parameters != NULL) g_hash_table_unref (priv->parameters); priv->parameters = g_value_dup_boxed (value); break; case PROP_ADDRESS_TYPE: g_assert (g_value_get_uint (value) == TP_SOCKET_ADDRESS_TYPE_UNIX || g_value_get_uint (value) == TP_SOCKET_ADDRESS_TYPE_IPV4 || g_value_get_uint (value) == TP_SOCKET_ADDRESS_TYPE_IPV6); priv->address_type = g_value_get_uint (value); break; case PROP_ADDRESS: if (priv->address == NULL) { priv->address = tp_g_value_slice_dup (g_value_get_pointer (value)); } break; case PROP_ACCESS_CONTROL: priv->access_control = g_value_get_uint (value); break; case PROP_ACCESS_CONTROL_PARAM: if (priv->access_control_param == NULL) { priv->access_control_param = tp_g_value_slice_dup ( g_value_get_pointer (value)); } break; case PROP_MUC: priv->muc = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_tube_stream_constructed (GObject *obj) { GabbleTubeStream *self = GABBLE_TUBE_STREAM (obj); GabbleTubeStreamPrivate *priv = self->priv; TpBaseChannel *base = TP_BASE_CHANNEL (self); TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base); TpBaseConnection *base_conn = tp_base_channel_get_connection (base); GabbleConnection *conn = GABBLE_CONNECTION (base_conn); void (*chain_up) (GObject *) = ((GObjectClass *) gabble_tube_stream_parent_class)->constructed; if (chain_up != NULL) chain_up (obj); if (tp_base_channel_is_requested (base)) { /* We initiated this tube */ priv->state = TP_TUBE_CHANNEL_STATE_NOT_OFFERED; } else { priv->state = TP_TUBE_CHANNEL_STATE_LOCAL_PENDING; /* We'll need SOCKS5 proxies if the tube is accepted */ gabble_bytestream_factory_query_socks5_proxies ( conn->bytestream_factory); } if (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT) { g_assert (priv->muc == NULL); } else { g_assert (priv->muc != NULL); tp_external_group_mixin_init (obj, (GObject *) priv->muc); } } static void gabble_tube_stream_fill_immutable_properties (TpBaseChannel *chan, GHashTable *properties) { TpBaseChannelClass *cls = TP_BASE_CHANNEL_CLASS ( gabble_tube_stream_parent_class); cls->fill_immutable_properties (chan, properties); tp_dbus_properties_mixin_fill_properties_hash ( G_OBJECT (chan), properties, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE, "Service", TP_IFACE_CHANNEL_TYPE_STREAM_TUBE, "SupportedSocketTypes", NULL); if (!tp_base_channel_is_requested (chan)) { tp_dbus_properties_mixin_fill_properties_hash ( G_OBJECT (chan), properties, TP_IFACE_CHANNEL_INTERFACE_TUBE, "Parameters", NULL); } } static gchar * gabble_tube_stream_get_object_path_suffix (TpBaseChannel *base) { GabbleTubeStream *self = GABBLE_TUBE_STREAM (base); return g_strdup_printf ("StreamTubeChannel/%u/%" G_GUINT64_FORMAT, tp_base_channel_get_target_handle (base), self->priv->id); } static void gabble_tube_stream_close (TpBaseChannel *base) { gabble_tube_iface_close (GABBLE_TUBE_IFACE (base), FALSE); } static void gabble_tube_stream_class_init (GabbleTubeStreamClass *gabble_tube_stream_class) { static TpDBusPropertiesMixinPropImpl stream_tube_props[] = { { "Service", "service", NULL }, { "SupportedSocketTypes", "supported-socket-types", NULL }, { NULL } }; static TpDBusPropertiesMixinPropImpl tube_iface_props[] = { { "Parameters", "parameters", NULL }, { "State", "state", NULL }, { NULL } }; static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { { TP_IFACE_CHANNEL_TYPE_STREAM_TUBE, tp_dbus_properties_mixin_getter_gobject_properties, NULL, stream_tube_props, }, { TP_IFACE_CHANNEL_INTERFACE_TUBE, tp_dbus_properties_mixin_getter_gobject_properties, NULL, tube_iface_props, }, { NULL } }; GObjectClass *object_class = G_OBJECT_CLASS (gabble_tube_stream_class); TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (gabble_tube_stream_class); GParamSpec *param_spec; object_class->get_property = gabble_tube_stream_get_property; object_class->set_property = gabble_tube_stream_set_property; object_class->constructed = gabble_tube_stream_constructed; object_class->dispose = gabble_tube_stream_dispose; object_class->finalize = gabble_tube_stream_finalize; base_class->channel_type = TP_IFACE_CHANNEL_TYPE_STREAM_TUBE; base_class->get_interfaces = gabble_tube_stream_get_interfaces; base_class->target_handle_type = TP_HANDLE_TYPE_CONTACT; base_class->close = gabble_tube_stream_close; base_class->fill_immutable_properties = gabble_tube_stream_fill_immutable_properties; base_class->get_object_path_suffix = gabble_tube_stream_get_object_path_suffix; g_type_class_add_private (gabble_tube_stream_class, sizeof (GabbleTubeStreamPrivate)); g_object_class_override_property (object_class, PROP_SELF_HANDLE, "self-handle"); g_object_class_override_property (object_class, PROP_ID, "id"); g_object_class_override_property (object_class, PROP_TYPE, "type"); g_object_class_override_property (object_class, PROP_SERVICE, "service"); g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters"); g_object_class_override_property (object_class, PROP_STATE, "state"); param_spec = g_param_spec_boxed ( "supported-socket-types", "Supported socket types", "GHashTable containing supported socket types.", TP_HASH_TYPE_SUPPORTED_SOCKET_MAP, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SUPPORTED_SOCKET_TYPES, param_spec); param_spec = g_param_spec_uint ( "address-type", "address type", "a TpSocketAddressType representing the type of the listening" "address of the local service", 0, NUM_TP_SOCKET_ADDRESS_TYPES - 1, TP_SOCKET_ADDRESS_TYPE_UNIX, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ADDRESS_TYPE, param_spec); param_spec = g_param_spec_pointer ( "address", "address", "The listening address of the local service, as indicated by the " "address-type", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ADDRESS, param_spec); param_spec = g_param_spec_uint ( "access-control", "access control", "a TpSocketAccessControl representing the access control " "the local service applies to the local socket", 0, NUM_TP_SOCKET_ACCESS_CONTROLS - 1, TP_SOCKET_ACCESS_CONTROL_LOCALHOST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ACCESS_CONTROL, param_spec); param_spec = g_param_spec_pointer ( "access-control-param", "access control param", "A parameter for the access control type, to be interpreted as specified" "in the documentation for the Socket_Access_Control enum.", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ACCESS_CONTROL_PARAM, param_spec); param_spec = g_param_spec_object ( "muc", "GabbleMucChannel object", "Gabble text MUC channel corresponding to this Tube channel object, " "if the handle type is ROOM.", GABBLE_TYPE_MUC_CHANNEL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_MUC, param_spec); signals[OPENED] = g_signal_new ("tube-opened", G_OBJECT_CLASS_TYPE (gabble_tube_stream_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[NEW_CONNECTION] = g_signal_new ("tube-new-connection", G_OBJECT_CLASS_TYPE (gabble_tube_stream_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals[CLOSED] = g_signal_new ("tube-closed", G_OBJECT_CLASS_TYPE (gabble_tube_stream_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[OFFERED] = g_signal_new ("tube-offered", G_OBJECT_CLASS_TYPE (gabble_tube_stream_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); gabble_tube_stream_class->dbus_props_class.interfaces = prop_interfaces; tp_dbus_properties_mixin_class_init (object_class, G_STRUCT_OFFSET (GabbleTubeStreamClass, dbus_props_class)); tp_external_group_mixin_init_dbus_properties (object_class); } static void data_received_cb (GabbleBytestreamIface *bytestream, TpHandle sender, GString *data, gpointer user_data) { GabbleTubeStream *tube = GABBLE_TUBE_STREAM (user_data); GabbleTubeStreamPrivate *priv = tube->priv; GibberTransport *transport; GError *error = NULL; transport = g_hash_table_lookup (priv->bytestream_to_transport, bytestream); g_assert (transport != NULL); /* If something goes wrong when trying to write the data on the transport, * it could be disconnected, causing its removal from the hash tables. * When removed, the transport would be destroyed as the hash tables keep a * ref on it and so we'll call _buffer_is_empty on a destroyed transport. * We avoid that by reffing the transport between the 2 calls so we keep it * artificially alive if needed. */ g_object_ref (transport); if (!gibber_transport_send (transport, (const guint8 *) data->str, data->len, &error)) { DEBUG ("sending failed: %s", error->message); g_error_free (error); g_object_unref (transport); return; } if (!gibber_transport_buffer_is_empty (transport)) { /* We don't want to send more data while the buffer isn't empty */ DEBUG ("tube buffer isn't empty. Block the bytestream"); gabble_bytestream_iface_block_reading (bytestream, TRUE); } g_object_unref (transport); } GabbleTubeStream * gabble_tube_stream_new (GabbleConnection *conn, TpHandle handle, TpHandleType handle_type, TpHandle self_handle, TpHandle initiator, const gchar *service, GHashTable *parameters, guint64 id, GabbleMucChannel *muc, gboolean requested) { GabbleTubeStream *obj; GType gtype = GABBLE_TYPE_TUBE_STREAM; if (handle_type == TP_HANDLE_TYPE_ROOM) gtype = GABBLE_TYPE_MUC_TUBE_STREAM; obj = g_object_new (gtype, "connection", conn, "handle", handle, "self-handle", self_handle, "initiator-handle", initiator, "service", service, "parameters", parameters, "id", id, "muc", muc, "requested", requested, NULL); return obj; } /** * gabble_tube_stream_accept * * Implements gabble_tube_iface_accept on GabbleTubeIface */ static gboolean gabble_tube_stream_accept (GabbleTubeIface *tube, GError **error) { GabbleTubeStream *self = GABBLE_TUBE_STREAM (tube); GabbleTubeStreamPrivate *priv = self->priv; if (!gabble_tube_stream_check_params (priv->address_type, NULL, priv->access_control, priv->access_control_param, error)) { goto fail; } if (priv->state != TP_TUBE_CHANNEL_STATE_LOCAL_PENDING) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Tube is not in the local pending state"); goto fail; } if (!tube_stream_open (self, error)) { gabble_tube_iface_close (GABBLE_TUBE_IFACE (self), TRUE); goto fail; } priv->state = TP_TUBE_CHANNEL_STATE_OPEN; tp_svc_channel_interface_tube_emit_tube_channel_state_changed (self, TP_TUBE_CHANNEL_STATE_OPEN); g_signal_emit (G_OBJECT (self), signals[OPENED], 0); return TRUE; fail: priv->address_type = 0; priv->access_control = 0; tp_g_value_slice_free (priv->access_control_param); priv->access_control_param = NULL; return FALSE; } /** * gabble_tube_iface_stream_close * * Implements gabble_tube_iface_close on GabbleTubeIface */ static void gabble_tube_iface_stream_close (GabbleTubeIface *tube, gboolean closed_remotely) { GabbleTubeStream *self = GABBLE_TUBE_STREAM (tube); GabbleTubeStreamPrivate *priv = self->priv; TpBaseChannel *base = TP_BASE_CHANNEL (self); TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base); TpBaseConnection *base_conn = tp_base_channel_get_connection (base); GabbleConnection *conn = GABBLE_CONNECTION (base_conn); if (tp_base_channel_is_destroyed (base)) return; g_hash_table_foreach_remove (priv->bytestream_to_transport, close_each_extra_bytestream, self); if (!closed_remotely && cls->target_handle_type == TP_HANDLE_TYPE_CONTACT) { WockyStanza *msg; const gchar *jid; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( base_conn, TP_HANDLE_TYPE_CONTACT); gchar *id_str; jid = tp_handle_inspect (contact_repo, tp_base_channel_get_target_handle (base)); id_str = g_strdup_printf ("%" G_GUINT64_FORMAT, priv->id); /* Send the close message */ msg = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, jid, '(', "close", ':', NS_TUBES, '@', "tube", id_str, ')', GABBLE_AMP_DO_NOT_STORE_SPEC, NULL); g_free (id_str); _gabble_connection_send (conn, msg, NULL); g_object_unref (msg); } /* Take a ref to ourselves as when we emit tube-closed * GabbleTubesChannel will drop our last ref but we still need to * declare ourselves as destroyed. This is rubbish, but will * disappear when we finally remove the Tubes channel type.. */ g_object_ref (self); if (cls->target_handle_type == TP_HANDLE_TYPE_ROOM) gabble_muc_channel_send_presence (priv->muc); g_signal_emit (G_OBJECT (self), signals[CLOSED], 0); tp_base_channel_destroyed (base); g_object_unref (self); } static void augment_si_accept_iq (WockyNode *si, gpointer user_data) { wocky_node_add_child_ns (si, "tube", NS_TUBES); } /** * gabble_tube_stream_add_bytestream * * Implements gabble_tube_iface_add_bytestream on GabbleTubeIface */ static void gabble_tube_stream_add_bytestream (GabbleTubeIface *tube, GabbleBytestreamIface *bytestream) { GabbleTubeStream *self = GABBLE_TUBE_STREAM (tube); GabbleTubeStreamPrivate *priv = self->priv; TpBaseChannel *base = TP_BASE_CHANNEL (self); TpHandle contact; GibberTransport *transport; if (!tp_base_channel_is_requested (base)) { DEBUG ("I'm not the initiator of this tube, can't accept " "an extra bytestream"); gabble_bytestream_iface_close (bytestream, NULL); return; } g_object_get (bytestream, "peer-handle", &contact, NULL); /* New bytestream, let's connect to the socket */ transport = new_connection_to_socket (self, bytestream, contact); if (transport != NULL) { if (priv->state == TP_TUBE_CHANNEL_STATE_REMOTE_PENDING) { DEBUG ("Received first connection. Tube is now open"); priv->state = TP_TUBE_CHANNEL_STATE_OPEN; tp_svc_channel_interface_tube_emit_tube_channel_state_changed ( self, TP_TUBE_CHANNEL_STATE_OPEN); g_signal_emit (G_OBJECT (self), signals[OPENED], 0); } DEBUG ("accept the extra bytestream"); gabble_bytestream_iface_accept (bytestream, augment_si_accept_iq, self); g_signal_emit (G_OBJECT (self), signals[NEW_CONNECTION], 0, contact); if (gibber_transport_get_state (transport) == GIBBER_TRANSPORT_CONNECTED) { gabble_bytestream_iface_block_reading (bytestream, FALSE); fire_new_remote_connection (self, transport, contact); } else { /* NewConnection will be fired once the transport is connected. * We can't get access_control_param (as the source port for example) * until it's connected. */ transport_connected_data *data; data = transport_connected_data_new (self, contact); g_signal_connect_data (transport, "connected", G_CALLBACK (transport_connected_cb), data, (GClosureNotify) transport_connected_data_free, 0); } } else { gabble_bytestream_iface_close (bytestream, NULL); } } #ifdef GIBBER_TYPE_UNIX_TRANSPORT static gboolean check_unix_params (TpSocketAddressType address_type, const GValue *address, TpSocketAccessControl access_control, const GValue *access_control_param, GError **error) { GArray *array; GString *socket_address; struct stat stat_buff; guint i; struct sockaddr_un dummy; g_assert (address_type == TP_SOCKET_ADDRESS_TYPE_UNIX); /* Check address type */ if (address != NULL) { if (G_VALUE_TYPE (address) != DBUS_TYPE_G_UCHAR_ARRAY) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Unix socket address is supposed to be ay"); return FALSE; } array = g_value_get_boxed (address); if (array->len > sizeof (dummy.sun_path) - 1) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Unix socket path is too long (max length allowed: %" G_GSIZE_FORMAT ")", sizeof (dummy.sun_path) - 1); return FALSE; } for (i = 0; i < array->len; i++) { if (g_array_index (array, gchar , i) == '\0') { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Unix socket path can't contain zero bytes"); return FALSE; } } socket_address = g_string_new_len (array->data, array->len); if (g_stat (socket_address->str, &stat_buff) == -1) { DEBUG ("Error calling stat on socket: %s", g_strerror (errno)); g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "%s: %s", socket_address->str, g_strerror (errno)); g_string_free (socket_address, TRUE); return FALSE; } if (!S_ISSOCK (stat_buff.st_mode)) { DEBUG ("%s is not a socket", socket_address->str); g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "%s is not a socket", socket_address->str); g_string_free (socket_address, TRUE); return FALSE; } g_string_free (socket_address, TRUE); } if (access_control == TP_SOCKET_ACCESS_CONTROL_LOCALHOST || access_control == TP_SOCKET_ACCESS_CONTROL_CREDENTIALS) { /* no variant associated */ return TRUE; } g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "%u socket access control is not supported", access_control); return FALSE; } #endif static gboolean check_ip_params (TpSocketAddressType address_type, const GValue *address, TpSocketAccessControl access_control, const GValue *access_control_param, GError **error) { /* Check address type */ if (address != NULL) { gchar *ip; guint port; struct addrinfo req, *result = NULL; int ret; if (address_type == TP_SOCKET_ADDRESS_TYPE_IPV4) { if (G_VALUE_TYPE (address) != TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV4) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "IPv4 socket address is supposed to be sq"); return FALSE; } } else if (address_type == TP_SOCKET_ADDRESS_TYPE_IPV6) { if (G_VALUE_TYPE (address) != TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV6) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "IPv6 socket address is supposed to be sq"); return FALSE; } } else { g_return_val_if_reached (FALSE); } dbus_g_type_struct_get (address, 0, &ip, 1, &port, G_MAXUINT); memset (&req, 0, sizeof (req)); req.ai_flags = AI_NUMERICHOST; req.ai_socktype = SOCK_STREAM; req.ai_protocol = IPPROTO_TCP; if (address_type == TP_SOCKET_ADDRESS_TYPE_IPV4) req.ai_family = AF_INET; else req.ai_family = AF_INET6; ret = getaddrinfo (ip, NULL, &req, &result); if (ret != 0) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Invalid address: %s", gai_strerror (ret)); g_free (ip); return FALSE; } g_free (ip); freeaddrinfo (result); } if (access_control == TP_SOCKET_ACCESS_CONTROL_LOCALHOST) { return TRUE; } else if (access_control == TP_SOCKET_ACCESS_CONTROL_PORT) { if (access_control_param != NULL) { if (G_VALUE_TYPE (access_control_param) != TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV4) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Port access param is supposed to be sq"); return FALSE; } } return TRUE; } g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "%u socket access control is not supported", access_control); return FALSE; } /* used to check access control parameters both for OfferStreamTube and * AcceptStreamTube. In case of AcceptStreamTube, address is NULL because we * listen on the socket after the parameters have been accepted */ gboolean gabble_tube_stream_check_params (TpSocketAddressType address_type, const GValue *address, TpSocketAccessControl access_control, const GValue *access_control_param, GError **error) { switch (address_type) { #ifdef GIBBER_TYPE_UNIX_TRANSPORT case TP_SOCKET_ADDRESS_TYPE_UNIX: return check_unix_params (address_type, address, access_control, access_control_param, error); #endif case TP_SOCKET_ADDRESS_TYPE_IPV4: case TP_SOCKET_ADDRESS_TYPE_IPV6: return check_ip_params (address_type, address, access_control, access_control_param, error); default: g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "Address type %d not implemented", address_type); return FALSE; } } static gboolean send_tube_offer (GabbleTubeStream *self, GError **error) { GabbleTubeStreamPrivate *priv = self->priv; TpBaseChannel *base = TP_BASE_CHANNEL (self); TpBaseConnection *base_conn = tp_base_channel_get_connection (base); GabbleConnection *conn = GABBLE_CONNECTION (base_conn); TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base); WockyNode *tube_node = NULL; WockyStanza *msg; TpHandleRepoIface *contact_repo; const gchar *jid; gboolean result; GabblePresence *presence; const gchar *resource; gchar *full_jid; g_assert (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT); contact_repo = tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT); jid = tp_handle_inspect (contact_repo, tp_base_channel_get_target_handle (base)); presence = gabble_presence_cache_get (conn->presence_cache, tp_base_channel_get_target_handle (base)); if (presence == NULL) { DEBUG ("can't find tube recipient's presence"); g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "can't find tube recipient's presence"); return FALSE; } resource = gabble_presence_pick_resource_by_caps (presence, 0, gabble_capability_set_predicate_has, NS_TUBES); if (resource == NULL) { DEBUG ("tube recipient doesn't have tubes capabilities"); g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "tube recipient doesn't have tubes capabilities"); return FALSE; } full_jid = g_strdup_printf ("%s/%s", jid, resource); msg = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, full_jid, '(', "tube", '*', &tube_node, ':', NS_TUBES, ')', GABBLE_AMP_DO_NOT_STORE_SPEC, NULL); g_free (full_jid); g_assert (tube_node != NULL); gabble_tube_iface_publish_in_node (GABBLE_TUBE_IFACE (self), base_conn, tube_node); result = _gabble_connection_send (conn, msg, error); if (result) { priv->state = TP_TUBE_CHANNEL_STATE_REMOTE_PENDING; } g_object_unref (msg); return TRUE; } /* can be called both from the old tube API and the new tube API */ gboolean gabble_tube_stream_offer (GabbleTubeStream *self, GError **error) { GabbleTubeStreamPrivate *priv = self->priv; TpBaseChannel *base = TP_BASE_CHANNEL (self); TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base); g_assert (priv->state == TP_TUBE_CHANNEL_STATE_NOT_OFFERED); if (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT) { /* 1-1 tube. Send tube offer message */ if (!send_tube_offer (self, error)) return FALSE; } else { /* muc tube is open as soon it's offered */ priv->state = TP_TUBE_CHANNEL_STATE_OPEN; g_signal_emit (G_OBJECT (self), signals[OPENED], 0); gabble_muc_channel_send_presence (priv->muc); } g_signal_emit (G_OBJECT (self), signals[OFFERED], 0); return TRUE; } static void destroy_socket_control_list (gpointer data) { GArray *tab = data; g_array_unref (tab); } /** * gabble_tube_stream_get_supported_socket_types * * Used to implement D-Bus property * org.freedesktop.Telepathy.Channel.Type.StreamTube.SupportedSocketTypes * and D-Bus method GetAvailableStreamTubeTypes * on org.freedesktop.Telepathy.Channel.Type.Tubes */ GHashTable * gabble_tube_stream_get_supported_socket_types (void) { GHashTable *ret; GArray *ipv4_tab, *ipv6_tab; TpSocketAccessControl access_control; #ifdef GIBBER_TYPE_UNIX_TRANSPORT GArray *unix_tab; #endif ret = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, destroy_socket_control_list); #ifdef GIBBER_TYPE_UNIX_TRANSPORT /* Socket_Address_Type_Unix */ unix_tab = g_array_sized_new (FALSE, FALSE, sizeof (TpSocketAccessControl), 1); access_control = TP_SOCKET_ACCESS_CONTROL_LOCALHOST; g_array_append_val (unix_tab, access_control); /* Credentials-passing is non-portable, so only advertise it on platforms * where we have an implementation (like Linux) */ if (gibber_unix_transport_supports_credentials ()) { access_control = TP_SOCKET_ACCESS_CONTROL_CREDENTIALS; g_array_append_val (unix_tab, access_control); } g_hash_table_insert (ret, GUINT_TO_POINTER (TP_SOCKET_ADDRESS_TYPE_UNIX), unix_tab); #endif /* Socket_Address_Type_IPv4 */ ipv4_tab = g_array_sized_new (FALSE, FALSE, sizeof (TpSocketAccessControl), 1); access_control = TP_SOCKET_ACCESS_CONTROL_LOCALHOST; g_array_append_val (ipv4_tab, access_control); access_control = TP_SOCKET_ACCESS_CONTROL_PORT; g_array_append_val (ipv4_tab, access_control); g_hash_table_insert (ret, GUINT_TO_POINTER (TP_SOCKET_ADDRESS_TYPE_IPV4), ipv4_tab); /* Socket_Address_Type_IPv6 */ ipv6_tab = g_array_sized_new (FALSE, FALSE, sizeof (TpSocketAccessControl), 1); access_control = TP_SOCKET_ACCESS_CONTROL_LOCALHOST; g_array_append_val (ipv6_tab, access_control); access_control = TP_SOCKET_ACCESS_CONTROL_PORT; g_array_append_val (ipv6_tab, access_control); g_hash_table_insert (ret, GUINT_TO_POINTER (TP_SOCKET_ADDRESS_TYPE_IPV6), ipv6_tab); return ret; } /** * gabble_tube_stream_offer_async * * Implements D-Bus method Offer * on org.freedesktop.Telepathy.Channel.Type.StreamTube */ static void gabble_tube_stream_offer_async (TpSvcChannelTypeStreamTube *iface, guint address_type, const GValue *address, guint access_control, GHashTable *parameters, DBusGMethodInvocation *context) { GabbleTubeStream *self = GABBLE_TUBE_STREAM (iface); GabbleTubeStreamPrivate *priv = self->priv; GError *error = NULL; TpBaseChannel *base = TP_BASE_CHANNEL (self); TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base); if (priv->state != TP_TUBE_CHANNEL_STATE_NOT_OFFERED) { g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Tube is not in the not offered state"); dbus_g_method_return_error (context, error); g_error_free (error); return; } if (!gabble_tube_stream_check_params (address_type, address, access_control, NULL, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); return; } g_assert (address_type == TP_SOCKET_ADDRESS_TYPE_UNIX || address_type == TP_SOCKET_ADDRESS_TYPE_IPV4 || address_type == TP_SOCKET_ADDRESS_TYPE_IPV6); g_assert (priv->address == NULL); priv->address_type = address_type; priv->address = tp_g_value_slice_dup (address); g_assert (priv->access_control == TP_SOCKET_ACCESS_CONTROL_LOCALHOST); priv->access_control = access_control; g_object_set (self, "parameters", parameters, NULL); if (!gabble_tube_stream_offer (self, &error)) { gabble_tube_iface_stream_close (GABBLE_TUBE_IFACE (self), TRUE); dbus_g_method_return_error (context, error); g_error_free (error); return; } if (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT) { tp_svc_channel_interface_tube_emit_tube_channel_state_changed ( self, TP_TUBE_CHANNEL_STATE_REMOTE_PENDING); } else { tp_svc_channel_interface_tube_emit_tube_channel_state_changed ( self, TP_TUBE_CHANNEL_STATE_OPEN); } tp_svc_channel_type_stream_tube_return_from_offer (context); } /** * gabble_tube_stream_accept_async * * Implements D-Bus method Accept * on org.freedesktop.Telepathy.Channel.Type.StreamTube */ static void gabble_tube_stream_accept_async (TpSvcChannelTypeStreamTube *iface, guint address_type, guint access_control, const GValue *access_control_param, DBusGMethodInvocation *context) { GabbleTubeStream *self = GABBLE_TUBE_STREAM (iface); GabbleTubeStreamPrivate *priv = self->priv; GError *error = NULL; /* parameters sanity checks are done in gabble_tube_stream_accept */ priv->address_type = address_type; priv->access_control = access_control; if (priv->access_control_param != NULL) tp_g_value_slice_free (priv->access_control_param); priv->access_control_param = tp_g_value_slice_dup (access_control_param); if (!gabble_tube_stream_accept (GABBLE_TUBE_IFACE (self), &error)) { dbus_g_method_return_error (context, error); g_error_free (error); return; } #if 0 /* TODO: add a property "muc" and set it at initialization */ if (priv->handle_type == TP_HANDLE_TYPE_ROOM) gabble_muc_channel_send_presence (self->muc, NULL); #endif tp_svc_channel_type_stream_tube_return_from_accept (context, priv->address); } const gchar * const * gabble_tube_stream_channel_get_allowed_properties (void) { return gabble_tube_stream_channel_allowed_properties; } static void tube_iface_init (gpointer g_iface, gpointer iface_data) { GabbleTubeIfaceClass *klass = (GabbleTubeIfaceClass *) g_iface; klass->accept = gabble_tube_stream_accept; klass->close = gabble_tube_iface_stream_close; klass->add_bytestream = gabble_tube_stream_add_bytestream; } static void streamtube_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcChannelTypeStreamTubeClass *klass = (TpSvcChannelTypeStreamTubeClass *) g_iface; #define IMPLEMENT(x, suffix) tp_svc_channel_type_stream_tube_implement_##x (\ klass, gabble_tube_stream_##x##suffix) IMPLEMENT(offer,_async); IMPLEMENT(accept,_async); #undef IMPLEMENT } telepathy-gabble-0.18.3/src/jingle-tp-util.h0000664000175000017500000000235112223562023022000 0ustar00cassidycassidy00000000000000/* * jingle-tp-util.h - Header for Telepathy-flavoured Jingle utility functions * Copyright © 2008–2012 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GABBLE_JINGLE_TP_UTIL_H #define GABBLE_JINGLE_TP_UTIL_H #include #include WockyJingleMediaType wocky_jingle_media_type_from_tp (TpMediaStreamType type); TpMediaStreamType wocky_jingle_media_type_to_tp (WockyJingleMediaType type); GPtrArray *gabble_build_tp_relay_info (GPtrArray *relays); #endif /* GABBLE_JINGLE_TP_UTIL_H */ telepathy-gabble-0.18.3/src/call-channel.c0000664000175000017500000005514012332440117021454 0ustar00cassidycassidy00000000000000/* * gabble-call-channel.c - Source for GabbleCallChannel * Copyright (C) 2006, 2009 Collabora Ltd. * Copyright (C) 2006 Nokia Corporation * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include #include #include #include #include "util.h" #include "call-channel.h" #include "call-content.h" #include "connection.h" #include "jingle-tp-util.h" #include "presence-cache.h" #define DEBUG_FLAG GABBLE_DEBUG_MEDIA #include "debug.h" static void async_initable_iface_init (GAsyncInitableIface *iface); static void call_session_state_changed_cb (WockyJingleSession *session, GParamSpec *param, GabbleCallChannel *self); static void call_member_content_added_cb (GabbleCallMember *member, GabbleCallMemberContent *content, GabbleCallChannel *self); static void call_member_content_removed_cb (GabbleCallMember *member, GabbleCallMemberContent *mcontent, GabbleBaseCallChannel *self); static void call_session_terminated_cb (WockyJingleSession *session, gboolean locally_terminated, WockyJingleReason termination_reason, gchar *reason_text, GabbleCallChannel *self); static void call_channel_accept (TpBaseMediaCallChannel *channel); static TpBaseCallContent * call_channel_add_content ( TpBaseCallChannel *base, const gchar *name, TpMediaStreamType type, TpMediaStreamDirection initial_direction, GError **error); static void call_channel_hold_state_changed (TpBaseMediaCallChannel *self, TpLocalHoldState hold_state, TpLocalHoldStateReason hold_state_reason); G_DEFINE_TYPE_WITH_CODE(GabbleCallChannel, gabble_call_channel, GABBLE_TYPE_BASE_CALL_CHANNEL, G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init); ); /* properties */ enum { PROP_SESSION = 1, LAST_PROPERTY }; /* private structure */ struct _GabbleCallChannelPrivate { gboolean dispose_has_run; /* Our only call member, owned by the base channel */ GabbleCallMember *member; WockyJingleSession *session; }; static void gabble_call_channel_constructed (GObject *obj) { GabbleCallChannel *self = GABBLE_CALL_CHANNEL (obj); GabbleCallChannelPrivate *priv = self->priv; GabbleBaseCallChannel *g_base = GABBLE_BASE_CALL_CHANNEL (obj); GabbleCallMember *member; member = gabble_base_call_channel_ensure_member_from_handle (g_base, tp_base_channel_get_target_handle (TP_BASE_CHANNEL (obj))); priv->member = member; if (priv->session != NULL) { GList *contents, *l; gabble_call_member_set_session (member, priv->session); gabble_signal_connect_weak (priv->session, "notify::state", G_CALLBACK (call_session_state_changed_cb), obj); gabble_signal_connect_weak (priv->session, "terminated", G_CALLBACK (call_session_terminated_cb), G_OBJECT (self)); gabble_signal_connect_weak (member, "content-added", G_CALLBACK (call_member_content_added_cb), G_OBJECT (self)); gabble_signal_connect_weak (member, "content-removed", G_CALLBACK (call_member_content_removed_cb), G_OBJECT (self)); contents = gabble_call_member_get_contents (member); for (l = contents; l != NULL; l = g_list_next (l)) { GabbleCallMemberContent *content = GABBLE_CALL_MEMBER_CONTENT (l->data); GabbleCallContent *c; c = gabble_base_call_channel_add_content (g_base, gabble_call_member_content_get_name (content), gabble_call_member_content_get_media_type (content), TP_CALL_CONTENT_DISPOSITION_INITIAL); gabble_call_content_add_member_content (c, content); } } if (G_OBJECT_CLASS (gabble_call_channel_parent_class)->constructed != NULL) G_OBJECT_CLASS (gabble_call_channel_parent_class)->constructed (obj); } static void gabble_call_channel_init (GabbleCallChannel *self) { GabbleCallChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_CALL_CHANNEL, GabbleCallChannelPrivate); self->priv = priv; } static void gabble_call_channel_dispose (GObject *object); static void gabble_call_channel_finalize (GObject *object); static void gabble_call_channel_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleCallChannel *self = GABBLE_CALL_CHANNEL (object); GabbleCallChannelPrivate *priv = self->priv; switch (property_id) { case PROP_SESSION: g_value_set_object (value, priv->session); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_call_channel_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleCallChannel *self = GABBLE_CALL_CHANNEL (object); GabbleCallChannelPrivate *priv = self->priv; switch (property_id) { case PROP_SESSION: g_assert (priv->session == NULL); priv->session = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_call_channel_class_init ( GabbleCallChannelClass *gabble_call_channel_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_call_channel_class); TpBaseMediaCallChannelClass *tp_base_media_call_class = TP_BASE_MEDIA_CALL_CHANNEL_CLASS (gabble_call_channel_class); TpBaseCallChannelClass *tp_base_call_class = TP_BASE_CALL_CHANNEL_CLASS (gabble_call_channel_class); TpBaseChannelClass *base_channel_class = TP_BASE_CHANNEL_CLASS (gabble_call_channel_class); GParamSpec *param_spec; g_type_class_add_private (gabble_call_channel_class, sizeof (GabbleCallChannelPrivate)); object_class->constructed = gabble_call_channel_constructed; object_class->get_property = gabble_call_channel_get_property; object_class->set_property = gabble_call_channel_set_property; object_class->dispose = gabble_call_channel_dispose; object_class->finalize = gabble_call_channel_finalize; base_channel_class->target_handle_type = TP_HANDLE_TYPE_CONTACT; tp_base_call_class->add_content = call_channel_add_content; tp_base_media_call_class->accept = call_channel_accept; tp_base_media_call_class->hold_state_changed = call_channel_hold_state_changed; param_spec = g_param_spec_object ("session", "WockyJingleSession object", "Jingle session associated with this media channel object.", WOCKY_TYPE_JINGLE_SESSION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SESSION, param_spec); } void gabble_call_channel_dispose (GObject *object) { GabbleCallChannel *self = GABBLE_CALL_CHANNEL (object); GabbleCallChannelPrivate *priv = self->priv; if (priv->dispose_has_run) return; self->priv->dispose_has_run = TRUE; tp_clear_object (&priv->session); if (G_OBJECT_CLASS (gabble_call_channel_parent_class)->dispose) G_OBJECT_CLASS (gabble_call_channel_parent_class)->dispose (object); } void gabble_call_channel_finalize (GObject *object) { G_OBJECT_CLASS (gabble_call_channel_parent_class)->finalize (object); } static void call_session_terminated_cb (WockyJingleSession *session, gboolean locally_terminated, WockyJingleReason termination_reason, gchar *reason_text, GabbleCallChannel *self) { TpHandle actor; TpCallStateChangeReason call_reason = TP_CALL_STATE_CHANGE_REASON_UNKNOWN; const gchar *dbus_detail = ""; if (tp_base_call_channel_get_state (TP_BASE_CALL_CHANNEL (self)) == TP_CALL_STATE_ENDED) { DEBUG ("ignoring jingle session terminate, already in ENDED state"); return; } if (reason_text == NULL) reason_text = ""; if (locally_terminated) actor = tp_base_channel_get_self_handle (TP_BASE_CHANNEL (self)); else actor = tp_base_channel_get_target_handle (TP_BASE_CHANNEL (self)); switch (termination_reason) { case WOCKY_JINGLE_REASON_UNKNOWN: call_reason = TP_CALL_STATE_CHANGE_REASON_UNKNOWN; break; case WOCKY_JINGLE_REASON_BUSY: call_reason = TP_CALL_STATE_CHANGE_REASON_BUSY; break; case WOCKY_JINGLE_REASON_CANCEL: if (locally_terminated) call_reason = TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED; else call_reason = TP_CALL_STATE_CHANGE_REASON_REJECTED; break; case WOCKY_JINGLE_REASON_CONNECTIVITY_ERROR: call_reason = TP_CALL_STATE_CHANGE_REASON_CONNECTIVITY_ERROR; break; case WOCKY_JINGLE_REASON_FAILED_APPLICATION: call_reason = TP_CALL_STATE_CHANGE_REASON_MEDIA_ERROR; dbus_detail = TP_ERROR_STR_MEDIA_CODECS_INCOMPATIBLE; break; case WOCKY_JINGLE_REASON_GENERAL_ERROR: call_reason = TP_CALL_STATE_CHANGE_REASON_SERVICE_ERROR; break; case WOCKY_JINGLE_REASON_GONE: /* This one is only in the media channel, we don't have a * Call reason to match */ call_reason = TP_CALL_STATE_CHANGE_REASON_UNKNOWN; break; case WOCKY_JINGLE_REASON_MEDIA_ERROR: call_reason = TP_CALL_STATE_CHANGE_REASON_MEDIA_ERROR; break; case WOCKY_JINGLE_REASON_SUCCESS: call_reason = TP_CALL_STATE_CHANGE_REASON_USER_REQUESTED; break; case WOCKY_JINGLE_REASON_TIMEOUT: call_reason = TP_CALL_STATE_CHANGE_REASON_NO_ANSWER; break; case WOCKY_JINGLE_REASON_DECLINE: call_reason = TP_CALL_STATE_CHANGE_REASON_REJECTED; break; case WOCKY_JINGLE_REASON_ALTERNATIVE_SESSION: break; case WOCKY_JINGLE_REASON_UNSUPPORTED_TRANSPORTS: call_reason = TP_CALL_STATE_CHANGE_REASON_NETWORK_ERROR; break; case WOCKY_JINGLE_REASON_FAILED_TRANSPORT: call_reason = TP_CALL_STATE_CHANGE_REASON_CONNECTIVITY_ERROR; dbus_detail = TP_ERROR_STR_CONNECTION_FAILED; break; case WOCKY_JINGLE_REASON_INCOMPATIBLE_PARAMETERS: call_reason = TP_CALL_STATE_CHANGE_REASON_MEDIA_ERROR; dbus_detail = TP_ERROR_STR_MEDIA_CODECS_INCOMPATIBLE; break; case WOCKY_JINGLE_REASON_SECURITY_ERROR: call_reason = TP_CALL_STATE_CHANGE_REASON_CONNECTIVITY_ERROR; break; case WOCKY_JINGLE_REASON_UNSUPPORTED_APPLICATIONS: call_reason = TP_CALL_STATE_CHANGE_REASON_MEDIA_ERROR; dbus_detail = TP_ERROR_STR_MEDIA_UNSUPPORTED_TYPE; break; case WOCKY_JINGLE_REASON_EXPIRED: /* No matching error in our spec */ call_reason = TP_CALL_STATE_CHANGE_REASON_UNKNOWN; break; default: call_reason = TP_CALL_STATE_CHANGE_REASON_UNKNOWN; break; } DEBUG ("Moving to ENDED state"); tp_base_call_channel_set_state (TP_BASE_CALL_CHANNEL (self), TP_CALL_STATE_ENDED, actor, call_reason, dbus_detail, reason_text); } static void call_session_state_changed_cb (WockyJingleSession *session, GParamSpec *param, GabbleCallChannel *self) { TpBaseCallChannel *cbase = TP_BASE_CALL_CHANNEL (self); WockyJingleState state; g_object_get (session, "state", &state, NULL); if (state == WOCKY_JINGLE_STATE_ACTIVE && !tp_base_call_channel_is_accepted (cbase)) { tp_base_call_channel_remote_accept (cbase); } } /* This function handles additional contents added by the remote side */ static void call_member_content_added_cb (GabbleCallMember *member, GabbleCallMemberContent *content, GabbleCallChannel *self) { GabbleBaseCallChannel *cbase = GABBLE_BASE_CALL_CHANNEL (self); WockyJingleContent *jingle_content; GabbleCallContent *c; jingle_content = gabble_call_member_content_get_jingle_content (content); if (jingle_content == NULL || wocky_jingle_content_is_created_by_us (jingle_content)) return; c = gabble_base_call_channel_add_content (cbase, gabble_call_member_content_get_name (content), gabble_call_member_content_get_media_type (content), TP_CALL_CONTENT_DISPOSITION_NONE); gabble_call_content_add_member_content (c, content); } static gboolean contact_is_media_capable (GabbleCallChannel *self, TpHandle handle, gboolean *wait_ret, GError **error) { TpBaseChannel *base = TP_BASE_CHANNEL (self); TpBaseConnection *base_conn = tp_base_channel_get_connection (base); GabbleConnection *conn = GABBLE_CONNECTION (base_conn); GabblePresence *presence; TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT); gboolean wait = FALSE; presence = gabble_presence_cache_get (conn->presence_cache, handle); if (presence != NULL) { const GabbleCapabilitySet *caps = gabble_presence_peek_caps (presence); if (gabble_capability_set_has_one (caps, gabble_capabilities_get_any_audio_video ())) return TRUE; } /* Okay, they're not capable (yet). Let's figure out whether we should wait, * and return an appropriate error. */ if (gabble_presence_cache_is_unsure (conn->presence_cache, handle)) { DEBUG ("presence cache is still unsure about handle %u", handle); wait = TRUE; } if (wait_ret != NULL) *wait_ret = wait; if (presence == NULL) g_set_error (error, TP_ERROR, TP_ERROR_OFFLINE, "contact %d (%s) has no presence available", handle, tp_handle_inspect (contact_handles, handle)); else g_set_error (error, TP_ERROR, TP_ERROR_NOT_CAPABLE, "contact %d (%s) doesn't have sufficient media caps", handle, tp_handle_inspect (contact_handles, handle)); return FALSE; } static void call_member_content_removed_cb (GabbleCallMember *member, GabbleCallMemberContent *mcontent, GabbleBaseCallChannel *self) { TpBaseCallChannel *cbase = TP_BASE_CALL_CHANNEL (self); GList *l; for (l = tp_base_call_channel_get_contents (cbase); l != NULL; l = g_list_next (l)) { GabbleCallContent *content = GABBLE_CALL_CONTENT (l->data); GList *contents = gabble_call_content_get_member_contents (content); if (contents != NULL && contents->data == mcontent) { tp_base_call_channel_remove_content (cbase, TP_BASE_CALL_CONTENT (content), 0, TP_CALL_STATE_CHANGE_REASON_PROGRESS_MADE, "", ""); break; } } } static void call_channel_continue_init (GabbleCallChannel *self, GSimpleAsyncResult *result) { GabbleCallChannelPrivate *priv = self->priv; TpBaseCallChannel *base = TP_BASE_CALL_CHANNEL (self); TpBaseChannel *tp_base = TP_BASE_CHANNEL (self); GError *error = NULL; gboolean initial_audio, initial_video; const gchar *initial_audio_name = NULL, *initial_video_name = NULL; if (priv->session == NULL) { GabbleCallMember *member; GList *contents, *l; member = gabble_base_call_channel_ensure_member_from_handle ( GABBLE_BASE_CALL_CHANNEL (self), tp_base_channel_get_target_handle (tp_base)); initial_audio = tp_base_call_channel_has_initial_audio (base, &initial_audio_name); initial_video = tp_base_call_channel_has_initial_video (base, &initial_video_name); if (!gabble_call_member_start_session (member, initial_audio ? initial_audio_name : NULL, initial_video ? initial_video_name : NULL, &error)) { g_simple_async_result_set_from_error (result, error); g_error_free (error); goto out; } priv->session = g_object_ref (gabble_call_member_get_session (member)); gabble_signal_connect_weak (priv->session, "notify::state", G_CALLBACK (call_session_state_changed_cb), G_OBJECT (self)); gabble_signal_connect_weak (priv->session, "terminated", G_CALLBACK (call_session_terminated_cb), G_OBJECT (self)); contents = gabble_call_member_get_contents (member); for (l = contents; l != NULL; l = g_list_next (l)) { GabbleCallMemberContent *content = GABBLE_CALL_MEMBER_CONTENT (l->data); GabbleCallContent *c; c = gabble_base_call_channel_add_content ( GABBLE_BASE_CALL_CHANNEL (self), gabble_call_member_content_get_name (content), gabble_call_member_content_get_media_type (content), TP_CALL_CONTENT_DISPOSITION_INITIAL); gabble_call_content_add_member_content (c, content); } gabble_signal_connect_weak (member, "content-added", G_CALLBACK (call_member_content_added_cb), G_OBJECT (self)); gabble_signal_connect_weak (member, "content-removed", G_CALLBACK (call_member_content_removed_cb), G_OBJECT (self)); } tp_base_channel_register (tp_base); out: g_simple_async_result_complete_in_idle (result); g_object_unref (result); } static void call_channel_capabilities_discovered_cb (GabblePresenceCache *cache, TpHandle handle, gpointer user_data) { GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); GabbleCallChannel *self = GABBLE_CALL_CHANNEL ( g_async_result_get_source_object (G_ASYNC_RESULT (result))); TpBaseChannel *tp_base = TP_BASE_CHANNEL (self); TpHandle target = tp_base_channel_get_target_handle (tp_base); GError *error_ = NULL; gboolean wait; if (target != handle || tp_base_channel_is_registered (tp_base)) goto out; if (!contact_is_media_capable (self, target, &wait, &error_)) { if (wait) { DEBUG ("contact %u caps still pending", target); g_error_free (error_); } else { DEBUG ("%u: %s", error_->code, error_->message); g_simple_async_result_set_from_error (result, error_); g_error_free (error_); g_simple_async_result_complete_in_idle (result); g_object_unref (result); } } else { call_channel_continue_init (self, result); } out: g_object_unref (self); } static void call_channel_init_async (GAsyncInitable *initable, int priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GabbleCallChannel *self = GABBLE_CALL_CHANNEL (initable); GabbleCallChannelPrivate *priv = self->priv; GabbleBaseCallChannel *base = GABBLE_BASE_CALL_CHANNEL (self); TpBaseChannel *tp_base = TP_BASE_CHANNEL (base); TpHandle target = tp_base_channel_get_target_handle (tp_base); GabbleConnection *conn = GABBLE_CONNECTION ( tp_base_channel_get_connection (tp_base)); GSimpleAsyncResult *result; GError *error_ = NULL; gboolean wait; result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, NULL); if (tp_base_channel_is_registered (tp_base)) { g_simple_async_result_complete_in_idle (result); g_object_unref (result); return; } if (priv->session == NULL && !contact_is_media_capable (self, target, &wait, &error_)) { if (wait) { DEBUG ("contact %u caps still pending, adding anyways", target); g_error_free (error_); /* Fuckers */ gabble_signal_connect_weak (conn->presence_cache, "capabilities-discovered", G_CALLBACK (call_channel_capabilities_discovered_cb), G_OBJECT (result)); } else { DEBUG ("%u: %s", error_->code, error_->message); g_simple_async_result_set_from_error (result, error_); g_error_free (error_); g_simple_async_result_complete_in_idle (result); g_object_unref (result); } } else { call_channel_continue_init (self, result); } } static void async_initable_iface_init (GAsyncInitableIface *iface) { iface->init_async = call_channel_init_async; } static void call_channel_accept (TpBaseMediaCallChannel *channel) { GabbleCallChannel *self = GABBLE_CALL_CHANNEL (channel); wocky_jingle_session_accept (self->priv->session); } static TpBaseCallContent * call_channel_add_content (TpBaseCallChannel *base, const gchar *name, TpMediaStreamType type, TpMediaStreamDirection initial_direction, GError **error) { GabbleCallChannel *self = GABBLE_CALL_CHANNEL (base); GabbleCallContent *content = NULL; GabbleCallMemberContent *mcontent; WockyJingleContentSenders senders; gboolean initiated_by_us; if (initial_direction == TP_MEDIA_STREAM_DIRECTION_NONE) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Jingle can not do contents with direction = NONE"); return NULL; } g_object_get (self->priv->session, "local-initiator", &initiated_by_us, NULL); switch (initial_direction) { case TP_MEDIA_STREAM_DIRECTION_SEND: senders = initiated_by_us ? WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR : WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER; break; case TP_MEDIA_STREAM_DIRECTION_RECEIVE: senders = initiated_by_us ? WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER : WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR; break; default: case TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL: senders = WOCKY_JINGLE_CONTENT_SENDERS_BOTH; } mcontent = gabble_call_member_create_content (self->priv->member, name, wocky_jingle_media_type_from_tp (type), senders, error); if (mcontent != NULL) { content = gabble_base_call_channel_add_content ( GABBLE_BASE_CALL_CHANNEL (base), name, wocky_jingle_media_type_from_tp (type), TP_CALL_CONTENT_DISPOSITION_NONE); gabble_call_content_add_member_content (content, mcontent); } return TP_BASE_CALL_CONTENT (content); } static void call_channel_hold_state_changed (TpBaseMediaCallChannel *bmcc, TpLocalHoldState hold_state, TpLocalHoldStateReason hold_state_reason) { GabbleCallChannel *self = GABBLE_CALL_CHANNEL (bmcc); switch (hold_state) { case TP_LOCAL_HOLD_STATE_HELD: case TP_LOCAL_HOLD_STATE_PENDING_HOLD: wocky_jingle_session_set_local_hold (self->priv->session, TRUE); break; case TP_LOCAL_HOLD_STATE_UNHELD: wocky_jingle_session_set_local_hold (self->priv->session, FALSE); break; case TP_LOCAL_HOLD_STATE_PENDING_UNHOLD: break; default: g_assert_not_reached (); } } telepathy-gabble-0.18.3/src/roomlist-manager.h0000644000175000017500000000425711165152372022427 0ustar00cassidycassidy00000000000000/* * roomlist-manager - ChannelManager for room lists * Copyright (C) 2006-2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GABBLE_ROOMLIST_MANAGER_H #define GABBLE_ROOMLIST_MANAGER_H #include G_BEGIN_DECLS typedef struct _GabbleRoomlistManager GabbleRoomlistManager; typedef struct _GabbleRoomlistManagerClass GabbleRoomlistManagerClass; typedef struct _GabbleRoomlistManagerPrivate GabbleRoomlistManagerPrivate; struct _GabbleRoomlistManagerClass { GObjectClass parent_class; }; struct _GabbleRoomlistManager { GObject parent; GabbleRoomlistManagerPrivate *priv; }; GType gabble_roomlist_manager_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_ROOMLIST_MANAGER \ (gabble_roomlist_manager_get_type ()) #define GABBLE_ROOMLIST_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_ROOMLIST_MANAGER,\ GabbleRoomlistManager)) #define GABBLE_ROOMLIST_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_ROOMLIST_MANAGER,\ GabbleRoomlistManagerClass)) #define GABBLE_IS_ROOMLIST_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_ROOMLIST_MANAGER)) #define GABBLE_IS_ROOMLIST_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_ROOMLIST_MANAGER)) #define GABBLE_ROOMLIST_MANAGER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_ROOMLIST_MANAGER,\ GabbleRoomlistManagerClass)) G_END_DECLS #endif telepathy-gabble-0.18.3/src/olpc-activity.h0000664000175000017500000000477212332440117021734 0ustar00cassidycassidy00000000000000/* * olpc-activity.h - Header for GabbleOlpcActivity * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_OLPC_ACTIVITY_H__ #define __GABBLE_OLPC_ACTIVITY_H__ #include #include #include "connection.h" G_BEGIN_DECLS typedef struct _GabbleOlpcActivity GabbleOlpcActivity; typedef struct _GabbleOlpcActivityClass GabbleOlpcActivityClass; typedef struct _GabbleOlpcActivityPrivate GabbleOlpcActivityPrivate; struct _GabbleOlpcActivityClass { GObjectClass parent_class; }; struct _GabbleOlpcActivity { GObject parent; TpHandle room; gchar *id; GHashTable *properties; GabbleOlpcActivityPrivate *priv; }; GType gabble_olpc_activity_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_OLPC_ACTIVITY \ (gabble_olpc_activity_get_type ()) #define GABBLE_OLPC_ACTIVITY(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_OLPC_ACTIVITY,\ GabbleOlpcActivity)) #define GABBLE_OLPC_ACTIVITY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_OLPC_ACTIVITY,\ GabbleOlpcActivityClass)) #define GABBLE_IS_OLPC_ACTIVITY(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_OLPC_ACTIVITY)) #define GABBLE_IS_OLPC_ACTIVITY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_OLPC_ACTIVITY)) #define GABBLE_OLPC_ACTIVITY_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_OLPC_ACTIVITY,\ GabbleOlpcActivityClass)) GabbleOlpcActivity * gabble_olpc_activity_new (GabbleConnection *conn, TpHandle room); const gchar * gabble_olpc_activity_get_room (GabbleOlpcActivity *activity); gboolean gabble_olpc_activity_is_visible (GabbleOlpcActivity *activity); G_END_DECLS #endif /* #ifndef __GABBLE_OLPC_ACTIVITY_H__ */ telepathy-gabble-0.18.3/src/connection-manager.h0000664000175000017500000000456612223562023022715 0ustar00cassidycassidy00000000000000/* * gabble-connection-manager.h - Header for GabbleConnectionManager * Copyright (C) 2005 Collabora Ltd. * Copyright (C) 2005 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_CONNECTION_MANAGER_H__ #define __GABBLE_CONNECTION_MANAGER_H__ #include #include G_BEGIN_DECLS typedef struct _GabbleConnectionManager GabbleConnectionManager; typedef struct _GabbleConnectionManagerClass GabbleConnectionManagerClass; typedef struct _GabbleConnectionManagerPrivate GabbleConnectionManagerPrivate; struct _GabbleConnectionManagerClass { TpBaseConnectionManagerClass parent_class; }; struct _GabbleConnectionManager { TpBaseConnectionManager parent; }; GType gabble_connection_manager_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_CONNECTION_MANAGER \ (gabble_connection_manager_get_type ()) #define GABBLE_CONNECTION_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_CONNECTION_MANAGER, \ GabbleConnectionManager)) #define GABBLE_CONNECTION_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_CONNECTION_MANAGER, \ GabbleConnectionManagerClass)) #define GABBLE_IS_CONNECTION_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_CONNECTION_MANAGER)) #define GABBLE_IS_CONNECTION_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_CONNECTION_MANAGER)) #define GABBLE_CONNECTION_MANAGER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_CONNECTION_MANAGER, \ GabbleConnectionManagerClass)) G_END_DECLS #endif /* #ifndef __GABBLE_CONNECTION_MANAGER_H__*/ telepathy-gabble-0.18.3/src/media-factory.c0000664000175000017500000012151712332441362021664 0ustar00cassidycassidy00000000000000/* * media-factory.c - Source for GabbleMediaFactory * Copyright (C) 2006 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "media-factory.h" #include #include #include #include #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_MEDIA #include "gabble/caps-channel-manager.h" #include "connection.h" #include "debug.h" #include "call-channel.h" #include "media-channel.h" #include "namespaces.h" #include "util.h" typedef struct { GabbleMediaFactory *self; TpExportableChannel *channel; GSList *request_tokens; } MediaChannelRequest; static MediaChannelRequest * media_channel_request_new (GabbleMediaFactory *self, TpExportableChannel *channel, gpointer request_token) { MediaChannelRequest *mcr = g_slice_new0 (MediaChannelRequest); mcr->self = self; mcr->channel = g_object_ref (channel); if (request_token != NULL) mcr->request_tokens = g_slist_prepend (mcr->request_tokens, request_token); return mcr; } static void media_channel_request_free (MediaChannelRequest *mcr) { g_object_unref (mcr->channel); g_slist_free (mcr->request_tokens); g_slice_free (MediaChannelRequest, mcr); } static void media_channel_request_succeeded_cb (MediaChannelRequest *mcr, GPtrArray *streams) { tp_channel_manager_emit_new_channel (mcr->self, mcr->channel, mcr->request_tokens); media_channel_request_free (mcr); } static void media_channel_request_failed_cb (MediaChannelRequest *mcr, GError *error) { GSList *l; for (l = mcr->request_tokens; l != NULL; l = g_slist_next (l)) tp_channel_manager_emit_request_failed (mcr->self, l->data, error->domain, error->code, error->message); media_channel_request_free (mcr); } static void channel_manager_iface_init (gpointer, gpointer); static void caps_channel_manager_iface_init (gpointer, gpointer); G_DEFINE_TYPE_WITH_CODE (GabbleMediaFactory, gabble_media_factory, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER, channel_manager_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_CAPS_CHANNEL_MANAGER, caps_channel_manager_iface_init)); /* properties */ enum { PROP_CONNECTION = 1, LAST_PROPERTY }; struct _GabbleMediaFactoryPrivate { GabbleConnection *conn; gulong status_changed_id; GList *media_channels; GList *call_channels; GList *pending_call_channels; guint channel_index; /* Whether or not we should use call channels for incoming calls */ gboolean use_call_channels; gboolean dispose_has_run; }; static void gabble_media_factory_init (GabbleMediaFactory *fac) { GabbleMediaFactoryPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (fac, GABBLE_TYPE_MEDIA_FACTORY, GabbleMediaFactoryPrivate); fac->priv = priv; priv->channel_index = 0; priv->conn = NULL; priv->dispose_has_run = FALSE; } static void gabble_media_factory_close_all (GabbleMediaFactory *fac); static void gabble_media_factory_dispose (GObject *object) { GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (object); GabbleMediaFactoryPrivate *priv = fac->priv; if (priv->dispose_has_run) return; DEBUG ("dispose called"); priv->dispose_has_run = TRUE; gabble_media_factory_close_all (fac); g_assert (priv->media_channels == NULL); g_assert (priv->call_channels == NULL); if (G_OBJECT_CLASS (gabble_media_factory_parent_class)->dispose) G_OBJECT_CLASS (gabble_media_factory_parent_class)->dispose (object); } static void gabble_media_factory_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (object); GabbleMediaFactoryPrivate *priv = fac->priv; switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, priv->conn); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_media_factory_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (object); GabbleMediaFactoryPrivate *priv = fac->priv; switch (property_id) { case PROP_CONNECTION: priv->conn = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_media_factory_constructed (GObject *object); static void gabble_media_factory_class_init (GabbleMediaFactoryClass *gabble_media_factory_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_media_factory_class); GParamSpec *param_spec; g_type_class_add_private (gabble_media_factory_class, sizeof (GabbleMediaFactoryPrivate)); object_class->constructed = gabble_media_factory_constructed; object_class->dispose = gabble_media_factory_dispose; object_class->get_property = gabble_media_factory_get_property; object_class->set_property = gabble_media_factory_set_property; param_spec = g_param_spec_object ("connection", "GabbleConnection object", "Gabble connection object that owns this media channel manager object.", GABBLE_TYPE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); } /** * media_channel_closed_cb: * * Signal callback for when a media channel is closed. Removes the references * that #GabbleMediaFactory holds to them. */ static void media_channel_closed_cb (GabbleMediaChannel *chan, gpointer user_data) { GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (user_data); GabbleMediaFactoryPrivate *priv = fac->priv; tp_channel_manager_emit_channel_closed_for_object (fac, TP_EXPORTABLE_CHANNEL (chan)); DEBUG ("removing media channel %p with ref count %d", chan, G_OBJECT (chan)->ref_count); priv->media_channels = g_list_remove (priv->media_channels, chan); g_object_unref (chan); } /** * new_media_channel * * Creates a new empty GabbleMediaChannel. */ static GabbleMediaChannel * new_media_channel (GabbleMediaFactory *fac, WockyJingleSession *sess, TpHandle maybe_peer, gboolean peer_in_rp, gboolean initial_audio, gboolean initial_video) { GabbleMediaFactoryPrivate *priv; TpBaseConnection *conn; GabbleMediaChannel *chan; gchar *object_path; g_assert (GABBLE_IS_MEDIA_FACTORY (fac)); priv = fac->priv; conn = (TpBaseConnection *) priv->conn; object_path = g_strdup_printf ("%s/MediaChannel%u", tp_base_connection_get_object_path (conn), priv->channel_index); priv->channel_index += 1; chan = g_object_new (GABBLE_TYPE_MEDIA_CHANNEL, "connection", priv->conn, "object-path", object_path, "session", sess, "initial-peer", maybe_peer, "peer-in-rp", peer_in_rp, "initial-audio", initial_audio, "initial-video", initial_video, NULL); DEBUG ("object path %s", object_path); g_signal_connect (chan, "closed", (GCallback) media_channel_closed_cb, fac); priv->media_channels = g_list_prepend (priv->media_channels, chan); g_free (object_path); return chan; } static void call_channel_closed_cb (GabbleCallChannel *chan, gpointer user_data) { GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (user_data); GabbleMediaFactoryPrivate *priv = fac->priv; tp_channel_manager_emit_channel_closed_for_object (fac, TP_EXPORTABLE_CHANNEL (chan)); DEBUG ("removing media channel %p with ref count %d", chan, G_OBJECT (chan)->ref_count); priv->call_channels = g_list_remove (priv->call_channels, chan); g_object_unref (chan); } static void call_channel_initialized (GObject *source, GAsyncResult *res, gpointer user_data) { MediaChannelRequest *mcr = user_data; GabbleMediaFactoryPrivate *priv = mcr->self->priv; GError *error = NULL; priv->pending_call_channels = g_list_remove (priv->pending_call_channels, mcr); if (g_async_initable_init_finish (G_ASYNC_INITABLE (source), res, &error)) { priv->call_channels = g_list_prepend (priv->call_channels, g_object_ref (mcr->channel)); tp_channel_manager_emit_new_channel (mcr->self, mcr->channel, mcr->request_tokens); g_signal_connect (mcr->channel, "closed", G_CALLBACK (call_channel_closed_cb), mcr->self); } else { GSList *l; for (l = mcr->request_tokens; l != NULL; l = g_slist_next (l)) tp_channel_manager_emit_request_failed (mcr->self, l->data, error->domain, error->code, error->message); } media_channel_request_free (mcr); } /** * new_call_channel * * Creates and triggers initialisation of a new empty GabbleCallChannel. */ static void new_call_channel (GabbleMediaFactory *self, WockyJingleSession *sess, TpHandle peer, gboolean initial_audio, const gchar *initial_audio_name, gboolean initial_video, const gchar *initial_video_name, gpointer request_token) { GabbleCallChannel *channel; MediaChannelRequest *mcr; gchar *object_path; TpBaseConnection *conn = TP_BASE_CONNECTION (self->priv->conn); TpHandle initiator; if (sess != NULL) initiator = peer; else initiator = tp_base_connection_get_self_handle (conn); object_path = g_strdup_printf ("%s/CallChannel%u", tp_base_connection_get_object_path (conn), self->priv->channel_index); self->priv->channel_index++; channel = g_object_new (GABBLE_TYPE_CALL_CHANNEL, "connection", conn, "object-path", object_path, "session", sess, "handle", peer, "initial-audio", initial_audio, "initial-audio-name", initial_audio_name != NULL ? initial_audio_name : "audio", "initial-video", initial_video, "initial-video-name", initial_video_name != NULL ? initial_video_name : "video", "requested", request_token != NULL, "initiator-handle", initiator, "mutable-contents", TRUE, NULL); g_free (object_path); mcr = media_channel_request_new (self, TP_EXPORTABLE_CHANNEL (channel), request_token); g_async_initable_init_async (G_ASYNC_INITABLE (channel), G_PRIORITY_DEFAULT, NULL, /* FIXME support cancelling the channel creation */ call_channel_initialized, mcr); self->priv->pending_call_channels = g_list_prepend (self->priv->pending_call_channels, mcr); g_object_unref (channel); } static void gabble_media_factory_close_all (GabbleMediaFactory *fac) { GabbleMediaFactoryPrivate *priv = fac->priv; DEBUG ("closing channels"); /* Close will cause the channel to be removed from the list indirectly..*/ while (priv->media_channels != NULL) gabble_media_channel_close ( GABBLE_MEDIA_CHANNEL (priv->media_channels->data)); /* Close will cause the channel to be removed from the list indirectly..*/ while (priv->call_channels != NULL) tp_base_channel_close (TP_BASE_CHANNEL (priv->call_channels->data)); if (priv->status_changed_id != 0) { g_signal_handler_disconnect (priv->conn, priv->status_changed_id); priv->status_changed_id = 0; } } static void new_jingle_session_cb (GabbleJingleMint *jm, WockyJingleSession *sess, gpointer data) { GabbleMediaFactory *self = GABBLE_MEDIA_FACTORY (data); GabbleMediaFactoryPrivate *priv = self->priv; TpHandleRepoIface *contacts; TpHandle peer; if (wocky_jingle_session_get_content_type (sess) != WOCKY_TYPE_JINGLE_MEDIA_RTP) return; if (gabble_muc_factory_handle_jingle_session (priv->conn->muc_factory, sess)) { /* Muji channel the muc factory is taking care of it */ return; } contacts = tp_base_connection_get_handles (TP_BASE_CONNECTION (priv->conn), TP_HANDLE_TYPE_CONTACT); peer = tp_handle_ensure (contacts, wocky_jingle_session_get_peer_jid (sess), NULL, NULL); if (self->priv->use_call_channels) { new_call_channel (self, sess, peer, FALSE, NULL, FALSE, NULL, NULL); } else { GabbleMediaChannel *chan = new_media_channel (self, sess, peer, FALSE, FALSE, FALSE); GList *cs; /* FIXME: we need this detection to properly adjust nat-traversal on * the channel. We hope all contents will have the same transport... */ cs = wocky_jingle_session_get_contents (sess); if (cs != NULL) { WockyJingleContent *c = cs->data; gchar *ns; g_object_get (c, "transport-ns", &ns, NULL); if (!tp_strdiff (ns, NS_JINGLE_TRANSPORT_ICEUDP)) g_object_set (chan, "nat-traversal", "ice-udp", NULL); else if (!tp_strdiff (ns, NS_JINGLE_TRANSPORT_RAWUDP)) g_object_set (chan, "nat-traversal", "none", NULL); g_free (ns); g_list_free (cs); } tp_channel_manager_emit_new_channel (self, TP_EXPORTABLE_CHANNEL (chan), NULL); } } static void connection_status_changed_cb (GabbleConnection *conn, guint status, guint reason, GabbleMediaFactory *self) { GabbleMediaFactoryPrivate *priv = self->priv; switch (status) { case TP_CONNECTION_STATUS_CONNECTING: g_signal_connect (priv->conn->jingle_mint, "incoming-session", G_CALLBACK (new_jingle_session_cb), self); break; case TP_CONNECTION_STATUS_DISCONNECTED: gabble_media_factory_close_all (self); break; } } static void gabble_media_factory_constructed (GObject *object) { void (*chain_up) (GObject *) = G_OBJECT_CLASS (gabble_media_factory_parent_class)->constructed; GabbleMediaFactory *self = GABBLE_MEDIA_FACTORY (object); GabbleMediaFactoryPrivate *priv = self->priv; if (chain_up != NULL) chain_up (object); priv->status_changed_id = g_signal_connect (priv->conn, "status-changed", (GCallback) connection_status_changed_cb, object); } static void gabble_media_factory_foreach_channel (TpChannelManager *manager, TpExportableChannelFunc foreach, gpointer user_data) { GabbleMediaFactory *fac = GABBLE_MEDIA_FACTORY (manager); GabbleMediaFactoryPrivate *priv = fac->priv; GList *l; for (l = priv->media_channels; l != NULL; l = g_list_next (l)) foreach (TP_EXPORTABLE_CHANNEL (l->data), user_data); for (l = priv->call_channels; l != NULL; l = g_list_next (l)) foreach (TP_EXPORTABLE_CHANNEL (l->data), user_data); } static const gchar * const media_channel_fixed_properties[] = { TP_PROP_CHANNEL_CHANNEL_TYPE, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL }; /* If you change this at all, you'll probably also need to change both_allowed * and video_allowed */ static const gchar * const named_channel_allowed_properties[] = { TP_PROP_CHANNEL_TARGET_HANDLE, TP_PROP_CHANNEL_TARGET_ID, TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_AUDIO, TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_VIDEO, NULL }; static const gchar * const * both_allowed = named_channel_allowed_properties + 2; static const gchar * const audio_allowed[] = { TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_AUDIO, TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_IMMUTABLE_STREAMS, NULL }; static const gchar * const video_allowed[] = { TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_VIDEO, TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_IMMUTABLE_STREAMS, NULL }; static const gchar * const both_allowed_immutable[] = { TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_AUDIO, TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_VIDEO, TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_IMMUTABLE_STREAMS, NULL }; static const gchar * const call_channel_allowed_properties[] = { TP_PROP_CHANNEL_TARGET_HANDLE, TP_PROP_CHANNEL_TARGET_ID, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO_NAME, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO_NAME, TP_PROP_CHANNEL_TYPE_CALL_MUTABLE_CONTENTS, NULL }; static const gchar * const call_audio_allowed[] = { TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO_NAME, NULL }; static const gchar * const call_video_allowed[] = { TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO_NAME, NULL }; static const gchar * const call_both_allowed[] = { TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO_NAME, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO_NAME, TP_PROP_CHANNEL_TYPE_CALL_MUTABLE_CONTENTS, NULL }; static const gchar * const call_both_allowed_immutable[] = { TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO_NAME, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO_NAME, NULL }; /* not advertised in type_foreach_channel_class - can only be requested with * RequestChannel, not with CreateChannel/EnsureChannel */ static const gchar * const anon_channel_allowed_properties[] = { NULL }; const gchar * const * gabble_media_factory_call_channel_allowed_properties (void) { return call_channel_allowed_properties; } static GHashTable * gabble_media_factory_streamed_media_channel_class (void) { GHashTable *table = tp_asv_new ( TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT, NULL); tp_asv_set_static_string (table, TP_PROP_CHANNEL_CHANNEL_TYPE, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA); return table; } static GHashTable * gabble_media_factory_call_channel_class (void) { GHashTable *table = tp_asv_new ( TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_CONTACT, NULL); tp_asv_set_static_string (table, TP_PROP_CHANNEL_CHANNEL_TYPE, TP_IFACE_CHANNEL_TYPE_CALL); return table; } static void gabble_media_factory_type_foreach_channel_class (GType type, TpChannelManagerTypeChannelClassFunc func, gpointer user_data) { GHashTable *table = gabble_media_factory_streamed_media_channel_class (); func (type, table, named_channel_allowed_properties, user_data); g_hash_table_unref (table); table = gabble_media_factory_call_channel_class (); func (type, table, call_channel_allowed_properties, user_data); g_hash_table_unref (table); } typedef enum { METHOD_REQUEST, METHOD_CREATE, METHOD_ENSURE, } RequestMethod; static gboolean gabble_media_factory_requestotron (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties, RequestMethod method) { GabbleMediaFactory *self = GABBLE_MEDIA_FACTORY (manager); GabbleMediaFactoryPrivate *priv = self->priv; TpHandleType handle_type; TpHandle handle; GabbleMediaChannel *channel = NULL; GError *error = NULL; gboolean require_target_handle, add_peer_to_remote_pending; gboolean initial_audio, initial_video; /* Supported modes of operation: * - RequestChannel(None, 0): * channel is anonymous; * caller may optionally use AddMembers to add the peer to RemotePending * without sending them any XML; * caller uses RequestStreams to set the peer and start the call. * - RequestChannel(Contact, n) where n != 0: * channel has TargetHandle=n; * n is in remote pending; * call is started when caller calls RequestStreams. * - CreateChannel({THT: Contact, TH: n}): * channel has TargetHandle=n * n is not in the group interface at all * call is started when caller calls RequestStreams. * - EnsureChannel({THT: Contact, TH: n}): * look for a channel whose peer is n, and return that if found with * whatever properties and group membership it has; * otherwise the same as into CreateChannel */ switch (method) { case METHOD_REQUEST: require_target_handle = FALSE; add_peer_to_remote_pending = TRUE; break; case METHOD_CREATE: case METHOD_ENSURE: require_target_handle = TRUE; add_peer_to_remote_pending = FALSE; break; default: g_assert_not_reached (); } if (tp_strdiff (tp_asv_get_string (request_properties, TP_PROP_CHANNEL_CHANNEL_TYPE), TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA)) return FALSE; handle_type = tp_asv_get_uint32 (request_properties, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL); handle = tp_asv_get_uint32 (request_properties, TP_PROP_CHANNEL_TARGET_HANDLE, NULL); initial_audio = tp_asv_get_boolean (request_properties, TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_AUDIO, NULL); initial_video = tp_asv_get_boolean (request_properties, TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_VIDEO, NULL); switch (handle_type) { case TP_HANDLE_TYPE_NONE: /* already checked by TpBaseConnection */ g_assert (handle == 0); if (require_target_handle) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "A valid Contact handle must be provided when requesting a media " "channel"); goto error; } if (tp_channel_manager_asv_has_unknown_properties (request_properties, media_channel_fixed_properties, anon_channel_allowed_properties, &error)) goto error; channel = new_media_channel (self, NULL, 0, FALSE, FALSE, FALSE); break; case TP_HANDLE_TYPE_CONTACT: /* validity already checked by TpBaseConnection */ g_assert (handle != 0); if (tp_channel_manager_asv_has_unknown_properties (request_properties, media_channel_fixed_properties, named_channel_allowed_properties, &error)) goto error; if (method == METHOD_ENSURE) { GList *l; TpHandle peer = 0; for (l = priv->media_channels; l != NULL; l = g_list_next (l)) { channel = GABBLE_MEDIA_CHANNEL (l->data); g_object_get (channel, "peer", &peer, NULL); if (peer == handle) { /* Per the spec, we ignore InitialAudio and InitialVideo when * looking for an existing channel. */ tp_channel_manager_emit_request_already_satisfied (self, request_token, TP_EXPORTABLE_CHANNEL (channel)); return TRUE; } } } channel = new_media_channel (self, NULL, handle, add_peer_to_remote_pending, initial_audio, initial_video); break; default: return FALSE; } g_assert (channel != NULL); gabble_media_channel_request_initial_streams (channel, (GFunc) media_channel_request_succeeded_cb, (GFunc) media_channel_request_failed_cb, media_channel_request_new (self, TP_EXPORTABLE_CHANNEL (channel), request_token)); return TRUE; error: tp_channel_manager_emit_request_failed (self, request_token, error->domain, error->code, error->message); g_error_free (error); return TRUE; } static gboolean gabble_media_factory_create_call (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties, RequestMethod method) { GabbleMediaFactory *self = GABBLE_MEDIA_FACTORY (manager); TpHandle target; GError *error = NULL; gboolean initial_audio, initial_video; const gchar *initial_audio_name, *initial_video_name; DEBUG ("Creating a new call channel"); if (tp_asv_get_uint32 (request_properties, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL) != TP_HANDLE_TYPE_CONTACT) return FALSE; if (tp_channel_manager_asv_has_unknown_properties (request_properties, media_channel_fixed_properties, call_channel_allowed_properties, &error)) goto error; target = tp_asv_get_uint32 (request_properties, TP_PROP_CHANNEL_TARGET_HANDLE, NULL); if (method == METHOD_ENSURE) { GList *l; TpHandle handle = 0; for (l = self->priv->call_channels; l != NULL; l = g_list_next (l)) { GabbleCallChannel *channel = GABBLE_CALL_CHANNEL (l->data); g_object_get (channel, "handle", &handle, NULL); if (handle == target) { /* Per the spec, we ignore InitialAudio and InitialVideo when * looking for an existing channel. */ tp_channel_manager_emit_request_already_satisfied (self, request_token, TP_EXPORTABLE_CHANNEL (channel)); return TRUE; } } for (l = self->priv->pending_call_channels; l != NULL; l = g_list_next (l)) { MediaChannelRequest *mcr = (MediaChannelRequest *) l->data; g_object_get (mcr->channel, "handle", &handle, NULL); if (handle == target) { /* Per the spec, we ignore InitialAudio and InitialVideo when * looking for an existing channel. */ mcr->request_tokens = g_slist_prepend (mcr->request_tokens, request_token); return TRUE; } } } initial_audio = tp_asv_get_boolean (request_properties, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, NULL); initial_video = tp_asv_get_boolean (request_properties, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, NULL); if (!initial_audio && !initial_video) { g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Call channel must contain at least " "one of InitialAudio or InitialVideo"); goto error; } /* FIXME creating the channel should check and wait for the capabilities * FIXME need to cope with disconnecting while channels are setting up */ initial_audio_name = tp_asv_get_string (request_properties, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO_NAME); initial_video_name = tp_asv_get_string (request_properties, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO_NAME); new_call_channel (self, NULL, target, initial_audio, initial_audio_name, initial_video, initial_video_name, request_token); return TRUE; error: tp_channel_manager_emit_request_failed (self, request_token, error->domain, error->code, error->message); g_error_free (error); return TRUE; } static gboolean gabble_media_factory_request_channel (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties) { return gabble_media_factory_requestotron (manager, request_token, request_properties, METHOD_REQUEST); } static gboolean gabble_media_factory_create_channel (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties) { if (!tp_strdiff (tp_asv_get_string (request_properties, TP_PROP_CHANNEL_CHANNEL_TYPE), TP_IFACE_CHANNEL_TYPE_CALL)) return gabble_media_factory_create_call (manager, request_token, request_properties, METHOD_CREATE); else return gabble_media_factory_requestotron (manager, request_token, request_properties, METHOD_CREATE); } static gboolean gabble_media_factory_ensure_channel (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties) { if (!tp_strdiff (tp_asv_get_string (request_properties, TP_PROP_CHANNEL_CHANNEL_TYPE), TP_IFACE_CHANNEL_TYPE_CALL)) return gabble_media_factory_create_call (manager, request_token, request_properties, METHOD_ENSURE); else return gabble_media_factory_requestotron (manager, request_token, request_properties, METHOD_ENSURE); } static void channel_manager_iface_init (gpointer g_iface, gpointer iface_data) { TpChannelManagerIface *iface = g_iface; iface->foreach_channel = gabble_media_factory_foreach_channel; iface->type_foreach_channel_class = gabble_media_factory_type_foreach_channel_class; iface->request_channel = gabble_media_factory_request_channel; iface->create_channel = gabble_media_factory_create_channel; iface->ensure_channel = gabble_media_factory_ensure_channel; } static void gabble_media_factory_add_caps (GabbleCapabilitySet *caps, const gchar *client_name, gboolean audio, gboolean video, gboolean gtalk_p2p, gboolean ice_udp, gboolean h264) { gboolean any_content = audio || video; DEBUG ("Client %s media capabilities:%s%s%s%s%s", client_name, audio ? " audio" : "", video ? " video" : "", gtalk_p2p ? " gtalk-p2p" : "", ice_udp ? " ice-udp" : "", h264 ? " H.264" : ""); if (gtalk_p2p && any_content) gabble_capability_set_add (caps, NS_GOOGLE_TRANSPORT_P2P); if (ice_udp && any_content) gabble_capability_set_add (caps, NS_JINGLE_TRANSPORT_ICEUDP); if (audio) { gabble_capability_set_add (caps, NS_JINGLE_RTP); gabble_capability_set_add (caps, NS_JINGLE_RTP_AUDIO); gabble_capability_set_add (caps, NS_JINGLE_DESCRIPTION_AUDIO); gabble_capability_set_add (caps, NS_JINGLE_RTP_HDREXT); gabble_capability_set_add (caps, NS_JINGLE_RTCP_FB); /* voice-v1 implies that we interop with GTalk, i.e. we have gtalk-p2p * as well as audio */ if (gtalk_p2p) gabble_capability_set_add (caps, NS_GOOGLE_FEAT_VOICE); } if (video) { gabble_capability_set_add (caps, NS_JINGLE_RTP); gabble_capability_set_add (caps, NS_JINGLE_RTP_VIDEO); gabble_capability_set_add (caps, NS_JINGLE_DESCRIPTION_VIDEO); gabble_capability_set_add (caps, NS_JINGLE_RTP_HDREXT); gabble_capability_set_add (caps, NS_JINGLE_RTCP_FB); /* video-v1 implies that we interop with Google Video Chat, i.e. we have * gtalk-p2p and H.264 as well as video */ if (gtalk_p2p && h264) { gabble_capability_set_add (caps, NS_GOOGLE_FEAT_VIDEO); gabble_capability_set_add (caps, NS_GOOGLE_FEAT_CAMERA); } } } /* The switch in gabble_media_factory_get_contact_caps needs to be kept in * sync with the possible returns from this function. */ TpChannelMediaCapabilities _gabble_media_factory_caps_to_typeflags (const GabbleCapabilitySet *caps) { TpChannelMediaCapabilities typeflags = 0; gboolean has_a_transport, just_google, one_media_type; has_a_transport = gabble_capability_set_has_one (caps, gabble_capabilities_get_any_transport ()); if (has_a_transport && gabble_capability_set_has_one (caps, gabble_capabilities_get_any_audio ())) typeflags |= TP_CHANNEL_MEDIA_CAPABILITY_AUDIO; if (has_a_transport && gabble_capability_set_has_one (caps, gabble_capabilities_get_any_video ())) typeflags |= TP_CHANNEL_MEDIA_CAPABILITY_VIDEO; /* The checks below are an intentional asymmetry with the function going the * other way - we don't require the other end to advertise the GTalk-P2P * transport capability separately because old GTalk clients didn't do that. * Having Google voice implied Google session and GTalk-P2P. */ if (gabble_capability_set_has (caps, NS_GOOGLE_FEAT_VOICE)) typeflags |= TP_CHANNEL_MEDIA_CAPABILITY_AUDIO; if (gabble_capability_set_has (caps, NS_GOOGLE_FEAT_VIDEO)) typeflags |= TP_CHANNEL_MEDIA_CAPABILITY_VIDEO; just_google = gabble_capability_set_has_one (caps, gabble_capabilities_get_any_google_av ()) && !gabble_capability_set_has_one (caps, gabble_capabilities_get_any_jingle_av ()); one_media_type = (typeflags == TP_CHANNEL_MEDIA_CAPABILITY_AUDIO) || (typeflags == TP_CHANNEL_MEDIA_CAPABILITY_VIDEO); if (just_google || one_media_type) typeflags |= TP_CHANNEL_MEDIA_CAPABILITY_IMMUTABLE_STREAMS; return typeflags; } void _gabble_media_factory_typeflags_to_caps (TpChannelMediaCapabilities flags, GabbleCapabilitySet *caps) { DEBUG ("adding Jingle caps %u", flags); /* The client name just appears in a debug message, so use something that * won't, in practice, clash with any client that uses ContactCapabilities */ gabble_media_factory_add_caps (caps, "", (flags & TP_CHANNEL_MEDIA_CAPABILITY_AUDIO) != 0, (flags & TP_CHANNEL_MEDIA_CAPABILITY_VIDEO) != 0, (flags & TP_CHANNEL_MEDIA_CAPABILITY_NAT_TRAVERSAL_GTALK_P2P) != 0, (flags & TP_CHANNEL_MEDIA_CAPABILITY_NAT_TRAVERSAL_ICE_UDP) != 0, TRUE /* assume we have H.264 for now */); } static void gabble_media_factory_get_contact_caps (GabbleCapsChannelManager *manager, TpHandle handle, const GabbleCapabilitySet *caps, GPtrArray *arr) { TpChannelMediaCapabilities typeflags = _gabble_media_factory_caps_to_typeflags (caps); GValueArray *va; const gchar * const *streamed_media_allowed; const gchar * const *call_allowed; typeflags &= (TP_CHANNEL_MEDIA_CAPABILITY_AUDIO | TP_CHANNEL_MEDIA_CAPABILITY_VIDEO | TP_CHANNEL_MEDIA_CAPABILITY_IMMUTABLE_STREAMS); /* This switch is over the values of several bits from a * bitfield-represented-as-an-enum, simultaneously, which upsets gcc-4.5; * the guint cast reassures it that we know what we're doing. * _gabble_media_factory_caps_to_typeflags shouldn't return any cases not * handled here. */ switch ((guint) typeflags) { case 0: return; case TP_CHANNEL_MEDIA_CAPABILITY_AUDIO | TP_CHANNEL_MEDIA_CAPABILITY_IMMUTABLE_STREAMS: streamed_media_allowed = audio_allowed; call_allowed = call_audio_allowed; break; case TP_CHANNEL_MEDIA_CAPABILITY_VIDEO | TP_CHANNEL_MEDIA_CAPABILITY_IMMUTABLE_STREAMS: streamed_media_allowed = video_allowed; call_allowed = call_video_allowed; break; case TP_CHANNEL_MEDIA_CAPABILITY_AUDIO | TP_CHANNEL_MEDIA_CAPABILITY_VIDEO: /* both */ streamed_media_allowed = both_allowed; call_allowed = call_both_allowed; break; case TP_CHANNEL_MEDIA_CAPABILITY_AUDIO /* both but immutable */ | TP_CHANNEL_MEDIA_CAPABILITY_VIDEO | TP_CHANNEL_MEDIA_CAPABILITY_IMMUTABLE_STREAMS: streamed_media_allowed = both_allowed_immutable; call_allowed = call_both_allowed_immutable; break; default: g_assert_not_reached (); } /* Streamed Media channel */ va = g_value_array_new (2); g_value_array_append (va, NULL); g_value_array_append (va, NULL); g_value_init (va->values + 0, TP_HASH_TYPE_CHANNEL_CLASS); g_value_init (va->values + 1, G_TYPE_STRV); g_value_take_boxed (va->values + 0, gabble_media_factory_streamed_media_channel_class ()); g_value_set_static_boxed (va->values + 1, streamed_media_allowed); g_ptr_array_add (arr, va); /* Call channel */ va = g_value_array_new (2); g_value_array_append (va, NULL); g_value_array_append (va, NULL); g_value_init (va->values + 0, TP_HASH_TYPE_CHANNEL_CLASS); g_value_init (va->values + 1, G_TYPE_STRV); g_value_take_boxed (va->values + 0, gabble_media_factory_call_channel_class ()); g_value_set_static_boxed (va->values + 1, call_allowed); g_ptr_array_add (arr, va); } static void gabble_media_factory_represent_client (GabbleCapsChannelManager *manager, const gchar *client_name, const GPtrArray *filters, const gchar * const *cap_tokens, GabbleCapabilitySet *cap_set, GPtrArray *data_forms) { static GQuark q_gtalk_p2p = 0, q_ice_udp = 0, q_h264 = 0; static GQuark qc_gtalk_p2p = 0, qc_ice_udp = 0, qc_h264 = 0, qc_ice = 0; gboolean gtalk_p2p = FALSE, h264 = FALSE, audio = FALSE, video = FALSE, ice_udp = FALSE; guint i; /* One-time initialization - turn the tokens we care about into quarks */ if (G_UNLIKELY (q_gtalk_p2p == 0)) { q_gtalk_p2p = g_quark_from_static_string ( TP_TOKEN_CHANNEL_INTERFACE_MEDIA_SIGNALLING_GTALK_P2P); qc_gtalk_p2p = g_quark_from_static_string ( TP_TOKEN_CHANNEL_TYPE_CALL_GTALK_P2P); q_ice_udp = g_quark_from_static_string ( TP_TOKEN_CHANNEL_INTERFACE_MEDIA_SIGNALLING_ICE_UDP); qc_ice = g_quark_from_static_string ( TP_TOKEN_CHANNEL_TYPE_CALL_ICE); /* 'ice-udp' isn't the proper cap name, 'ice' is. We keep supporting * 'ice-udp' for now to not break existing clients. */ qc_ice_udp = g_quark_from_static_string ( TP_IFACE_CHANNEL_TYPE_CALL "/ice-udp"); q_h264 = g_quark_from_static_string ( TP_IFACE_CHANNEL_INTERFACE_MEDIA_SIGNALLING "/video/h264"); qc_h264 = g_quark_from_static_string ( TP_IFACE_CHANNEL_TYPE_CALL "/video/h264"); } if (cap_tokens != NULL) { const gchar * const *token; for (token = cap_tokens; *token != NULL; token++) { GQuark quark = g_quark_try_string (*token); struct { GQuark quark; gboolean *cap; } q2cap[] = { { q_gtalk_p2p, >alk_p2p }, { qc_gtalk_p2p, >alk_p2p }, { q_ice_udp, &ice_udp }, { qc_ice_udp, &ice_udp }, { qc_ice, &ice_udp }, { q_h264, &h264 }, { qc_h264, &h264 }, { 0, NULL }, }; for (i = 0; q2cap[i].quark != 0; i++) { if (quark == q2cap[i].quark) *(q2cap[i].cap) = TRUE; } } } for (i = 0; i < filters->len; i++) { GHashTable *filter = g_ptr_array_index (filters, i); if (tp_asv_size (filter) == 0) { /* a client that claims to be able to do absolutely everything can * presumably do audio, video, smell, etc. etc. */ audio = TRUE; video = TRUE; continue; } if (tp_strdiff (tp_asv_get_string (filter, TP_PROP_CHANNEL_CHANNEL_TYPE), TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA) && tp_strdiff (tp_asv_get_string (filter, TP_PROP_CHANNEL_CHANNEL_TYPE), TP_IFACE_CHANNEL_TYPE_CALL)) { /* not interesting to this channel manager */ continue; } #ifdef ENABLE_CHANNEL_TYPE_CALL /* If there is a handler that can support Call channels, use those for * incoming channels */ if (!tp_strdiff (tp_asv_get_string (filter, TP_PROP_CHANNEL_CHANNEL_TYPE), TP_IFACE_CHANNEL_TYPE_CALL)) { GabbleMediaFactory *self = GABBLE_MEDIA_FACTORY (manager); self->priv->use_call_channels = TRUE; } #endif if (tp_asv_lookup (filter, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE) != NULL && tp_asv_get_uint32 (filter, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL) != TP_HANDLE_TYPE_CONTACT) { /* not interesting to this channel manager: we only care about * Jingle calls involving contacts (or about clients that support * all Jingle calls regardless of handle type) */ continue; } if (tp_asv_get_boolean (filter, TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_AUDIO, NULL) || tp_asv_get_boolean (filter, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, NULL)) audio = TRUE; if (tp_asv_get_boolean (filter, TP_PROP_CHANNEL_TYPE_STREAMED_MEDIA_INITIAL_VIDEO, NULL) || tp_asv_get_boolean (filter, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, NULL)) video = TRUE; /* If we've picked up all the capabilities we're ever going to, then * we don't need to look at the rest of the filters */ if (audio && video) break; } gabble_media_factory_add_caps (cap_set, client_name, audio, video, gtalk_p2p, ice_udp, h264); } static void caps_channel_manager_iface_init (gpointer g_iface, gpointer iface_data) { GabbleCapsChannelManagerInterface *iface = g_iface; iface->get_contact_caps = gabble_media_factory_get_contact_caps; iface->represent_client = gabble_media_factory_represent_client; } telepathy-gabble-0.18.3/src/conn-presence.h0000664000175000017500000000517212332440117021677 0ustar00cassidycassidy00000000000000/* * conn-presence.h - Header for Gabble connection presence interface * Copyright (C) 2005-2007 Collabora Ltd. * Copyright (C) 2005-2007 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __CONN_PRESENCE_H__ #define __CONN_PRESENCE_H__ #include #include "connection.h" G_BEGIN_DECLS typedef enum { CONN_PRESENCE_ERROR_SET_INVISIBLE = 0, CONN_PRESENCE_ERROR_CREATE_PRIVACY_LIST, CONN_PRESENCE_ERROR_RETRIEVE_PRIVACY_LIST, CONN_PRESENCE_ERROR_INVALID_PRIVACY_LIST, CONN_PRESENCE_ERROR_SET_PRIVACY_LIST, CONN_PRESENCE_ERROR_SET_INVISIBLE_PRESENCE, CONN_PRESENCE_ERROR_SET_SHARED_STATUS } GabbleConnPresenceErrorType; GQuark conn_presence_error_quark (void); #define CONN_PRESENCE_ERROR (conn_presence_error_quark ()) void conn_presence_class_init (GabbleConnectionClass *klass); void conn_presence_init (GabbleConnection *conn); void conn_presence_finalize (GabbleConnection *conn); void conn_presence_dispose (GabbleConnection *self); void conn_presence_iface_init (gpointer g_iface, gpointer iface_data); void conn_presence_emit_presence_update ( GabbleConnection *, const GArray *contact_handles); gboolean conn_presence_signal_own_presence (GabbleConnection *self, const gchar *to, GError **error); gboolean conn_presence_visible_to (GabbleConnection *self, TpHandle recipient); void conn_presence_set_initial_presence_async (GabbleConnection *self, GAsyncReadyCallback callback, gpointer user_data); gboolean conn_presence_set_initial_presence_finish (GabbleConnection *self, GAsyncResult *result, GError **error); void conn_decloak_iface_init (gpointer g_iface, gpointer iface_data); void conn_decloak_emit_requested (GabbleConnection *conn, TpHandle contact, const gchar *reason, gboolean decloaked); TpConnectionPresenceType conn_presence_get_type (GabblePresence *presence); const TpPresenceStatusSpec *conn_presence_statuses (void); G_END_DECLS #endif /* __CONN_PRESENCE_H__ */ telepathy-gabble-0.18.3/src/muc-factory.c0000664000175000017500000015740712332441362021400 0ustar00cassidycassidy00000000000000/* * muc-factory.c - Source for GabbleMucFactory * Copyright (C) 2006 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "muc-factory.h" #include #include #include #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_MUC #include "gabble/caps-channel-manager.h" #include "connection.h" #include "conn-olpc.h" #include "debug.h" #include "disco.h" #include "im-channel.h" #ifdef ENABLE_VOIP #include "media-factory.h" #endif #include "message-util.h" #include "muc-channel.h" #include "namespaces.h" #include "presence-cache.h" #include "tube-dbus.h" #include "tube-stream.h" #include "util.h" #ifdef ENABLE_VOIP #include "call-muc-channel.h" #endif static void channel_manager_iface_init (gpointer, gpointer); G_DEFINE_TYPE_WITH_CODE (GabbleMucFactory, gabble_muc_factory, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER, channel_manager_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_CAPS_CHANNEL_MANAGER, NULL)); /* properties */ enum { PROP_CONNECTION = 1, LAST_PROPERTY }; typedef struct { GabbleMucFactory *self; gpointer token; } Request; struct _GabbleMucFactoryPrivate { GabbleConnection *conn; gulong status_changed_id; guint message_cb_id; /* GUINT_TO_POINTER(room_handle) => (GabbleMucChannel *) */ GHashTable *text_channels; /* Tube channels which will be considered ready when the corresponding * text channel is created. * Borrowed GabbleMucChannel => owned GQueue of borrowed GabbleTubeIface */ GHashTable *text_needed_for_tube; /* GabbleDiscoRequest * => NULL (used as a set) */ GHashTable *disco_requests; /* Map from channels to the request-tokens of requests that they will satisfy * when they're ready. * Borrowed TpExportableChannel => GSList of gpointer */ GHashTable *queued_requests; gboolean dispose_has_run; }; static GObject *gabble_muc_factory_constructor (GType type, guint n_props, GObjectConstructParam *props); static void gabble_muc_factory_associate_tube (GabbleMucFactory *self, GabbleMucChannel *gmuc, GabbleTubeIface *tube); static void gabble_muc_factory_init (GabbleMucFactory *fac) { GabbleMucFactoryPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (fac, GABBLE_TYPE_MUC_FACTORY, GabbleMucFactoryPrivate); fac->priv = priv; priv->text_channels = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); priv->text_needed_for_tube = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_queue_free); priv->disco_requests = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); priv->queued_requests = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); priv->conn = NULL; priv->dispose_has_run = FALSE; } static void cancel_disco_request (gpointer key, gpointer value, gpointer user_data) { GabbleDisco *disco = GABBLE_DISCO (user_data); GabbleDiscoRequest *request = (GabbleDiscoRequest *) key; gabble_disco_cancel_request (disco, request); } static void gabble_muc_factory_close_all (GabbleMucFactory *fac); static void gabble_muc_factory_dispose (GObject *object) { GabbleMucFactory *fac = GABBLE_MUC_FACTORY (object); GabbleMucFactoryPrivate *priv = fac->priv; if (priv->dispose_has_run) return; DEBUG ("dispose called"); priv->dispose_has_run = TRUE; gabble_muc_factory_close_all (fac); g_assert (priv->text_channels == NULL); g_assert (priv->text_needed_for_tube == NULL); g_assert (priv->queued_requests == NULL); g_hash_table_foreach (priv->disco_requests, cancel_disco_request, priv->conn->disco); g_hash_table_unref (priv->disco_requests); if (G_OBJECT_CLASS (gabble_muc_factory_parent_class)->dispose) G_OBJECT_CLASS (gabble_muc_factory_parent_class)->dispose (object); } static void gabble_muc_factory_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleMucFactory *fac = GABBLE_MUC_FACTORY (object); GabbleMucFactoryPrivate *priv = fac->priv; switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, priv->conn); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_muc_factory_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleMucFactory *fac = GABBLE_MUC_FACTORY (object); GabbleMucFactoryPrivate *priv = fac->priv; switch (property_id) { case PROP_CONNECTION: priv->conn = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_muc_factory_class_init (GabbleMucFactoryClass *gabble_muc_factory_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_muc_factory_class); GParamSpec *param_spec; g_type_class_add_private (gabble_muc_factory_class, sizeof (GabbleMucFactoryPrivate)); object_class->constructor = gabble_muc_factory_constructor; object_class->dispose = gabble_muc_factory_dispose; object_class->get_property = gabble_muc_factory_get_property; object_class->set_property = gabble_muc_factory_set_property; param_spec = g_param_spec_object ("connection", "GabbleConnection object", "Gabble connection object that owns this MUC factory object.", GABBLE_TYPE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); } /** * muc_channel_closed_cb: * * Signal callback for when a MUC channel is closed. Removes the references * that MucFactory holds to them. */ static void muc_channel_closed_cb (GabbleMucChannel *chan, gpointer user_data) { GabbleMucFactory *fac = GABBLE_MUC_FACTORY (user_data); GabbleMucFactoryPrivate *priv = fac->priv; TpBaseChannel *base = TP_BASE_CHANNEL (chan); TpHandle room_handle; /* channel is actually reappearing, announce it */ if (tp_base_channel_is_respawning (base)) { tp_channel_manager_emit_new_channel (fac, TP_EXPORTABLE_CHANNEL (chan), NULL); return; } if (tp_base_channel_is_registered (base)) { tp_channel_manager_emit_channel_closed_for_object (fac, TP_EXPORTABLE_CHANNEL (chan)); } if (tp_base_channel_is_destroyed (base) && priv->text_channels != NULL) { g_object_get (chan, "handle", &room_handle, NULL); DEBUG ("removing MUC channel with handle %d", room_handle); g_hash_table_remove (priv->text_channels, GUINT_TO_POINTER (room_handle)); } } static void muc_ready_cb (GabbleMucChannel *text_chan, gpointer data) { GabbleMucFactory *fac = GABBLE_MUC_FACTORY (data); GabbleMucFactoryPrivate *priv = fac->priv; GHashTable *channels; TpBaseChannel *base = TP_BASE_CHANNEL (text_chan); GSList *requests_satisfied_text = NULL; GQueue *tube_channels; DEBUG ("text chan=%p", text_chan); channels = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_slist_free); requests_satisfied_text = g_hash_table_lookup ( priv->queued_requests, text_chan); g_hash_table_steal (priv->queued_requests, text_chan); requests_satisfied_text = g_slist_reverse (requests_satisfied_text); /* Announce tube channels now */ tube_channels = g_hash_table_lookup (priv->text_needed_for_tube, text_chan); if (tube_channels != NULL) { GList *l; for (l = tube_channels->head; l != NULL; l = l->next) { GabbleTubeIface *tube_chan = GABBLE_TUBE_IFACE (l->data); GSList *requests_satisfied_tube; requests_satisfied_tube = g_hash_table_lookup ( priv->queued_requests, tube_chan); g_hash_table_steal (priv->queued_requests, tube_chan); requests_satisfied_tube = g_slist_reverse (requests_satisfied_tube); g_hash_table_insert (channels, tube_chan, requests_satisfied_tube); } g_hash_table_remove (priv->text_needed_for_tube, text_chan); } /* only announce channels which are on the bus (requested or * requested with an invite, not channels only around because they * have to be) */ if (tp_base_channel_is_registered (base)) { tp_channel_manager_emit_new_channel (fac, TP_EXPORTABLE_CHANNEL (text_chan), requests_satisfied_text); } tp_channel_manager_emit_new_channels (fac, channels); g_hash_table_unref (channels); } static void muc_join_error_cb (GabbleMucChannel *chan, GError *error, gpointer data) { GabbleMucFactory *fac = GABBLE_MUC_FACTORY (data); GabbleMucFactoryPrivate *priv = fac->priv; GQueue *tube_channels; GSList *requests_satisfied; GSList *iter; DEBUG ("error->code=%u, error->message=\"%s\"", error->code, error->message); requests_satisfied = g_slist_reverse (g_hash_table_lookup ( priv->queued_requests, chan)); g_hash_table_steal (priv->queued_requests, chan); for (iter = requests_satisfied; iter != NULL; iter = iter->next) { tp_channel_manager_emit_request_failed (fac, iter->data, error->domain, error->code, error->message); } g_slist_free (requests_satisfied); /* tube channels */ tube_channels = g_hash_table_lookup (priv->text_needed_for_tube, chan); if (tube_channels != NULL) { GList *l; for (l = tube_channels->head; l != NULL; l = l->next) { GabbleTubeIface *tube_chan = GABBLE_TUBE_IFACE (l->data); requests_satisfied = g_hash_table_lookup ( priv->queued_requests, tube_chan); g_hash_table_steal (priv->queued_requests, tube_chan); requests_satisfied = g_slist_reverse (requests_satisfied); for (iter = requests_satisfied; iter != NULL; iter = iter->next) { tp_channel_manager_emit_request_failed (fac, iter->data, error->domain, error->code, error->message); } g_slist_free (requests_satisfied); } g_hash_table_remove (priv->text_needed_for_tube, chan); } } static void muc_sub_channel_closed_cb (TpSvcChannel *chan, gpointer user_data) { GabbleMucFactory *fac = GABBLE_MUC_FACTORY (user_data); GabbleMucChannel *muc; tp_channel_manager_emit_channel_closed_for_object (fac, TP_EXPORTABLE_CHANNEL (chan)); /* GabbleTubeDBus, GabbleTubeStream, and GabbleMucCallChannel all * have "muc" properties. */ g_object_get (chan, "muc", &muc, NULL); if (muc == NULL) return; if (gabble_muc_channel_can_be_closed (muc) && gabble_muc_channel_get_autoclose (muc)) tp_base_channel_close (TP_BASE_CHANNEL (muc)); } #ifdef ENABLE_VOIP static void muc_channel_new_call (GabbleMucChannel *muc, GabbleCallMucChannel *call, GSList *requests, gpointer user_data) { GabbleMucFactory *fac = GABBLE_MUC_FACTORY (user_data); DEBUG ("Emitting new Call channel"); tp_channel_manager_emit_new_channel (fac, TP_EXPORTABLE_CHANNEL (call), requests); g_signal_connect (call, "closed", G_CALLBACK (muc_sub_channel_closed_cb), fac); } #endif static void muc_channel_new_tube (GabbleMucChannel *channel, GabbleTubeIface *tube, gpointer user_data) { GabbleMucFactory *fac = GABBLE_MUC_FACTORY (user_data); /* If the muc channel is ready announce the tube channel right away * otherwise wait for the text channel to be ready */ if (_gabble_muc_channel_is_ready (channel)) tp_channel_manager_emit_new_channel (fac, TP_EXPORTABLE_CHANNEL (tube), NULL); else gabble_muc_factory_associate_tube (fac, channel, tube); g_signal_connect (tube, "closed", G_CALLBACK (muc_sub_channel_closed_cb), fac); } /** * new_muc_channel */ static GabbleMucChannel * new_muc_channel (GabbleMucFactory *fac, TpHandle handle, gboolean invited, TpHandle inviter, const gchar *message, gboolean requested, gboolean initially_register, GHashTable *initial_channels, GArray *initial_handles, char **initial_ids, const char *room_name) { GabbleMucFactoryPrivate *priv = fac->priv; TpBaseConnection *conn = (TpBaseConnection *) priv->conn; GabbleMucChannel *chan; char *object_path; GPtrArray *initial_channels_array = NULL; g_assert (gabble_muc_factory_find_text_channel (fac, handle) == NULL); object_path = g_strdup_printf ("%s/MucChannel%u", tp_base_connection_get_object_path (conn), handle); initial_channels_array = g_ptr_array_new (); if (initial_channels != NULL) { GHashTableIter iter; gpointer key; g_hash_table_iter_init (&iter, initial_channels); while (g_hash_table_iter_next (&iter, &key, NULL)) { g_ptr_array_add (initial_channels_array, key); } } if (initial_handles != NULL) g_array_ref (initial_handles); else initial_handles = g_array_new (FALSE, TRUE, sizeof (TpHandle)); DEBUG ("creating new chan, object path %s", object_path); chan = g_object_new (GABBLE_TYPE_MUC_CHANNEL, "connection", priv->conn, "object-path", object_path, "handle", handle, "invited", invited, "initiator-handle", invited ? inviter : tp_base_connection_get_self_handle (conn), "invitation-message", message, "requested", requested, "initial-channels", initial_channels_array, "initial-invitee-handles", initial_handles, "initial-invitee-ids", initial_ids, "room-name", room_name, "initially-register", initially_register, NULL); g_signal_connect (chan, "closed", (GCallback) muc_channel_closed_cb, fac); g_signal_connect (chan, "new-tube", (GCallback) muc_channel_new_tube, fac); #ifdef ENABLE_VOIP g_signal_connect (chan, "new-call", (GCallback) muc_channel_new_call, fac); #endif g_hash_table_insert (priv->text_channels, GUINT_TO_POINTER (handle), chan); g_free (object_path); g_ptr_array_unref (initial_channels_array); g_array_unref (initial_handles); if (_gabble_muc_channel_is_ready (chan)) muc_ready_cb (chan, fac); else g_signal_connect (chan, "ready", G_CALLBACK (muc_ready_cb), fac); g_signal_connect (chan, "join-error", G_CALLBACK (muc_join_error_cb), fac); return chan; } static void do_invite (GabbleMucFactory *fac, const gchar *room, TpHandle inviter_handle, const gchar *reason) { GabbleMucFactoryPrivate *priv = fac->priv; TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_ROOM); TpHandle room_handle; room_handle = tp_handle_ensure (room_repo, room, NULL, NULL); if (room_handle == 0) { DEBUG ("got a MUC invitation message with invalid room JID \"%s\"; " "ignoring", room); return; } if (gabble_muc_factory_find_text_channel (fac, room_handle) == NULL) { new_muc_channel (fac, room_handle, TRUE, inviter_handle, reason, FALSE, TRUE, NULL, NULL, NULL, NULL); } else { DEBUG ("ignoring invite to room \"%s\"; we're already there", room); } } struct DiscoInviteData { GabbleMucFactory *factory; gchar *reason; TpHandle inviter; }; /** * obsolete_invite_disco_cb: * * Callback for disco request we fired upon encountering obsolete disco. * If the object is in fact MUC room, create a channel for it. */ static void obsolete_invite_disco_cb (GabbleDisco *self, GabbleDiscoRequest *request, const gchar *jid, const gchar *node, WockyNode *query_result, GError* error, gpointer user_data) { struct DiscoInviteData *data = (struct DiscoInviteData *) user_data; GabbleMucFactory *fac = GABBLE_MUC_FACTORY (data->factory); GabbleMucFactoryPrivate *priv = fac->priv; WockyNode *identity; const char *category = NULL, *type = NULL; g_hash_table_remove (priv->disco_requests, request); if (error != NULL) { DEBUG ("ignoring obsolete invite to room '%s'; got disco error: %s", jid, error->message); goto out; } identity = wocky_node_get_child (query_result, "identity"); if (identity != NULL) { category = wocky_node_get_attribute (identity, "category"); type = wocky_node_get_attribute (identity, "type"); } if (tp_strdiff (category, "conference") || tp_strdiff (type, "text")) { DEBUG ("obsolete invite request specified inappropriate jid '%s' " "(not a text conference); ignoring request", jid); goto out; } /* OK, it's MUC after all, create a new channel */ do_invite (fac, jid, data->inviter, data->reason); out: g_free (data->reason); g_slice_free (struct DiscoInviteData, data); } static gboolean process_muc_invite (GabbleMucFactory *fac, WockyStanza *message, const gchar *from, TpChannelTextSendError send_error) { GabbleMucFactoryPrivate *priv = fac->priv; TpBaseConnection *conn = (TpBaseConnection *) priv->conn; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT); WockyNode *x_node, *invite_node, *reason_node; const gchar *invite_from, *reason = NULL; TpHandle inviter_handle; gchar *room; /* does it have a muc subnode? */ x_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (message), "x", NS_MUC_USER); if (x_node == NULL) return FALSE; /* and an invitation? */ invite_node = wocky_node_get_child (x_node, "invite"); if (invite_node == NULL) return FALSE; /* FIXME: do something with these? */ if (send_error != GABBLE_TEXT_CHANNEL_SEND_NO_ERROR) { STANZA_DEBUG (message, "got a MUC invitation message with a send " "error; ignoring"); return TRUE; } invite_from = wocky_node_get_attribute (invite_node, "from"); if (invite_from == NULL) { STANZA_DEBUG (message, "got a MUC invitation message with no JID; " "ignoring"); return TRUE; } inviter_handle = tp_handle_ensure (contact_repo, invite_from, NULL, NULL); if (inviter_handle == 0) { STANZA_DEBUG (message, "got a MUC invitation message with invalid " "inviter JID; ignoring"); return TRUE; } reason_node = wocky_node_get_child (invite_node, "reason"); if (reason_node != NULL) reason = reason_node->content; /* create the channel */ room = gabble_remove_resource (from); do_invite (fac, room, inviter_handle, reason); g_free (room); return TRUE; } static gboolean process_obsolete_invite (GabbleMucFactory *fac, WockyStanza *message, const gchar *from, const gchar *body, TpChannelTextSendError send_error) { GabbleMucFactoryPrivate *priv = fac->priv; TpBaseConnection *conn = (TpBaseConnection *) priv->conn; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT); WockyNode *x_node; const gchar *room; TpHandle inviter_handle; GabbleDiscoRequest *request; struct DiscoInviteData *disco_udata; /* check for obsolete invite method */ x_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (message), "x", NS_X_CONFERENCE); if (x_node == NULL) return FALSE; /* this can only happen if the user sent an obsolete invite with another * client or something */ if (send_error != GABBLE_TEXT_CHANNEL_SEND_NO_ERROR) { STANZA_DEBUG (message, "got an obsolete MUC invitation message with " "a send error; ignoring"); return TRUE; } /* the room JID is in x */ room = wocky_node_get_attribute (x_node, "jid"); if (room == NULL) { STANZA_DEBUG (message, "got a obsolete MUC invitation with no room JID; ignoring"); return TRUE; } /* the inviter JID is in "from" */ inviter_handle = tp_handle_ensure (contact_repo, from, NULL, NULL); if (inviter_handle == 0) { STANZA_DEBUG (message, "got an obsolete MUC invitation message from " "an invalid JID; ignoring"); return TRUE; } disco_udata = g_slice_new0 (struct DiscoInviteData); disco_udata->factory = fac; disco_udata->reason = g_strdup (body); disco_udata->inviter = inviter_handle; DEBUG ("received obsolete MUC invite from handle %u (%s), discoing room %s", inviter_handle, from, room); request = gabble_disco_request (priv->conn->disco, GABBLE_DISCO_TYPE_INFO, room, NULL, obsolete_invite_disco_cb, disco_udata, G_OBJECT (fac), NULL); if (request != NULL) { g_hash_table_insert (priv->disco_requests, request, NULL); } else { DEBUG ("obsolete MUC invite disco failed, freeing info"); g_free (disco_udata->reason); g_slice_free (struct DiscoInviteData, disco_udata); } return TRUE; } /** * muc_factory_message_cb: * * Called by Wocky when we get an incoming . * We filter only groupchat and MUC messages, ignoring the rest. */ static gboolean muc_factory_message_cb ( WockyPorter *porter, WockyStanza *message, gpointer user_data) { GabbleMucFactory *fac = GABBLE_MUC_FACTORY (user_data); GabbleMucFactoryPrivate *priv = fac->priv; const gchar *from, *body, *id; time_t stamp; TpChannelTextMessageType msgtype; gint state; TpChannelTextSendError send_error; TpDeliveryStatus delivery_status; if (!gabble_message_util_parse_incoming_message (message, &from, &stamp, &msgtype, &id, &body, &state, &send_error, &delivery_status)) return TRUE; if (conn_olpc_process_activity_properties_message (priv->conn, message, from)) return TRUE; if (conn_olpc_process_activity_uninvite_message (priv->conn, message, from)) return TRUE; if (process_muc_invite (fac, message, from, send_error)) return TRUE; if (process_obsolete_invite (fac, message, from, body, send_error)) return TRUE; /* we used to check if a room with the jid exists, instead at this * * point we stop caring: actual MUC messages are handled internally * * by the wocky muc implementation */ return FALSE; } void gabble_muc_factory_broadcast_presence (GabbleMucFactory *self) { GabbleMucFactoryPrivate *priv = self->priv; GHashTableIter iter; gpointer channel = NULL; if (priv->text_channels == NULL) return; g_hash_table_iter_init (&iter, priv->text_channels); while (g_hash_table_iter_next (&iter, NULL, &channel)) { g_assert (GABBLE_IS_MUC_CHANNEL (channel)); gabble_muc_channel_send_presence (GABBLE_MUC_CHANNEL (channel)); } } static void gabble_muc_factory_associate_tube (GabbleMucFactory *self, GabbleMucChannel *gmuc, GabbleTubeIface *tube) { GabbleMucFactoryPrivate *priv = self->priv; GQueue *queue; queue = g_hash_table_lookup (priv->text_needed_for_tube, gmuc); if (queue == NULL) { queue = g_queue_new (); g_hash_table_insert (priv->text_needed_for_tube, gmuc, queue); } g_queue_push_tail (queue, tube); } static void gabble_muc_factory_associate_request (GabbleMucFactory *self, gpointer channel, gpointer request) { GabbleMucFactoryPrivate *priv = self->priv; GSList *list = g_hash_table_lookup (priv->queued_requests, channel); g_assert (TP_IS_EXPORTABLE_CHANNEL (channel)); g_hash_table_steal (priv->queued_requests, channel); list = g_slist_prepend (list, request); g_hash_table_insert (priv->queued_requests, channel, list); } static void cancel_queued_requests ( GabbleMucFactory *self, GSList *requests_satisfied) { GSList *iter; requests_satisfied = g_slist_reverse (requests_satisfied); for (iter = requests_satisfied; iter != NULL; iter = iter->next) { tp_channel_manager_emit_request_failed (self, iter->data, TP_ERROR, TP_ERROR_DISCONNECTED, "Unable to complete this channel request, we're disconnecting!"); } g_slist_free (requests_satisfied); } static void gabble_muc_factory_close_all (GabbleMucFactory *self) { GabbleMucFactoryPrivate *priv = self->priv; DEBUG ("closing channels"); if (priv->status_changed_id != 0) { g_signal_handler_disconnect (priv->conn, priv->status_changed_id); priv->status_changed_id = 0; } if (priv->queued_requests != NULL) { GHashTableIter iter; gpointer value; g_hash_table_iter_init (&iter, priv->queued_requests); while (g_hash_table_iter_next (&iter, NULL, &value)) { cancel_queued_requests (self, value); g_hash_table_iter_steal (&iter); } } tp_clear_pointer (&priv->queued_requests, g_hash_table_unref); tp_clear_pointer (&priv->text_needed_for_tube, g_hash_table_unref); /* Use a temporary variable because we don't want * muc_channel_closed_cb remove the channel from the hash table a * second time */ if (priv->text_channels != NULL) { GHashTable *tmp = priv->text_channels; GHashTableIter iter; gpointer chan; priv->text_channels = NULL; g_hash_table_iter_init (&iter, tmp); while (g_hash_table_iter_next (&iter, NULL, &chan)) gabble_muc_channel_teardown (GABBLE_MUC_CHANNEL (chan)); g_hash_table_unref (tmp); } if (priv->message_cb_id != 0) { WockyPorter *porter = gabble_connection_dup_porter (priv->conn); wocky_porter_unregister_handler (porter, priv->message_cb_id); priv->message_cb_id = 0; g_object_unref (porter); } } static void porter_available_cb ( GabbleConnection *conn, WockyPorter *porter, gpointer user_data) { GabbleMucFactory *self = GABBLE_MUC_FACTORY (user_data); self->priv->message_cb_id = wocky_porter_register_handler_from_anyone (porter, WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, muc_factory_message_cb, self, NULL); } static void connection_status_changed_cb (GabbleConnection *conn, guint status, guint reason, GabbleMucFactory *self) { switch (status) { case TP_CONNECTION_STATUS_DISCONNECTED: gabble_muc_factory_close_all (self); break; } } static GObject * gabble_muc_factory_constructor (GType type, guint n_props, GObjectConstructParam *props) { GObject *obj = G_OBJECT_CLASS (gabble_muc_factory_parent_class)-> constructor (type, n_props, props); GabbleMucFactory *self = GABBLE_MUC_FACTORY (obj); GabbleMucFactoryPrivate *priv = self->priv; priv->status_changed_id = g_signal_connect (priv->conn, "status-changed", (GCallback) connection_status_changed_cb, obj); tp_g_signal_connect_object (priv->conn, "porter-available", (GCallback) porter_available_cb, obj, 0); return obj; } static void gabble_muc_factory_foreach_channel (TpChannelManager *manager, TpExportableChannelFunc foreach, gpointer user_data) { GabbleMucFactory *fac = GABBLE_MUC_FACTORY (manager); GabbleMucFactoryPrivate *priv = fac->priv; GHashTableIter iter; gpointer value; g_hash_table_iter_init (&iter, priv->text_channels); while (g_hash_table_iter_next (&iter, NULL, &value)) { GabbleMucChannel *gmuc = GABBLE_MUC_CHANNEL (value); foreach (TP_EXPORTABLE_CHANNEL (gmuc), user_data); gabble_muc_channel_foreach_tubes (gmuc, foreach, user_data); #ifdef ENABLE_VOIP g_list_foreach (gabble_muc_channel_get_call_channels (gmuc), (GFunc) foreach, user_data); #endif } } /** * ensure_muc_channel: * * Create a MUC channel in response to RequestChannel. * * Return TRUE if it already existed, or return FALSE * if it needed to be created (so isn't ready yet). */ static gboolean ensure_muc_channel (GabbleMucFactory *fac, GabbleMucFactoryPrivate *priv, TpHandle handle, GabbleMucChannel **ret, gboolean requested, gboolean export_text, GHashTable *initial_channels, GArray *initial_handles, char **initial_ids, const char *room_name) { TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn; *ret = gabble_muc_factory_find_text_channel (fac, handle); if (*ret == NULL) { *ret = new_muc_channel (fac, handle, FALSE, tp_base_connection_get_self_handle (base_conn), NULL, requested, export_text, initial_channels, initial_handles, initial_ids, room_name); gabble_muc_channel_set_autoclose (*ret, !export_text); } else { if (export_text) gabble_muc_channel_set_autoclose (*ret, FALSE); } if (_gabble_muc_channel_is_ready (*ret)) return TRUE; else return FALSE; } void gabble_muc_factory_handle_si_stream_request (GabbleMucFactory *self, GabbleBytestreamIface *bytestream, TpHandle room_handle, const gchar *stream_id, WockyStanza *msg) { GabbleMucFactoryPrivate *priv = self->priv; TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_ROOM); GabbleMucChannel *gmuc = NULL; WockyStanzaType stanza_type; WockyStanzaSubType sub_type; g_return_if_fail (tp_handle_is_valid (room_repo, room_handle, NULL)); wocky_stanza_get_type_info (msg, &stanza_type, &sub_type); g_return_if_fail (stanza_type == WOCKY_STANZA_TYPE_IQ); g_return_if_fail (sub_type == WOCKY_STANZA_SUB_TYPE_SET); gmuc = gabble_muc_factory_find_text_channel (self, room_handle); if (gmuc == NULL) { GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, "No MUC channel available" }; DEBUG ("MUC channel doesn't exist handle %d", room_handle); gabble_bytestream_iface_close (bytestream, &e); return; } gabble_muc_channel_handle_si_stream_request ( gmuc, bytestream, stream_id, msg); } GabbleMucChannel * gabble_muc_factory_find_text_channel (GabbleMucFactory *self, TpHandle handle) { GabbleMucFactoryPrivate *priv = self->priv; return g_hash_table_lookup (priv->text_channels, GUINT_TO_POINTER (handle)); } static const gchar * const muc_channel_fixed_properties[] = { TP_PROP_CHANNEL_CHANNEL_TYPE, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL }; static const gchar * const * muc_tubes_channel_fixed_properties = muc_channel_fixed_properties; static const gchar * const muc_channel_allowed_properties[] = { TP_PROP_CHANNEL_TARGET_HANDLE, TP_PROP_CHANNEL_TARGET_ID, TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_CHANNELS, TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_INVITEE_HANDLES, TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_INVITEE_IDS, TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INVITATION_MESSAGE, TP_PROP_CHANNEL_INTERFACE_ROOM_ROOM_NAME, TP_PROP_CHANNEL_INTERFACE_ROOM_SERVER, NULL }; static void gabble_muc_factory_type_foreach_channel_class (GType type, TpChannelManagerTypeChannelClassFunc func, gpointer user_data) { GHashTable *table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free); GValue *channel_type_value, *handle_type_value; channel_type_value = tp_g_value_slice_new (G_TYPE_STRING); /* no string value yet - we'll change it for each channel class */ g_hash_table_insert (table, TP_PROP_CHANNEL_CHANNEL_TYPE, channel_type_value); handle_type_value = tp_g_value_slice_new (G_TYPE_UINT); g_value_set_uint (handle_type_value, TP_HANDLE_TYPE_ROOM); g_hash_table_insert (table, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, handle_type_value); /* Channel.Type.Text */ g_value_set_static_string (channel_type_value, TP_IFACE_CHANNEL_TYPE_TEXT); func (type, table, muc_channel_allowed_properties, user_data); /* Muc Channel.Type.StreamTube */ g_value_set_static_string (channel_type_value, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE); func (type, table, gabble_tube_stream_channel_get_allowed_properties (), user_data); /* Muc Channel.Type.DBusTube */ g_value_set_static_string (channel_type_value, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE); func (type, table, gabble_tube_dbus_channel_get_allowed_properties (), user_data); #ifdef ENABLE_VOIP /* Muc Channel.Type.Call */ g_value_set_static_string (channel_type_value, TP_IFACE_CHANNEL_TYPE_CALL); func (type, table, gabble_media_factory_call_channel_allowed_properties (), user_data); #endif g_hash_table_unref (table); } static gboolean handle_text_channel_request (GabbleMucFactory *self, gpointer request_token, GHashTable *request_properties, gboolean require_new, TpHandle room, GError **error) { GabbleMucFactoryPrivate *priv = self->priv; TpBaseConnection *conn = TP_BASE_CONNECTION (priv->conn); GabbleMucChannel *text_chan; TpHandleSet *handles; TpIntset *continue_handles; guint i; gboolean ret = TRUE; TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT); TpHandleRepoIface *room_handles = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_ROOM); GPtrArray *initial_channels; GHashTable *final_channels; /* used as a set: (char *) -> NULL */ GArray *initial_handles, *final_handles; char **initial_ids, **final_ids; const char *invite_msg; const gchar *room_name, *server_prop; if (tp_channel_manager_asv_has_unknown_properties (request_properties, muc_channel_fixed_properties, muc_channel_allowed_properties, error)) return FALSE; initial_channels = tp_asv_get_boxed (request_properties, TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_CHANNELS, TP_ARRAY_TYPE_OBJECT_PATH_LIST); initial_handles = tp_asv_get_boxed (request_properties, TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_INVITEE_HANDLES, DBUS_TYPE_G_UINT_ARRAY); initial_ids = tp_asv_get_boxed (request_properties, TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_INVITEE_IDS, G_TYPE_STRV); invite_msg = tp_asv_get_string (request_properties, TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INVITATION_MESSAGE); room_name = tp_asv_get_string (request_properties, TP_PROP_CHANNEL_INTERFACE_ROOM_ROOM_NAME); server_prop = tp_asv_get_string (request_properties, TP_PROP_CHANNEL_INTERFACE_ROOM_SERVER); handles = tp_handle_set_new (contact_handles); continue_handles = tp_intset_new (); final_channels = g_hash_table_new (g_str_hash, g_str_equal); /* look at the list of initial channels, build a set of handles to invite */ if (initial_channels != NULL) { TpDBusDaemon *dbus_daemon = tp_base_connection_get_dbus_daemon (conn); DBusGConnection *bus = tp_proxy_get_dbus_connection (dbus_daemon); for (i = 0; i < initial_channels->len; i++) { const char *object_path = g_ptr_array_index (initial_channels, i); GObject *object; TpHandle handle; TpBaseConnection *connection; object = dbus_g_connection_lookup_g_object (bus, object_path); if (!GABBLE_IS_IM_CHANNEL (object)) { DEBUG ("Channel %s is not an ImChannel, ignoring", object_path); continue; } connection = tp_base_channel_get_connection ( TP_BASE_CHANNEL (object)); if ((GabbleConnection *) connection != priv->conn) { DEBUG ("Channel %s is from a different Connection, ignoring", object_path); continue; } handle = tp_base_channel_get_target_handle ( TP_BASE_CHANNEL (object)); tp_handle_set_add (handles, handle); tp_intset_add (continue_handles, handle); g_hash_table_insert (final_channels, (char *) object_path, NULL); } } /* look at the list of initial handles, add these to the handles set */ if (initial_handles != NULL) { for (i = 0; i < initial_handles->len; i++) { TpHandle handle = g_array_index (initial_handles, TpHandle, i); if (tp_handle_inspect (contact_handles, handle) == NULL) { DEBUG ("Bad Handle %u, ignoring", handle); continue; } tp_handle_set_add (handles, handle); } } /* look at the list of initial ids, add these to the handles set */ if (initial_ids != NULL) { char **ptr; for (ptr = initial_ids; *ptr != NULL; ptr++) { char *id = *ptr; TpHandle handle = tp_handle_ensure (contact_handles, id, NULL, NULL); if (handle == 0) { DEBUG ("Bad ID '%s', ignoring", id); continue; } tp_handle_set_add (handles, handle); } } /* build new InitialInviteeHandles and InitialInviteeIDs */ /* FIXME: include Self Handle to comply with spec ? */ final_handles = tp_handle_set_to_array (handles); final_ids = g_new0 (char *, final_handles->len + 1); for (i = 0; i < final_handles->len; i++) { TpHandle handle = g_array_index (final_handles, TpHandle, i); const char *id = tp_handle_inspect (contact_handles, handle); final_ids[i] = (char *) id; } /* TargetHandleType=None and TargetHandle=0 */ if (room == 0) { char *uuid, *id, *server = ""; gchar *tmp = NULL; /* There's no super obvious way to tell.. you can't invite GMail users to * a non-Google MUC (it just doesn't work), and if your own account is on * a Google server, you may as well use a Google PMUC. If one of your * initial contacts is using GMail, you should also use a Google PMUC */ for (i = 0; i < final_handles->len; i++) { TpHandle handle = g_array_index (final_handles, TpHandle, i); GabblePresence *presence; presence = gabble_presence_cache_get (priv->conn->presence_cache, handle); if (presence != NULL && gabble_presence_has_cap (presence, QUIRK_GOOGLE_WEBMAIL_CLIENT)) { DEBUG ("Initial invitee includes Google Webmail client"); server = "@groupchat.google.com"; break; } } if (server_prop != NULL) { tmp = g_strdup_printf ("@%s", server_prop); server = tmp; } if (room_name != NULL && room_name[0] != '\0') { id = g_strdup_printf ("%s%s", room_name, server); } else { uuid = gabble_generate_id (); id = g_strdup_printf ("private-chat-%s%s", uuid, server); g_free (uuid); DEBUG ("Creating PMUC '%s'", id); } room = tp_handle_ensure (room_handles, id, NULL, error); g_free (id); g_free (tmp); if (room == 0) { ret = FALSE; goto out; } } /* Make sure TargetID and RoomName don't conflict. */ if (room_name != NULL && room_name[0] != '\0') { const gchar *target_id = tp_handle_inspect (room_handles, room); gchar *target_room = NULL; gboolean ok; /* JIDs that are handles must already be valid. */ ok = wocky_decode_jid (target_id, &target_room, NULL, NULL); g_assert (ok); ok = !tp_strdiff (target_room, room_name); if (!ok) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "TargetID's node part (%s) doesn't match RoomName (%s)", target_room, room_name); ret = FALSE; } g_free (target_room); if (!ok) goto out; } /* Make sure TargetID and Server don't conflict. */ if (server_prop != NULL) { const gchar *target_id = tp_handle_inspect (room_handles, room); gchar *target_server = NULL; gboolean ok = TRUE; /* JIDs that are handles must already be valid. */ ok = wocky_decode_jid (target_id, NULL, &target_server, NULL); g_assert (ok); if (target_server != NULL) ok = !tp_strdiff (target_server, server_prop); else ok = TRUE; if (!ok) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "TargetID's domain part (%s) doesn't match Server (%s)", target_server, server_prop); ret = FALSE; } g_free (target_server); if (!ok) goto out; } if (ensure_muc_channel (self, priv, room, &text_chan, TRUE, TRUE, final_channels, final_handles, final_ids, room_name)) { /* channel exists */ if (require_new && tp_base_channel_is_registered (TP_BASE_CHANNEL (text_chan))) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "That channel has already been created (or requested)"); ret = FALSE; } else { if (initial_channels != NULL || initial_handles != NULL || initial_ids != NULL) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Cannot set InitialChannels, InitialInviteeHandles or " "InitialInviteIDs for existing channel"); ret = FALSE; } else { if (tp_base_channel_is_registered (TP_BASE_CHANNEL (text_chan))) { tp_channel_manager_emit_request_already_satisfied (self, request_token, TP_EXPORTABLE_CHANNEL (text_chan)); } else { GSList *tokens; tp_base_channel_register (TP_BASE_CHANNEL (text_chan)); tokens = g_slist_append (NULL, request_token); tp_channel_manager_emit_new_channel (self, TP_EXPORTABLE_CHANNEL (text_chan), tokens); g_slist_free (tokens); } ret = TRUE; } } goto out; } else { gabble_muc_factory_associate_request (self, text_chan, request_token); } /* invite all of the invitees to this new MUC */ /* members included in an InitialChannel will want the node set */ for (i = 0; i < final_handles->len; i++) { TpHandle handle = g_array_index (final_handles, TpHandle, i); char *id = final_ids[i]; GError *error2 = NULL; gboolean continue_; continue_ = tp_intset_is_member (continue_handles, handle); /* N.B. contrary to what Google's own spec implies, an invite message * will not be handled correctly by the GMail client. We're going to * have to strip it out of invites to GMail clients */ gabble_muc_channel_send_invite (text_chan, id, invite_msg, continue_, &error2); if (error2 != NULL) { DEBUG ("%s", error2->message); g_error_free (error2); continue; } } out: g_hash_table_unref (final_channels); g_array_unref (final_handles); g_free (final_ids); tp_handle_set_destroy (handles); tp_intset_destroy (continue_handles); return ret; } static gboolean handle_tube_channel_request (GabbleMucFactory *self, gpointer request_token, GHashTable *request_properties, gboolean require_new, TpHandle handle, GError **error) { GabbleMucFactoryPrivate *priv = self->priv; gboolean can_announce_now; GabbleMucChannel * gmuc; GabbleTubeIface *new_channel; gmuc = gabble_muc_factory_find_text_channel (self, handle); if (gmuc == NULL) ensure_muc_channel (self, priv, handle, &gmuc, FALSE, FALSE, NULL, NULL, NULL, NULL); can_announce_now = _gabble_muc_channel_is_ready (gmuc); new_channel = gabble_muc_channel_tube_request (gmuc, request_token, request_properties, TRUE); g_signal_connect (new_channel, "closed", G_CALLBACK (muc_sub_channel_closed_cb), self); if (can_announce_now) { GSList *request_tokens; request_tokens = g_slist_prepend (NULL, request_token); tp_channel_manager_emit_new_channel (self, TP_EXPORTABLE_CHANNEL (new_channel), request_tokens); g_slist_free (request_tokens); } else { gabble_muc_factory_associate_tube (self, gmuc, new_channel); /* And now finally associate the new stream or dbus tube channel with * the request token so that when the muc channel is ready, the request * will be satisfied. */ gabble_muc_factory_associate_request (self, new_channel, request_token); } return TRUE; } static gboolean handle_stream_tube_channel_request (GabbleMucFactory *self, gpointer request_token, GHashTable *request_properties, gboolean require_new, TpHandle handle, GError **error) { const gchar *service; if (tp_channel_manager_asv_has_unknown_properties (request_properties, muc_tubes_channel_fixed_properties, gabble_tube_stream_channel_get_allowed_properties (), error)) return FALSE; /* "Service" is a mandatory, not-fixed property */ service = tp_asv_get_string (request_properties, TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE); if (service == NULL) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "Request does not contain the mandatory property '%s'", TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE); return FALSE; } return handle_tube_channel_request (self, request_token, request_properties, require_new, handle, error); } static gboolean handle_dbus_tube_channel_request (GabbleMucFactory *self, gpointer request_token, GHashTable *request_properties, gboolean require_new, TpHandle handle, GError **error) { const gchar *service; if (tp_channel_manager_asv_has_unknown_properties (request_properties, muc_tubes_channel_fixed_properties, gabble_tube_dbus_channel_get_allowed_properties (), error)) return FALSE; /* "ServiceName" is a mandatory, not-fixed property */ service = tp_asv_get_string (request_properties, TP_PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME); if (service == NULL) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "Request does not contain the mandatory property '%s'", TP_PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME); return FALSE; } return handle_tube_channel_request (self, request_token, request_properties, require_new, handle, error); } #ifdef ENABLE_VOIP static void call_muc_channel_request_cb (GObject *source, GAsyncResult *result, gpointer user_data) { Request *r = user_data; GabbleMucFactory *self = GABBLE_MUC_FACTORY (r->self); GabbleMucChannel *channel = GABBLE_MUC_CHANNEL (source); gpointer request_token = r->token; GError *error = NULL; if (!gabble_muc_channel_request_call_finish (channel, result, &error)) { tp_channel_manager_emit_request_failed (self, request_token, error->domain, error->code, error->message); g_error_free (error); } /* No need to handle a successful request, this is handled when the muc * signals a new call channel automagically */ g_object_unref (r->self); g_slice_free (Request, r); } static gboolean handle_call_channel_request (GabbleMucFactory *self, gpointer request_token, GHashTable *request_properties, gboolean require_new, TpHandle handle, GError **error) { GabbleMucFactoryPrivate *priv = self->priv; gboolean initial_audio, initial_video; GabbleMucChannel *muc; GabbleCallMucChannel *call; Request *r; if (tp_channel_manager_asv_has_unknown_properties (request_properties, muc_channel_fixed_properties, gabble_media_factory_call_channel_allowed_properties (), error)) return FALSE; initial_audio = tp_asv_get_boolean (request_properties, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, NULL); initial_video = tp_asv_get_boolean (request_properties, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, NULL); if (!initial_audio && !initial_video) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "Request didn't set either InitialAudio or InitialVideo"); return FALSE; } ensure_muc_channel (self, priv, handle, &muc, FALSE, FALSE, NULL, NULL, NULL, NULL); call = gabble_muc_channel_get_call (muc); if (call != NULL) { if (require_new) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "There is already a call in this muc"); goto error; } else { tp_channel_manager_emit_request_already_satisfied (self, request_token, TP_EXPORTABLE_CHANNEL (call)); goto out; } } /* FIXME not coping properly with deinitialisation */ r = g_slice_new (Request); r->self = g_object_ref (self); r->token = request_token; gabble_muc_channel_request_call (muc, request_properties, require_new, request_token, call_muc_channel_request_cb, r); out: return TRUE; error: return FALSE; } #endif typedef gboolean (*ChannelTypeHandlerFunc) ( GabbleMucFactory *self, gpointer request_token, GHashTable *request_properties, gboolean require_new, TpHandle room, GError **error); typedef struct { const gchar *channel_type; ChannelTypeHandlerFunc f; } ChannelTypeHandler; static ChannelTypeHandler channel_type_handlers[] = { { TP_IFACE_CHANNEL_TYPE_TEXT, handle_text_channel_request }, { TP_IFACE_CHANNEL_TYPE_STREAM_TUBE, handle_stream_tube_channel_request }, { TP_IFACE_CHANNEL_TYPE_DBUS_TUBE, handle_dbus_tube_channel_request }, #ifdef ENABLE_VOIP { TP_IFACE_CHANNEL_TYPE_CALL, handle_call_channel_request }, #endif { NULL } }; static gboolean gabble_muc_factory_request (GabbleMucFactory *self, gpointer request_token, GHashTable *request_properties, gboolean require_new) { GError *error = NULL; TpHandleType handle_type; TpHandle handle; gboolean conference, room; const gchar *channel_type; ChannelTypeHandler *h; handle_type = tp_asv_get_uint32 (request_properties, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL); channel_type = tp_asv_get_string (request_properties, TP_PROP_CHANNEL_CHANNEL_TYPE); /* Conference channels can be anonymous (HandleTypeNone) */ conference = (handle_type == TP_HANDLE_TYPE_NONE && !tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TEXT) && (g_hash_table_lookup (request_properties, TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_CHANNELS) || g_hash_table_lookup (request_properties, TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_INVITEE_HANDLES) || g_hash_table_lookup (request_properties, TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_INVITEE_IDS))); room = (handle_type == TP_HANDLE_TYPE_NONE && !tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TEXT) && g_hash_table_lookup (request_properties, TP_PROP_CHANNEL_INTERFACE_ROOM_ROOM_NAME)); /* the channel must either be a room, or a new conference */ if (handle_type != TP_HANDLE_TYPE_ROOM && !conference && !room) return FALSE; /* validity already checked by TpBaseConnection */ handle = tp_asv_get_uint32 (request_properties, TP_PROP_CHANNEL_TARGET_HANDLE, NULL); g_assert (conference || room || handle != 0); for (h = channel_type_handlers; h->channel_type != NULL; h++) { if (tp_strdiff (channel_type, h->channel_type)) continue; if (!h->f (self, request_token, request_properties, require_new, handle, &error)) { tp_channel_manager_emit_request_failed (self, request_token, error->domain, error->code, error->message); g_error_free (error); } /* We've handled the request one way or another. */ return TRUE; } return FALSE; } static gboolean gabble_muc_factory_create_channel (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties) { GabbleMucFactory *self = GABBLE_MUC_FACTORY (manager); return gabble_muc_factory_request (self, request_token, request_properties, TRUE); } static gboolean gabble_muc_factory_request_channel (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties) { GabbleMucFactory *self = GABBLE_MUC_FACTORY (manager); return gabble_muc_factory_request (self, request_token, request_properties, FALSE); } static gboolean gabble_muc_factory_ensure_channel (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties) { GabbleMucFactory *self = GABBLE_MUC_FACTORY (manager); return gabble_muc_factory_request (self, request_token, request_properties, FALSE); } #ifdef ENABLE_VOIP gboolean gabble_muc_factory_handle_jingle_session (GabbleMucFactory *self, WockyJingleSession *session) { GabbleMucFactoryPrivate *priv = self->priv; TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_ROOM); TpHandle room; room = gabble_get_room_handle_from_jid (room_repo, wocky_jingle_session_get_peer_jid (session)); if (room != 0) { GabbleMucChannel *channel; channel = gabble_muc_factory_find_text_channel (self, room); g_assert (GABBLE_IS_MUC_CHANNEL (channel)); if (channel != NULL) return gabble_muc_channel_handle_jingle_session (channel, session); } return FALSE; } #endif static void channel_manager_iface_init (gpointer g_iface, gpointer iface_data) { TpChannelManagerIface *iface = g_iface; iface->foreach_channel = gabble_muc_factory_foreach_channel; iface->type_foreach_channel_class = gabble_muc_factory_type_foreach_channel_class; iface->request_channel = gabble_muc_factory_request_channel; iface->create_channel = gabble_muc_factory_create_channel; iface->ensure_channel = gabble_muc_factory_ensure_channel; } telepathy-gabble-0.18.3/src/ft-manager.h0000664000175000017500000000524311720700311021153 0ustar00cassidycassidy00000000000000/* * ft-manager.h - Header for GabbleFtManager * Copyright (C) 2009 Collabora Ltd. * @author: Guillaume Desmottes * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_FT_MANAGER_H__ #define __GABBLE_FT_MANAGER_H__ #include #include "bytestream-iface.h" #include "types.h" #include G_BEGIN_DECLS typedef struct _GabbleFtManager GabbleFtManager; typedef struct _GabbleFtManagerClass GabbleFtManagerClass; typedef struct _GabbleFtManagerPrivate GabbleFtManagerPrivate; struct _GabbleFtManagerClass { GObjectClass parent_class; }; struct _GabbleFtManager { GObject parent; GabbleFtManagerPrivate *priv; }; GType gabble_ft_manager_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_FT_MANAGER \ (gabble_ft_manager_get_type ()) #define GABBLE_FT_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_FT_MANAGER, GabbleFtManager)) #define GABBLE_FT_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_FT_MANAGER, GabbleFtManagerClass)) #define GABBLE_IS_FT_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_FT_MANAGER)) #define GABBLE_IS_FT_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_FT_MANAGER)) #define GABBLE_FT_MANAGER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_FT_MANAGER, GabbleFtManagerClass)) GabbleFtManager *gabble_ft_manager_new (GabbleConnection *connection); void gabble_ft_manager_handle_si_request (GabbleFtManager *self, GabbleBytestreamIface *bytestream, TpHandle handle, const gchar *stream_id, WockyStanza *msg); #ifdef G_OS_UNIX /* Slight encapsulation violation: this function isn't portable, but we * happen to know that it's only needed if we support Unix sockets, and * we only do *that* on Unix. Otherwise, we can leave it undefined. */ const gchar * gabble_ft_manager_get_tmp_dir (GabbleFtManager *self); #endif G_END_DECLS #endif /* #ifndef __GABBLE_FT_MANAGER_H__*/ telepathy-gabble-0.18.3/src/conn-contact-info.h0000664000175000017500000000276212332440117022461 0ustar00cassidycassidy00000000000000/* * conn-contact-info.h - Header for Gabble connection ContactInfo interface * Copyright (C) 2009-2010 Collabora Ltd. * Copyright (C) 2009-2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __CONN_CONTACT_INFO_H__ #define __CONN_CONTACT_INFO_H__ #include "connection.h" G_BEGIN_DECLS void conn_contact_info_class_init (GabbleConnectionClass *klass); void conn_contact_info_init (GabbleConnection *conn); void conn_contact_info_finalize (GabbleConnection *conn); void conn_contact_info_iface_init (gpointer g_iface, gpointer iface_data); extern TpDBusPropertiesMixinPropImpl *conn_contact_info_properties; void conn_contact_info_properties_getter (GObject *object, GQuark interface, GQuark name, GValue *value, gpointer getter_data); G_END_DECLS #endif /* __CONN_CONTACT_INFO_H__ */ telepathy-gabble-0.18.3/src/media-channel.h0000664000175000017500000000527412332441362021633 0ustar00cassidycassidy00000000000000/* * gabble-media-channel.h - Header for GabbleMediaChannel * Copyright (C) 2006 Collabora Ltd. * Copyright (C) 2006 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_MEDIA_CHANNEL_H__ #define __GABBLE_MEDIA_CHANNEL_H__ #include #include #include #include "presence.h" G_BEGIN_DECLS typedef struct _GabbleMediaChannel GabbleMediaChannel; typedef struct _GabbleMediaChannelPrivate GabbleMediaChannelPrivate; typedef struct _GabbleMediaChannelClass GabbleMediaChannelClass; struct _GabbleMediaChannelClass { GObjectClass parent_class; TpGroupMixinClass group_class; TpPropertiesMixinClass properties_class; TpDBusPropertiesMixinClass dbus_props_class; }; struct _GabbleMediaChannel { GObject parent; TpGroupMixin group; TpPropertiesMixin properties; GabbleMediaChannelPrivate *priv; }; GType gabble_media_channel_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_MEDIA_CHANNEL \ (gabble_media_channel_get_type ()) #define GABBLE_MEDIA_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_MEDIA_CHANNEL,\ GabbleMediaChannel)) #define GABBLE_MEDIA_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_MEDIA_CHANNEL,\ GabbleMediaChannelClass)) #define GABBLE_IS_MEDIA_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_MEDIA_CHANNEL)) #define GABBLE_IS_MEDIA_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_MEDIA_CHANNEL)) #define GABBLE_MEDIA_CHANNEL_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_MEDIA_CHANNEL, \ GabbleMediaChannelClass)) void gabble_media_channel_request_initial_streams (GabbleMediaChannel *chan, GFunc succeeded_cb, GFunc failed_cb, gpointer user_data); void gabble_media_channel_close (GabbleMediaChannel *self); G_END_DECLS #endif /* #ifndef __GABBLE_MEDIA_CHANNEL_H__*/ telepathy-gabble-0.18.3/src/connection.h0000664000175000017500000002443512332441362021305 0ustar00cassidycassidy00000000000000/* * gabble-connection.h - Header for GabbleConnection * Copyright © 2005-2012 Collabora Ltd. * Copyright © 2005-2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_CONNECTION_H__ #define __GABBLE_CONNECTION_H__ #include "config.h" #include #include #include #include #include "gabble/capabilities.h" #ifdef ENABLE_FILE_TRANSFER #include "ft-manager.h" #endif #ifdef ENABLE_VOIP #include "jingle-mint.h" #endif #include "muc-factory.h" #include "types.h" #include #include #include G_BEGIN_DECLS #define GABBLE_TYPE_CONNECTION (gabble_connection_get_type ()) #define GABBLE_CONNECTION(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_CONNECTION, GabbleConnection)) #define GABBLE_CONNECTION_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_CONNECTION, \ GabbleConnectionClass)) #define GABBLE_IS_CONNECTION(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_CONNECTION)) #define GABBLE_IS_CONNECTION_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_CONNECTION)) #define GABBLE_CONNECTION_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_CONNECTION, \ GabbleConnectionClass)) typedef struct _GabbleConnectionClass GabbleConnectionClass; GType gabble_connection_get_type (void); void gabble_connection_update_sidecar_capabilities ( GabbleConnection *connection, const GabbleCapabilitySet *add_set, const GabbleCapabilitySet *remove_set); gchar *gabble_connection_add_sidecar_own_caps ( GabblePluginConnection *connection, const GabbleCapabilitySet *cap_set, const GPtrArray *identities) G_GNUC_WARN_UNUSED_RESULT; gchar *gabble_connection_add_sidecar_own_caps_full ( GabblePluginConnection *connection, const GabbleCapabilitySet *cap_set, const GPtrArray *identities, GPtrArray *data_forms) G_GNUC_WARN_UNUSED_RESULT; WockySession *gabble_connection_get_session ( GabblePluginConnection *connection); gchar *gabble_connection_get_full_jid (GabbleConnection *conn); const gchar * gabble_connection_get_jid_for_caps (GabblePluginConnection *conn, WockyXep0115Capabilities *caps); const gchar * gabble_connection_pick_best_resource_for_caps ( GabblePluginConnection *connection, const gchar *jid, GabbleCapabilitySetPredicate predicate, gconstpointer user_data); TpBaseContactList * gabble_connection_get_contact_list ( GabbleConnection *connection); WockyXep0115Capabilities * gabble_connection_get_caps ( GabblePluginConnection *connection, TpHandle handle); /* Default parameters for optional parameters */ #define GABBLE_PARAMS_DEFAULT_HTTPS_PROXY_PORT 443 #define GABBLE_PARAMS_DEFAULT_STUN_PORT 3478 #define GABBLE_PARAMS_DEFAULT_FALLBACK_STUN_SERVER "stun.telepathy.im" #define GABBLE_PARAMS_DEFAULT_SOCKS5_PROXIES { NULL } /* order must match array of statuses in conn-presence.c */ /* in increasing order of presence */ /*< prefix=GABBLE_PRESENCE >*/ typedef enum { GABBLE_PRESENCE_OFFLINE = 0, GABBLE_PRESENCE_UNKNOWN, GABBLE_PRESENCE_ERROR, GABBLE_PRESENCE_LAST_UNAVAILABLE = GABBLE_PRESENCE_ERROR, /*< skip >*/ GABBLE_PRESENCE_HIDDEN, GABBLE_PRESENCE_XA, GABBLE_PRESENCE_AWAY, GABBLE_PRESENCE_DND, GABBLE_PRESENCE_AVAILABLE, GABBLE_PRESENCE_CHAT, NUM_GABBLE_PRESENCES /*< skip >*/ } GabblePresenceId; /*< flags >*/ typedef enum { GABBLE_CONNECTION_FEATURES_NONE = 0, GABBLE_CONNECTION_FEATURES_GOOGLE_JINGLE_INFO = 1 << 0, GABBLE_CONNECTION_FEATURES_GOOGLE_ROSTER = 1 << 1, GABBLE_CONNECTION_FEATURES_PRESENCE_INVISIBLE = 1 << 2, GABBLE_CONNECTION_FEATURES_PRIVACY = 1 << 3, GABBLE_CONNECTION_FEATURES_PEP = 1 << 4, GABBLE_CONNECTION_FEATURES_GOOGLE_MAIL_NOTIFY = 1 << 5, GABBLE_CONNECTION_FEATURES_INVISIBLE = 1 << 6, GABBLE_CONNECTION_FEATURES_GOOGLE_SHARED_STATUS = 1 << 7, GABBLE_CONNECTION_FEATURES_GOOGLE_QUEUE = 1 << 8, GABBLE_CONNECTION_FEATURES_GOOGLE_SETTING = 1 << 9, GABBLE_CONNECTION_FEATURES_WLM_JID_LOOKUP = 1 << 10, } GabbleConnectionFeatures; typedef struct _GabbleConnectionPrivate GabbleConnectionPrivate; typedef struct _GabbleConnectionMailNotificationPrivate GabbleConnectionMailNotificationPrivate; typedef struct _GabbleConnectionPresencePrivate GabbleConnectionPresencePrivate; typedef void (*GabbleConnectionMsgReplyFunc) ( GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg, GObject *object, gpointer user_data); typedef enum { /* The JID could be a "global" JID, or a MUC room member. We'll assume * that it's a global JID (and remove the resource) unless we've seen * that JID in a MUC before. */ GABBLE_JID_ANY = 0, /* The JID is definitely global. Remove the resource. */ GABBLE_JID_GLOBAL, /* The JID is definitely a room member. Assert that there is a "resource" * (nickname) and don't remove it. */ GABBLE_JID_ROOM_MEMBER } GabbleNormalizeContactJIDMode; struct _GabbleConnectionClass { TpBaseConnectionClass parent_class; TpDBusPropertiesMixinClass properties_class; TpPresenceMixinClass presence_class; TpContactsMixinClass contacts_class; }; struct _GabbleConnection { TpBaseConnection parent; TpPresenceMixin presence; TpContactsMixin contacts; /* DBus daemon instance */ TpDBusDaemon *daemon; WockySession *session; /* channel factories borrowed from TpBaseConnection's list */ GabbleRoster *roster; GabbleMucFactory *muc_factory; GabblePrivateTubesFactory *private_tubes_factory; /* DISCO! */ GabbleDisco *disco; /* connection feature flags */ GabbleConnectionFeatures features; /* presence */ GabblePresenceCache *presence_cache; GabblePresence *self_presence; GabbleConnectionPresencePrivate *presence_priv; /* IQ request pipeline helper, so simultaneous requests don't make * servers hate us */ GabbleRequestPipeline *req_pipeline; /* vCard lookup helper */ GabbleVCardManager *vcard_manager; /* OLPC hash tables */ GHashTable *olpc_activities_info; GHashTable *olpc_pep_activities; GHashTable *olpc_invited_activities; GHashTable *olpc_current_act; /* bytestream factory */ GabbleBytestreamFactory *bytestream_factory; /* outstanding avatar requests */ GHashTable *avatar_requests; /* outstanding vcard requests */ GHashTable *vcard_requests; #ifdef ENABLE_VOIP GabbleJingleMint *jingle_mint; #endif #ifdef ENABLE_FILE_TRANSFER /* file transfer manager */ GabbleFtManager *ft_manager; #endif /* PEP */ WockyPepService *pep_nick; WockyPepService *pep_location; WockyPepService *pep_olpc_buddy_props; WockyPepService *pep_olpc_activities; WockyPepService *pep_olpc_current_act; WockyPepService *pep_olpc_act_props; /* Sidecars */ /* gchar *interface → GabbleSidecar */ GHashTable *sidecars; /* gchar *interface → GList */ GHashTable *pending_sidecars; /* Mail Notification */ GabbleConnectionMailNotificationPrivate *mail_priv; /* ContactInfo.SupportedFields, or NULL to use the generic one */ GPtrArray *contact_info_fields; GabbleConnectionPrivate *priv; }; typedef enum { GABBLE_CONNECTION_ALIAS_NONE = 0, GABBLE_CONNECTION_ALIAS_FROM_JID, GABBLE_CONNECTION_ALIAS_FROM_VCARD, GABBLE_CONNECTION_ALIAS_FROM_MUC_RESOURCE, GABBLE_CONNECTION_ALIAS_FROM_CONNMGR, GABBLE_CONNECTION_ALIAS_FROM_PRESENCE, GABBLE_CONNECTION_ALIAS_FROM_ROSTER } GabbleConnectionAliasSource; WockyPorter *gabble_connection_dup_porter (GabbleConnection *conn); gboolean _gabble_connection_set_properties_from_account ( GabbleConnection *conn, const gchar *account, GError **error); gboolean _gabble_connection_send (GabbleConnection *conn, WockyStanza *msg, GError **error); gboolean _gabble_connection_send_with_reply (GabbleConnection *conn, WockyStanza *msg, GabbleConnectionMsgReplyFunc reply_func, GObject *object, gpointer user_data, GError **error); void _gabble_connection_acknowledge_set_iq (GabbleConnection *conn, WockyStanza *iq); void gabble_connection_update_last_use (GabbleConnection *conn); const char *_gabble_connection_find_conference_server (GabbleConnection *); gchar *gabble_connection_get_canonical_room_name (GabbleConnection *conn, const gchar *jid); void gabble_connection_ensure_capabilities (GabbleConnection *self, const GabbleCapabilitySet *ensured); gboolean gabble_connection_send_presence (GabbleConnection *conn, WockyStanzaSubType sub_type, const gchar *contact, const gchar *status, GError **error); gboolean gabble_connection_send_capabilities (GabbleConnection *self, const gchar *recipient, GError **error); gboolean gabble_connection_request_decloak (GabbleConnection *self, const gchar *to, const gchar *reason, GError **error); void gabble_connection_fill_in_caps (GabbleConnection *self, WockyStanza *presence_message); gboolean _gabble_connection_invisible_privacy_list_set_active ( GabbleConnection *self, gboolean active, GError **error); const gchar **gabble_connection_get_implemented_interfaces (void); const gchar **gabble_connection_get_guaranteed_interfaces (void); /* extern only for the benefit of the unit tests */ void _gabble_connection_create_handle_repos (TpBaseConnection *conn, TpHandleRepoIface *repos[NUM_TP_HANDLE_TYPES]); /* For unit tests only */ void gabble_connection_set_disco_reply_timeout (guint timeout); G_END_DECLS #endif /* #ifndef __GABBLE_CONNECTION_H__*/ telepathy-gabble-0.18.3/src/bytestream-ibb.h0000664000175000017500000000465412223562023022055 0ustar00cassidycassidy00000000000000/* * bytestream-ibb.h - Header for GabbleBytestreamIBB * Copyright (C) 2007 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_BYTESTREAM_IBB_H__ #define __GABBLE_BYTESTREAM_IBB_H__ #include #include #include G_BEGIN_DECLS typedef struct _GabbleBytestreamIBB GabbleBytestreamIBB; typedef struct _GabbleBytestreamIBBClass GabbleBytestreamIBBClass; typedef struct _GabbleBytestreamIBBPrivate GabbleBytestreamIBBPrivate; struct _GabbleBytestreamIBBClass { GObjectClass parent_class; }; struct _GabbleBytestreamIBB { GObject parent; GabbleBytestreamIBBPrivate *priv; }; GType gabble_bytestream_ibb_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_BYTESTREAM_IBB \ (gabble_bytestream_ibb_get_type ()) #define GABBLE_BYTESTREAM_IBB(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_BYTESTREAM_IBB,\ GabbleBytestreamIBB)) #define GABBLE_BYTESTREAM_IBB_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_BYTESTREAM_IBB,\ GabbleBytestreamIBBClass)) #define GABBLE_IS_BYTESTREAM_IBB(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_BYTESTREAM_IBB)) #define GABBLE_IS_BYTESTREAM_IBB_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_BYTESTREAM_IBB)) #define GABBLE_BYTESTREAM_IBB_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_BYTESTREAM_IBB,\ GabbleBytestreamIBBClass)) void gabble_bytestream_ibb_receive (GabbleBytestreamIBB *ibb, WockyStanza *msg, gboolean is_iq); void gabble_bytestream_ibb_close_received (GabbleBytestreamIBB *ibb, WockyStanza *iq); G_END_DECLS #endif /* #ifndef __GABBLE_BYTESTREAM_IBB_H__ */ telepathy-gabble-0.18.3/src/call-stream.h0000664000175000017500000000451112223562023021340 0ustar00cassidycassidy00000000000000/* * gabble-call-stream.h - Header for GabbleCallStream * Copyright (C) 2009 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_CALL_STREAM_H__ #define __GABBLE_CALL_STREAM_H__ #include #include #include G_BEGIN_DECLS typedef struct _GabbleCallStream GabbleCallStream; typedef struct _GabbleCallStreamPrivate GabbleCallStreamPrivate; typedef struct _GabbleCallStreamClass GabbleCallStreamClass; struct _GabbleCallStreamClass { TpBaseMediaCallStreamClass parent_class; }; struct _GabbleCallStream { TpBaseMediaCallStream parent; GabbleCallStreamPrivate *priv; }; GType gabble_call_stream_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_CALL_STREAM \ (gabble_call_stream_get_type ()) #define GABBLE_CALL_STREAM(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_CALL_STREAM, GabbleCallStream)) #define GABBLE_CALL_STREAM_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_CALL_STREAM, \ GabbleCallStreamClass)) #define GABBLE_IS_CALL_STREAM(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_CALL_STREAM)) #define GABBLE_IS_CALL_STREAM_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_CALL_STREAM)) #define GABBLE_CALL_STREAM_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_CALL_STREAM, \ GabbleCallStreamClass)) WockyJingleContent *gabble_call_stream_get_jingle_content ( GabbleCallStream *stream); void gabble_call_stream_update_member_states (GabbleCallStream *self); G_END_DECLS #endif /* #ifndef __GABBLE_CALL_STREAM_H__*/ telepathy-gabble-0.18.3/src/debug.h0000664000175000017500000000650112332441362020226 0ustar00cassidycassidy00000000000000#ifndef __DEBUG_H__ #define __DEBUG_H__ #include "config.h" #include #include G_BEGIN_DECLS /* Remember to keep this enum up to date with the keys array in debug.c */ typedef enum { GABBLE_DEBUG_PRESENCE = 1 << 0, GABBLE_DEBUG_GROUPS = 1 << 1, GABBLE_DEBUG_ROSTER = 1 << 2, GABBLE_DEBUG_DISCO = 1 << 3, GABBLE_DEBUG_PROPERTIES = 1 << 4, GABBLE_DEBUG_ROOMLIST = 1 << 5, GABBLE_DEBUG_MEDIA = 1 << 6, GABBLE_DEBUG_MUC = 1 << 7, GABBLE_DEBUG_CONNECTION = 1 << 8, GABBLE_DEBUG_IM = 1 << 9, GABBLE_DEBUG_TUBES = 1 << 10, GABBLE_DEBUG_VCARD = 1 << 11, GABBLE_DEBUG_PIPELINE = 1 << 12, GABBLE_DEBUG_JID = 1 << 13, GABBLE_DEBUG_OLPC = 1 << 14, GABBLE_DEBUG_BYTESTREAM = 1 << 16, GABBLE_DEBUG_LOCATION = 1 << 17, GABBLE_DEBUG_FT = 1 << 18, GABBLE_DEBUG_SEARCH = 1 << 19, GABBLE_DEBUG_BASE_CHANNEL = 1 << 20, GABBLE_DEBUG_PLUGINS = 1 << 21, GABBLE_DEBUG_MAIL_NOTIF = 1 << 22, GABBLE_DEBUG_AUTH = 1 << 23, GABBLE_DEBUG_SLACKER = 1 << 24, GABBLE_DEBUG_SHARE = 1 << 25, GABBLE_DEBUG_TLS = 1 << 26, GABBLE_DEBUG_CLIENT_TYPES = 1 << 27, } GabbleDebugFlags; void gabble_debug_set_flags_from_env (void); void gabble_debug_set_flags (GabbleDebugFlags flags); gboolean gabble_debug_flag_is_set (GabbleDebugFlags flag); void gabble_debug_free (void); void gabble_log (GLogLevelFlags level, GabbleDebugFlags flag, const gchar *format, ...) G_GNUC_PRINTF (3, 4); G_END_DECLS #ifdef DEBUG_FLAG #define ERROR(format, ...) \ G_STMT_START \ { \ gabble_log (G_LOG_LEVEL_ERROR, DEBUG_FLAG, "%s (%s): " format, \ G_STRFUNC, G_STRLOC, ##__VA_ARGS__); \ g_assert_not_reached (); \ } \ G_STMT_END #define CRITICAL(format, ...) \ gabble_log (G_LOG_LEVEL_CRITICAL, DEBUG_FLAG, "%s (%s): " format, \ G_STRFUNC, G_STRLOC, ##__VA_ARGS__) #define WARNING(format, ...) \ gabble_log (G_LOG_LEVEL_WARNING, DEBUG_FLAG, "%s (%s): " format, \ G_STRFUNC, G_STRLOC, ##__VA_ARGS__) #define MESSAGE(format, ...) \ gabble_log (G_LOG_LEVEL_MESSAGE, DEBUG_FLAG, "%s (%s): " format, \ G_STRFUNC, G_STRLOC, ##__VA_ARGS__) #define INFO(format, ...) \ gabble_log (G_LOG_LEVEL_INFO, DEBUG_FLAG, "%s (%s): " format, \ G_STRFUNC, G_STRLOC, ##__VA_ARGS__) #ifdef ENABLE_DEBUG # define DEBUG(format, ...) \ gabble_log (G_LOG_LEVEL_DEBUG, DEBUG_FLAG, "%s (%s): " format, \ G_STRFUNC, G_STRLOC, ##__VA_ARGS__) # define DEBUGGING gabble_debug_flag_is_set (DEBUG_FLAG) # define STANZA_DEBUG(st, s) \ NODE_DEBUG (wocky_stanza_get_top_node (st), s) # define NODE_DEBUG(n, s) \ G_STMT_START { \ gchar *debug_tmp = wocky_node_to_string (n); \ gabble_log (G_LOG_LEVEL_DEBUG, DEBUG_FLAG, "%s: %s:\n%s", G_STRFUNC, s, debug_tmp); \ g_free (debug_tmp); \ } G_STMT_END #else /* !defined (ENABLE_DEBUG) */ static inline void DEBUG ( const gchar *format, ...) { } # define DEBUGGING 0 static inline void STANZA_DEBUG ( WockyStanza *stanza, const gchar *format, ...) { } static inline void NODE_DEBUG ( WockyNode *node, const gchar *format, ...) { } #endif /* !defined (ENABLE_DEBUG) */ #endif /* DEBUG_FLAG */ #endif /* __DEBUG_H__ */ telepathy-gabble-0.18.3/src/presence.c0000664000175000017500000006114712332440117020743 0ustar00cassidycassidy00000000000000/* * gabble-presence.c - Gabble's per-contact presence structure * Copyright (C) 2005 Collabora Ltd. * Copyright (C) 2005 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "presence.h" #include #include #include #include "gabble/capabilities.h" #include "conn-presence.h" #include "presence-cache.h" #include "namespaces.h" #include "util.h" #include "gabble-enumtypes.h" #define DEBUG_FLAG GABBLE_DEBUG_PRESENCE #include "debug.h" static void xep_0115_capabilities_iface_init (gpointer, gpointer); G_DEFINE_TYPE_WITH_CODE (GabblePresence, gabble_presence, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (WOCKY_TYPE_XEP_0115_CAPABILITIES, xep_0115_capabilities_iface_init); ) typedef struct _Resource Resource; struct _Resource { gchar *name; guint client_type; GabbleCapabilitySet *cap_set; GPtrArray *data_forms; guint caps_serial; GabblePresenceId status; gchar *status_message; gint8 priority; /* The last time we saw an available (or chatty! \o\ /o/) presence for * this resource. */ time_t last_available; }; struct _GabblePresencePrivate { /* The aggregated caps of all the contacts' resources. */ GabbleCapabilitySet *cap_set; /* The aggregated data forms of all the contacts' resources */ GPtrArray *data_forms; gchar *no_resource_status_message; GSList *resources; guint olpc_views; gchar *active_resource; }; static Resource * _resource_new (gchar *name) { Resource *new = g_slice_new0 (Resource); new->name = name; new->client_type = 0; new->cap_set = gabble_capability_set_new (); new->data_forms = g_ptr_array_new_with_free_func ( (GDestroyNotify) g_object_unref); new->status = GABBLE_PRESENCE_OFFLINE; new->status_message = NULL; new->priority = 0; new->caps_serial = 0; new->last_available = 0; return new; } static void _resource_free (Resource *resource) { g_free (resource->name); g_free (resource->status_message); gabble_capability_set_free (resource->cap_set); g_ptr_array_unref (resource->data_forms); g_slice_free (Resource, resource); } static void gabble_presence_finalize (GObject *object) { GSList *i; GabblePresence *presence = GABBLE_PRESENCE (object); GabblePresencePrivate *priv = presence->priv; for (i = priv->resources; NULL != i; i = i->next) _resource_free (i->data); g_slist_free (priv->resources); gabble_capability_set_free (priv->cap_set); g_ptr_array_unref (priv->data_forms); g_free (presence->nickname); g_free (presence->avatar_sha1); g_free (priv->no_resource_status_message); g_free (priv->active_resource); } static void gabble_presence_class_init (GabblePresenceClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (object_class, sizeof (GabblePresencePrivate)); object_class->finalize = gabble_presence_finalize; } static void gabble_presence_init (GabblePresence *self) { GabblePresencePrivate *priv; self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_PRESENCE, GabblePresencePrivate); priv = self->priv; priv->cap_set = gabble_capability_set_new (); priv->data_forms = g_ptr_array_new_with_free_func ( (GDestroyNotify) g_object_unref); priv->resources = NULL; self->status = GABBLE_PRESENCE_UNKNOWN; } GabblePresence * gabble_presence_new (void) { return g_object_new (GABBLE_TYPE_PRESENCE, NULL); } static gboolean resource_better_than ( Resource *a, Resource *b, GabbleClientType preferred_client_type) { if (a->priority < 0) return FALSE; if (NULL == b) return TRUE; if (preferred_client_type != 0) { gboolean a_p = a->client_type & preferred_client_type; gboolean b_p = b->client_type & preferred_client_type; if (a_p && !b_p) return TRUE; if (!a_p && b_p) return FALSE; } if (a->status < b->status) return FALSE; else if (a->status > b->status) return TRUE; if (a->last_available < b->last_available) return FALSE; else if (a->last_available > b->last_available) return TRUE; return (a->priority > b->priority); } gboolean gabble_presence_has_cap (GabblePresence *presence, const gchar *ns) { g_return_val_if_fail (presence != NULL, FALSE); return gabble_capability_set_has (presence->priv->cap_set, ns); } GabbleCapabilitySet * gabble_presence_dup_caps (GabblePresence *presence) { g_return_val_if_fail (presence != NULL, NULL); return gabble_capability_set_copy (presence->priv->cap_set); } const GabbleCapabilitySet * gabble_presence_peek_caps (GabblePresence *presence) { g_return_val_if_fail (presence != NULL, NULL); return presence->priv->cap_set; } GPtrArray * gabble_presence_peek_data_forms (GabblePresence *presence) { g_return_val_if_fail (presence != NULL, NULL); return presence->priv->data_forms; } gboolean gabble_presence_has_resources (GabblePresence *self) { return (self->priv->resources != NULL); } /* * gabble_presence_pick_resource_by_caps: * @presence: a presence, which may not be NULL * @preferred_client_type: a single client type flag, such as * GABBLE_CLIENT_TYPE_PHONE, to specify that resources with that type should * be preferred to those without it; or 0 to express no preference * @predicate: a condition which must be satisfied by a resource's * capabilities, or NULL to disregard capabilities * @user_data: the second argument for @predicate (ignored if @predicate is * NULL) * */ const gchar * gabble_presence_pick_resource_by_caps ( GabblePresence *presence, GabbleClientType preferred_client_type, GabbleCapabilitySetPredicate predicate, gconstpointer user_data) { GabblePresencePrivate *priv = presence->priv; GSList *i; Resource *chosen = NULL; g_return_val_if_fail (presence != NULL, NULL); for (i = priv->resources; NULL != i; i = i->next) { Resource *res = (Resource *) i->data; if (predicate != NULL && !predicate (res->cap_set, user_data)) continue; if (resource_better_than (res, chosen, preferred_client_type)) chosen = res; } if (chosen) return chosen->name; else return NULL; } gboolean gabble_presence_resource_has_caps (GabblePresence *presence, const gchar *resource, GabbleCapabilitySetPredicate predicate, gconstpointer user_data) { GabblePresencePrivate *priv = presence->priv; GSList *i; for (i = priv->resources; NULL != i; i = i->next) { Resource *res = (Resource *) i->data; if (!tp_strdiff (res->name, resource)) return predicate (res->cap_set, user_data); } return FALSE; } static void extend_and_dup (GPtrArray *target, GPtrArray *source) { if (source == NULL) return; g_ptr_array_foreach (source, (GFunc) g_object_ref, NULL); tp_g_ptr_array_extend (target, source); } void gabble_presence_set_capabilities (GabblePresence *presence, const gchar *resource, const GabbleCapabilitySet *cap_set, const GPtrArray *data_forms, guint serial) { GabblePresencePrivate *priv = presence->priv; GSList *i; if (resource == NULL && priv->resources != NULL) { /* This is consistent with the handling of presence: if we get presence * from a bare JID, we throw away all the resources, and if we get * presence from a resource, any presence we stored from a bare JID is * overridden by the aggregated presence. */ DEBUG ("Ignoring caps for NULL resource since we have presence for " "some resources"); return; } gabble_capability_set_clear (priv->cap_set); g_ptr_array_set_size (priv->data_forms, 0); if (resource == NULL) { DEBUG ("Setting capabilities for bare JID"); gabble_capability_set_update (priv->cap_set, cap_set); extend_and_dup (priv->data_forms, (GPtrArray *) data_forms); return; } DEBUG ("about to add caps to resource %s with serial %u", resource, serial); for (i = priv->resources; NULL != i; i = i->next) { Resource *tmp = (Resource *) i->data; /* This does not use _find_resource() because it also refreshes * priv->cap_set as we go. */ if (0 == strcmp (tmp->name, resource)) { DEBUG ("found resource %s", resource); if (serial > tmp->caps_serial) { DEBUG ("new serial %u, old %u, clearing caps", serial, tmp->caps_serial); tmp->caps_serial = serial; gabble_capability_set_clear (tmp->cap_set); g_ptr_array_set_size (tmp->data_forms, 0); } if (serial >= tmp->caps_serial) { DEBUG ("updating caps for resource %s", resource); gabble_capability_set_update (tmp->cap_set, cap_set); /* TODO: deal with duplicates */ extend_and_dup (tmp->data_forms, (GPtrArray *) data_forms); } } gabble_capability_set_update (priv->cap_set, tmp->cap_set); /* TODO: deal with duplicates */ extend_and_dup (priv->data_forms, tmp->data_forms); } g_signal_emit_by_name (presence, "capabilities-changed"); } static Resource * _find_resource (GabblePresence *presence, const gchar *resource) { GSList *i; /* you've been warned! */ g_return_val_if_fail (presence != NULL, NULL); g_return_val_if_fail (resource != NULL, NULL); for (i = presence->priv->resources; NULL != i; i = i->next) { Resource *res = i->data; if (!tp_strdiff (res->name, resource)) return res; } return NULL; } static gboolean aggregate_resources (GabblePresence *presence) { GabblePresencePrivate *priv = presence->priv; GSList *i; Resource *best = NULL; guint old_client_types = presence->client_types; /* select the most preferable Resource and update presence->* based on our * choice */ gabble_capability_set_clear (priv->cap_set); presence->status = GABBLE_PRESENCE_OFFLINE; for (i = priv->resources; NULL != i; i = i->next) { Resource *r = (Resource *) i->data; gabble_capability_set_update (priv->cap_set, r->cap_set); /* This doesn't use resource_better_than() because phone preferences take * priority above all others whereas this is only using the PC thing as a * last-ditch tiebreak. wjt looked into changing this but gave up because * it's messy and the phone preference stuff will go away when we do * Jingle call forking anyway: * */ /* trump existing status & message if it's more present * or has the same presence and was more recently available * or has the same presence and a higher priority */ if (best == NULL || r->status > best->status || (r->status == best->status && (r->last_available > best->last_available || r->priority > best->priority)) || (r->client_type & GABBLE_CLIENT_TYPE_PC && !(best->client_type & GABBLE_CLIENT_TYPE_PC))) best = r; } if (best != NULL) { presence->status = best->status; presence->status_message = best->status_message; presence->client_types = best->client_type; g_free (priv->active_resource); priv->active_resource = g_strdup (best->name); } if (presence->status <= GABBLE_PRESENCE_HIDDEN && priv->olpc_views > 0) { /* Contact is in at least one view and we didn't receive a better * presence from him so announce it as available */ presence->status = GABBLE_PRESENCE_AVAILABLE; g_free (presence->status_message); presence->status_message = NULL; } return old_client_types != presence->client_types; } gboolean gabble_presence_update (GabblePresence *presence, const gchar *resource, GabblePresenceId status, const gchar *status_message, gint8 priority, gboolean *update_client_types, time_t now) { GabblePresencePrivate *priv = presence->priv; Resource *res; GabblePresenceId old_status; gchar *old_status_message; GSList *i; gboolean ret = FALSE; /* save our current state */ old_status = presence->status; old_status_message = g_strdup (presence->status_message); if (NULL == resource) { /* presence from a JID with no resource: free all resources and set * presence directly */ for (i = priv->resources; i; i = i->next) _resource_free (i->data); g_slist_free (priv->resources); priv->resources = NULL; if (tp_strdiff (priv->no_resource_status_message, status_message)) { g_free (priv->no_resource_status_message); priv->no_resource_status_message = g_strdup (status_message); } presence->status = status; presence->status_message = priv->no_resource_status_message; goto OUT; } res = _find_resource (presence, resource); /* remove, create or update a Resource as appropriate */ if (status <= GABBLE_PRESENCE_LAST_UNAVAILABLE) { if (NULL != res) { priv->resources = g_slist_remove (priv->resources, res); _resource_free (res); res = NULL; /* recalculate aggregate capability mask */ gabble_capability_set_clear (priv->cap_set); for (i = priv->resources; i; i = i->next) { Resource *r = (Resource *) i->data; gabble_capability_set_update (priv->cap_set, r->cap_set); } } } else { if (NULL == res) { res = _resource_new (g_strdup (resource)); priv->resources = g_slist_append (priv->resources, res); } res->status = status; if (tp_strdiff (res->status_message, status_message)) { g_free (res->status_message); res->status_message = g_strdup (status_message); } res->priority = priority; if (res->status >= GABBLE_PRESENCE_AVAILABLE) res->last_available = now; } /* select the most preferable Resource and update presence->* based on our * choice */ gabble_capability_set_clear (priv->cap_set); presence->status = GABBLE_PRESENCE_OFFLINE; /* use the status message from any offline Resource we're * keeping around just because it has a message on it */ presence->status_message = res ? res->status_message : NULL; if (update_client_types != NULL) *update_client_types = aggregate_resources (presence); else aggregate_resources (presence); OUT: /* detect changes */ if (presence->status != old_status || tp_strdiff (presence->status_message, old_status_message)) ret = TRUE; g_free (old_status_message); return ret; } void gabble_presence_add_status_and_vcard (GabblePresence *presence, WockyStanza *stanza) { WockyNode *node = wocky_stanza_get_top_node (stanza); WockyNode *vcard_node; switch (presence->status) { case GABBLE_PRESENCE_AVAILABLE: case GABBLE_PRESENCE_OFFLINE: case GABBLE_PRESENCE_HIDDEN: break; case GABBLE_PRESENCE_AWAY: wocky_node_add_child_with_content (node, "show", JABBER_PRESENCE_SHOW_AWAY); break; case GABBLE_PRESENCE_CHAT: wocky_node_add_child_with_content (node, "show", JABBER_PRESENCE_SHOW_CHAT); break; case GABBLE_PRESENCE_DND: wocky_node_add_child_with_content (node, "show", JABBER_PRESENCE_SHOW_DND); break; case GABBLE_PRESENCE_XA: wocky_node_add_child_with_content (node, "show", JABBER_PRESENCE_SHOW_XA); break; default: { /* FIXME: we're almost duplicate the add_child code here, * and we're calling into conn-presence which is not nice. */ TpConnectionPresenceType presence_type = conn_presence_get_type (presence); switch (presence_type) { case TP_CONNECTION_PRESENCE_TYPE_AVAILABLE: case TP_CONNECTION_PRESENCE_TYPE_OFFLINE: case TP_CONNECTION_PRESENCE_TYPE_HIDDEN: break; case TP_CONNECTION_PRESENCE_TYPE_AWAY: wocky_node_add_child_with_content (node, "show", JABBER_PRESENCE_SHOW_AWAY); break; case TP_CONNECTION_PRESENCE_TYPE_BUSY: wocky_node_add_child_with_content (node, "show", JABBER_PRESENCE_SHOW_DND); break; case TP_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY: wocky_node_add_child_with_content (node, "show", JABBER_PRESENCE_SHOW_XA); break; default: g_critical ("%s: Unexpected Telepathy presence type: %d", G_STRFUNC, presence_type); break; } } } if (presence->status_message) wocky_node_add_child_with_content (node, "status", presence->status_message); vcard_node = wocky_node_add_child_ns (node, "x", NS_VCARD_TEMP_UPDATE); if (presence->avatar_sha1 != NULL) { wocky_node_add_child_with_content (vcard_node, "photo", presence->avatar_sha1); } } WockyStanza * gabble_presence_as_message (GabblePresence *presence, const gchar *to) { GabblePresencePrivate *priv = presence->priv; WockyStanza *message; WockyStanzaSubType subtype; Resource *res = priv->resources->data; /* pick first resource */ g_assert (NULL != res); if (presence->status == GABBLE_PRESENCE_OFFLINE) subtype = WOCKY_STANZA_SUB_TYPE_UNAVAILABLE; else subtype = WOCKY_STANZA_SUB_TYPE_AVAILABLE; message = wocky_stanza_build (WOCKY_STANZA_TYPE_PRESENCE, subtype, NULL, to, NULL); gabble_presence_add_status_and_vcard (presence, message); if (res->priority) { gchar *priority = g_strdup_printf ("%d", res->priority); WockyNode *node; node = wocky_stanza_get_top_node (message); wocky_node_add_child_with_content (node, "priority", priority); g_free (priority); } return message; } gchar * gabble_presence_dump (GabblePresence *presence) { GSList *i; GString *ret = g_string_new (""); gchar *tmp; GabblePresencePrivate *priv = presence->priv; const gchar *presence_name = wocky_enum_to_nick (GABBLE_TYPE_PRESENCE_ID, presence->status); if (presence_name == NULL) presence_name = "plugin-specific, not an element of GabblePresenceId"; g_string_append_printf (ret, "nickname: %s\n" "accumulated status: %d (%s)\n" "accumulated status msg: %s\n" "kept while unavailable: %d\n", presence->nickname, presence->status, presence_name, presence->status_message, presence->keep_unavailable); if (priv->cap_set != NULL) { tmp = gabble_capability_set_dump (priv->cap_set, " "); g_string_append (ret, "capabilities:\n"); g_string_append (ret, tmp); g_free (tmp); } g_string_append_printf (ret, "resources:\n"); for (i = priv->resources; i; i = i->next) { Resource *res = (Resource *) i->data; g_string_append_printf (ret, " %s\n" " status: %d\n" " status msg: %s\n" " priority: %d\n", res->name, res->status, res->status_message, res->priority); if (res->cap_set != NULL) { tmp = gabble_capability_set_dump (res->cap_set, " "); g_string_append (ret, " capabilities:\n"); g_string_append (ret, tmp); g_free (tmp); } } if (priv->resources == NULL) g_string_append_printf (ret, " (none)\n"); return g_string_free (ret, FALSE); } gboolean gabble_presence_added_to_view (GabblePresence *self) { GabblePresencePrivate *priv = self->priv; GabblePresenceId old_status; gchar *old_status_message; gboolean ret = FALSE; /* save our current state */ old_status = self->status; old_status_message = g_strdup (self->status_message); priv->olpc_views++; aggregate_resources (self); /* detect changes */ if (self->status != old_status || tp_strdiff (self->status_message, old_status_message)) ret = TRUE; g_free (old_status_message); return ret; } gboolean gabble_presence_removed_from_view (GabblePresence *self) { GabblePresencePrivate *priv = self->priv; GabblePresenceId old_status; gchar *old_status_message; gboolean ret = FALSE; /* save our current state */ old_status = self->status; old_status_message = g_strdup (self->status_message); priv->olpc_views--; aggregate_resources (self); /* detect changes */ if (self->status != old_status || tp_strdiff (self->status_message, old_status_message)) ret = TRUE; g_free (old_status_message); return ret; } gconstpointer gabble_presence_resource_pick_best_feature (GabblePresence *presence, const gchar *resource, const GabbleFeatureFallback *table, GabbleCapabilitySetPredicate predicate) { Resource *res; const GabbleFeatureFallback *row; g_return_val_if_fail (presence != NULL, NULL); g_return_val_if_fail (resource != NULL, NULL); g_return_val_if_fail (predicate != NULL, NULL); g_return_val_if_fail (table != NULL, NULL); res = _find_resource (presence, resource); if (res == NULL) return NULL; for (row = table; row->result != NULL; row++) { if (row->considered && predicate (res->cap_set, row->check_data)) { return row->result; } } return NULL; } gconstpointer gabble_presence_pick_best_feature (GabblePresence *presence, const GabbleFeatureFallback *table, GabbleCapabilitySetPredicate predicate) { const GabbleFeatureFallback *row; g_return_val_if_fail (presence != NULL, NULL); g_return_val_if_fail (predicate != NULL, NULL); g_return_val_if_fail (table != NULL, NULL); for (row = table; row->result != NULL; row++) { if (row->considered && predicate (presence->priv->cap_set, row->check_data)) { return row->result; } } return NULL; } /* FIXME: this function should be combined with * gabble_presence_set_capabilities(). */ gboolean gabble_presence_update_client_types (GabblePresence *presence, const gchar *resource, guint client_types) { Resource *res; if (resource == NULL && presence->priv->resources != NULL) { DEBUG ("Ignoring client types for NULL resource since we have " "presence for some resources"); return FALSE; } if (resource == NULL) { guint old_client_types = presence->client_types; presence->client_types = client_types; return (old_client_types != client_types); } res = _find_resource (presence, resource); if (res == NULL) return FALSE; res->client_type = client_types; return aggregate_resources (presence); } gchar ** gabble_presence_get_client_types_array (GabblePresence *presence, const char **resource_name) { GPtrArray *array = g_ptr_array_new (); GFlagsClass *klass = g_type_class_ref (GABBLE_TYPE_CLIENT_TYPE); if (klass != NULL) { guint i; for (i = 0; i < klass->n_values; i++) { GFlagsValue *value = &klass->values[i]; if (presence->client_types & value->value) g_ptr_array_add (array, g_strdup (value->value_nick)); } g_type_class_unref (klass); } g_ptr_array_add (array, NULL); if (resource_name != NULL) *resource_name = presence->priv->active_resource; return (gchar **) g_ptr_array_free (array, FALSE); } static const GPtrArray * gabble_presence_get_data_forms (WockyXep0115Capabilities *caps) { GabblePresence *presence = GABBLE_PRESENCE (caps); return presence->priv->data_forms; } static void xep_0115_capabilities_iface_init (gpointer g_iface, gpointer iface_data) { WockyXep0115CapabilitiesInterface *iface = g_iface; iface->get_data_forms = gabble_presence_get_data_forms; } telepathy-gabble-0.18.3/src/call-member-content.h0000664000175000017500000000707712223562023022776 0ustar00cassidycassidy00000000000000/* * call-member-content.h - Header for GabbleCallMemberContent * Copyright (C) 2010 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __CALL_MEMBER_CONTENT_H__ #define __CALL_MEMBER_CONTENT_H__ #include #include #include "types.h" G_BEGIN_DECLS typedef struct _GabbleCallMemberContentPrivate GabbleCallMemberContentPrivate; typedef struct _GabbleCallMemberContentClass GabbleCallMemberContentClass; struct _GabbleCallMemberContentClass { GObjectClass parent_class; }; struct _GabbleCallMemberContent { GObject parent; GabbleCallMemberContentPrivate *priv; }; GType gabble_call_member_content_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_CALL_MEMBER_CONTENT \ (gabble_call_member_content_get_type ()) #define GABBLE_CALL_MEMBER_CONTENT(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_CALL_MEMBER_CONTENT, \ GabbleCallMemberContent)) #define GABBLE_CALL_MEMBER_CONTENT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_CALL_MEMBER_CONTENT, \ GabbleCallMemberContentClass)) #define GABBLE_IS_CALL_MEMBER_CONTENT(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_CALL_MEMBER_CONTENT)) #define GABBLE_IS_CALL_MEMBER_CONTENT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_CALL_MEMBER_CONTENT)) #define GABBLE_CALL_MEMBER_CONTENT_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_CALL_MEMBER_CONTENT, \ GabbleCallMemberContentClass)) GabbleCallMemberContent *gabble_call_member_content_new (const gchar *name, WockyJingleMediaType type, GabbleCallMember *member); GabbleCallMemberContent *gabble_call_member_content_from_jingle_content ( WockyJingleContent *jingle_content, GabbleCallMember *member); WockyJingleMediaType gabble_call_member_content_get_media_type ( GabbleCallMemberContent *self); const gchar *gabble_call_member_content_get_name ( GabbleCallMemberContent *self); WockyJingleContent *gabble_call_member_content_get_jingle_content ( GabbleCallMemberContent *self); gboolean gabble_call_member_content_has_jingle_content ( GabbleCallMemberContent *self); GList *gabble_call_member_content_get_remote_codecs ( GabbleCallMemberContent *self); void gabble_call_member_content_set_remote_codecs ( GabbleCallMemberContent *self, GList *codecs); GList * gabble_call_member_content_get_remote_codecs ( GabbleCallMemberContent *self); GabbleCallMember *gabble_call_member_content_get_member ( GabbleCallMemberContent *self); void gabble_call_member_content_set_jingle_content ( GabbleCallMemberContent *self, WockyJingleContent *content); void gabble_call_member_content_add_to_session ( GabbleCallMemberContent *self); void gabble_call_member_content_remove ( GabbleCallMemberContent *self); G_END_DECLS #endif /* #ifndef __CALL_MEMBER_CONTENT_H__*/ telepathy-gabble-0.18.3/src/server-tls-channel.h0000664000175000017500000000472412223562023022656 0ustar00cassidycassidy00000000000000/* * server-tls-channel.h - Header for GabbleServerTLSChannel * Copyright (C) 2010 Collabora Ltd. * @author Cosimo Cecchi * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_SERVER_TLS_CHANNEL_H__ #define __GABBLE_SERVER_TLS_CHANNEL_H__ #include #include #include #include "tls-certificate.h" G_BEGIN_DECLS typedef struct _GabbleServerTLSChannelPrivate GabbleServerTLSChannelPrivate; typedef struct _GabbleServerTLSChannelClass GabbleServerTLSChannelClass; typedef struct _GabbleServerTLSChannel GabbleServerTLSChannel; struct _GabbleServerTLSChannelClass { TpBaseChannelClass base_class; }; struct _GabbleServerTLSChannel { TpBaseChannel parent; GabbleServerTLSChannelPrivate *priv; }; GType gabble_server_tls_channel_get_type (void); #define GABBLE_TYPE_SERVER_TLS_CHANNEL \ (gabble_server_tls_channel_get_type ()) #define GABBLE_SERVER_TLS_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_SERVER_TLS_CHANNEL, \ GabbleServerTLSChannel)) #define GABBLE_SERVER_TLS_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_SERVER_TLS_CHANNEL, \ GabbleServerTLSChannelClass)) #define GABBLE_IS_SERVER_TLS_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_SERVER_TLS_CHANNEL)) #define GABBLE_IS_SERVER_TLS_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_SERVER_TLS_CHANNEL)) #define GABBLE_SERVER_TLS_CHANNEL_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_SERVER_TLS_CHANNEL,\ GabbleServerTLSChannelClass)) GabbleTLSCertificate * gabble_server_tls_channel_get_certificate ( GabbleServerTLSChannel *self); G_END_DECLS #endif /* #ifndef __GABBLE_SERVER_TLS_CHANNEL_H__*/ telepathy-gabble-0.18.3/src/room-config.c0000664000175000017500000000612012223562023021344 0ustar00cassidycassidy00000000000000/* * room-config.c - Channel.Interface.RoomConfig1 implementation * Copyright ©2011 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "room-config.h" #include "muc-channel.h" #define DEBUG_FLAG GABBLE_DEBUG_MUC #include "debug.h" static void gabble_room_config_update_configuration_async ( TpBaseRoomConfig *base_config, GHashTable *validated_properties, GAsyncReadyCallback callback, gpointer user_data); struct _GabbleRoomConfigPrivate { gpointer hi_dere; }; G_DEFINE_TYPE (GabbleRoomConfig, gabble_room_config, TP_TYPE_BASE_ROOM_CONFIG) static void gabble_room_config_init (GabbleRoomConfig *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_ROOM_CONFIG, GabbleRoomConfigPrivate); } static void gabble_room_config_class_init (GabbleRoomConfigClass *klass) { TpBaseRoomConfigClass *parent_class = TP_BASE_ROOM_CONFIG_CLASS (klass); parent_class->update_async = gabble_room_config_update_configuration_async; g_type_class_add_private (klass, sizeof (GabbleRoomConfigPrivate)); } GabbleRoomConfig * gabble_room_config_new ( TpBaseChannel *channel) { g_return_val_if_fail (TP_IS_BASE_CHANNEL (channel), NULL); return g_object_new (GABBLE_TYPE_ROOM_CONFIG, "channel", channel, NULL); } static void updated_configuration_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { GabbleMucChannel *channel = GABBLE_MUC_CHANNEL (source); GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); GError *error = NULL; if (!gabble_muc_channel_update_configuration_finish (channel, result, &error)) { g_simple_async_result_set_from_error (simple, error); g_clear_error (&error); } g_simple_async_result_complete (simple); g_object_unref (simple); } static void gabble_room_config_update_configuration_async ( TpBaseRoomConfig *base_config, GHashTable *validated_properties, GAsyncReadyCallback callback, gpointer user_data) { TpBaseChannel *base_channel = tp_base_room_config_dup_channel (base_config); GSimpleAsyncResult *simple = g_simple_async_result_new ( G_OBJECT (base_config), callback, user_data, gabble_room_config_update_configuration_async); gabble_muc_channel_update_configuration_async ( GABBLE_MUC_CHANNEL (base_channel), validated_properties, updated_configuration_cb, simple); g_object_unref (base_channel); } telepathy-gabble-0.18.3/src/conn-util.c0000664000175000017500000000630712332440117021044 0ustar00cassidycassidy00000000000000/* * conn-util.c - Header for Gabble connection kitchen-sink code. * Copyright (C) 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "conn-util.h" #include #define DEBUG_FLAG GABBLE_DEBUG_CONNECTION #include "debug.h" #include "namespaces.h" #include "util.h" #include static void conn_util_send_iq_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { WockyPorter *porter = WOCKY_PORTER (source_object); WockyStanza *reply; GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); GError *error = NULL; reply = wocky_porter_send_iq_finish (porter, res, &error); if (reply != NULL) { g_simple_async_result_set_op_res_gpointer (result, reply, (GDestroyNotify) g_object_unref); } else { g_simple_async_result_set_from_error (result, error); g_clear_error (&error); } g_simple_async_result_complete (result); g_object_unref (result); } void conn_util_send_iq_async (GabbleConnection *self, WockyStanza *stanza, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyPorter *porter = wocky_session_get_porter (self->session); GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, conn_util_send_iq_async); wocky_porter_send_iq_async (porter, stanza, cancellable, conn_util_send_iq_cb, result); } gboolean conn_util_send_iq_finish (GabbleConnection *self, GAsyncResult *result, WockyStanza **response, GError **error) { GSimpleAsyncResult *res; WockyStanza *resp; GError *err = NULL; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), conn_util_send_iq_async), FALSE); res = (GSimpleAsyncResult *) result; resp = g_simple_async_result_get_op_res_gpointer (res); if (g_simple_async_result_propagate_error (res, &err) || wocky_stanza_extract_errors (resp, NULL, &err, NULL, NULL)) { gabble_set_tp_error_from_wocky (err, error); g_error_free (err); return FALSE; } if (response != NULL) *response = g_object_ref (resp); return TRUE; } const gchar * conn_util_get_bare_self_jid (GabbleConnection *conn) { TpBaseConnection *base = TP_BASE_CONNECTION (conn); TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); TpHandle self = tp_base_connection_get_self_handle (base); return tp_handle_inspect (contact_handles, self); } telepathy-gabble-0.18.3/src/media-stream.c0000664000175000017500000020100112332441362021473 0ustar00cassidycassidy00000000000000/* * gabble-media-stream.c - Source for GabbleMediaStream * Copyright © 2006-2009 Collabora Ltd. * Copyright © 2006-2009 Nokia Corporation * @author Ole Andre Vadla Ravnaas * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "media-stream.h" #include #include #include #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_MEDIA #include "connection.h" #include "debug.h" #include "gabble-signals-marshal.h" #include "media-channel.h" #include "namespaces.h" #include "util.h" static void stream_handler_iface_init (gpointer, gpointer); G_DEFINE_TYPE_WITH_CODE(GabbleMediaStream, gabble_media_stream, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_MEDIA_STREAM_HANDLER, stream_handler_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, tp_dbus_properties_mixin_iface_init); ) /* signal enum */ enum { ERROR, UNHOLD_FAILED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; /* properties */ enum { PROP_DBUS_DAEMON = 1, PROP_OBJECT_PATH, PROP_NAME, PROP_ID, PROP_MEDIA_TYPE, PROP_CONNECTION_STATE, PROP_READY, PROP_PLAYING, PROP_COMBINED_DIRECTION, PROP_LOCAL_HOLD, PROP_CONTENT, PROP_STUN_SERVERS, PROP_RELAY_INFO, PROP_NAT_TRAVERSAL, PROP_CREATED_LOCALLY, LAST_PROPERTY }; /* private structure */ struct _GabbleMediaStreamPrivate { WockyJingleContent *content; TpDBusDaemon *dbus_daemon; gchar *object_path; guint id; guint media_type; gboolean local_codecs_set; /* Whether we're waiting for a codec intersection from the streaming * implementation. If FALSE, SupportedCodecs is a no-op. */ gboolean awaiting_intersection; GValue local_rtp_hdrexts; GValue local_feedback_messages; GValue remote_codecs; GValue remote_rtp_hdrexts; GValue remote_feedback_messages; GValue remote_candidates; guint remote_candidate_count; /* source ID for initial codecs/candidates getter */ gulong initial_getter_id; gchar *nat_traversal; /* GPtrArray(GValueArray(STRING, UINT)) */ GPtrArray *stun_servers; /* GPtrArray(GHashTable(string => GValue)) */ GPtrArray *relay_info; gboolean on_hold; /* These are really booleans, but gboolean is signed. Thanks, GLib */ unsigned closed:1; unsigned dispose_has_run:1; unsigned local_hold:1; unsigned ready:1; unsigned sending:1; unsigned created_locally:1; }; static void push_remote_media_description (GabbleMediaStream *stream); static void push_remote_candidates (GabbleMediaStream *stream); static void push_playing (GabbleMediaStream *stream); static void push_sending (GabbleMediaStream *stream); static void new_remote_candidates_cb (WockyJingleContent *content, GList *clist, GabbleMediaStream *stream); static void new_remote_media_description_cb (WockyJingleContent *content, WockyJingleMediaDescription *md, GabbleMediaStream *stream); static void content_state_changed_cb (WockyJingleContent *c, GParamSpec *pspec, GabbleMediaStream *stream); static void content_senders_changed_cb (WockyJingleContent *c, GParamSpec *pspec, GabbleMediaStream *stream); static void remote_state_changed_cb (WockyJingleSession *session, GabbleMediaStream *stream); static void content_removed_cb (WockyJingleContent *content, GabbleMediaStream *stream); static void update_direction (GabbleMediaStream *stream, WockyJingleContent *c); static void update_sending (GabbleMediaStream *stream, gboolean start_sending); GabbleMediaStream * gabble_media_stream_new ( TpDBusDaemon *dbus_daemon, const gchar *object_path, WockyJingleContent *content, const gchar *name, guint id, const gchar *nat_traversal, const GPtrArray *relay_info, gboolean local_hold) { GPtrArray *empty = NULL; GabbleMediaStream *result; g_return_val_if_fail (WOCKY_IS_JINGLE_MEDIA_RTP (content), NULL); if (relay_info == NULL) { empty = g_ptr_array_sized_new (0); relay_info = empty; } result = g_object_new (GABBLE_TYPE_MEDIA_STREAM, "dbus-daemon", dbus_daemon, "object-path", object_path, "content", content, "name", name, "id", id, "nat-traversal", nat_traversal, "relay-info", relay_info, "local-hold", local_hold, NULL); if (empty != NULL) g_ptr_array_unref (empty); return result; } TpMediaStreamType gabble_media_stream_get_media_type (GabbleMediaStream *self) { return self->priv->media_type; } static void gabble_media_stream_init (GabbleMediaStream *self) { GabbleMediaStreamPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_MEDIA_STREAM, GabbleMediaStreamPrivate); GType candidate_list_type = TP_ARRAY_TYPE_MEDIA_STREAM_HANDLER_CANDIDATE_LIST; GType codec_list_type = TP_ARRAY_TYPE_MEDIA_STREAM_HANDLER_CODEC_LIST; GType rtp_hdrext_list_type = TP_ARRAY_TYPE_RTP_HEADER_EXTENSIONS_LIST; GType fb_msg_map_type = TP_HASH_TYPE_RTCP_FEEDBACK_MESSAGE_MAP; self->priv = priv; g_value_init (&priv->local_rtp_hdrexts, rtp_hdrext_list_type); g_value_init (&priv->local_feedback_messages, fb_msg_map_type); g_value_init (&priv->remote_codecs, codec_list_type); g_value_take_boxed (&priv->remote_codecs, dbus_g_type_specialized_construct (codec_list_type)); g_value_init (&priv->remote_rtp_hdrexts, rtp_hdrext_list_type); g_value_take_boxed (&priv->remote_rtp_hdrexts, dbus_g_type_specialized_construct (rtp_hdrext_list_type)); g_value_init (&priv->remote_feedback_messages, fb_msg_map_type); g_value_take_boxed (&priv->remote_feedback_messages, dbus_g_type_specialized_construct (fb_msg_map_type)); g_value_init (&priv->remote_candidates, candidate_list_type); g_value_take_boxed (&priv->remote_candidates, dbus_g_type_specialized_construct (candidate_list_type)); priv->stun_servers = g_ptr_array_sized_new (1); } static gboolean _get_initial_codecs_and_candidates (gpointer user_data) { GabbleMediaStream *stream = GABBLE_MEDIA_STREAM (user_data); GabbleMediaStreamPrivate *priv = stream->priv; WockyJingleMediaDescription *md; priv->initial_getter_id = 0; /* we can immediately get the codecs if we're responder */ md = wocky_jingle_media_rtp_get_remote_media_description ( WOCKY_JINGLE_MEDIA_RTP (priv->content)); if (md != NULL) new_remote_media_description_cb (priv->content, md, stream); /* if any candidates arrived before idle loop had the chance to excute * us (e.g. specified in session-initiate/content-add), we don't want to * miss them */ new_remote_candidates_cb (priv->content, wocky_jingle_content_get_remote_candidates (priv->content), stream); return FALSE; } static GObject * gabble_media_stream_constructor (GType type, guint n_props, GObjectConstructParam *props) { GObject *obj; GabbleMediaStream *stream; GabbleMediaStreamPrivate *priv; WockyJingleFactory *jf; GList *stun_servers; /* call base class constructor */ obj = G_OBJECT_CLASS (gabble_media_stream_parent_class)-> constructor (type, n_props, props); stream = GABBLE_MEDIA_STREAM (obj); priv = stream->priv; g_assert (priv->content != NULL); /* STUN servers are needed as soon as the stream appears, so there's little * point in waiting for them - either they've already been resolved, or * we're too late to use them for this stream */ jf = wocky_jingle_session_get_factory (priv->content->session); stun_servers = wocky_jingle_info_get_stun_servers ( wocky_jingle_factory_get_jingle_info (jf)); while (stun_servers != NULL) { WockyStunServer *stun_server = stun_servers->data; GValueArray *va = tp_value_array_build (2, G_TYPE_STRING, stun_server->address, G_TYPE_UINT, (guint) stun_server->port, G_TYPE_INVALID); g_ptr_array_add (priv->stun_servers, va); stun_servers = g_list_delete_link (stun_servers, stun_servers); } /* go for the bus */ g_assert (priv->dbus_daemon != NULL); tp_dbus_daemon_register_object (priv->dbus_daemon, priv->object_path, obj); update_direction (stream, priv->content); /* MediaStream is created as soon as WockyJingleContent is * created, but we want to let it parse the initiation (if * initiated by remote end) before we pick up initial * codecs and candidates. * FIXME: add API for ordering IQs rather than using g_idle_add. */ priv->initial_getter_id = g_idle_add (_get_initial_codecs_and_candidates, stream); if (priv->created_locally) { g_object_set (stream, "combined-direction", MAKE_COMBINED_DIRECTION (TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL, 0), NULL); } else { priv->awaiting_intersection = TRUE; } return obj; } static void gabble_media_stream_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleMediaStream *stream = GABBLE_MEDIA_STREAM (object); GabbleMediaStreamPrivate *priv = stream->priv; switch (property_id) { case PROP_DBUS_DAEMON: g_value_set_object (value, priv->dbus_daemon); break; case PROP_OBJECT_PATH: g_value_set_string (value, priv->object_path); break; case PROP_NAME: g_value_set_string (value, stream->name); break; case PROP_ID: g_value_set_uint (value, priv->id); break; case PROP_MEDIA_TYPE: g_value_set_uint (value, priv->media_type); break; case PROP_CONNECTION_STATE: g_value_set_uint (value, stream->connection_state); break; case PROP_READY: g_value_set_boolean (value, priv->ready); break; case PROP_PLAYING: g_value_set_boolean (value, stream->playing); break; case PROP_COMBINED_DIRECTION: g_value_set_uint (value, stream->combined_direction); break; case PROP_LOCAL_HOLD: g_value_set_boolean (value, priv->local_hold); break; case PROP_CONTENT: g_value_set_object (value, priv->content); break; case PROP_STUN_SERVERS: g_value_set_boxed (value, priv->stun_servers); break; case PROP_NAT_TRAVERSAL: g_value_set_string (value, priv->nat_traversal); break; case PROP_CREATED_LOCALLY: g_value_set_boolean (value, priv->created_locally); break; case PROP_RELAY_INFO: g_value_set_boxed (value, priv->relay_info); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_media_stream_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleMediaStream *stream = GABBLE_MEDIA_STREAM (object); GabbleMediaStreamPrivate *priv = stream->priv; switch (property_id) { case PROP_OBJECT_PATH: g_free (priv->object_path); priv->object_path = g_value_dup_string (value); break; case PROP_DBUS_DAEMON: g_assert (priv->dbus_daemon == NULL); priv->dbus_daemon = g_value_dup_object (value); break; case PROP_NAME: g_free (stream->name); stream->name = g_value_dup_string (value); break; case PROP_ID: priv->id = g_value_get_uint (value); break; case PROP_CONNECTION_STATE: DEBUG ("stream %s connection state %d", stream->name, stream->connection_state); stream->connection_state = g_value_get_uint (value); break; case PROP_READY: priv->ready = g_value_get_boolean (value); break; case PROP_PLAYING: { gboolean old = stream->playing; stream->playing = g_value_get_boolean (value); if (stream->playing != old) push_playing (stream); } break; case PROP_COMBINED_DIRECTION: DEBUG ("changing combined direction from %u to %u", stream->combined_direction, g_value_get_uint (value)); stream->combined_direction = g_value_get_uint (value); break; case PROP_CONTENT: g_assert (priv->content == NULL); priv->content = g_value_dup_object (value); { guint jtype; gboolean locally_created; g_object_get (priv->content, "media-type", &jtype, "locally-created", &locally_created, NULL); if (jtype == WOCKY_JINGLE_MEDIA_TYPE_VIDEO) priv->media_type = TP_MEDIA_STREAM_TYPE_VIDEO; else priv->media_type = TP_MEDIA_STREAM_TYPE_AUDIO; priv->created_locally = locally_created; } DEBUG ("%p: connecting to content %p signals", stream, priv->content); gabble_signal_connect_weak (priv->content, "new-candidates", (GCallback) new_remote_candidates_cb, object); /* we need this also, if we're the initiator of the stream * (so remote codecs arrive later) */ gabble_signal_connect_weak (priv->content, "remote-media-description", (GCallback) new_remote_media_description_cb, object); gabble_signal_connect_weak (priv->content, "notify::state", (GCallback) content_state_changed_cb, object); gabble_signal_connect_weak (priv->content, "notify::senders", (GCallback) content_senders_changed_cb, object); gabble_signal_connect_weak (priv->content->session, "remote-state-changed", (GCallback) remote_state_changed_cb, object); gabble_signal_connect_weak (priv->content, "removed", (GCallback) content_removed_cb, object); break; case PROP_NAT_TRAVERSAL: g_assert (priv->nat_traversal == NULL); priv->nat_traversal = g_value_dup_string (value); break; case PROP_RELAY_INFO: g_assert (priv->relay_info == NULL); priv->relay_info = g_value_dup_boxed (value); break; case PROP_LOCAL_HOLD: priv->local_hold = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_media_stream_dispose (GObject *object); static void gabble_media_stream_finalize (GObject *object); static void gabble_media_stream_class_init (GabbleMediaStreamClass *gabble_media_stream_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_media_stream_class); GParamSpec *param_spec; static TpDBusPropertiesMixinPropImpl stream_handler_props[] = { { "RelayInfo", "relay-info", NULL }, { "STUNServers", "stun-servers", NULL }, { "NATTraversal", "nat-traversal", NULL }, { "CreatedLocally", "created-locally", NULL }, { NULL } }; static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { { TP_IFACE_MEDIA_STREAM_HANDLER, tp_dbus_properties_mixin_getter_gobject_properties, NULL, stream_handler_props, }, { NULL } }; g_type_class_add_private (gabble_media_stream_class, sizeof (GabbleMediaStreamPrivate)); object_class->constructor = gabble_media_stream_constructor; object_class->get_property = gabble_media_stream_get_property; object_class->set_property = gabble_media_stream_set_property; object_class->dispose = gabble_media_stream_dispose; object_class->finalize = gabble_media_stream_finalize; param_spec = g_param_spec_object ("dbus-daemon", "TpDBusDaemon", "Bus on which to export this object", TP_TYPE_DBUS_DAEMON, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_DBUS_DAEMON, param_spec); param_spec = g_param_spec_string ("object-path", "D-Bus object path", "The D-Bus object path used for this " "object on the bus.", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_OBJECT_PATH, param_spec); param_spec = g_param_spec_string ("name", "Stream name", "An opaque name for the stream used in the signalling.", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_NAME, param_spec); param_spec = g_param_spec_uint ("id", "Stream ID", "A stream number for the stream used in the " "D-Bus API.", 0, G_MAXUINT, 0, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_ID, param_spec); param_spec = g_param_spec_uint ("media-type", "Stream media type", "A constant indicating which media type the stream carries.", TP_MEDIA_STREAM_TYPE_AUDIO, TP_MEDIA_STREAM_TYPE_VIDEO, TP_MEDIA_STREAM_TYPE_AUDIO, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_MEDIA_TYPE, param_spec); param_spec = g_param_spec_uint ("connection-state", "Stream connection state", "An integer indicating the state of the" "stream's connection.", TP_MEDIA_STREAM_STATE_DISCONNECTED, TP_MEDIA_STREAM_STATE_CONNECTED, TP_MEDIA_STREAM_STATE_DISCONNECTED, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_CONNECTION_STATE, param_spec); param_spec = g_param_spec_boolean ("ready", "Ready?", "A boolean signifying whether the user " "is ready to handle signals from this " "object.", FALSE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_READY, param_spec); param_spec = g_param_spec_boolean ("playing", "Set playing", "A boolean signifying whether the stream " "has been set playing yet.", FALSE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_PLAYING, param_spec); param_spec = g_param_spec_uint ("combined-direction", "Combined direction", "An integer indicating the directions the stream currently sends in, " "and the peers who have been asked to send.", TP_MEDIA_STREAM_DIRECTION_NONE, MAKE_COMBINED_DIRECTION (TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL, TP_MEDIA_STREAM_PENDING_LOCAL_SEND | TP_MEDIA_STREAM_PENDING_REMOTE_SEND), TP_MEDIA_STREAM_DIRECTION_NONE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_COMBINED_DIRECTION, param_spec); param_spec = g_param_spec_boolean ("local-hold", "Local hold?", "True if resources used for this stream have been freed.", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK); g_object_class_install_property (object_class, PROP_LOCAL_HOLD, param_spec); param_spec = g_param_spec_object ("content", "WockyJingleContent object", "Jingle content signalling this media stream.", WOCKY_TYPE_JINGLE_CONTENT, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_CONTENT, param_spec); param_spec = g_param_spec_boxed ("stun-servers", "STUN servers", "Array of (STRING: address literal, UINT: port) pairs", /* FIXME: use correct macro when available */ tp_type_dbus_array_su (), G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_STUN_SERVERS, param_spec); param_spec = g_param_spec_boxed ("relay-info", "Relay info", "Array of mappings containing relay server information", TP_ARRAY_TYPE_STRING_VARIANT_MAP_LIST, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_RELAY_INFO, param_spec); param_spec = g_param_spec_string ("nat-traversal", "NAT traversal", "NAT traversal mechanism for this stream", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_NAT_TRAVERSAL, param_spec); param_spec = g_param_spec_boolean ("created-locally", "Created locally?", "True if this stream was created by the local user", FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CREATED_LOCALLY, param_spec); /* signals not exported by D-Bus interface */ signals[ERROR] = g_signal_new ("error", G_OBJECT_CLASS_TYPE (gabble_media_stream_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, gabble_marshal_VOID__UINT_STRING, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_STRING); signals[UNHOLD_FAILED] = g_signal_new ("unhold-failed", G_OBJECT_CLASS_TYPE (gabble_media_stream_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); gabble_media_stream_class->props_class.interfaces = prop_interfaces; tp_dbus_properties_mixin_class_init (object_class, G_STRUCT_OFFSET (GabbleMediaStreamClass, props_class)); } void gabble_media_stream_dispose (GObject *object) { GabbleMediaStream *self = GABBLE_MEDIA_STREAM (object); GabbleMediaStreamPrivate *priv = self->priv; DEBUG ("called"); if (priv->dispose_has_run) return; if (priv->initial_getter_id != 0) { g_source_remove (priv->initial_getter_id); priv->initial_getter_id = 0; } gabble_media_stream_close (self); priv->dispose_has_run = TRUE; tp_clear_object (&priv->content); tp_clear_pointer (&self->name, g_free); g_clear_object (&priv->dbus_daemon); if (G_OBJECT_CLASS (gabble_media_stream_parent_class)->dispose) G_OBJECT_CLASS (gabble_media_stream_parent_class)->dispose (object); } void gabble_media_stream_finalize (GObject *object) { GabbleMediaStream *self = GABBLE_MEDIA_STREAM (object); GabbleMediaStreamPrivate *priv = self->priv; g_free (priv->object_path); g_free (priv->nat_traversal); /* FIXME: use correct macro when available */ if (priv->stun_servers != NULL) g_boxed_free (tp_type_dbus_array_su (), priv->stun_servers); if (priv->relay_info != NULL) g_boxed_free (TP_ARRAY_TYPE_STRING_VARIANT_MAP_LIST, priv->relay_info); g_value_unset (&priv->local_rtp_hdrexts); g_value_unset (&priv->local_feedback_messages); g_value_unset (&priv->remote_codecs); g_value_unset (&priv->remote_rtp_hdrexts); g_value_unset (&priv->remote_feedback_messages); g_value_unset (&priv->remote_candidates); G_OBJECT_CLASS (gabble_media_stream_parent_class)->finalize (object); } /** * gabble_media_stream_codec_choice * * Implements D-Bus method CodecChoice * on interface org.freedesktop.Telepathy.Media.StreamHandler */ static void gabble_media_stream_codec_choice (TpSvcMediaStreamHandler *iface, guint codec_id, DBusGMethodInvocation *context) { tp_svc_media_stream_handler_return_from_codec_choice (context); } gboolean gabble_media_stream_error (GabbleMediaStream *self, guint errnum, const gchar *message, GError **error) { g_assert (GABBLE_IS_MEDIA_STREAM (self)); DEBUG ( "Media.StreamHandler::Error called, error %u (%s) -- emitting signal", errnum, message); g_signal_emit (self, signals[ERROR], 0, errnum, message); return TRUE; } /** * gabble_media_stream_error * * Implements D-Bus method Error * on interface org.freedesktop.Telepathy.Media.StreamHandler */ static void gabble_media_stream_error_async (TpSvcMediaStreamHandler *iface, guint errnum, const gchar *message, DBusGMethodInvocation *context) { GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface); GError *error = NULL; if (gabble_media_stream_error (self, errnum, message, &error)) { tp_svc_media_stream_handler_return_from_error (context); } else { dbus_g_method_return_error (context, error); g_error_free (error); } } /** * gabble_media_stream_hold: * * Tell streaming clients that the stream is going on hold, so they should * stop streaming and free up any resources they are currently holding * (e.g. close hardware devices); or that the stream is coming off hold, * so they should reacquire those resources. */ void gabble_media_stream_hold (GabbleMediaStream *self, gboolean hold) { tp_svc_media_stream_handler_emit_set_stream_held (self, hold); } /** * gabble_media_stream_hold_state: * * Called by streaming clients when the stream's hold state has been changed * successfully in response to SetStreamHeld. */ static void gabble_media_stream_hold_state (TpSvcMediaStreamHandler *iface, gboolean hold_state, DBusGMethodInvocation *context) { GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface); GabbleMediaStreamPrivate *priv = self->priv; DEBUG ("%p: %s", self, hold_state ? "held" : "unheld"); priv->local_hold = hold_state; g_object_notify ((GObject *) self, "local-hold"); tp_svc_media_stream_handler_return_from_hold_state (context); } /** * gabble_media_stream_unhold_failure: * * Called by streaming clients when an attempt to reacquire the necessary * hardware or software resources to unhold the stream, in response to * SetStreamHeld, has failed. */ static void gabble_media_stream_unhold_failure (TpSvcMediaStreamHandler *iface, DBusGMethodInvocation *context) { GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface); GabbleMediaStreamPrivate *priv = self->priv; DEBUG ("%p", self); priv->local_hold = TRUE; g_signal_emit (self, signals[UNHOLD_FAILED], 0); g_object_notify ((GObject *) self, "local-hold"); tp_svc_media_stream_handler_return_from_unhold_failure (context); } /** * gabble_media_stream_native_candidates_prepared * * Implements D-Bus method NativeCandidatesPrepared * on interface org.freedesktop.Telepathy.Media.StreamHandler */ static void gabble_media_stream_native_candidates_prepared (TpSvcMediaStreamHandler *iface, DBusGMethodInvocation *context) { tp_svc_media_stream_handler_return_from_native_candidates_prepared (context); } /** * gabble_media_stream_new_active_candidate_pair * * Implements D-Bus method NewActiveCandidatePair * on interface org.freedesktop.Telepathy.Media.StreamHandler */ static void gabble_media_stream_new_active_candidate_pair (TpSvcMediaStreamHandler *iface, const gchar *native_candidate_id, const gchar *remote_candidate_id, DBusGMethodInvocation *context) { DEBUG ("called (%s, %s); this is a no-op on Jingle", native_candidate_id, remote_candidate_id); tp_svc_media_stream_handler_return_from_new_active_candidate_pair (context); } /** * gabble_media_stream_new_native_candidate * * Implements D-Bus method NewNativeCandidate * on interface org.freedesktop.Telepathy.Media.StreamHandler */ static void gabble_media_stream_new_native_candidate (TpSvcMediaStreamHandler *iface, const gchar *candidate_id, const GPtrArray *transports, DBusGMethodInvocation *context) { GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface); GabbleMediaStreamPrivate *priv; WockyJingleState state; GList *li = NULL; guint i; g_assert (GABBLE_IS_MEDIA_STREAM (self)); priv = self->priv; g_object_get (priv->content->session, "state", &state, NULL); /* FIXME: maybe this should be an assertion in case the channel * isn't closed early enough right now? */ if (state > WOCKY_JINGLE_STATE_ACTIVE) { DEBUG ("state > WOCKY_JINGLE_STATE_ACTIVE, doing nothing"); tp_svc_media_stream_handler_return_from_new_native_candidate (context); return; } for (i = 0; i < transports->len; i++) { GValueArray *transport; guint component; const gchar *addr; WockyJingleCandidate *c; transport = g_ptr_array_index (transports, i); component = g_value_get_uint (g_value_array_get_nth (transport, 0)); /* Farsight 1 compatibility */ if (component == 0) component = 1; /* We understand RTP and RTCP, and silently ignore the rest */ if ((component != 1) && (component != 2)) continue; addr = g_value_get_string (g_value_array_get_nth (transport, 1)); if (!strcmp (addr, "127.0.0.1")) { DEBUG ("ignoring native localhost candidate"); continue; } c = wocky_jingle_candidate_new ( /* protocol */ g_value_get_uint (g_value_array_get_nth (transport, 3)), /* candidate type, we're relying on 1:1 candidate type mapping */ g_value_get_uint (g_value_array_get_nth (transport, 7)), /* id */ candidate_id, /* component */ component, /* address */ g_value_get_string (g_value_array_get_nth (transport, 1)), /* port */ g_value_get_uint (g_value_array_get_nth (transport, 2)), /* generation */ 0, /* preference */ (int) (g_value_get_double (g_value_array_get_nth (transport, 6)) * 65536), /* username */ g_value_get_string (g_value_array_get_nth (transport, 8)), /* password */ g_value_get_string (g_value_array_get_nth (transport, 9)), /* network */ 0); li = g_list_prepend (li, c); } if (li != NULL) wocky_jingle_content_add_candidates (priv->content, li); tp_svc_media_stream_handler_return_from_new_native_candidate (context); } static void gabble_media_stream_set_local_codecs (TpSvcMediaStreamHandler *, const GPtrArray *codecs, DBusGMethodInvocation *); /** * gabble_media_stream_ready * * Implements D-Bus method Ready * on interface org.freedesktop.Telepathy.Media.StreamHandler */ static void gabble_media_stream_ready (TpSvcMediaStreamHandler *iface, const GPtrArray *codecs, DBusGMethodInvocation *context) { GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface); GabbleMediaStreamPrivate *priv; g_assert (GABBLE_IS_MEDIA_STREAM (self)); priv = self->priv; DEBUG ("ready called"); if (priv->ready == FALSE) { g_object_set (self, "ready", TRUE, NULL); push_remote_media_description (self); push_remote_candidates (self); push_playing (self); push_sending (self); /* If a new stream is added while the call's on hold, it will have * local_hold set at construct time. So once tp-fs has called Ready(), we * should let it know this stream's on hold. */ if (priv->local_hold) gabble_media_stream_hold (self, priv->local_hold); } else { DEBUG ("Ready called twice, running plain SetLocalCodecs instead"); } /* set_local_codecs and ready return the same thing, so we can do... */ gabble_media_stream_set_local_codecs (iface, codecs, context); } static gboolean pass_local_codecs (GabbleMediaStream *stream, const GPtrArray *codecs, gboolean ready, GError **error) { GabbleMediaStreamPrivate *priv = stream->priv; guint i; WockyJingleMediaDescription *md; const GPtrArray *hdrexts; GHashTable *fbs; GError *wocky_error = NULL; DEBUG ("putting list of %d supported codecs from stream-engine into cache", codecs->len); md = wocky_jingle_media_description_new (); fbs = g_value_get_boxed (&priv->local_feedback_messages); for (i = 0; i < codecs->len; i++) { GType codec_struct_type = TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_CODEC; GValue codec = { 0, }; guint id, clock_rate, channels; gchar *name; GHashTable *params; WockyJingleCodec *c; GValueArray *fb_codec; g_value_init (&codec, codec_struct_type); g_value_set_static_boxed (&codec, g_ptr_array_index (codecs, i)); dbus_g_type_struct_get (&codec, 0, &id, 1, &name, 3, &clock_rate, 4, &channels, 5, ¶ms, G_MAXUINT); c = jingle_media_rtp_codec_new (id, name, clock_rate, channels, params); if (fbs != NULL) { fb_codec = g_hash_table_lookup (fbs, GUINT_TO_POINTER (id)); if (fb_codec != NULL) { if (G_VALUE_HOLDS_UINT ( g_value_array_get_nth (fb_codec, 0)) && G_VALUE_TYPE (g_value_array_get_nth (fb_codec, 1)) == TP_ARRAY_TYPE_RTCP_FEEDBACK_MESSAGE_LIST) { GValue *val; const GPtrArray *fb_array; guint j; val = g_value_array_get_nth (fb_codec, 0); c->trr_int = g_value_get_uint (val); val = g_value_array_get_nth (fb_codec, 1); fb_array = g_value_get_boxed (val); for (j = 0; j < fb_array->len; j++) { GValueArray *message = g_ptr_array_index (fb_array, j); const gchar *type; const gchar *subtype; val = g_value_array_get_nth (message, 0); type = g_value_get_string (val); val = g_value_array_get_nth (message, 1); subtype = g_value_get_string (val); c->feedback_msgs = g_list_append (c->feedback_msgs, wocky_jingle_feedback_message_new (type, subtype)); } } } } DEBUG ("adding codec %s (%u %u %u)", c->name, c->id, c->clockrate, c->channels); md->codecs = g_list_append (md->codecs, c); g_free (name); g_hash_table_unref (params); } if (fbs != NULL) g_value_reset (&priv->local_feedback_messages); hdrexts = g_value_get_boxed (&priv->local_rtp_hdrexts); if (hdrexts != NULL) { gboolean have_initiator = FALSE; gboolean initiated_by_us; for (i = 0; i < hdrexts->len; i++) { GValueArray *hdrext; guint id; guint direction; WockyJingleContentSenders senders; gchar *uri; gchar *params; hdrext = g_ptr_array_index (hdrexts, i); g_assert (hdrext); g_assert (hdrext->n_values == 4); g_assert (G_VALUE_HOLDS_UINT (g_value_array_get_nth (hdrext, 0))); g_assert (G_VALUE_HOLDS_UINT (g_value_array_get_nth (hdrext, 1))); g_assert (G_VALUE_HOLDS_STRING (g_value_array_get_nth (hdrext, 2))); g_assert (G_VALUE_HOLDS_STRING (g_value_array_get_nth (hdrext, 3))); tp_value_array_unpack (hdrext, 4, &id, &direction, &uri, ¶ms); if (!have_initiator) { g_object_get (priv->content->session, "local-initiator", &initiated_by_us, NULL); have_initiator = TRUE; } switch (direction) { case TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL: senders = WOCKY_JINGLE_CONTENT_SENDERS_BOTH; break; case TP_MEDIA_STREAM_DIRECTION_NONE: senders = WOCKY_JINGLE_CONTENT_SENDERS_NONE; break; case TP_MEDIA_STREAM_DIRECTION_SEND: senders = initiated_by_us ? WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR : WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER; break; case TP_MEDIA_STREAM_DIRECTION_RECEIVE: senders = initiated_by_us ? WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER : WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR; break; default: g_assert_not_reached (); } md->hdrexts = g_list_append (md->hdrexts, wocky_jingle_rtp_header_extension_new (id, senders, uri)); } /* Can only be used once */ g_value_reset (&priv->local_rtp_hdrexts); } wocky_jingle_media_description_simplify (md); if (jingle_media_rtp_set_local_media_description ( WOCKY_JINGLE_MEDIA_RTP (priv->content), md, ready, &wocky_error)) return TRUE; g_set_error_literal (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, wocky_error->message); g_clear_error (&wocky_error); return FALSE; } /** * gabble_media_stream_set_local_codecs * * Implements D-Bus method SetLocalCodecs * on interface org.freedesktop.Telepathy.Media.StreamHandler */ static void gabble_media_stream_set_local_codecs (TpSvcMediaStreamHandler *iface, const GPtrArray *codecs, DBusGMethodInvocation *context) { GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface); GabbleMediaStreamPrivate *priv = self->priv; GError *error = NULL; DEBUG ("called"); if (codecs->len == 0) goto done; priv->local_codecs_set = TRUE; if (wocky_jingle_content_is_created_by_us (self->priv->content)) { if (!pass_local_codecs (self, codecs, self->priv->created_locally, &error)) { DEBUG ("failed: %s", error->message); dbus_g_method_return_error (context, error); g_error_free (error); return; } } else { DEBUG ("ignoring local codecs, waiting for codec intersection"); } done: tp_svc_media_stream_handler_return_from_set_local_codecs (context); } /** * gabble_media_stream_stream_state * * Implements D-Bus method StreamState * on interface org.freedesktop.Telepathy.Media.StreamHandler */ static void gabble_media_stream_stream_state (TpSvcMediaStreamHandler *iface, guint connection_state, DBusGMethodInvocation *context) { GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface); GabbleMediaStreamPrivate *priv = self->priv; WockyJingleTransportState ts = WOCKY_JINGLE_TRANSPORT_STATE_DISCONNECTED; switch (connection_state) { case TP_MEDIA_STREAM_STATE_DISCONNECTED: ts = WOCKY_JINGLE_TRANSPORT_STATE_DISCONNECTED; break; case TP_MEDIA_STREAM_STATE_CONNECTING: ts = WOCKY_JINGLE_TRANSPORT_STATE_CONNECTING; break; case TP_MEDIA_STREAM_STATE_CONNECTED: ts = WOCKY_JINGLE_TRANSPORT_STATE_CONNECTED; break; default: DEBUG ("ignoring unknown connection state %u", connection_state); goto OUT; } g_object_set (self, "connection-state", connection_state, NULL); wocky_jingle_content_set_transport_state (priv->content, ts); OUT: tp_svc_media_stream_handler_return_from_stream_state (context); } /** * gabble_media_stream_supported_codecs * * Implements D-Bus method SupportedCodecs * on interface org.freedesktop.Telepathy.Media.StreamHandler */ static void gabble_media_stream_supported_codecs (TpSvcMediaStreamHandler *iface, const GPtrArray *codecs, DBusGMethodInvocation *context) { GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface); GabbleMediaStreamPrivate *priv = self->priv; GError *error = NULL; DEBUG ("called"); if (codecs->len == 0) { GError e = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "SupportedCodecs must have a non-empty list of codecs" }; dbus_g_method_return_error (context, &e); return; } priv->local_codecs_set = TRUE; if (priv->awaiting_intersection) { if (!pass_local_codecs (self, codecs, TRUE, &error)) { DEBUG ("failed: %s", error->message); dbus_g_method_return_error (context, error); g_error_free (error); return; } priv->awaiting_intersection = FALSE; } else { /* If we created the stream, we don't need to send the intersection. If * we didn't create it, but have already sent the intersection once, we * don't need to send it again. In either case, extra calls to * SupportedCodecs are in response to an incoming description-info, which * can only change parameters and which XEP-0167 §10 says is purely * advisory. */ DEBUG ("we already sent, or don't need to send, our codecs"); } tp_svc_media_stream_handler_return_from_supported_codecs (context); } /** * gabble_media_stream_codecs_updated * * Implements D-Bus method CodecsUpdated * on interface org.freedesktop.Telepathy.Media.StreamHandler */ static void gabble_media_stream_codecs_updated (TpSvcMediaStreamHandler *iface, const GPtrArray *codecs, DBusGMethodInvocation *context) { GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface); GError *error = NULL; if (!self->priv->local_codecs_set) { GError e = { TP_ERROR, TP_ERROR_NOT_AVAILABLE, "CodecsUpdated may only be called once an initial set of codecs " "has been set" }; dbus_g_method_return_error (context, &e); return; } if (self->priv->awaiting_intersection) { /* When awaiting an intersection the initial set of codecs should be set * by calling SupportedCodecs as that is the canonical set of codecs, * updates are only meaningful afterwards */ tp_svc_media_stream_handler_return_from_codecs_updated (context); return; } if (pass_local_codecs (self, codecs, self->priv->created_locally, &error)) { tp_svc_media_stream_handler_return_from_codecs_updated (context); } else { DEBUG ("failed: %s", error->message); dbus_g_method_return_error (context, error); g_error_free (error); } } /** * gabble_media_stream_supported_header_extensions * * Implements D-Bus method SupportedHeaderExtensions * on interface org.freedesktop.Telepathy.Media.StreamHandler */ static void gabble_media_stream_supported_header_extensions (TpSvcMediaStreamHandler *iface, const GPtrArray *hdrexts, DBusGMethodInvocation *context) { GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface); g_value_set_boxed (&self->priv->local_rtp_hdrexts, hdrexts); tp_svc_media_stream_handler_return_from_supported_header_extensions (context); } /** * gabble_media_stream_supported_feedback_messages * * Implements D-Bus method SupportedFeedbackMessages * on interface org.freedesktop.Telepathy.Media.StreamHandler */ static void gabble_media_stream_supported_feedback_messages (TpSvcMediaStreamHandler *iface, GHashTable *messages, DBusGMethodInvocation *context) { GabbleMediaStream *self = GABBLE_MEDIA_STREAM (iface); g_value_set_boxed (&self->priv->local_feedback_messages, messages); tp_svc_media_stream_handler_return_from_supported_feedback_messages (context); } void gabble_media_stream_close (GabbleMediaStream *stream) { GabbleMediaStreamPrivate *priv; g_assert (GABBLE_IS_MEDIA_STREAM (stream)); priv = stream->priv; if (!priv->closed) { priv->closed = TRUE; tp_svc_media_stream_handler_emit_close (stream); } } static void insert_feedback_message (WockyJingleFeedbackMessage *fb, GPtrArray *fb_msgs) { GValueArray *msg; msg = tp_value_array_build (3, G_TYPE_STRING, fb->type, G_TYPE_STRING, fb->subtype, G_TYPE_STRING, "", G_TYPE_INVALID); g_ptr_array_add (fb_msgs, msg); } static void new_remote_media_description_cb (WockyJingleContent *content, WockyJingleMediaDescription *md, GabbleMediaStream *stream) { GabbleMediaStreamPrivate *priv; GList *li; GPtrArray *codecs; GPtrArray *hdrexts; GHashTable *fbs; GType codec_struct_type = TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_CODEC; gboolean have_initiator = FALSE; gboolean initiated_by_us; DEBUG ("called"); g_assert (GABBLE_IS_MEDIA_STREAM (stream)); priv = stream->priv; codecs = g_value_get_boxed (&priv->remote_codecs); if (codecs->len != 0) { /* We already had some codecs; let's free the old list and make a new, * empty one to fill in. */ g_value_reset (&priv->remote_codecs); codecs = dbus_g_type_specialized_construct ( TP_ARRAY_TYPE_MEDIA_STREAM_HANDLER_CODEC_LIST); g_value_take_boxed (&priv->remote_codecs, codecs); } hdrexts = g_value_get_boxed (&priv->remote_rtp_hdrexts); if (hdrexts->len != 0) { /* We already had some rtp hdrext; let's free the old list and make a new, * empty one to fill in. */ g_value_reset (&priv->remote_rtp_hdrexts); hdrexts = dbus_g_type_specialized_construct ( TP_ARRAY_TYPE_RTP_HEADER_EXTENSIONS_LIST); g_value_take_boxed (&priv->remote_rtp_hdrexts, hdrexts); } fbs = g_value_get_boxed (&priv->remote_feedback_messages); if (g_hash_table_size (fbs) != 0) { /* We already had some rtp hdrext; let's free the old list and make a new, * empty one to fill in. */ g_value_reset (&priv->remote_feedback_messages); fbs = dbus_g_type_specialized_construct ( TP_HASH_TYPE_RTCP_FEEDBACK_MESSAGE_MAP); g_value_take_boxed (&priv->remote_feedback_messages, fbs); } for (li = md->codecs; li; li = li->next) { GValue codec = { 0, }; WockyJingleCodec *c = li->data; g_value_init (&codec, codec_struct_type); g_value_take_boxed (&codec, dbus_g_type_specialized_construct (codec_struct_type)); DEBUG ("new remote %s codec: %u '%s' %u %u %u", priv->media_type == TP_MEDIA_STREAM_TYPE_AUDIO ? "audio" : "video", c->id, c->name, priv->media_type, c->clockrate, c->channels); dbus_g_type_struct_set (&codec, 0, c->id, 1, c->name, 2, priv->media_type, 3, c->clockrate, 4, c->channels, 5, c->params, G_MAXUINT); if (md->trr_int != G_MAXUINT || c->trr_int != G_MAXUINT || md->feedback_msgs != NULL || c->feedback_msgs != NULL) { GValueArray *fb_msg_props; guint trr_int; GPtrArray *fb_msgs = g_ptr_array_new (); if (c->trr_int != G_MAXUINT) trr_int = c->trr_int; else trr_int = md->trr_int; g_list_foreach (md->feedback_msgs, (GFunc) insert_feedback_message, fb_msgs); g_list_foreach (c->feedback_msgs, (GFunc) insert_feedback_message, fb_msgs); fb_msg_props = tp_value_array_build (2, G_TYPE_UINT, trr_int, TP_ARRAY_TYPE_RTCP_FEEDBACK_MESSAGE_LIST, fb_msgs, G_TYPE_INVALID); g_boxed_free (TP_ARRAY_TYPE_RTCP_FEEDBACK_MESSAGE_LIST, fb_msgs); g_hash_table_insert (fbs, GUINT_TO_POINTER (c->id), fb_msg_props); } g_ptr_array_add (codecs, g_value_get_boxed (&codec)); } for (li = md->hdrexts; li; li = li->next) { WockyJingleRtpHeaderExtension *h = li->data; TpMediaStreamDirection direction; if (!have_initiator) { g_object_get (priv->content->session, "local-initiator", &initiated_by_us, NULL); have_initiator = TRUE; } switch (h->senders) { case WOCKY_JINGLE_CONTENT_SENDERS_BOTH: direction = TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL; break; case WOCKY_JINGLE_CONTENT_SENDERS_NONE: direction = TP_MEDIA_STREAM_DIRECTION_NONE; break; case WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR: direction = initiated_by_us ? TP_MEDIA_STREAM_DIRECTION_SEND : TP_MEDIA_STREAM_DIRECTION_RECEIVE; break; case WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER: direction = initiated_by_us ? TP_MEDIA_STREAM_DIRECTION_RECEIVE : TP_MEDIA_STREAM_DIRECTION_SEND; break; default: g_assert_not_reached (); } DEBUG ("new RTP header ext : %u %s", h->id, h->uri); g_ptr_array_add (hdrexts, tp_value_array_build (4, G_TYPE_UINT, h->id, G_TYPE_UINT, direction, G_TYPE_STRING, h->uri, G_TYPE_STRING, "", /* No protocol defines parameters */ G_TYPE_INVALID)); } DEBUG ("pushing remote codecs"); push_remote_media_description (stream); } static void push_remote_media_description (GabbleMediaStream *stream) { GabbleMediaStreamPrivate *priv; GPtrArray *codecs; GPtrArray *hdrexts; GHashTable *fbs; g_assert (GABBLE_IS_MEDIA_STREAM (stream)); priv = stream->priv; if (!priv->ready) return; codecs = g_value_get_boxed (&priv->remote_codecs); if (codecs->len == 0) return; hdrexts = g_value_get_boxed (&priv->remote_rtp_hdrexts); fbs = g_value_get_boxed (&priv->remote_feedback_messages); DEBUG ("passing %d remote codecs to stream-engine", codecs->len); tp_svc_media_stream_handler_emit_set_remote_header_extensions (stream, hdrexts); tp_svc_media_stream_handler_emit_set_remote_feedback_messages (stream, fbs); tp_svc_media_stream_handler_emit_set_remote_codecs (stream, codecs); } static void new_remote_candidates_cb (WockyJingleContent *content, GList *clist, GabbleMediaStream *stream) { GabbleMediaStreamPrivate *priv = stream->priv; GPtrArray *candidates; GList *li; candidates = g_value_get_boxed (&priv->remote_candidates); DEBUG ("got new remote candidates"); for (li = clist; li; li = li->next) { gchar *candidate_id; GValue candidate = { 0, }; GPtrArray *transports; GValue transport = { 0, }; WockyJingleCandidate *c = li->data; GType transport_struct_type = TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_TRANSPORT; GType candidate_struct_type = TP_STRUCT_TYPE_MEDIA_STREAM_HANDLER_CANDIDATE; g_value_init (&transport, transport_struct_type); g_value_take_boxed (&transport, dbus_g_type_specialized_construct (transport_struct_type)); dbus_g_type_struct_set (&transport, 0, c->component, 1, c->address, 2, c->port, 3, c->protocol == WOCKY_JINGLE_TRANSPORT_PROTOCOL_UDP ? 0 : 1, 4, "RTP", 5, "AVP", 6, (gdouble) (c->preference / 65536.0), 7, c->type, /* FIXME: we're relying on 1:1 tp/jingle candidate type enums */ 8, c->username, 9, c->password, G_MAXUINT); transports = g_ptr_array_sized_new (1); g_ptr_array_add (transports, g_value_get_boxed (&transport)); g_value_init (&candidate, candidate_struct_type); g_value_take_boxed (&candidate, dbus_g_type_specialized_construct (candidate_struct_type)); if (c->id == NULL) /* FIXME: is this naming scheme sensible? */ candidate_id = g_strdup_printf ("R%d", ++priv->remote_candidate_count); else candidate_id = c->id; dbus_g_type_struct_set (&candidate, 0, candidate_id, 1, transports, G_MAXUINT); g_free (candidate_id); g_value_unset (&transport); g_ptr_array_unref (transports); g_ptr_array_add (candidates, g_value_get_boxed (&candidate)); } push_remote_candidates (stream); } static void content_state_changed_cb (WockyJingleContent *c, GParamSpec *pspec, GabbleMediaStream *stream) { GabbleMediaStreamPrivate *priv = stream->priv; WockyJingleContentState state; g_object_get (c, "state", &state, NULL); DEBUG ("called"); switch (state) { case WOCKY_JINGLE_CONTENT_STATE_ACKNOWLEDGED: /* connected stream means we can play, but sending is determined * by content senders (in update_senders) */ stream->playing = TRUE; update_sending (stream, TRUE); push_playing (stream); push_sending (stream); break; case WOCKY_JINGLE_CONTENT_STATE_REMOVING: stream->playing = FALSE; priv->sending = FALSE; push_playing (stream); break; default: /* so gcc doesn't cry */ break; } } static void push_remote_candidates (GabbleMediaStream *stream) { GabbleMediaStreamPrivate *priv; GPtrArray *candidates; guint i; GType candidate_list_type = TP_ARRAY_TYPE_MEDIA_STREAM_HANDLER_CANDIDATE_LIST; g_assert (GABBLE_IS_MEDIA_STREAM (stream)); priv = stream->priv; candidates = g_value_get_boxed (&priv->remote_candidates); if (candidates->len == 0) return; if (!priv->ready) return; for (i = 0; i < candidates->len; i++) { GValueArray *candidate = g_ptr_array_index (candidates, i); const gchar *candidate_id; const GPtrArray *transports; candidate_id = g_value_get_string (g_value_array_get_nth (candidate, 0)); transports = g_value_get_boxed (g_value_array_get_nth (candidate, 1)); DEBUG ("passing 1 remote candidate to stream engine: %s", candidate_id); tp_svc_media_stream_handler_emit_add_remote_candidate ( stream, candidate_id, transports); } g_value_take_boxed (&priv->remote_candidates, dbus_g_type_specialized_construct (candidate_list_type)); } static void push_playing (GabbleMediaStream *stream) { GabbleMediaStreamPrivate *priv; g_assert (GABBLE_IS_MEDIA_STREAM (stream)); priv = stream->priv; if (!priv->ready) return; DEBUG ("stream %s emitting SetStreamPlaying(%s)", stream->name, stream->playing ? "true" : "false"); tp_svc_media_stream_handler_emit_set_stream_playing ( stream, stream->playing); } static void push_sending (GabbleMediaStream *stream) { GabbleMediaStreamPrivate *priv; gboolean emit; g_assert (GABBLE_IS_MEDIA_STREAM (stream)); priv = stream->priv; if (!priv->ready) return; emit = (priv->sending && !(priv->on_hold)); DEBUG ("stream %s emitting SetStreamSending(%s); sending=%s, on_hold=%s", stream->name, emit ? "true" : "false", priv->sending ? "true" : "false", priv->on_hold ? "true" : "false"); tp_svc_media_stream_handler_emit_set_stream_sending ( stream, emit); } static void update_direction (GabbleMediaStream *stream, WockyJingleContent *c) { CombinedStreamDirection new_combined_dir; TpMediaStreamDirection requested_dir, current_dir; TpMediaStreamPendingSend pending_send; WockyJingleContentSenders senders; gboolean local_initiator; DEBUG ("called"); g_object_get (c, "senders", &senders, NULL); g_object_get (c->session, "local-initiator", &local_initiator, NULL); switch (senders) { case WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR: requested_dir = local_initiator ? TP_MEDIA_STREAM_DIRECTION_SEND : TP_MEDIA_STREAM_DIRECTION_RECEIVE; break; case WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER: requested_dir = local_initiator ? TP_MEDIA_STREAM_DIRECTION_RECEIVE : TP_MEDIA_STREAM_DIRECTION_SEND; break; case WOCKY_JINGLE_CONTENT_SENDERS_BOTH: requested_dir = TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL; break; default: requested_dir = TP_MEDIA_STREAM_DIRECTION_NONE; } current_dir = COMBINED_DIRECTION_GET_DIRECTION (stream->combined_direction); pending_send = COMBINED_DIRECTION_GET_PENDING_SEND (stream->combined_direction); /* if local sending has been added, remove it, * and set the pending local send flag */ if (((current_dir & TP_MEDIA_STREAM_DIRECTION_SEND) == 0) && ((requested_dir & TP_MEDIA_STREAM_DIRECTION_SEND) != 0)) { DEBUG ("setting pending local send flag"); requested_dir &= ~TP_MEDIA_STREAM_DIRECTION_SEND; pending_send |= TP_MEDIA_STREAM_PENDING_LOCAL_SEND; } /* make any necessary changes */ new_combined_dir = MAKE_COMBINED_DIRECTION (requested_dir, pending_send); if (new_combined_dir != stream->combined_direction) { g_object_set (stream, "combined-direction", new_combined_dir, NULL); update_sending (stream, FALSE); } } static void content_senders_changed_cb (WockyJingleContent *c, GParamSpec *pspec, GabbleMediaStream *stream) { update_direction (stream, c); } static void remote_state_changed_cb (WockyJingleSession *session, GabbleMediaStream *stream) { GabbleMediaStreamPrivate *priv = stream->priv; gboolean old_hold = priv->on_hold; priv->on_hold = wocky_jingle_session_get_remote_hold (session); if (old_hold != priv->on_hold) push_sending (stream); } static void content_removed_cb (WockyJingleContent *content, GabbleMediaStream *stream) { gabble_media_stream_close (stream); } gboolean gabble_media_stream_change_direction (GabbleMediaStream *stream, guint requested_dir, GError **error) { GabbleMediaStreamPrivate *priv = stream->priv; CombinedStreamDirection new_combined_dir; TpMediaStreamDirection current_dir; TpMediaStreamPendingSend pending_send; WockyJingleContentSenders senders; gboolean local_initiator; current_dir = COMBINED_DIRECTION_GET_DIRECTION (stream->combined_direction); pending_send = COMBINED_DIRECTION_GET_PENDING_SEND (stream->combined_direction); /* if we're awaiting a local decision on sending... */ if ((pending_send & TP_MEDIA_STREAM_PENDING_LOCAL_SEND) != 0) { /* clear the flag */ pending_send &= ~TP_MEDIA_STREAM_PENDING_LOCAL_SEND; /* make our current_dir match what other end thinks (he thinks we're * bidirectional) so that we send the correct transitions */ current_dir ^= TP_MEDIA_STREAM_DIRECTION_SEND; } /* make any necessary changes */ new_combined_dir = MAKE_COMBINED_DIRECTION (requested_dir, pending_send); if (new_combined_dir != stream->combined_direction) { WockyJingleContentState state; gboolean start_sending; g_object_set (stream, "combined-direction", new_combined_dir, NULL); /* We would like to emit SetStreamSending(True) (if appropriate) only if: * - the content was locally created, or * - the user explicitly okayed the content. * This appears to be the meaning of Acknowledged. :-) */ g_object_get (stream->priv->content, "state", &state, NULL); start_sending = (state == WOCKY_JINGLE_CONTENT_STATE_ACKNOWLEDGED); update_sending (stream, start_sending); } DEBUG ("current_dir: %u, requested_dir: %u", current_dir, requested_dir); /* short-circuit sending a request if we're not asking for anything new */ if (current_dir == requested_dir) return TRUE; g_object_get (priv->content->session, "local-initiator", &local_initiator, NULL); switch (requested_dir) { case TP_MEDIA_STREAM_DIRECTION_SEND: senders = local_initiator ? WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR : WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER; break; case TP_MEDIA_STREAM_DIRECTION_RECEIVE: senders = local_initiator ? WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER : WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR; break; case TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL: senders = WOCKY_JINGLE_CONTENT_SENDERS_BOTH; break; default: g_assert_not_reached (); } if (!wocky_jingle_content_change_direction (priv->content, senders)) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "stream direction invalid for the Jingle dialect in use"); return FALSE; } return TRUE; } void gabble_media_stream_accept_pending_local_send (GabbleMediaStream *stream) { CombinedStreamDirection combined_dir = stream->combined_direction; TpMediaStreamDirection current_dir; TpMediaStreamPendingSend pending_send; current_dir = COMBINED_DIRECTION_GET_DIRECTION (combined_dir); pending_send = COMBINED_DIRECTION_GET_PENDING_SEND (combined_dir); if ((pending_send & TP_MEDIA_STREAM_PENDING_LOCAL_SEND) != 0) { DEBUG ("accepting pending local send on stream %s", stream->name); gabble_media_stream_change_direction (stream, current_dir | TP_MEDIA_STREAM_DIRECTION_SEND, NULL); } else { DEBUG ("stream %s not pending local send", stream->name); } } static void update_sending (GabbleMediaStream *stream, gboolean start_sending) { GabbleMediaStreamPrivate *priv = stream->priv; gboolean new_sending; new_sending = ((stream->combined_direction & TP_MEDIA_STREAM_DIRECTION_SEND) != 0); if (priv->sending == new_sending) return; if (new_sending && !start_sending) return; priv->sending = new_sending; push_sending (stream); } static void stream_handler_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcMediaStreamHandlerClass *klass = (TpSvcMediaStreamHandlerClass *) g_iface; #define IMPLEMENT(x,suffix) tp_svc_media_stream_handler_implement_##x (\ klass, gabble_media_stream_##x##suffix) IMPLEMENT(codec_choice,); IMPLEMENT(error,_async); IMPLEMENT(hold_state,); IMPLEMENT(native_candidates_prepared,); IMPLEMENT(new_active_candidate_pair,); IMPLEMENT(new_native_candidate,); IMPLEMENT(ready,); IMPLEMENT(set_local_codecs,); IMPLEMENT(stream_state,); IMPLEMENT(supported_codecs,); IMPLEMENT(unhold_failure,); IMPLEMENT(codecs_updated,); IMPLEMENT(supported_header_extensions,); IMPLEMENT(supported_feedback_messages,); #undef IMPLEMENT } WockyJingleMediaRtp * gabble_media_stream_get_content (GabbleMediaStream *self) { /* FIXME: we should fix this whole class up. It relies throughout on * self->priv->content actually secretly being a WockyJingleMediaRtp. */ return WOCKY_JINGLE_MEDIA_RTP (self->priv->content); } void gabble_media_stream_start_telephony_event (GabbleMediaStream *self, guchar event) { DEBUG ("stream %s: %c", self->name, tp_dtmf_event_to_char (event)); tp_svc_media_stream_handler_emit_start_telephony_event ( (TpSvcMediaStreamHandler *) self, event); } void gabble_media_stream_stop_telephony_event (GabbleMediaStream *self) { DEBUG ("stream %s", self->name); tp_svc_media_stream_handler_emit_stop_telephony_event ( (TpSvcMediaStreamHandler *) self); } void gabble_media_stream_add_dtmf_player (GabbleMediaStream *self, TpDTMFPlayer *dtmf_player) { tp_g_signal_connect_object (dtmf_player, "started-tone", G_CALLBACK (gabble_media_stream_start_telephony_event), self, G_CONNECT_SWAPPED); tp_g_signal_connect_object (dtmf_player, "stopped-tone", G_CALLBACK (gabble_media_stream_stop_telephony_event), self, G_CONNECT_SWAPPED); } telepathy-gabble-0.18.3/src/roomlist-manager.c0000664000175000017500000003064512332440117022416 0ustar00cassidycassidy00000000000000/* * roomlist-manager - ChannelManager for room lists * Copyright (C) 2006-2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "roomlist-manager.h" #include #include #include #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_MUC #include "gabble/caps-channel-manager.h" #include "connection.h" #include "debug.h" #include "namespaces.h" #include "roomlist-channel.h" #include "util.h" static void channel_manager_iface_init (gpointer, gpointer); G_DEFINE_TYPE_WITH_CODE (GabbleRoomlistManager, gabble_roomlist_manager, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER, channel_manager_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_CAPS_CHANNEL_MANAGER, NULL)); /* properties */ enum { PROP_CONNECTION = 1, LAST_PROPERTY }; struct _GabbleRoomlistManagerPrivate { GabbleConnection *conn; gulong status_changed_id; GPtrArray *channels; gboolean dispose_has_run; }; static void gabble_roomlist_manager_init (GabbleRoomlistManager *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_ROOMLIST_MANAGER, GabbleRoomlistManagerPrivate); /* In practice we probably won't have more than one room list at a time */ self->priv->channels = g_ptr_array_sized_new (2); } static void gabble_roomlist_manager_close_all (GabbleRoomlistManager *self) { DEBUG ("%p", self); if (self->priv->status_changed_id != 0) { g_signal_handler_disconnect (self->priv->conn, self->priv->status_changed_id); self->priv->status_changed_id = 0; } /* Use a temporary variable because we don't want * roomlist_channel_closed_cb to remove the channel from the ptr array a * second time */ if (self->priv->channels != NULL) { GPtrArray *tmp = self->priv->channels; guint i; self->priv->channels = NULL; for (i = 0; i < tmp->len; i++) { GabbleRoomlistChannel *channel = g_ptr_array_index (tmp, i); DEBUG ("Channel's refcount is %u before unref", G_OBJECT (channel)->ref_count); g_object_unref (channel); } g_ptr_array_unref (tmp); } } static void gabble_roomlist_manager_dispose (GObject *object) { GabbleRoomlistManager *self = GABBLE_ROOMLIST_MANAGER (object); if (self->priv->dispose_has_run) return; DEBUG ("running"); self->priv->dispose_has_run = TRUE; gabble_roomlist_manager_close_all (self); g_assert (self->priv->channels == NULL); if (G_OBJECT_CLASS (gabble_roomlist_manager_parent_class)->dispose) G_OBJECT_CLASS (gabble_roomlist_manager_parent_class)->dispose (object); } static void gabble_roomlist_manager_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleRoomlistManager *self = GABBLE_ROOMLIST_MANAGER (object); switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, self->priv->conn); break; } } static void gabble_roomlist_manager_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleRoomlistManager *self = GABBLE_ROOMLIST_MANAGER (object); switch (property_id) { case PROP_CONNECTION: g_assert (self->priv->conn == NULL); self->priv->conn = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void connection_status_changed_cb (GabbleConnection *conn, guint status, guint reason, GabbleRoomlistManager *self) { switch (status) { case TP_CONNECTION_STATUS_CONNECTING: break; case TP_CONNECTION_STATUS_CONNECTED: break; case TP_CONNECTION_STATUS_DISCONNECTED: DEBUG ("disconnected, closing room lists"); gabble_roomlist_manager_close_all (self); break; default: g_assert_not_reached (); } } static void gabble_roomlist_manager_constructed (GObject *object) { GabbleRoomlistManager *self = GABBLE_ROOMLIST_MANAGER (object); void (*chain_up) (GObject *) = G_OBJECT_CLASS (gabble_roomlist_manager_parent_class)->constructed; DEBUG ("%p", self); if (chain_up != NULL) chain_up (object); self->priv->status_changed_id = g_signal_connect (self->priv->conn, "status-changed", (GCallback) connection_status_changed_cb, object); } static void gabble_roomlist_manager_class_init (GabbleRoomlistManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GParamSpec *param_spec; g_type_class_add_private (klass, sizeof (GabbleRoomlistManagerPrivate)); object_class->constructed = gabble_roomlist_manager_constructed; object_class->dispose = gabble_roomlist_manager_dispose; object_class->get_property = gabble_roomlist_manager_get_property; object_class->set_property = gabble_roomlist_manager_set_property; param_spec = g_param_spec_object ("connection", "GabbleConnection object", "Gabble connection object that owns this room-list manager.", GABBLE_TYPE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); } static void gabble_roomlist_manager_foreach_channel (TpChannelManager *manager, TpExportableChannelFunc foreach, gpointer user_data) { GabbleRoomlistManager *self = GABBLE_ROOMLIST_MANAGER (manager); guint i; for (i = 0; i < self->priv->channels->len; i++) { TpExportableChannel *channel = TP_EXPORTABLE_CHANNEL ( g_ptr_array_index (self->priv->channels, i)); foreach (channel, user_data); } } static const gchar * const roomlist_channel_fixed_properties[] = { TP_IFACE_CHANNEL ".ChannelType", TP_IFACE_CHANNEL ".TargetHandleType", NULL }; static const gchar * const roomlist_channel_allowed_properties[] = { TP_IFACE_CHANNEL_TYPE_ROOM_LIST ".Server", NULL }; static void gabble_roomlist_manager_type_foreach_channel_class (GType type, TpChannelManagerTypeChannelClassFunc func, gpointer user_data) { GHashTable *table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free); GValue *value; value = tp_g_value_slice_new (G_TYPE_STRING); g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_ROOM_LIST); g_hash_table_insert (table, TP_IFACE_CHANNEL ".ChannelType", value); value = tp_g_value_slice_new (G_TYPE_UINT); g_value_set_uint (value, TP_HANDLE_TYPE_NONE); g_hash_table_insert (table, TP_IFACE_CHANNEL ".TargetHandleType", value); func (type, table, roomlist_channel_allowed_properties, user_data); g_hash_table_unref (table); } static void roomlist_channel_closed_cb (GabbleRoomlistChannel *channel, gpointer user_data) { GabbleRoomlistManager *self = GABBLE_ROOMLIST_MANAGER (user_data); tp_channel_manager_emit_channel_closed_for_object (self, TP_EXPORTABLE_CHANNEL (channel)); if (self->priv->channels != NULL) { g_ptr_array_remove (self->priv->channels, channel); g_object_unref (channel); } } static gboolean gabble_roomlist_manager_handle_request (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties, gboolean require_new) { GabbleRoomlistManager *self = GABBLE_ROOMLIST_MANAGER (manager); GabbleRoomlistChannel *channel = NULL; GError *error = NULL; GSList *request_tokens; const gchar *server; if (tp_strdiff (tp_asv_get_string (request_properties, TP_IFACE_CHANNEL ".ChannelType"), TP_IFACE_CHANNEL_TYPE_ROOM_LIST)) return FALSE; if (tp_asv_get_uint32 (request_properties, TP_IFACE_CHANNEL ".TargetHandleType", NULL) != 0) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "RoomList channels can't have a target handle"); goto error; } if (tp_channel_manager_asv_has_unknown_properties (request_properties, roomlist_channel_fixed_properties, roomlist_channel_allowed_properties, &error)) goto error; server = tp_asv_get_string (request_properties, TP_IFACE_CHANNEL_TYPE_ROOM_LIST ".Server"); if (server == NULL || server[0] == '\0') { server = _gabble_connection_find_conference_server (self->priv->conn); if (server == NULL) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "Unable to choose a default conference server"); goto error; } } if (!require_new) { guint i; for (i = 0; i < self->priv->channels->len; i++) { gchar *its_server; gboolean good; channel = g_ptr_array_index (self->priv->channels, i); g_object_get (channel, "conference-server", &its_server, NULL); good = !tp_strdiff (its_server, server); g_free (its_server); if (good) { tp_channel_manager_emit_request_already_satisfied (self, request_token, TP_EXPORTABLE_CHANNEL (channel)); return TRUE; } } } /* no existing channel is suitable - make a new one */ channel = _gabble_roomlist_channel_new (self->priv->conn, server); g_signal_connect (channel, "closed", (GCallback) roomlist_channel_closed_cb, self); g_ptr_array_add (self->priv->channels, channel); request_tokens = g_slist_prepend (NULL, request_token); tp_channel_manager_emit_new_channel (self, TP_EXPORTABLE_CHANNEL (channel), request_tokens); g_slist_free (request_tokens); return TRUE; error: tp_channel_manager_emit_request_failed (self, request_token, error->domain, error->code, error->message); g_error_free (error); return TRUE; } static gboolean gabble_roomlist_manager_create_channel (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties) { return gabble_roomlist_manager_handle_request (manager, request_token, request_properties, TRUE); } static gboolean gabble_roomlist_manager_request_channel (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties) { return gabble_roomlist_manager_handle_request (manager, request_token, request_properties, FALSE); } static gboolean gabble_roomlist_manager_ensure_channel (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties) { return gabble_roomlist_manager_handle_request (manager, request_token, request_properties, FALSE); } static void channel_manager_iface_init (gpointer g_iface, gpointer iface_data) { TpChannelManagerIface *iface = g_iface; iface->foreach_channel = gabble_roomlist_manager_foreach_channel; iface->type_foreach_channel_class = gabble_roomlist_manager_type_foreach_channel_class; iface->request_channel = gabble_roomlist_manager_request_channel; iface->create_channel = gabble_roomlist_manager_create_channel; iface->ensure_channel = gabble_roomlist_manager_ensure_channel; } telepathy-gabble-0.18.3/src/conn-mail-notif.c0000664000175000017500000005637712332441362022145 0ustar00cassidycassidy00000000000000/* * conn-mail-notif - Gabble mail notification interface * Copyright (C) 2009-2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* This is implementation of Gmail Notification protocol as documented at * http://code.google.com/apis/talk/jep_extensions/gmail.html * This is the only protocol supported at the moment. To add new protocol, * one would have to split the google specific parts wich are the * update_unread_mails() function and the new-mail signal on google xml * namespace. The data structure and suscription mechanism shall remain across * protocols. */ #include "config.h" #include "conn-mail-notif.h" #include #include #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_MAIL_NOTIF #include "connection.h" #include "debug.h" #include "namespaces.h" #include "util.h" /* The Google server stops pushing updates for the periode of * POLL_DURATION seconds. To ensure that MailNotification remains accurate, * we manually update every POLL_DELAY second the mail information. */ #define POLL_DELAY 5 #define POLL_DURATION 60 enum { PROP_MAIL_NOTIFICATION_FLAGS, PROP_UNREAD_MAIL_COUNT, PROP_UNREAD_MAILS, PROP_MAIL_ADDRESS, NUM_OF_PROP, }; struct _GabbleConnectionMailNotificationPrivate { gboolean interested; gchar *inbox_url; GHashTable *unread_mails; guint unread_count; guint new_mail_handler_id; guint poll_timeout_id; guint poll_count; GList *inbox_url_requests; /* list of DBusGMethodInvocation */ gboolean should_set_google_settings; }; static void update_unread_mails (GabbleConnection *conn); static void return_from_request_inbox_url (GabbleConnection *conn) { GValueArray *result = NULL; GPtrArray *empty_array = NULL; GError *error = NULL; GList *it; GabbleConnectionMailNotificationPrivate *priv = conn->mail_priv; if (priv->inbox_url != NULL && priv->inbox_url[0] == '\0') { error = g_error_new (TP_ERROR, TP_ERROR_NETWORK_ERROR, "Server did not provide base URL."); } else if (priv->inbox_url == NULL) { error = g_error_new (TP_ERROR, TP_ERROR_DISCONNECTED, "Connection was disconnected during request."); } else { empty_array = g_ptr_array_new (); result = tp_value_array_build (3, G_TYPE_STRING, priv->inbox_url, G_TYPE_UINT, TP_HTTP_METHOD_GET, TP_ARRAY_TYPE_HTTP_POST_DATA_LIST, empty_array, G_TYPE_INVALID); } it = priv->inbox_url_requests; while (it != NULL) { DBusGMethodInvocation *context = it->data; if (error != NULL) dbus_g_method_return_error (context, error); else tp_svc_connection_interface_mail_notification_return_from_request_inbox_url ( context, result); it = g_list_next (it); } if (error == NULL) { g_value_array_free (result); g_ptr_array_unref (empty_array); } else { g_error_free (error); } g_list_free (priv->inbox_url_requests); priv->inbox_url_requests = NULL; } static inline gboolean check_supported_or_dbus_return (GabbleConnection *conn, DBusGMethodInvocation *context) { TpBaseConnection *base = TP_BASE_CONNECTION (conn); if (tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTED) { GError e = { TP_ERROR, TP_ERROR_DISCONNECTED, "Not connected" }; dbus_g_method_return_error (context, &e); return TRUE; } if (!(conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_MAIL_NOTIFY)) { tp_dbus_g_method_return_not_implemented (context); return TRUE; } return FALSE; } static void gabble_mail_notification_request_inbox_url ( TpSvcConnectionInterfaceMailNotification *iface, DBusGMethodInvocation *context) { GabbleConnection *conn = GABBLE_CONNECTION (iface); GabbleConnectionMailNotificationPrivate *priv = conn->mail_priv; if (check_supported_or_dbus_return (conn, context)) return; /* TODO Make sure we don't have to authenticate again */ priv->inbox_url_requests = g_list_append (priv->inbox_url_requests, context); if (priv->inbox_url != NULL) return_from_request_inbox_url (conn); } static void gabble_mail_notification_request_mail_url ( TpSvcConnectionInterfaceMailNotification *iface, const gchar *in_id, const GValue *in_url_data, DBusGMethodInvocation *context) { GabbleConnection *conn = GABBLE_CONNECTION (iface); GabbleConnectionMailNotificationPrivate *priv = conn->mail_priv; if (check_supported_or_dbus_return (conn, context)) return; /* TODO Make sure we don't have to authenticate again */ if (priv->inbox_url != NULL && priv->inbox_url[0] != 0) { GValueArray *result; gchar *url = NULL; GPtrArray *empty_array; /* IDs are decimal on the XMPP side and hexadecimal on the wemail side. */ guint64 tid = g_ascii_strtoull (in_id, NULL, 0); url = g_strdup_printf ("%s/#inbox/%" G_GINT64_MODIFIER "x", priv->inbox_url, tid); empty_array = g_ptr_array_new (); result = tp_value_array_build (3, G_TYPE_STRING, url ? url : "", G_TYPE_UINT, TP_HTTP_METHOD_GET, TP_ARRAY_TYPE_HTTP_POST_DATA_LIST, empty_array, G_TYPE_INVALID); tp_svc_connection_interface_mail_notification_return_from_request_mail_url ( context, result); g_value_array_free (result); g_ptr_array_unref (empty_array); g_free (url); } else { GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR, "Failed to retrieve URL from server."}; dbus_g_method_return_error (context, &error); } } static gboolean sender_each (WockyNode *node, gpointer user_data) { GPtrArray *senders = user_data; if (!tp_strdiff ("1", wocky_node_get_attribute (node, "unread"))) { GValueArray *sender; const gchar *name; const gchar *address; name = wocky_node_get_attribute (node, "name"); address = wocky_node_get_attribute (node, "address"); sender = tp_value_array_build (2, G_TYPE_STRING, name ? name : "", G_TYPE_STRING, address ? address : "", G_TYPE_INVALID); g_ptr_array_add (senders, sender); } return TRUE; } static gboolean handle_senders (WockyNode *parent_node, GHashTable *mail) { gboolean dirty = FALSE; WockyNode *node; node = wocky_node_get_child (parent_node, "senders"); if (node != NULL) { GType addr_list_type = TP_ARRAY_TYPE_MAIL_ADDRESS_LIST; GPtrArray *senders, *old_senders; senders = g_ptr_array_new (); wocky_node_each_child (node, sender_each, senders); old_senders = tp_asv_get_boxed (mail, "senders", addr_list_type); if (old_senders == NULL || senders->len != old_senders->len) dirty = TRUE; tp_asv_take_boxed (mail, "senders", addr_list_type, senders); } return dirty; } static gboolean handle_subject (WockyNode *parent_node, GHashTable *mail) { gboolean dirty = FALSE; WockyNode *node; node = wocky_node_get_child (parent_node, "subject"); if (node != NULL) { if (tp_strdiff (node->content, tp_asv_get_string (mail, "subject"))) { dirty = TRUE; tp_asv_set_string (mail, "subject", node->content); } } return dirty; } static gboolean handle_snippet (WockyNode *parent_node, GHashTable *mail) { gboolean dirty = FALSE; WockyNode *node; node = wocky_node_get_child (parent_node, "snippet"); if (node != NULL) { if (tp_strdiff (node->content, tp_asv_get_string (mail, "content"))) { dirty = TRUE; tp_asv_set_boolean (mail, "truncated", TRUE); tp_asv_set_string (mail, "content", node->content); } } return dirty; } /* Structure used has user_data mail_thread_info_each callback */ typedef struct { GabbleConnection *conn; /* stolen from conn -> unread_mails, the left items in this is * represent the removed emails */ GHashTable *old_mails; GPtrArray *mails_added; } MailThreadCollector; static gboolean mail_thread_info_each (WockyNode *node, gpointer user_data) { MailThreadCollector *collector = user_data; if (!tp_strdiff (node->name, "mail-thread-info")) { GHashTable *mail = NULL; const gchar *val_str; gchar *tid; gboolean dirty = FALSE; val_str = wocky_node_get_attribute (node, "tid"); /* We absolutly need an ID */ if (val_str == NULL) return TRUE; tid = g_strdup (val_str); if (collector->old_mails != NULL) { mail = g_hash_table_lookup (collector->old_mails, tid); g_hash_table_steal (collector->old_mails, tid); } if (mail == NULL) { mail = tp_asv_new ("id", G_TYPE_STRING, tid, "url-data", G_TYPE_STRING, "", NULL); dirty = TRUE; } val_str = wocky_node_get_attribute (node, "date"); if (val_str != NULL) { gint64 date; date = (g_ascii_strtoll (val_str, NULL, 0) / 1000l); if (date != tp_asv_get_int64 (mail, "received-timestamp", NULL)) dirty = TRUE; tp_asv_set_int64 (mail, "received-timestamp", date); } if (handle_senders (node, mail)) dirty = TRUE; if (handle_subject (node, mail)) dirty = TRUE; if (handle_snippet (node, mail)) dirty = TRUE; /* gives tid ownership to unread_mails hash table */ g_hash_table_insert (collector->conn->mail_priv->unread_mails, tid, mail); if (dirty) g_ptr_array_add (collector->mails_added, mail); } return TRUE; } static void store_unread_mails (GabbleConnection *conn, WockyNode *mailbox) { GabbleConnectionMailNotificationPrivate *priv = conn->mail_priv; GHashTableIter iter; GPtrArray *mails_removed; MailThreadCollector collector; const gchar *url, *unread_count; collector.conn = conn; collector.old_mails = priv->unread_mails; priv->unread_mails = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_hash_table_unref); collector.mails_added = g_ptr_array_new (); url = wocky_node_get_attribute (mailbox, "url"); g_free (priv->inbox_url); /* Use empty string to differentiate pending request from server failing to provide an URL.*/ if (url != NULL) priv->inbox_url = g_strdup (url); else priv->inbox_url = g_strdup (""); /* Store new mails */ wocky_node_each_child (mailbox, mail_thread_info_each, &collector); /* Generate the list of removed thread IDs */ mails_removed = g_ptr_array_new_with_free_func (g_free); if (collector.old_mails != NULL) { gpointer key; g_hash_table_iter_init (&iter, collector.old_mails); while (g_hash_table_iter_next (&iter, &key, NULL)) { gchar *tid = key; g_ptr_array_add (mails_removed, g_strdup (tid)); } g_hash_table_unref (collector.old_mails); } g_ptr_array_add (mails_removed, NULL); unread_count = wocky_node_get_attribute (mailbox, "total-matched"); if (unread_count != NULL) priv->unread_count = (guint)g_ascii_strtoll (unread_count, NULL, 0); else priv->unread_count = g_hash_table_size (priv->unread_mails); tp_svc_connection_interface_mail_notification_emit_unread_mails_changed ( conn, priv->unread_count, collector.mails_added, (const char **)mails_removed->pdata); g_ptr_array_unref (collector.mails_added); g_ptr_array_unref (mails_removed); } static void set_settings_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; WockyPorter *porter = WOCKY_PORTER (source_object); WockyStanza *reply = wocky_porter_send_iq_finish (porter, res, &error); if (reply == NULL || wocky_stanza_extract_errors (reply, NULL, &error, NULL, NULL)) { DEBUG ("Failed to set google user settings: %s", error->message); g_error_free (error); } tp_clear_object (&reply); } static void query_unread_mails_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; WockyPorter *porter = WOCKY_PORTER (source_object); WockyStanza *reply = wocky_porter_send_iq_finish (porter, res, &error); GabbleConnection *conn = GABBLE_CONNECTION (user_data); if (reply == NULL || wocky_stanza_extract_errors (reply, NULL, &error, NULL, NULL)) { DEBUG ("Failed retreive unread emails information: %s", error->message); g_error_free (error); } else if (conn->mail_priv->interested) { WockyNode *node = wocky_node_get_child ( wocky_stanza_get_top_node (reply), "mailbox"); DEBUG ("Got unread mail details"); if (node != NULL) store_unread_mails (conn, node); } /* else we no longer care about unread mail, so ignore it */ tp_clear_object (&reply); return_from_request_inbox_url (conn); } static void update_unread_mails (GabbleConnection *conn) { TpBaseConnection *base = TP_BASE_CONNECTION (conn); WockyStanza *query; WockyPorter *porter = wocky_session_get_porter (conn->session); if (tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTED) return; if (!(conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_MAIL_NOTIFY)) return; DEBUG ("Updating unread mails information"); query = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, NULL, '(', "query", ':', NS_GOOGLE_MAIL_NOTIFY, ')', NULL); wocky_porter_send_iq_async (porter, query, NULL, query_unread_mails_cb, conn); g_object_unref (query); } static gboolean poll_unread_mails_cb (gpointer user_data) { GabbleConnection *conn = GABBLE_CONNECTION (user_data); GabbleConnectionMailNotificationPrivate *priv = conn->mail_priv; if (priv->poll_count * POLL_DELAY >= POLL_DURATION) { DEBUG ("%i seconds since , stopping polling", priv->poll_count * POLL_DELAY); priv->poll_timeout_id = 0; priv->poll_count = 0; return FALSE; } priv->poll_count++; /* When no subscriber, keep counting time, but don't actually update the * data since nobody would care about it */ if (priv->interested) { update_unread_mails (conn); DEBUG ("%i seconds since , still polling", priv->poll_count * POLL_DELAY); } return TRUE; } static gboolean new_mail_handler (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { GabbleConnection *conn = GABBLE_CONNECTION (user_data); if (conn->mail_priv->interested) { DEBUG ("Got Google notification"); update_unread_mails (conn); conn->mail_priv->poll_count = 0; if (conn->mail_priv->poll_timeout_id == 0) { DEBUG ("Starting to poll mail for next %i seconds", POLL_DURATION); conn->mail_priv->poll_timeout_id = g_timeout_add_seconds ( POLL_DELAY, (GSourceFunc) poll_unread_mails_cb, conn); } } return TRUE; } /* Make sure google knows we want mail notifications. According to * Google clients should set 'mailnotifications' to true when needed * but never to false, for compatibility reasons: * https://code.google.com/apis/talk/jep_extensions/usersettings.html#3 */ static void ensure_google_settings (GabbleConnection *self) { TpBaseConnection *base = TP_BASE_CONNECTION (self); WockyStanza *query; WockyPorter *porter; if (!self->mail_priv->should_set_google_settings) return; if (tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTED) return; porter = wocky_session_get_porter (self->session); query = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL, '@', "id", "user-setting-3", '(', "usersetting", ':', NS_GOOGLE_SETTING, '(', "mailnotifications", '@', "value", "true", ')', ')', NULL); wocky_porter_send_iq_async (porter, query, NULL, set_settings_cb, self); self->mail_priv->should_set_google_settings = FALSE; g_object_unref (query); } static void connection_status_changed (GabbleConnection *conn, TpConnectionStatus status, TpConnectionStatusReason reason, gpointer user_data) { if (status == TP_CONNECTION_STATUS_CONNECTED && (conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_MAIL_NOTIFY)) { DEBUG ("Connected, registering Google 'new-mail' notification"); conn->mail_priv->new_mail_handler_id = wocky_c2s_porter_register_handler_from_server ( WOCKY_C2S_PORTER (wocky_session_get_porter (conn->session)), WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, new_mail_handler, conn, '(', "new-mail", ':', NS_GOOGLE_MAIL_NOTIFY, ')', NULL); if (conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_SETTING) conn->mail_priv->should_set_google_settings = TRUE; if (conn->mail_priv->interested) { DEBUG ("Someone is already interested in MailNotification"); update_unread_mails (conn); ensure_google_settings (conn); } } } /* called on transition from 0 to 1 interested clients */ static void mail_clients_interested_cb (GabbleConnection *self, const gchar *token G_GNUC_UNUSED, gpointer nil G_GNUC_UNUSED) { DEBUG ("The first client is interested"); self->mail_priv->interested = TRUE; update_unread_mails (self); ensure_google_settings (self); } /* called on transition from 1 to 0 interested clients */ static void mail_clients_uninterested_cb (GabbleConnection *self, const gchar *token G_GNUC_UNUSED, gpointer nil G_GNUC_UNUSED) { DEBUG ("All clients lost interest, cleaning up"); self->mail_priv->interested = FALSE; self->mail_priv->unread_count = 0; tp_clear_pointer (&self->mail_priv->inbox_url, g_free); return_from_request_inbox_url (self); tp_clear_pointer (&self->mail_priv->unread_mails, g_hash_table_unref); } void conn_mail_notif_init (GabbleConnection *conn) { conn->mail_priv = g_slice_new0 (GabbleConnectionMailNotificationPrivate); g_signal_connect (conn, "status-changed", G_CALLBACK (connection_status_changed), conn); g_signal_connect (conn, "clients-interested::" TP_IFACE_CONNECTION_INTERFACE_MAIL_NOTIFICATION, G_CALLBACK (mail_clients_interested_cb), NULL); g_signal_connect (conn, "clients-uninterested::" TP_IFACE_CONNECTION_INTERFACE_MAIL_NOTIFICATION, G_CALLBACK (mail_clients_uninterested_cb), NULL); } void conn_mail_notif_dispose (GabbleConnection *conn) { GabbleConnectionMailNotificationPrivate *priv = conn->mail_priv; if (priv == NULL) return; tp_clear_pointer (&priv->inbox_url, g_free); return_from_request_inbox_url (conn); tp_clear_pointer (&priv->unread_mails, g_hash_table_unref); priv->unread_count = 0; if (priv->new_mail_handler_id != 0) { WockyPorter *porter = wocky_session_get_porter (conn->session); wocky_porter_unregister_handler (porter, priv->new_mail_handler_id); priv->new_mail_handler_id = 0; } if (priv->poll_timeout_id != 0) g_source_remove (priv->poll_timeout_id); g_slice_free (GabbleConnectionMailNotificationPrivate, priv); conn->mail_priv = NULL; } void conn_mail_notif_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcConnectionInterfaceMailNotificationClass *klass = g_iface; #define IMPLEMENT(x) tp_svc_connection_interface_mail_notification_implement_##x (\ klass, gabble_mail_notification_##x) IMPLEMENT (request_inbox_url); IMPLEMENT (request_mail_url); #undef IMPLEMENT } static GPtrArray * get_unread_mails (GabbleConnection *conn) { GabbleConnectionMailNotificationPrivate *priv = conn->mail_priv; GPtrArray *mails = g_ptr_array_new (); GHashTableIter iter; gpointer value; if (priv->unread_mails != NULL) { g_hash_table_iter_init (&iter, priv->unread_mails); while (g_hash_table_iter_next (&iter, NULL, &value)) { GHashTable *mail = value; g_ptr_array_add (mails, mail); } } return mails; } void conn_mail_notif_properties_getter (GObject *object, GQuark interface, GQuark name, GValue *value, gpointer getter_data) { static GQuark prop_quarks[NUM_OF_PROP] = {0}; GabbleConnection *conn = GABBLE_CONNECTION (object); GabbleConnectionMailNotificationPrivate *priv = conn->mail_priv; if (G_UNLIKELY (prop_quarks[0] == 0)) { prop_quarks[PROP_MAIL_NOTIFICATION_FLAGS] = g_quark_from_static_string ("MailNotificationFlags"); prop_quarks[PROP_UNREAD_MAIL_COUNT] = g_quark_from_static_string ("UnreadMailCount"); prop_quarks[PROP_UNREAD_MAILS] = g_quark_from_static_string ("UnreadMails"); prop_quarks[PROP_MAIL_ADDRESS] = g_quark_from_static_string ("MailAddress"); } DEBUG ("MailNotification get property %s", g_quark_to_string (name)); if (name == prop_quarks[PROP_MAIL_NOTIFICATION_FLAGS]) { if (conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_MAIL_NOTIFY) g_value_set_uint (value, TP_MAIL_NOTIFICATION_FLAG_SUPPORTS_UNREAD_MAIL_COUNT | TP_MAIL_NOTIFICATION_FLAG_SUPPORTS_UNREAD_MAILS | TP_MAIL_NOTIFICATION_FLAG_SUPPORTS_REQUEST_INBOX_URL | TP_MAIL_NOTIFICATION_FLAG_SUPPORTS_REQUEST_MAIL_URL | TP_MAIL_NOTIFICATION_FLAG_THREAD_BASED ); else g_value_set_uint (value, 0); } else if (name == prop_quarks[PROP_UNREAD_MAIL_COUNT]) { g_value_set_uint (value, priv->unread_count); } else if (name == prop_quarks[PROP_UNREAD_MAILS]) { GPtrArray *mails = get_unread_mails (conn); g_value_set_boxed (value, mails); g_ptr_array_unref (mails); } else if (name == prop_quarks[PROP_MAIL_ADDRESS]) { TpBaseConnection *base = TP_BASE_CONNECTION (object); TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); TpHandle self = tp_base_connection_get_self_handle (base); const gchar *bare_jid = tp_handle_inspect (contact_handles, self); /* After some testing I found that the bare jid (username@stream_server) * always represent the e-mail address on Google account. */ g_value_set_string (value, bare_jid); } else { g_assert_not_reached (); } } telepathy-gabble-0.18.3/src/media-channel-internal.h0000664000175000017500000000524512332441362023443 0ustar00cassidycassidy00000000000000/* * media-channel-internal.h - implementation details shared between * MediaChannel source files * Copyright © 2006–2009 Collabora Ltd. * Copyright © 2006–2009 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_MEDIA_CHANNEL_INTERNAL_H__ #define __GABBLE_MEDIA_CHANNEL_INTERNAL_H__ #include "media-channel.h" #include #include #include #include "media-stream.h" G_BEGIN_DECLS struct _GabbleMediaChannelPrivate { GabbleConnection *conn; gchar *object_path; TpHandle creator; TpHandle initial_peer; TpHandle peer; gboolean peer_in_rp; WockyJingleSession *session; /* array of referenced GabbleMediaStream*. Always non-NULL. */ GPtrArray *streams; /* list of PendingStreamRequest* in no particular order */ GList *pending_stream_requests; /* list of StreamCreationData* in no particular order */ GList *stream_creation_datas; guint next_stream_id; TpLocalHoldState hold_state; TpLocalHoldStateReason hold_state_reason; TpChannelCallStateFlags call_state; GPtrArray *delayed_request_streams; TpDTMFPlayer *dtmf_player; gchar *deferred_tones; gboolean initial_audio; gboolean initial_video; gboolean immutable_streams; gboolean ready; gboolean closed; gboolean dispose_has_run; gboolean tried_decloaking; gboolean have_some_audio; }; void gabble_media_channel_hold_latch_to_session (GabbleMediaChannel *chan); void gabble_media_channel_hold_new_stream (GabbleMediaChannel *chan, GabbleMediaStream *stream, WockyJingleMediaRtp *content); void gabble_media_channel_hold_stream_closed (GabbleMediaChannel *chan, GabbleMediaStream *stream); void gabble_media_channel_hold_iface_init (gpointer g_iface, gpointer iface_data G_GNUC_UNUSED); void gabble_media_channel_call_state_iface_init (gpointer g_iface, gpointer iface_data G_GNUC_UNUSED); G_END_DECLS #endif /* #ifndef __GABBLE_MEDIA_CHANNEL_INTERNAL_H__ */ telepathy-gabble-0.18.3/src/roomlist-channel.c0000664000175000017500000004211512332440117022407 0ustar00cassidycassidy00000000000000/* * gabble-roomlist-channel.c - Source for GabbleRoomlistChannel * Copyright (C) 2005 Collabora Ltd. * Copyright (C) 2005 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "roomlist-channel.h" #include #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_ROOMLIST #include "connection.h" #include "debug.h" #include "disco.h" #include "namespaces.h" #include "util.h" static void roomlist_iface_init (gpointer, gpointer); G_DEFINE_TYPE_WITH_CODE (GabbleRoomlistChannel, gabble_roomlist_channel, TP_TYPE_BASE_CHANNEL, G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_ROOM_LIST, roomlist_iface_init); ); /* properties */ enum { PROP_CONFERENCE_SERVER = 1, LAST_PROPERTY }; /* private structure */ struct _GabbleRoomlistChannelPrivate { gchar *conference_server; gboolean listing; gpointer disco_pipeline; TpHandleSet *signalled_rooms; GPtrArray *pending_room_signals; guint timer_source_id; gboolean dispose_has_run; }; #define ROOM_SIGNAL_INTERVAL 300 static gboolean emit_room_signal (gpointer data); static void gabble_roomlist_channel_close (TpBaseChannel *base); static void gabble_roomlist_channel_init (GabbleRoomlistChannel *self) { GabbleRoomlistChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_ROOMLIST_CHANNEL, GabbleRoomlistChannelPrivate); self->priv = priv; priv->pending_room_signals = g_ptr_array_new (); } static void gabble_roomlist_channel_constructed (GObject *obj) { GObjectClass *parent_class = gabble_roomlist_channel_parent_class; GabbleRoomlistChannel *self = GABBLE_ROOMLIST_CHANNEL (obj); TpBaseChannel *base_chan = (TpBaseChannel *) self; TpBaseConnection *conn = tp_base_channel_get_connection (base_chan); TpHandleRepoIface *room_handles; if (parent_class->constructed != NULL) parent_class->constructed (obj); room_handles = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_ROOM); self->priv->signalled_rooms = tp_handle_set_new (room_handles); tp_base_channel_register (TP_BASE_CHANNEL (obj)); } static void gabble_roomlist_channel_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleRoomlistChannel *chan = GABBLE_ROOMLIST_CHANNEL (object); GabbleRoomlistChannelPrivate *priv = chan->priv; switch (property_id) { case PROP_CONFERENCE_SERVER: g_value_set_string (value, priv->conference_server); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_roomlist_channel_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleRoomlistChannel *chan = GABBLE_ROOMLIST_CHANNEL (object); GabbleRoomlistChannelPrivate *priv = chan->priv; switch (property_id) { case PROP_CONFERENCE_SERVER: g_free (priv->conference_server); priv->conference_server = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_roomlist_channel_dispose (GObject *object); static void gabble_roomlist_channel_finalize (GObject *object); static void gabble_roomlist_channel_fill_immutable_properties ( TpBaseChannel *chan, GHashTable *properties) { TP_BASE_CHANNEL_CLASS (gabble_roomlist_channel_parent_class)->fill_immutable_properties ( chan, properties); tp_dbus_properties_mixin_fill_properties_hash ( G_OBJECT (chan), properties, TP_IFACE_CHANNEL_TYPE_ROOM_LIST, "Server", NULL); } static gchar * gabble_roomlist_channel_get_object_path_suffix (TpBaseChannel *base) { return g_strdup_printf ("RoomlistChannel%p", base); } static void gabble_roomlist_channel_class_init (GabbleRoomlistChannelClass *klass) { static TpDBusPropertiesMixinPropImpl roomlist_props[] = { { "Server", "conference-server", NULL }, { NULL } }; TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass); GParamSpec *param_spec; g_type_class_add_private (klass, sizeof (GabbleRoomlistChannelPrivate)); object_class->constructed = gabble_roomlist_channel_constructed; object_class->get_property = gabble_roomlist_channel_get_property; object_class->set_property = gabble_roomlist_channel_set_property; object_class->dispose = gabble_roomlist_channel_dispose; object_class->finalize = gabble_roomlist_channel_finalize; base_class->channel_type = TP_IFACE_CHANNEL_TYPE_ROOM_LIST; base_class->target_handle_type = TP_HANDLE_TYPE_NONE; base_class->get_object_path_suffix = gabble_roomlist_channel_get_object_path_suffix; base_class->fill_immutable_properties = gabble_roomlist_channel_fill_immutable_properties; base_class->close = gabble_roomlist_channel_close; param_spec = g_param_spec_string ("conference-server", "Name of conference server to use", "Name of the XMPP conference server on which to list rooms", "", G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONFERENCE_SERVER, param_spec); tp_dbus_properties_mixin_implement_interface (object_class, TP_IFACE_QUARK_CHANNEL_TYPE_ROOM_LIST, tp_dbus_properties_mixin_getter_gobject_properties, NULL, roomlist_props); } static void stop_listing (GabbleRoomlistChannel *self); static void gabble_roomlist_channel_dispose (GObject *object) { GabbleRoomlistChannel *self = GABBLE_ROOMLIST_CHANNEL (object); GabbleRoomlistChannelPrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; stop_listing (self); g_assert (priv->pending_room_signals != NULL); g_assert (priv->pending_room_signals->len == 0); g_ptr_array_unref (priv->pending_room_signals); priv->pending_room_signals = NULL; if (G_OBJECT_CLASS (gabble_roomlist_channel_parent_class)->dispose) G_OBJECT_CLASS (gabble_roomlist_channel_parent_class)->dispose (object); } static void gabble_roomlist_channel_finalize (GObject *object) { GabbleRoomlistChannel *self = GABBLE_ROOMLIST_CHANNEL (object); GabbleRoomlistChannelPrivate *priv = self->priv; /* free any data held directly by the object here */ g_free (priv->conference_server); if (priv->signalled_rooms != NULL) tp_handle_set_destroy (priv->signalled_rooms); G_OBJECT_CLASS (gabble_roomlist_channel_parent_class)->finalize (object); } GabbleRoomlistChannel * _gabble_roomlist_channel_new (GabbleConnection *conn, const gchar *conference_server) { TpHandle initiator; g_return_val_if_fail (GABBLE_IS_CONNECTION (conn), NULL); g_return_val_if_fail (conference_server != NULL, NULL); /* We are always the initiator. */ initiator = tp_base_connection_get_self_handle ((TpBaseConnection *) conn); return GABBLE_ROOMLIST_CHANNEL ( g_object_new (GABBLE_TYPE_ROOMLIST_CHANNEL, "connection", conn, "initiator-handle", initiator, "requested", TRUE, "conference-server", conference_server, NULL)); } static gboolean emit_room_signal (gpointer data) { GabbleRoomlistChannel *chan = data; GabbleRoomlistChannelPrivate *priv = chan->priv; GType room_info_type = TP_STRUCT_TYPE_ROOM_INFO; if (!priv->listing) return FALSE; if (priv->pending_room_signals->len == 0) return TRUE; tp_svc_channel_type_room_list_emit_got_rooms ( (TpSvcChannelTypeRoomList *) chan, priv->pending_room_signals); while (priv->pending_room_signals->len != 0) { gpointer boxed = g_ptr_array_index (priv->pending_room_signals, 0); g_boxed_free (room_info_type, boxed); g_ptr_array_remove_index_fast (priv->pending_room_signals, 0); } return TRUE; } static void room_info_cb (gpointer pipeline, GabbleDiscoItem *item, gpointer user_data) { GabbleRoomlistChannel *chan = user_data; TpBaseChannel *base; GabbleRoomlistChannelPrivate *priv; TpHandleRepoIface *room_handles; const char *jid, *category, *type, *var, *name; TpHandle handle; GHashTable *keys; GValue room = {0,}; GValue *tmp; gpointer k, v; GType room_info_type = TP_STRUCT_TYPE_ROOM_INFO; #define INSERT_KEY(hash, name, type, type2, value) \ do {\ tmp = g_slice_new0 (GValue); \ g_value_init (tmp, (type)); \ g_value_set_##type2 (tmp, (value)); \ g_hash_table_insert (hash, (name), tmp); \ } while (0) g_assert (GABBLE_IS_ROOMLIST_CHANNEL (chan)); base = TP_BASE_CHANNEL (chan); priv = chan->priv; room_handles = tp_base_connection_get_handles ( tp_base_channel_get_connection (base), TP_HANDLE_TYPE_ROOM); jid = item->jid; name = item->name; category = item->category; type = item->type; if (0 != strcmp (category, "conference") || 0 != strcmp (type, "text")) return; if (!g_hash_table_lookup_extended (item->features, "http://jabber.org/protocol/muc", &k, &v)) { /* not muc */ return; } handle = tp_handle_ensure (room_handles, jid, NULL, NULL); if (handle == 0) { DEBUG ("ignoring listed room with invalid JID '%s'", jid); return; } DEBUG ("got room identity, name=%s, category=%s, type=%s", name, category, type); keys = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free); INSERT_KEY (keys, "handle-name", G_TYPE_STRING, string, tp_handle_inspect (room_handles, handle)); INSERT_KEY (keys, "name", G_TYPE_STRING, string, name); if (g_hash_table_lookup_extended (item->features, "muc_membersonly", &k, &v)) INSERT_KEY (keys, "invite-only", G_TYPE_BOOLEAN, boolean, TRUE); if (g_hash_table_lookup_extended (item->features, "muc_open", &k, &v)) INSERT_KEY (keys, "invite-only", G_TYPE_BOOLEAN, boolean, FALSE); if (g_hash_table_lookup_extended (item->features, "muc_passwordprotected", &k, &v)) INSERT_KEY (keys, "password", G_TYPE_BOOLEAN, boolean, TRUE); if (g_hash_table_lookup_extended (item->features, "muc_unsecure", &k, &v)) INSERT_KEY (keys, "password", G_TYPE_BOOLEAN, boolean, FALSE); if (g_hash_table_lookup_extended (item->features, "muc_unsecured", &k, &v)) INSERT_KEY (keys, "password", G_TYPE_BOOLEAN, boolean, FALSE); if (g_hash_table_lookup_extended (item->features, "muc_hidden", &k, &v)) INSERT_KEY (keys, "hidden", G_TYPE_BOOLEAN, boolean, TRUE); if (g_hash_table_lookup_extended (item->features, "muc_public", &k, &v)) INSERT_KEY (keys, "hidden", G_TYPE_BOOLEAN, boolean, FALSE); if (g_hash_table_lookup_extended (item->features, "muc_membersonly", &k, &v)) INSERT_KEY (keys, "members-only", G_TYPE_BOOLEAN, boolean, TRUE); if (g_hash_table_lookup_extended (item->features, "muc_open", &k, &v)) INSERT_KEY (keys, "members-only", G_TYPE_BOOLEAN, boolean, FALSE); if (g_hash_table_lookup_extended (item->features, "muc_moderated", &k, &v)) INSERT_KEY (keys, "moderated", G_TYPE_BOOLEAN, boolean, TRUE); if (g_hash_table_lookup_extended (item->features, "muc_unmoderated", &k, &v)) INSERT_KEY (keys, "moderated", G_TYPE_BOOLEAN, boolean, FALSE); if (g_hash_table_lookup_extended (item->features, "muc_nonanonymous", &k, &v)) INSERT_KEY (keys, "anonymous", G_TYPE_BOOLEAN, boolean, FALSE); if (g_hash_table_lookup_extended (item->features, "muc_anonymous", &k, &v)) INSERT_KEY (keys, "anonymous", G_TYPE_BOOLEAN, boolean, TRUE); if (g_hash_table_lookup_extended (item->features, "muc_semianonymous", &k, &v)) INSERT_KEY (keys, "anonymous", G_TYPE_BOOLEAN, boolean, FALSE); if (g_hash_table_lookup_extended (item->features, "muc_persistent", &k, &v)) INSERT_KEY (keys, "persistent", G_TYPE_BOOLEAN, boolean, TRUE); if (g_hash_table_lookup_extended (item->features, "muc_temporary", &k, &v)) INSERT_KEY (keys, "persistent", G_TYPE_BOOLEAN, boolean, FALSE); var = g_hash_table_lookup (item->features, "muc#roominfo_description"); if (var != NULL) INSERT_KEY (keys, "description", G_TYPE_STRING, string, var); var = g_hash_table_lookup (item->features, "muc#roominfo_occupants"); if (var != NULL) INSERT_KEY (keys, "members", G_TYPE_UINT, uint, (guint) g_ascii_strtoull (var, NULL, 10)); var = g_hash_table_lookup (item->features, "muc#roominfo_lang"); if (var != NULL) INSERT_KEY (keys, "language", G_TYPE_STRING, string, var); /* transfer the room handle ref to signalled_rooms */ tp_handle_set_add (priv->signalled_rooms, handle); g_value_init (&room, room_info_type); g_value_take_boxed (&room, dbus_g_type_specialized_construct (room_info_type)); dbus_g_type_struct_set (&room, 0, handle, 1, "org.freedesktop.Telepathy.Channel.Type.Text", 2, keys, G_MAXUINT); DEBUG ("adding new room signal data to pending: %s", jid); g_ptr_array_add (priv->pending_room_signals, g_value_get_boxed (&room)); g_hash_table_unref (keys); } static void rooms_end_cb (gpointer data, gpointer user_data) { GabbleRoomlistChannel *chan = user_data; GabbleRoomlistChannelPrivate *priv = chan->priv; emit_room_signal (chan); priv->listing = FALSE; tp_svc_channel_type_room_list_emit_listing_rooms ( (TpSvcChannelTypeRoomList *) chan, FALSE); g_source_remove (priv->timer_source_id); priv->timer_source_id = 0; } static void stop_listing (GabbleRoomlistChannel *self) { GabbleRoomlistChannelPrivate *priv = self->priv; if (priv->listing) { emit_room_signal (self); priv->listing = FALSE; tp_svc_channel_type_room_list_emit_listing_rooms ( (TpSvcChannelTypeRoomList *) self, FALSE); } if (priv->disco_pipeline != NULL) { gabble_disco_pipeline_destroy (priv->disco_pipeline); priv->disco_pipeline = NULL; } if (priv->timer_source_id) { g_source_remove (priv->timer_source_id); priv->timer_source_id = 0; } g_assert (priv->pending_room_signals->len == 0); } static void gabble_roomlist_channel_close (TpBaseChannel *base) { GabbleRoomlistChannel *self = GABBLE_ROOMLIST_CHANNEL (base); DEBUG ("called on %p", self); stop_listing (self); tp_base_channel_destroyed (base); } static void gabble_roomlist_channel_get_listing_rooms (TpSvcChannelTypeRoomList *iface, DBusGMethodInvocation *context) { GabbleRoomlistChannel *self = GABBLE_ROOMLIST_CHANNEL (iface); GabbleRoomlistChannelPrivate *priv; g_assert (GABBLE_IS_ROOMLIST_CHANNEL (self)); priv = self->priv; tp_svc_channel_type_room_list_return_from_get_listing_rooms ( context, priv->listing); } static void gabble_roomlist_channel_list_rooms (TpSvcChannelTypeRoomList *iface, DBusGMethodInvocation *context) { GabbleRoomlistChannel *self = GABBLE_ROOMLIST_CHANNEL (iface); GabbleRoomlistChannelPrivate *priv = self->priv; TpBaseChannel *base = TP_BASE_CHANNEL (self); GabbleConnection *conn = GABBLE_CONNECTION (tp_base_channel_get_connection (base)); priv->listing = TRUE; tp_svc_channel_type_room_list_emit_listing_rooms (iface, TRUE); if (priv->disco_pipeline == NULL) priv->disco_pipeline = gabble_disco_pipeline_init (conn->disco, room_info_cb, rooms_end_cb, self); gabble_disco_pipeline_run (priv->disco_pipeline, priv->conference_server); priv->timer_source_id = g_timeout_add (ROOM_SIGNAL_INTERVAL, emit_room_signal, self); tp_svc_channel_type_room_list_return_from_list_rooms (context); } static void gabble_roomlist_channel_stop_listing (TpSvcChannelTypeRoomList *iface, DBusGMethodInvocation *context) { GabbleRoomlistChannel *self = GABBLE_ROOMLIST_CHANNEL (iface); g_assert (GABBLE_IS_ROOMLIST_CHANNEL (self)); stop_listing (self); tp_svc_channel_type_room_list_return_from_stop_listing (context); } static void roomlist_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcChannelTypeRoomListClass *klass = (TpSvcChannelTypeRoomListClass *) g_iface; #define IMPLEMENT(x) tp_svc_channel_type_room_list_implement_##x (\ klass, gabble_roomlist_channel_##x) IMPLEMENT(get_listing_rooms); IMPLEMENT(list_rooms); IMPLEMENT(stop_listing); #undef IMPLEMENT } telepathy-gabble-0.18.3/src/server-tls-channel.c0000664000175000017500000002247312332440117022652 0ustar00cassidycassidy00000000000000/* * server-tls-channel.c - Source for GabbleServerTLSChannel * Copyright (C) 2010 Collabora Ltd. * @author Cosimo Cecchi * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "server-tls-channel.h" #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_TLS #include "debug.h" #include "connection.h" #include "tls-certificate.h" G_DEFINE_TYPE_WITH_CODE (GabbleServerTLSChannel, gabble_server_tls_channel, TP_TYPE_BASE_CHANNEL, G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_SERVER_TLS_CONNECTION, NULL)); static void gabble_server_tls_channel_close (TpBaseChannel *base); enum { /* server TLS channel iface */ PROP_SERVER_CERTIFICATE = 1, PROP_HOSTNAME, PROP_REFERENCE_IDENTITIES, /* not exported */ PROP_TLS_SESSION, NUM_PROPERTIES }; struct _GabbleServerTLSChannelPrivate { WockyTLSSession *tls_session; GabbleTLSCertificate *server_cert; gchar *server_cert_path; gchar *hostname; GStrv reference_identities; gboolean dispose_has_run; }; static void gabble_server_tls_channel_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleServerTLSChannel *self = GABBLE_SERVER_TLS_CHANNEL (object); switch (property_id) { case PROP_SERVER_CERTIFICATE: g_value_set_boxed (value, self->priv->server_cert_path); break; case PROP_HOSTNAME: g_value_set_string (value, self->priv->hostname); break; case PROP_REFERENCE_IDENTITIES: g_value_set_boxed (value, self->priv->reference_identities); break; case PROP_TLS_SESSION: g_value_set_object (value, self->priv->tls_session); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_server_tls_channel_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleServerTLSChannel *self = GABBLE_SERVER_TLS_CHANNEL (object); switch (property_id) { case PROP_TLS_SESSION: self->priv->tls_session = g_value_dup_object (value); break; case PROP_HOSTNAME: self->priv->hostname = g_value_dup_string (value); break; case PROP_REFERENCE_IDENTITIES: self->priv->reference_identities = g_value_dup_boxed (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_server_tls_channel_finalize (GObject *object) { GabbleServerTLSChannel *self = GABBLE_SERVER_TLS_CHANNEL (object); DEBUG ("Finalize TLS channel"); g_free (self->priv->server_cert_path); g_free (self->priv->hostname); g_strfreev (self->priv->reference_identities); G_OBJECT_CLASS (gabble_server_tls_channel_parent_class)->finalize (object); } static void gabble_server_tls_channel_dispose (GObject *object) { GabbleServerTLSChannel *self = GABBLE_SERVER_TLS_CHANNEL (object); if (self->priv->dispose_has_run) return; DEBUG ("Dispose TLS channel"); self->priv->dispose_has_run = TRUE; tp_clear_object (&self->priv->server_cert); tp_clear_object (&self->priv->tls_session); G_OBJECT_CLASS (gabble_server_tls_channel_parent_class)->dispose (object); } static const gchar * cert_type_to_str (WockyTLSCertType type) { const gchar *retval = NULL; switch (type) { case WOCKY_TLS_CERT_TYPE_X509: retval = "x509"; break; case WOCKY_TLS_CERT_TYPE_OPENPGP: retval = "pgp"; break; default: break; } return retval; } static void gabble_server_tls_channel_constructed (GObject *object) { GabbleServerTLSChannel *self = GABBLE_SERVER_TLS_CHANNEL (object); TpBaseChannel *base = TP_BASE_CHANNEL (self); TpBaseConnection *base_conn = tp_base_channel_get_connection (base); void (*chain_up) (GObject *) = G_OBJECT_CLASS (gabble_server_tls_channel_parent_class)->constructed; WockyTLSCertType cert_type; const gchar *path; gchar *cert_object_path; GPtrArray *certificates; if (chain_up != NULL) chain_up (object); tp_base_channel_register (base); /* create the TLS certificate object */ path = tp_base_channel_get_object_path (base); cert_object_path = g_strdup_printf ("%s/TLSCertificateObject", path); certificates = wocky_tls_session_get_peers_certificate ( self->priv->tls_session, &cert_type); self->priv->server_cert = g_object_new (GABBLE_TYPE_TLS_CERTIFICATE, "object-path", cert_object_path, "certificate-chain-data", certificates, "certificate-type", cert_type_to_str (cert_type), "dbus-daemon", GABBLE_CONNECTION (base_conn)->daemon, NULL); self->priv->server_cert_path = cert_object_path; DEBUG ("Server TLS channel constructed at %s", path); } static void gabble_server_tls_channel_fill_immutable_properties ( TpBaseChannel *chan, GHashTable *properties) { TP_BASE_CHANNEL_CLASS (gabble_server_tls_channel_parent_class) ->fill_immutable_properties (chan, properties); tp_dbus_properties_mixin_fill_properties_hash ( G_OBJECT (chan), properties, TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, "ServerCertificate", TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, "Hostname", TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, "ReferenceIdentities", NULL); } static gchar * gabble_server_tls_channel_get_object_path_suffix (TpBaseChannel *base) { static guint count = 0; return g_strdup_printf ("ServerTLSChannel%u", ++count); } static void gabble_server_tls_channel_init (GabbleServerTLSChannel *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_SERVER_TLS_CHANNEL, GabbleServerTLSChannelPrivate); } static void gabble_server_tls_channel_class_init (GabbleServerTLSChannelClass *klass) { static TpDBusPropertiesMixinPropImpl server_tls_props[] = { { "ServerCertificate", "server-certificate", NULL }, { "Hostname", "hostname", NULL }, { "ReferenceIdentities", "reference-identities", NULL }, { NULL } }; GObjectClass *oclass = G_OBJECT_CLASS (klass); TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (klass); GParamSpec *pspec; g_type_class_add_private (klass, sizeof (GabbleServerTLSChannelPrivate)); oclass->get_property = gabble_server_tls_channel_get_property; oclass->set_property = gabble_server_tls_channel_set_property; oclass->dispose = gabble_server_tls_channel_dispose; oclass->finalize = gabble_server_tls_channel_finalize; oclass->constructed = gabble_server_tls_channel_constructed; base_class->channel_type = TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION; base_class->target_handle_type = TP_HANDLE_TYPE_NONE; base_class->fill_immutable_properties = gabble_server_tls_channel_fill_immutable_properties; base_class->get_object_path_suffix = gabble_server_tls_channel_get_object_path_suffix; base_class->close = gabble_server_tls_channel_close; pspec = g_param_spec_boxed ("server-certificate", "Server certificate path", "The object path of the server certificate.", DBUS_TYPE_G_OBJECT_PATH, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (oclass, PROP_SERVER_CERTIFICATE, pspec); pspec = g_param_spec_string ("hostname", "The hostname to be verified", "The hostname which should be certified by the server certificate.", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (oclass, PROP_HOSTNAME, pspec); pspec = g_param_spec_boxed ("reference-identities", "The various identities to check the certificate against", "The server certificate identity should match one of these identities.", G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (oclass, PROP_REFERENCE_IDENTITIES, pspec); pspec = g_param_spec_object ("tls-session", "The WockyTLSSession", "The WockyTLSSession object containing the TLS information", WOCKY_TYPE_TLS_SESSION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (oclass, PROP_TLS_SESSION, pspec); tp_dbus_properties_mixin_implement_interface (oclass, TP_IFACE_QUARK_CHANNEL_TYPE_SERVER_TLS_CONNECTION, tp_dbus_properties_mixin_getter_gobject_properties, NULL, server_tls_props); } static void gabble_server_tls_channel_close (TpBaseChannel *base) { DEBUG ("Close() called on the TLS channel %p", base); tp_base_channel_destroyed (base); } GabbleTLSCertificate * gabble_server_tls_channel_get_certificate (GabbleServerTLSChannel *self) { return self->priv->server_cert; } telepathy-gabble-0.18.3/src/im-channel.h0000664000175000017500000000553712223562023021160 0ustar00cassidycassidy00000000000000/* * gabble-im-channel.h - Header for GabbleIMChannel * Copyright (C) 2005 Collabora Ltd. * Copyright (C) 2005 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_IM_CHANNEL_H__ #define __GABBLE_IM_CHANNEL_H__ #include #include #include #include G_BEGIN_DECLS typedef struct _GabbleIMChannel GabbleIMChannel; typedef struct _GabbleIMChannelClass GabbleIMChannelClass; typedef struct _GabbleIMChannelPrivate GabbleIMChannelPrivate; struct _GabbleIMChannelClass { TpBaseChannelClass parent_class; }; struct _GabbleIMChannel { TpBaseChannel parent; TpMessageMixin message_mixin; GabbleIMChannelPrivate *priv; }; GType gabble_im_channel_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_IM_CHANNEL \ (gabble_im_channel_get_type ()) #define GABBLE_IM_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_IM_CHANNEL, GabbleIMChannel)) #define GABBLE_IM_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_IM_CHANNEL,\ GabbleIMChannelClass)) #define GABBLE_IS_IM_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_IM_CHANNEL)) #define GABBLE_IS_IM_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_IM_CHANNEL)) #define GABBLE_IM_CHANNEL_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_IM_CHANNEL, \ GabbleIMChannelClass)) void _gabble_im_channel_receive (GabbleIMChannel *chan, WockyStanza *message, TpChannelTextMessageType type, const char *from, time_t timestamp, const char *id, const char *text, gint state); void _gabble_im_channel_state_receive (GabbleIMChannel *chan, TpChannelChatState state); void gabble_im_channel_receive_receipt ( GabbleIMChannel *self, const gchar *receipt_id); void _gabble_im_channel_report_delivery ( GabbleIMChannel *self, TpChannelTextMessageType type, time_t timestamp, const gchar *id, const char *text, TpChannelTextSendError send_error, TpDeliveryStatus delivery_status); G_END_DECLS #endif /* #ifndef __GABBLE_IM_CHANNEL_H__*/ telepathy-gabble-0.18.3/src/request-pipeline.h0000664000175000017500000000617711720700311022434 0ustar00cassidycassidy00000000000000/* * request-pipeline.h - Pipeline logic for XMPP requests * * Copyright (C) 2007 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_REQUEST_PIPELINE_H__ #define __GABBLE_REQUEST_PIPELINE_H__ #include #include #include "types.h" G_BEGIN_DECLS typedef struct _GabbleRequestPipelinePrivate GabbleRequestPipelinePrivate; typedef struct _GabbleRequestPipelineClass GabbleRequestPipelineClass; typedef struct _GabbleRequestPipelineItem GabbleRequestPipelineItem; typedef void (*GabbleRequestPipelineCb) (GabbleConnection *conn, WockyStanza *msg, gpointer user_data, GError *error); /** * GabbleRequestPipelineError: * @GABBLE_REQUEST_PIPELINE_ERROR_CANCELLED: The request was cancelled * @GABBLE_REQUEST_PIPELINE_ERROR_TIMEOUT: The request timed out */ typedef enum { GABBLE_REQUEST_PIPELINE_ERROR_CANCELLED, GABBLE_REQUEST_PIPELINE_ERROR_TIMEOUT } GabbleRequestPipelineError; GQuark gabble_request_pipeline_error_quark (void); #define GABBLE_REQUEST_PIPELINE_ERROR gabble_request_pipeline_error_quark () GType gabble_request_pipeline_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_REQUEST_PIPELINE \ (gabble_request_pipeline_get_type ()) #define GABBLE_REQUEST_PIPELINE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GABBLE_TYPE_REQUEST_PIPELINE, \ GabbleRequestPipeline)) #define GABBLE_REQUEST_PIPELINE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), GABBLE_TYPE_REQUEST_PIPELINE, \ GabbleRequestPipelineClass)) #define GABBLE_IS_REQUEST_PIPELINE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GABBLE_TYPE_REQUEST_PIPELINE)) #define GABBLE_IS_REQUEST_PIPELINE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), GABBLE_TYPE_REQUEST_PIPELINE)) #define GABBLE_REQUEST_PIPELINE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_REQUEST_PIPELINE, \ GabbleRequestPipelineClass)) struct _GabbleRequestPipelineClass { GObjectClass parent_class; }; struct _GabbleRequestPipeline { GObject parent; GabbleRequestPipelinePrivate *priv; }; GabbleRequestPipeline *gabble_request_pipeline_new (GabbleConnection *conn); GabbleRequestPipelineItem *gabble_request_pipeline_enqueue (GabbleRequestPipeline *pipeline, WockyStanza *msg, guint timeout, GabbleRequestPipelineCb callback, gpointer user_data); void gabble_request_pipeline_item_cancel (GabbleRequestPipelineItem *req); G_END_DECLS #endif telepathy-gabble-0.18.3/src/presence.h0000664000175000017500000001170111720700311020732 0ustar00cassidycassidy00000000000000/* * gabble-presence.h - Headers for Gabble's per-contact presence structure * Copyright (C) 2005 Collabora Ltd. * Copyright (C) 2005 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_PRESENCE_H__ #define __GABBLE_PRESENCE_H__ #include #include "gabble/capabilities.h" #include "connection.h" #include "types.h" G_BEGIN_DECLS #define GABBLE_TYPE_PRESENCE gabble_presence_get_type () #define GABBLE_PRESENCE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ GABBLE_TYPE_PRESENCE, GabblePresence)) #define GABBLE_PRESENCE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), \ GABBLE_TYPE_PRESENCE, GabblePresenceClass)) #define GABBLE_IS_PRESENCE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ GABBLE_TYPE_PRESENCE)) #define GABBLE_IS_PRESENCE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), \ GABBLE_TYPE_PRESENCE)) #define GABBLE_PRESENCE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ GABBLE_TYPE_PRESENCE, GabblePresenceClass)) typedef struct _GabblePresencePrivate GabblePresencePrivate; struct _GabblePresence { GObject parent; GabblePresenceId status; gchar *status_message; gchar *nickname; gchar *avatar_sha1; guint client_types; gboolean keep_unavailable; GabblePresencePrivate *priv; }; typedef enum { GABBLE_CLIENT_TYPE_BOT = 1 << 0, GABBLE_CLIENT_TYPE_CONSOLE = 1 << 1, GABBLE_CLIENT_TYPE_GAME = 1 << 2, GABBLE_CLIENT_TYPE_HANDHELD = 1 << 3, GABBLE_CLIENT_TYPE_PC = 1 << 4, GABBLE_CLIENT_TYPE_PHONE = 1 << 5, GABBLE_CLIENT_TYPE_WEB = 1 << 6, GABBLE_CLIENT_TYPE_SMS = 1 << 7, } GabbleClientType; typedef struct _GabblePresenceClass GabblePresenceClass; struct _GabblePresenceClass { GObjectClass parent_class; }; GType gabble_presence_get_type (void); GabblePresence* gabble_presence_new (void); gboolean gabble_presence_update (GabblePresence *presence, const gchar *resource, GabblePresenceId status, const gchar *status_message, gint8 priority, gboolean *update_client_types, time_t now); void gabble_presence_set_capabilities (GabblePresence *presence, const gchar *resource, const GabbleCapabilitySet *cap_set, const GPtrArray *data_forms, guint serial); gboolean gabble_presence_has_cap (GabblePresence *presence, const gchar *ns); GabbleCapabilitySet *gabble_presence_dup_caps (GabblePresence *presence); const GabbleCapabilitySet *gabble_presence_peek_caps (GabblePresence *presence); GPtrArray *gabble_presence_peek_data_forms (GabblePresence *presence); gboolean gabble_presence_has_resources (GabblePresence *self); const gchar *gabble_presence_pick_resource_by_caps (GabblePresence *presence, GabbleClientType preferred_client_type, GabbleCapabilitySetPredicate predicate, gconstpointer user_data); gboolean gabble_presence_resource_has_caps (GabblePresence *presence, const gchar *resource, GabbleCapabilitySetPredicate predicate, gconstpointer user_data); WockyStanza *gabble_presence_as_message (GabblePresence *presence, const gchar *to); void gabble_presence_add_status_and_vcard (GabblePresence *presence, WockyStanza *stanza); gchar *gabble_presence_dump (GabblePresence *presence); gboolean gabble_presence_added_to_view (GabblePresence *presence); gboolean gabble_presence_removed_from_view (GabblePresence *presence); /* Data-driven feature fallback */ typedef struct { gboolean considered; gconstpointer check_data; gconstpointer result; } GabbleFeatureFallback; gconstpointer gabble_presence_resource_pick_best_feature ( GabblePresence *presence, const gchar *resource, const GabbleFeatureFallback *table, GabbleCapabilitySetPredicate predicate); gconstpointer gabble_presence_pick_best_feature (GabblePresence *presence, const GabbleFeatureFallback *table, GabbleCapabilitySetPredicate predicate); gboolean gabble_presence_update_client_types (GabblePresence *presence, const gchar *resource, guint client_types); gchar **gabble_presence_get_client_types_array (GabblePresence *presence, const gchar **resource_name); G_END_DECLS #endif /* __GABBLE_PRESENCE_H__ */ telepathy-gabble-0.18.3/src/gabble.c0000664000175000017500000001110212332441362020340 0ustar00cassidycassidy00000000000000/* * gabble.h - entry point and utility functions for telepathy-gabble * Copyright (C) 2005 Collabora Ltd. * Copyright (C) 2005 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "gabble.h" #ifdef HAVE_UNISTD_H # include #endif #include #include #include #include #include "debug.h" #include "connection-manager.h" #include "plugin-loader.h" static TpBaseConnectionManager * construct_cm (void) { return (TpBaseConnectionManager *) g_object_new ( GABBLE_TYPE_CONNECTION_MANAGER, NULL); } #ifdef ENABLE_DEBUG static TpDebugSender *debug_sender = NULL; static void log_to_debug_sender (const gchar *log_domain, GLogLevelFlags log_level, const gchar *string) { GTimeVal now; g_return_if_fail (TP_IS_DEBUG_SENDER (debug_sender)); g_get_current_time (&now); tp_debug_sender_add_message (debug_sender, &now, log_domain, log_level, string); } /* Whether we redirect all wocky log message purely to the debug sender */ static gboolean redirect_wocky = FALSE; /* Whether to add a timestamp to the output messages */ static gboolean stamp_logs = FALSE; static void log_handler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) { if (!redirect_wocky || tp_strdiff (log_domain, "wocky")) { if (stamp_logs) { GTimeVal now; gchar *now_str = NULL; gchar *tmp; g_get_current_time (&now); now_str = g_time_val_to_iso8601 (&now); tmp = g_strdup_printf ("%s.%06ld: %s", now_str, now.tv_usec, message); g_log_default_handler (log_domain, log_level, tmp, NULL); g_free (now_str); g_free (tmp); } else { g_log_default_handler (log_domain, log_level, message, NULL); } } /* Gabble messages are already sent to the debug sender in gabble_debug. */ if (log_level != G_LOG_LEVEL_DEBUG || tp_strdiff (log_domain, G_LOG_DOMAIN)) log_to_debug_sender (log_domain, log_level, message); } #endif void gabble_init (void) { if (!dbus_threads_init_default ()) g_error ("Unable to initialize libdbus thread-safety (out of memory?)"); g_type_init (); wocky_init (); } static void try_to_delete_old_caps_cache (void) { gchar *cache = g_build_path (G_DIR_SEPARATOR_S, g_get_user_cache_dir (), "telepathy", "gabble", "caps-cache.db", NULL); if (g_file_test (cache, G_FILE_TEST_IS_REGULAR)) { /* fire and forget */ g_unlink (cache); } g_free (cache); } int gabble_main (int argc, char **argv) { GabblePluginLoader *loader; int out; GLogLevelFlags fatal_mask; tp_debug_divert_messages (g_getenv ("GABBLE_LOGFILE")); #ifdef ENABLE_FATAL_CRITICALS /* make critical warnings fatal */ fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK); fatal_mask |= G_LOG_LEVEL_CRITICAL; g_log_set_always_fatal (fatal_mask); #endif #ifdef ENABLE_DEBUG gabble_debug_set_flags_from_env (); stamp_logs = (g_getenv ("GABBLE_TIMING") != NULL); if (g_getenv ("WOCKY_DEBUG") == NULL) { redirect_wocky = TRUE; wocky_debug_set_flags ( WOCKY_DEBUG_XMPP | WOCKY_DEBUG_AUTH | WOCKY_DEBUG_PORTER ); } debug_sender = tp_debug_sender_dup (); g_log_set_default_handler (log_handler, NULL); if (g_getenv ("GABBLE_PERSIST") != NULL) tp_debug_set_persistent (TRUE); #endif loader = gabble_plugin_loader_dup (); try_to_delete_old_caps_cache (); out = tp_run_connection_manager ("telepathy-gabble", VERSION, construct_cm, argc, argv); g_object_unref (loader); #ifdef ENABLE_DEBUG g_log_set_default_handler (g_log_default_handler, NULL); g_object_unref (debug_sender); #endif wocky_deinit (); return out; } telepathy-gabble-0.18.3/src/protocol.c0000664000175000017500000003436212332441362021002 0ustar00cassidycassidy00000000000000/* * protocol.c - source for GabbleJabberProtocol * Copyright (C) 2007-2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "protocol.h" #include #include #include #include #include #include "extensions/extensions.h" #include "conn-presence.h" #include "connection.h" #include "connection-manager.h" #include "im-factory.h" #ifdef ENABLE_VOIP #include "media-factory.h" #endif #include "private-tubes-factory.h" #include "roomlist-manager.h" #include "search-manager.h" #include "util.h" #include "addressing-util.h" #define PROTOCOL_NAME "jabber" #define ICON_NAME "im-" PROTOCOL_NAME #define VCARD_FIELD_NAME "x-" PROTOCOL_NAME #define ENGLISH_NAME "Jabber" static void addressing_iface_init (TpProtocolAddressingInterface *iface); G_DEFINE_TYPE_WITH_CODE (GabbleJabberProtocol, gabble_jabber_protocol, TP_TYPE_BASE_PROTOCOL, G_IMPLEMENT_INTERFACE (TP_TYPE_PROTOCOL_ADDRESSING, addressing_iface_init); ) static TpCMParamSpec jabber_params[] = { { "account", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, TP_CONN_MGR_PARAM_FLAG_REQUIRED | TP_CONN_MGR_PARAM_FLAG_REGISTER, NULL, 0 /* unused */, /* FIXME: validate the JID according to the RFC */ tp_cm_param_filter_string_nonempty, NULL }, { "password", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, TP_CONN_MGR_PARAM_FLAG_REGISTER | TP_CONN_MGR_PARAM_FLAG_SECRET, NULL, 0 /* unused */, NULL, NULL }, { "server", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL, 0 /* unused */, /* FIXME: validate the server properly */ tp_cm_param_filter_string_nonempty, NULL }, { "resource", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL, 0 /* unused */, /* FIXME: validate the resource according to the RFC */ tp_cm_param_filter_string_nonempty, NULL }, { "priority", DBUS_TYPE_INT16_AS_STRING, G_TYPE_INT, TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GINT_TO_POINTER(0), 0 /* unused */, NULL, NULL }, { "port", DBUS_TYPE_UINT16_AS_STRING, G_TYPE_UINT, TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(5222), 0 /* unused */, tp_cm_param_filter_uint_nonzero, NULL }, { "old-ssl", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN, TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GINT_TO_POINTER(FALSE), 0 /* unused */, NULL, NULL }, { "require-encryption", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN, TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GINT_TO_POINTER(TRUE), 0 /* unused */, NULL, NULL }, { "register", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN, TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GINT_TO_POINTER(FALSE), 0 /* unused */, NULL, NULL }, { "low-bandwidth", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN, TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GINT_TO_POINTER(FALSE), 0 /* unused */, NULL, NULL }, { "https-proxy-server", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL, 0 /* unused */, /* FIXME: validate properly */ tp_cm_param_filter_string_nonempty, NULL }, { "https-proxy-port", DBUS_TYPE_UINT16_AS_STRING, G_TYPE_UINT, TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(GABBLE_PARAMS_DEFAULT_HTTPS_PROXY_PORT), 0 /* unused */, tp_cm_param_filter_uint_nonzero, NULL }, { "fallback-conference-server", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, "conference.telepathy.im", 0 /* offset, not used */, /* FIXME: validate properly */ tp_cm_param_filter_string_nonempty, NULL }, { "stun-server", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL, 0 /* unused */, /* FIXME: validate properly */ tp_cm_param_filter_string_nonempty, NULL }, { "stun-port", DBUS_TYPE_UINT16_AS_STRING, G_TYPE_UINT, TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(GABBLE_PARAMS_DEFAULT_STUN_PORT), 0 /* unused */, tp_cm_param_filter_uint_nonzero, NULL }, { "fallback-stun-server", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GABBLE_PARAMS_DEFAULT_FALLBACK_STUN_SERVER, 0 /* unused */, /* FIXME: validate properly */ tp_cm_param_filter_string_nonempty, NULL }, { "fallback-stun-port", DBUS_TYPE_UINT16_AS_STRING, G_TYPE_UINT, TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER(GABBLE_PARAMS_DEFAULT_STUN_PORT), 0 /* unused */, tp_cm_param_filter_uint_nonzero, NULL }, { "ignore-ssl-errors", DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN, TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GINT_TO_POINTER(FALSE), 0 /* unused */, NULL, NULL }, { "alias", DBUS_TYPE_STRING_AS_STRING, G_TYPE_STRING, 0, NULL, 0 /* unused */, /* setting a 0-length alias makes no sense */ tp_cm_param_filter_string_nonempty, NULL }, { "fallback-socks5-proxies", "as", 0, TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, NULL, 0 /* unused */, NULL, NULL }, { "keepalive-interval", "u", G_TYPE_UINT, TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT, GUINT_TO_POINTER (30), 0 /* unused */, NULL, NULL }, { TP_PROP_CONNECTION_INTERFACE_CONTACT_LIST_DOWNLOAD_AT_CONNECTION, DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN, TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT | TP_CONN_MGR_PARAM_FLAG_DBUS_PROPERTY, GUINT_TO_POINTER (TRUE), 0 /* unused */, NULL, NULL }, { GABBLE_PROP_CONNECTION_INTERFACE_GABBLE_DECLOAK_DECLOAK_AUTOMATICALLY, DBUS_TYPE_BOOLEAN_AS_STRING, G_TYPE_BOOLEAN, TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT | TP_CONN_MGR_PARAM_FLAG_DBUS_PROPERTY, GINT_TO_POINTER (TRUE), 0 /* unused */, NULL, NULL }, { "fallback-servers", "as", 0, 0, NULL, 0 /* unused */, NULL, NULL }, { "extra-certificate-identities", "as", 0, 0, NULL, 0 /* unused */, NULL, NULL }, { NULL, NULL, 0, 0, NULL, 0 } }; static const gchar *default_socks5_proxies[] = GABBLE_PARAMS_DEFAULT_SOCKS5_PROXIES; static void gabble_jabber_protocol_init (GabbleJabberProtocol *self) { } static const TpCMParamSpec * get_parameters (TpBaseProtocol *self G_GNUC_UNUSED) { static gsize init_value = 0; if (g_once_init_enter (&init_value)) { guint i; for (i = 0; jabber_params[i].name != NULL; i++) { if (!g_strcmp0 (jabber_params[i].name, "fallback-socks5-proxies")) { jabber_params[i].gtype = G_TYPE_STRV; jabber_params[i].def = default_socks5_proxies; } else if (!g_strcmp0 (jabber_params[i].name, "fallback-servers")) { jabber_params[i].gtype = G_TYPE_STRV; } else if (!g_strcmp0 (jabber_params[i].name, "extra-certificate-identities")) { jabber_params[i].gtype = G_TYPE_STRV; } } g_once_init_leave (&init_value, 1); } return jabber_params; } #define MAP(x,y) { x, y } #define SAME(x) { x, x } /* This should be in sync with jabber_params from connection-manager.c, * and should contain all settable params/props for the connection, * except account and password, which are set manually. */ struct ParamMapping { const gchar *tp_param; const gchar *conn_prop; } params2props[] = { MAP ("server", "explicit-server"), SAME ("resource"), SAME ("priority"), SAME ("port"), SAME ("old-ssl"), SAME ("require-encryption"), SAME ("register"), SAME ("low-bandwidth"), SAME ("https-proxy-server"), SAME ("https-proxy-port"), SAME ("fallback-conference-server"), SAME ("stun-server"), SAME ("stun-port"), SAME ("fallback-stun-server"), SAME ("fallback-stun-port"), SAME ("ignore-ssl-errors"), SAME ("alias"), SAME ("fallback-socks5-proxies"), SAME ("keepalive-interval"), MAP (TP_PROP_CONNECTION_INTERFACE_CONTACT_LIST_DOWNLOAD_AT_CONNECTION, "download-roster-at-connection"), MAP (GABBLE_PROP_CONNECTION_INTERFACE_GABBLE_DECLOAK_DECLOAK_AUTOMATICALLY, "decloak-automatically"), SAME ("fallback-servers"), SAME ("extra-certificate-identities"), SAME (NULL) }; #undef SAME #undef MAP static TpBaseConnection * new_connection (TpBaseProtocol *protocol, GHashTable *params, GError **error) { GabbleConnection *conn; guint i; conn = g_object_new (GABBLE_TYPE_CONNECTION, "protocol", PROTOCOL_NAME, "password", tp_asv_get_string (params, "password"), NULL); /* split up account into username, stream-server and resource */ if (!_gabble_connection_set_properties_from_account (conn, tp_asv_get_string (params, "account"), error)) { g_object_unref (G_OBJECT (conn)); return NULL; } /* fill in the rest of the properties */ for (i = 0; params2props[i].tp_param != NULL; i++) { GValue *val = g_hash_table_lookup (params, params2props[i].tp_param); if (val != NULL) { g_object_set_property (G_OBJECT (conn), params2props[i].conn_prop, val); } } return TP_BASE_CONNECTION (conn); } static gchar * normalize_contact (TpBaseProtocol *self G_GNUC_UNUSED, const gchar *contact, GError **error) { return gabble_normalize_contact (NULL, contact, GUINT_TO_POINTER (GABBLE_JID_GLOBAL), error); } static gchar * identify_account (TpBaseProtocol *self G_GNUC_UNUSED, GHashTable *asv, GError **error) { const gchar *account = tp_asv_get_string (asv, "account"); g_assert (account != NULL); return g_strdup (account); } static GPtrArray * get_interfaces_array (TpBaseProtocol *self) { GPtrArray *interfaces; interfaces = TP_BASE_PROTOCOL_CLASS ( gabble_jabber_protocol_parent_class)->get_interfaces_array (self); g_ptr_array_add (interfaces, TP_IFACE_PROTOCOL_INTERFACE_PRESENCE); g_ptr_array_add (interfaces, TP_IFACE_PROTOCOL_INTERFACE_ADDRESSING); return interfaces; } static const TpPresenceStatusSpec * get_presence_statuses (TpBaseProtocol *self) { return conn_presence_statuses (); } static void get_connection_details (TpBaseProtocol *self, GStrv *connection_interfaces, GType **channel_managers, gchar **icon_name, gchar **english_name, gchar **vcard_field) { if (connection_interfaces != NULL) { *connection_interfaces = g_strdupv ( (GStrv) gabble_connection_get_implemented_interfaces ()); } if (channel_managers != NULL) { GType types[] = { #ifdef ENABLE_FILE_TRANSFER GABBLE_TYPE_FT_MANAGER, #endif GABBLE_TYPE_IM_FACTORY, #ifdef ENABLE_VOIP GABBLE_TYPE_MEDIA_FACTORY, #endif GABBLE_TYPE_MUC_FACTORY, GABBLE_TYPE_ROOMLIST_MANAGER, GABBLE_TYPE_SEARCH_MANAGER, GABBLE_TYPE_PRIVATE_TUBES_FACTORY, G_TYPE_INVALID }; *channel_managers = g_memdup (types, sizeof(types)); } if (icon_name != NULL) { *icon_name = g_strdup (ICON_NAME); } if (vcard_field != NULL) { *vcard_field = g_strdup (VCARD_FIELD_NAME); } if (english_name != NULL) { *english_name = g_strdup (ENGLISH_NAME); } } static GStrv dup_authentication_types (TpBaseProtocol *self) { const gchar * const types[] = { TP_IFACE_CHANNEL_TYPE_SERVER_TLS_CONNECTION, TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION, NULL }; return g_strdupv ((GStrv) types); } static GStrv dup_supported_uri_schemes (TpBaseProtocol *self) { return g_strdupv ((gchar **) gabble_get_addressable_uri_schemes ()); } static GStrv dup_supported_vcard_fields (TpBaseProtocol *self) { return g_strdupv ((gchar **) gabble_get_addressable_vcard_fields ()); } static gchar * addressing_normalize_vcard_address (TpBaseProtocol *self, const gchar *vcard_field, const gchar *vcard_address, GError **error) { gchar *normalized_address = gabble_normalize_vcard_address (vcard_field, vcard_address, error); if (normalized_address == NULL) { /* InvalidHandle makes no sense in Protocol */ if (error != NULL && g_error_matches (*error, TP_ERROR, TP_ERROR_INVALID_HANDLE)) { (*error)->code = TP_ERROR_INVALID_ARGUMENT; } } return normalized_address; } static gchar * addressing_normalize_contact_uri (TpBaseProtocol *self, const gchar *uri, GError **error) { gchar *normalized_address = NULL; normalized_address = gabble_normalize_contact_uri (uri, error); if (normalized_address == NULL) { /* InvalidHandle makes no sense in Protocol */ if (error != NULL && g_error_matches (*error, TP_ERROR, TP_ERROR_INVALID_HANDLE)) { (*error)->code = TP_ERROR_INVALID_ARGUMENT; } } return normalized_address; } static void gabble_jabber_protocol_class_init (GabbleJabberProtocolClass *klass) { TpBaseProtocolClass *base_class = (TpBaseProtocolClass *) klass; base_class->get_parameters = get_parameters; base_class->new_connection = new_connection; base_class->normalize_contact = normalize_contact; base_class->identify_account = identify_account; base_class->get_interfaces_array = get_interfaces_array; base_class->get_connection_details = get_connection_details; base_class->get_statuses = get_presence_statuses; base_class->dup_authentication_types = dup_authentication_types; } TpBaseProtocol * gabble_jabber_protocol_new (void) { return g_object_new (GABBLE_TYPE_JABBER_PROTOCOL, "name", PROTOCOL_NAME, NULL); } static void addressing_iface_init (TpProtocolAddressingInterface *iface) { iface->dup_supported_vcard_fields = dup_supported_vcard_fields; iface->dup_supported_uri_schemes = dup_supported_uri_schemes; iface->normalize_vcard_address = addressing_normalize_vcard_address; iface->normalize_contact_uri = addressing_normalize_contact_uri; } telepathy-gabble-0.18.3/src/conn-avatars.c0000664000175000017500000007146112332441362021536 0ustar00cassidycassidy00000000000000/* * conn-avatars.c - Gabble connection avatar interface * Copyright (C) 2005-2010 Collabora Ltd. * Copyright (C) 2005-2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "conn-avatars.h" #include #include #include #include "presence.h" #include "presence-cache.h" #include "conn-presence.h" #include "namespaces.h" #include "vcard-manager.h" #include "util.h" #define DEBUG_FLAG GABBLE_DEBUG_CONNECTION #include "debug.h" /* If the SHA1 has changed, this function will copy it to self_presence, * emit a signal and push it to the server. */ static gboolean update_own_avatar_sha1 (GabbleConnection *conn, const gchar *sha1, GError **out_error) { TpBaseConnection *base = (TpBaseConnection *) conn; GError *error = NULL; /* sha1 can be "" if we know there is no avatar, but must not be NULL here */ g_assert (sha1 != NULL); if (!tp_strdiff (sha1, conn->self_presence->avatar_sha1)) return TRUE; tp_svc_connection_interface_avatars_emit_avatar_updated (conn, tp_base_connection_get_self_handle (base), sha1); g_free (conn->self_presence->avatar_sha1); conn->self_presence->avatar_sha1 = g_strdup (sha1); if (!conn_presence_signal_own_presence (conn, NULL, &error)) { DEBUG ("failed to signal changed avatar sha1 to the server: %s", error->message); g_propagate_error (out_error, error); return FALSE; } return TRUE; } static void connection_avatar_update_cb (GabblePresenceCache *cache, TpHandle handle, const gchar *sha1, gpointer user_data) { GabbleConnection *conn = GABBLE_CONNECTION (user_data); TpBaseConnection *base = (TpBaseConnection *) conn; /* sha1 can be "" if we know there is no avatar, but must not be NULL here */ g_assert (sha1 != NULL); if (handle == tp_base_connection_get_self_handle (base)) update_own_avatar_sha1 (conn, sha1, NULL); else tp_svc_connection_interface_avatars_emit_avatar_updated (conn, handle, sha1); } /* Called when our vCard is first fetched, so we can start putting the * SHA-1 of an existing avatar in our presence. */ static void connection_got_self_initial_avatar_cb (GObject *obj, gchar *sha1, gpointer user_data) { GabbleConnection *conn = GABBLE_CONNECTION (user_data); /* sha1 can be "" if we know there is no avatar, but must not be NULL here */ g_assert (sha1 != NULL); update_own_avatar_sha1 (conn, sha1, NULL); } /* Jabber prescribes no MIME type for avatars, but XEP-0153 says support * for image/png is REQUIRED, with image/jpeg and image/gif RECOMMENDED */ static const char *mimetypes[] = { "image/png", "image/jpeg", "image/gif", NULL }; /* Jabber has no min/max width/height or max size, but XEP-0153 says * you SHOULD use 32-96px either way, and no more than 8K of data */ #define AVATAR_MIN_PX 32 #define AVATAR_REC_PX 64 #define AVATAR_MAX_PX 96 #define AVATAR_MAX_BYTES 8192 /** * gabble_connection_get_avatar_requirements * * Implements D-Bus method GetAvatarRequirements * on interface org.freedesktop.Telepathy.Connection.Interface.Avatars * * @error: Used to return a pointer to a GError detailing any error * that occurred, D-Bus will throw the error only if this * function returns FALSE. * * Returns: TRUE if successful, FALSE if an error was thrown. */ static void gabble_connection_get_avatar_requirements (TpSvcConnectionInterfaceAvatars *iface, DBusGMethodInvocation *context) { TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (TP_BASE_CONNECTION (iface), context); tp_svc_connection_interface_avatars_return_from_get_avatar_requirements ( context, mimetypes, AVATAR_MIN_PX, AVATAR_MIN_PX, AVATAR_MAX_PX, AVATAR_MAX_PX, AVATAR_MAX_BYTES); } /* begin deprecated code */ typedef struct { DBusGMethodInvocation *invocation; gchar **ret; guint my_index; gulong signal_conn; } GetAvatarTokensContext; static void _got_self_avatar_for_get_avatar_tokens (GObject *obj, gchar *sha1, gpointer user_data) { GetAvatarTokensContext *context = (GetAvatarTokensContext *) user_data; g_signal_handler_disconnect (obj, context->signal_conn); g_free (context->ret[context->my_index]); context->ret[context->my_index] = g_strdup (sha1); /* Cast to (const gchar **) necessary because no-one understands 'const' * in C. */ tp_svc_connection_interface_avatars_return_from_get_avatar_tokens ( context->invocation, (const gchar **)context->ret); g_strfreev (context->ret); g_slice_free (GetAvatarTokensContext, context); } /** * gabble_connection_get_avatar_tokens * * Implements D-Bus method GetAvatarTokens * on interface org.freedesktop.Telepathy.Connection.Interface.Avatars * * @context: The D-Bus invocation context to use to return values * or throw an error. */ static void gabble_connection_get_avatar_tokens (TpSvcConnectionInterfaceAvatars *iface, const GArray *contacts, DBusGMethodInvocation *invocation) { GabbleConnection *self = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) self; gboolean wait_for_self_avatar = FALSE; gboolean have_self_avatar; guint i, my_index = 0; gchar **ret; GError *err = NULL; TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, invocation); if (!tp_handles_are_valid (contact_handles, contacts, FALSE, &err)) { dbus_g_method_return_error (invocation, err); g_error_free (err); return; } g_object_get (self->vcard_manager, "have-self-avatar", &have_self_avatar, NULL); ret = g_new0 (gchar *, contacts->len + 1); /* TODO: always call the callback so we can defer presence lookups until * we return the method, then we don't need to strdup the strings we're * returning. */ for (i = 0; i < contacts->len; i++) { TpHandle handle; GabblePresence *presence = NULL; handle = g_array_index (contacts, TpHandle, i); if (tp_base_connection_get_self_handle (base) == handle) { if (have_self_avatar) { presence = self->self_presence; } else { wait_for_self_avatar = TRUE; my_index = i; } } else { presence = gabble_presence_cache_get (self->presence_cache, handle); } if (NULL != presence && NULL != presence->avatar_sha1) ret[i] = g_strdup (presence->avatar_sha1); else ret[i] = g_strdup (""); } if (wait_for_self_avatar) { GetAvatarTokensContext *context = g_slice_new (GetAvatarTokensContext); context->invocation = invocation; context->my_index = my_index; context->ret = ret; context->signal_conn = g_signal_connect (self->vcard_manager, "got-self-initial-avatar", G_CALLBACK (_got_self_avatar_for_get_avatar_tokens), context); return; } /* Cast to (const gchar **) necessary because no-one understands 'const' * in C. */ tp_svc_connection_interface_avatars_return_from_get_avatar_tokens ( invocation, (const gchar **)ret); g_strfreev (ret); } /* end deprecated code */ typedef struct { GabbleConnection *conn; DBusGMethodInvocation *invocation; GHashTable *ret; gulong signal_conn; } GetKnownAvatarTokensContext; static void _got_self_avatar_for_get_known_avatar_tokens (GObject *obj, gchar *sha1, gpointer user_data) { GetKnownAvatarTokensContext *context = (GetKnownAvatarTokensContext *) user_data; TpBaseConnection *base = (TpBaseConnection *) context->conn; g_signal_handler_disconnect (obj, context->signal_conn); g_assert (tp_base_connection_get_self_handle (base) != 0); g_hash_table_insert (context->ret, GUINT_TO_POINTER (tp_base_connection_get_self_handle (base)), g_strdup (sha1)); tp_svc_connection_interface_avatars_return_from_get_known_avatar_tokens ( context->invocation, context->ret); g_hash_table_unref (context->ret); g_slice_free (GetKnownAvatarTokensContext, context); } /** * gabble_connection_get_known_avatar_tokens * * Implements D-Bus method GetKnownAvatarTokens * on interface org.freedesktop.Telepathy.Connection.Interface.Avatars * * @context: The D-Bus invocation context to use to return values * or throw an error. */ static void gabble_connection_get_known_avatar_tokens (TpSvcConnectionInterfaceAvatars *iface, const GArray *contacts, DBusGMethodInvocation *invocation) { GabbleConnection *self = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) self; gboolean wait_for_self_avatar = FALSE; gboolean have_self_avatar; guint i; GHashTable *ret; GError *err = NULL; TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, invocation); if (!tp_handles_are_valid (contact_handles, contacts, FALSE, &err)) { dbus_g_method_return_error (invocation, err); g_error_free (err); return; } g_object_get (self->vcard_manager, "have-self-avatar", &have_self_avatar, NULL); ret = g_hash_table_new_full (NULL, NULL, NULL, g_free); /* TODO: always call the callback so we can defer presence lookups until * we return the method, then we don't need to strdup the strings we're * returning. */ for (i = 0; i < contacts->len; i++) { TpHandle handle; GabblePresence *presence = NULL; handle = g_array_index (contacts, TpHandle, i); if (tp_base_connection_get_self_handle (base) == handle) { if (have_self_avatar) { presence = self->self_presence; } else { wait_for_self_avatar = TRUE; } } else { presence = gabble_presence_cache_get (self->presence_cache, handle); } if (NULL != presence) { if (NULL != presence->avatar_sha1) g_hash_table_insert (ret, GUINT_TO_POINTER (handle), g_strdup (presence->avatar_sha1)); else g_hash_table_insert (ret, GUINT_TO_POINTER (handle), g_strdup ("")); } } if (wait_for_self_avatar) { GetKnownAvatarTokensContext *context = g_slice_new (GetKnownAvatarTokensContext); context->conn = self; context->invocation = invocation; context->ret = ret; context->signal_conn = g_signal_connect (self->vcard_manager, "got-self-initial-avatar", G_CALLBACK (_got_self_avatar_for_get_known_avatar_tokens), context); return; } tp_svc_connection_interface_avatars_return_from_get_known_avatar_tokens ( invocation, ret); g_hash_table_unref (ret); } static gboolean parse_avatar (WockyNode *vcard, const gchar **mime_type, GString **avatar, GError **error) { WockyNode *photo_node; WockyNode *type_node; WockyNode *binval_node; const gchar *binval_value; guchar *st; gsize outlen; photo_node = wocky_node_get_child (vcard, "PHOTO"); if (NULL == photo_node) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "contact vCard has no photo"); return FALSE; } type_node = wocky_node_get_child (photo_node, "TYPE"); if (NULL != type_node) { *mime_type = type_node->content; } else { *mime_type = ""; } binval_node = wocky_node_get_child (photo_node, "BINVAL"); if (NULL == binval_node) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "contact avatar is missing binval node"); return FALSE; } binval_value = binval_node->content; if (NULL == binval_value) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "contact avatar is missing binval content"); return FALSE; } st = g_base64_decode (binval_value, &outlen); *avatar = g_string_new_len ((gchar *) st, outlen); g_free (st); if (NULL == *avatar) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "failed to decode avatar from base64"); return FALSE; } return TRUE; } static void _request_avatar_cb (GabbleVCardManager *self, GabbleVCardManagerRequest *request, TpHandle handle, WockyNode *vcard, GError *vcard_error, gpointer user_data) { DBusGMethodInvocation *context = (DBusGMethodInvocation *) user_data; GabbleConnection *conn; TpBaseConnection *base; const gchar *mime_type = NULL; GArray *arr; GError *error = NULL; GString *avatar = NULL; GabblePresence *presence; g_object_get (self, "connection", &conn, NULL); base = TP_BASE_CONNECTION (conn); if (NULL == vcard) { GError tp_error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE, vcard_error->message }; if (vcard_error->domain == WOCKY_XMPP_ERROR) { switch (vcard_error->code) { case WOCKY_XMPP_ERROR_NOT_AUTHORIZED: case WOCKY_XMPP_ERROR_FORBIDDEN: tp_error.code = TP_ERROR_PERMISSION_DENIED; break; case WOCKY_XMPP_ERROR_ITEM_NOT_FOUND: tp_error.code = TP_ERROR_DOES_NOT_EXIST; break; } /* what other mappings make sense here? */ } dbus_g_method_return_error (context, &tp_error); goto out; } if (!parse_avatar (vcard, &mime_type, &avatar, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); goto out; } if (handle == tp_base_connection_get_self_handle (base)) presence = conn->self_presence; else presence = gabble_presence_cache_get (conn->presence_cache, handle); if (presence != NULL) { gchar *sha1; sha1 = sha1_hex (avatar->str, avatar->len); if (tp_strdiff (presence->avatar_sha1, sha1)) { /* the thinking here is that we have to return an error, because we * can't give the user the vcard they're expecting, which has the * hash from the time that they requested it. */ DEBUG ("treason uncloaked! avatar hash in presence does not match " "avatar in vCard for handle %u", handle); g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "avatar hash in presence does not match avatar in vCard"); dbus_g_method_return_error (context, error); g_error_free (error); error = NULL; if (handle == tp_base_connection_get_self_handle (base)) { update_own_avatar_sha1 (conn, sha1, NULL); g_free (sha1); } else { g_free (presence->avatar_sha1); presence->avatar_sha1 = sha1; /* take ownership */ tp_svc_connection_interface_avatars_emit_avatar_updated ( conn, handle, sha1); } goto out; } g_free (sha1); } arr = g_array_new (FALSE, FALSE, sizeof (gchar)); g_array_append_vals (arr, avatar->str, avatar->len); tp_svc_connection_interface_avatars_return_from_request_avatar ( context, arr, mime_type); g_array_unref (arr); out: if (avatar != NULL) g_string_free (avatar, TRUE); g_object_unref (conn); } /** * gabble_connection_request_avatar * * Implements D-Bus method RequestAvatar * on interface org.freedesktop.Telepathy.Connection.Interface.Avatars * * @context: The D-Bus invocation context to use to return values * or throw an error. */ static void gabble_connection_request_avatar (TpSvcConnectionInterfaceAvatars *iface, guint contact, DBusGMethodInvocation *context) { GabbleConnection *self = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) self; TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); GError *err = NULL; WockyNode *vcard_node; TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); if (!tp_handle_is_valid (contact_handles, contact, &err)) { dbus_g_method_return_error (context, err); g_error_free (err); return; } if (gabble_vcard_manager_get_cached (self->vcard_manager, contact, &vcard_node)) { _request_avatar_cb (self->vcard_manager, NULL, contact, vcard_node, NULL, context); } else { gabble_vcard_manager_request (self->vcard_manager, contact, 0, _request_avatar_cb, context, NULL); } } static void emit_avatar_retrieved (TpSvcConnectionInterfaceAvatars *iface, TpHandle contact, WockyNode *vcard_node) { const gchar *mime_type; GString *avatar_str; gchar *sha1; GArray *arr; if (!parse_avatar (vcard_node, &mime_type, &avatar_str, NULL)) return; sha1 = sha1_hex (avatar_str->str, avatar_str->len); arr = g_array_new (FALSE, FALSE, sizeof (gchar)); g_array_append_vals (arr, avatar_str->str, avatar_str->len); tp_svc_connection_interface_avatars_emit_avatar_retrieved (iface, contact, sha1, arr, mime_type); g_array_unref (arr); g_free (sha1); g_string_free (avatar_str, TRUE); } /* All references are borrowed */ typedef struct { TpHandle handle; GabbleConnection *conn; TpSvcConnectionInterfaceAvatars *iface; } RequestAvatarsContext; static void request_avatars_cb (GabbleVCardManager *manager, GabbleVCardManagerRequest *request, TpHandle handle, WockyNode *vcard, GError *vcard_error, gpointer user_data) { RequestAvatarsContext *ctx = user_data; g_assert (g_hash_table_lookup (ctx->conn->avatar_requests, GUINT_TO_POINTER (ctx->handle))); g_hash_table_remove (ctx->conn->avatar_requests, GUINT_TO_POINTER (ctx->handle)); if (vcard_error == NULL) emit_avatar_retrieved (ctx->iface, handle, vcard); g_slice_free (RequestAvatarsContext, ctx); } static void gabble_connection_request_avatars (TpSvcConnectionInterfaceAvatars *iface, const GArray *contacts, DBusGMethodInvocation *context) { GabbleConnection *self = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) self; TpHandleRepoIface *contacts_repo = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); GError *error = NULL; guint i; TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); if (!tp_handles_are_valid (contacts_repo, contacts, FALSE, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); return; } for (i = 0; i < contacts->len; i++) { WockyNode *vcard_node; TpHandle contact = g_array_index (contacts, TpHandle, i); if (gabble_vcard_manager_get_cached (self->vcard_manager, contact, &vcard_node)) { emit_avatar_retrieved (iface, contact, vcard_node); } else { if (NULL == g_hash_table_lookup (self->avatar_requests, GUINT_TO_POINTER (contact))) { RequestAvatarsContext *ctx = g_slice_new (RequestAvatarsContext); ctx->conn = self; ctx->iface = iface; ctx->handle = contact; g_hash_table_insert (self->avatar_requests, GUINT_TO_POINTER (contact), ctx); gabble_vcard_manager_request (self->vcard_manager, contact, 0, request_avatars_cb, ctx, NULL); } } } tp_svc_connection_interface_avatars_return_from_request_avatars (context); } struct _set_avatar_ctx { GabbleConnection *conn; DBusGMethodInvocation *invocation; GString *avatar; }; static void _set_avatar_ctx_free (struct _set_avatar_ctx *ctx) { if (ctx->avatar) g_string_free (ctx->avatar, TRUE); g_free (ctx); } static void _set_avatar_cb2 (GabbleVCardManager *manager, GabbleVCardManagerEditRequest *request, WockyNode *vcard, GError *vcard_error, gpointer user_data) { struct _set_avatar_ctx *ctx = (struct _set_avatar_ctx *) user_data; TpBaseConnection *base = (TpBaseConnection *) ctx->conn; if (NULL == vcard) { GError tp_error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE, vcard_error->message }; /* Google Talk has been observed to return bad-request when the avatar is * too big. It's not clear what other XMPP errors make sense here, or how * to map them. */ if (vcard_error->domain == WOCKY_XMPP_ERROR) if (vcard_error->code == WOCKY_XMPP_ERROR_BAD_REQUEST || vcard_error->code == WOCKY_XMPP_ERROR_NOT_ACCEPTABLE) tp_error.code = TP_ERROR_INVALID_ARGUMENT; dbus_g_method_return_error (ctx->invocation, &tp_error); } else { GabblePresence *presence = ctx->conn->self_presence; GError *error = NULL; g_free (presence->avatar_sha1); if (ctx->avatar) { presence->avatar_sha1 = sha1_hex (ctx->avatar->str, ctx->avatar->len); } else { presence->avatar_sha1 = NULL; } if (conn_presence_signal_own_presence (ctx->conn, NULL, &error)) { tp_svc_connection_interface_avatars_return_from_set_avatar ( ctx->invocation, presence->avatar_sha1); tp_svc_connection_interface_avatars_emit_avatar_updated ( ctx->conn, tp_base_connection_get_self_handle (base), presence->avatar_sha1); } else { dbus_g_method_return_error (ctx->invocation, error); g_error_free (error); } } _set_avatar_ctx_free (ctx); } /** * gabble_connection_set_avatar * * Implements D-Bus method SetAvatar * on interface org.freedesktop.Telepathy.Connection.Interface.Avatars * * @context: The D-Bus invocation context to use to return values * or throw an error. */ static void gabble_connection_set_avatar (TpSvcConnectionInterfaceAvatars *iface, const GArray *avatar, const gchar *mime_type, DBusGMethodInvocation *context) { GabbleConnection *self = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) self; GabbleVCardManagerEditInfo *edit_info; GList *edits = NULL; struct _set_avatar_ctx *ctx; gchar *base64; TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); ctx = g_new0 (struct _set_avatar_ctx, 1); ctx->conn = self; ctx->invocation = context; if (avatar != NULL && avatar->len > 0) { gint state = 0, save = 0, outlen; /* See the documentation for g_base64_encode_step(). */ guint base64_data_size = (avatar->len / 3 + 1) * 4 + 4; guint base64_line_wrapped_data_size = base64_data_size + (base64_data_size / 72) + 1; ctx->avatar = g_string_new_len (avatar->data, avatar->len); base64 = g_malloc (base64_line_wrapped_data_size); outlen = g_base64_encode_step ((const guchar *) avatar->data, avatar->len, TRUE, base64, &state, &save); outlen += g_base64_encode_close (TRUE, base64 + outlen, &state, &save); base64[outlen] = '\0'; DEBUG ("Replacing avatar"); edit_info = gabble_vcard_manager_edit_info_new ("PHOTO", NULL, GABBLE_VCARD_EDIT_REPLACE, '(', "TYPE", '$', mime_type, ')', '(', "BINVAL", '$', base64, ')', NULL); g_free (base64); } else { DEBUG ("Removing avatar"); edit_info = gabble_vcard_manager_edit_info_new ("PHOTO", NULL, GABBLE_VCARD_EDIT_DELETE, NULL); } edits = g_list_append (edits, edit_info); gabble_vcard_manager_edit (self->vcard_manager, 0, _set_avatar_cb2, ctx, (GObject *) self, edits); } /** * gabble_connection_clear_avatar * * Implements D-Bus method ClearAvatar * on interface org.freedesktop.Telepathy.Connection.Interface.Avatars * * @context: The D-Bus invocation context to use to return values * or throw an error. */ static void gabble_connection_clear_avatar (TpSvcConnectionInterfaceAvatars *iface, DBusGMethodInvocation *context) { gabble_connection_set_avatar (iface, NULL, NULL, context); } static void conn_avatars_fill_contact_attributes (GObject *obj, const GArray *contacts, GHashTable *attributes_hash) { guint i; GabbleConnection *self = GABBLE_CONNECTION(obj); TpBaseConnection *base = (TpBaseConnection *) self; for (i = 0; i < contacts->len; i++) { TpHandle handle = g_array_index (contacts, guint, i); GabblePresence *presence = NULL; if (tp_base_connection_get_self_handle (base) == handle) presence = self->self_presence; else presence = gabble_presence_cache_get (self->presence_cache, handle); if (NULL != presence) { GValue *val = tp_g_value_slice_new (G_TYPE_STRING); if (NULL != presence->avatar_sha1) g_value_set_string (val, presence->avatar_sha1); else g_value_set_string (val, ""); tp_contacts_mixin_set_contact_attribute (attributes_hash, handle, TP_IFACE_CONNECTION_INTERFACE_AVATARS"/token", val); } } } void conn_avatars_init (GabbleConnection *conn) { g_assert (conn->vcard_manager != NULL); g_signal_connect (conn->vcard_manager, "got-self-initial-avatar", G_CALLBACK (connection_got_self_initial_avatar_cb), conn); g_signal_connect (conn->presence_cache, "avatar-update", G_CALLBACK (connection_avatar_update_cb), conn); tp_contacts_mixin_add_contact_attributes_iface (G_OBJECT (conn), TP_IFACE_CONNECTION_INTERFACE_AVATARS, conn_avatars_fill_contact_attributes); } void conn_avatars_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcConnectionInterfaceAvatarsClass *klass = g_iface; #define IMPLEMENT(x) tp_svc_connection_interface_avatars_implement_##x (\ klass, gabble_connection_##x) IMPLEMENT(get_avatar_requirements); IMPLEMENT(get_avatar_tokens); IMPLEMENT(get_known_avatar_tokens); IMPLEMENT(request_avatar); IMPLEMENT(request_avatars); IMPLEMENT(set_avatar); IMPLEMENT(clear_avatar); #undef IMPLEMENT } static TpDBusPropertiesMixinPropImpl props[] = { { "MinimumAvatarWidth", GUINT_TO_POINTER (AVATAR_MIN_PX), NULL }, { "RecommendedAvatarWidth", GUINT_TO_POINTER (AVATAR_REC_PX), NULL }, { "MaximumAvatarWidth", GUINT_TO_POINTER (AVATAR_MAX_PX), NULL }, { "MinimumAvatarHeight", GUINT_TO_POINTER (AVATAR_MIN_PX), NULL }, { "RecommendedAvatarHeight", GUINT_TO_POINTER (AVATAR_REC_PX), NULL }, { "MaximumAvatarHeight", GUINT_TO_POINTER (AVATAR_MAX_PX), NULL }, { "MaximumAvatarBytes", GUINT_TO_POINTER (AVATAR_MAX_BYTES), NULL }, /* special-cased - it's the only one with a non-guint value */ { "SupportedAvatarMIMETypes", NULL, NULL }, { NULL } }; TpDBusPropertiesMixinPropImpl *conn_avatars_properties = props; void conn_avatars_properties_getter (GObject *object, GQuark interface, GQuark name, GValue *value, gpointer getter_data) { GQuark q_mime_types = g_quark_from_static_string ( "SupportedAvatarMIMETypes"); if (name == q_mime_types) { g_value_set_static_boxed (value, mimetypes); } else { g_value_set_uint (value, GPOINTER_TO_UINT (getter_data)); } } telepathy-gabble-0.18.3/src/connection-manager.c0000664000175000017500000000511112223562023022673 0ustar00cassidycassidy00000000000000/* * gabble-connection-manager.c - Source for GabbleConnectionManager * Copyright (C) 2005-2007 Collabora Ltd. * Copyright (C) 2005-2007 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "connection-manager.h" #include #include #include #include #include #include #include "connection.h" #include "debug.h" #include "extensions/extensions.h" #include "protocol.h" G_DEFINE_TYPE(GabbleConnectionManager, gabble_connection_manager, TP_TYPE_BASE_CONNECTION_MANAGER) /* type definition stuff */ static void gabble_connection_manager_init (GabbleConnectionManager *self) { } static void gabble_connection_manager_constructed (GObject *object) { GabbleConnectionManager *self = GABBLE_CONNECTION_MANAGER (object); TpBaseConnectionManager *base = (TpBaseConnectionManager *) self; void (*constructed) (GObject *) = ((GObjectClass *) gabble_connection_manager_parent_class)->constructed; TpBaseProtocol *protocol; if (constructed != NULL) constructed (object); protocol = gabble_jabber_protocol_new (); tp_base_connection_manager_add_protocol (base, protocol); g_object_unref (protocol); } static void gabble_connection_manager_finalize (GObject *object) { wocky_caps_cache_free_shared (); gabble_debug_free (); G_OBJECT_CLASS (gabble_connection_manager_parent_class)->finalize (object); } static void gabble_connection_manager_class_init (GabbleConnectionManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); TpBaseConnectionManagerClass *base_class = (TpBaseConnectionManagerClass *) klass; base_class->cm_dbus_name = "gabble"; object_class->constructed = gabble_connection_manager_constructed; object_class->finalize = gabble_connection_manager_finalize; } telepathy-gabble-0.18.3/src/conn-sidecars.h0000664000175000017500000000230112332441362021662 0ustar00cassidycassidy00000000000000/* * conn-sidecars.h - Header for Gabble connection implementation of sidecars * Copyright © 2009 Collabora Ltd. * Copyright © 2009 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __CONN_SIDECARS_H__ #define __CONN_SIDECARS_H__ #include "connection.h" G_BEGIN_DECLS void conn_sidecars_init (GabbleConnection *conn); void conn_sidecars_dispose (GabbleConnection *conn); void conn_future_iface_init (gpointer g_iface, gpointer iface_data); G_END_DECLS #endif /* __CONN_SIDECARS_H__ */ telepathy-gabble-0.18.3/src/conn-power-saving.c0000664000175000017500000001237012332440117022505 0ustar00cassidycassidy00000000000000/* * conn-power-saving.c - Header for Gabble connection code handling power saving * Copyright (C) 2010 Collabora Ltd. * Copyright (C) 2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "conn-power-saving.h" #define DEBUG_FLAG GABBLE_DEBUG_CONNECTION #include "debug.h" #include "namespaces.h" #include "util.h" #include "conn-util.h" #include enum { PROP_POWER_SAVING_ACTIVE, NUM_OF_PROP, }; typedef struct { DBusGMethodInvocation *dbus_context; gboolean enabling; } ToggleQueueingContext; static void google_queueing_send_command ( GabbleConnection *conn, const gchar *command, GAsyncReadyCallback callback, gpointer user_data) { WockyStanza *stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL, '(', "query", ':', NS_GOOGLE_QUEUE, '(', command, ')', ')', NULL); conn_util_send_iq_async (conn, stanza, NULL, callback, user_data); g_object_unref (stanza); } static void maybe_emit_power_saving_changed (GabbleConnection *self, gboolean enabling) { gboolean enabled; g_object_get (self, "power-saving", &enabled, NULL); if (enabling != enabled) { g_object_set (self, "power-saving", enabling, NULL); tp_svc_connection_interface_power_saving_emit_power_saving_changed ( self, enabling); } } static void toggle_google_queueing_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GabbleConnection *self = GABBLE_CONNECTION (source_object); ToggleQueueingContext *queueing_context = (ToggleQueueingContext *) user_data; GError *error = NULL; gboolean enabling; enabling = queueing_context->enabling; if (!conn_util_send_iq_finish (self, res, NULL, &error)) { DEBUG ("Failed to %sable queueing: %s", enabling ? "en" : "dis", error->message); enabling = FALSE; dbus_g_method_return_error (queueing_context->dbus_context, error); g_error_free (error); } else { DEBUG ("%sabled queueing", enabling ? "en" : "dis"); tp_svc_connection_interface_power_saving_return_from_set_power_saving ( queueing_context->dbus_context); if (!enabling) google_queueing_send_command (self, "flush", NULL, NULL); } maybe_emit_power_saving_changed (self, enabling); g_slice_free (ToggleQueueingContext, queueing_context); } static void conn_power_saving_set_power_saving ( TpSvcConnectionInterfacePowerSaving *conn, gboolean enable, DBusGMethodInvocation *context) { GabbleConnection *self = GABBLE_CONNECTION (conn); TpBaseConnection *base = TP_BASE_CONNECTION (self); gboolean enabled; TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); g_object_get (G_OBJECT (self), "power-saving", &enabled, NULL); if (enable == enabled) { /* no-op */ tp_svc_connection_interface_power_saving_return_from_set_power_saving ( context); return; } DEBUG ("%sabling presence queueing", enable ? "en" : "dis"); /* google:queue is loosely described here: * . Since * April 2011, it is advertised as a stream feature by the Google Talk * server; the development version of M-Link, and possibly other servers, * also implement the protocol and advertise this stream feature. */ if (self->features & GABBLE_CONNECTION_FEATURES_GOOGLE_QUEUE) { ToggleQueueingContext *queueing_context; queueing_context = g_slice_new0 (ToggleQueueingContext); queueing_context->enabling = enable; queueing_context->dbus_context = context; google_queueing_send_command (self, enable ? "enable" : "disable", toggle_google_queueing_cb, queueing_context); } else { /* If the server doesn't support any method of queueing, we can still * do it locally by enabling power save mode on Wocky. */ WockyPorter *porter = gabble_connection_dup_porter (self); wocky_c2s_porter_enable_power_saving_mode (WOCKY_C2S_PORTER (porter), enable); DEBUG ("%sabled local stanza queueing", enable ? "En" : "Dis"); g_object_unref (porter); maybe_emit_power_saving_changed (self, enable); tp_svc_connection_interface_power_saving_return_from_set_power_saving ( context); } } void conn_power_saving_iface_init (gpointer g_iface, gpointer iface_data) { #define IMPLEMENT(x) \ tp_svc_connection_interface_power_saving_implement_##x (\ g_iface, conn_power_saving_##x) IMPLEMENT (set_power_saving); #undef IMPLEMENT } telepathy-gabble-0.18.3/src/presence-cache.h0000664000175000017500000001212112332440117021775 0ustar00cassidycassidy00000000000000/* * gabble-presence-cache.h - Headers for Gabble's contact presence cache * Copyright (C) 2005 Collabora Ltd. * Copyright (C) 2005 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_PRESENCE_CACHE_H__ #define __GABBLE_PRESENCE_CACHE_H__ #include #include "presence.h" G_BEGIN_DECLS #define GABBLE_TYPE_PRESENCE_CACHE gabble_presence_cache_get_type () #define GABBLE_PRESENCE_CACHE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ GABBLE_TYPE_PRESENCE_CACHE, GabblePresenceCache)) #define GABBLE_PRESENCE_CACHE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), \ GABBLE_TYPE_PRESENCE_CACHE, GabblePresenceCacheClass)) #define GABBLE_IS_PRESENCE_CACHE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ GABBLE_TYPE_PRESENCE_CACHE)) #define GABBLE_IS_PRESENCE_CACHE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), \ GABBLE_TYPE_PRESENCE_CACHE)) #define GABBLE_PRESENCE_CACHE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ GABBLE_TYPE_PRESENCE_CACHE, GabblePresenceCacheClass)) #define JABBER_PRESENCE_SHOW_AWAY "away" #define JABBER_PRESENCE_SHOW_CHAT "chat" #define JABBER_PRESENCE_SHOW_DND "dnd" #define JABBER_PRESENCE_SHOW_XA "xa" typedef struct _GabbleCapabilityInfo GabbleCapabilityInfo; struct _GabbleCapabilityInfo { /* struct _GabbleCapabilityInfo can be allocated before receiving the contact's * caps. In this case, cap_set is NULL. */ GabbleCapabilitySet *cap_set; /* array of GabbleDiscoIdentity or NULL */ GPtrArray *identities; /* array of WockyDataForm or NULL */ GPtrArray *data_forms; TpIntset *guys; guint trust; /* bitfield of GabbleClientType flags */ guint client_types; /* TRUE if this cache entry is one of our own, so between caps and * per_channel_manager_caps it holds the complete set of features for the * node. */ gboolean complete; }; typedef struct _GabblePresenceCachePrivate GabblePresenceCachePrivate; struct _GabblePresenceCache { GObject parent; GabblePresenceCachePrivate *priv; }; typedef struct _GabblePresenceCacheClass GabblePresenceCacheClass; struct _GabblePresenceCacheClass { GObjectClass parent_class; }; GType gabble_presence_cache_get_type (void); GabblePresenceCache *gabble_presence_cache_new (GabbleConnection *conn); GabblePresence *gabble_presence_cache_get (GabblePresenceCache *cache, TpHandle handle); GabblePresence *gabble_presence_cache_get_for_contact ( GabblePresenceCache *cache, WockyContact *contact); void gabble_presence_cache_update (GabblePresenceCache *cache, TpHandle handle, const gchar *resource, GabblePresenceId presence_id, const gchar *status_message, gint8 priority); void gabble_presence_cache_update_many (GabblePresenceCache *cache, const GArray *contact_handles, const gchar *resource, GabblePresenceId presence_id, const gchar *status_message, gint8 priority); void gabble_presence_cache_maybe_remove (GabblePresenceCache *cache, TpHandle handle); void gabble_presence_cache_add_own_caps (GabblePresenceCache *cache, const gchar *ver, const GabbleCapabilitySet *cap_set, const GPtrArray *identities, GPtrArray *data_forms); const GabbleCapabilityInfo *gabble_presence_cache_peek_own_caps ( GabblePresenceCache *cache, const gchar *ver); void gabble_presence_cache_really_remove (GabblePresenceCache *cache, TpHandle handle); gboolean gabble_presence_parse_presence_message ( GabblePresenceCache *cache, TpHandle handle, const gchar *from, WockyStanza *message); void gabble_presence_cache_contacts_added_to_olpc_view ( GabblePresenceCache *cache, TpHandleSet *handles); void gabble_presence_cache_contacts_removed_from_olpc_view ( GabblePresenceCache *cache, TpHandleSet *handles); gboolean gabble_presence_cache_is_unsure (GabblePresenceCache *cache, TpHandle handle); gboolean gabble_presence_cache_request_decloaking (GabblePresenceCache *self, TpHandle handle, const gchar *reason); void gabble_presence_cache_update_location (GabblePresenceCache *cache, TpHandle handle, GHashTable *location); GHashTable* gabble_presence_cache_get_location (GabblePresenceCache *cache, TpHandle handle); gboolean gabble_presence_cache_disco_in_progress (GabblePresenceCache *cache, TpHandle handle, const gchar *resource); TpHandle gabble_presence_cache_get_handle (GabblePresenceCache *cache, GabblePresence *presence); G_END_DECLS #endif /* __GABBLE_PRESENCE_CACHE_H__ */ telepathy-gabble-0.18.3/src/search-channel.c0000664000175000017500000010607312332441362022013 0ustar00cassidycassidy00000000000000/* * search-channel.c - implementation of ContactSearch channels * Copyright (C) 2009 Collabora Ltd. * Copyright (C) 2009 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "search-channel.h" #include #include #include #include #define DEBUG_FLAG GABBLE_DEBUG_SEARCH #include #include "connection.h" #include "debug.h" #include "gabble-signals-marshal.h" #include "namespaces.h" #include "util.h" /* properties */ enum { PROP_SEARCH_STATE = 1, PROP_AVAILABLE_SEARCH_KEYS, PROP_SERVER, PROP_LIMIT, LAST_PROPERTY }; /* signal enum */ enum { READY_OR_NOT, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; /* private structure */ struct _GabbleSearchChannelPrivate { TpChannelContactSearchState state; gchar **available_search_keys; gchar *server; gboolean xforms; /* owned tp_name (gchar *) => owned xmpp_name (gchar *) * This mapping contains the fields that are supported by the server so * if a tp_name can be mapped to different xmpp_name, the hash table will * map to the one supported. */ GHashTable *tp_to_xmpp; /* Array of owned (gchar *) containing all the boolean search terms * supported by this server. */ GPtrArray *boolean_keys; GHashTable *results; /* TRUE if the channel is ready to be used (we received the keys supported * by the server). */ gboolean ready; TpHandleSet *result_handles; }; /* Human-readable values of TpChannelContactSearchState. */ static const gchar *states[] = { "not started", "in progress", "more available", "completed", "failed", }; static void contact_search_iface_init (gpointer, gpointer); G_DEFINE_TYPE_WITH_CODE (GabbleSearchChannel, gabble_search_channel, TP_TYPE_BASE_CHANNEL, G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_CONTACT_SEARCH, contact_search_iface_init); ) /* Mapping between XEP 0055/misc data forms fields seen in the wild and * vCard/Telepathy names. */ typedef struct { gchar *xmpp_name; gchar *tp_name; } FieldNameMapping; /* XMPP is not clear about the semantic of "first" and "last". We asked for * clarifications on the standards mailing list and got confirmation * that "first" is actually "Given Name" and "last" is "Family Name". * See http://mail.jabber.org/pipermail/standards/2009-August/022530.html */ static const FieldNameMapping field_mappings[] = { /* Fields specified for non-Data Forms searches */ { "first", "x-n-given" }, { "last", "x-n-family" }, { "nick", "nickname" }, { "email", "email" }, /* Fields observed in implementations of Data Forms searches */ /* ejabberd */ { "user", "x-telepathy-identifier" }, { "fn", "fn" }, { "middle", "x-n-additional" }, { "bday", "bday" }, { "ctry", "x-adr-country" }, { "locality", "x-adr-locality" }, { "x-gender", "x-gender" }, { "orgname", "x-org-name" }, { "orgunit", "x-org-unit" }, { "given", "x-n-given" }, { "family", "x-n-family" }, { "nickname", "nickname" }, /* openfire */ { "search", "" }, /* one big search box */ { "Name", "fn" }, { "Email", "email" }, /* openfire also includes "Username" which is the user part of the jid */ { NULL, NULL }, }; #define NUM_UNEXTENDED_FIELDS 4 static GHashTable *xmpp_to_tp = NULL; static GHashTable *unextended_xmpp_to_tp = NULL; static void build_mapping_tables (void) { guint i; g_return_if_fail (xmpp_to_tp == NULL); xmpp_to_tp = g_hash_table_new (g_str_hash, g_str_equal); unextended_xmpp_to_tp = g_hash_table_new (g_str_hash, g_str_equal); for (i = 0; i < NUM_UNEXTENDED_FIELDS; i++) { g_hash_table_insert (xmpp_to_tp, field_mappings[i].xmpp_name, field_mappings[i].tp_name); } tp_g_hash_table_update (unextended_xmpp_to_tp, xmpp_to_tp, NULL, NULL); for (; field_mappings[i].xmpp_name != NULL; i++) { g_hash_table_insert (xmpp_to_tp, field_mappings[i].xmpp_name, field_mappings[i].tp_name); } } /* Supported field */ static void supported_fields_discovered (GabbleSearchChannel *chan) { DEBUG ("called"); tp_base_channel_register ((TpBaseChannel *) chan); chan->priv->ready = TRUE; g_signal_emit (chan, signals[READY_OR_NOT], 0, 0, 0, NULL); } static void supported_field_discovery_failed (GabbleSearchChannel *chan, const GError *error) { DEBUG ("called: %s, %u, %s", g_quark_to_string (error->domain), error->code, error->message); g_signal_emit (chan, signals[READY_OR_NOT], 0, error->domain, error->code, error->message); } static GPtrArray * parse_unextended_field_response ( GabbleSearchChannel *self, WockyNode *query_node, GError **error) { GPtrArray *search_keys = g_ptr_array_new (); WockyNodeIter i; WockyNode *field; wocky_node_iter_init (&i, query_node, NULL, NULL); while (wocky_node_iter_next (&i, &field)) { gchar *tp_name; if (!strcmp (field->name, "instructions")) { DEBUG ("server gave us some instructions: %s", field->content); continue; } tp_name = g_hash_table_lookup (unextended_xmpp_to_tp, field->name); if (tp_name != NULL) { g_ptr_array_add (search_keys, tp_name); g_hash_table_insert (self->priv->tp_to_xmpp, g_strdup (tp_name), g_strdup (field->name)); } else { g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "server is broken: %s is not a field defined in XEP 0055", field->name); g_ptr_array_unref (search_keys); return NULL; } } return search_keys; } static gboolean name_in_array (GPtrArray *array, const gchar *name) { guint i; for (i = 0; i < array->len; i++) { if (!tp_strdiff (g_ptr_array_index (array, i), name)) return TRUE; } return FALSE; } static GPtrArray * parse_data_form ( GabbleSearchChannel *self, WockyNode *x_node, GError **error) { GPtrArray *search_keys = g_ptr_array_new (); WockyNodeIter i; WockyNode *n; if (tp_strdiff (wocky_node_get_attribute (x_node, "type"), "form")) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "server is broken: not type='form'"); goto fail; } wocky_node_iter_init (&i, x_node, NULL, NULL); while (wocky_node_iter_next (&i, &n)) { const gchar *type = wocky_node_get_attribute (n, "type"); const gchar *var = wocky_node_get_attribute (n, "var"); gchar *tp_name; if (!strcmp (n->name, "title") || !strcmp (n->name, "instructions")) { DEBUG ("ignoring <%s>: %s", n->name, n->content); continue; } if (strcmp (n->name, "field")) { /* and don't make sense here, and nothing else is * legal. */ DEBUG ("<%s> is not , <instructions> or <field>", n->name); continue; } if (!strcmp (var, "FORM_TYPE")) { const gchar *form_type = wocky_node_get_content_from_child (n, "value"); if (tp_strdiff (form_type, NS_SEARCH)) { DEBUG ("<x> form does not have FORM_TYPE %s", NS_SEARCH); g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "server is broken: form lacking FORM_TYPE %s", NS_SEARCH); goto fail; } continue; } /* Openfire's search plugin has one search box, called "search", and * tickyboxes controlling which fields it searches. * * So: if the only non-tickybox is a field called "search", expose that * field as "", and remember the tickyboxes. When submitting the form, * tick them all (XXX: or maybe have a whitelist?) */ if (!tp_strdiff (type, "boolean")) { g_ptr_array_add (self->priv->boolean_keys, g_strdup (var)); continue; } tp_name = g_hash_table_lookup (xmpp_to_tp, var); if (tp_name != NULL) { if (name_in_array (search_keys, tp_name)) { DEBUG ("%s has already been added as a search key; Skipping", tp_name); } else { g_ptr_array_add (search_keys, tp_name); g_hash_table_insert (self->priv->tp_to_xmpp, g_strdup (tp_name), g_strdup (var)); } } else { DEBUG ("Unknown data form field: %s\n", var); } } return search_keys; fail: g_ptr_array_unref (search_keys); return NULL; } static void parse_search_field_response (GabbleSearchChannel *chan, WockyNode *query_node) { WockyNode *x_node; GPtrArray *search_keys = NULL; GError *e = NULL; g_return_if_fail (query_node != NULL); x_node = wocky_node_get_child_ns (query_node, "x", NS_X_DATA); if (x_node == NULL) { chan->priv->xforms = FALSE; search_keys = parse_unextended_field_response (chan, query_node, &e); } else { chan->priv->xforms = TRUE; search_keys = parse_data_form (chan, x_node, &e); } if (search_keys == NULL) { supported_field_discovery_failed (chan, e); g_error_free (e); return; } DEBUG ("extracted available fields"); g_ptr_array_add (search_keys, NULL); chan->priv->available_search_keys = (gchar **) g_ptr_array_free (search_keys, FALSE); supported_fields_discovered (chan); } static void query_reply_cb (GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg, GObject *object, gpointer user_data) { GabbleSearchChannel *chan = GABBLE_SEARCH_CHANNEL (object); WockyNode *query_node; GError *err = NULL; query_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (reply_msg), "query", NS_SEARCH); if (wocky_stanza_extract_errors (reply_msg, NULL, &err, NULL, NULL)) { /* pass */ } else if (NULL == query_node) { err = g_error_new (TP_ERROR, TP_ERROR_NOT_AVAILABLE, "%s is broken: it replied to our <query> with an empty IQ", chan->priv->server); } else { parse_search_field_response (chan, query_node); } if (err != NULL) { supported_field_discovery_failed (chan, err); g_error_free (err); } } static void request_search_fields (GabbleSearchChannel *chan) { TpBaseChannel *base = TP_BASE_CHANNEL (chan); TpBaseConnection *base_conn = tp_base_channel_get_connection (base); WockyStanza *msg; GError *error = NULL; msg = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, chan->priv->server, '(', "query", ':', NS_SEARCH, ')', NULL); if (! _gabble_connection_send_with_reply (GABBLE_CONNECTION (base_conn), msg, query_reply_cb, (GObject *) chan, NULL, &error)) { supported_field_discovery_failed (chan, error); g_error_free (error); } g_object_unref (msg); } /* Search implementation */ /** * change_search_state: * @chan: a search channel * @state: the new state for the channel * @reason: an error in the TP_ERROR domain if the search has failed; NULL * otherwise. */ static void change_search_state (GabbleSearchChannel *chan, TpChannelContactSearchState state, const GError *reason) { GabbleSearchChannelPrivate *priv = chan->priv; GHashTable *details = g_hash_table_new (g_str_hash, g_str_equal); const gchar *error_name = NULL; GValue v = { 0, }; switch (state) { case TP_CHANNEL_CONTACT_SEARCH_STATE_NOT_STARTED: /* Gabble shouldn't ever get into state More_Available */ case TP_CHANNEL_CONTACT_SEARCH_STATE_MORE_AVAILABLE: g_assert_not_reached (); return; case TP_CHANNEL_CONTACT_SEARCH_STATE_IN_PROGRESS: g_assert (priv->state == TP_CHANNEL_CONTACT_SEARCH_STATE_NOT_STARTED); break; case TP_CHANNEL_CONTACT_SEARCH_STATE_COMPLETED: case TP_CHANNEL_CONTACT_SEARCH_STATE_FAILED: g_assert (priv->state == TP_CHANNEL_CONTACT_SEARCH_STATE_IN_PROGRESS); break; } if (state == TP_CHANNEL_CONTACT_SEARCH_STATE_FAILED) { g_assert (reason != NULL); g_assert (reason->domain == TP_ERROR); error_name = tp_error_get_dbus_name (reason->code); g_value_init (&v, G_TYPE_STRING); g_value_set_static_string (&v, reason->message); g_hash_table_insert (details, "debug-message", &v); } else { g_assert (reason == NULL); } DEBUG ("moving from %s to %s for reason '%s'", states[priv->state], states[state], error_name == NULL ? "" : error_name); priv->state = state; tp_svc_channel_type_contact_search_emit_search_state_changed ( chan, state, (error_name == NULL ? "" : error_name), details); g_hash_table_unref (details); } /** * make_field: * @field_name: name of a vCard field; must be a static string. * @values: strv of values for the field. * * Returns: the Contact_Info_Field (field_name, [], values). */ static GValueArray * make_field (const gchar *field_name, gchar **values) { GValueArray *field = g_value_array_new (3); GValue *value; static const gchar **empty = { NULL }; g_value_array_append (field, NULL); value = g_value_array_get_nth (field, 0); g_value_init (value, G_TYPE_STRING); g_value_set_static_string (value, field_name); g_value_array_append (field, NULL); value = g_value_array_get_nth (field, 1); g_value_init (value, G_TYPE_STRV); g_value_set_static_boxed (value, empty); g_value_array_append (field, NULL); value = g_value_array_get_nth (field, 2); g_value_init (value, G_TYPE_STRV); g_value_set_boxed (value, values); return field; } static gchar * ht_lookup_and_remove (GHashTable *info_map, gchar *field_name) { gchar *ret = g_hash_table_lookup (info_map, field_name); g_hash_table_remove (info_map, field_name); return ret; } static void add_search_result (GabbleSearchChannel *chan, GHashTable *info_map) { GPtrArray *info = g_ptr_array_new (); gchar *jid, *first = NULL, *last = NULL; gpointer key, value; GHashTableIter iter; jid = ht_lookup_and_remove (info_map, "jid"); if (jid == NULL) { DEBUG ("no jid; giving up"); return; } if (!wocky_decode_jid (jid, NULL, NULL, NULL)) { DEBUG ("'%s' is not a valid jid; ignoring this result", jid); return; } g_hash_table_iter_init (&iter, info_map); while (g_hash_table_iter_next (&iter, &key, &value)) { const gchar *tp_name; gchar *components[] = { value, NULL }; tp_name = g_hash_table_lookup (xmpp_to_tp, key); if (tp_name == NULL) { DEBUG ("<item> contained field we don't understand (%s); ignoring it:" , (const gchar *) key); continue; } if (value == NULL) { DEBUG ("field %s (%s) doesn't have a value; ignoring it", (const gchar *) key, tp_name); continue; } DEBUG ("found field %s (%s): %s", (const gchar *) key, tp_name, (const gchar *) value); g_ptr_array_add (info, make_field (tp_name, components)); if (!tp_strdiff (key, "last") || !tp_strdiff (key, "family")) last = value; else if (!tp_strdiff (key, "first") || !tp_strdiff (key, "given")) first = value; } /* Build 'n' field: Family Name, Given Name, Additional Names, Honorific * Prefixes, and Honorific Suffixes. */ if (last != NULL || first != NULL) { gchar *components[] = { (last == NULL ? "" : last), (first == NULL ? "" : first), "", "", "", NULL }; g_ptr_array_add (info, make_field ("n", components)); } g_hash_table_insert (chan->priv->results, g_strdup (jid), info); } static void parse_result_item (GabbleSearchChannel *chan, WockyNode *item) { const gchar *jid = wocky_node_get_attribute (item, "jid"); GHashTable *info; WockyNodeIter i; WockyNode *n; if (jid == NULL) { DEBUG ("<item> didn't have a jid attribute; skipping"); return; } info = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_insert (info, "jid", (gchar *) jid); wocky_node_iter_init (&i, item, NULL, NULL); while (wocky_node_iter_next (&i, &n)) { gchar *value = (gchar *) n->content; g_hash_table_insert (info, n->name, value); } add_search_result (chan, info); g_hash_table_unref (info); } static void parse_extended_result_item (GabbleSearchChannel *chan, WockyNode *item) { GHashTable *info = g_hash_table_new (g_str_hash, g_str_equal); WockyNodeIter i; WockyNode *field; wocky_node_iter_init (&i, item, "field", NULL); while (wocky_node_iter_next (&i, &field)) { WockyNode *value_node; const gchar *var, *value; var = wocky_node_get_attribute (field, "var"); if (var == NULL) { DEBUG ("Ignore <field/> without 'var' attribut"); continue; } value_node = wocky_node_get_child (field, "value"); if (value_node == NULL) { DEBUG ("Ignore <field/> without <value/> child"); continue; } value = value_node->content; g_hash_table_insert (info, (gchar *) var, (gchar *) value); } if (g_hash_table_lookup (info, "jid") == NULL) { DEBUG ("<item> didn't have a jid attribute; skipping"); } else { add_search_result (chan, info); } g_hash_table_unref (info); } static gboolean parse_unextended_search_results (GabbleSearchChannel *chan, WockyNode *query_node, GError **error) { WockyNodeIter i; WockyNode *item; wocky_node_iter_init (&i, query_node, "item", NULL); while (wocky_node_iter_next (&i, &item)) { parse_result_item (chan, item); } return TRUE; } static gboolean parse_extended_search_results (GabbleSearchChannel *chan, WockyNode *query_node, GError **error) { WockyNode *x, *item; WockyNodeIter i; x = wocky_node_get_child_ns (query_node, "x", NS_X_DATA); if (x == NULL) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "reply doens't contain a <x> node"); return FALSE; } wocky_node_iter_init (&i, x, NULL, NULL); while (wocky_node_iter_next (&i, &item)) { if (!tp_strdiff (item->name, "item")) parse_extended_result_item (chan, item); else if (!tp_strdiff (item->name, "reported")) /* Ignore <reported> node */ continue; else if (!tp_strdiff (item->name, "title")) DEBUG ("title: %s", item->content); else DEBUG ("found <%s/> in <x/> rather than <item/>, <title/> and " "<reported/>, skipping", item->name); } return TRUE; } static gboolean parse_search_results (GabbleSearchChannel *chan, WockyNode *query_node, GError **error) { if (chan->priv->xforms) return parse_extended_search_results (chan, query_node, error); else return parse_unextended_search_results (chan, query_node, error); } static void search_reply_cb (GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg, GObject *object, gpointer user_data) { GabbleSearchChannel *chan = GABBLE_SEARCH_CHANNEL (object); WockyNode *query_node; GError *stanza_error = NULL; GError *err = NULL; DEBUG ("called"); if (chan->priv->state != TP_CHANNEL_CONTACT_SEARCH_STATE_IN_PROGRESS) { DEBUG ("state is %s, not in progress; ignoring results", states[chan->priv->state]); return; } query_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (reply_msg), "query", NS_SEARCH); if (wocky_stanza_extract_errors (reply_msg, NULL, &stanza_error, NULL, NULL)) { gabble_set_tp_error_from_wocky (stanza_error, &err); g_clear_error (&stanza_error); } else if (NULL == query_node) { err = g_error_new (TP_ERROR, TP_ERROR_NOT_AVAILABLE, "%s is broken: its iq reply didn't contain a <query/>", chan->priv->server); } else { parse_search_results (chan, query_node, &err); } if (err == NULL) { /* fire SearchStateChanged */ tp_svc_channel_type_contact_search_emit_search_result_received (chan, chan->priv->results); change_search_state (chan, TP_CHANNEL_CONTACT_SEARCH_STATE_COMPLETED, NULL); } else { DEBUG ("Searching failed: %s", err->message); change_search_state (chan, TP_CHANNEL_CONTACT_SEARCH_STATE_FAILED, err); g_error_free (err); } } static gboolean validate_terms (GabbleSearchChannel *chan, GHashTable *terms, GError **error) { const gchar * const *asks = (const gchar * const *) chan->priv->available_search_keys; GHashTableIter iter; gpointer key; g_hash_table_iter_init (&iter, terms); while (g_hash_table_iter_next (&iter, &key, NULL)) { gchar *field = key; if (!tp_strv_contains (asks, field)) { DEBUG ("%s is not in AvailableSearchKeys", field); g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "%s is not in AvailableSearchKeys", field); return FALSE; } } return TRUE; } static void build_unextended_query ( GabbleSearchChannel *self, WockyNode *query, GHashTable *terms) { GHashTableIter iter; gpointer key, value; g_hash_table_iter_init (&iter, terms); while (g_hash_table_iter_next (&iter, &key, &value)) { gchar *xmpp_field = g_hash_table_lookup (self->priv->tp_to_xmpp, key); g_assert (xmpp_field != NULL); wocky_node_add_child_with_content (query, xmpp_field, value); } } static void build_extended_query (GabbleSearchChannel *self, WockyNode *query, GHashTable *terms) { WockyNode *x, *field; GHashTableIter iter; gpointer key, value; x = wocky_node_add_child_ns_q (query, "x", g_quark_from_static_string (NS_X_DATA)); wocky_node_set_attribute (x, "type", "submit"); /* add FORM_TYPE */ field = wocky_node_add_child (x, "field"); wocky_node_set_attributes (field, "type", "hidden", "var", "FORM_TYPE", NULL); wocky_node_add_child_with_content (field, "value", NS_SEARCH); /* Add search terms */ g_hash_table_iter_init (&iter, terms); while (g_hash_table_iter_next (&iter, &key, &value)) { const gchar *tp_name = key; gchar *xmpp_field = g_hash_table_lookup (self->priv->tp_to_xmpp, tp_name); g_assert (xmpp_field != NULL); field = wocky_node_add_child (x, "field"); wocky_node_set_attribute (field, "var", xmpp_field); wocky_node_add_child_with_content (field, "value", value); if (!tp_strdiff (tp_name, "")) { /* Open fire search. Tick all the boolean fields */ guint i; for (i = 0; i < self->priv->boolean_keys->len; i++) { xmpp_field = g_ptr_array_index (self->priv->boolean_keys, i); field = wocky_node_add_child (x, "field"); wocky_node_set_attributes (field, "var", xmpp_field, "type", "boolean", NULL); wocky_node_add_child_with_content (field, "value", "1"); } } } } static gboolean do_search (GabbleSearchChannel *chan, GHashTable *terms, GError **error) { TpBaseChannel *base = TP_BASE_CHANNEL (chan); TpBaseConnection *base_conn = tp_base_channel_get_connection (base); WockyStanza *msg; WockyNode *query; gboolean ret; DEBUG ("called"); if (!validate_terms (chan, terms, error)) return FALSE; msg = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, chan->priv->server, '(', "query", ':', NS_SEARCH, '*', &query, ')', NULL); if (chan->priv->xforms) { build_extended_query (chan, query, terms); } else { build_unextended_query (chan, query, terms); } DEBUG ("Sending search"); if (_gabble_connection_send_with_reply (GABBLE_CONNECTION (base_conn), msg, search_reply_cb, (GObject *) chan, NULL, error)) { ret = TRUE; change_search_state (chan, TP_CHANNEL_CONTACT_SEARCH_STATE_IN_PROGRESS, NULL); } else { ret = FALSE; } g_object_unref (msg); return ret; } /* GObject implementation */ static void gabble_search_channel_init (GabbleSearchChannel *self) { GabbleSearchChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_SEARCH_CHANNEL, GabbleSearchChannelPrivate); self->priv = priv; } static void free_info (GPtrArray *info) { g_boxed_free (TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST, info); } static GObject * gabble_search_channel_constructor (GType type, guint n_props, GObjectConstructParam *props) { GObject *obj; GabbleSearchChannel *chan; TpBaseChannel *base; TpBaseConnection *conn; obj = G_OBJECT_CLASS (gabble_search_channel_parent_class)->constructor ( type, n_props, props); chan = GABBLE_SEARCH_CHANNEL (obj); base = TP_BASE_CHANNEL (obj); conn = tp_base_channel_get_connection (base); chan->priv->result_handles = tp_handle_set_new ( tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT)); chan->priv->tp_to_xmpp = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); chan->priv->boolean_keys = g_ptr_array_new (); chan->priv->results = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) free_info); request_search_fields (chan); return obj; } static void gabble_search_channel_finalize (GObject *obj) { GabbleSearchChannel *chan = GABBLE_SEARCH_CHANNEL (obj); GabbleSearchChannelPrivate *priv = chan->priv; guint i; DEBUG ("bye bye %p", obj); g_free (priv->server); tp_handle_set_destroy (priv->result_handles); g_hash_table_unref (chan->priv->tp_to_xmpp); g_free (chan->priv->available_search_keys); for (i = 0; i < priv->boolean_keys->len; i++) { g_free (g_ptr_array_index (priv->boolean_keys, i)); } g_ptr_array_unref (priv->boolean_keys); g_hash_table_unref (chan->priv->results); if (G_OBJECT_CLASS (gabble_search_channel_parent_class)->finalize) G_OBJECT_CLASS (gabble_search_channel_parent_class)->finalize (obj); } static void gabble_search_channel_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleSearchChannel *chan = GABBLE_SEARCH_CHANNEL (object); switch (property_id) { case PROP_SEARCH_STATE: g_value_set_uint (value, chan->priv->state); break; case PROP_AVAILABLE_SEARCH_KEYS: g_value_set_boxed (value, chan->priv->available_search_keys); break; case PROP_SERVER: g_value_set_string (value, chan->priv->server); break; case PROP_LIMIT: g_value_set_uint (value, 0); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_search_channel_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleSearchChannel *chan = GABBLE_SEARCH_CHANNEL (object); switch (property_id) { case PROP_SERVER: chan->priv->server = g_value_dup_string (value); g_assert (chan->priv->server != NULL); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_search_channel_fill_immutable_properties ( TpBaseChannel *chan, GHashTable *properties) { TP_BASE_CHANNEL_CLASS (gabble_search_channel_parent_class)->fill_immutable_properties ( chan, properties); tp_dbus_properties_mixin_fill_properties_hash ( G_OBJECT (chan), properties, TP_IFACE_CHANNEL_TYPE_CONTACT_SEARCH, "AvailableSearchKeys", TP_IFACE_CHANNEL_TYPE_CONTACT_SEARCH, "Server", TP_IFACE_CHANNEL_TYPE_CONTACT_SEARCH, "Limit", NULL); } static gchar * gabble_search_channel_get_object_path_suffix (TpBaseChannel *base) { GabbleSearchChannel *self = GABBLE_SEARCH_CHANNEL (base); gchar *escaped, *ret; escaped = tp_escape_as_identifier (self->priv->server); ret = g_strdup_printf ("SearchChannel_%s_%p", escaped, self); g_free (escaped); return ret; } static void gabble_search_channel_class_init (GabbleSearchChannelClass *klass) { static TpDBusPropertiesMixinPropImpl search_channel_props[] = { { "SearchState", "search-state", NULL }, { "AvailableSearchKeys", "available-search-keys", NULL }, { "Server", "server", NULL }, { "Limit", "limit", NULL }, { NULL } }; GObjectClass *object_class = G_OBJECT_CLASS (klass); TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (klass); GParamSpec *param_spec; g_type_class_add_private (klass, sizeof (GabbleSearchChannelPrivate)); object_class->constructor = gabble_search_channel_constructor; object_class->finalize = gabble_search_channel_finalize; object_class->get_property = gabble_search_channel_get_property; object_class->set_property = gabble_search_channel_set_property; base_class->channel_type = TP_IFACE_CHANNEL_TYPE_CONTACT_SEARCH; base_class->target_handle_type = TP_HANDLE_TYPE_NONE; base_class->fill_immutable_properties = gabble_search_channel_fill_immutable_properties; base_class->get_object_path_suffix = gabble_search_channel_get_object_path_suffix; /* We don't have to do any special clean-up when told to close, so we can * just roll over and die immediately. */ base_class->close = tp_base_channel_destroyed; param_spec = g_param_spec_uint ("search-state", "Search state", "The current state of the search represented by this channel", TP_CHANNEL_CONTACT_SEARCH_STATE_NOT_STARTED, TP_CHANNEL_CONTACT_SEARCH_STATE_FAILED, TP_CHANNEL_CONTACT_SEARCH_STATE_NOT_STARTED, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SEARCH_STATE, param_spec); param_spec = g_param_spec_boxed ("available-search-keys", "Available search keys", "The set of search keys supported by this channel", G_TYPE_STRV, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_AVAILABLE_SEARCH_KEYS, param_spec); param_spec = g_param_spec_string ("server", "Search server", "The user directory server used by this search", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SERVER, param_spec); param_spec = g_param_spec_uint ("limit", "Result limit", "Always 0 for unlimited in Gabble", 0, 0, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_LIMIT, param_spec); /* Emitted when we get a reply from the server about which search keys it * supports. Its three arguments are the components of a GError. If the * server gave us a set of search keys, and they were sane, all components * will be 0 or %NULL, indicating that this channel can be announced and * used; if the server doesn't actually speak XEP 0055 or is full of bees, * they'll be an error in either the GABBLE_XMPP_ERROR or the TP_ERROR * domain. */ signals[READY_OR_NOT] = g_signal_new ("ready-or-not", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, gabble_marshal_VOID__UINT_INT_STRING, G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_INT, G_TYPE_STRING); tp_dbus_properties_mixin_implement_interface (object_class, TP_IFACE_QUARK_CHANNEL_TYPE_CONTACT_SEARCH, tp_dbus_properties_mixin_getter_gobject_properties, NULL, search_channel_props); build_mapping_tables (); } static void gabble_search_channel_search (TpSvcChannelTypeContactSearch *self, GHashTable *terms, DBusGMethodInvocation *context) { GabbleSearchChannel *chan = GABBLE_SEARCH_CHANNEL (self); GabbleSearchChannelPrivate *priv = chan->priv; GError *error = NULL; if (priv->state != TP_CHANNEL_CONTACT_SEARCH_STATE_NOT_STARTED) { error = g_error_new (TP_ERROR, TP_ERROR_NOT_AVAILABLE, "SearchState is %s", states[priv->state]); goto err; } if (do_search (chan, terms, &error)) { tp_svc_channel_type_contact_search_return_from_search (context); return; } err: dbus_g_method_return_error (context, error); g_error_free (error); } static void gabble_search_channel_stop (TpSvcChannelTypeContactSearch *self, DBusGMethodInvocation *context) { GabbleSearchChannel *chan = GABBLE_SEARCH_CHANNEL (self); GabbleSearchChannelPrivate *priv = chan->priv; switch (priv->state) { case TP_CHANNEL_CONTACT_SEARCH_STATE_IN_PROGRESS: { GError e = { TP_ERROR, TP_ERROR_CANCELLED, "Stop() called" }; change_search_state (chan, TP_CHANNEL_CONTACT_SEARCH_STATE_FAILED, &e); /* Deliberately falling through to return from the method: */ } case TP_CHANNEL_CONTACT_SEARCH_STATE_COMPLETED: case TP_CHANNEL_CONTACT_SEARCH_STATE_FAILED: tp_svc_channel_type_contact_search_return_from_stop (context); break; case TP_CHANNEL_CONTACT_SEARCH_STATE_NOT_STARTED: { GError e = { TP_ERROR, TP_ERROR_NOT_AVAILABLE, "Search() hasn't been called yet" }; dbus_g_method_return_error (context, &e); break; } case TP_CHANNEL_CONTACT_SEARCH_STATE_MORE_AVAILABLE: g_assert_not_reached (); } } gboolean gabble_search_channel_is_ready (GabbleSearchChannel *self) { return self->priv->ready; } static void contact_search_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcChannelTypeContactSearchClass *klass = g_iface; #define IMPLEMENT(x) tp_svc_channel_type_contact_search_implement_##x (\ klass, gabble_search_channel_##x) IMPLEMENT(search); IMPLEMENT(stop); #undef IMPLEMENT } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/gtalk-file-collection.h�������������������������������������������������0000664�0001750�0001750�00000007261�12223562023�023311� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gtalk-file-collection.h - Header for GTalkFileCollection * Copyright (C) 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GTALK_FILE_COLLECTION_H__ #define __GTALK_FILE_COLLECTION_H__ #include <glib-object.h> #include <wocky/wocky.h> #include "connection.h" typedef struct _GTalkFileCollection GTalkFileCollection; typedef enum { GTALK_FILE_COLLECTION_STATE_PENDING, GTALK_FILE_COLLECTION_STATE_ACCEPTED, GTALK_FILE_COLLECTION_STATE_OPEN, GTALK_FILE_COLLECTION_STATE_TERMINATED, GTALK_FILE_COLLECTION_STATE_CONNECTION_FAILED, GTALK_FILE_COLLECTION_STATE_ERROR, GTALK_FILE_COLLECTION_STATE_COMPLETED } GTalkFileCollectionState; #include "ft-channel.h" G_BEGIN_DECLS typedef struct _GTalkFileCollectionClass GTalkFileCollectionClass; GType gtalk_file_collection_get_type (void); /* TYPE MACROS */ #define GTALK_TYPE_FILE_COLLECTION \ (gtalk_file_collection_get_type ()) #define GTALK_FILE_COLLECTION(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GTALK_TYPE_FILE_COLLECTION, \ GTalkFileCollection)) #define GTALK_FILE_COLLECTION_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GTALK_TYPE_FILE_COLLECTION, \ GTalkFileCollectionClass)) #define GTALK_IS_FILE_COLLECTION(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTALK_TYPE_FILE_COLLECTION)) #define GTALK_IS_FILE_COLLECTION_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GTALK_TYPE_FILE_COLLECTION)) #define GTALK_FILE_COLLECTION_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GTALK_TYPE_FILE_COLLECTION, \ GTalkFileCollectionClass)) struct _GTalkFileCollectionClass { GObjectClass parent_class; }; typedef struct _GTalkFileCollectionPrivate GTalkFileCollectionPrivate; struct _GTalkFileCollection { GObject parent; GTalkFileCollectionPrivate *priv; }; GTalkFileCollection *gtalk_file_collection_new ( GabbleFileTransferChannel *channel, WockyJingleFactory *jingle_factory, TpHandle handle, const gchar *jid); GTalkFileCollection *gtalk_file_collection_new_from_session ( WockyJingleFactory *jingle_factory, WockyJingleSession *session); void gtalk_file_collection_add_channel (GTalkFileCollection *self, GabbleFileTransferChannel *channel); void gtalk_file_collection_initiate (GTalkFileCollection *self, GabbleFileTransferChannel *channel); void gtalk_file_collection_accept (GTalkFileCollection *self, GabbleFileTransferChannel *channel); void gtalk_file_collection_terminate (GTalkFileCollection *self, GabbleFileTransferChannel *channel); void gtalk_file_collection_completed (GTalkFileCollection *self, GabbleFileTransferChannel *channel); void gtalk_file_collection_block_reading (GTalkFileCollection *self, GabbleFileTransferChannel *channel, gboolean block); gboolean gtalk_file_collection_send_data (GTalkFileCollection *self, GabbleFileTransferChannel *channel, const gchar *data, guint length); void gtalk_file_collection_set_test_mode (void); #endif /* __GTALK_FILE_COLLECTION_H__ */ �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/conn-client-types.c�����������������������������������������������������0000664�0001750�0001750�00000015730�12332441362�022512� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * conn-client-types - Gabble client types interface * Copyright (C) 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include <string.h> #include <stdlib.h> #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #include <extensions/extensions.h> #include "conn-client-types.h" #include "disco.h" #include "namespaces.h" #include "presence.h" #include "presence-cache.h" #define DEBUG_FLAG GABBLE_DEBUG_CLIENT_TYPES #include "debug.h" static gboolean get_client_types_from_handle (GabbleConnection *conn, TpHandle handle, gchar ***types_out) { GabblePresence *presence = gabble_presence_cache_get (conn->presence_cache, handle); g_return_val_if_fail (types_out != NULL, FALSE); if (presence == NULL) { /* We have no presence information for this contact; so they have no * known client types. */ static gchar *empty[] = { NULL }; *types_out = g_strdupv (empty); return TRUE; } else { const gchar *res; gchar **types = gabble_presence_get_client_types_array (presence, &res); /* If we don't have any client types for this contact, and a disco * request is in progress, then keep quiet rather than reporting that * they have no client types; when the result comes in, their true client * types will be reported. */ if (types[0] == NULL && gabble_presence_cache_disco_in_progress (conn->presence_cache, handle, res)) { g_strfreev (types); return FALSE; } *types_out = types; return TRUE; } } static void client_types_get_client_types (TpSvcConnectionInterfaceClientTypes *iface, const GArray *contacts, DBusGMethodInvocation *context) { GabbleConnection *conn = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) conn; TpHandleRepoIface *contact_handles; guint i; GHashTable *client_types; GError *error = NULL; /* Validate contacts */ contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); if (!tp_handles_are_valid (contact_handles, contacts, TRUE, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); return; } if (DEBUGGING) { DEBUG ("GetClientTypes called on the following handles:"); for (i = 0; i < contacts->len; i++) { DEBUG (" * %u", g_array_index (contacts, TpHandle, i)); } } client_types = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_strfreev); for (i = 0; i < contacts->len; i++) { TpHandle handle = g_array_index (contacts, TpHandle, i); gchar **types; if (!get_client_types_from_handle (conn, handle, &types)) continue; g_hash_table_insert (client_types, GUINT_TO_POINTER (handle), types); } tp_svc_connection_interface_client_types_return_from_get_client_types ( context, client_types); g_hash_table_unref (client_types); } void conn_client_types_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcConnectionInterfaceClientTypesClass *klass = g_iface; #define IMPLEMENT(x) tp_svc_connection_interface_client_types_implement_##x \ (klass, client_types_##x) IMPLEMENT (get_client_types); #undef IMPLEMENT } static void conn_client_types_fill_contact_attributes (GObject *obj, const GArray *contacts, GHashTable *attributes_hash) { GabbleConnection *conn = GABBLE_CONNECTION (obj); guint i; for (i = 0; i < contacts->len; i++) { TpHandle handle = g_array_index (contacts, TpHandle, i); GValue *val; gchar **types; if (!get_client_types_from_handle (conn, handle, &types)) continue; val = tp_g_value_slice_new_take_boxed (G_TYPE_STRV, types); tp_contacts_mixin_set_contact_attribute (attributes_hash, handle, TP_IFACE_CONNECTION_INTERFACE_CLIENT_TYPES "/client-types", val); } } typedef struct { TpHandle handle; GabbleConnection *conn; } UpdatedData; static void updated_data_free (gpointer user_data) { UpdatedData *data = user_data; if (data->conn != NULL) g_object_remove_weak_pointer (G_OBJECT (data->conn), (gpointer *) &data->conn); g_slice_free (UpdatedData, data); } static gboolean idle_timeout (gpointer user_data) { UpdatedData *data = user_data; gchar **types; if (data->conn == NULL) return FALSE; if (get_client_types_from_handle (data->conn, data->handle, &types)) { tp_svc_connection_interface_client_types_emit_client_types_updated ( data->conn, data->handle, (const gchar **) types); g_strfreev (types); } return FALSE; } static void presence_cache_client_types_updated_cb (GabblePresenceCache *presence_cache, TpHandle handle, GabbleConnection *conn) { UpdatedData *data = g_slice_new0 (UpdatedData); data->handle = handle; data->conn = conn; g_object_add_weak_pointer (G_OBJECT (conn), (gpointer *) &data->conn); /* Unfortunately, the client-types-updated signal can be emitted before the * caps URIs have been processed to determine which client types a * freshly-online contact has (and whether a disco request needs to be made * to find out). * * Specifically, gabble_presence_cache_update() may emit client-types-updated * if a presence change causes the "dominant" resource to change and the new * resource has a different set of client types to the previous one. It is * called by gabble_presence_parse_presence_message() just before * _process_caps() is called (within which disco requests are sent if * necessary). It turns out to be very difficult to rearrange things to sort * this out. Moving the emission of the D-Bus signal to an idle allows us to * avoid it when we're actually waiting for a disco response to come in. */ g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, idle_timeout, data, updated_data_free); } void conn_client_types_init (GabbleConnection *conn) { tp_contacts_mixin_add_contact_attributes_iface (G_OBJECT (conn), TP_IFACE_CONNECTION_INTERFACE_CLIENT_TYPES, conn_client_types_fill_contact_attributes); g_signal_connect (conn->presence_cache, "client-types-updated", G_CALLBACK (presence_cache_client_types_updated_cb), conn); } ����������������������������������������telepathy-gabble-0.18.3/src/conn-sidecars.c���������������������������������������������������������0000664�0001750�0001750�00000024013�12332441362�021661� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * conn-sidecars.h - Gabble connection implementation of sidecars * Copyright © 2009 Collabora Ltd. * Copyright © 2009 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "conn-sidecars.h" #include <telepathy-glib/telepathy-glib.h> #include "extensions/extensions.h" #define DEBUG_FLAG GABBLE_DEBUG_CONNECTION #include "debug.h" #include "plugin-loader.h" #include "gabble/sidecar.h" static void sidecars_conn_status_changed_cb ( GabbleConnection *conn, guint status, guint reason, gpointer unused); void conn_sidecars_init (GabbleConnection *conn) { conn->sidecars = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); conn->pending_sidecars = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_list_free); g_signal_connect (conn, "status-changed", (GCallback) sidecars_conn_status_changed_cb, NULL); } void conn_sidecars_dispose (GabbleConnection *conn) { g_warn_if_fail (g_hash_table_size (conn->sidecars) == 0); tp_clear_pointer (&conn->sidecars, g_hash_table_unref); g_warn_if_fail (g_hash_table_size (conn->pending_sidecars) == 0); tp_clear_pointer (&conn->pending_sidecars, g_hash_table_unref); } static gchar * make_sidecar_path ( GabbleConnection *conn, const gchar *sidecar_iface) { TpBaseConnection *base = TP_BASE_CONNECTION (conn); return g_strdelimit ( g_strdup_printf ("%s/Sidecar/%s", tp_base_connection_get_object_path (base), sidecar_iface), ".", '/'); } /** * connection_install_sidecar: * * Registers @sidecar on the bus, and returns its object path. */ static gchar * connection_install_sidecar ( GabbleConnection *conn, GabbleSidecar *sidecar, const gchar *sidecar_iface) { TpDBusDaemon *bus = tp_base_connection_get_dbus_daemon ( (TpBaseConnection *) conn); gchar *path = make_sidecar_path (conn, sidecar_iface); tp_dbus_daemon_register_object (bus, path, G_OBJECT (sidecar)); g_hash_table_insert (conn->sidecars, g_strdup (sidecar_iface), g_object_ref (sidecar)); return path; } typedef struct { GabbleConnection *conn; gchar *sidecar_iface; } Grr; static Grr * grr_new ( GabbleConnection *conn, const gchar *sidecar_iface) { Grr *grr = g_slice_new (Grr); grr->conn = g_object_ref (conn); grr->sidecar_iface = g_strdup (sidecar_iface); return grr; } static void grr_free (Grr *grr) { g_object_unref (grr->conn); g_free (grr->sidecar_iface); g_slice_free (Grr, grr); } static void create_sidecar_cb ( GObject *loader_obj, GAsyncResult *result, gpointer user_data) { GabblePluginLoader *loader = GABBLE_PLUGIN_LOADER (loader_obj); Grr *ctx = user_data; GabbleConnection *conn = ctx->conn; const gchar *sidecar_iface = ctx->sidecar_iface; GabbleSidecar *sidecar; GList *contexts; GError *error = NULL; sidecar = gabble_plugin_loader_create_sidecar_finish (loader, result, &error); contexts = g_hash_table_lookup (conn->pending_sidecars, sidecar_iface); if (contexts == NULL) { /* We never use the empty list as a value in pending_sidecars, so this * must mean we've disconnected and already returned. Jettison the * sidecar! */ DEBUG ("creating sidecar %s %s after connection closed; jettisoning!", sidecar_iface, (sidecar != NULL ? "succeeded" : "failed")); goto out; } if (sidecar != NULL) { const gchar *actual_iface = gabble_sidecar_get_interface (sidecar); if (tp_strdiff (ctx->sidecar_iface, actual_iface)) { /* TODO: maybe this lives in the loader? It knows what the plugin is * called. */ g_set_error (&error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "A buggy plugin created a %s sidecar when asked to create %s", actual_iface, ctx->sidecar_iface); } } else /* sidecar == NULL */ { /* If creating the sidecar failed, 'error' should have been set */ g_return_if_fail (error != NULL); } if (error == NULL) { gchar *path = connection_install_sidecar (ctx->conn, sidecar, ctx->sidecar_iface); GHashTable *props = gabble_sidecar_get_immutable_properties (sidecar); GList *l; for (l = contexts; l != NULL; l = l->next) gabble_svc_connection_future_return_from_ensure_sidecar (l->data, path, props); g_hash_table_unref (props); g_free (path); } else { g_list_foreach (contexts, (GFunc) dbus_g_method_return_error, error); } g_hash_table_remove (ctx->conn->pending_sidecars, ctx->sidecar_iface); out: tp_clear_object (&sidecar); g_clear_error (&error); grr_free (ctx); } static void gabble_connection_ensure_sidecar ( GabbleSvcConnectionFUTURE *iface, const gchar *sidecar_iface, DBusGMethodInvocation *context) { GabbleConnection *conn = GABBLE_CONNECTION (iface); TpBaseConnection *base = TP_BASE_CONNECTION (conn); GabbleSidecar *sidecar; gpointer key, value; GError *error = NULL; if (tp_base_connection_is_destroyed (base)) { GError e = { TP_ERROR, TP_ERROR_DISCONNECTED, "This connection has already disconnected" }; DEBUG ("already disconnected, declining request for %s", sidecar_iface); dbus_g_method_return_error (context, &e); return; } if (!tp_dbus_check_valid_interface_name (sidecar_iface, &error)) { error->domain = TP_ERROR; error->code = TP_ERROR_INVALID_ARGUMENT; DEBUG ("%s is malformed: %s", sidecar_iface, error->message); dbus_g_method_return_error (context, error); g_clear_error (&error); return; } sidecar = g_hash_table_lookup (conn->sidecars, sidecar_iface); if (sidecar != NULL) { gchar *path = make_sidecar_path (conn, sidecar_iface); GHashTable *props = gabble_sidecar_get_immutable_properties (sidecar); DEBUG ("sidecar %s already exists at %s", sidecar_iface, path); gabble_svc_connection_future_return_from_ensure_sidecar (context, path, props); g_free (path); g_hash_table_unref (props); return; } if (g_hash_table_lookup_extended (conn->pending_sidecars, sidecar_iface, &key, &value)) { GList *contexts = value; DEBUG ("already awaiting %s, joining a queue of %u", sidecar_iface, g_list_length (contexts)); contexts = g_list_prepend (contexts, context); g_hash_table_steal (conn->pending_sidecars, key); g_hash_table_insert (conn->pending_sidecars, key, contexts); return; } DEBUG ("enqueuing first request for %s", sidecar_iface); g_hash_table_insert (conn->pending_sidecars, g_strdup (sidecar_iface), g_list_prepend (NULL, context)); if (tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_CONNECTED) { GabblePluginLoader *loader = gabble_plugin_loader_dup (); DEBUG ("requesting %s from the plugin loader", sidecar_iface); gabble_plugin_loader_create_sidecar (loader, sidecar_iface, conn, conn->session, create_sidecar_cb, grr_new (conn, sidecar_iface)); g_object_unref (loader); } else { DEBUG ("not yet connected; waiting."); } } static void sidecars_conn_status_changed_cb ( GabbleConnection *conn, guint status, guint reason, gpointer unused) { TpDBusDaemon *bus = tp_base_connection_get_dbus_daemon ( (TpBaseConnection *) conn); GHashTableIter iter; gpointer key, value; if (status == TP_CONNECTION_STATUS_DISCONNECTED) { g_hash_table_iter_init (&iter, conn->sidecars); while (g_hash_table_iter_next (&iter, NULL, &value)) { DEBUG ("removing %s from the bus", gabble_sidecar_get_interface (value)); tp_dbus_daemon_unregister_object (bus, G_OBJECT (value)); } g_hash_table_iter_init (&iter, conn->pending_sidecars); while (g_hash_table_iter_next (&iter, &key, &value)) { const gchar *sidecar_iface = key; GList *contexts = value; GError *error = g_error_new (TP_ERROR, TP_ERROR_CANCELLED, "Disconnected before %s could be created", sidecar_iface); DEBUG ("failing all %u requests for %s", g_list_length (contexts), sidecar_iface); g_list_foreach (contexts, (GFunc) dbus_g_method_return_error, error); g_error_free (error); } g_hash_table_remove_all (conn->sidecars); g_hash_table_remove_all (conn->pending_sidecars); } else if (status == TP_CONNECTION_STATUS_CONNECTED) { GabblePluginLoader *loader = gabble_plugin_loader_dup (); DEBUG ("connected; requesting sidecars from plugins"); g_hash_table_iter_init (&iter, conn->pending_sidecars); while (g_hash_table_iter_next (&iter, &key, NULL)) { const gchar *sidecar_iface = key; DEBUG ("requesting %s from the plugin loader", sidecar_iface); gabble_plugin_loader_create_sidecar (loader, sidecar_iface, conn, conn->session, create_sidecar_cb, grr_new (conn, sidecar_iface)); } g_object_unref (loader); } } void conn_future_iface_init ( gpointer g_iface, gpointer iface_data) { GabbleSvcConnectionFUTUREClass *klass = g_iface; #define IMPLEMENT(x) \ gabble_svc_connection_future_implement_##x (\ klass, gabble_connection_##x) IMPLEMENT (ensure_sidecar); #undef IMPLEMENT } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/call-content.h����������������������������������������������������������0000664�0001750�0001750�00000005140�12223562023�021516� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gabble-call-content.h - Header for GabbleCallContent * Copyright (C) 2009 Collabora Ltd. * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_CALL_CONTENT_H__ #define __GABBLE_CALL_CONTENT_H__ #include <glib-object.h> #include <telepathy-glib/telepathy-glib.h> #include <wocky/wocky.h> #include "call-member-content.h" G_BEGIN_DECLS typedef struct _GabbleCallContent GabbleCallContent; typedef struct _GabbleCallContentPrivate GabbleCallContentPrivate; typedef struct _GabbleCallContentClass GabbleCallContentClass; struct _GabbleCallContentClass { TpBaseMediaCallContentClass parent_class; }; struct _GabbleCallContent { TpBaseMediaCallContent parent; GabbleCallContentPrivate *priv; }; GType gabble_call_content_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_CALL_CONTENT \ (gabble_call_content_get_type ()) #define GABBLE_CALL_CONTENT(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), \ GABBLE_TYPE_CALL_CONTENT, GabbleCallContent)) #define GABBLE_CALL_CONTENT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), \ GABBLE_TYPE_CALL_CONTENT, GabbleCallContentClass)) #define GABBLE_IS_CALL_CONTENT(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_CALL_CONTENT)) #define GABBLE_IS_CALL_CONTENT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_CALL_CONTENT)) #define GABBLE_CALL_CONTENT_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ GABBLE_TYPE_CALL_CONTENT, GabbleCallContentClass)) WockyJingleMediaType gabble_call_content_get_media_type (GabbleCallContent *self); void gabble_call_content_new_offer (GabbleCallContent *self, GabbleCallMemberContent *content); void gabble_call_content_add_member_content (GabbleCallContent *self, GabbleCallMemberContent *content); GList *gabble_call_content_get_member_contents (GabbleCallContent *self); G_END_DECLS #endif /* #ifndef __GABBLE_CALL_CONTENT_H__*/ ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/debug.c�����������������������������������������������������������������0000664�0001750�0001750�00000007200�12332440117�020213� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ #include "config.h" #include "debug.h" #include <stdarg.h> #ifdef HAVE_UNISTD_H # include <unistd.h> #endif #include <sys/types.h> #include <sys/stat.h> #ifdef HAVE_FCNTL_H # include <fcntl.h> #endif #include <errno.h> #include <glib/gstdio.h> #include <telepathy-glib/telepathy-glib.h> static GabbleDebugFlags flags = 0; /* Remember to keep this array up to date with the GabbleDebugFlags enum in debug.h */ static GDebugKey keys[] = { { "presence", GABBLE_DEBUG_PRESENCE }, { "groups", GABBLE_DEBUG_GROUPS }, { "roster", GABBLE_DEBUG_ROSTER }, { "disco", GABBLE_DEBUG_DISCO }, { "properties", GABBLE_DEBUG_PROPERTIES }, { "roomlist", GABBLE_DEBUG_ROOMLIST }, { "media-channel", GABBLE_DEBUG_MEDIA }, { "im", GABBLE_DEBUG_IM }, { "muc", GABBLE_DEBUG_MUC }, { "connection", GABBLE_DEBUG_CONNECTION }, { "vcard", GABBLE_DEBUG_VCARD }, { "pipeline", GABBLE_DEBUG_PIPELINE }, { "jid", GABBLE_DEBUG_JID }, { "olpc", GABBLE_DEBUG_OLPC }, { "bytestream", GABBLE_DEBUG_BYTESTREAM }, { "tubes", GABBLE_DEBUG_TUBES }, { "location", GABBLE_DEBUG_LOCATION }, { "file-transfer", GABBLE_DEBUG_FT }, { "search", GABBLE_DEBUG_SEARCH }, { "base-channel", GABBLE_DEBUG_BASE_CHANNEL }, { "plugins", GABBLE_DEBUG_PLUGINS }, { "mail", GABBLE_DEBUG_MAIL_NOTIF }, { "authentication", GABBLE_DEBUG_AUTH }, { "share", GABBLE_DEBUG_SHARE }, { "tls", GABBLE_DEBUG_TLS }, { "client-types", GABBLE_DEBUG_CLIENT_TYPES }, { 0, }, }; void gabble_debug_set_flags_from_env () { guint nkeys; const gchar *flags_string; for (nkeys = 0; keys[nkeys].value; nkeys++); flags_string = g_getenv ("GABBLE_DEBUG"); tp_debug_set_flags (flags_string); tp_debug_set_flags (flags_string); if (flags_string != NULL) { gabble_debug_set_flags (g_parse_debug_string (flags_string, keys, nkeys)); } } void gabble_debug_set_flags (GabbleDebugFlags new_flags) { flags |= new_flags; } gboolean gabble_debug_flag_is_set (GabbleDebugFlags flag) { return flag & flags; } GHashTable *flag_to_domains = NULL; static const gchar * debug_flag_to_domain (GabbleDebugFlags flag) { if (G_UNLIKELY (flag_to_domains == NULL)) { guint i; flag_to_domains = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); for (i = 0; keys[i].value; i++) { GDebugKey key = keys[i]; gchar *val; val = g_strdup_printf ("%s/%s", G_LOG_DOMAIN, key.key); g_hash_table_insert (flag_to_domains, GUINT_TO_POINTER (key.value), val); } } return g_hash_table_lookup (flag_to_domains, GUINT_TO_POINTER (flag)); } void gabble_debug_free (void) { if (flag_to_domains == NULL) return; g_hash_table_unref (flag_to_domains); flag_to_domains = NULL; } static void log_to_debug_sender (GLogLevelFlags level, GabbleDebugFlags flag, const gchar *message) { TpDebugSender *dbg; GTimeVal now; dbg = tp_debug_sender_dup (); g_get_current_time (&now); tp_debug_sender_add_message (dbg, &now, debug_flag_to_domain (flag), level, message); g_object_unref (dbg); } void gabble_log (GLogLevelFlags level, GabbleDebugFlags flag, const gchar *format, ...) { gchar *message; va_list args; va_start (args, format); message = g_strdup_vprintf (format, args); va_end (args); log_to_debug_sender (level, flag, message); if (flag & flags || level > G_LOG_LEVEL_DEBUG) g_log (G_LOG_DOMAIN, level, "%s", message); g_free (message); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/jingle-share.c����������������������������������������������������������0000664�0001750�0001750�00000035512�12223562023�021504� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * jingle-share.c - Source for GabbleJingleShare * * Copyright (C) 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* Share content type deals with file sharing content, ie. file transfers. It * Google's jingle variants (libjingle 0.3/0.4). */ #include "config.h" #include "jingle-share.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <glib.h> #define DEBUG_FLAG GABBLE_DEBUG_SHARE #include "connection.h" #include "debug.h" #include "namespaces.h" #include "util.h" /****************************************************************** * Example description XML: * * <description xmlns="http://www.google.com/session/share"> * <manifest> * <file size='341'> * <name>foo.txt</name> * </file> * <file size='51321'> * <name>foo.jpg</name> * <image width='480' height='320'/> * </file> * <folder> * <name>stuff</name> * </folder> * </manifest> * <protocol> * <http> * <url name='source-path'>/temporary/23A53F01/</url> * <url name='preview-path'>/temporary/90266EA1/</url> * </http> * </protocol> * </description> * *******************************************************************/ G_DEFINE_TYPE (GabbleJingleShare, gabble_jingle_share, WOCKY_TYPE_JINGLE_CONTENT); /* properties */ enum { PROP_MEDIA_TYPE = 1, PROP_FILENAME, PROP_FILESIZE, LAST_PROPERTY }; struct _GabbleJingleSharePrivate { gboolean dispose_has_run; GabbleJingleShareManifest *manifest; gchar *filename; guint64 filesize; }; static gchar * generate_temp_url (void) { gchar *uuid = gabble_generate_id (); gchar *url = NULL; url = g_strdup_printf ("/temporary/%s/", uuid); g_free (uuid); return url; } static void free_manifest (GabbleJingleShare *self) { GList * i; if (self->priv->manifest) { for (i = self->priv->manifest->entries; i; i = i->next) { GabbleJingleShareManifestEntry *item = i->data; g_free (item->name); g_slice_free (GabbleJingleShareManifestEntry, item); } g_list_free (self->priv->manifest->entries); g_free (self->priv->manifest->source_url); g_free (self->priv->manifest->preview_url); g_slice_free (GabbleJingleShareManifest, self->priv->manifest); self->priv->manifest = NULL; } } static void ensure_manifest (GabbleJingleShare *self) { if (self->priv->manifest == NULL) { GabbleJingleShareManifestEntry *m = NULL; self->priv->manifest = g_slice_new0 (GabbleJingleShareManifest); self->priv->manifest->source_url = generate_temp_url (); self->priv->manifest->preview_url = generate_temp_url (); if (self->priv->filename != NULL) { m = g_slice_new0 (GabbleJingleShareManifestEntry); m->name = g_strdup (self->priv->filename); m->size = self->priv->filesize; self->priv->manifest->entries = g_list_prepend (NULL, m); } } } static void gabble_jingle_share_init (GabbleJingleShare *obj) { GabbleJingleSharePrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, GABBLE_TYPE_JINGLE_SHARE, GabbleJingleSharePrivate); DEBUG ("jingle share init called"); obj->priv = priv; priv->dispose_has_run = FALSE; } static void gabble_jingle_share_dispose (GObject *object) { GabbleJingleShare *self = GABBLE_JINGLE_SHARE (object); GabbleJingleSharePrivate *priv = self->priv; if (priv->dispose_has_run) return; DEBUG ("dispose called"); priv->dispose_has_run = TRUE; g_free (priv->filename); priv->filename = NULL; free_manifest (self); if (G_OBJECT_CLASS (gabble_jingle_share_parent_class)->dispose) G_OBJECT_CLASS (gabble_jingle_share_parent_class)->dispose (object); } static void parse_description (WockyJingleContent *content, WockyNode *desc_node, GError **error); static void produce_description (WockyJingleContent *obj, WockyNode *content_node); static void gabble_jingle_share_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleJingleShare *self = GABBLE_JINGLE_SHARE (object); GabbleJingleSharePrivate *priv = self->priv; switch (property_id) { case PROP_MEDIA_TYPE: g_value_set_uint (value, WOCKY_JINGLE_MEDIA_TYPE_NONE); break; case PROP_FILENAME: g_value_set_string (value, priv->filename); break; case PROP_FILESIZE: g_value_set_uint64 (value, priv->filesize); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_jingle_share_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleJingleShare *self = GABBLE_JINGLE_SHARE (object); GabbleJingleSharePrivate *priv = self->priv; switch (property_id) { case PROP_MEDIA_TYPE: break; case PROP_FILENAME: g_free (priv->filename); priv->filename = g_value_dup_string (value); free_manifest (self); /* simulate a media_ready when we know our own filename */ _wocky_jingle_content_set_media_ready (WOCKY_JINGLE_CONTENT (self)); break; case PROP_FILESIZE: priv->filesize = g_value_get_uint64 (value); free_manifest (self); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static WockyJingleContentSenders get_default_senders (WockyJingleContent *c) { return WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR; } static void gabble_jingle_share_class_init (GabbleJingleShareClass *cls) { GObjectClass *object_class = G_OBJECT_CLASS (cls); WockyJingleContentClass *content_class = WOCKY_JINGLE_CONTENT_CLASS (cls); g_type_class_add_private (cls, sizeof (GabbleJingleSharePrivate)); object_class->get_property = gabble_jingle_share_get_property; object_class->set_property = gabble_jingle_share_set_property; object_class->dispose = gabble_jingle_share_dispose; content_class->parse_description = parse_description; content_class->produce_description = produce_description; content_class->get_default_senders = get_default_senders; /* This property is here only because jingle-session sets the media-type when constructing the object.. */ g_object_class_install_property (object_class, PROP_MEDIA_TYPE, g_param_spec_uint ("media-type", "media type", "irrelevant media type. Will always be NONE.", WOCKY_JINGLE_MEDIA_TYPE_NONE, WOCKY_JINGLE_MEDIA_TYPE_NONE, WOCKY_JINGLE_MEDIA_TYPE_NONE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_FILENAME, g_param_spec_string ("filename", "file name", "The name of the file", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_FILESIZE, g_param_spec_uint64 ("filesize", "file size", "The size of the file", 0, G_MAXUINT64, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } static void parse_description (WockyJingleContent *content, WockyNode *desc_node, GError **error) { GabbleJingleShare *self = GABBLE_JINGLE_SHARE (content); GabbleJingleSharePrivate *priv = self->priv; WockyNodeIter i; WockyNode *manifest_node = NULL; WockyNode *protocol_node = NULL; WockyNode *http_node = NULL; WockyNode *node; DEBUG ("parse description called"); if (priv->manifest != NULL) { DEBUG ("Not parsing description, we already have a manifest"); return; } manifest_node = wocky_node_get_child (desc_node, "manifest"); if (manifest_node == NULL) { g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, "description missing <manifest/> node"); return; } protocol_node = wocky_node_get_child (desc_node, "protocol"); if (protocol_node != NULL) http_node = wocky_node_get_child (protocol_node, "http"); free_manifest (self); priv->manifest = g_slice_new0 (GabbleJingleShareManifest); /* Build the manifest */ wocky_node_iter_init (&i, manifest_node, NULL, NULL); while (wocky_node_iter_next (&i, &node)) { WockyNode *name = NULL; WockyNode *image = NULL; gboolean folder; const gchar *size; GabbleJingleShareManifestEntry *m = NULL; if (!wocky_strdiff (node->name, "folder")) folder = TRUE; else if (!wocky_strdiff (node->name, "file")) folder = FALSE; else continue; name = wocky_node_get_child (node, "name"); if (name == NULL) continue; m = g_slice_new0 (GabbleJingleShareManifestEntry); m->folder = folder; m->name = g_strdup (name->content); size = wocky_node_get_attribute (node, "size"); if (size) m->size = g_ascii_strtoull (size, NULL, 10); image = wocky_node_get_child (node, "image"); if (image) { const gchar *width; const gchar *height; m->image = TRUE; width = wocky_node_get_attribute (image, "width"); if (width) m->image_width = g_ascii_strtoull (width, NULL, 10); height =wocky_node_get_attribute (image, "height"); if (height) m->image_height = g_ascii_strtoull (height, NULL, 10); } priv->manifest->entries = g_list_prepend (priv->manifest->entries, m); } /* Get the source and preview url paths from the protocol/http node */ if (http_node != NULL) { /* clear the previously set values */ wocky_node_iter_init (&i, http_node, "url", NULL); while (wocky_node_iter_next (&i, &node)) { const gchar *name = wocky_node_get_attribute (node, "name"); if (name == NULL) continue; if (!wocky_strdiff (name, "source-path")) { const gchar *url = node->content; priv->manifest->source_url = g_strdup (url); } if (!wocky_strdiff (name, "preview-path")) { const gchar *url = node->content; priv->manifest->preview_url = g_strdup (url); } } } /* Build the filename/filesize property values based on the new manifest */ g_free (priv->filename); priv->filename = NULL; priv->filesize = 0; if (g_list_length (priv->manifest->entries) > 0) { if (g_list_length (priv->manifest->entries) == 1) { GabbleJingleShareManifestEntry *m = priv->manifest->entries->data; if (m->folder) priv->filename = g_strdup_printf ("%s.tar", m->name); else priv->filename = g_strdup (m->name); priv->filesize = m->size; } else { GList *li; gchar *temp; priv->filename = g_strdup (""); for (li = priv->manifest->entries; li; li = li->next) { GabbleJingleShareManifestEntry *m = li->data; temp = priv->filename; priv->filename = g_strdup_printf ("%s%s%s%s", temp, m->name, m->folder? ".tar":"", li->next == NULL? "": "-"); g_free (temp); priv->filesize += m->size; } temp = priv->filename; priv->filename = g_strdup_printf ("%s.tar", temp); g_free (temp); } } _wocky_jingle_content_set_media_ready (content); } static void produce_description (WockyJingleContent *content, WockyNode *content_node) { GabbleJingleShare *self = GABBLE_JINGLE_SHARE (content); GabbleJingleSharePrivate *priv = self->priv; GList *i; WockyNode *desc_node; WockyNode *manifest_node; WockyNode *protocol_node; WockyNode *http_node; WockyNode *url_node; DEBUG ("produce description called"); ensure_manifest (self); desc_node = wocky_node_add_child_ns (content_node, "description", NS_GOOGLE_SESSION_SHARE); manifest_node = wocky_node_add_child (desc_node, "manifest"); for (i = priv->manifest->entries; i; i = i->next) { GabbleJingleShareManifestEntry *m = i->data; WockyNode *file_node; WockyNode *image_node; gchar *size_str, *width_str, *height_str; if (m->folder) file_node = wocky_node_add_child (manifest_node, "folder"); else file_node = wocky_node_add_child (manifest_node, "file"); if (m->size > 0) { size_str = g_strdup_printf ("%" G_GUINT64_FORMAT, m->size); wocky_node_set_attribute (file_node, "size", size_str); g_free (size_str); } wocky_node_add_child_with_content (file_node, "name", m->name); if (m->image && (m->image_width > 0 || m->image_height > 0)) { image_node = wocky_node_add_child (file_node, "image"); if (m->image_width > 0) { width_str = g_strdup_printf ("%d", m->image_width); wocky_node_set_attribute (image_node, "width", width_str); g_free (width_str); } if (m->image_height > 0) { height_str = g_strdup_printf ("%d", m->image_height); wocky_node_set_attribute (image_node, "height", height_str); g_free (height_str); } } } protocol_node = wocky_node_add_child (desc_node, "protocol"); http_node = wocky_node_add_child (protocol_node, "http"); url_node = wocky_node_add_child_with_content (http_node, "url", priv->manifest->source_url); wocky_node_set_attribute (url_node, "name", "source-path"); url_node = wocky_node_add_child_with_content (http_node, "url", priv->manifest->preview_url); wocky_node_set_attribute (url_node, "name", "preview-path"); } GabbleJingleShareManifest * gabble_jingle_share_get_manifest (GabbleJingleShare *self) { ensure_manifest (self); return self->priv->manifest; } void jingle_share_register (WockyJingleFactory *factory) { /* GTalk video call namespace */ wocky_jingle_factory_register_content_type (factory, NS_GOOGLE_SESSION_SHARE, GABBLE_TYPE_JINGLE_SHARE); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/conn-location.h���������������������������������������������������������0000664�0001750�0001750�00000001104�12332440117�021672� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ #ifndef __CONN_LOCATION_H__ #define __CONN_LOCATION_H__ #include "connection.h" #include <extensions/extensions.h> G_BEGIN_DECLS void location_iface_init (gpointer g_iface, gpointer iface_data); void conn_location_properties_getter (GObject *object, GQuark interface, GQuark name, GValue *value, gpointer getter_data); gboolean conn_location_properties_setter (GObject *object, GQuark interface, GQuark name, const GValue *value, gpointer setter_data, GError **error); void conn_location_init (GabbleConnection *conn); G_END_DECLS #endif /* __CONN_LOCATION_H__ */ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/namespaces.h������������������������������������������������������������0000664�0001750�0001750�00000016133�12332440117�021256� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * namespaces.h - XMPP namespace constants * Copyright (C) 2005 Collabora Ltd. * Copyright (C) 2005 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_NAMESPACES__H__ #define __GABBLE_NAMESPACES__H__ #include "gabble/namespaces.h" #define NS_AMP "http://jabber.org/protocol/amp" #define NS_BYTESTREAMS "http://jabber.org/protocol/bytestreams" #define NS_CHAT_STATES "http://jabber.org/protocol/chatstates" #define NS_DISCO_INFO "http://jabber.org/protocol/disco#info" #define NS_DISCO_ITEMS "http://jabber.org/protocol/disco#items" #define NS_FEATURENEG "http://jabber.org/protocol/feature-neg" #define NS_FILE_TRANSFER "http://jabber.org/protocol/si/profile/file-transfer" #define NS_GOOGLE_CAPS "http://www.google.com/xmpp/client/caps" #define NS_GOOGLE_FEAT_SESSION "http://www.google.com/xmpp/protocol/session" #define NS_GOOGLE_FEAT_SHARE "http://google.com/xmpp/protocol/share/v1" #define NS_GOOGLE_FEAT_VOICE "http://www.google.com/xmpp/protocol/voice/v1" #define NS_GOOGLE_FEAT_VIDEO "http://www.google.com/xmpp/protocol/video/v1" #define NS_GOOGLE_FEAT_CAMERA "http://www.google.com/xmpp/protocol/camera/v1" #define NS_GOOGLE_JINGLE_INFO "google:jingleinfo" #define NS_GOOGLE_ROSTER "google:roster" #define NS_GOOGLE_QUEUE "google:queue" #define NS_IBB "http://jabber.org/protocol/ibb" /* Namespaces for XEP-0166 draft v0.15, the most capable Jingle dialect * supported by telepathy-gabble < 0.7.16, including the versions shipped with * Maemo Chinook and Diablo. */ #define NS_JINGLE015 "http://jabber.org/protocol/jingle" /* RTP audio capability in Jingle v0.15 (obsoleted by NS_JINGLE_RTP) */ #define NS_JINGLE_DESCRIPTION_AUDIO \ "http://jabber.org/protocol/jingle/description/audio" /* RTP video capability in Jingle v0.15 (obsoleted by NS_JINGLE_RTP) */ #define NS_JINGLE_DESCRIPTION_VIDEO \ "http://jabber.org/protocol/jingle/description/video" /* XEP-0166 draft */ #define NS_JINGLE032 "urn:xmpp:jingle:1" #define NS_JINGLE_ERRORS "urn:xmpp:jingle:errors:1" /* XEP-0167 (Jingle RTP) */ #define NS_JINGLE_RTP "urn:xmpp:jingle:apps:rtp:1" #define NS_JINGLE_RTP_ERRORS "urn:xmpp:jingle:apps:rtp:errors:1" #define NS_JINGLE_RTP_INFO "urn:xmpp:jingle:apps:rtp:info:1" #define NS_JINGLE_RTP_AUDIO "urn:xmpp:jingle:apps:rtp:audio" #define NS_JINGLE_RTP_VIDEO "urn:xmpp:jingle:apps:rtp:video" /* ProtoXEPs for rtcp-fb and rtp-hdrext */ #define NS_JINGLE_RTCP_FB "urn:xmpp:jingle:apps:rtp:rtcp-fb:0" #define NS_JINGLE_RTP_HDREXT "urn:xmpp:jingle:apps:rtp:rtp-hdrext:0" /* Google's Jingle dialect */ #define NS_GOOGLE_SESSION "http://www.google.com/session" /* Audio capability in Google Jingle dialect */ #define NS_GOOGLE_SESSION_PHONE "http://www.google.com/session/phone" /* Video capability in Google's Jingle dialect */ #define NS_GOOGLE_SESSION_VIDEO "http://www.google.com/session/video" /* File transfer capability in Google's Jingle dialect */ #define NS_GOOGLE_SESSION_SHARE "http://www.google.com/session/share" /* google-p2p transport */ #define NS_GOOGLE_TRANSPORT_P2P "http://www.google.com/transport/p2p" /* Jingle RAW-UDP transport */ #define NS_JINGLE_TRANSPORT_RAWUDP "urn:xmpp:jingle:transports:raw-udp:1" /* Jingle ICE-UDP transport */ #define NS_JINGLE_TRANSPORT_ICEUDP "urn:xmpp:jingle:transports:ice-udp:1" #define NS_LAST "jabber:iq:last" #define NS_MUC "http://jabber.org/protocol/muc" #define NS_MUC_BYTESTREAM "http://telepathy.freedesktop.org/xmpp/protocol/muc-bytestream" #define NS_MUC_USER "http://jabber.org/protocol/muc#user" #define NS_MUC_ADMIN "http://jabber.org/protocol/muc#admin" #define NS_MUC_OWNER "http://jabber.org/protocol/muc#owner" #define NS_NICK "http://jabber.org/protocol/nick" #define NS_OOB "jabber:iq:oob" #define NS_OLPC_BUDDY_PROPS "http://laptop.org/xmpp/buddy-properties" #define NS_OLPC_ACTIVITIES "http://laptop.org/xmpp/activities" #define NS_OLPC_CURRENT_ACTIVITY "http://laptop.org/xmpp/current-activity" #define NS_OLPC_ACTIVITY_PROPS "http://laptop.org/xmpp/activity-properties" #define NS_OLPC_BUDDY "http://laptop.org/xmpp/buddy" #define NS_OLPC_ACTIVITY "http://laptop.org/xmpp/activity" #define NS_PUBSUB "http://jabber.org/protocol/pubsub" #define NS_PRESENCE_INVISIBLE "presence-invisible" #define NS_PRIVACY "jabber:iq:privacy" #define NS_INVISIBLE "urn:xmpp:invisible:0" #define NS_RECEIPTS "urn:xmpp:receipts" #define NS_REGISTER "jabber:iq:register" #define NS_ROSTER "jabber:iq:roster" #define NS_SEARCH "jabber:iq:search" #define NS_SI "http://jabber.org/protocol/si" #define NS_SI_MULTIPLE "http://telepathy.freedesktop.org/xmpp/si-multiple" #define NS_TUBES "http://telepathy.freedesktop.org/xmpp/tubes" #define NS_MUJI "http://telepathy.freedesktop.org/xmpp/muji" #define NS_VCARD_TEMP "vcard-temp" #define NS_VCARD_TEMP_UPDATE "vcard-temp:x:update" #define NS_X_DATA "jabber:x:data" #define NS_X_DELAY "jabber:x:delay" #define NS_X_CONFERENCE "jabber:x:conference" #define NS_XMPP_STANZAS "urn:ietf:params:xml:ns:xmpp-stanzas" #define NS_VERSION "jabber:iq:version" #define NS_GEOLOC "http://jabber.org/protocol/geoloc" #define NS_GOOGLE_MAIL_NOTIFY "google:mail:notify" #define NS_GOOGLE_SETTING "google:setting" #define NS_TEMPPRES "urn:xmpp:temppres:0" #define NS_GOOGLE_SHARED_STATUS "google:shared-status" /* This is used by the extension Facebook uses to push you messages you send * using other devices (or the website). * * http://www.youtube.com/watch?v=rSnXE2791yg is not the song I was looking * for, but it's not bad. */ #define NS_FACEBOOK_MESSAGES "http://www.facebook.com/xmpp/messages" #define NS_TP_FT_METADATA_SERVICE "http://telepathy.freedesktop.org/xmpp/file-transfer-service" #define NS_TP_FT_METADATA "http://telepathy.freedesktop.org/xmpp/file-transfer-metadata" /* This is used by WLM to convert Windows Live ID to XMPP jid. * See http://msdn.microsoft.com/en-us/library/live/hh550849.aspx */ #define NS_WLM_JID_LOOKUP "http://messenger.live.com/xmpp/jidlookup" #endif /* __GABBLE_NAMESPACES__H__ */ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/tls-certificate.c�������������������������������������������������������0000664�0001750�0001750�00000024341�12332441362�022217� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * tls-certificate.c - Source for GabbleTLSCertificate * Copyright (C) 2010 Collabora Ltd. * @author Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "tls-certificate.h" #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #define DEBUG_FLAG GABBLE_DEBUG_TLS #include "debug.h" static void tls_certificate_iface_init (gpointer g_iface, gpointer iface_data); G_DEFINE_TYPE_WITH_CODE (GabbleTLSCertificate, gabble_tls_certificate, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_AUTHENTICATION_TLS_CERTIFICATE, tls_certificate_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, tp_dbus_properties_mixin_iface_init);) struct _GabbleTLSCertificatePrivate { gchar *object_path; gchar *cert_type; TpTLSCertificateState cert_state; GPtrArray *rejections; GPtrArray *cert_data; TpDBusDaemon *daemon; gboolean dispose_has_run; }; enum { PROP_OBJECT_PATH = 1, PROP_STATE, PROP_REJECTIONS, PROP_CERTIFICATE_TYPE, PROP_CERTIFICATE_CHAIN_DATA, /* not exported */ PROP_DBUS_DAEMON, NUM_PROPERTIES }; static void gabble_tls_certificate_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleTLSCertificate *self = GABBLE_TLS_CERTIFICATE (object); switch (property_id) { case PROP_OBJECT_PATH: g_value_set_string (value, self->priv->object_path); break; case PROP_STATE: g_value_set_uint (value, self->priv->cert_state); break; case PROP_REJECTIONS: g_value_set_boxed (value, self->priv->rejections); break; case PROP_CERTIFICATE_TYPE: g_value_set_string (value, self->priv->cert_type); break; case PROP_CERTIFICATE_CHAIN_DATA: g_value_set_boxed (value, self->priv->cert_data); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_tls_certificate_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleTLSCertificate *self = GABBLE_TLS_CERTIFICATE (object); switch (property_id) { case PROP_OBJECT_PATH: self->priv->object_path = g_value_dup_string (value); break; case PROP_CERTIFICATE_TYPE: self->priv->cert_type = g_value_dup_string (value); break; case PROP_CERTIFICATE_CHAIN_DATA: self->priv->cert_data = g_value_dup_boxed (value); break; case PROP_DBUS_DAEMON: self->priv->daemon = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, value); break; } } static void gabble_tls_certificate_finalize (GObject *object) { GabbleTLSCertificate *self = GABBLE_TLS_CERTIFICATE (object); tp_clear_boxed (TP_ARRAY_TYPE_TLS_CERTIFICATE_REJECTION_LIST, &self->priv->rejections); g_free (self->priv->object_path); g_free (self->priv->cert_type); g_ptr_array_unref (self->priv->cert_data); G_OBJECT_CLASS (gabble_tls_certificate_parent_class)->finalize (object); } static void gabble_tls_certificate_dispose (GObject *object) { GabbleTLSCertificate *self = GABBLE_TLS_CERTIFICATE (object); if (self->priv->dispose_has_run) return; self->priv->dispose_has_run = TRUE; tp_clear_object (&self->priv->daemon); G_OBJECT_CLASS (gabble_tls_certificate_parent_class)->dispose (object); } static void gabble_tls_certificate_constructed (GObject *object) { GabbleTLSCertificate *self = GABBLE_TLS_CERTIFICATE (object); void (*chain_up) (GObject *) = G_OBJECT_CLASS (gabble_tls_certificate_parent_class)->constructed; if (chain_up != NULL) chain_up (object); /* register the certificate on the bus */ tp_dbus_daemon_register_object (self->priv->daemon, self->priv->object_path, self); } static void gabble_tls_certificate_init (GabbleTLSCertificate *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_TLS_CERTIFICATE, GabbleTLSCertificatePrivate); self->priv->rejections = g_ptr_array_new (); } static void gabble_tls_certificate_class_init (GabbleTLSCertificateClass *klass) { static TpDBusPropertiesMixinPropImpl object_props[] = { { "State", "state", NULL }, { "Rejections", "rejections", NULL }, { "CertificateType", "certificate-type", NULL }, { "CertificateChainData", "certificate-chain-data", NULL }, { NULL } }; static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { { TP_IFACE_AUTHENTICATION_TLS_CERTIFICATE, tp_dbus_properties_mixin_getter_gobject_properties, NULL, object_props, }, { NULL } }; GObjectClass *oclass = G_OBJECT_CLASS (klass); GParamSpec *pspec; g_type_class_add_private (klass, sizeof (GabbleTLSCertificatePrivate)); oclass->finalize = gabble_tls_certificate_finalize; oclass->dispose = gabble_tls_certificate_dispose; oclass->set_property = gabble_tls_certificate_set_property; oclass->get_property = gabble_tls_certificate_get_property; oclass->constructed = gabble_tls_certificate_constructed; pspec = g_param_spec_string ("object-path", "D-Bus object path", "The D-Bus object path used for this object on the bus.", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (oclass, PROP_OBJECT_PATH, pspec); pspec = g_param_spec_uint ("state", "State of this certificate", "The state of this TLS certificate.", 0, NUM_TP_TLS_CERTIFICATE_STATES - 1, TP_TLS_CERTIFICATE_STATE_PENDING, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (oclass, PROP_STATE, pspec); pspec = g_param_spec_boxed ("rejections", "The reject reasons", "The reasons why this TLS certificate has been rejected", TP_ARRAY_TYPE_TLS_CERTIFICATE_REJECTION_LIST, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (oclass, PROP_REJECTIONS, pspec); pspec = g_param_spec_string ("certificate-type", "The certificate type", "The type of this certificate.", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (oclass, PROP_CERTIFICATE_TYPE, pspec); pspec = g_param_spec_boxed ("certificate-chain-data", "The certificate chain data", "The raw PEM-encoded trust chain of this certificate.", TP_ARRAY_TYPE_UCHAR_ARRAY_LIST, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (oclass, PROP_CERTIFICATE_CHAIN_DATA, pspec); pspec = g_param_spec_object ("dbus-daemon", "The DBus daemon connection", "The connection to the DBus daemon owning the CM", TP_TYPE_DBUS_DAEMON, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (oclass, PROP_DBUS_DAEMON, pspec); klass->dbus_props_class.interfaces = prop_interfaces; tp_dbus_properties_mixin_class_init (oclass, G_STRUCT_OFFSET (GabbleTLSCertificateClass, dbus_props_class)); } static void gabble_tls_certificate_accept (TpSvcAuthenticationTLSCertificate *cert, DBusGMethodInvocation *context) { GabbleTLSCertificate *self = GABBLE_TLS_CERTIFICATE (cert); DEBUG ("Accept() called on the TLS certificate; current state %u", self->priv->cert_state); if (self->priv->cert_state != TP_TLS_CERTIFICATE_STATE_PENDING) { GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Calling Accept() on a certificate with state != PENDING " "doesn't make sense." }; dbus_g_method_return_error (context, &error); return; } self->priv->cert_state = TP_TLS_CERTIFICATE_STATE_ACCEPTED; tp_svc_authentication_tls_certificate_emit_accepted (self); tp_svc_authentication_tls_certificate_return_from_accept (context); } static void gabble_tls_certificate_reject (TpSvcAuthenticationTLSCertificate *cert, const GPtrArray *rejections, DBusGMethodInvocation *context) { GabbleTLSCertificate *self = GABBLE_TLS_CERTIFICATE (cert); DEBUG ("Reject() called on the TLS certificate with rejections %p, " "length %u; current state %u", rejections, rejections->len, self->priv->cert_state); if (rejections->len < 1) { GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Calling Reject() with a zero-length rejection list." }; dbus_g_method_return_error (context, &error); return; } if (self->priv->cert_state != TP_TLS_CERTIFICATE_STATE_PENDING) { GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Calling Reject() on a certificate with state != PENDING " "doesn't make sense." }; dbus_g_method_return_error (context, &error); return; } tp_clear_boxed (TP_ARRAY_TYPE_TLS_CERTIFICATE_REJECTION_LIST, &self->priv->rejections); self->priv->rejections = g_boxed_copy (TP_ARRAY_TYPE_TLS_CERTIFICATE_REJECTION_LIST, rejections); self->priv->cert_state = TP_TLS_CERTIFICATE_STATE_REJECTED; tp_svc_authentication_tls_certificate_emit_rejected ( self, self->priv->rejections); tp_svc_authentication_tls_certificate_return_from_reject (context); } static void tls_certificate_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcAuthenticationTLSCertificateClass *klass = g_iface; #define IMPLEMENT(x) \ tp_svc_authentication_tls_certificate_implement_##x ( \ klass, gabble_tls_certificate_##x) IMPLEMENT (accept); IMPLEMENT (reject); #undef IMPLEMENT } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/addressing-util.h�������������������������������������������������������0000664�0001750�0001750�00000005003�12332440117�022227� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * addressing-util.c - Headers for Gabble addressing utility functions * Copyright (C) 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_UTIL_ADDRESSING_H__ #define __GABBLE_UTIL_ADDRESSING_H__ #include <telepathy-glib/telepathy-glib.h> const gchar * const * gabble_get_addressable_uri_schemes (void); const gchar * const * gabble_get_addressable_vcard_fields (void); gchar * gabble_normalize_contact_uri (const gchar *uri, GError **error); gchar * gabble_uri_to_jid (const gchar *uri, GError **error); gchar * gabble_jid_to_uri (const gchar *scheme, const gchar *jid, GError **error); TpHandle gabble_ensure_handle_from_uri (TpHandleRepoIface *repo, const gchar *uri, GError **error); gchar * gabble_normalize_vcard_address (const gchar *vcard_field, const gchar *vcard_address, GError **error); gchar * gabble_vcard_address_to_jid (const gchar *vcard_field, const gchar *vcard_address, GError **error); gchar * gabble_jid_to_vcard_address (const gchar *vcard_field, const gchar *jid, GError **error); TpHandle gabble_ensure_handle_from_vcard_address (TpHandleRepoIface *repo, const gchar *vcard_field, const gchar *vcard_address, GError **error); gchar **gabble_uris_for_handle (TpHandleRepoIface *contact_repo, TpHandle contact); GHashTable *gabble_vcard_addresses_for_handle (TpHandleRepoIface *contact_repo, TpHandle contact); gchar *gabble_uri_for_handle (TpHandleRepoIface *contact_repo, const gchar *uri_scheme, TpHandle contact); gchar *gabble_vcard_address_for_handle (TpHandleRepoIface *contact_repo, const gchar *vcard_field, TpHandle contact); gboolean gabble_parse_xmpp_uri (const gchar *uri, gchar **node, gchar **domain, gchar **resource, GError **error); #endif /* __GABBLE_UTIL_ADDRESSING_H__ */ �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/tube-iface.c������������������������������������������������������������0000664�0001750�0001750�00000014450�12332441362�021141� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * tube-iface.c - Source for GabbleTube interface * Copyright (C) 2007-2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "tube-iface.h" #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #include "connection.h" #include "util.h" gboolean gabble_tube_iface_accept (GabbleTubeIface *self, GError **error) { gboolean (*virtual_method)(GabbleTubeIface *, GError **) = GABBLE_TUBE_IFACE_GET_CLASS (self)->accept; g_assert (virtual_method != NULL); return virtual_method (self, error); } void gabble_tube_iface_close (GabbleTubeIface *self, gboolean closed_remotely) { void (*virtual_method)(GabbleTubeIface *, gboolean) = GABBLE_TUBE_IFACE_GET_CLASS (self)->close; g_assert (virtual_method != NULL); virtual_method (self, closed_remotely); } void gabble_tube_iface_add_bytestream (GabbleTubeIface *self, GabbleBytestreamIface *bytestream) { void (*virtual_method)(GabbleTubeIface *, GabbleBytestreamIface *) = GABBLE_TUBE_IFACE_GET_CLASS (self)->add_bytestream; g_assert (virtual_method != NULL); virtual_method (self, bytestream); } static void gabble_tube_iface_base_init (gpointer klass) { static gboolean initialized = FALSE; if (!initialized) { GParamSpec *param_spec; param_spec = g_param_spec_uint ( "self-handle", "Self handle", "The handle to use for ourself. This can be different from the " "connection's self handle if our handle is a room handle.", 0, G_MAXUINT, 0, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_uint64 ( "id", "id", "The unique identifier of this tube", 0, G_MAXUINT32, 0, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_uint ( "type", "Tube type", "The TpTubeType this tube object.", 0, G_MAXUINT32, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_string ( "service", "service name", "the service associated with this tube object.", "", G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_boxed ( "parameters", "parameters GHashTable", "GHashTable containing parameters of this tube object.", TP_HASH_TYPE_STRING_VARIANT_MAP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_uint ( "state", "Tube state", "The TpTubeChannelState of this tube object", 0, G_MAXUINT32, TP_TUBE_CHANNEL_STATE_REMOTE_PENDING, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); initialized = TRUE; } } GType gabble_tube_iface_get_type (void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof (GabbleTubeIfaceClass), gabble_tube_iface_base_init, /* base_init */ NULL, /* base_finalize */ NULL, /* class_init */ NULL, /* class_finalize */ NULL, /* class_data */ 0, 0, /* n_preallocs */ NULL /* instance_init */ }; type = g_type_register_static (G_TYPE_INTERFACE, "GabbleTubeIface", &info, 0); } return type; } void gabble_tube_iface_publish_in_node (GabbleTubeIface *tube, TpBaseConnection *conn, WockyNode *node) { WockyNode *parameters_node; GHashTable *parameters; TpTubeType type; gchar *service, *id_str; guint64 tube_id; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( conn, TP_HANDLE_TYPE_CONTACT); TpHandle initiator_handle; g_object_get (G_OBJECT (tube), "type", &type, "initiator-handle", &initiator_handle, "service", &service, "parameters", ¶meters, "id", &tube_id, NULL); id_str = g_strdup_printf ("%" G_GUINT64_FORMAT, tube_id); wocky_node_set_attributes (node, "service", service, "id", id_str, NULL); g_free (id_str); switch (type) { case TP_TUBE_TYPE_DBUS: { gchar *name, *stream_id; g_object_get (G_OBJECT (tube), "stream-id", &stream_id, "dbus-name", &name, NULL); wocky_node_set_attributes (node, "type", "dbus", "stream-id", stream_id, "initiator", tp_handle_inspect (contact_repo, initiator_handle), NULL); if (name != NULL) wocky_node_set_attribute (node, "dbus-name", name); g_free (name); g_free (stream_id); } break; case TP_TUBE_TYPE_STREAM: { wocky_node_set_attribute (node, "type", "stream"); } break; default: { g_return_if_reached (); } } parameters_node = wocky_node_add_child_with_content (node, "parameters", NULL); lm_message_node_add_children_from_properties (parameters_node, parameters, "parameter"); g_free (service); g_hash_table_unref (parameters); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/conn-location.c���������������������������������������������������������0000664�0001750�0001750�00000046456�12332441362�021713� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ #define _GNU_SOURCE #include "config.h" #include "conn-location.h" #include <string.h> #include <stdlib.h> #define DEBUG_FLAG GABBLE_DEBUG_LOCATION #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #include <wocky/wocky.h> #include <gabble/gabble.h> #include "debug.h" #include "namespaces.h" #include "presence-cache.h" #include "util.h" typedef struct { gchar *xmpp_name; gchar *tp_name; GType type; } LocationMapping; static const LocationMapping mappings[] = { { "alt", "alt", G_TYPE_DOUBLE }, { "area", "area", G_TYPE_STRING }, { "bearing", "bearing", G_TYPE_DOUBLE }, { "building", "building", G_TYPE_STRING }, { "country", "country", G_TYPE_STRING }, { "description", "description", G_TYPE_STRING }, { "floor", "floor", G_TYPE_STRING }, { "lat", "lat", G_TYPE_DOUBLE }, { "locality", "locality", G_TYPE_STRING }, { "lon", "lon", G_TYPE_DOUBLE }, { "postalcode", "postalcode", G_TYPE_STRING }, { "region", "region", G_TYPE_STRING }, { "room", "room", G_TYPE_STRING }, { "speed", "speed", G_TYPE_DOUBLE }, { "street", "street", G_TYPE_STRING }, { "text", "text", G_TYPE_STRING }, { "timestamp", "timestamp", G_TYPE_INT64 }, { "uri", "uri", G_TYPE_STRING }, { "accuracy", "accuracy", G_TYPE_DOUBLE }, { "countrycode", "countrycode", G_TYPE_STRING }, /* language is a special case as it's not mapped on a node but on the * xml:lang attribute of the 'geoloc' node. */ { NULL, NULL }, }; static GHashTable *xmpp_to_tp = NULL; static GHashTable *tp_to_xmpp = NULL; static void build_mapping_tables (void) { guint i; if (xmpp_to_tp != NULL) return; g_assert (tp_to_xmpp == NULL); xmpp_to_tp = g_hash_table_new (g_str_hash, g_str_equal); tp_to_xmpp = g_hash_table_new (g_str_hash, g_str_equal); for (i = 0; mappings[i].xmpp_name != NULL; i++) { g_hash_table_insert (xmpp_to_tp, mappings[i].xmpp_name, (gpointer) &mappings[i]); g_hash_table_insert (tp_to_xmpp, mappings[i].tp_name, (gpointer) &mappings[i]); } } static gboolean update_location_from_item ( GabbleConnection *conn, TpHandle contact, WockyNode *item_node); /* * get_cached_location: * @conn: a connection * @handle: a handle, which must have been pre-validated. * * Returns: a new ref to a GHashTable containing @handle's location, or %NULL * if we have no cached location. */ static GHashTable * get_cached_location (GabbleConnection *conn, TpHandle handle) { TpBaseConnection *base = (TpBaseConnection *) conn; GHashTable *location; const gchar *jid; TpHandleRepoIface *contact_repo; contact_repo = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); jid = tp_handle_inspect (contact_repo, handle); location = gabble_presence_cache_get_location (conn->presence_cache, handle); if (location != NULL) DEBUG (" - %s: cached", jid); else DEBUG (" - %s: unknown", jid); return location; } static void location_get_locations (TpSvcConnectionInterfaceLocation *iface, const GArray *contacts, DBusGMethodInvocation *context) { GabbleConnection *conn = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) conn; TpHandleRepoIface *contact_handles; guint i; GError *error = NULL; GHashTable *return_locations = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_hash_table_unref); DEBUG ("GetLocation for contacts:"); gabble_connection_ensure_capabilities (conn, gabble_capabilities_get_geoloc_notify ()); /* Validate contacts */ contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); if (!tp_handles_are_valid (contact_handles, contacts, TRUE, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); g_hash_table_unref (return_locations); return; } for (i = 0; i < contacts->len; i++) { TpHandle contact = g_array_index (contacts, TpHandle, i); GHashTable *location = get_cached_location (conn, contact); if (location != NULL) g_hash_table_insert (return_locations, GUINT_TO_POINTER (contact), location); } tp_svc_connection_interface_location_return_from_get_locations (context, return_locations); g_hash_table_unref (return_locations); } typedef struct { GabbleConnection *self; TpHandle handle; DBusGMethodInvocation *context; } YetAnotherContextStruct; static void request_location_reply_cb (GObject *source, GAsyncResult *res, gpointer user_data) { YetAnotherContextStruct *ctx = user_data; WockyStanza *reply; WockyNode *item_node; GError *wocky_error = NULL, *tp_error = NULL; reply = wocky_pep_service_get_finish (WOCKY_PEP_SERVICE (source), res, &item_node, &wocky_error); if (reply == NULL || wocky_stanza_extract_errors (reply, NULL, &wocky_error, NULL, NULL)) { DEBUG ("fetching location failed: %s", wocky_error->message); gabble_set_tp_error_from_wocky (wocky_error, &tp_error); dbus_g_method_return_error (ctx->context, tp_error); g_error_free (tp_error); } else { GHashTable *location; if (update_location_from_item (ctx->self, ctx->handle, item_node)) { location = get_cached_location (ctx->self, ctx->handle); /* We just cached a location for this contact, so it should be * non-NULL. */ g_return_if_fail (location != NULL); } else { /* If the location's unparseable, we'll hit this path. That seems * okay. */ location = g_hash_table_new (NULL, NULL); } tp_svc_connection_interface_location_return_from_request_location ( ctx->context, location); g_hash_table_unref (location); } tp_clear_object (&reply); g_object_unref (ctx->self); g_slice_free (YetAnotherContextStruct, ctx); } static void location_request_location ( TpSvcConnectionInterfaceLocation *iface, TpHandle handle, DBusGMethodInvocation *context) { GabbleConnection *self = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) self; TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); const gchar *jid; WockyBareContact *contact; YetAnotherContextStruct *ctx; GError *error = NULL; if (!tp_handle_is_valid (contact_handles, handle, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); return; } /* Oh! for GDBus. */ ctx = g_slice_new (YetAnotherContextStruct); ctx->self = g_object_ref (self); ctx->handle = handle; ctx->context = context; jid = tp_handle_inspect (contact_handles, handle); contact = ensure_bare_contact_from_jid (self, jid); DEBUG ("fetching location for '%s'", jid); wocky_pep_service_get_async (self->pep_location, contact, NULL, request_location_reply_cb, ctx); g_object_unref (contact); } static gboolean add_to_geoloc_node (const gchar *tp_name, GValue *value, WockyNode *geoloc, GError **err) { LocationMapping *mapping; gchar *str = NULL; /* Map "language" to the xml:lang attribute. */ if (!tp_strdiff (tp_name, "language")) { if (G_VALUE_TYPE (value) != G_TYPE_STRING) { g_set_error (err, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "expecting string for language value, but got %s", G_VALUE_TYPE_NAME (value)); return FALSE; } wocky_node_set_attribute ( geoloc, "xml:lang", g_value_get_string (value)); return TRUE; } mapping = g_hash_table_lookup (tp_to_xmpp, tp_name); if (mapping == NULL) { DEBUG ("Unknown location key: %s ; skipping", (const gchar *) tp_name); /* We don't raise a D-Bus error if the key is unknown to stay backward * compatible if new keys are added in a future version of the spec. */ return TRUE; } if (G_VALUE_TYPE (value) != mapping->type) { g_set_error (err, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "'%s' is supposed to be of type %s but is %s", (const char *) tp_name, g_type_name (mapping->type), G_VALUE_TYPE_NAME (value)); return FALSE; } if (G_VALUE_TYPE (value) == G_TYPE_INT64) { GTimeVal timeval; timeval.tv_sec = CLAMP (g_value_get_int64 (value), 0, G_MAXLONG); timeval.tv_usec = 0; str = g_time_val_to_iso8601 (&timeval); } else if (G_VALUE_TYPE (value) == G_TYPE_DOUBLE) { str = g_strdup_printf ("%.6f", g_value_get_double (value)); } else if (G_VALUE_TYPE (value) == G_TYPE_STRING) { str = g_value_dup_string (value); } else /* Keys and their type have been checked */ g_assert_not_reached (); wocky_node_add_child_with_content (geoloc, mapping->xmpp_name, str); DEBUG ("\t - %s: %s", (gchar *) tp_name, str); g_free (str); return TRUE; } static void set_location_sent_cb (GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg, GObject *object, gpointer user_data) { DBusGMethodInvocation *context = user_data; GError *error = NULL; if (!wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL)) { dbus_g_method_return (context); } else { GError *tp_error = NULL; DEBUG ("SetLocation failed: %s", error->message); gabble_set_tp_error_from_wocky (error, &tp_error); dbus_g_method_return_error (context, tp_error); g_error_free (tp_error); g_error_free (error); } } static void location_set_location (TpSvcConnectionInterfaceLocation *iface, GHashTable *location, DBusGMethodInvocation *context) { GabbleConnection *conn = GABBLE_CONNECTION (iface); WockyStanza *msg; WockyNode *geoloc; WockyNode *item; GHashTableIter iter; gpointer key, value; GError *err = NULL; TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED ((TpBaseConnection *) conn, context); if (!(conn->features & GABBLE_CONNECTION_FEATURES_PEP)) { GError error = { TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "Server does not support PEP, cannot publish geolocation" }; dbus_g_method_return_error (context, &error); return; } gabble_connection_ensure_capabilities (conn, gabble_capabilities_get_geoloc_notify ()); msg = wocky_pep_service_make_publish_stanza (conn->pep_location, &item); geoloc = wocky_node_add_child_ns (item, "geoloc", NS_GEOLOC); DEBUG ("SetLocation to"); build_mapping_tables (); g_hash_table_iter_init (&iter, location); while (g_hash_table_iter_next (&iter, &key, &value)) { if (!add_to_geoloc_node ((const gchar *) key, (GValue *) value, geoloc, &err)) { DEBUG ("%s", err->message); dbus_g_method_return_error (context, err); g_error_free (err); goto out; } } if (!_gabble_connection_send_with_reply (conn, msg, set_location_sent_cb, G_OBJECT (conn), context, NULL)) { GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR, "Failed to send msg" }; dbus_g_method_return_error (context, &error); } out: g_object_unref (msg); } void location_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcConnectionInterfaceLocationClass *klass = g_iface; #define IMPLEMENT(x) tp_svc_connection_interface_location_implement_##x \ (klass, location_##x) IMPLEMENT(get_locations); IMPLEMENT(set_location); IMPLEMENT(request_location); #undef IMPLEMENT } void conn_location_properties_getter (GObject *object, GQuark interface, GQuark name, GValue *value, gpointer getter_data) { GabbleConnection *conn = GABBLE_CONNECTION (object); if (!tp_strdiff (g_quark_to_string (name), "LocationAccessControlTypes")) { guint access_control_type = TP_RICH_PRESENCE_ACCESS_CONTROL_TYPE_PUBLISH_LIST; GArray *access_control = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1); g_array_append_val (access_control, access_control_type); g_value_take_boxed (value, access_control); } else if (!tp_strdiff (g_quark_to_string (name), "LocationAccessControl")) { GValueArray *access_control = g_value_array_new (2); GValue type = {0,}; GValue variant = {0,}; GValue *allocated_value; /* G_TYPE_UINT is the D-Bus type of TpRichPresenceAccessControlType */ g_value_init (&type, G_TYPE_UINT); g_value_set_uint (&type, TP_RICH_PRESENCE_ACCESS_CONTROL_TYPE_PUBLISH_LIST); g_value_array_append (access_control, &type); g_value_unset (&type); g_value_init (&variant, G_TYPE_VALUE); /* For Publish_List, the variant isn't used, so we set a dummy value, * (guint) 0 */ allocated_value = tp_g_value_slice_new (G_TYPE_UINT); g_value_set_uint (allocated_value, 0); g_value_set_boxed (&variant, allocated_value); g_value_array_append (access_control, &variant); g_value_unset (&variant); tp_g_value_slice_free (allocated_value); g_value_take_boxed (value, access_control); } else if (name == g_quark_from_static_string ("SupportedLocationFeatures")) { TpLocationFeatures flags = 0; if (conn->features & GABBLE_CONNECTION_FEATURES_PEP) flags |= TP_LOCATION_FEATURE_CAN_SET; g_value_set_uint (value, flags); } else { g_assert_not_reached (); } } gboolean conn_location_properties_setter (GObject *object, GQuark interface, GQuark name, const GValue *value, gpointer setter_data, GError **error) { GValueArray *access_control; GValue *access_control_type_value; TpRichPresenceAccessControlType access_control_type; g_return_val_if_fail (interface == TP_IFACE_QUARK_CONNECTION_INTERFACE_LOCATION, FALSE); /* There is only one property with write access. So TpDBusPropertiesMixin * already checked this. */ g_assert (name == g_quark_from_static_string ("LocationAccessControl")); access_control = g_value_get_boxed (value); /* TpDBusPropertiesMixin already checked this */ g_assert (access_control->n_values == 2); access_control_type_value = g_value_array_get_nth (access_control, 0); /* TpDBusPropertiesMixin already checked this */ g_assert (G_VALUE_TYPE (access_control_type_value) == G_TYPE_UINT); access_control_type = g_value_get_uint (access_control_type_value); if (access_control_type != TP_RICH_PRESENCE_ACCESS_CONTROL_TYPE_PUBLISH_LIST) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "Access control type not implemented"); return FALSE; } return TRUE; } static gboolean update_location_from_item ( GabbleConnection *conn, TpHandle contact, WockyNode *item_node) { WockyNode *node; GHashTable *location = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_free, (GDestroyNotify) tp_g_value_slice_free); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); const gchar *from = tp_handle_inspect (contact_repo, contact); WockyNodeIter i; WockyNode *subloc_node; const gchar *lang; if (item_node == NULL) return FALSE; node = wocky_node_get_child_ns (item_node, "geoloc", NS_GEOLOC); if (node == NULL) return FALSE; DEBUG ("LocationsUpdate for %s:", from); lang = wocky_node_get_language (node); if (lang != NULL) { g_hash_table_insert (location, g_strdup ("language"), tp_g_value_slice_new_string (lang)); } build_mapping_tables (); wocky_node_iter_init (&i, node, NULL, NULL); while (wocky_node_iter_next (&i, &subloc_node)) { GValue *value = NULL; gchar *xmpp_name; const gchar *str; LocationMapping *mapping; xmpp_name = subloc_node->name; str = subloc_node->content; if (str == NULL) continue; mapping = g_hash_table_lookup (xmpp_to_tp, xmpp_name); if (mapping == NULL) { DEBUG ("Unknown location attribute: %s\n", xmpp_name); continue; } if (mapping->type == G_TYPE_DOUBLE) { gdouble double_value; gchar *end; double_value = g_ascii_strtod (str, &end); if (end == str) continue; value = tp_g_value_slice_new_double (double_value); DEBUG ("\t - %s: %f", xmpp_name, double_value); } else if (strcmp (xmpp_name, "timestamp") == 0) { GTimeVal timeval; if (g_time_val_from_iso8601 (str, &timeval)) { value = tp_g_value_slice_new_int64 (timeval.tv_sec); DEBUG ("\t - %s: %s", xmpp_name, str); } else { DEBUG ("\t - %s: %s: unknown date format", xmpp_name, str); continue; } } else if (mapping->type == G_TYPE_STRING) { value = tp_g_value_slice_new_string (str); DEBUG ("\t - %s: %s", xmpp_name, str); } else { g_assert_not_reached (); } g_hash_table_insert (location, g_strdup (mapping->tp_name), value); } tp_svc_connection_interface_location_emit_location_updated (conn, contact, location); gabble_presence_cache_update_location (conn->presence_cache, contact, location); return TRUE; } static void location_pep_node_changed (WockyPepService *pep, WockyBareContact *contact, WockyStanza *stanza, WockyNode *item_node, GabbleConnection *conn) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); TpBaseConnection *base = (TpBaseConnection *) conn; TpHandle handle; const gchar *jid; jid = wocky_bare_contact_get_jid (contact); handle = tp_handle_ensure (contact_repo, jid, NULL, NULL); if (handle == 0) { DEBUG ("Invalid from: %s", jid); return; } if (handle == tp_base_connection_get_self_handle (base)) /* Ignore echoed pubsub notifications */ return; update_location_from_item (conn, handle, item_node); } static void conn_location_fill_contact_attributes (GObject *obj, const GArray *contacts, GHashTable *attributes_hash) { GabbleConnection *self = GABBLE_CONNECTION (obj); guint i; for (i = 0; i < contacts->len; i++) { TpHandle handle = g_array_index (contacts, TpHandle, i); GHashTable *location = get_cached_location (self, handle); if (location != NULL) { GValue *val = tp_g_value_slice_new_take_boxed ( TP_HASH_TYPE_STRING_VARIANT_MAP, location); tp_contacts_mixin_set_contact_attribute (attributes_hash, handle, TP_IFACE_CONNECTION_INTERFACE_LOCATION"/location", val); } } } void conn_location_init (GabbleConnection *conn) { tp_contacts_mixin_add_contact_attributes_iface (G_OBJECT (conn), TP_IFACE_CONNECTION_INTERFACE_LOCATION, conn_location_fill_contact_attributes); conn->pep_location = wocky_pep_service_new (NS_GEOLOC, TRUE); g_signal_connect (conn->pep_location, "changed", G_CALLBACK (location_pep_node_changed), conn); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/bytestream-socks5.h�����������������������������������������������������0000664�0001750�0001750�00000005075�12223562023�022526� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * bytestream-socks5.h - Header for GabbleBytestreamSocks5 * Copyright (C) 2007-2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_BYTESTREAM_SOCKS5_H__ #define __GABBLE_BYTESTREAM_SOCKS5_H__ #include <stdlib.h> #include <glib-object.h> #include <wocky/wocky.h> #include <telepathy-glib/telepathy-glib.h> G_BEGIN_DECLS typedef struct _GabbleBytestreamSocks5 GabbleBytestreamSocks5; typedef struct _GabbleBytestreamSocks5Class GabbleBytestreamSocks5Class; typedef struct _GabbleBytestreamSocks5Private GabbleBytestreamSocks5Private; struct _GabbleBytestreamSocks5Class { GObjectClass parent_class; }; struct _GabbleBytestreamSocks5 { GObject parent; GabbleBytestreamSocks5Private *priv; }; GType gabble_bytestream_socks5_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_BYTESTREAM_SOCKS5 \ (gabble_bytestream_socks5_get_type ()) #define GABBLE_BYTESTREAM_SOCKS5(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_BYTESTREAM_SOCKS5,\ GabbleBytestreamSocks5)) #define GABBLE_BYTESTREAM_SOCKS5_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_BYTESTREAM_SOCKS5,\ GabbleBytestreamSocks5Class)) #define GABBLE_IS_BYTESTREAM_SOCKS5(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_BYTESTREAM_SOCKS5)) #define GABBLE_IS_BYTESTREAM_SOCKS5_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_BYTESTREAM_SOCKS5)) #define GABBLE_BYTESTREAM_SOCKS5_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_BYTESTREAM_SOCKS5,\ GabbleBytestreamSocks5Class)) void gabble_bytestream_socks5_add_streamhost (GabbleBytestreamSocks5 *socks5, WockyNode *streamhost_node); void gabble_bytestream_socks5_connect_to_streamhost ( GabbleBytestreamSocks5 *socks5, WockyStanza *msg); G_END_DECLS #endif /* #ifndef __GABBLE_BYTESTREAM_SOCKS5_H__ */ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/bytestream-muc.h��������������������������������������������������������0000664�0001750�0001750�00000004672�12223562023�022105� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * bytestream-muc.h - Header for GabbleBytestreamMuc * Copyright (C) 2007 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_BYTESTREAM_MUC_H__ #define __GABBLE_BYTESTREAM_MUC_H__ #include <glib-object.h> #include <wocky/wocky.h> #include <telepathy-glib/telepathy-glib.h> G_BEGIN_DECLS typedef struct _GabbleBytestreamMuc GabbleBytestreamMuc; typedef struct _GabbleBytestreamMucClass GabbleBytestreamMucClass; typedef struct _GabbleBytestreamMucPrivate GabbleBytestreamMucPrivate; struct _GabbleBytestreamMucClass { GObjectClass parent_class; }; struct _GabbleBytestreamMuc { GObject parent; GabbleBytestreamMucPrivate *priv; }; GType gabble_bytestream_muc_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_BYTESTREAM_MUC \ (gabble_bytestream_muc_get_type ()) #define GABBLE_BYTESTREAM_MUC(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_BYTESTREAM_MUC,\ GabbleBytestreamMuc)) #define GABBLE_BYTESTREAM_MUC_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_BYTESTREAM_MUC,\ GabbleBytestreamMucClass)) #define GABBLE_IS_BYTESTREAM_MUC(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_BYTESTREAM_MUC)) #define GABBLE_IS_BYTESTREAM_MUC_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_BYTESTREAM_MUC)) #define GABBLE_BYTESTREAM_MUC_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_BYTESTREAM_MUC,\ GabbleBytestreamMucClass)) void gabble_bytestream_muc_receive (GabbleBytestreamMuc *bytestream, WockyStanza *msg); gboolean gabble_bytestream_muc_send_to (GabbleBytestreamMuc *bytestream, TpHandle to, guint len, gchar *str); G_END_DECLS #endif /* #ifndef __GABBLE_BYTESTREAM_MUC_H__ */ ����������������������������������������������������������������������telepathy-gabble-0.18.3/src/bytestream-ibb.c��������������������������������������������������������0000664�0001750�0001750�00000066604�12332440117�022053� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * bytestream-ibb.c - Source for GabbleBytestreamIBB * Copyright (C) 2007 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "bytestream-ibb.h" #include <string.h> #include <dbus/dbus-glib.h> #include <dbus/dbus-glib-lowlevel.h> #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #define DEBUG_FLAG GABBLE_DEBUG_BYTESTREAM #include "bytestream-factory.h" #include "bytestream-iface.h" #include "connection.h" #include "conn-util.h" #include "debug.h" #include "disco.h" #include "namespaces.h" #include "util.h" static void bytestream_iface_init (gpointer g_iface, gpointer iface_data); G_DEFINE_TYPE_WITH_CODE (GabbleBytestreamIBB, gabble_bytestream_ibb, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GABBLE_TYPE_BYTESTREAM_IFACE, bytestream_iface_init)); /* properties */ enum { PROP_CONNECTION = 1, PROP_PEER_HANDLE, PROP_PEER_HANDLE_TYPE, PROP_STREAM_ID, PROP_STREAM_INIT_ID, PROP_PEER_JID, PROP_PEER_RESOURCE, PROP_STATE, PROP_PROTOCOL, PROP_BLOCK_SIZE, LAST_PROPERTY }; #define READ_BUFFER_MAX_SIZE (512 * 1024) /* the number of not acked stanzas allowed. Once this number reached, we stop * sending and wait for acks. */ #define WINDOW_SIZE 10 struct _GabbleBytestreamIBBPrivate { GabbleConnection *conn; TpHandle peer_handle; gchar *stream_id; gchar *stream_init_id; gchar *peer_resource; GabbleBytestreamState state; gchar *peer_jid; guint block_size; guint16 seq; guint16 last_seq_recv; WockyStanza *close_iq_to_ack; /* We can't stop receving IBB data so if user wants to block the bytestream * we buffer them until he unblocks it. */ gboolean read_blocked; GString *read_buffer; /* list of reffed (WockyStanza *) */ GSList *received_stanzas_not_acked; /* (WockyStanza *) -> TRUE * We don't keep a ref on the WockyStanza as we just use this table to track * stanzas waiting for reply. The stanza is never used (and so deferenced). */ GHashTable *sent_stanzas_not_acked; GString *write_buffer; gboolean write_blocked; gboolean dispose_has_run; }; #define GABBLE_BYTESTREAM_IBB_GET_PRIVATE(obj) ((obj)->priv) static void gabble_bytestream_ibb_init (GabbleBytestreamIBB *self) { GabbleBytestreamIBBPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_BYTESTREAM_IBB, GabbleBytestreamIBBPrivate); self->priv = priv; priv->read_buffer = NULL; priv->received_stanzas_not_acked = NULL; priv->sent_stanzas_not_acked = g_hash_table_new (g_direct_hash, g_direct_equal); priv->write_buffer = NULL; priv->write_blocked = FALSE; } static void gabble_bytestream_ibb_dispose (GObject *object) { GabbleBytestreamIBB *self = GABBLE_BYTESTREAM_IBB (object); GabbleBytestreamIBBPrivate *priv = GABBLE_BYTESTREAM_IBB_GET_PRIVATE (self); if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; if (priv->state != GABBLE_BYTESTREAM_STATE_CLOSED) { gabble_bytestream_iface_close (GABBLE_BYTESTREAM_IFACE (self), NULL); } if (priv->close_iq_to_ack != NULL) { _gabble_connection_acknowledge_set_iq (priv->conn, priv->close_iq_to_ack); g_object_unref (priv->close_iq_to_ack); priv->close_iq_to_ack = NULL; } G_OBJECT_CLASS (gabble_bytestream_ibb_parent_class)->dispose (object); } static void gabble_bytestream_ibb_finalize (GObject *object) { GabbleBytestreamIBB *self = GABBLE_BYTESTREAM_IBB (object); GabbleBytestreamIBBPrivate *priv = GABBLE_BYTESTREAM_IBB_GET_PRIVATE (self); g_free (priv->stream_id); g_free (priv->stream_init_id); g_free (priv->peer_resource); g_free (priv->peer_jid); if (priv->read_buffer != NULL) g_string_free (priv->read_buffer, TRUE); if (priv->write_buffer != NULL) g_string_free (priv->write_buffer, TRUE); g_hash_table_unref (priv->sent_stanzas_not_acked); G_OBJECT_CLASS (gabble_bytestream_ibb_parent_class)->finalize (object); } static void gabble_bytestream_ibb_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleBytestreamIBB *self = GABBLE_BYTESTREAM_IBB (object); GabbleBytestreamIBBPrivate *priv = GABBLE_BYTESTREAM_IBB_GET_PRIVATE (self); switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, priv->conn); break; case PROP_PEER_HANDLE: g_value_set_uint (value, priv->peer_handle); break; case PROP_PEER_HANDLE_TYPE: g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT); break; case PROP_STREAM_ID: g_value_set_string (value, priv->stream_id); break; case PROP_STREAM_INIT_ID: g_value_set_string (value, priv->stream_init_id); break; case PROP_PEER_RESOURCE: g_value_set_string (value, priv->peer_resource); break; case PROP_PEER_JID: g_value_set_string (value, priv->peer_jid); break; case PROP_STATE: g_value_set_uint (value, priv->state); break; case PROP_PROTOCOL: g_value_set_string (value, NS_IBB); break; case PROP_BLOCK_SIZE: g_value_set_uint (value, priv->block_size); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_bytestream_ibb_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleBytestreamIBB *self = GABBLE_BYTESTREAM_IBB (object); GabbleBytestreamIBBPrivate *priv = GABBLE_BYTESTREAM_IBB_GET_PRIVATE (self); switch (property_id) { case PROP_CONNECTION: priv->conn = g_value_get_object (value); break; case PROP_PEER_HANDLE: priv->peer_handle = g_value_get_uint (value); break; case PROP_STREAM_ID: g_free (priv->stream_id); priv->stream_id = g_value_dup_string (value); break; case PROP_STREAM_INIT_ID: g_free (priv->stream_init_id); priv->stream_init_id = g_value_dup_string (value); break; case PROP_PEER_RESOURCE: g_free (priv->peer_resource); priv->peer_resource = g_value_dup_string (value); break; case PROP_STATE: if (priv->state != g_value_get_uint (value)) { priv->state = g_value_get_uint (value); g_signal_emit_by_name (object, "state-changed", priv->state); } break; case PROP_BLOCK_SIZE: priv->block_size = g_value_get_uint (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static GObject * gabble_bytestream_ibb_constructor (GType type, guint n_props, GObjectConstructParam *props) { GObject *obj; GabbleBytestreamIBBPrivate *priv; TpHandleRepoIface *contact_repo; const gchar *jid; obj = G_OBJECT_CLASS (gabble_bytestream_ibb_parent_class)-> constructor (type, n_props, props); priv = GABBLE_BYTESTREAM_IBB_GET_PRIVATE (GABBLE_BYTESTREAM_IBB (obj)); g_assert (priv->conn != NULL); g_assert (priv->peer_handle != 0); g_assert (priv->stream_id != NULL); contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); jid = tp_handle_inspect (contact_repo, priv->peer_handle); if (priv->peer_resource != NULL) priv->peer_jid = g_strdup_printf ("%s/%s", jid, priv->peer_resource); else priv->peer_jid = g_strdup (jid); return obj; } static void gabble_bytestream_ibb_class_init ( GabbleBytestreamIBBClass *gabble_bytestream_ibb_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_bytestream_ibb_class); GParamSpec *param_spec; g_type_class_add_private (gabble_bytestream_ibb_class, sizeof (GabbleBytestreamIBBPrivate)); object_class->dispose = gabble_bytestream_ibb_dispose; object_class->finalize = gabble_bytestream_ibb_finalize; object_class->get_property = gabble_bytestream_ibb_get_property; object_class->set_property = gabble_bytestream_ibb_set_property; object_class->constructor = gabble_bytestream_ibb_constructor; g_object_class_override_property (object_class, PROP_CONNECTION, "connection"); g_object_class_override_property (object_class, PROP_PEER_HANDLE, "peer-handle"); g_object_class_override_property (object_class, PROP_PEER_HANDLE_TYPE, "peer-handle-type"); g_object_class_override_property (object_class, PROP_STREAM_ID, "stream-id"); g_object_class_override_property (object_class, PROP_PEER_JID, "peer-jid"); g_object_class_override_property (object_class, PROP_STATE, "state"); g_object_class_override_property (object_class, PROP_PROTOCOL, "protocol"); param_spec = g_param_spec_string ( "peer-resource", "Peer resource", "the resource used by the remote peer during the SI, if any", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_PEER_RESOURCE, param_spec); param_spec = g_param_spec_string ( "stream-init-id", "stream init ID", "the iq ID of the SI request, if any", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_STREAM_INIT_ID, param_spec); param_spec = g_param_spec_uint ( "block-size", "block size", "Maximum data sent using one stanza as described in XEP-0047", 0, G_MAXUINT32, 4096, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_BLOCK_SIZE, param_spec); } static void change_write_blocked_state (GabbleBytestreamIBB *self, gboolean blocked) { GabbleBytestreamIBBPrivate *priv = GABBLE_BYTESTREAM_IBB_GET_PRIVATE (self); if (priv->write_blocked == blocked) return; priv->write_blocked = blocked; g_signal_emit_by_name (self, "write-blocked", blocked); } static void send_close_stanza (GabbleBytestreamIBB *self) { GabbleBytestreamIBBPrivate *priv = GABBLE_BYTESTREAM_IBB_GET_PRIVATE (self); WockyStanza *msg; if (priv->close_iq_to_ack != NULL) { /* We received a close IQ and just need to ACK it */ _gabble_connection_acknowledge_set_iq (priv->conn, priv->close_iq_to_ack); g_object_unref (priv->close_iq_to_ack); priv->close_iq_to_ack = NULL; } DEBUG ("send IBB close stanza"); msg = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, priv->peer_jid, '(', "close", ':', NS_IBB, '@', "sid", priv->stream_id, ')', NULL); /* We don't really care about the answer as the bytestream * is closed anyway. */ _gabble_connection_send_with_reply (priv->conn, msg, NULL, NULL, NULL, NULL); g_object_unref (msg); } static guint send_data (GabbleBytestreamIBB *self, const gchar *str, guint len); static void iq_reply_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { TpWeakRef *weak_ref = user_data; GabbleBytestreamIBB *self = tp_weak_ref_dup_object (weak_ref); /* We don't hold a ref to the outgoing stanza; we just use its address as a * key */ gpointer sent_msg = tp_weak_ref_get_user_data (weak_ref); GabbleBytestreamIBBPrivate *priv; GError *error = NULL; tp_weak_ref_destroy (weak_ref); /* If the channel is already dead, never mind! */ if (self == NULL) return; priv = GABBLE_BYTESTREAM_IBB_GET_PRIVATE (self); g_hash_table_remove (priv->sent_stanzas_not_acked, sent_msg); if (!conn_util_send_iq_finish (GABBLE_CONNECTION (source), result, NULL, &error)) { DEBUG ("error sending IBB stanza: %s #%u '%s'. Closing the bytestream", g_quark_to_string (error->domain), error->code, error->message); g_clear_error (&error); /* FIXME: we should be able to feed this up to the application somehow. */ gabble_bytestream_iface_close (GABBLE_BYTESTREAM_IFACE (self), NULL); } else if (priv->write_buffer != NULL) { guint sent; DEBUG ("A stanza has been acked. Try to flush the buffer"); sent = send_data (self, priv->write_buffer->str, priv->write_buffer->len); if (sent == priv->write_buffer->len) { DEBUG ("buffer has been flushed; unblock write the bytestream"); g_string_free (priv->write_buffer, TRUE); priv->write_buffer = NULL; change_write_blocked_state (self, FALSE); if (priv->state == GABBLE_BYTESTREAM_STATE_CLOSING) { DEBUG ("Can close the bystream now the buffer is flushed"); send_close_stanza (self); g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_CLOSED, NULL); } } else { g_string_erase (priv->write_buffer, 0, sent); DEBUG ("buffer has not been completely flushed; %" G_GSIZE_FORMAT " bytes left", priv->write_buffer->len); } } g_object_unref (self); } static guint send_data (GabbleBytestreamIBB *self, const gchar *str, guint len) { GabbleBytestreamIBBPrivate *priv = GABBLE_BYTESTREAM_IBB_GET_PRIVATE (self); guint sent, stanza_count; sent = 0; stanza_count = 0; while (sent < len) { WockyStanza *iq; guint send_now, remaining; gchar *seq, *encoded; guint nb_stanzas_waiting; remaining = (len - sent); nb_stanzas_waiting = g_hash_table_size (priv->sent_stanzas_not_acked); if (nb_stanzas_waiting >= WINDOW_SIZE) { DEBUG ("Window is full (%u). Stop sending stanzas", nb_stanzas_waiting); break; } /* We can send stanzas */ if (remaining > priv->block_size) { /* We can't send all the remaining data in one stanza */ send_now = priv->block_size; } else { /* Send all the remaining data */ send_now = remaining; } encoded = g_base64_encode ((const guchar *) str + sent, send_now); seq = g_strdup_printf ("%u", priv->seq++); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, priv->peer_jid, '(', "data", '$', encoded, ':', NS_IBB, '@', "sid", priv->stream_id, '@', "seq", seq, ')', NULL); conn_util_send_iq_async (priv->conn, iq, NULL, iq_reply_cb, tp_weak_ref_new (self, iq, NULL)); g_free (encoded); g_free (seq); g_object_unref (iq); g_hash_table_insert (priv->sent_stanzas_not_acked, iq, GUINT_TO_POINTER (TRUE)); DEBUG ("send %d bytes (window size: %u)", send_now, nb_stanzas_waiting + 1); sent += send_now; stanza_count++; } DEBUG ("sent %d bytes (%d stanzas needed)", sent, stanza_count); return sent; } /* * gabble_bytestream_ibb_send * * Implements gabble_bytestream_iface_send on GabbleBytestreamIface */ static gboolean gabble_bytestream_ibb_send (GabbleBytestreamIface *iface, guint len, const gchar *str) { GabbleBytestreamIBB *self = GABBLE_BYTESTREAM_IBB (iface); GabbleBytestreamIBBPrivate *priv = GABBLE_BYTESTREAM_IBB_GET_PRIVATE (self); guint sent; if (priv->state != GABBLE_BYTESTREAM_STATE_OPEN) { DEBUG ("can't send data through a not open bytestream (state: %d)", priv->state); return FALSE; } if (priv->write_blocked) { DEBUG ("sending data while the bytestream was blocked"); } if (priv->write_buffer != NULL) { DEBUG ("Write buffer is not empty. Buffering data"); g_string_append_len (priv->write_buffer, str, len); return TRUE; } sent = send_data (self, str, len); if (sent < len) { guint remaining; DEBUG ("Some data have not been sent. Buffer them and write " "block the bytestream"); remaining = (len - sent); if (priv->write_buffer == NULL) { priv->write_buffer = g_string_new_len (str + sent, remaining); } else { g_string_append_len (priv->write_buffer, str + sent, remaining); } DEBUG ("write buffer size: %" G_GSIZE_FORMAT, priv->write_buffer->len); change_write_blocked_state (self, TRUE); } return TRUE; } void gabble_bytestream_ibb_receive (GabbleBytestreamIBB *self, WockyStanza *msg, gboolean is_iq) { GabbleBytestreamIBBPrivate *priv = GABBLE_BYTESTREAM_IBB_GET_PRIVATE (self); WockyNode *data; GString *str; guchar *st; gsize outlen; TpHandle sender; /* caller must have checked for this in order to know which bytestream to * route this packet to */ data = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "data", NS_IBB); g_assert (data != NULL); if (priv->state != GABBLE_BYTESTREAM_STATE_OPEN) { DEBUG ("can't receive data through a not open bytestream (state: %d)", priv->state); if (is_iq) wocky_porter_send_iq_error ( wocky_session_get_porter (priv->conn->session), msg, WOCKY_XMPP_ERROR_BAD_REQUEST, "IBB bytestream isn't open"); return; } /* Private stream using SI - the bytestream factory has already checked * the sender in order to dispatch to us */ sender = priv->peer_handle; /* FIXME: check sequence number */ st = g_base64_decode (data->content, &outlen); str = g_string_new_len ((gchar *) st, outlen); g_free (st); if (str == NULL) { DEBUG ("base64 decoding failed"); if (is_iq) wocky_porter_send_iq_error ( wocky_session_get_porter (priv->conn->session), msg, WOCKY_XMPP_ERROR_BAD_REQUEST, "base64 decoding failed"); return; } if (priv->read_blocked) { gsize current_buffer_len = 0; DEBUG ("Bytestream is blocked. Buffering data"); if (priv->read_buffer != NULL) current_buffer_len = priv->read_buffer->len; if (current_buffer_len + str->len > READ_BUFFER_MAX_SIZE) { DEBUG ("Buffer is full. Closing the bytestream"); if (is_iq) wocky_porter_send_iq_error ( wocky_session_get_porter (priv->conn->session), msg, WOCKY_XMPP_ERROR_NOT_ACCEPTABLE, "buffer is full"); gabble_bytestream_iface_close (GABBLE_BYTESTREAM_IFACE (self), NULL); g_string_free (str, TRUE); return; } if (priv->read_buffer == NULL) { priv->read_buffer = str; } else { g_string_append_len (priv->read_buffer, str->str, str->len); g_string_free (str, TRUE); } if (is_iq) { priv->received_stanzas_not_acked = g_slist_prepend ( priv->received_stanzas_not_acked, g_object_ref (msg)); } return; } g_signal_emit_by_name (G_OBJECT (self), "data-received", sender, str); g_string_free (str, TRUE); if (is_iq) _gabble_connection_acknowledge_set_iq (priv->conn, msg); return; } /* * gabble_bytestream_ibb_accept * * Implements gabble_bytestream_iface_accept on GabbleBytestreamIface */ static void gabble_bytestream_ibb_accept (GabbleBytestreamIface *iface, GabbleBytestreamAugmentSiAcceptReply func, gpointer user_data) { GabbleBytestreamIBB *self = GABBLE_BYTESTREAM_IBB (iface); GabbleBytestreamIBBPrivate *priv = GABBLE_BYTESTREAM_IBB_GET_PRIVATE (self); WockyStanza *msg; WockyNode *si; if (priv->state != GABBLE_BYTESTREAM_STATE_LOCAL_PENDING) { /* The stream was previoulsy or automatically accepted */ return; } msg = gabble_bytestream_factory_make_accept_iq (priv->peer_jid, priv->stream_init_id, NS_IBB); si = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "si", NS_SI); g_assert (si != NULL); if (func != NULL) { /* let the caller add his profile specific data */ func (si, user_data); } if (_gabble_connection_send (priv->conn, msg, NULL)) { DEBUG ("stream %s with %s is now accepted", priv->stream_id, priv->peer_jid); g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_ACCEPTED, NULL); } g_object_unref (msg); } static void gabble_bytestream_ibb_decline (GabbleBytestreamIBB *self, GError *error) { GabbleBytestreamIBBPrivate *priv = GABBLE_BYTESTREAM_IBB_GET_PRIVATE (self); WockyStanza *msg; g_return_if_fail (priv->state == GABBLE_BYTESTREAM_STATE_LOCAL_PENDING); msg = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, NULL, priv->peer_jid, '@', "id", priv->stream_init_id, NULL); if (error != NULL) { wocky_stanza_error_to_node (error, wocky_stanza_get_top_node (msg)); } else { GError fallback = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_FORBIDDEN, "Offer Declined" }; wocky_stanza_error_to_node (&fallback, wocky_stanza_get_top_node (msg)); } _gabble_connection_send (priv->conn, msg, NULL); g_object_unref (msg); g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_CLOSED, NULL); } /* * gabble_bytestream_ibb_close * * Implements gabble_bytestream_iface_close on GabbleBytestreamIface */ static void gabble_bytestream_ibb_close (GabbleBytestreamIface *iface, GError *error) { GabbleBytestreamIBB *self = GABBLE_BYTESTREAM_IBB (iface); GabbleBytestreamIBBPrivate *priv = GABBLE_BYTESTREAM_IBB_GET_PRIVATE (self); WockyPorter *porter = wocky_session_get_porter (priv->conn->session); GSList *l; if (priv->state == GABBLE_BYTESTREAM_STATE_CLOSED) /* bytestream already closed, do nothing */ return; /* Send error for pending IQ's */ priv->received_stanzas_not_acked = g_slist_reverse ( priv->received_stanzas_not_acked); for (l = priv->received_stanzas_not_acked; l != NULL; l = g_slist_next (l)) wocky_porter_send_iq_error (porter, l->data, WOCKY_XMPP_ERROR_ITEM_NOT_FOUND, NULL); g_slist_free (priv->received_stanzas_not_acked); priv->received_stanzas_not_acked = NULL; if (priv->state == GABBLE_BYTESTREAM_STATE_LOCAL_PENDING) { /* Stream was created using SI so we decline the request */ gabble_bytestream_ibb_decline (self, error); } else { if (priv->write_buffer != NULL) { DEBUG ("write buffer is not empty. Wait before sending close stanza"); g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_CLOSING, NULL); } else { send_close_stanza (self); g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_CLOSED, NULL); } } } static void ibb_init_reply_cb (GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg, GObject *obj, gpointer user_data) { GabbleBytestreamIBB *self = GABBLE_BYTESTREAM_IBB (obj); GError *error = NULL; if (!wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL)) { /* yeah, stream initiated */ DEBUG ("IBB stream initiated"); g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_OPEN, NULL); } else { DEBUG ("error during IBB initiation: %s", error->message); g_clear_error (&error); g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_CLOSED, NULL); } } /* * gabble_bytestream_ibb_initiate * * Implements gabble_bytestream_iface_initiate on GabbleBytestreamIface */ static gboolean gabble_bytestream_ibb_initiate (GabbleBytestreamIface *iface) { GabbleBytestreamIBB *self = GABBLE_BYTESTREAM_IBB (iface); GabbleBytestreamIBBPrivate *priv = GABBLE_BYTESTREAM_IBB_GET_PRIVATE (self); WockyStanza *msg; gchar *block_size; if (priv->state != GABBLE_BYTESTREAM_STATE_INITIATING) { DEBUG ("bytestream is not is the initiating state (state %d", priv->state); return FALSE; } block_size = g_strdup_printf ("%u", priv->block_size); msg = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, priv->peer_jid, '(', "open", ':', NS_IBB, '@', "sid", priv->stream_id, '@', "block-size", block_size, ')', NULL); g_free (block_size); if (!_gabble_connection_send_with_reply (priv->conn, msg, ibb_init_reply_cb, G_OBJECT (self), NULL, NULL)) { DEBUG ("Error when sending IBB init stanza"); g_object_unref (msg); return FALSE; } g_object_unref (msg); return TRUE; } static void gabble_bytestream_ibb_block_reading (GabbleBytestreamIface *iface, gboolean block) { GabbleBytestreamIBB *self = GABBLE_BYTESTREAM_IBB (iface); GabbleBytestreamIBBPrivate *priv = GABBLE_BYTESTREAM_IBB_GET_PRIVATE (self); if (priv->read_blocked == block) return; priv->read_blocked = block; DEBUG ("%s the transport bytestream", block ? "block": "unblock"); if (priv->read_buffer != NULL && !block) { GSList *l; DEBUG ("Bytestream unblocked, flushing the buffer"); g_signal_emit_by_name (G_OBJECT (self), "data-received", priv->peer_handle, priv->read_buffer); g_string_free (priv->read_buffer, TRUE); priv->read_buffer = NULL; /* ack pending stanzas */ priv->received_stanzas_not_acked = g_slist_reverse ( priv->received_stanzas_not_acked); for (l = priv->received_stanzas_not_acked; l != NULL; l = g_slist_next (l)) { WockyStanza *iq = (WockyStanza *) l->data; _gabble_connection_acknowledge_set_iq (priv->conn, iq); g_object_unref (iq); } g_slist_free (priv->received_stanzas_not_acked); priv->received_stanzas_not_acked = NULL; } } void gabble_bytestream_ibb_close_received (GabbleBytestreamIBB *self, WockyStanza *iq) { GabbleBytestreamIBBPrivate *priv = GABBLE_BYTESTREAM_IBB_GET_PRIVATE (self); DEBUG ("received IBB close stanza. Closing bytestream"); priv->close_iq_to_ack = g_object_ref (iq); gabble_bytestream_ibb_close (GABBLE_BYTESTREAM_IFACE (self), NULL); } static void bytestream_iface_init (gpointer g_iface, gpointer iface_data) { GabbleBytestreamIfaceClass *klass = (GabbleBytestreamIfaceClass *) g_iface; klass->initiate = gabble_bytestream_ibb_initiate; klass->send = gabble_bytestream_ibb_send; klass->close = gabble_bytestream_ibb_close; klass->accept = gabble_bytestream_ibb_accept; klass->block_reading = gabble_bytestream_ibb_block_reading; } ����������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/base-call-channel.c�����������������������������������������������������0000664�0001750�0001750�00000022610�12223562023�022360� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * base-call-channel.c - Source for GabbleBaseCallChannel * Copyright © 2009–2010 Collabora Ltd. * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include <stdio.h> #include <stdlib.h> #include <gio/gio.h> #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #include "util.h" #include "call-content.h" #include "base-call-channel.h" #include "connection.h" #include "jingle-tp-util.h" #define DEBUG_FLAG GABBLE_DEBUG_MEDIA #include "debug.h" G_DEFINE_TYPE(GabbleBaseCallChannel, gabble_base_call_channel, TP_TYPE_BASE_MEDIA_CALL_CHANNEL); static void gabble_base_call_channel_hangup ( TpBaseCallChannel *base, guint reason, const gchar *detailed_reason, const gchar *message); static void gabble_base_call_channel_close (TpBaseChannel *base); /* properties */ enum { PROP_OBJECT_PATH_PREFIX = 1, LAST_PROPERTY }; /* private structure */ struct _GabbleBaseCallChannelPrivate { gchar *object_path_prefix; gboolean dispose_has_run; /* handle -> CallMember object hash */ GHashTable *members; }; static void gabble_base_call_channel_init (GabbleBaseCallChannel *self) { GabbleBaseCallChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_BASE_CALL_CHANNEL, GabbleBaseCallChannelPrivate); self->priv = priv; priv->members = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); } static void gabble_base_call_channel_dispose (GObject *object); static void gabble_base_call_channel_finalize (GObject *object); static void gabble_base_call_channel_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleBaseCallChannel *self = GABBLE_BASE_CALL_CHANNEL (object); GabbleBaseCallChannelPrivate *priv = self->priv; switch (property_id) { case PROP_OBJECT_PATH_PREFIX: g_value_set_string (value, priv->object_path_prefix); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_base_call_channel_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleBaseCallChannel *self = GABBLE_BASE_CALL_CHANNEL (object); GabbleBaseCallChannelPrivate *priv = self->priv; switch (property_id) { case PROP_OBJECT_PATH_PREFIX: priv->object_path_prefix = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static gchar * gabble_base_call_channel_get_object_path_suffix (TpBaseChannel *base) { GabbleBaseCallChannel *self = GABBLE_BASE_CALL_CHANNEL (base); GabbleBaseCallChannelPrivate *priv = self->priv; g_assert (priv->object_path_prefix != NULL); return g_strdup_printf ("%s/CallChannel%p", priv->object_path_prefix, self); } static void gabble_base_call_channel_class_init ( GabbleBaseCallChannelClass *gabble_base_call_channel_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_base_call_channel_class); TpBaseChannelClass *base_channel_class = TP_BASE_CHANNEL_CLASS (gabble_base_call_channel_class); TpBaseCallChannelClass *tp_base_call_channel_class = TP_BASE_CALL_CHANNEL_CLASS (gabble_base_call_channel_class); GParamSpec *param_spec; g_type_class_add_private (gabble_base_call_channel_class, sizeof (GabbleBaseCallChannelPrivate)); object_class->get_property = gabble_base_call_channel_get_property; object_class->set_property = gabble_base_call_channel_set_property; object_class->dispose = gabble_base_call_channel_dispose; object_class->finalize = gabble_base_call_channel_finalize; base_channel_class->get_object_path_suffix = gabble_base_call_channel_get_object_path_suffix; base_channel_class->close = gabble_base_call_channel_close; tp_base_call_channel_class->hangup = gabble_base_call_channel_hangup; param_spec = g_param_spec_string ("object-path-prefix", "Object path prefix", "prefix of the object path", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_OBJECT_PATH_PREFIX, param_spec); } void gabble_base_call_channel_dispose (GObject *object) { GabbleBaseCallChannel *self = GABBLE_BASE_CALL_CHANNEL (object); GabbleBaseCallChannelPrivate *priv = self->priv; DEBUG ("hello thar"); if (priv->dispose_has_run) return; self->priv->dispose_has_run = TRUE; tp_clear_pointer (&priv->members, g_hash_table_unref); if (G_OBJECT_CLASS (gabble_base_call_channel_parent_class)->dispose) G_OBJECT_CLASS (gabble_base_call_channel_parent_class)->dispose (object); } void gabble_base_call_channel_finalize (GObject *object) { GabbleBaseCallChannel *self = GABBLE_BASE_CALL_CHANNEL (object); GabbleBaseCallChannelPrivate *priv = self->priv; g_free (priv->object_path_prefix); G_OBJECT_CLASS (gabble_base_call_channel_parent_class)->finalize (object); } GabbleCallContent * gabble_base_call_channel_add_content (GabbleBaseCallChannel *self, const gchar *name, WockyJingleMediaType mtype, TpCallContentDisposition disposition) { TpBaseChannel *base = TP_BASE_CHANNEL (self); gchar *object_path; TpBaseCallContent *content; gchar *escaped; /* FIXME could clash when other party in a one-to-one call creates a stream * with the same media type and name */ escaped = tp_escape_as_identifier (name); object_path = g_strdup_printf ("%s/Content_%s_%d", tp_base_channel_get_object_path (base), escaped, mtype); g_free (escaped); content = g_object_new (GABBLE_TYPE_CALL_CONTENT, "connection", tp_base_channel_get_connection (base), "object-path", object_path, "disposition", disposition, "media-type", wocky_jingle_media_type_to_tp (mtype), "name", name, NULL); g_free (object_path); tp_base_call_channel_add_content (TP_BASE_CALL_CHANNEL (self), content); return GABBLE_CALL_CONTENT (content); } static void call_member_flags_changed_cb (GabbleCallMember *member, TpCallMemberFlags flags, gpointer user_data) { TpBaseCallChannel *base = TP_BASE_CALL_CHANNEL (user_data); tp_base_call_channel_update_member_flags (base, gabble_call_member_get_handle (member), flags, 0, TP_CALL_STATE_CHANGE_REASON_PROGRESS_MADE, "", ""); } GabbleCallMember * gabble_base_call_channel_get_member_from_handle ( GabbleBaseCallChannel *self, TpHandle handle) { return g_hash_table_lookup (self->priv->members, GUINT_TO_POINTER (handle)); } GabbleCallMember * gabble_base_call_channel_ensure_member_from_handle ( GabbleBaseCallChannel *self, TpHandle handle) { GabbleBaseCallChannelPrivate *priv = self->priv; GabbleCallMember *m; m = g_hash_table_lookup (priv->members, GUINT_TO_POINTER (handle)); if (m == NULL) { m = GABBLE_CALL_MEMBER (g_object_new (GABBLE_TYPE_CALL_MEMBER, "target", handle, "call", self, NULL)); g_hash_table_insert (priv->members, GUINT_TO_POINTER (handle), m); tp_base_call_channel_update_member_flags (TP_BASE_CALL_CHANNEL (self), gabble_call_member_get_handle (m), gabble_call_member_get_flags (m), 0, TP_CALL_STATE_CHANGE_REASON_PROGRESS_MADE, "", ""); gabble_signal_connect_weak (m, "flags-changed", G_CALLBACK (call_member_flags_changed_cb), G_OBJECT (self)); } return m; } void gabble_base_call_channel_remove_member (GabbleBaseCallChannel *self, GabbleCallMember *member) { TpHandle h = gabble_call_member_get_handle (member); g_assert (g_hash_table_lookup (self->priv->members, GUINT_TO_POINTER (h))== member); gabble_call_member_shutdown (member); tp_base_call_channel_remove_member (TP_BASE_CALL_CHANNEL (self), gabble_call_member_get_handle (member), 0, TP_CALL_STATE_CHANGE_REASON_PROGRESS_MADE, "", ""); g_hash_table_remove (self->priv->members, GUINT_TO_POINTER (h)); } static void gabble_base_call_channel_shutdown_all_members (GabbleBaseCallChannel *self) { GHashTableIter iter; gpointer value; g_hash_table_iter_init (&iter, self->priv->members); while (g_hash_table_iter_next (&iter, NULL, &value)) gabble_call_member_shutdown (GABBLE_CALL_MEMBER (value)); } static void gabble_base_call_channel_hangup (TpBaseCallChannel *base, guint reason, const gchar *detailed_reason, const gchar *message) { gabble_base_call_channel_shutdown_all_members ( GABBLE_BASE_CALL_CHANNEL (base)); } static void gabble_base_call_channel_close (TpBaseChannel *base) { gabble_base_call_channel_shutdown_all_members ( GABBLE_BASE_CALL_CHANNEL (base)); TP_BASE_CHANNEL_CLASS (gabble_base_call_channel_parent_class)->close (base); } ������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/call-muc-channel.h������������������������������������������������������0000664�0001750�0001750�00000005423�12223562023�022242� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * call-muc-channel.h - Header for GabbleCallMucChannel * Copyright (C) 2010 Collabora Ltd. * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_CALL_MUC_CHANNEL_H__ #define __GABBLE_CALL_MUC_CHANNEL_H__ #include <glib-object.h> #include <wocky/wocky.h> #include "base-call-channel.h" G_BEGIN_DECLS typedef struct _GabbleCallMucChannel GabbleCallMucChannel; typedef struct _GabbleCallMucChannelPrivate GabbleCallMucChannelPrivate; typedef struct _GabbleCallMucChannelClass GabbleCallMucChannelClass; struct _GabbleCallMucChannelClass { GabbleBaseCallChannelClass parent_class; }; struct _GabbleCallMucChannel { GabbleBaseCallChannel parent; GabbleCallMucChannelPrivate *priv; }; GType gabble_call_muc_channel_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_CALL_MUC_CHANNEL \ (gabble_call_muc_channel_get_type ()) #define GABBLE_CALL_MUC_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_CALL_MUC_CHANNEL, \ GabbleCallMucChannel)) #define GABBLE_CALL_MUC_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_CALL_MUC_CHANNEL, \ GabbleCallMucChannelClass)) #define GABBLE_IS_CALL_MUC_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_CALL_MUC_CHANNEL)) #define GABBLE_IS_CALL_MUC_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_CALL_MUC_CHANNEL)) #define GABBLE_CALL_MUC_CHANNEL_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_CALL_MUC_CHANNEL, \ GabbleCallMucChannelClass)) void gabble_call_muc_channel_new_async (GabbleConnection *connection, GCancellable *cancellable, const gchar *path_prefix, GabbleMucChannel *muc, TpHandle target, GHashTable *request, GAsyncReadyCallback callback, gpointer user_data); GabbleCallMucChannel * gabble_call_muc_channel_new_finish (GObject *source, GAsyncResult *result, GError **error); void gabble_call_muc_channel_incoming_session (GabbleCallMucChannel *self, WockyJingleSession *session); G_END_DECLS #endif /* #ifndef __GABBLE_CALL_MUC_CHANNEL_H__*/ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/private-tubes-factory.h�������������������������������������������������0000664�0001750�0001750�00000006317�12332441362�023404� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * private-tubes-factory.h - Header for GabblePrivateTubesFactory * Copyright (C) 2007 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __PRIVATE_TUBES_FACTORY_H__ #define __PRIVATE_TUBES_FACTORY_H__ #include <glib-object.h> #include <telepathy-glib/telepathy-glib.h> #include "connection.h" #include "bytestream-iface.h" G_BEGIN_DECLS typedef struct _GabblePrivateTubesFactoryClass GabblePrivateTubesFactoryClass; typedef struct _GabblePrivateTubesFactoryPrivate GabblePrivateTubesFactoryPrivate; struct _GabblePrivateTubesFactoryClass { GObjectClass parent_class; }; struct _GabblePrivateTubesFactory { GObject parent; GabblePrivateTubesFactoryPrivate *priv; }; GType gabble_private_tubes_factory_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_PRIVATE_TUBES_FACTORY \ (gabble_private_tubes_factory_get_type ()) #define GABBLE_PRIVATE_TUBES_FACTORY(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_PRIVATE_TUBES_FACTORY,\ GabblePrivateTubesFactory)) #define GABBLE_PRIVATE_TUBES_FACTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_PRIVATE_TUBES_FACTORY,\ GabblePrivateTubesFactoryClass)) #define GABBLE_IS_PRIVATE_TUBES_FACTORY(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_PRIVATE_TUBES_FACTORY)) #define GABBLE_IS_PRIVATE_TUBES_FACTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_PRIVATE_TUBES_FACTORY)) #define GABBLE_PRIVATE_TUBES_FACTORY_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_PRIVATE_TUBES_FACTORY,\ GabblePrivateTubesFactoryClass)) GabblePrivateTubesFactory * gabble_private_tubes_factory_new ( GabbleConnection *conn); /* New 1-1 D-Bus tube requested by the remote contact */ void gabble_private_tubes_factory_handle_si_tube_request ( GabblePrivateTubesFactory *fac, GabbleBytestreamIface *bytestream, TpHandle handle, const gchar *stream_id, WockyStanza *msg); /* New connection requested in a existing 1-1 stream tube */ void gabble_private_tubes_factory_handle_si_stream_request ( GabblePrivateTubesFactory *fac, GabbleBytestreamIface *bytestream, TpHandle handle, const gchar *stream_id, WockyStanza *msg); gboolean gabble_private_tubes_factory_extract_tube_information ( TpHandleRepoIface *contact_repo, WockyNode *tube_node, TpTubeType *type, TpHandle *initiator_handle, const gchar **service, GHashTable **parameters, guint64 *tube_id); G_END_DECLS #endif /* #ifndef __PRIVATE_TUBES_FACTORY_H__ */ �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/conn-aliasing.c���������������������������������������������������������0000664�0001750�0001750�00000107154�12332441362�021663� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * conn-aliasing.c - Gabble connection aliasing interface * Copyright (C) 2005-2010 Collabora Ltd. * Copyright (C) 2005-2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "conn-aliasing.h" #include <wocky/wocky.h> #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #define DEBUG_FLAG GABBLE_DEBUG_CONNECTION #include "connection.h" #include "debug.h" #include "namespaces.h" #include "presence-cache.h" #include "request-pipeline.h" #include "roster.h" #include "util.h" #include "vcard-manager.h" static void gabble_conn_aliasing_pep_nick_reply_handler ( GabbleConnection *conn, WockyStanza *msg, TpHandle handle); static GQuark gabble_conn_aliasing_pep_alias_quark (void); static GabbleConnectionAliasSource _gabble_connection_get_cached_remote_alias ( GabbleConnection *, TpHandle, gchar **); static void maybe_request_vcard (GabbleConnection *self, TpHandle handle, GabbleConnectionAliasSource source); /* distinct from any strdup()d pointer - used for negative caching */ static const gchar *NO_ALIAS = ""; /** * gabble_connection_get_alias_flags * * Implements D-Bus method GetAliasFlags * on interface org.freedesktop.Telepathy.Connection.Interface.Aliasing * * @error: Used to return a pointer to a GError detailing any error * that occurred, D-Bus will throw the error only if this * function returns FALSE. * * Returns: TRUE if successful, FALSE if an error was thrown. */ static void gabble_connection_get_alias_flags (TpSvcConnectionInterfaceAliasing *iface, DBusGMethodInvocation *context) { TpBaseConnection *base = TP_BASE_CONNECTION (iface); g_assert (GABBLE_IS_CONNECTION (base)); TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); tp_svc_connection_interface_aliasing_return_from_get_alias_flags ( context, TP_CONNECTION_ALIAS_FLAG_USER_SET); } typedef struct _AliasesRequest AliasesRequest; struct _AliasesRequest { GabbleConnection *conn; DBusGMethodInvocation *request_call; guint pending_vcard_requests; guint pending_pep_requests; GArray *contacts; GabbleVCardManagerRequest **vcard_requests; GabbleRequestPipelineItem **pep_requests; gchar **aliases; }; typedef struct { AliasesRequest *aliases_request; guint index; } AliasRequest; static AliasesRequest * aliases_request_new (GabbleConnection *conn, DBusGMethodInvocation *request_call, const GArray *contacts) { AliasesRequest *request; request = g_slice_new0 (AliasesRequest); request->conn = conn; request->request_call = request_call; request->contacts = g_array_new (FALSE, FALSE, sizeof (TpHandle)); g_array_insert_vals (request->contacts, 0, contacts->data, contacts->len); request->vcard_requests = g_new0 (GabbleVCardManagerRequest *, contacts->len); request->pep_requests = g_new0 (GabbleRequestPipelineItem *, contacts->len); request->aliases = g_new0 (gchar *, contacts->len + 1); return request; } static void aliases_request_free (AliasesRequest *request) { guint i; for (i = 0; i < request->contacts->len; i++) { /* FIXME: what if vcard_manager is NULL? */ if (request->vcard_requests[i] != NULL) gabble_vcard_manager_cancel_request (request->conn->vcard_manager, request->vcard_requests[i]); } g_array_unref (request->contacts); g_free (request->vcard_requests); g_free (request->pep_requests); g_strfreev (request->aliases); g_slice_free (AliasesRequest, request); } static gboolean aliases_request_try_return (AliasesRequest *request) { if (request->pending_vcard_requests == 0 && request->pending_pep_requests == 0) { /* Cast to (const gchar **) necessary because no-one understands 'const' * in C. */ tp_svc_connection_interface_aliasing_return_from_request_aliases ( request->request_call, (const gchar **)request->aliases); return TRUE; } return FALSE; } static void aliases_request_vcard_cb (GabbleVCardManager *manager, GabbleVCardManagerRequest *request, TpHandle handle, WockyNode *vcard, GError *error, gpointer user_data) { AliasesRequest *aliases_request = (AliasesRequest *) user_data; GabbleConnectionAliasSource source; guint i; gboolean found = FALSE; gchar *alias = NULL; g_assert (aliases_request->pending_vcard_requests > 0); /* The index of the vCard request in the vCard request array is the * index of the contact/alias in their respective arrays. */ for (i = 0; i < aliases_request->contacts->len; i++) if (aliases_request->vcard_requests[i] == request) { found = TRUE; break; } g_assert (found); source = _gabble_connection_get_cached_alias (aliases_request->conn, g_array_index (aliases_request->contacts, TpHandle, i), &alias); g_assert (source != GABBLE_CONNECTION_ALIAS_NONE); g_assert (NULL != alias); aliases_request->pending_vcard_requests--; aliases_request->vcard_requests[i] = NULL; aliases_request->aliases[i] = alias; if (aliases_request_try_return (aliases_request)) aliases_request_free (aliases_request); } static void _cache_negatively (GabbleConnection *self, TpHandle handle) { TpBaseConnection *base = (TpBaseConnection *) self; TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); tp_handle_set_qdata (contact_handles, handle, gabble_conn_aliasing_pep_alias_quark (), (gchar *) NO_ALIAS, NULL); } /* Cache pep if successful */ static void aliases_request_cache_pep (GabbleConnection *self, WockyStanza *msg, TpHandle handle, GError *error) { if (error != NULL) { DEBUG ("Error getting alias from PEP: %s", error->message); _cache_negatively (self, handle); return; } else if (wocky_stanza_extract_errors (msg, NULL, NULL, NULL, NULL)) { STANZA_DEBUG (msg, "Error getting alias from PEP"); _cache_negatively (self, handle); } else { /* Try to extract an alias, caching it if necessary. */ gabble_conn_aliasing_pep_nick_reply_handler (self, msg, handle); } } static void aliases_request_basic_pep_cb (GabbleConnection *self, WockyStanza *msg, gpointer user_data, GError *error) { TpBaseConnection *base = (TpBaseConnection *) self; GabbleConnectionAliasSource source = GABBLE_CONNECTION_ALIAS_NONE; TpHandle handle = GPOINTER_TO_UINT (user_data); aliases_request_cache_pep (self, msg, handle, error); source = _gabble_connection_get_cached_alias (self, handle, NULL); if (source < GABBLE_CONNECTION_ALIAS_FROM_VCARD && tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_CONNECTED && !gabble_vcard_manager_has_cached_alias (self->vcard_manager, handle)) { /* no alias in PEP, get the vcard */ gabble_vcard_manager_request (self->vcard_manager, handle, 0, NULL, NULL, G_OBJECT (self)); } } static void aliases_request_pep_cb (GabbleConnection *self, WockyStanza *msg, gpointer user_data, GError *error) { TpBaseConnection *base = (TpBaseConnection *) self; AliasRequest *alias_request = (AliasRequest *) user_data; AliasesRequest *aliases_request = alias_request->aliases_request; guint index = alias_request->index; TpHandle handle = g_array_index (aliases_request->contacts, TpHandle, index); GabbleConnectionAliasSource source = GABBLE_CONNECTION_ALIAS_NONE; gchar *alias = NULL; aliases_request->pending_pep_requests--; aliases_request->pep_requests[index] = NULL; g_slice_free (AliasRequest, alias_request); aliases_request_cache_pep (self, msg, handle, error); source = _gabble_connection_get_cached_alias (aliases_request->conn, handle, &alias); g_assert (source != GABBLE_CONNECTION_ALIAS_NONE); g_assert (NULL != alias); DEBUG ("Got cached alias %s with priority %u", alias, source); if (source >= GABBLE_CONNECTION_ALIAS_FROM_VCARD || (self->vcard_manager != NULL && gabble_vcard_manager_has_cached_alias (self->vcard_manager, handle))) { aliases_request->aliases[index] = alias; } else if (tp_base_connection_get_status (base) != TP_CONNECTION_STATUS_CONNECTED) { DEBUG ("no longer connected, not chaining up to vCard"); g_free (alias); } else { /* not in PEP and we have no vCard - chain to looking up their vCard */ GabbleVCardManagerRequest *vcard_request = gabble_vcard_manager_request (self->vcard_manager, handle, 0, aliases_request_vcard_cb, aliases_request, G_OBJECT (self)); g_free (alias); aliases_request->vcard_requests[index] = vcard_request; aliases_request->pending_vcard_requests++; } if (aliases_request_try_return (aliases_request)) aliases_request_free (aliases_request); } typedef struct { GabbleRequestPipelineCb callback; gpointer user_data; TpHandleRepoIface *contact_handles; TpHandle handle; } pep_request_ctx; static void pep_request_cb ( GabbleConnection *conn, WockyStanza *msg, gpointer user_data, GError *error) { pep_request_ctx *ctx = user_data; ctx->callback (conn, msg, ctx->user_data, error); g_slice_free (pep_request_ctx, ctx); } /** * @self must have %TP_CONNECTION_STATUS_CONNECTED. */ static GabbleRequestPipelineItem * gabble_do_pep_request (GabbleConnection *self, TpHandle handle, TpHandleRepoIface *contact_handles, GabbleRequestPipelineCb callback, gpointer user_data) { TpBaseConnection *base = (TpBaseConnection *) self; const gchar *to; WockyStanza *msg; GabbleRequestPipelineItem *pep_request; pep_request_ctx *ctx; /* callers must check this... */ g_assert (tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_CONNECTED); /* ... which implies this */ g_assert (self->req_pipeline != NULL); ctx = g_slice_new0 (pep_request_ctx); ctx->callback = callback; ctx->user_data = user_data; ctx->contact_handles = contact_handles; ctx->handle = handle; to = tp_handle_inspect (contact_handles, handle); msg = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, to, '(', "pubsub", ':', NS_PUBSUB, '(', "items", '@', "node", NS_NICK, ')', ')', NULL); pep_request = gabble_request_pipeline_enqueue (self->req_pipeline, msg, 0, pep_request_cb, ctx); g_object_unref (msg); return pep_request; } /** * gabble_connection_request_aliases * * Implements D-Bus method RequestAliases * on interface org.freedesktop.Telepathy.Connection.Interface.Aliasing * * @context: The D-Bus invocation context to use to return values * or throw an error. */ static void gabble_connection_request_aliases (TpSvcConnectionInterfaceAliasing *iface, const GArray *contacts, DBusGMethodInvocation *context) { GabbleConnection *self = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) self; TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); guint i; AliasesRequest *request; GError *error = NULL; g_assert (GABBLE_IS_CONNECTION (self)); TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); if (!tp_handles_are_valid (contact_handles, contacts, FALSE, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); return; } request = aliases_request_new (self, context, contacts); for (i = 0; i < contacts->len; i++) { TpHandle handle = g_array_index (contacts, TpHandle, i); GabbleConnectionAliasSource source; GabbleVCardManagerRequest *vcard_request; gchar *alias; source = _gabble_connection_get_cached_alias (self, handle, &alias); g_assert (source != GABBLE_CONNECTION_ALIAS_NONE); g_assert (NULL != alias); if (source >= GABBLE_CONNECTION_ALIAS_FROM_VCARD || gabble_vcard_manager_has_cached_alias (self->vcard_manager, handle)) { /* Either the alias we got was from a vCard or better, or we already * tried getting an alias from a vcard and failed, so there's no * point trying again. */ request->aliases[i] = alias; } else if (self->features & GABBLE_CONNECTION_FEATURES_PEP) { /* FIXME: we shouldn't have to do this, since we should get PEP * events when someone first sends us presence. However, the * current ejabberd PEP implementation doesn't seem to give * us notifications of the initial state. */ AliasRequest *data = g_slice_new (AliasRequest); g_free (alias); data->aliases_request = request; data->index = i; request->pending_pep_requests++; request->pep_requests[i] = gabble_do_pep_request (self, handle, contact_handles, aliases_request_pep_cb, data); } else { DEBUG ("requesting vCard for alias of contact %s", tp_handle_inspect (contact_handles, handle)); g_free (alias); vcard_request = gabble_vcard_manager_request (self->vcard_manager, handle, 0, aliases_request_vcard_cb, request, G_OBJECT (self)); request->vcard_requests[i] = vcard_request; request->pending_vcard_requests++; } } if (aliases_request_try_return (request)) aliases_request_free (request); } static void nick_publish_msg_reply_cb (GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg, GObject *object, gpointer user_data) { #ifdef ENABLE_DEBUG GError *error = NULL; if (wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL)) { DEBUG ("can't publish nick using PEP: %s: %s", wocky_xmpp_stanza_error_to_string (error), error->message); g_clear_error (&error); } #endif } static gboolean set_one_alias ( GabbleConnection *conn, TpHandle handle, gchar *alias, GError **error) { TpBaseConnection *base = (TpBaseConnection *) conn; TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); gboolean ret = TRUE; g_assert (tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_CONNECTED); if (tp_str_empty (alias)) alias = NULL; if (!tp_handle_is_valid (contact_handles, handle, error)) { ret = FALSE; } else if (tp_base_connection_get_self_handle (base) == handle) { /* only alter the roster if we're already there, e.g. because someone * added us with another client */ if (gabble_roster_handle_has_entry (conn->roster, handle) && !gabble_roster_handle_set_name (conn->roster, handle, alias, error)) { ret = FALSE; } } else { gchar *remote_alias = NULL; GabbleConnectionAliasSource source = GABBLE_CONNECTION_ALIAS_FROM_ROSTER; if (alias == NULL) { source = _gabble_connection_get_cached_remote_alias (conn, handle, &remote_alias); alias = remote_alias; } ret = gabble_roster_handle_set_name (conn->roster, handle, alias, error); g_free (remote_alias); /* If we don't have a cached remote alias for this contact, try to ask * for one. (Maybe we haven't seen a PEP update or fetched their vCard in * this session?) */ maybe_request_vcard (conn, handle, source); } if (tp_base_connection_get_self_handle (base) == handle) { GabbleVCardManagerEditInfo *edit; GQueue edits = G_QUEUE_INIT; /* User has called SetAliases on themselves - patch their vCard. * FIXME: because SetAliases is currently synchronous, we ignore errors * here, and just let the request happen in the background. */ if (conn->features & GABBLE_CONNECTION_FEATURES_PEP) { /* Publish nick using PEP */ WockyStanza *msg; WockyNode *item; msg = wocky_pep_service_make_publish_stanza (conn->pep_nick, &item); /* Does the right thing if alias == NULL. */ wocky_node_add_child_with_content_ns (item, "nick", alias, NS_NICK); _gabble_connection_send_with_reply (conn, msg, nick_publish_msg_reply_cb, NULL, NULL, NULL); g_object_unref (msg); } if (alias == NULL) /* Deliberately not doing the fall-back-to-FN-on-GTalk dance because * clearing your FN is more serious. */ edit = gabble_vcard_manager_edit_info_new ("NICKNAME", NULL, GABBLE_VCARD_EDIT_DELETE, NULL); else edit = gabble_vcard_manager_edit_info_new (NULL, alias, GABBLE_VCARD_EDIT_SET_ALIAS, NULL); g_queue_push_head (&edits, edit); /* Yes, gabble_vcard_manager_edit steals the list you pass it. */ gabble_vcard_manager_edit (conn->vcard_manager, 0, NULL, NULL, G_OBJECT (conn), edits.head); } return ret; } /** * gabble_connection_set_aliases * * Implements D-Bus method SetAliases * on interface org.freedesktop.Telepathy.Connection.Interface.Aliasing */ static void gabble_connection_set_aliases (TpSvcConnectionInterfaceAliasing *iface, GHashTable *aliases, DBusGMethodInvocation *context) { GabbleConnection *self = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) self; GHashTableIter iter; gpointer key, value; gboolean retval = TRUE; GError *first_error = NULL; g_assert (GABBLE_IS_CONNECTION (self)); TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); g_hash_table_iter_init (&iter, aliases); while (g_hash_table_iter_next (&iter, &key, &value)) { if (!set_one_alias (self, GPOINTER_TO_UINT (key), value, (first_error == NULL ? &first_error : NULL))) retval = FALSE; } if (retval) { tp_svc_connection_interface_aliasing_return_from_set_aliases ( context); } else { dbus_g_method_return_error (context, first_error); g_error_free (first_error); } } GQuark gabble_conn_aliasing_pep_alias_quark (void) { static GQuark quark = 0; if (G_UNLIKELY (quark == 0)) quark = g_quark_from_static_string ("gabble_conn_aliasing_pep_alias_quark"); return quark; } static gboolean _grab_nickname (GabbleConnection *self, TpHandle handle, WockyNode *node) { TpBaseConnection *base = (TpBaseConnection *) self; TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); GQuark quark = gabble_conn_aliasing_pep_alias_quark (); const gchar *old, *nickname; node = wocky_node_get_child_ns (node, "nick", NS_NICK); if (NULL == node) { DEBUG ("didn't get a nickname for %s", tp_handle_inspect (contact_handles, handle)); _cache_negatively (self, handle); return FALSE; } nickname = node->content; old = tp_handle_get_qdata (contact_handles, handle, quark); if (tp_strdiff (old, nickname)) { if (nickname == NULL) { DEBUG ("got empty <nick/> node, caching as NO_ALIAS"); _cache_negatively (self, handle); } else { tp_handle_set_qdata (contact_handles, handle, quark, g_strdup (nickname), g_free); } gabble_conn_aliasing_nickname_updated ((GObject *) self, handle, self); } return TRUE; } static void pep_nick_node_changed (WockyPepService *pep, WockyBareContact *contact, WockyStanza *stanza, WockyNode *item, GabbleConnection *conn) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); TpHandle handle; const gchar *jid; jid = wocky_bare_contact_get_jid (contact); handle = tp_handle_ensure (contact_repo, jid, NULL, NULL); if (handle == 0) { DEBUG ("Invalid from: %s", jid); return; } if (NULL == item) { STANZA_DEBUG (stanza, "PEP event without item node, ignoring"); return; } _grab_nickname (conn, handle, item); } static void gabble_conn_aliasing_pep_nick_reply_handler (GabbleConnection *conn, WockyStanza *msg, TpHandle handle) { WockyNode *pubsub_node, *items_node, *item_node; gboolean found = FALSE; WockyNodeIter i; pubsub_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "pubsub", NS_PUBSUB); if (pubsub_node == NULL) { pubsub_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "pubsub", NS_PUBSUB "#event"); if (pubsub_node == NULL) { STANZA_DEBUG (msg, "PEP reply with no <pubsub>, ignoring"); _cache_negatively (conn, handle); return; } else { STANZA_DEBUG (msg, "PEP reply from buggy server with #event " "on <pubsub> namespace"); } } items_node = wocky_node_get_child (pubsub_node, "items"); if (items_node == NULL) { STANZA_DEBUG (msg, "No items in PEP reply"); _cache_negatively (conn, handle); return; } wocky_node_iter_init (&i, items_node, NULL, NULL); while (wocky_node_iter_next (&i, &item_node)) { if (_grab_nickname (conn, handle, item_node)) { /* FIXME: does this do the right thing on servers which return * multiple items? ejabberd only returns one anyway */ found = TRUE; break; } } if (!found) { _cache_negatively (conn, handle); } } void gabble_conn_aliasing_nickname_updated (GObject *object, TpHandle handle, gpointer user_data) { GArray *handles; handles = g_array_sized_new (FALSE, FALSE, sizeof (TpHandle), 1); g_array_append_val (handles, handle); gabble_conn_aliasing_nicknames_updated (object, handles, user_data); g_array_unref (handles); } void gabble_conn_aliasing_nicknames_updated (GObject *object, GArray *handles, gpointer user_data) { GabbleConnection *conn = GABBLE_CONNECTION (user_data); GabbleConnectionAliasSource signal_source; GPtrArray *aliases; guint i; g_return_if_fail (handles->len > 0); if (object == user_data) { /* actually PEP */ signal_source = GABBLE_CONNECTION_ALIAS_FROM_PRESENCE; } else if (object == G_OBJECT (conn->roster)) { signal_source = GABBLE_CONNECTION_ALIAS_FROM_ROSTER; } else if (object == G_OBJECT (conn->presence_cache)) { signal_source = GABBLE_CONNECTION_ALIAS_FROM_PRESENCE; } else if (object == G_OBJECT (conn->vcard_manager)) { signal_source = GABBLE_CONNECTION_ALIAS_FROM_VCARD; } else { g_assert_not_reached (); return; } aliases = g_ptr_array_sized_new (handles->len); for (i = 0; i < handles->len; i++) { TpHandle handle = g_array_index (handles, TpHandle, i); GabbleConnectionAliasSource current_source; gchar *alias = NULL; GValue entry = { 0, }; current_source = _gabble_connection_get_cached_alias (conn, handle, &alias); g_assert (current_source != GABBLE_CONNECTION_ALIAS_NONE); /* if the active alias for this handle is already known and from * a higher priority, this signal is not interesting so we do * nothing */ if (signal_source < current_source) { DEBUG ("ignoring boring alias change for handle %u, signal from %u " "but source %u has alias \"%s\"", handle, signal_source, current_source, alias); g_free (alias); continue; } g_value_init (&entry, TP_STRUCT_TYPE_ALIAS_PAIR); g_value_take_boxed (&entry, dbus_g_type_specialized_construct (TP_STRUCT_TYPE_ALIAS_PAIR)); dbus_g_type_struct_set (&entry, 0, handle, 1, alias, G_MAXUINT); g_ptr_array_add (aliases, g_value_get_boxed (&entry)); /* Check whether the roster has an entry for the handle and if so, set * the roster alias so the vCard isn't fetched on every connect. */ if (signal_source < GABBLE_CONNECTION_ALIAS_FROM_ROSTER && gabble_roster_handle_has_entry (conn->roster, handle)) gabble_roster_handle_set_name (conn->roster, handle, alias, NULL); g_free (alias); } if (aliases->len > 0) tp_svc_connection_interface_aliasing_emit_aliases_changed (conn, aliases); for (i = 0; i < aliases->len; i++) g_boxed_free (TP_STRUCT_TYPE_ALIAS_PAIR, g_ptr_array_index (aliases, i)); g_ptr_array_unref (aliases); } static void set_or_clear (gchar **target, gchar *source) { if (target != NULL) *target = source; else g_free (source); } static void maybe_set (gchar **target, const gchar *source) { if (target != NULL) *target = g_strdup (source); } static GabbleConnectionAliasSource get_cached_remote_alias ( GabbleConnection *conn, TpHandleRepoIface *contact_handles, TpHandle handle, const gchar *jid, gchar **alias) { TpBaseConnection *base = (TpBaseConnection *) conn; GabblePresence *pres; const gchar *tmp; gchar *resource; tmp = tp_handle_get_qdata (contact_handles, handle, gabble_conn_aliasing_pep_alias_quark ()); if (tmp != NULL && tmp != NO_ALIAS) { maybe_set (alias, tmp); return GABBLE_CONNECTION_ALIAS_FROM_PRESENCE; } pres = gabble_presence_cache_get (conn->presence_cache, handle); if (NULL != pres && NULL != pres->nickname) { maybe_set (alias, pres->nickname); return GABBLE_CONNECTION_ALIAS_FROM_PRESENCE; } /* XXX: should this be more important than the ones from presence? */ /* if it's our own handle, use alias passed to the connmgr, if any */ if (handle == tp_base_connection_get_self_handle (base)) { gchar *cm_alias; g_object_get (conn, "alias", &cm_alias, NULL); if (cm_alias != NULL) { set_or_clear (alias, cm_alias); return GABBLE_CONNECTION_ALIAS_FROM_CONNMGR; } } /* MUC handles have the nickname in the resource */ if (wocky_decode_jid (jid, NULL, NULL, &resource) && NULL != resource) { set_or_clear (alias, resource); return GABBLE_CONNECTION_ALIAS_FROM_MUC_RESOURCE; } if (conn->vcard_manager != NULL) { /* if we've seen a nickname in their vCard, use that */ tmp = gabble_vcard_manager_get_cached_alias (conn->vcard_manager, handle); if (NULL != tmp) { maybe_set (alias, tmp); return GABBLE_CONNECTION_ALIAS_FROM_VCARD; } } maybe_set (alias, NULL); return GABBLE_CONNECTION_ALIAS_NONE; } /* * _gabble_connection_get_cached_alias: * @conn: a connection * @handle: a handle * @alias: (allow-none): location at which to store @handle's alias. If * provided, it will always be set to a non-NULL, non-empty string, * which the caller must free. * * Gets the best possible alias for @handle, falling back to their JID if * necessary. * * Returns: the source of the alias. */ GabbleConnectionAliasSource _gabble_connection_get_cached_alias (GabbleConnection *conn, TpHandle handle, gchar **alias) { TpBaseConnection *base = (TpBaseConnection *) conn; TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); const gchar *tmp, *jid; gboolean roster_alias_was_jid = FALSE; GabbleConnectionAliasSource source; g_return_val_if_fail (NULL != conn, GABBLE_CONNECTION_ALIAS_NONE); g_return_val_if_fail (GABBLE_IS_CONNECTION (conn), GABBLE_CONNECTION_ALIAS_NONE); g_return_val_if_fail (tp_handle_is_valid (contact_handles, handle, NULL), GABBLE_CONNECTION_ALIAS_NONE); jid = tp_handle_inspect (contact_handles, handle); g_assert (NULL != jid); tmp = gabble_roster_handle_get_name (conn->roster, handle); if (!tp_strdiff (tmp, jid)) { /* Normally, we prefer whatever we've cached on the roster, to avoid * wasting bandwidth checking for aliases by repeatedly fetching the * vCard, and (more importantly) to prefer anything the local user set * over what the contact says their name is. * * However, if the alias stored on the roster is just the contact's JID, * we check for better aliases that we happen to have received from other * sources (maybe a PEP nick update, or a vCard we've fetched for the * avatar, or whatever). If we can't find anything better, we'll use the * JID, and still say that it came from the roster: this means we don't * defeat negative caching for contacts who genuinely don't have an * alias. */ roster_alias_was_jid = TRUE; } else if (!tp_str_empty (tmp)) { maybe_set (alias, tmp); return GABBLE_CONNECTION_ALIAS_FROM_ROSTER; } source = get_cached_remote_alias (conn, contact_handles, handle, jid, alias); if (source != GABBLE_CONNECTION_ALIAS_NONE) return source; /* otherwise just take their jid, which may have been specified on the roster * as the contact's alias. */ maybe_set (alias, jid); return roster_alias_was_jid ? GABBLE_CONNECTION_ALIAS_FROM_ROSTER : GABBLE_CONNECTION_ALIAS_FROM_JID; } /* * _gabble_connection_get_cached_remote_alias: * @conn: a connection * @handle: a handle * @alias: (allow-none): location at which to store @handle's alias. If * provided, it may be set to %NULL (if @handle has no cached remote * alias) or a non-empty string which the caller must free. * * Gets the best cached alias for @handle as provided by them (such as via PEP * Nicknames, in their vCard, etc), not considering anything the local user has * specified on their roster. * * Returns: the source of the alias, or GABBLE_CONNECTION_ALIAS_NONE if we have * no cached remote alias for @handle */ static GabbleConnectionAliasSource _gabble_connection_get_cached_remote_alias ( GabbleConnection *conn, TpHandle handle, gchar **alias) { TpBaseConnection *base = (TpBaseConnection *) conn; TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); const gchar *jid = tp_handle_inspect (contact_handles, handle); g_assert (NULL != jid); return get_cached_remote_alias (conn, contact_handles, handle, jid, alias); } static void maybe_request_vcard (GabbleConnection *self, TpHandle handle, GabbleConnectionAliasSource source) { TpBaseConnection *base = (TpBaseConnection *) self; /* If the source wasn't good enough then do a request */ if (source < GABBLE_CONNECTION_ALIAS_FROM_VCARD && tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_CONNECTED && !gabble_vcard_manager_has_cached_alias (self->vcard_manager, handle)) { if (self->features & GABBLE_CONNECTION_FEATURES_PEP) { TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); gabble_do_pep_request (self, handle, contact_handles, aliases_request_basic_pep_cb, GUINT_TO_POINTER (handle)); } else { gabble_vcard_manager_request (self->vcard_manager, handle, 0, NULL, NULL, G_OBJECT (self)); } } } static void conn_aliasing_fill_contact_attributes (GObject *obj, const GArray *contacts, GHashTable *attributes_hash) { guint i; GabbleConnection *self = GABBLE_CONNECTION(obj); for (i = 0; i < contacts->len; i++) { TpHandle handle = g_array_index (contacts, TpHandle, i); GabbleConnectionAliasSource source; gchar *alias; GValue *val = tp_g_value_slice_new (G_TYPE_STRING); source = _gabble_connection_get_cached_alias (self, handle, &alias); g_assert (alias != NULL); g_value_take_string (val, alias); tp_contacts_mixin_set_contact_attribute (attributes_hash, handle, TP_IFACE_CONNECTION_INTERFACE_ALIASING"/alias", val); maybe_request_vcard (self, handle, source); } } /** * gabble_connection_get_aliases * * Implements D-Bus method GetAliases * on interface org.freedesktop.Telepathy.Connection.Interface.Aliasing * * @context: The D-Bus invocation context to use to return values * or throw an error. */ static void gabble_connection_get_aliases (TpSvcConnectionInterfaceAliasing *iface, const GArray *contacts, DBusGMethodInvocation *context) { GabbleConnection *self = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) self; TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); GHashTable *result; GError *error = NULL; guint i; g_assert (GABBLE_IS_CONNECTION (self)); TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); if (!tp_handles_are_valid (contact_handles, contacts, FALSE, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); return; } result = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); for (i = 0; i < contacts->len; i++) { TpHandle handle = g_array_index (contacts, TpHandle, i); GabbleConnectionAliasSource source; gchar *alias; source = _gabble_connection_get_cached_alias (self, handle, &alias); g_assert (alias != NULL); g_hash_table_insert (result, GUINT_TO_POINTER (handle), alias); maybe_request_vcard (self, handle, source); } tp_svc_connection_interface_aliasing_return_from_get_aliases (context, result); g_hash_table_unref (result); } void conn_aliasing_init (GabbleConnection *conn) { tp_contacts_mixin_add_contact_attributes_iface (G_OBJECT (conn), TP_IFACE_CONNECTION_INTERFACE_ALIASING, conn_aliasing_fill_contact_attributes); conn->pep_nick = wocky_pep_service_new (NS_NICK, TRUE); g_signal_connect (conn->pep_nick, "changed", G_CALLBACK (pep_nick_node_changed), conn); } void conn_aliasing_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcConnectionInterfaceAliasingClass *klass = g_iface; #define IMPLEMENT(x) tp_svc_connection_interface_aliasing_implement_##x (\ klass, gabble_connection_##x) IMPLEMENT(get_alias_flags); IMPLEMENT(request_aliases); IMPLEMENT(get_aliases); IMPLEMENT(set_aliases); #undef IMPLEMENT } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/capabilities.c����������������������������������������������������������0000664�0001750�0001750�00000050000�12332440117�021552� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * capabilities.c - Connection.Interface.Capabilities constants and utilities * Copyright (C) 2005 Collabora Ltd. * Copyright (C) 2005 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "gabble/capabilities.h" #include <stdlib.h> #include <string.h> #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #define DEBUG_FLAG GABBLE_DEBUG_PRESENCE #include "debug.h" #include "namespaces.h" typedef struct _Feature Feature; struct _Feature { enum { FEATURE_FIXED, FEATURE_OPTIONAL, FEATURE_OLPC } feature_type; gchar *ns; }; static const Feature self_advertised_features[] = { { FEATURE_FIXED, NS_GOOGLE_FEAT_SESSION }, #ifdef ENABLE_VOIP { FEATURE_FIXED, NS_JINGLE_TRANSPORT_RAWUDP }, { FEATURE_FIXED, NS_JINGLE015 }, { FEATURE_FIXED, NS_JINGLE032 }, #endif { FEATURE_FIXED, NS_CHAT_STATES }, { FEATURE_FIXED, NS_NICK }, { FEATURE_FIXED, NS_NICK "+notify" }, { FEATURE_FIXED, NS_SI }, { FEATURE_FIXED, NS_IBB }, { FEATURE_FIXED, NS_TUBES }, { FEATURE_FIXED, NS_BYTESTREAMS }, { FEATURE_FIXED, NS_VERSION }, { FEATURE_FIXED, NS_LAST }, { FEATURE_FIXED, NS_RECEIPTS }, #ifdef ENABLE_FILE_TRANSFER { FEATURE_OPTIONAL, NS_FILE_TRANSFER }, { FEATURE_OPTIONAL, NS_TP_FT_METADATA }, #endif #ifdef ENABLE_VOIP { FEATURE_OPTIONAL, NS_GOOGLE_TRANSPORT_P2P }, { FEATURE_OPTIONAL, NS_JINGLE_TRANSPORT_ICEUDP }, { FEATURE_OPTIONAL, NS_GOOGLE_FEAT_SHARE }, { FEATURE_OPTIONAL, NS_GOOGLE_FEAT_VOICE }, { FEATURE_OPTIONAL, NS_GOOGLE_FEAT_VIDEO }, { FEATURE_OPTIONAL, NS_GOOGLE_FEAT_CAMERA }, { FEATURE_OPTIONAL, NS_JINGLE_DESCRIPTION_AUDIO }, { FEATURE_OPTIONAL, NS_JINGLE_DESCRIPTION_VIDEO }, { FEATURE_OPTIONAL, NS_JINGLE_RTP }, { FEATURE_OPTIONAL, NS_JINGLE_RTP_AUDIO }, { FEATURE_OPTIONAL, NS_JINGLE_RTP_VIDEO }, #endif { FEATURE_OLPC, NS_OLPC_BUDDY_PROPS "+notify" }, { FEATURE_OLPC, NS_OLPC_ACTIVITIES "+notify" }, { FEATURE_OLPC, NS_OLPC_CURRENT_ACTIVITY "+notify" }, { FEATURE_OLPC, NS_OLPC_ACTIVITY_PROPS "+notify" }, { FEATURE_OPTIONAL, NS_GEOLOC "+notify" }, { 0, NULL } }; static const Feature quirks[] = { { 0, QUIRK_OMITS_CONTENT_CREATORS }, { 0, NULL } }; static GabbleCapabilitySet *legacy_caps = NULL; static GabbleCapabilitySet *share_v1_caps = NULL; static GabbleCapabilitySet *voice_v1_caps = NULL; static GabbleCapabilitySet *video_v1_caps = NULL; static GabbleCapabilitySet *camera_v1_caps = NULL; static GabbleCapabilitySet *any_audio_caps = NULL; static GabbleCapabilitySet *any_video_caps = NULL; static GabbleCapabilitySet *any_audio_video_caps = NULL; static GabbleCapabilitySet *any_google_av_caps = NULL; static GabbleCapabilitySet *any_jingle_av_caps = NULL; static GabbleCapabilitySet *any_transport_caps = NULL; static GabbleCapabilitySet *fixed_caps = NULL; static GabbleCapabilitySet *geoloc_caps = NULL; static GabbleCapabilitySet *olpc_caps = NULL; const GabbleCapabilitySet * gabble_capabilities_get_legacy (void) { return legacy_caps; } const GabbleCapabilitySet * gabble_capabilities_get_bundle_share_v1 (void) { return share_v1_caps; } const GabbleCapabilitySet * gabble_capabilities_get_bundle_voice_v1 (void) { return voice_v1_caps; } const GabbleCapabilitySet * gabble_capabilities_get_bundle_video_v1 (void) { return video_v1_caps; } const GabbleCapabilitySet * gabble_capabilities_get_bundle_camera_v1 (void) { return camera_v1_caps; } const GabbleCapabilitySet * gabble_capabilities_get_any_audio (void) { return any_audio_caps; } const GabbleCapabilitySet * gabble_capabilities_get_any_video (void) { return any_video_caps; } const GabbleCapabilitySet * gabble_capabilities_get_any_audio_video (void) { return any_audio_video_caps; } const GabbleCapabilitySet * gabble_capabilities_get_any_google_av (void) { return any_google_av_caps; } const GabbleCapabilitySet * gabble_capabilities_get_any_jingle_av (void) { return any_jingle_av_caps; } const GabbleCapabilitySet * gabble_capabilities_get_any_transport (void) { return any_transport_caps; } const GabbleCapabilitySet * gabble_capabilities_get_fixed_caps (void) { return fixed_caps; } const GabbleCapabilitySet * gabble_capabilities_get_geoloc_notify (void) { return geoloc_caps; } const GabbleCapabilitySet * gabble_capabilities_get_olpc_notify (void) { return olpc_caps; } static gboolean omits_content_creators (WockyNode *identity) { const gchar *name, *suffix; gchar *end; int ver; name = wocky_node_get_attribute (identity, "name"); if (name == NULL) return FALSE; #define PREFIX "Telepathy Gabble 0.7." if (!g_str_has_prefix (name, PREFIX)) return FALSE; suffix = name + strlen (PREFIX); ver = strtol (suffix, &end, 10); if (*end != '\0') return FALSE; /* Gabble versions since 0.7.16 did not send the creator='' attribute for * contents. The bug is fixed in 0.7.29. */ if (ver >= 16 && ver < 29) { DEBUG ("contact is using '%s' which omits 'creator'", name); return TRUE; } else { return FALSE; } } static gsize feature_handles_refcount = 0; /* The handles in this repository are not really handles in the tp-spec sense * of the word; we're just using it as a convenient implementation of a * refcounted string pool. Their string values are either XMPP namespaces, * or "quirk" pseudo-namespaces starting with QUIRK_PREFIX_CHAR (like * QUIRK_OMITS_CONTENT_CREATORS). */ static TpHandleRepoIface *feature_handles = NULL; void gabble_capabilities_init (gpointer conn) { DEBUG ("%p", conn); if (feature_handles_refcount++ == 0) { const Feature *feat; g_assert (feature_handles == NULL); /* TpDynamicHandleRepo wants a handle type, which isn't relevant here * (we're just using it as a string pool). Use an arbitrary handle type * to shut it up. */ feature_handles = tp_dynamic_handle_repo_new (TP_HANDLE_TYPE_CONTACT, NULL, NULL); /* make the pre-cooked bundles */ legacy_caps = gabble_capability_set_new (); for (feat = self_advertised_features; feat->ns != NULL; feat++) { gabble_capability_set_add (legacy_caps, feat->ns); } #ifdef ENABLE_VOIP share_v1_caps = gabble_capability_set_new (); gabble_capability_set_add (share_v1_caps, NS_GOOGLE_FEAT_SHARE); voice_v1_caps = gabble_capability_set_new (); gabble_capability_set_add (voice_v1_caps, NS_GOOGLE_FEAT_VOICE); video_v1_caps = gabble_capability_set_new (); gabble_capability_set_add (video_v1_caps, NS_GOOGLE_FEAT_VIDEO); camera_v1_caps = gabble_capability_set_new (); gabble_capability_set_add (camera_v1_caps, NS_GOOGLE_FEAT_CAMERA); any_audio_caps = gabble_capability_set_new (); gabble_capability_set_add (any_audio_caps, NS_JINGLE_RTP_AUDIO); gabble_capability_set_add (any_audio_caps, NS_JINGLE_DESCRIPTION_AUDIO); gabble_capability_set_add (any_audio_caps, NS_GOOGLE_FEAT_VOICE); any_video_caps = gabble_capability_set_new (); gabble_capability_set_add (any_video_caps, NS_JINGLE_RTP_VIDEO); gabble_capability_set_add (any_video_caps, NS_JINGLE_DESCRIPTION_VIDEO); gabble_capability_set_add (any_video_caps, NS_GOOGLE_FEAT_VIDEO); any_audio_video_caps = gabble_capability_set_copy (any_audio_caps); gabble_capability_set_update (any_audio_video_caps, any_video_caps); any_google_av_caps = gabble_capability_set_new (); gabble_capability_set_add (any_google_av_caps, NS_GOOGLE_FEAT_VOICE); gabble_capability_set_add (any_google_av_caps, NS_GOOGLE_FEAT_VIDEO); any_jingle_av_caps = gabble_capability_set_copy (any_audio_caps); gabble_capability_set_update (any_jingle_av_caps, any_video_caps); gabble_capability_set_exclude (any_jingle_av_caps, any_google_av_caps); any_transport_caps = gabble_capability_set_new (); gabble_capability_set_add (any_transport_caps, NS_GOOGLE_TRANSPORT_P2P); gabble_capability_set_add (any_transport_caps, NS_JINGLE_TRANSPORT_ICEUDP); gabble_capability_set_add (any_transport_caps, NS_JINGLE_TRANSPORT_RAWUDP); #endif fixed_caps = gabble_capability_set_new (); for (feat = self_advertised_features; feat->ns != NULL; feat++) { if (feat->feature_type == FEATURE_FIXED) gabble_capability_set_add (fixed_caps, feat->ns); } geoloc_caps = gabble_capability_set_new (); gabble_capability_set_add (geoloc_caps, NS_GEOLOC "+notify"); olpc_caps = gabble_capability_set_new (); for (feat = self_advertised_features; feat->ns != NULL; feat++) { if (feat->feature_type == FEATURE_OLPC) gabble_capability_set_add (olpc_caps, feat->ns); } } g_assert (feature_handles != NULL); } void gabble_capabilities_finalize (gpointer conn) { DEBUG ("%p", conn); g_assert (feature_handles_refcount > 0); if (--feature_handles_refcount == 0) { gabble_capability_set_free (legacy_caps); #ifdef ENABLE_VOIP gabble_capability_set_free (share_v1_caps); gabble_capability_set_free (voice_v1_caps); gabble_capability_set_free (video_v1_caps); gabble_capability_set_free (camera_v1_caps); gabble_capability_set_free (any_audio_caps); gabble_capability_set_free (any_video_caps); gabble_capability_set_free (any_audio_video_caps); gabble_capability_set_free (any_google_av_caps); gabble_capability_set_free (any_jingle_av_caps); gabble_capability_set_free (any_transport_caps); #endif gabble_capability_set_free (fixed_caps); gabble_capability_set_free (geoloc_caps); gabble_capability_set_free (olpc_caps); legacy_caps = NULL; share_v1_caps = NULL; voice_v1_caps = NULL; video_v1_caps = NULL; camera_v1_caps = NULL; any_audio_caps = NULL; any_video_caps = NULL; any_audio_video_caps = NULL; any_google_av_caps = NULL; any_jingle_av_caps = NULL; any_transport_caps = NULL; fixed_caps = NULL; geoloc_caps = NULL; olpc_caps = NULL; tp_clear_object (&feature_handles); } } struct _GabbleCapabilitySet { TpHandleSet *handles; }; GabbleCapabilitySet * gabble_capability_set_new (void) { GabbleCapabilitySet *ret = g_slice_new0 (GabbleCapabilitySet); g_assert (feature_handles != NULL); ret->handles = tp_handle_set_new (feature_handles); return ret; } GabbleCapabilitySet * gabble_capability_set_new_from_stanza (WockyNode *query_result) { GabbleCapabilitySet *ret; const gchar *var; GSList *ni; g_return_val_if_fail (query_result != NULL, NULL); ret = gabble_capability_set_new (); for (ni = query_result->children; ni != NULL; ni = g_slist_next (ni)) { WockyNode *child = ni->data; if (!tp_strdiff (child->name, "identity")) { if (omits_content_creators (child)) gabble_capability_set_add (ret, QUIRK_OMITS_CONTENT_CREATORS); continue; } if (tp_strdiff (child->name, "feature")) continue; var = wocky_node_get_attribute (child, "var"); if (NULL == var) continue; if (G_UNLIKELY (var[0] == QUIRK_PREFIX_CHAR)) { /* I think not! (It's not allowed in XML...) */ continue; } /* TODO: only store namespaces we understand. */ gabble_capability_set_add (ret, var); } return ret; } GabbleCapabilitySet * gabble_capability_set_copy (const GabbleCapabilitySet *caps) { GabbleCapabilitySet *ret; g_return_val_if_fail (caps != NULL, NULL); ret = gabble_capability_set_new (); gabble_capability_set_update (ret, caps); return ret; } void gabble_capability_set_update (GabbleCapabilitySet *target, const GabbleCapabilitySet *source) { TpIntset *ret; g_return_if_fail (target != NULL); g_return_if_fail (source != NULL); ret = tp_handle_set_update (target->handles, tp_handle_set_peek (source->handles)); tp_intset_destroy (ret); } typedef struct { GSList *deleted; TpHandleSet *intersect_with; } IntersectHelper; static void intersect_helper (TpHandleSet *unused G_GNUC_UNUSED, TpHandle handle, gpointer p) { IntersectHelper *data = p; if (!tp_handle_set_is_member (data->intersect_with, handle)) data->deleted = g_slist_prepend (data->deleted, GUINT_TO_POINTER (handle)); } void gabble_capability_set_intersect (GabbleCapabilitySet *target, const GabbleCapabilitySet *source) { IntersectHelper data = { NULL, NULL }; g_return_if_fail (target != NULL); g_return_if_fail (source != NULL); if (target == source) return; data.intersect_with = source->handles; tp_handle_set_foreach (target->handles, intersect_helper, &data); while (data.deleted != NULL) { DEBUG ("dropping %s", tp_handle_inspect (feature_handles, GPOINTER_TO_UINT (data.deleted->data))); tp_handle_set_remove (target->handles, GPOINTER_TO_UINT (data.deleted->data)); data.deleted = g_slist_delete_link (data.deleted, data.deleted); } } static void remove_from_set (TpHandleSet *unused G_GNUC_UNUSED, TpHandle handle, gpointer handles) { tp_handle_set_remove (handles, handle); } void gabble_capability_set_exclude (GabbleCapabilitySet *caps, const GabbleCapabilitySet *removed) { g_return_if_fail (caps != NULL); g_return_if_fail (removed != NULL); if (caps == removed) { gabble_capability_set_clear (caps); return; } tp_handle_set_foreach (removed->handles, remove_from_set, caps->handles); } void gabble_capability_set_add (GabbleCapabilitySet *caps, const gchar *cap) { TpHandle handle; g_return_if_fail (caps != NULL); g_return_if_fail (cap != NULL); handle = tp_handle_ensure (feature_handles, cap, NULL, NULL); tp_handle_set_add (caps->handles, handle); } gboolean gabble_capability_set_remove (GabbleCapabilitySet *caps, const gchar *cap) { TpHandle handle; g_return_val_if_fail (caps != NULL, FALSE); g_return_val_if_fail (cap != NULL, FALSE); handle = tp_handle_lookup (feature_handles, cap, NULL, NULL); if (handle == 0) return FALSE; return tp_handle_set_remove (caps->handles, handle); } void gabble_capability_set_clear (GabbleCapabilitySet *caps) { g_return_if_fail (caps != NULL); /* There is no tp_handle_set_clear, so do the next best thing */ tp_handle_set_destroy (caps->handles); caps->handles = tp_handle_set_new (feature_handles); } void gabble_capability_set_free (GabbleCapabilitySet *caps) { g_return_if_fail (caps != NULL); tp_handle_set_destroy (caps->handles); g_slice_free (GabbleCapabilitySet, caps); } gint gabble_capability_set_size (const GabbleCapabilitySet *caps) { g_return_val_if_fail (caps != NULL, 0); return tp_handle_set_size (caps->handles); } /* By design, this function can be used as a GabbleCapabilitySetPredicate */ gboolean gabble_capability_set_has (const GabbleCapabilitySet *caps, const gchar *cap) { TpHandle handle; g_return_val_if_fail (caps != NULL, FALSE); g_return_val_if_fail (cap != NULL, FALSE); handle = tp_handle_lookup (feature_handles, cap, NULL, NULL); if (handle == 0) { /* nobody in the whole CM has this capability */ return FALSE; } return tp_handle_set_is_member (caps->handles, handle); } /* By design, this function can be used as a GabbleCapabilitySetPredicate */ gboolean gabble_capability_set_has_one (const GabbleCapabilitySet *caps, const GabbleCapabilitySet *alternatives) { TpIntsetFastIter iter; guint element; g_return_val_if_fail (caps != NULL, FALSE); g_return_val_if_fail (alternatives != NULL, FALSE); tp_intset_fast_iter_init (&iter, tp_handle_set_peek (alternatives->handles)); while (tp_intset_fast_iter_next (&iter, &element)) { if (tp_handle_set_is_member (caps->handles, element)) { return TRUE; } } return FALSE; } /* By design, this function can be used as a GabbleCapabilitySetPredicate */ gboolean gabble_capability_set_at_least (const GabbleCapabilitySet *caps, const GabbleCapabilitySet *query) { TpIntsetFastIter iter; guint element; g_return_val_if_fail (caps != NULL, FALSE); g_return_val_if_fail (query != NULL, FALSE); tp_intset_fast_iter_init (&iter, tp_handle_set_peek (query->handles)); while (tp_intset_fast_iter_next (&iter, &element)) { if (!tp_handle_set_is_member (caps->handles, element)) { return FALSE; } } return TRUE; } gboolean gabble_capability_set_equals (const GabbleCapabilitySet *a, const GabbleCapabilitySet *b) { g_return_val_if_fail (a != NULL, FALSE); g_return_val_if_fail (b != NULL, FALSE); return tp_intset_is_equal (tp_handle_set_peek (a->handles), tp_handle_set_peek (b->handles)); } /* Does not iterate over quirks, only real features. */ void gabble_capability_set_foreach (const GabbleCapabilitySet *caps, GFunc func, gpointer user_data) { TpIntsetFastIter iter; guint element; g_return_if_fail (caps != NULL); g_return_if_fail (func != NULL); tp_intset_fast_iter_init (&iter, tp_handle_set_peek (caps->handles)); while (tp_intset_fast_iter_next (&iter, &element)) { const gchar *var = tp_handle_inspect (feature_handles, element); g_return_if_fail (var != NULL); if (var[0] != QUIRK_PREFIX_CHAR) func ((gchar *) var, user_data); } } static void append_intset (GString *ret, const TpIntset *cap_ints, const gchar *indent) { TpIntsetFastIter iter; guint element; tp_intset_fast_iter_init (&iter, cap_ints); while (tp_intset_fast_iter_next (&iter, &element)) { const gchar *var = tp_handle_inspect (feature_handles, element); g_return_if_fail (var != NULL); if (var[0] == QUIRK_PREFIX_CHAR) { g_string_append_printf (ret, "%sQuirk: %s\n", indent, var + 1); } else { g_string_append_printf (ret, "%sFeature: %s\n", indent, var); } } } gchar * gabble_capability_set_dump (const GabbleCapabilitySet *caps, const gchar *indent) { GString *ret; g_return_val_if_fail (caps != NULL, NULL); if (indent == NULL) indent = ""; ret = g_string_new (indent); g_string_append (ret, "--begin--\n"); append_intset (ret, tp_handle_set_peek (caps->handles), indent); g_string_append (ret, indent); g_string_append (ret, "--end--\n"); return g_string_free (ret, FALSE); } gchar * gabble_capability_set_dump_diff (const GabbleCapabilitySet *old_caps, const GabbleCapabilitySet *new_caps, const gchar *indent) { TpIntset *old_ints, *new_ints, *rem, *add; GString *ret; g_return_val_if_fail (old_caps != NULL, NULL); g_return_val_if_fail (new_caps != NULL, NULL); old_ints = tp_handle_set_peek (old_caps->handles); new_ints = tp_handle_set_peek (new_caps->handles); if (tp_intset_is_equal (old_ints, new_ints)) return g_strdup_printf ("%s--no change--", indent); rem = tp_intset_difference (old_ints, new_ints); add = tp_intset_difference (new_ints, old_ints); ret = g_string_new (""); if (!tp_intset_is_empty (rem)) { g_string_append (ret, indent); g_string_append (ret, "--removed--\n"); append_intset (ret, rem, indent); } if (!tp_intset_is_empty (add)) { g_string_append (ret, indent); g_string_append (ret, "--added--\n"); append_intset (ret, add, indent); } g_string_append (ret, indent); g_string_append (ret, "--end--"); tp_intset_destroy (add); tp_intset_destroy (rem); return g_string_free (ret, FALSE); } telepathy-gabble-0.18.3/src/util.h������������������������������������������������������������������0000664�0001750�0001750�00000011200�12223562023�020102� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * util.h - Headers for Gabble utility functions * Copyright (C) 2006 Collabora Ltd. * Copyright (C) 2006 Nokia Corporation * @author Robert McQueen <robert.mcqueen@collabora.co.uk> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_UTIL_H__ #define __GABBLE_UTIL_H__ #include <config.h> #include <glib.h> #include <telepathy-glib/telepathy-glib.h> #include <wocky/wocky.h> #include "types.h" /* Guarantees that the resulting hash is in lower-case */ gchar *sha1_hex (const gchar *bytes, guint len); /* A SHA1 digest is 20 bytes long */ #define SHA1_HASH_SIZE 20 void sha1_bin (const gchar *bytes, guint len, guchar out[SHA1_HASH_SIZE]); gchar *gabble_generate_id (void); void lm_message_node_add_own_nick (WockyNode *node, GabbleConnection *conn); G_GNUC_WARN_UNUSED_RESULT gchar *gabble_encode_jid (const gchar *node, const gchar *domain, const gchar *resource); gchar *gabble_remove_resource (const gchar *jid); gchar *gabble_normalize_contact (TpHandleRepoIface *repo, const gchar *jid, gpointer userdata, GError **error); gchar *gabble_normalize_room (TpHandleRepoIface *repo, const gchar *jid, gpointer context, GError **error); TpHandle gabble_get_room_handle_from_jid (TpHandleRepoIface *room_repo, const gchar *jid); GHashTable *lm_message_node_extract_properties (WockyNode *node, const gchar *prop); void lm_message_node_add_children_from_properties (WockyNode *node, GHashTable *properties, const gchar *prop); void gabble_signal_connect_weak (gpointer instance, const gchar *detailed_signal, GCallback c_handler, GObject *user_data); guint gabble_idle_add_weak (GSourceFunc function, GObject *object); GPtrArray *gabble_g_ptr_array_copy (GPtrArray *source); WockyBareContact * ensure_bare_contact_from_jid (GabbleConnection *conn, const gchar *jid); TpHandle ensure_handle_from_contact ( GabbleConnection *conn, WockyContact *contact); #ifdef ENABLE_VOIP gboolean jingle_pick_best_resource (GabbleConnection *conn, TpHandle peer, gboolean want_audio, gboolean want_video, const char **transport_ns, WockyJingleDialect *dialect, const gchar **resource_out); const gchar *jingle_pick_best_content_type (GabbleConnection *conn, TpHandle peer, const gchar *resource, WockyJingleMediaType type); GPtrArray *gabble_call_candidates_to_array (GList *candidates); #endif gchar * gabble_peer_to_jid (GabbleConnection *conn, TpHandle peer, const gchar *resource); gboolean gabble_flag_from_nick (GType flag_type, const gchar *nick, guint *value); void gabble_simple_async_succeed_or_fail_in_idle (gpointer self, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, const GError *error); GSimpleAsyncResult *gabble_simple_async_countdown_new (gpointer self, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag, gssize todo); void gabble_simple_async_countdown_inc (GSimpleAsyncResult *simple); void gabble_simple_async_countdown_dec (GSimpleAsyncResult *simple); /* Boilerplate for telling servers which implement XEP-0079 not to store these * messages for delivery later. Include it in your call to wocky_stanza_build() * like so: * * wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, * NULL, jid, * '(', "close", * ':', NS_TUBES, * '@', "tube", id_str, * ')', * GABBLE_AMP_DO_NOT_STORE_SPEC, * NULL); * * Every 1000th user will win a Marshall amplifier! */ #define GABBLE_AMP_DO_NOT_STORE_SPEC \ '(', "amp", \ ':', NS_AMP, \ '(', "rule", \ '@', "condition", "deliver-at", \ '@', "value", "stored", \ '@', "action", "error", \ ')', \ '(', "rule", \ '@', "condition", "match-resource", \ '@', "value", "exact", \ '@', "action", "error", \ ')', \ ')' #endif /* __GABBLE_UTIL_H__ */ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/olpc-activity.c���������������������������������������������������������0000664�0001750�0001750�00000015717�12332440117�021730� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * olpc-activity.c - Source for GabbleOlpcActivity * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "olpc-activity.h" #include <stdlib.h> #include <string.h> #include <glib.h> #define DEBUG_FLAG GABBLE_DEBUG_OLPC #include "debug.h" #include "extensions/extensions.h" #include "gabble-signals-marshal.h" #include "namespaces.h" #include "util.h" /* properties */ enum { PROP_CONNECTION = 1, PROP_ROOM, PROP_ID, PROP_PROPERTIES, LAST_PROPERTY }; struct _GabbleOlpcActivityPrivate { GabbleConnection *conn; gboolean dispose_has_run; }; G_DEFINE_TYPE (GabbleOlpcActivity, gabble_olpc_activity, G_TYPE_OBJECT); static void gabble_olpc_activity_init (GabbleOlpcActivity *self) { GabbleOlpcActivityPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_OLPC_ACTIVITY, GabbleOlpcActivityPrivate); self->priv = priv; priv->dispose_has_run = FALSE; } static void gabble_olpc_activity_finalize (GObject *object) { GabbleOlpcActivity *self = GABBLE_OLPC_ACTIVITY (object); if (self->id != NULL) { g_free (self->id); self->id = NULL; } if (self->properties != NULL) { g_hash_table_unref (self->properties); self->properties = NULL; } G_OBJECT_CLASS (gabble_olpc_activity_parent_class)->finalize (object); } static void gabble_olpc_activity_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleOlpcActivity *self = GABBLE_OLPC_ACTIVITY (object); GabbleOlpcActivityPrivate *priv = self->priv; switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, priv->conn); break; case PROP_ROOM: g_value_set_uint (value, self->room); break; case PROP_ID: g_value_set_string (value, self->id); break; case PROP_PROPERTIES: g_value_set_boxed (value, self->properties); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_olpc_activity_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleOlpcActivity *self = GABBLE_OLPC_ACTIVITY (object); GabbleOlpcActivityPrivate *priv = self->priv; switch (property_id) { case PROP_CONNECTION: priv->conn = g_value_get_object (value); break; case PROP_ROOM: self->room = g_value_get_uint (value); break; case PROP_ID: g_free (self->id); self->id = g_value_dup_string (value); break; case PROP_PROPERTIES: if (self->properties != NULL) g_hash_table_unref (self->properties); self->properties = g_value_get_boxed (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static GObject * gabble_olpc_activity_constructor (GType type, guint n_props, GObjectConstructParam *props) { GObject *obj; GabbleOlpcActivity *self; obj = G_OBJECT_CLASS (gabble_olpc_activity_parent_class)-> constructor (type, n_props, props); self = GABBLE_OLPC_ACTIVITY (obj); g_assert (self->room != 0); DEBUG ("new activity %s (%d)", gabble_olpc_activity_get_room (self), self->room); return obj; } static void gabble_olpc_activity_class_init ( GabbleOlpcActivityClass *gabble_olpc_activity_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_olpc_activity_class); GParamSpec *param_spec; object_class->get_property = gabble_olpc_activity_get_property; object_class->set_property = gabble_olpc_activity_set_property; object_class->constructor = gabble_olpc_activity_constructor; g_type_class_add_private (gabble_olpc_activity_class, sizeof (GabbleOlpcActivityPrivate)); object_class->finalize = gabble_olpc_activity_finalize; param_spec = g_param_spec_object ( "connection", "GabbleConnection object", "Gabble connection object that owns this activity object.", GABBLE_TYPE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); param_spec = g_param_spec_uint ( "room", "activity room", "a TpHandle representing the activity room", 0, G_MAXUINT, 0, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ROOM, param_spec); param_spec = g_param_spec_string ( "id", "activity id", "the activity ID", NULL, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ID, param_spec); param_spec = g_param_spec_boxed ( "properties", "activity properties", "a GHashTable containing activity's properties", G_TYPE_HASH_TABLE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_PROPERTIES, param_spec); } GabbleOlpcActivity * gabble_olpc_activity_new (GabbleConnection *conn, TpHandle room) { return g_object_new (GABBLE_TYPE_OLPC_ACTIVITY, "connection", conn, "room", room, NULL); } const gchar * gabble_olpc_activity_get_room (GabbleOlpcActivity *self) { TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_ROOM); return tp_handle_inspect (room_repo, self->room); } gboolean gabble_olpc_activity_is_visible (GabbleOlpcActivity *self) { GValue *gv; /* false if incomplete */ if (self->id == NULL || self->properties == NULL) return FALSE; gv = g_hash_table_lookup (self->properties, "private"); if (gv == NULL) { return FALSE; } /* if they put something non-boolean in it, err on the side of privacy */ if (!G_VALUE_HOLDS_BOOLEAN (gv)) return FALSE; /* if they specified a privacy level, go with it */ return !g_value_get_boolean (gv); } �������������������������������������������������telepathy-gabble-0.18.3/src/bytestream-multiple.h���������������������������������������������������0000664�0001750�0001750�00000005101�11720700311�023133� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * bytestream-socks5.h - Header for GabbleBytestreamMultiple * Copyright (C) 2007-2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_BYTESTREAM_MULTIPLE_H__ #define __GABBLE_BYTESTREAM_MULTIPLE_H__ #include <stdlib.h> #include <glib-object.h> #include "bytestream-iface.h" G_BEGIN_DECLS typedef struct _GabbleBytestreamMultiple GabbleBytestreamMultiple; typedef struct _GabbleBytestreamMultipleClass GabbleBytestreamMultipleClass; typedef struct _GabbleBytestreamMultiplePrivate GabbleBytestreamMultiplePrivate; struct _GabbleBytestreamMultipleClass { GObjectClass parent_class; }; struct _GabbleBytestreamMultiple { GObject parent; GabbleBytestreamMultiplePrivate *priv; }; GType gabble_bytestream_multiple_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_BYTESTREAM_MULTIPLE \ (gabble_bytestream_multiple_get_type ()) #define GABBLE_BYTESTREAM_MULTIPLE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_BYTESTREAM_MULTIPLE,\ GabbleBytestreamMultiple)) #define GABBLE_BYTESTREAM_MULTIPLE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_BYTESTREAM_MULTIPLE,\ GabbleBytestreamMultipleClass)) #define GABBLE_IS_BYTESTREAM_MULTIPLE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_BYTESTREAM_MULTIPLE)) #define GABBLE_IS_BYTESTREAM_MULTIPLE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_BYTESTREAM_MULTIPLE)) #define GABBLE_BYTESTREAM_MULTIPLE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_BYTESTREAM_MULTIPLE,\ GabbleBytestreamMultipleClass)) void gabble_bytestream_multiple_add_stream_method ( GabbleBytestreamMultiple *self, const gchar *method); gboolean gabble_bytestream_multiple_has_stream_method ( GabbleBytestreamMultiple *self); G_END_DECLS #endif /* #ifndef __GABBLE_BYTESTREAM_MULTIPLE_H__ */ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/bytestream-iface.c������������������������������������������������������0000664�0001750�0001750�00000015142�12332440117�022355� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * bytestream-iface.c - Source for GabbleBytestream interface * Copyright (C) 2007 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "bytestream-iface.h" #include "gabble-signals-marshal.h" #include "connection.h" gboolean gabble_bytestream_iface_initiate (GabbleBytestreamIface *self) { gboolean (*virtual_method)(GabbleBytestreamIface *) = GABBLE_BYTESTREAM_IFACE_GET_CLASS (self)->initiate; g_assert (virtual_method != NULL); return virtual_method (self); } gboolean gabble_bytestream_iface_send (GabbleBytestreamIface *self, guint len, const gchar *data) { gboolean (*virtual_method)(GabbleBytestreamIface *, guint, const gchar *) = GABBLE_BYTESTREAM_IFACE_GET_CLASS (self)->send; g_assert (virtual_method != NULL); return virtual_method (self, len, data); } void gabble_bytestream_iface_close (GabbleBytestreamIface *self, GError *error) { void (*virtual_method)(GabbleBytestreamIface *, GError *) = GABBLE_BYTESTREAM_IFACE_GET_CLASS (self)->close; g_assert (virtual_method != NULL); virtual_method (self, error); } void gabble_bytestream_iface_accept (GabbleBytestreamIface *self, GabbleBytestreamAugmentSiAcceptReply func, gpointer user_data) { void (*virtual_method)(GabbleBytestreamIface *, GabbleBytestreamAugmentSiAcceptReply, gpointer) = GABBLE_BYTESTREAM_IFACE_GET_CLASS (self)->accept; g_assert (virtual_method != NULL); virtual_method (self, func, user_data); } static void gabble_bytestream_iface_base_init (gpointer klass) { static gboolean initialized = FALSE; if (!initialized) { GParamSpec *param_spec; param_spec = g_param_spec_object ( "connection", "GabbleConnection object", "Gabble connection object that owns this Bytestream object.", GABBLE_TYPE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_uint ( "peer-handle", "Peer handle", "The TpHandle of the remote peer involved in this bytestream", 0, G_MAXUINT32, 0, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_uint ( "peer-handle-type", "Peer handle type", "The TpHandleType of the remote peer's associated handle", 0, G_MAXUINT32, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_string ( "stream-id", "stream ID", "the ID of the stream", "", G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_string ( "peer-jid", "Peer JID", "The JID used by the remote peer during the SI", "", G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_uint ( "state", "Bytestream state", "An enum (GabbleBytestreamState) signifying the current state of" "this bytestream object", 0, NUM_GABBLE_BYTESTREAM_STATES - 1, GABBLE_BYTESTREAM_STATE_LOCAL_PENDING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_string ( "protocol", "protocol", "the name of the protocol implemented by this bytestream", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (klass, param_spec); g_signal_new ("data-received", G_TYPE_FROM_INTERFACE (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT_POINTER, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_POINTER); g_signal_new ("state-changed", G_TYPE_FROM_INTERFACE (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); g_signal_new ("write-blocked", G_TYPE_FROM_INTERFACE (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); g_signal_new ("connection-error", G_TYPE_FROM_INTERFACE (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); initialized = TRUE; } } void gabble_bytestream_iface_block_reading (GabbleBytestreamIface *self, gboolean block) { void (*virtual_method)(GabbleBytestreamIface *, gboolean) = GABBLE_BYTESTREAM_IFACE_GET_CLASS (self)->block_reading; if (virtual_method != NULL) virtual_method (self, block); /* else: do nothing. Some bytestreams like IBB can't implement read_block. */ } GType gabble_bytestream_iface_get_type (void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof (GabbleBytestreamIfaceClass), gabble_bytestream_iface_base_init, /* base_init */ NULL, /* base_finalize */ NULL, /* class_init */ NULL, /* class_finalize */ NULL, /* class_data */ 0, 0, /* n_preallocs */ NULL /* instance_init */ }; type = g_type_register_static (G_TYPE_INTERFACE, "GabbleBytestreamIface", &info, 0); } return type; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/sidecar.c���������������������������������������������������������������0000664�0001750�0001750�00000004415�12223562023�020544� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * sidecar.c — interface for connection sidecars * Copyright © 2009 Collabora Ltd. * Copyright © 2009 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "gabble/sidecar.h" GType gabble_sidecar_get_type (void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof (GabbleSidecarInterface), NULL, /* base_init */ NULL, /* base_finalize */ NULL, /* class_init */ NULL, /* class_finalize */ NULL, /* class_data */ 0, 0, /* n_preallocs */ NULL /* instance_init */ }; type = g_type_register_static (G_TYPE_INTERFACE, "GabbleSidecar", &info, 0); } return type; } const gchar * gabble_sidecar_get_interface (GabbleSidecar *sidecar) { GabbleSidecarInterface *iface = GABBLE_SIDECAR_GET_INTERFACE (sidecar); return iface->interface; } /** * gabble_sidecar_get_immutable_properties: * @sidecar: a sidecar object * * Retrieves the immutable properties for a sidecar, as a map from * fully-qualified property names to GValues containing the properties' values * (such as that created with tp_asv_new ()). * * Returns: a non-%NULL hash of @sidecar's immutable properties, which must be * unreffed but not modified by the caller. */ GHashTable * gabble_sidecar_get_immutable_properties (GabbleSidecar *sidecar) { GabbleSidecarInterface *iface = GABBLE_SIDECAR_GET_INTERFACE (sidecar); if (iface->get_immutable_properties) return iface->get_immutable_properties (sidecar); else return g_hash_table_new (NULL, NULL); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/vcard-manager.h���������������������������������������������������������0000664�0001750�0001750�00000014426�11720700311�021644� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * vcard-manager.h - vCard lookup helper for Gabble connections * * Copyright (C) 2006-2010 Collabora Ltd. * Copyright (C) 2006-2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_VCARD_MANAGER_H__ #define __GABBLE_VCARD_MANAGER_H__ #include <glib-object.h> #include <wocky/wocky.h> #include "types.h" G_BEGIN_DECLS typedef struct _GabbleVCardManagerPrivate GabbleVCardManagerPrivate; typedef struct _GabbleVCardManagerClass GabbleVCardManagerClass; typedef struct _GabbleVCardManagerRequest GabbleVCardManagerRequest; typedef struct _GabbleVCardManagerEditRequest GabbleVCardManagerEditRequest; typedef struct _GabbleVCardManagerEditInfo GabbleVCardManagerEditInfo; /** * GabbleVCardManagerError: * @GABBLE_VCARD_MANAGER_ERROR_CANCELLED: The vCard request was cancelled * @GABBLE_VCARD_MANAGER_ERROR_TIMEOUT: The vCard request timed out * @GABBLE_VCARD_MANAGER_ERROR_UNKNOWN: An unknown error occured */ typedef enum { GABBLE_VCARD_MANAGER_ERROR_CANCELLED, GABBLE_VCARD_MANAGER_ERROR_TIMEOUT, GABBLE_VCARD_MANAGER_ERROR_UNKNOWN } GabbleVCardManagerError; GQuark gabble_vcard_manager_error_quark (void); #define GABBLE_VCARD_MANAGER_ERROR gabble_vcard_manager_error_quark () GType gabble_vcard_manager_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_VCARD_MANAGER \ (gabble_vcard_manager_get_type ()) #define GABBLE_VCARD_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_VCARD_MANAGER, \ GabbleVCardManager)) #define GABBLE_VCARD_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_VCARD_MANAGER, \ GabbleVCardManagerClass)) #define GABBLE_IS_VCARD_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_VCARD_MANAGER)) #define GABBLE_IS_VCARD_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_VCARD_MANAGER)) #define GABBLE_VCARD_MANAGER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_VCARD_MANAGER, \ GabbleVCardManagerClass)) struct _GabbleVCardManagerClass { GObjectClass parent_class; }; struct _GabbleVCardManager { GObject parent; GabbleVCardManagerPrivate *priv; }; typedef enum { GABBLE_VCARD_EDIT_REPLACE, GABBLE_VCARD_EDIT_APPEND, GABBLE_VCARD_EDIT_DELETE, GABBLE_VCARD_EDIT_CLEAR, GABBLE_VCARD_EDIT_SET_ALIAS } GabbleVCardEditType; typedef void (*GabbleVCardManagerCb)(GabbleVCardManager *self, GabbleVCardManagerRequest *request, TpHandle handle, WockyNode *vcard, GError *error, gpointer user_data); GabbleVCardManager *gabble_vcard_manager_new (GabbleConnection *); GQuark gabble_vcard_manager_cache_quark (void); GabbleVCardManagerRequest *gabble_vcard_manager_request (GabbleVCardManager *, TpHandle, guint timeout, GabbleVCardManagerCb, gpointer user_data, GObject *object); void gabble_vcard_manager_cancel_request (GabbleVCardManager *manager, GabbleVCardManagerRequest *request); const gchar *gabble_vcard_manager_get_cached_alias (GabbleVCardManager *, TpHandle); gboolean gabble_vcard_manager_has_cached_alias (GabbleVCardManager *manager, TpHandle handle); gboolean gabble_vcard_manager_get_cached (GabbleVCardManager *, TpHandle, WockyNode **); void gabble_vcard_manager_invalidate_cache (GabbleVCardManager *, TpHandle); typedef void (*GabbleVCardManagerEditCb)(GabbleVCardManager *self, GabbleVCardManagerEditRequest *request, WockyNode *vcard, GError *error, gpointer user_data); GabbleVCardManagerEditRequest *gabble_vcard_manager_edit (GabbleVCardManager *, guint timeout, GabbleVCardManagerEditCb, gpointer user_data, GObject *object, GList *edits); void gabble_vcard_manager_remove_edit_request (GabbleVCardManagerEditRequest *); gchar *vcard_get_avatar_sha1 (WockyNode *vcard); GabbleVCardManagerEditInfo *gabble_vcard_manager_edit_info_new ( const gchar *element_name, const gchar *element_value, GabbleVCardEditType edit_type, ...) G_GNUC_NULL_TERMINATED; void gabble_vcard_manager_edit_info_add_child ( GabbleVCardManagerEditInfo *edit_info, const gchar *key, const gchar *value); void gabble_vcard_manager_edit_info_free (GabbleVCardManagerEditInfo *info); gboolean gabble_vcard_manager_has_limited_vcard_fields ( GabbleVCardManager *self); gboolean gabble_vcard_manager_can_use_vcard_field (GabbleVCardManager *self, const gchar *field_name); /* For unit tests only */ void gabble_vcard_manager_set_suspend_reply_timeout (guint timeout); void gabble_vcard_manager_set_default_request_timeout (guint timeout); G_END_DECLS #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/call-muc-channel.c������������������������������������������������������0000664�0001750�0001750�00000104274�12332440117�022241� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * call-muc-channel.c - Source for CallMucChannel * Copyright (C) 2010 Collabora Ltd. * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include <stdio.h> #include <stdlib.h> #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #include "call-content.h" #include "muc-channel.h" #include "call-muc-channel.h" #include "util.h" #include "namespaces.h" #include "jingle-tp-util.h" #define DEBUG_FLAG GABBLE_DEBUG_MEDIA #include "debug.h" static void async_initable_iface_init (GAsyncInitableIface *iface); static void call_muc_channel_accept (TpBaseMediaCallChannel *channel); static TpBaseCallContent * call_muc_channel_add_content ( TpBaseCallChannel *base, const gchar *name, TpMediaStreamType type, TpMediaStreamDirection initial_direction, GError **error); static void call_muc_channel_hangup ( TpBaseCallChannel *base, guint reason, const gchar *detailed_reason, const gchar *message); static void call_muc_channel_close (TpBaseChannel *base); G_DEFINE_TYPE_WITH_CODE (GabbleCallMucChannel, gabble_call_muc_channel, GABBLE_TYPE_BASE_CALL_CHANNEL, G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP, tp_external_group_mixin_iface_init)); typedef enum { STATE_NOT_JOINED = 0, /* Internally preparing before we can send muji information to the muc, only * happens on the initial join */ STATE_PREPARING, /* Sent the stanza with the preparing node */ STATE_PREPARING_SENT, /* We know when our turn is, now waiting for it */ STATE_WAIT_FOR_TURN, /* Our state matches the state we published */ STATE_STABLE, /* we left this muc */ STATE_LEFT, } MucCallState; enum { PROP_MUC = 1, }; /* private structure */ struct _GabbleCallMucChannelPrivate { gboolean dispose_has_run; GabbleMucChannel *muc; WockyMuc *wmuc; gboolean initialized; MucCallState state; /* The list of members who should sent an update before us */ GQueue *before; GQueue *after; /* List of members we should initial a session to after joining */ GQueue *sessions_to_open; gboolean sessions_opened; GQueue *new_contents; /* Our current muji information */ WockyNodeTree *muji; }; typedef struct { GabbleCallMucChannel *self; GSimpleAsyncResult *result; GCancellable *cancellable; gulong cancel_id; gulong ready_id; } ChannelInitialisation; static void channel_init_free (ChannelInitialisation *ci) { g_cancellable_disconnect (ci->cancellable, ci->cancel_id); tp_clear_object (&ci->cancellable); g_signal_handler_disconnect (ci->self->priv->muc, ci->ready_id); g_object_unref (ci->result); g_slice_free (ChannelInitialisation, ci); } static void gabble_call_muc_channel_init (GabbleCallMucChannel *self) { GabbleCallMucChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_CALL_MUC_CHANNEL, GabbleCallMucChannelPrivate); self->priv = priv; priv->before = g_queue_new (); priv->after = g_queue_new (); priv->sessions_to_open = g_queue_new (); priv->new_contents = g_queue_new (); } static void gabble_call_muc_channel_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleCallMucChannel *self = GABBLE_CALL_MUC_CHANNEL (object); GabbleCallMucChannelPrivate *priv = self->priv; switch (property_id) { case PROP_MUC: g_value_set_object (value, priv->muc); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_call_muc_channel_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleCallMucChannel *self = GABBLE_CALL_MUC_CHANNEL (object); GabbleCallMucChannelPrivate *priv = self->priv; switch (property_id) { case PROP_MUC: priv->muc = g_value_get_object (value); g_assert (priv->muc != NULL); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_call_muc_channel_dispose (GObject *object); static void gabble_call_muc_channel_finalize (GObject *object); static void gabble_call_muc_channel_constructed (GObject *obj) { GabbleCallMucChannel *self = GABBLE_CALL_MUC_CHANNEL (obj); tp_external_group_mixin_init (obj, G_OBJECT (self->priv->muc)); if (G_OBJECT_CLASS (gabble_call_muc_channel_parent_class)->constructed != NULL) G_OBJECT_CLASS (gabble_call_muc_channel_parent_class)->constructed (obj); } static void gabble_call_muc_channel_class_init ( GabbleCallMucChannelClass *gabble_call_muc_channel_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_call_muc_channel_class); TpBaseMediaCallChannelClass *base_media_call_class = TP_BASE_MEDIA_CALL_CHANNEL_CLASS (gabble_call_muc_channel_class); TpBaseCallChannelClass *base_call_class = TP_BASE_CALL_CHANNEL_CLASS (gabble_call_muc_channel_class); TpBaseChannelClass *base_channel_class = TP_BASE_CHANNEL_CLASS (gabble_call_muc_channel_class); GParamSpec *param_spec; g_type_class_add_private (gabble_call_muc_channel_class, sizeof (GabbleCallMucChannelPrivate)); object_class->set_property = gabble_call_muc_channel_set_property; object_class->get_property = gabble_call_muc_channel_get_property; object_class->constructed = gabble_call_muc_channel_constructed; object_class->dispose = gabble_call_muc_channel_dispose; object_class->finalize = gabble_call_muc_channel_finalize; base_channel_class->target_handle_type = TP_HANDLE_TYPE_ROOM; base_channel_class->close = call_muc_channel_close; base_call_class->add_content = call_muc_channel_add_content; base_call_class->hangup = call_muc_channel_hangup; base_media_call_class->accept = call_muc_channel_accept; param_spec = g_param_spec_object ("muc", "GabbleMuc object", "The muc to which this call is related", GABBLE_TYPE_MUC_CHANNEL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_MUC, param_spec); tp_external_group_mixin_init_dbus_properties (object_class); } void gabble_call_muc_channel_dispose (GObject *object) { GabbleCallMucChannel *self = GABBLE_CALL_MUC_CHANNEL (object); GabbleCallMucChannelPrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; tp_clear_object (&priv->wmuc); tp_clear_object (&priv->muji); tp_external_group_mixin_finalize (object); /* release any references held by the object here */ if (G_OBJECT_CLASS (gabble_call_muc_channel_parent_class)->dispose) G_OBJECT_CLASS (gabble_call_muc_channel_parent_class)->dispose (object); } void gabble_call_muc_channel_finalize (GObject *object) { GabbleCallMucChannel *self = GABBLE_CALL_MUC_CHANNEL (object); GabbleCallMucChannelPrivate *priv = self->priv; /* free any data held directly by the object here */ g_queue_free (priv->before); g_queue_free (priv->after); g_queue_free (priv->sessions_to_open); g_queue_free (priv->new_contents); G_OBJECT_CLASS (gabble_call_muc_channel_parent_class)->finalize (object); } static gboolean call_muc_channel_got_codecs (GabbleCallMucChannel *self) { GList *l; for (l = tp_base_call_channel_get_contents ( TP_BASE_CALL_CHANNEL (self)); l != NULL; l = g_list_next (l)) { TpBaseMediaCallContent *content = TP_BASE_MEDIA_CALL_CONTENT (l->data); GHashTable *tp_md; GPtrArray *codecs; /* FIXME: remote_contact==0 ??? */ tp_md = tp_base_media_call_content_get_local_media_description (content, 0); codecs = tp_asv_get_boxed (tp_md, TP_PROP_CALL_CONTENT_MEDIA_DESCRIPTION_CODECS, TP_ARRAY_TYPE_CODEC_LIST); if (codecs == NULL) return FALSE; } return TRUE; } /* Decide on what to do next for an update */ static void call_muc_do_update (GabbleCallMucChannel *self) { GabbleCallMucChannelPrivate *priv = self->priv; MucCallState old = priv->state; switch (priv->state) { case STATE_NOT_JOINED: case STATE_PREPARING_SENT: case STATE_WAIT_FOR_TURN: /* we either didn't want to join yet or are already in the progress of * doing one, no need to take action */ break; case STATE_PREPARING: g_assert (priv->muji == NULL); if (!call_muc_channel_got_codecs (self)) { DEBUG ("Postponing sending prepare, waiting for codecs"); break; } priv->muji = wocky_node_tree_new ("muji", NS_MUJI, NULL); /* fall through */ case STATE_STABLE: /* Start preparation of the next round */ g_assert (priv->muji != NULL); wocky_node_add_child (wocky_node_tree_get_top_node (priv->muji), "preparing"); priv->state = STATE_PREPARING_SENT; gabble_muc_channel_send_presence (priv->muc); break; case STATE_LEFT: /* we left not doing anything */ break; } DEBUG ("Updated muji state %d -> %d", old, priv->state); } static void call_muc_channel_content_local_media_description_updated ( GabbleCallContent *content, TpHandle contact, GHashTable *properties, gpointer user_data) { GabbleCallMucChannel *self = GABBLE_CALL_MUC_CHANNEL (user_data); DEBUG ("Local codecs of a content updated"); call_muc_do_update (self); } static void call_muc_channel_open_new_streams (GabbleCallMucChannel *self) { GabbleCallMucChannelPrivate *priv = self->priv; GabbleCallMember *m; GabbleCallContent *c; if (!priv->sessions_opened) { /* At the point where we opened the sessions we're accepted in the call */ tp_base_call_channel_set_state (TP_BASE_CALL_CHANNEL (self), TP_CALL_STATE_ACCEPTED, 0, TP_CALL_STATE_CHANGE_REASON_PROGRESS_MADE, "", ""); } priv->sessions_opened = TRUE; while ((m = g_queue_pop_head (priv->sessions_to_open)) != NULL) gabble_call_member_open_session (m, NULL); while ((c = g_queue_pop_head (priv->new_contents)) != NULL) { GList *l; l = gabble_call_content_get_member_contents (c); for (; l != NULL; l = g_list_next (l)) { gabble_call_member_content_add_to_session ( GABBLE_CALL_MEMBER_CONTENT (l->data)); } } } static void call_muc_channel_setup_content (GabbleCallMucChannel *self, GabbleCallContent *content) { GabbleCallMucChannelPrivate *priv = self->priv; DEBUG ("Setting up content"); gabble_signal_connect_weak (content, "local-media-description-updated", G_CALLBACK (call_muc_channel_content_local_media_description_updated), G_OBJECT (self)); if (priv->sessions_opened) g_queue_push_tail (priv->new_contents, content); gabble_call_content_new_offer (content, NULL); } static void call_muc_channel_member_content_added_cb (GabbleCallMember *member, GabbleCallMemberContent *content, gpointer user_data) { GabbleCallMucChannel *self = GABBLE_CALL_MUC_CHANNEL (user_data); const gchar *name; WockyJingleMediaType mtype; GList *l; GabbleCallContent *ccontent; /* A new content was added for one of the members, match it up with the call * channels contents */ name = gabble_call_member_content_get_name (content); mtype = gabble_call_member_content_get_media_type (content); DEBUG ("New call member content: %s (type: %d)", name, mtype); for (l = tp_base_call_channel_get_contents ( TP_BASE_CALL_CHANNEL (self)); l != NULL; l = g_list_next (l)) { const char *cname; WockyJingleMediaType cmtype; ccontent = GABBLE_CALL_CONTENT (l->data); cname = tp_base_call_content_get_name ( TP_BASE_CALL_CONTENT (ccontent)); cmtype = gabble_call_content_get_media_type (ccontent); if (!tp_strdiff (cname, name) && mtype == cmtype) goto have_content; } ccontent = gabble_base_call_channel_add_content ( GABBLE_BASE_CALL_CHANNEL (self), name, mtype, self->priv->initialized ? TP_CALL_CONTENT_DISPOSITION_INITIAL : 0); call_muc_channel_setup_content (self, ccontent); have_content: gabble_call_content_add_member_content (ccontent, content); } static GList * call_muc_channel_parse_codecs (GabbleCallMucChannel *self, WockyNode *description) { GList *codecs = NULL; WockyNodeIter iter; WockyNode *payload; wocky_node_iter_init (&iter, description, "payload-type", NS_JINGLE_RTP); while (wocky_node_iter_next (&iter, &payload)) { const gchar *name; const gchar *value; guint id; guint clockrate = 0; guint channels = 0; WockyJingleCodec *codec; WockyNodeIter param_iter; WockyNode *parameter; value = wocky_node_get_attribute (payload, "id"); if (value == NULL) continue; id = atoi (value); name = wocky_node_get_attribute (payload, "name"); if (name == NULL) continue; value = wocky_node_get_attribute (payload, "clockrate"); if (value != NULL) clockrate = atoi (value); value = wocky_node_get_attribute (payload, "channels"); if (value != NULL) channels = atoi (value); codec = jingle_media_rtp_codec_new (id, name, clockrate, channels, NULL); codecs = g_list_append (codecs, codec); wocky_node_iter_init (¶m_iter, payload, "parameter", NS_JINGLE_RTP); while (wocky_node_iter_next (¶m_iter, ¶meter)) { const gchar *key; key = wocky_node_get_attribute (parameter, "name"); value = wocky_node_get_attribute (parameter, "value"); if (key == NULL || value == NULL) continue; g_hash_table_insert (codec->params, g_strdup (key), g_strdup (value)); } } return codecs; } static void call_muc_channel_send_new_state (GabbleCallMucChannel *self) { GabbleCallMucChannelPrivate *priv = self->priv; /* Our turn! */ GQueue *t; WockyNode *m; GList *l; /* switch the before and after queues */ t = priv->before; priv->before = priv->after; priv->after = t; g_object_unref (priv->muji); priv->muji = wocky_node_tree_new ("muji", NS_MUJI, '*', &m, NULL); for (l = tp_base_call_channel_get_contents ( TP_BASE_CALL_CHANNEL (self)); l != NULL; l = g_list_next (l)) { GabbleCallContent *content = GABBLE_CALL_CONTENT (l->data); const gchar *name = tp_base_call_content_get_name ( TP_BASE_CALL_CONTENT (content)); WockyNode *description; GHashTable *tp_md; GPtrArray *codecs; guint i; WockyJingleMediaType mtype = gabble_call_content_get_media_type (content); wocky_node_add_build (m, '(', "content", '@', "name", name, '(', "description", ':', NS_JINGLE_RTP, '*', &description, '@', "media", mtype == WOCKY_JINGLE_MEDIA_TYPE_AUDIO ? "audio" : "video", ')', ')', NULL); /* FIXME: remote_contact==0 ??? */ tp_md = tp_base_media_call_content_get_local_media_description ( TP_BASE_MEDIA_CALL_CONTENT (content), 0); codecs = tp_asv_get_boxed (tp_md, TP_PROP_CALL_CONTENT_MEDIA_DESCRIPTION_CODECS, TP_ARRAY_TYPE_CODEC_LIST); for (i = 0; i < codecs->len; i++) { GValueArray *codec = g_ptr_array_index (codecs, i); WockyNode *pt; GHashTableIter iter; gpointer key, value; gchar *idstr; guint v; idstr = g_strdup_printf ("%d", g_value_get_uint (codec->values)); wocky_node_add_build (description, '(', "payload-type", '*', &pt, '@', "id", idstr, '@', "name", g_value_get_string (codec->values + 1), ')', NULL); g_free (idstr); /* clock-rate */ v = g_value_get_uint (codec->values + 2); if (v > 0) { gchar *rate = g_strdup_printf ("%d", v); wocky_node_set_attribute (pt, "clockrate", rate); g_free (rate); } /* channels */ v = g_value_get_uint (codec->values + 3); if (v > 0) { gchar *channels = g_strdup_printf ("%d", v); wocky_node_set_attribute (pt, "channels", channels); g_free (channels); } g_hash_table_iter_init (&iter, g_value_get_boxed (codec->values + 5)); while (g_hash_table_iter_next (&iter, &key, &value)) wocky_node_add_build (pt, '(', "parameter", '@', "name", (gchar *) key, '@', "value", (gchar *) value, ')', NULL); } } priv->state = STATE_STABLE; gabble_muc_channel_send_presence (priv->muc); } static void call_muc_channel_parse_participant (GabbleCallMucChannel *self, GabbleCallMember *member, WockyNode *muji) { GabbleCallMucChannelPrivate *priv = self->priv; WockyNodeIter iter; WockyNode *content; wocky_node_iter_init (&iter, muji, "content", NS_MUJI); while (wocky_node_iter_next (&iter, &content)) { GabbleCallMemberContent *member_content; WockyNode *description; WockyJingleMediaType mtype; const gchar *name; const gchar *mattr; GList *codecs; name = wocky_node_get_attribute (content, "name"); if (name == NULL) { DEBUG ("Content is missing the name attribute"); continue; } DEBUG ("Parsing content: %s", name); description = wocky_node_get_child (content, "description"); if (description == NULL) { DEBUG ("Content %s is missing a description", name); continue; } mattr = wocky_node_get_attribute (description, "media"); if (mattr == NULL) { DEBUG ("Content %s is missing a media type", name); continue; } if (!tp_strdiff (mattr, "video")) { mtype = WOCKY_JINGLE_MEDIA_TYPE_VIDEO; } else if (!tp_strdiff (mattr, "audio")) { mtype = WOCKY_JINGLE_MEDIA_TYPE_AUDIO; } else { DEBUG ("Content %s has an unknown media type: %s", name, mattr); continue; } member_content = gabble_call_member_ensure_content (member, name, mtype); if (gabble_call_member_content_has_jingle_content (member_content)) continue; codecs = call_muc_channel_parse_codecs (self, description); gabble_call_member_content_set_remote_codecs (member_content, codecs); if (!priv->initialized) { if (mtype == WOCKY_JINGLE_MEDIA_TYPE_AUDIO) g_object_set (self, "initial-audio", TRUE, NULL); else g_object_set (self, "initial-video", TRUE, NULL); } } } static void call_muc_channel_remove_member (GabbleCallMucChannel *self, GabbleCallMember *call_member) { GabbleCallMucChannelPrivate *priv = self->priv; g_queue_remove (priv->before, call_member); g_queue_remove (priv->after, call_member); g_queue_remove (priv->sessions_to_open, call_member); gabble_base_call_channel_remove_member ( GABBLE_BASE_CALL_CHANNEL (self), call_member); } static void call_muc_channel_got_participant_presence (GabbleCallMucChannel *self, WockyMucMember *member, WockyStanza *stanza) { GabbleCallMucChannelPrivate *priv = self->priv; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( tp_base_channel_get_connection (TP_BASE_CHANNEL (self)), TP_HANDLE_TYPE_CONTACT); GabbleCallMember *call_member; TpHandle handle; WockyNode *muji; muji = wocky_node_get_child_ns ( wocky_stanza_get_top_node (stanza), "muji", NS_MUJI); DEBUG ("Muji participant: %s", member->from); handle = tp_handle_ensure (contact_repo, member->from, NULL, NULL); call_member = gabble_base_call_channel_get_member_from_handle ( GABBLE_BASE_CALL_CHANNEL (self), handle); if (muji == NULL) { /* Member without muji information remove it if needed otherwise ignore */ if (call_member != NULL) call_muc_channel_remove_member (self, call_member); return; } if (call_member == NULL) { call_member = gabble_base_call_channel_ensure_member_from_handle ( GABBLE_BASE_CALL_CHANNEL (self), handle); gabble_signal_connect_weak (call_member, "content-added", G_CALLBACK (call_muc_channel_member_content_added_cb), G_OBJECT (self)); gabble_call_member_accept (call_member); } if (!priv->sessions_opened && priv->state < STATE_WAIT_FOR_TURN) g_queue_push_tail (priv->sessions_to_open, call_member); call_muc_channel_parse_participant (self, call_member, muji); if (wocky_node_get_child (muji, "preparing")) { /* remote member is preparing something, add to the right queue */ if (!g_queue_find (priv->before, call_member) && !g_queue_find (priv->after, call_member)) { g_queue_push_tail ( priv->state != STATE_WAIT_FOR_TURN ? priv->before : priv->after, call_member); } } else { /* remote member isn't preparing or at least not anymore */ g_queue_remove (priv->before, call_member); g_queue_remove (priv->after, call_member); if (priv->state == STATE_WAIT_FOR_TURN && g_queue_is_empty (priv->before)) { call_muc_channel_send_new_state (self); } } } static void call_muc_channel_presence_cb (WockyMuc *wmuc, WockyStanza *stanza, guint codes, WockyMucMember *who, gpointer user_data) { GabbleCallMucChannel *self = GABBLE_CALL_MUC_CHANNEL (user_data); call_muc_channel_got_participant_presence (self, who, stanza); } static void call_muc_channel_left_cb (GObject *source, WockyStanza *stanza, guint codes, WockyMucMember *member, const gchar *actor_jid, const gchar *why, const gchar *msg, gpointer user_data) { GabbleCallMucChannel *self = GABBLE_CALL_MUC_CHANNEL (user_data); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( tp_base_channel_get_connection (TP_BASE_CHANNEL (self)), TP_HANDLE_TYPE_CONTACT); TpHandle handle; GabbleCallMember *call_member; handle = tp_handle_ensure (contact_repo, member->from, NULL, NULL); call_member = gabble_base_call_channel_get_member_from_handle ( GABBLE_BASE_CALL_CHANNEL (self), handle); DEBUG ("%s left the room, %p", member->from, call_member); if (call_member != NULL) call_muc_channel_remove_member (self, call_member); } static void call_muc_channel_update_all_members (GabbleCallMucChannel *self) { GabbleCallMucChannelPrivate *priv = self->priv; GHashTable *members; GHashTableIter iter; gpointer value; members = wocky_muc_members (priv->wmuc); g_hash_table_iter_init (&iter, members); while (g_hash_table_iter_next (&iter, NULL, &value)) { WockyMucMember *member = (WockyMucMember *) value; call_muc_channel_got_participant_presence (self, member, member->presence_stanza); } g_hash_table_unref (members); } static void call_muc_channel_joined_cb (WockyMuc *muc, WockyStanza *stanza, guint codes, gpointer user_data) { GabbleCallMucChannel *self = GABBLE_CALL_MUC_CHANNEL (user_data); call_muc_channel_update_all_members (self); } static void call_muc_channel_pre_presence_cb (WockyMuc *wmuc, WockyStanza *stanza, gpointer user_data) { GabbleCallMucChannel *self = GABBLE_CALL_MUC_CHANNEL (user_data); if (self->priv->muji == NULL) return; wocky_node_add_node_tree (wocky_stanza_get_top_node (stanza), self->priv->muji); } static void call_muc_channel_own_presence_cb (WockyMuc *wmuc, WockyStanza *stanza, guint codes, gpointer user_data) { GabbleCallMucChannel *self = GABBLE_CALL_MUC_CHANNEL (user_data); GabbleCallMucChannelPrivate *priv = self->priv; WockyNode *muji; DEBUG ("Got our own presence"); muji = wocky_node_get_child_ns ( wocky_stanza_get_top_node (stanza), "muji", NS_MUJI); /* If our presence didn't have a muji stanza or had an older version we don't * care about it */ if (muji == NULL || priv->muji == NULL || !wocky_node_equal (muji, wocky_node_tree_get_top_node (priv->muji))) return; switch (priv->state) { case STATE_PREPARING_SENT: DEBUG ("Got our preperation message, now waiting for our turn"); priv->state = STATE_WAIT_FOR_TURN; if (g_queue_is_empty (priv->before)) call_muc_channel_send_new_state (self); break; case STATE_WAIT_FOR_TURN: break; case STATE_STABLE: call_muc_channel_open_new_streams (self); break; default: DEBUG ("Got a muji presence from ourselves before we sent one ?!"); } } static void call_muc_channel_ready (GabbleCallMucChannel *self) { GabbleCallMucChannelPrivate *priv = self->priv; g_object_get (priv->muc, "wocky-muc", &(priv->wmuc), NULL); g_assert (priv->wmuc != NULL); if (wocky_muc_get_state (priv->wmuc) == WOCKY_MUC_JOINED) call_muc_channel_update_all_members (self); /* we care about presences */ gabble_signal_connect_weak (priv->wmuc, "joined", G_CALLBACK (call_muc_channel_joined_cb), G_OBJECT (self)); gabble_signal_connect_weak (priv->wmuc, "presence", G_CALLBACK (call_muc_channel_presence_cb), G_OBJECT (self)); gabble_signal_connect_weak (priv->wmuc, "own-presence", G_CALLBACK (call_muc_channel_own_presence_cb), G_OBJECT (self)); gabble_signal_connect_weak (priv->wmuc, "left", G_CALLBACK (call_muc_channel_left_cb), G_OBJECT (self)); gabble_signal_connect_weak (priv->muc, "pre-presence", G_CALLBACK (call_muc_channel_pre_presence_cb), G_OBJECT (self)); priv->initialized = TRUE; tp_base_channel_register (TP_BASE_CHANNEL (self)); } static void call_muc_channel_cancelled_cb (GCancellable *cancellable, gpointer user_data) { ChannelInitialisation *ci = user_data; DEBUG ("Cancelled"); g_simple_async_result_set_error (ci->result, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Channel request was cancelled"); g_simple_async_result_complete (ci->result); /* called, don't disconnect */ ci->cancel_id = 0; channel_init_free (ci); } static void call_muc_channel_ready_cb (GabbleMucChannel *muc, gpointer user_data) { ChannelInitialisation *ci = user_data; DEBUG ("Happy muc"); call_muc_channel_ready (ci->self); g_simple_async_result_complete (ci->result); channel_init_free (ci); } static void call_muc_channel_init_async (GAsyncInitable *initable, int priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GabbleCallMucChannel *self = GABBLE_CALL_MUC_CHANNEL (initable); GabbleCallMucChannelPrivate *priv = self->priv; TpBaseCallChannel *base = TP_BASE_CALL_CHANNEL (self); GabbleCallContent *content; GSimpleAsyncResult *result; gboolean initial_audio, initial_video; const gchar *initial_audio_name, *initial_video_name; initial_audio = tp_base_call_channel_has_initial_audio (base, &initial_audio_name); initial_video = tp_base_call_channel_has_initial_video (base, &initial_video_name); result = g_simple_async_result_new (G_OBJECT (initable), callback, user_data, NULL); if (initial_audio) { content = gabble_base_call_channel_add_content ( GABBLE_BASE_CALL_CHANNEL (base), initial_audio_name, WOCKY_JINGLE_MEDIA_TYPE_AUDIO, TP_CALL_CONTENT_DISPOSITION_INITIAL); call_muc_channel_setup_content (self, content); } if (initial_video) { content = gabble_base_call_channel_add_content ( GABBLE_BASE_CALL_CHANNEL (base), initial_video_name, WOCKY_JINGLE_MEDIA_TYPE_VIDEO, TP_CALL_CONTENT_DISPOSITION_INITIAL); call_muc_channel_setup_content (self, content); } if (_gabble_muc_channel_is_ready (priv->muc)) { DEBUG ("Muc channel is ready to fly"); call_muc_channel_ready (self); g_simple_async_result_complete_in_idle (result); g_object_unref (result); } else { ChannelInitialisation *ci = g_slice_new0 (ChannelInitialisation); DEBUG ("Muc channel isn't ready yet"); ci->self = self; ci->result = result; ci->ready_id = g_signal_connect (priv->muc, "ready", G_CALLBACK (call_muc_channel_ready_cb), ci); if (cancellable != NULL) { ci->cancellable = g_object_ref (cancellable); ci->cancel_id = g_cancellable_connect (cancellable, G_CALLBACK (call_muc_channel_cancelled_cb), ci, NULL); } } } static void async_initable_iface_init (GAsyncInitableIface *iface) { iface->init_async = call_muc_channel_init_async; } void gabble_call_muc_channel_new_async (GabbleConnection *connection, GCancellable *cancellable, const gchar *path_prefix, GabbleMucChannel *muc, TpHandle target, GHashTable *request, GAsyncReadyCallback callback, gpointer user_data) { gboolean initial_audio = FALSE; gboolean initial_video = FALSE; const gchar *initial_audio_name = NULL; const gchar *initial_video_name = NULL; DEBUG ("Starting initialisation of a Muji call channel"); if (request != NULL) { initial_audio = tp_asv_get_boolean (request, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO, NULL); initial_video = tp_asv_get_boolean (request, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO, NULL); initial_audio_name = tp_asv_get_string (request, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_AUDIO_NAME); initial_video_name = tp_asv_get_string (request, TP_PROP_CHANNEL_TYPE_CALL_INITIAL_VIDEO_NAME); } g_async_initable_new_async (GABBLE_TYPE_CALL_MUC_CHANNEL, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "muc", muc, "object-path-prefix", path_prefix, "connection", connection, "handle", target, "requested", request != NULL, "mutable-contents", TRUE, "initial-audio", initial_audio, "initial-audio-name", initial_audio_name != NULL ? initial_audio_name : "audio", "initial-video", initial_video, "initial-video-name", initial_video_name != NULL ? initial_video_name : "video", NULL); } GabbleCallMucChannel * gabble_call_muc_channel_new_finish (GObject *source, GAsyncResult *result, GError **error) { GObject *o; o = g_async_initable_new_finish (G_ASYNC_INITABLE (source), result, error); return o != NULL ? GABBLE_CALL_MUC_CHANNEL (o) : NULL; } void gabble_call_muc_channel_incoming_session (GabbleCallMucChannel *self, WockyJingleSession *session) { GabbleCallMember *member; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( tp_base_channel_get_connection (TP_BASE_CHANNEL (self)), TP_HANDLE_TYPE_CONTACT); const gchar *jid = wocky_jingle_session_get_peer_jid (session); TpHandle peer = tp_handle_ensure (contact_repo, jid, NULL, NULL); DEBUG ("New incoming session from %s", jid); member = gabble_base_call_channel_get_member_from_handle ( GABBLE_BASE_CALL_CHANNEL (self), peer); if (member == NULL || gabble_call_member_get_session (member) != NULL) { wocky_jingle_session_terminate (session, WOCKY_JINGLE_REASON_UNKNOWN, "Muji jingle session initiated while there already was one", NULL); } else { gabble_call_member_set_session (member, session); } } static void call_muc_channel_accept (TpBaseMediaCallChannel *channel) { GabbleCallMucChannel *self = GABBLE_CALL_MUC_CHANNEL (channel); if (self->priv->state != STATE_NOT_JOINED) return; DEBUG ("Accepted muji channel"); /* Start preparing to join the conference */ self->priv->state = STATE_PREPARING; call_muc_do_update (self); } static TpBaseCallContent * call_muc_channel_add_content (TpBaseCallChannel *base, const gchar *name, TpMediaStreamType type, TpMediaStreamDirection initial_direction, GError **error) { GabbleCallMucChannel *self = GABBLE_CALL_MUC_CHANNEL (base); GabbleCallContent *content; if (initial_direction == TP_MEDIA_STREAM_DIRECTION_NONE) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Jingle can not do contents with direction = NONE"); return NULL; } if (initial_direction != TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "Adding un-directional contents is not supported" " in MUC channels"); return NULL; } content = gabble_base_call_channel_add_content ( GABBLE_BASE_CALL_CHANNEL (base), name, wocky_jingle_media_type_from_tp (type), TP_CALL_CONTENT_DISPOSITION_NONE); call_muc_channel_setup_content (self, content); return TP_BASE_CALL_CONTENT (content); } static void call_muc_channel_leave (GabbleCallMucChannel *self) { GabbleCallMucChannelPrivate *priv = self->priv; if (priv->state == STATE_LEFT) return; tp_clear_object (&priv->muji); priv->state = STATE_LEFT; gabble_muc_channel_send_presence (priv->muc); } static void call_muc_channel_hangup (TpBaseCallChannel *base, guint reason, const gchar *detailed_reason, const gchar *message) { TpBaseCallChannelClass *parent = TP_BASE_CALL_CHANNEL_CLASS ( gabble_call_muc_channel_parent_class); call_muc_channel_leave (GABBLE_CALL_MUC_CHANNEL (base)); if (parent->hangup != NULL) parent->hangup (base, reason, detailed_reason, message); } static void call_muc_channel_close (TpBaseChannel *base) { call_muc_channel_leave (GABBLE_CALL_MUC_CHANNEL (base)); TP_BASE_CHANNEL_CLASS (gabble_call_muc_channel_parent_class)->close (base); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/tls-certificate.h�������������������������������������������������������0000664�0001750�0001750�00000004405�12332440117�022220� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * tls-certificate.h - Header for GabbleTLSCertificate * Copyright (C) 2010 Collabora Ltd. * @author Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_TLS_CERTIFICATE_H__ #define __GABBLE_TLS_CERTIFICATE_H__ #include <glib-object.h> #include <telepathy-glib/telepathy-glib.h> G_BEGIN_DECLS typedef struct _GabbleTLSCertificate GabbleTLSCertificate; typedef struct _GabbleTLSCertificateClass GabbleTLSCertificateClass; typedef struct _GabbleTLSCertificatePrivate GabbleTLSCertificatePrivate; struct _GabbleTLSCertificateClass { GObjectClass parent_class; TpDBusPropertiesMixinClass dbus_props_class; }; struct _GabbleTLSCertificate { GObject parent; GabbleTLSCertificatePrivate *priv; }; GType gabble_tls_certificate_get_type (void); #define GABBLE_TYPE_TLS_CERTIFICATE \ (gabble_tls_certificate_get_type ()) #define GABBLE_TLS_CERTIFICATE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_TLS_CERTIFICATE, \ GabbleTLSCertificate)) #define GABBLE_TLS_CERTIFICATE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_TLS_CERTIFICATE, \ GabbleTLSCertificateClass)) #define GABBLE_IS_TLS_CERTIFICATE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_TLS_CERTIFICATE)) #define GABBLE_IS_TLS_CERTIFICATE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_TLS_CERTIFICATE)) #define GABBLE_TLS_CERTIFICATE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_TLS_CERTIFICATE, \ GabbleTLSCertificateClass)) G_END_DECLS #endif /* #ifndef __GABBLE_TLS_CERTIFICATE_H__*/ �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/roster.h����������������������������������������������������������������0000664�0001750�0001750�00000004607�12223562023�020460� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * roster.h - Headers for Gabble roster helper * * Copyright © 2006–2010 Collabora Ltd. * Copyright © 2006–2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __ROSTER_H__ #define __ROSTER_H__ #include <glib-object.h> #include <telepathy-glib/telepathy-glib.h> #include "types.h" G_BEGIN_DECLS typedef struct _GabbleRosterPrivate GabbleRosterPrivate; typedef struct _GabbleRosterClass GabbleRosterClass; GType gabble_roster_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_ROSTER \ (gabble_roster_get_type ()) #define GABBLE_ROSTER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_ROSTER, GabbleRoster)) #define GABBLE_ROSTER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_ROSTER, GabbleRosterClass)) #define GABBLE_IS_ROSTER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_ROSTER)) #define GABBLE_IS_ROSTER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_ROSTER)) #define GABBLE_ROSTER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_ROSTER, GabbleRosterClass)) struct _GabbleRosterClass { TpBaseContactListClass parent_class; }; struct _GabbleRoster { TpBaseContactList parent; GabbleRosterPrivate *priv; }; GabbleRoster *gabble_roster_new (GabbleConnection *); gboolean gabble_roster_handle_sends_presence_to_us (GabbleRoster *, TpHandle); gboolean gabble_roster_handle_gets_presence_from_us (GabbleRoster *, TpHandle); const gchar *gabble_roster_handle_get_name (GabbleRoster *, TpHandle); gboolean gabble_roster_handle_set_name (GabbleRoster *, TpHandle, const gchar *, GError **); gboolean gabble_roster_handle_has_entry (GabbleRoster *, TpHandle); G_END_DECLS #endif /* __ROSTER_H__ */ �������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/ft-manager.c������������������������������������������������������������0000664�0001750�0001750�00000076701�12332441362�021165� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * ft-manager.c - Source for GabbleFtManager * Copyright (C) 2009-2010 Collabora Ltd. * @author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #define _BSD_SOURCE #define _XOPEN_SOURCE /* glibc2 needs this */ #include <time.h> #include <dbus/dbus-glib.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <glib/gstdio.h> #ifdef ENABLE_JINGLE_FILE_TRANSFER #include "jingle-share.h" #endif #include "gabble/caps-channel-manager.h" #include "connection.h" #include "ft-manager.h" #include "ft-channel.h" #include "gabble-signals-marshal.h" #include "namespaces.h" #include "presence-cache.h" #include "util.h" #include <wocky/wocky.h> #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #define DEBUG_FLAG GABBLE_DEBUG_FT #include "debug.h" static void channel_manager_iface_init (gpointer, gpointer); static void gabble_ft_manager_channel_created (GabbleFtManager *mgr, GabbleFileTransferChannel *chan, gpointer request_token); static void caps_channel_manager_iface_init (gpointer g_iface, gpointer iface_data); G_DEFINE_TYPE_WITH_CODE (GabbleFtManager, gabble_ft_manager, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER, channel_manager_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_CAPS_CHANNEL_MANAGER, caps_channel_manager_iface_init)); /* properties */ enum { PROP_CONNECTION = 1, LAST_PROPERTY }; /* private structure */ struct _GabbleFtManagerPrivate { gboolean dispose_has_run; GabbleConnection *connection; GList *channels; /* path of the temporary directory used to store UNIX sockets */ gchar *tmp_dir; gulong status_changed_id; }; static void gabble_ft_manager_init (GabbleFtManager *obj) { obj->priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, GABBLE_TYPE_FT_MANAGER, GabbleFtManagerPrivate); obj->priv->connection = NULL; /* allocate any data required by the object here */ obj->priv->channels = NULL; } static void gabble_ft_manager_constructed (GObject *object); static void gabble_ft_manager_dispose (GObject *object); static void gabble_ft_manager_finalize (GObject *object); static void connection_status_changed_cb (GabbleConnection *conn, guint status, guint reason, GabbleFtManager *self); static void gabble_ft_manager_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleFtManager *self = GABBLE_FT_MANAGER (object); switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, self->priv->connection); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_ft_manager_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleFtManager *self = GABBLE_FT_MANAGER (object); switch (property_id) { case PROP_CONNECTION: self->priv->connection = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_ft_manager_class_init (GabbleFtManagerClass *gabble_ft_manager_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_ft_manager_class); GParamSpec *param_spec; g_type_class_add_private (gabble_ft_manager_class, sizeof (GabbleFtManagerPrivate)); object_class->constructed = gabble_ft_manager_constructed; object_class->get_property = gabble_ft_manager_get_property; object_class->set_property = gabble_ft_manager_set_property; object_class->dispose = gabble_ft_manager_dispose; object_class->finalize = gabble_ft_manager_finalize; param_spec = g_param_spec_object ("connection", "GabbleConnection object", "Gabble Connection that owns the connection for this FT manager", GABBLE_TYPE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); } static void gabble_ft_manager_constructed (GObject *object) { void (*chain_up) (GObject *) = G_OBJECT_CLASS (gabble_ft_manager_parent_class)->constructed; GabbleFtManager *self = GABBLE_FT_MANAGER (object); if (chain_up != NULL) chain_up (object); self->priv->status_changed_id = g_signal_connect (self->priv->connection, "status-changed", (GCallback) connection_status_changed_cb, object); } static void ft_manager_close_all (GabbleFtManager *self) { GList *l; while ((l = self->priv->channels) != NULL) { tp_base_channel_close (l->data); /* Channels should have closed and disappeared from the list */ g_assert (l != self->priv->channels); } } void gabble_ft_manager_dispose (GObject *object) { GabbleFtManager *self = GABBLE_FT_MANAGER (object); if (self->priv->dispose_has_run) return; self->priv->dispose_has_run = TRUE; g_assert (self->priv->channels == NULL); if (G_OBJECT_CLASS (gabble_ft_manager_parent_class)->dispose) G_OBJECT_CLASS (gabble_ft_manager_parent_class)->dispose (object); } void gabble_ft_manager_finalize (GObject *object) { GabbleFtManager *self = GABBLE_FT_MANAGER (object); if (self->priv->tmp_dir != NULL) { if (g_rmdir (self->priv->tmp_dir) != 0) { DEBUG ("rmdir failed: %s", g_strerror (errno)); } } g_free (self->priv->tmp_dir); G_OBJECT_CLASS (gabble_ft_manager_parent_class)->finalize (object); } /* Channel Manager interface */ struct foreach_data { TpExportableChannelFunc func; gpointer data; }; static void gabble_ft_manager_iface_foreach_one (gpointer value, gpointer data) { TpExportableChannel *chan; struct foreach_data *f = (struct foreach_data *) data; chan = TP_EXPORTABLE_CHANNEL (value); f->func (chan, f->data); } static void gabble_ft_manager_foreach_channel (TpChannelManager *iface, TpExportableChannelFunc func, gpointer data) { GabbleFtManager *self = GABBLE_FT_MANAGER (iface); struct foreach_data f; f.func = func; f.data = data; g_list_foreach (self->priv->channels, (GFunc) gabble_ft_manager_iface_foreach_one, &f); } static void file_channel_closed_cb (GabbleFileTransferChannel *chan, gpointer user_data) { GabbleFtManager *self = GABBLE_FT_MANAGER (user_data); if (self->priv->channels != NULL) { gchar *path, *id; g_object_get (chan, "target-id", &id, "object-path", &path, NULL); DEBUG ("Removing channel %s with %s", path, id); self->priv->channels = g_list_remove (self->priv->channels, chan); g_object_unref (chan); g_free (id); g_free (path); } } #ifdef ENABLE_JINGLE_FILE_TRANSFER static void gabble_ft_manager_channels_created (GabbleFtManager *self, GList *channels) { GList *i; GHashTable *new_channels = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); for (i = channels; i ; i = i->next) { GabbleFileTransferChannel *chan = i->data; tp_base_channel_register (TP_BASE_CHANNEL (chan)); gabble_signal_connect_weak (chan, "closed", G_CALLBACK (file_channel_closed_cb), G_OBJECT (self)); self->priv->channels = g_list_append (self->priv->channels, chan); /* The channels can't satisfy a request because this will always be called when we receive an incoming jingle-share session */ g_hash_table_insert (new_channels, chan, NULL); } tp_channel_manager_emit_new_channels (self, new_channels); g_hash_table_unref (new_channels); } #endif static void gabble_ft_manager_channel_created (GabbleFtManager *self, GabbleFileTransferChannel *chan, gpointer request_token) { GSList *requests = NULL; tp_base_channel_register (TP_BASE_CHANNEL (chan)); gabble_signal_connect_weak (chan, "closed", G_CALLBACK (file_channel_closed_cb), G_OBJECT (self)); self->priv->channels = g_list_append (self->priv->channels, chan); if (request_token != NULL) requests = g_slist_prepend (requests, request_token); tp_channel_manager_emit_new_channel (self, TP_EXPORTABLE_CHANNEL (chan), requests); g_slist_free (requests); } #ifdef ENABLE_JINGLE_FILE_TRANSFER static void new_jingle_session_cb (GabbleJingleMint *jm, WockyJingleSession *sess, gpointer data) { GabbleFtManager *self = GABBLE_FT_MANAGER (data); GTalkFileCollection *gtalk_fc = NULL; WockyJingleContent *content = NULL; GabbleJingleShareManifest *manifest = NULL; GList *channels = NULL; GList *cs, *i; if (wocky_jingle_session_get_content_type (sess) == GABBLE_TYPE_JINGLE_SHARE) { cs = wocky_jingle_session_get_contents (sess); if (cs != NULL) { content = WOCKY_JINGLE_CONTENT (cs->data); g_list_free (cs); } if (content == NULL) return; gtalk_fc = gtalk_file_collection_new_from_session ( gabble_jingle_mint_get_factory (jm), sess); if (gtalk_fc) { gchar *token = NULL; g_object_get (gtalk_fc, "token", &token, NULL); manifest = gabble_jingle_share_get_manifest ( GABBLE_JINGLE_SHARE (content)); for (i = manifest->entries; i; i = i->next) { GabbleJingleShareManifestEntry *entry = i->data; GabbleFileTransferChannel *channel = NULL; gchar *filename = NULL; TpHandleRepoIface *contacts = tp_base_connection_get_handles ( TP_BASE_CONNECTION (self->priv->connection), TP_HANDLE_TYPE_CONTACT); TpHandle peer = tp_handle_ensure (contacts, wocky_jingle_session_get_peer_jid (sess), NULL, NULL); filename = g_strdup_printf ("%s%s", entry->name, entry->folder? ".tar":""); channel = gabble_file_transfer_channel_new (self->priv->connection, peer, peer, TP_FILE_TRANSFER_STATE_PENDING, NULL, filename, entry->size, TP_FILE_HASH_TYPE_NONE, NULL, NULL, 0, 0, FALSE, NULL, gtalk_fc, token, NULL, NULL, NULL); g_free (filename); gtalk_file_collection_add_channel (gtalk_fc, channel); channels = g_list_prepend (channels, channel); } if (channels != NULL) gabble_ft_manager_channels_created (self, channels); g_list_free (channels); /* Channels will hold the reference to the gtalk file collection, so we can drop ours already. If no channels were created, then we need to destroy it anyways */ g_object_unref (gtalk_fc); } } } #endif static void connection_status_changed_cb (GabbleConnection *conn, guint status, guint reason, GabbleFtManager *self) { switch (status) { #ifdef ENABLE_JINGLE_FILE_TRANSFER case TP_CONNECTION_STATUS_CONNECTING: g_signal_connect (self->priv->connection->jingle_mint, "incoming-session", G_CALLBACK (new_jingle_session_cb), self); break; #endif case TP_CONNECTION_STATUS_DISCONNECTED: ft_manager_close_all (self); if (self->priv->status_changed_id != 0) { g_signal_handler_disconnect (self->priv->connection, self->priv->status_changed_id); self->priv->status_changed_id = 0; } break; } } static gboolean gabble_ft_manager_handle_request (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties) { GabbleFtManager *self = GABBLE_FT_MANAGER (manager); GabbleFileTransferChannel *chan; TpBaseConnection *base_conn = TP_BASE_CONNECTION (self->priv->connection); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT); TpHandle handle; const gchar *content_type, *filename, *content_hash, *description; const gchar *file_uri, *service_name; guint64 size, date, initial_offset; TpFileHashType content_hash_type; const GHashTable *metadata; GError *error = NULL; gboolean valid; DEBUG ("File transfer request"); /* We only support file transfer channels */ if (tp_strdiff (tp_asv_get_string (request_properties, TP_IFACE_CHANNEL ".ChannelType"), TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER)) return FALSE; /* And only contact handles */ if (tp_asv_get_uint32 (request_properties, TP_IFACE_CHANNEL ".TargetHandleType", NULL) != TP_HANDLE_TYPE_CONTACT) return FALSE; handle = tp_asv_get_uint32 (request_properties, TP_IFACE_CHANNEL ".TargetHandle", NULL); /* Must be a valid contact handle */ if (!tp_handle_is_valid (contact_repo, handle, &error)) goto error; /* Don't support opening a channel to our self handle */ if (handle == tp_base_connection_get_self_handle (base_conn)) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "Can't open a file transfer channel to yourself"); goto error; } content_type = tp_asv_get_string (request_properties, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".ContentType"); if (content_type == NULL) { g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "ContentType property is mandatory"); goto error; } filename = tp_asv_get_string (request_properties, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".Filename"); if (filename == NULL) { g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Filename property is mandatory"); goto error; } size = tp_asv_get_uint64 (request_properties, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".Size", NULL); if (size == 0) { g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Size property is mandatory"); goto error; } content_hash_type = tp_asv_get_uint32 (request_properties, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".ContentHashType", &valid); if (!valid) { /* Assume File_Hash_Type_None */ content_hash_type = TP_FILE_HASH_TYPE_NONE; } else { if (content_hash_type >= NUM_TP_FILE_HASH_TYPES) { g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "%u is not a valid ContentHashType", content_hash_type); goto error; } } if (content_hash_type != TP_FILE_HASH_TYPE_NONE) { content_hash = tp_asv_get_string (request_properties, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".ContentHash"); if (content_hash == NULL) { g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "ContentHash property is mandatory if ContentHashType is " "not None"); goto error; } } else { content_hash = NULL; } description = tp_asv_get_string (request_properties, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".Description"); date = tp_asv_get_uint64 (request_properties, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".Date", NULL); initial_offset = tp_asv_get_uint64 (request_properties, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".InitialOffset", NULL); file_uri = tp_asv_get_string (request_properties, TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_URI); service_name = tp_asv_get_string (request_properties, TP_PROP_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA_SERVICE_NAME); metadata = tp_asv_get_boxed (request_properties, TP_PROP_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA_METADATA, TP_HASH_TYPE_METADATA); if (metadata != NULL && g_hash_table_lookup ((GHashTable *) metadata, "FORM_TYPE")) { g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Metadata cannot contain an item with key 'FORM_TYPE'"); goto error; } DEBUG ("Requested outgoing channel with contact: %s", tp_handle_inspect (contact_repo, handle)); chan = gabble_file_transfer_channel_new (self->priv->connection, handle, tp_base_connection_get_self_handle (base_conn), TP_FILE_TRANSFER_STATE_PENDING, content_type, filename, size, content_hash_type, content_hash, description, date, initial_offset, TRUE, NULL, NULL, NULL, file_uri, service_name, metadata); if (!gabble_file_transfer_channel_offer_file (chan, &error)) { g_object_unref (chan); goto error; } gabble_ft_manager_channel_created (self, chan, request_token); return TRUE; error: tp_channel_manager_emit_request_failed (self, request_token, error->domain, error->code, error->message); g_error_free (error); return TRUE; } /* Keep in sync with values set in gabble_ft_manager_type_foreach_channel_class */ static const gchar * const file_transfer_channel_fixed_properties[] = { TP_IFACE_CHANNEL ".ChannelType", TP_IFACE_CHANNEL ".TargetHandleType", NULL }; /* ContentHashType has to be first so we can easily skip it when needed */ #define STANDARD_PROPERTIES \ TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_CONTENT_HASH_TYPE, \ TP_PROP_CHANNEL_TARGET_HANDLE, \ TP_PROP_CHANNEL_TARGET_ID, \ TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_CONTENT_TYPE, \ TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_FILENAME, \ TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_SIZE, \ TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_CONTENT_HASH, \ TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_DESCRIPTION, \ TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_DATE, \ TP_PROP_CHANNEL_TYPE_FILE_TRANSFER_URI static const gchar * const file_transfer_channel_allowed_properties[] = { STANDARD_PROPERTIES, NULL }; static const gchar * const file_transfer_channel_allowed_properties_with_metadata_prop[] = { STANDARD_PROPERTIES, TP_PROP_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA_METADATA, NULL }; static const gchar * const file_transfer_channel_allowed_properties_with_both_metadata_props[] = { STANDARD_PROPERTIES, TP_PROP_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA_SERVICE_NAME, TP_PROP_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA_METADATA, NULL }; static void gabble_ft_manager_type_foreach_channel_class (GType type, TpChannelManagerTypeChannelClassFunc func, gpointer user_data) { GHashTable *table; /* general FT class */ table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free); g_hash_table_insert (table, TP_IFACE_CHANNEL ".ChannelType" , tp_g_value_slice_new_string (TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER)); g_hash_table_insert (table, TP_IFACE_CHANNEL ".TargetHandleType", tp_g_value_slice_new_uint (TP_HANDLE_TYPE_CONTACT)); func (type, table, file_transfer_channel_allowed_properties_with_both_metadata_props, user_data); /* MD5 HashType class */ g_hash_table_insert (table, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER ".ContentHashType", tp_g_value_slice_new_uint (TP_FILE_HASH_TYPE_MD5)); /* skip ContentHashType in allowed properties */ func (type, table, file_transfer_channel_allowed_properties_with_both_metadata_props + 1, user_data); g_hash_table_unref (table); } static WockyNode * hyvaa_vappua ( WockyNode *si_node, const gchar **filename, const gchar **size_str, GError **error) { #define die_if_null(var, msg) \ if ((var) == NULL) \ { \ g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, \ msg); \ return NULL; \ } WockyNode *file_node = wocky_node_get_child_ns (si_node, "file", NS_FILE_TRANSFER); die_if_null (file_node, "Invalid file transfer SI request: no <file>") die_if_null (*filename = wocky_node_get_attribute (file_node, "name"), "Invalid file transfer SI request: missing file name") die_if_null (*size_str = wocky_node_get_attribute (file_node, "size"), "Invalid file transfer SI request: missing file size") return file_node; #undef die_if_null } static WockyDataForm * find_data_form (WockyNode *file, const gchar *form_type) { WockyNodeIter iter; WockyNode *x; wocky_node_iter_init (&iter, file, "x", NS_X_DATA); while (wocky_node_iter_next (&iter, &x)) { GError *error = NULL; WockyDataForm *form = wocky_data_form_new_from_node (x, &error); WockyDataFormField *field; if (form == NULL) { DEBUG ("Failed to parse data form: %s", error->message); g_clear_error (&error); continue; } field = g_hash_table_lookup (form->fields, "FORM_TYPE"); if (field == NULL) { DEBUG ("Data form doesn't have FORM_TYPE field!"); g_object_unref (form); continue; } /* found it! */ if (!tp_strdiff (field->raw_value_contents[0], form_type)) return form; g_object_unref (form); } return NULL; } static gchar * extract_service_name (WockyNode *file) { WockyDataForm *form = find_data_form (file, NS_TP_FT_METADATA_SERVICE); WockyDataFormField *field; gchar *service_name = NULL; if (form == NULL) return NULL; field = g_hash_table_lookup (form->fields, "ServiceName"); if (field == NULL) { DEBUG ("ServiceName property not present in data form; odd..."); goto out; } if (field->raw_value_contents == NULL || field->raw_value_contents[0] == NULL) { DEBUG ("ServiceName property doesn't have a real value; odd..."); } else { service_name = g_strdup (field->raw_value_contents[0]); } out: g_object_unref (form); return service_name; } static GHashTable * extract_metadata (WockyNode *file) { WockyDataForm *form = find_data_form (file, NS_TP_FT_METADATA); GHashTable *metadata; GHashTableIter iter; gpointer key, value; if (form == NULL) return NULL; metadata = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_strfreev); g_hash_table_iter_init (&iter, form->fields); while (g_hash_table_iter_next (&iter, &key, &value)) { const gchar *var = key; WockyDataFormField *field = value; if (!tp_strdiff (var, "FORM_TYPE")) continue; g_hash_table_insert (metadata, g_strdup (var), g_strdupv (field->raw_value_contents)); } g_object_unref (form); return metadata; } void gabble_ft_manager_handle_si_request (GabbleFtManager *self, GabbleBytestreamIface *bytestream, TpHandle handle, const gchar *stream_id, WockyStanza *msg) { WockyNode *si_node, *file_node, *desc_node; const gchar *filename, *size_str, *content_type, *content_hash, *description; const gchar *date_str; gchar *service_name; GHashTable *metadata; guint64 size; guint64 date = 0; TpFileHashType content_hash_type; GabbleFileTransferChannel *chan; gboolean resume_supported; GError *error = NULL; si_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "si", NS_SI); g_assert (si_node != NULL); file_node = hyvaa_vappua (si_node, &filename, &size_str, &error); if (file_node == NULL) { DEBUG ("%s", error->message); gabble_bytestream_iface_close (bytestream, error); g_clear_error (&error); return; } size = g_ascii_strtoull (size_str, NULL, 0); content_type = wocky_node_get_attribute (file_node, "mime-type"); if (content_type == NULL) content_type = "application/octet-stream"; /* The hash is always an MD5-sum, if present. */ content_hash = wocky_node_get_attribute (file_node, "hash"); if (content_hash != NULL) content_hash_type = TP_FILE_HASH_TYPE_MD5; else content_hash_type = TP_FILE_HASH_TYPE_NONE; desc_node = wocky_node_get_child (file_node, "desc"); if (desc_node != NULL) description = desc_node->content; else description = NULL; date_str = wocky_node_get_attribute (file_node, "date"); if (date_str != NULL) { GTimeVal val; /* FIXME: this assume the timezone is always UTC */ if (g_time_val_from_iso8601 (date_str, &val)) date = val.tv_sec; } resume_supported = (wocky_node_get_child (file_node, "range") != NULL); /* metadata */ service_name = extract_service_name (file_node); metadata = extract_metadata (file_node); chan = gabble_file_transfer_channel_new (self->priv->connection, handle, handle, TP_FILE_TRANSFER_STATE_PENDING, content_type, filename, size, content_hash_type, content_hash, description, date, 0, resume_supported, bytestream, NULL, NULL, NULL, service_name, metadata); gabble_ft_manager_channel_created (self, chan, NULL); g_free (service_name); if (metadata != NULL) g_hash_table_unref (metadata); } static void channel_manager_iface_init (gpointer g_iface, gpointer iface_data) { TpChannelManagerIface *iface = g_iface; iface->foreach_channel = gabble_ft_manager_foreach_channel; iface->type_foreach_channel_class = gabble_ft_manager_type_foreach_channel_class; iface->create_channel = gabble_ft_manager_handle_request; iface->ensure_channel = gabble_ft_manager_handle_request; } /* public functions */ GabbleFtManager * gabble_ft_manager_new (GabbleConnection *connection) { g_assert (connection != NULL); return g_object_new (GABBLE_TYPE_FT_MANAGER, "connection", connection, NULL); } #ifdef G_OS_UNIX /* We assume that all Unixes have mkdtemp */ const gchar * gabble_ft_manager_get_tmp_dir (GabbleFtManager *self) { if (self->priv->tmp_dir != NULL) return self->priv->tmp_dir; self->priv->tmp_dir = g_strdup_printf ("%s/gabble-ft-XXXXXX", g_get_tmp_dir ()); self->priv->tmp_dir = mkdtemp (self->priv->tmp_dir); if (self->priv->tmp_dir == NULL) DEBUG ("mkdtemp failed: %s\n", g_strerror (errno)); return self->priv->tmp_dir; } #endif static void add_file_transfer_channel_class (GPtrArray *arr, gboolean include_metadata_properties, const gchar *service_name_str) { GValue monster = {0, }; GHashTable *fixed_properties; GValue *channel_type_value; GValue *target_handle_type_value; GValue *service_name_value; const gchar * const *allowed_properties; g_value_init (&monster, TP_STRUCT_TYPE_REQUESTABLE_CHANNEL_CLASS); g_value_take_boxed (&monster, dbus_g_type_specialized_construct ( TP_STRUCT_TYPE_REQUESTABLE_CHANNEL_CLASS)); fixed_properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free); channel_type_value = tp_g_value_slice_new_static_string ( TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER); g_hash_table_insert (fixed_properties, TP_IFACE_CHANNEL ".ChannelType", channel_type_value); target_handle_type_value = tp_g_value_slice_new_uint (TP_HANDLE_TYPE_CONTACT); g_hash_table_insert (fixed_properties, TP_IFACE_CHANNEL ".TargetHandleType", target_handle_type_value); if (service_name_str != NULL) { service_name_value = tp_g_value_slice_new_string (service_name_str); g_hash_table_insert (fixed_properties, TP_PROP_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA_SERVICE_NAME, service_name_value); } if (include_metadata_properties) { if (service_name_str == NULL) allowed_properties = file_transfer_channel_allowed_properties_with_both_metadata_props; else allowed_properties = file_transfer_channel_allowed_properties_with_metadata_prop; } else { allowed_properties = file_transfer_channel_allowed_properties; } dbus_g_type_struct_set (&monster, 0, fixed_properties, 1, allowed_properties, G_MAXUINT); g_hash_table_unref (fixed_properties); g_ptr_array_add (arr, g_value_get_boxed (&monster)); } static void get_contact_caps_foreach (gpointer data, gpointer user_data) { const gchar *ns = data; GPtrArray *arr = user_data; if (!g_str_has_prefix (ns, NS_TP_FT_METADATA "#")) return; add_file_transfer_channel_class (arr, TRUE, ns + strlen (NS_TP_FT_METADATA "#")); } static void gabble_ft_manager_get_contact_caps ( GabbleCapsChannelManager *manager G_GNUC_UNUSED, TpHandle handle G_GNUC_UNUSED, const GabbleCapabilitySet *caps, GPtrArray *arr) { if (gabble_capability_set_has (caps, NS_FILE_TRANSFER) || gabble_capability_set_has (caps, NS_GOOGLE_FEAT_SHARE)) { add_file_transfer_channel_class (arr, gabble_capability_set_has (caps, NS_TP_FT_METADATA), NULL); } gabble_capability_set_foreach (caps, get_contact_caps_foreach, arr); } static void gabble_ft_manager_represent_client ( GabbleCapsChannelManager *manager G_GNUC_UNUSED, const gchar *client_name, const GPtrArray *filters, const gchar * const *cap_tokens G_GNUC_UNUSED, GabbleCapabilitySet *cap_set, GPtrArray *data_forms G_GNUC_UNUSED) { guint i; for (i = 0; i < filters->len; i++) { GHashTable *channel_class = g_ptr_array_index (filters, i); const gchar *service_name; gchar *ns; if (tp_strdiff (tp_asv_get_string (channel_class, TP_IFACE_CHANNEL ".ChannelType"), TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER)) continue; if (tp_asv_get_uint32 (channel_class, TP_IFACE_CHANNEL ".TargetHandleType", NULL) != TP_HANDLE_TYPE_CONTACT) continue; DEBUG ("client %s supports file transfer", client_name); gabble_capability_set_add (cap_set, NS_FILE_TRANSFER); gabble_capability_set_add (cap_set, NS_GOOGLE_FEAT_SHARE); gabble_capability_set_add (cap_set, NS_TP_FT_METADATA); /* now look at service names */ /* capabilities mean being able to RECEIVE said kinds of * FTs. hence, skip Requested=true (locally initiated) channel * classes */ if (tp_asv_get_boolean (channel_class, TP_PROP_CHANNEL_REQUESTED, FALSE)) continue; service_name = tp_asv_get_string (channel_class, TP_PROP_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA_SERVICE_NAME); if (service_name == NULL) continue; ns = g_strconcat (NS_TP_FT_METADATA "#", service_name, NULL); DEBUG ("%s: adding capability %s", client_name, ns); gabble_capability_set_add (cap_set, ns); g_free (ns); } } static void caps_channel_manager_iface_init (gpointer g_iface, gpointer iface_data) { GabbleCapsChannelManagerInterface *iface = g_iface; iface->get_contact_caps = gabble_ft_manager_get_contact_caps; iface->represent_client = gabble_ft_manager_represent_client; } ���������������������������������������������������������������telepathy-gabble-0.18.3/src/ft-channel.h������������������������������������������������������������0000664�0001750�0001750�00000010646�12223562023�021161� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * ft-channel.h - Header for GabbleFileTransferChannel * Copyright (C) 2009 Collabora Ltd. * @author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_FILE_TRANSFER_CHANNEL_H__ #define __GABBLE_FILE_TRANSFER_CHANNEL_H__ #include "config.h" #include <glib-object.h> #include <extensions/extensions.h> #include <telepathy-glib/telepathy-glib.h> typedef struct _GabbleFileTransferChannel GabbleFileTransferChannel; #ifdef ENABLE_JINGLE_FILE_TRANSFER #include "gtalk-file-collection.h" #endif #include "bytestream-factory.h" G_BEGIN_DECLS typedef struct _GabbleFileTransferChannelClass GabbleFileTransferChannelClass; typedef struct _GabbleFileTransferChannelPrivate GabbleFileTransferChannelPrivate; struct _GabbleFileTransferChannelClass { TpBaseChannelClass parent_class; TpDBusPropertiesMixinClass dbus_props_class; }; struct _GabbleFileTransferChannel { TpBaseChannel parent; GabbleFileTransferChannelPrivate *priv; }; GType gabble_file_transfer_channel_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_FILE_TRANSFER_CHANNEL \ (gabble_file_transfer_channel_get_type ()) #define GABBLE_FILE_TRANSFER_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_FILE_TRANSFER_CHANNEL, GabbleFileTransferChannel)) #define GABBLE_FILE_TRANSFER_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_FILE_TRANSFER_CHANNEL, \ GabbleFileTransferChannelClass)) #define GABBLE_IS_FILE_TRANSFER_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_FILE_TRANSFER_CHANNEL)) #define GABBLE_IS_FILE_TRANSFER_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_FILE_TRANSFER_CHANNEL)) #define GABBLE_FILE_TRANSFER_CHANNEL_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_FILE_TRANSFER_CHANNEL, \ GabbleFileTransferChannelClass)) GabbleFileTransferChannel * gabble_file_transfer_channel_new (GabbleConnection *conn, TpHandle handle, TpHandle initiator_handle, TpFileTransferState state, const gchar *content_type, const gchar *filename, guint64 size, TpFileHashType content_hash_type, const gchar *content_hash, const gchar *description, guint64 date, guint64 initial_offset, gboolean resume_supported, GabbleBytestreamIface *bytestream, #ifdef ENABLE_JINGLE_FILE_TRANSFER GTalkFileCollection *gtalk_fc, #else /* It's easier for the calling code if we don't change the number of * arguments based on a #ifdef */ gpointer gtalk_fc_dummy, #endif const gchar *file_collection, const gchar *uri, const gchar *service_name, const GHashTable *metadata); gboolean gabble_file_transfer_channel_offer_file ( GabbleFileTransferChannel *self, GError **error); #ifdef ENABLE_JINGLE_FILE_TRANSFER /* The following methods are a hack, they are 'signal-like' callbacks for the GTalkFileCollection. They have to be made this way because the FileCollection can't send out signals since it needs its signals to be sent to a specific channel only. So instead it calls these callbacks directly on the channel it needs to notify. This is a known layering violation and accepted as the lesser of any other evil [hack]. */ void gabble_file_transfer_channel_gtalk_file_collection_state_changed ( GabbleFileTransferChannel *self, GTalkFileCollectionState gtalk_fc_state, gboolean local_terminator); void gabble_file_transfer_channel_gtalk_file_collection_write_blocked ( GabbleFileTransferChannel *self, gboolean blocked); void gabble_file_transfer_channel_gtalk_file_collection_data_received ( GabbleFileTransferChannel *self, const gchar *data, guint len); #endif G_END_DECLS #endif /* #ifndef __GABBLE_FILE_TRANSFER_CHANNEL_H__*/ ������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/server-tls-manager.h����������������������������������������������������0000664�0001750�0001750�00000005220�12332440117�022650� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * server-tls-manager.h - Header for GabbleServerTLSManager * Copyright (C) 2010 Collabora Ltd. * @author Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_SERVER_TLS_MANAGER_H__ #define __GABBLE_SERVER_TLS_MANAGER_H__ #include <glib-object.h> #include <wocky/wocky.h> #include <telepathy-glib/telepathy-glib.h> #include "extensions/extensions.h" G_BEGIN_DECLS typedef struct _GabbleServerTLSManager GabbleServerTLSManager; typedef struct _GabbleServerTLSManagerClass GabbleServerTLSManagerClass; typedef struct _GabbleServerTLSManagerPrivate GabbleServerTLSManagerPrivate; struct _GabbleServerTLSManagerClass { WockyTLSHandlerClass parent_class; }; struct _GabbleServerTLSManager { WockyTLSHandler parent; GabbleServerTLSManagerPrivate *priv; }; GType gabble_server_tls_manager_get_type (void); #define GABBLE_TYPE_SERVER_TLS_MANAGER \ (gabble_server_tls_manager_get_type ()) #define GABBLE_SERVER_TLS_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_SERVER_TLS_MANAGER, \ GabbleServerTLSManager)) #define GABBLE_SERVER_TLS_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_SERVER_TLS_MANAGER, \ GabbleServerTLSManagerClass)) #define GABBLE_IS_SERVER_TLS_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_SERVER_TLS_MANAGER)) #define GABBLE_IS_SERVER_TLS_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_SERVER_TLS_MANAGER)) #define GABBLE_SERVER_TLS_MANAGER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_SERVER_TLS_MANAGER, \ GabbleServerTLSManagerClass)) #define GABBLE_SERVER_TLS_ERROR gabble_server_tls_error_quark () GQuark gabble_server_tls_error_quark (void); void gabble_server_tls_manager_get_rejection_details ( GabbleServerTLSManager *self, gchar **dbus_error, GHashTable **details, TpConnectionStatusReason *reason); G_END_DECLS #endif /* #ifndef __GABBLE_SERVER_TLS_MANAGER_H__ */ ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/jingle-mint.c�����������������������������������������������������������0000664�0001750�0001750�00000023506�12332440117�021351� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * jingle-mint.c - creates and configures a WockyJingleFactory * Copyright ©2012 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * * * "Mint" is intended in the manufacturing sense: a mint is a factory which * produces coins. <http://en.wikipedia.org/wiki/Mint_(coin)>. It was chosen * in favour of "factory" because this is a "factory factory"; and in favour of * "foundry" to make JingleFactory and this class have different initials. */ #include "config.h" #include "jingle-mint.h" #define DEBUG_FLAG GABBLE_DEBUG_MEDIA #include "debug.h" #include "connection.h" #include "conn-presence.h" #include "jingle-share.h" #include "presence-cache.h" struct _GabbleJingleMintPrivate { GabbleConnection *conn; WockyJingleFactory *factory; }; enum { INCOMING_SESSION = 0, N_SIGNALS }; static guint signals[N_SIGNALS]; enum { PROP_CONNECTION = 1, }; static void connection_status_changed_cb ( GabbleConnection *conn, guint status, guint reason, gpointer user_data); static void connection_porter_available_cb ( GabbleConnection *conn, WockyPorter *porter, gpointer user_data); static void factory_new_session_cb ( WockyJingleFactory *factory, WockyJingleSession *session, gboolean initiated_locally, gpointer user_data); static gboolean factory_query_cap_cb ( WockyJingleFactory *factory, WockyContact *contact, const gchar *cap_or_quirk, gpointer user_data); G_DEFINE_TYPE (GabbleJingleMint, gabble_jingle_mint, G_TYPE_OBJECT) static void gabble_jingle_mint_init (GabbleJingleMint *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_JINGLE_MINT, GabbleJingleMintPrivate); } static void gabble_jingle_mint_get_property ( GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleJingleMint *self = GABBLE_JINGLE_MINT (object); GabbleJingleMintPrivate *priv = self->priv; switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, priv->conn); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void gabble_jingle_mint_set_property ( GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleJingleMint *self = GABBLE_JINGLE_MINT (object); GabbleJingleMintPrivate *priv = self->priv; switch (property_id) { case PROP_CONNECTION: priv->conn = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void gabble_jingle_mint_constructed (GObject *object) { GabbleJingleMint *self = GABBLE_JINGLE_MINT (object); GabbleJingleMintPrivate *priv = self->priv; GObjectClass *parent_class = gabble_jingle_mint_parent_class; if (parent_class->constructed != NULL) parent_class->constructed (object); tp_g_signal_connect_object (priv->conn, "status-changed", (GCallback) connection_status_changed_cb, self, 0); tp_g_signal_connect_object (priv->conn, "porter-available", (GCallback) connection_porter_available_cb, self, 0); } static void gabble_jingle_mint_dispose (GObject *object) { GabbleJingleMint *self = GABBLE_JINGLE_MINT (object); GabbleJingleMintPrivate *priv = self->priv; GObjectClass *parent_class = gabble_jingle_mint_parent_class; g_clear_object (&priv->factory); if (parent_class->dispose != NULL) parent_class->dispose (object); } static void gabble_jingle_mint_class_init (GabbleJingleMintClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GParamSpec *param_spec; object_class->get_property = gabble_jingle_mint_get_property; object_class->set_property = gabble_jingle_mint_set_property; object_class->constructed = gabble_jingle_mint_constructed; object_class->dispose = gabble_jingle_mint_dispose; g_type_class_add_private (klass, sizeof (GabbleJingleMintPrivate)); param_spec = g_param_spec_object ("connection", "GabbleConnection object", "Gabble connection object that uses this JingleMint object", GABBLE_TYPE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); signals[INCOMING_SESSION] = g_signal_new ("incoming-session", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, WOCKY_TYPE_JINGLE_SESSION); } GabbleJingleMint * gabble_jingle_mint_new ( GabbleConnection *connection) { return g_object_new (GABBLE_TYPE_JINGLE_MINT, "connection", connection, NULL); } static void connection_status_changed_cb ( GabbleConnection *conn, guint status, guint reason, gpointer user_data) { GabbleJingleMint *self = GABBLE_JINGLE_MINT (user_data); GabbleJingleMintPrivate *priv = self->priv; switch (status) { case TP_CONNECTION_STATUS_CONNECTING: g_assert (priv->conn != NULL); break; case TP_CONNECTION_STATUS_CONNECTED: { WockyJingleInfo *info = gabble_jingle_mint_get_info (self); gchar *stun_server = NULL; guint stun_port = 0; g_object_get (priv->conn, "stun-server", &stun_server, "stun-port", &stun_port, NULL); if (stun_server != NULL) wocky_jingle_info_take_stun_server (info, stun_server, stun_port, FALSE); g_object_get (priv->conn, "fallback-stun-server", &stun_server, "fallback-stun-port", &stun_port, NULL); if (stun_server != NULL) wocky_jingle_info_take_stun_server (info, stun_server, stun_port, TRUE); wocky_jingle_info_send_request (info, /* FIXME: one day Wocky will know about caps and then we won't * have to pass in a flag here. */ !!(priv->conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_JINGLE_INFO)); } break; case TP_CONNECTION_STATUS_DISCONNECTED: if (priv->factory != NULL) wocky_jingle_factory_stop (priv->factory); break; } } static void connection_porter_available_cb ( GabbleConnection *conn, WockyPorter *porter, gpointer user_data) { GabbleJingleMint *self = GABBLE_JINGLE_MINT (user_data); GabbleJingleMintPrivate *priv = self->priv; /* If we have a WockyPorter, we should definitely have a WockySession */ g_assert (conn->session != NULL); g_assert (priv->factory == NULL); priv->factory = wocky_jingle_factory_new (conn->session); jingle_share_register (priv->factory); tp_g_signal_connect_object (priv->factory, "new-session", (GCallback) factory_new_session_cb, self, 0); tp_g_signal_connect_object (priv->factory, "query-cap", (GCallback) factory_query_cap_cb, self, 0); } static void session_about_to_initiate_cb ( WockyJingleSession *session, gpointer user_data) { GabbleJingleMint *self = GABBLE_JINGLE_MINT (user_data); GabbleJingleMintPrivate *priv = self->priv; const gchar *peer_jid = wocky_jingle_session_get_peer_jid (session); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); TpHandle peer = tp_handle_ensure (contact_repo, peer_jid, NULL, NULL); /* send directed presence (including our own caps, avatar etc.) to * the peer, if we aren't already visible to them */ if (!conn_presence_visible_to (priv->conn, peer)) conn_presence_signal_own_presence (priv->conn, peer_jid, NULL); } static void factory_new_session_cb ( WockyJingleFactory *factory, WockyJingleSession *session, gboolean initiated_locally, gpointer user_data) { GabbleJingleMint *self = GABBLE_JINGLE_MINT (user_data); if (initiated_locally) tp_g_signal_connect_object (session, "about-to-initiate", (GCallback) session_about_to_initiate_cb, self, 0); /* Proxy the signal outwards if this is a new incoming session. */ if (!initiated_locally) g_signal_emit (self, signals[INCOMING_SESSION], 0, session); } static gboolean factory_query_cap_cb ( WockyJingleFactory *factory, WockyContact *contact, const gchar *cap_or_quirk, gpointer user_data) { GabbleJingleMint *self = GABBLE_JINGLE_MINT (user_data); GabbleJingleMintPrivate *priv = self->priv; GabblePresence *presence = gabble_presence_cache_get_for_contact ( priv->conn->presence_cache, contact); if (presence == NULL) return FALSE; if (WOCKY_IS_RESOURCE_CONTACT (contact)) { const gchar *peer_resource = wocky_resource_contact_get_resource ( WOCKY_RESOURCE_CONTACT (contact)); return gabble_presence_resource_has_caps (presence, peer_resource, gabble_capability_set_predicate_has, cap_or_quirk); } else { return gabble_presence_has_cap (presence, cap_or_quirk); } } WockyJingleFactory * gabble_jingle_mint_get_factory ( GabbleJingleMint *self) { return self->priv->factory; } WockyJingleInfo * gabble_jingle_mint_get_info ( GabbleJingleMint *self) { return wocky_jingle_factory_get_jingle_info (self->priv->factory); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/tube-stream.h�����������������������������������������������������������0000664�0001750�0001750�00000005715�12332440117�021373� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * tube-stream.h - Header for GabbleTubeStream * Copyright (C) 2007 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_TUBE_STREAM_H__ #define __GABBLE_TUBE_STREAM_H__ #include <glib-object.h> #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #include "connection.h" #include "extensions/extensions.h" #include "muc-channel.h" G_BEGIN_DECLS typedef struct _GabbleTubeStream GabbleTubeStream; typedef struct _GabbleTubeStreamPrivate GabbleTubeStreamPrivate; typedef struct _GabbleTubeStreamClass GabbleTubeStreamClass; struct _GabbleTubeStreamClass { TpBaseChannelClass parent_class; TpDBusPropertiesMixinClass dbus_props_class; }; struct _GabbleTubeStream { TpBaseChannel parent; GabbleTubeStreamPrivate *priv; }; GType gabble_tube_stream_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_TUBE_STREAM \ (gabble_tube_stream_get_type ()) #define GABBLE_TUBE_STREAM(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_TUBE_STREAM, GabbleTubeStream)) #define GABBLE_TUBE_STREAM_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_TUBE_STREAM,\ GabbleTubeStreamClass)) #define GABBLE_IS_TUBE_STREAM(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_TUBE_STREAM)) #define GABBLE_IS_TUBE_STREAM_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_TUBE_STREAM)) #define GABBLE_TUBE_STREAM_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_TUBE_STREAM,\ GabbleTubeStreamClass)) GabbleTubeStream *gabble_tube_stream_new (GabbleConnection *conn, TpHandle handle, TpHandleType handle_type, TpHandle self_handle, TpHandle initiator, const gchar *service, GHashTable *parameters, guint64 id, GabbleMucChannel *muc, gboolean requested); gboolean gabble_tube_stream_check_params (TpSocketAddressType address_type, const GValue *address, TpSocketAccessControl access_control, const GValue *access_control_param, GError **error); gboolean gabble_tube_stream_offer (GabbleTubeStream *self, GError **error); GHashTable *gabble_tube_stream_get_supported_socket_types (void); const gchar * const * gabble_tube_stream_channel_get_allowed_properties (void); G_END_DECLS #endif /* #ifndef __GABBLE_TUBE_STREAM_H__ */ ���������������������������������������������������telepathy-gabble-0.18.3/src/auth-manager.c����������������������������������������������������������0000664�0001750�0001750�00000050742�12332440117�021507� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * auth-manager.c - TpChannelManager implementation for auth channels * Copyright (C) 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "auth-manager.h" #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #include <wocky/wocky.h> #define DEBUG_FLAG GABBLE_DEBUG_AUTH #include "gabble/caps-channel-manager.h" #include "server-sasl-channel.h" #include "connection.h" #include "debug.h" #include "util.h" static void channel_manager_iface_init (gpointer, gpointer); G_DEFINE_TYPE_WITH_CODE (GabbleAuthManager, gabble_auth_manager, WOCKY_TYPE_AUTH_REGISTRY, G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER, channel_manager_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_CAPS_CHANNEL_MANAGER, NULL)); /* properties */ enum { PROP_CONNECTION = 1, LAST_PROPERTY }; typedef struct { gchar *name; GHashTable *details; TpConnectionStatusReason reason; GError *wocky_error; } SavedError; struct _GabbleAuthManagerPrivate { GabbleConnection *conn; GabbleServerSaslChannel *channel; gulong closed_id; /* TRUE if we are authenticating using our parent class's methods (because we * have a username and password). */ gboolean chaining_up; GSList *mechanisms; gchar *server; gchar *session_id; gchar *username; gboolean allow_plain; gboolean is_secure_channel; SavedError *error; gboolean dispose_has_run; }; static void gabble_auth_manager_init (GabbleAuthManager *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_AUTH_MANAGER, GabbleAuthManagerPrivate); } static void gabble_auth_manager_close_all (GabbleAuthManager *self) { DEBUG ("called"); if (self->priv->channel != NULL) tp_base_channel_close ((TpBaseChannel *) self->priv->channel); /* that results in the signal-driven-object-clearing dance */ g_assert (self->priv->channel == NULL); } static void connection_status_changed_cb (GabbleConnection *conn, guint status, guint reason, GabbleAuthManager *self) { if (status == TP_CONNECTION_STATUS_DISCONNECTED) gabble_auth_manager_close_all (self); } static void auth_channel_closed_cb (GabbleServerSaslChannel *channel, GabbleAuthManager *self) { SavedError tmp = { NULL, NULL, 0, NULL }; tp_channel_manager_emit_channel_closed_for_object (self, TP_EXPORTABLE_CHANNEL (channel)); g_assert (self->priv->channel == channel); /* this is our last chance to find out why it failed */ if (gabble_server_sasl_channel_get_failure_details (channel, &tmp.name, &tmp.details, &tmp.reason, &tmp.wocky_error)) self->priv->error = g_slice_dup (SavedError, &tmp); g_signal_handler_disconnect (self->priv->channel, self->priv->closed_id); tp_clear_object (&self->priv->channel); /* discard info we were holding in case we wanted to fall back */ g_slist_foreach (self->priv->mechanisms, (GFunc) g_free, NULL); tp_clear_pointer (&self->priv->mechanisms, g_slist_free); tp_clear_pointer (&self->priv->server, g_free); tp_clear_pointer (&self->priv->session_id, g_free); tp_clear_pointer (&self->priv->username, g_free); } static void gabble_auth_manager_constructed (GObject *object) { GabbleAuthManager *self = GABBLE_AUTH_MANAGER (object); if (G_OBJECT_CLASS (gabble_auth_manager_parent_class)->constructed != NULL) G_OBJECT_CLASS (gabble_auth_manager_parent_class)->constructed (object); self->priv->dispose_has_run = FALSE; gabble_signal_connect_weak (self->priv->conn, "status-changed", G_CALLBACK (connection_status_changed_cb), object); } static void gabble_auth_manager_dispose (GObject *object) { GabbleAuthManager *self = GABBLE_AUTH_MANAGER (object); GabbleAuthManagerPrivate *priv = self->priv; if (priv->dispose_has_run) return; DEBUG ("dispose called"); priv->dispose_has_run = TRUE; gabble_auth_manager_close_all (self); if (G_OBJECT_CLASS (gabble_auth_manager_parent_class)->dispose) G_OBJECT_CLASS ( gabble_auth_manager_parent_class)->dispose (object); } static void gabble_auth_manager_finalize (GObject *object) { GabbleAuthManager *self = GABBLE_AUTH_MANAGER (object); if (self->priv->error != NULL) { g_free (self->priv->error->name); g_hash_table_unref (self->priv->error->details); g_slice_free (SavedError, self->priv->error); } if (G_OBJECT_CLASS (gabble_auth_manager_parent_class)->finalize) G_OBJECT_CLASS (gabble_auth_manager_parent_class)->finalize (object); } static void gabble_auth_manager_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleAuthManager *self = GABBLE_AUTH_MANAGER (object); switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, self->priv->conn); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_auth_manager_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleAuthManager *self = GABBLE_AUTH_MANAGER (object); switch (property_id) { case PROP_CONNECTION: self->priv->conn = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_auth_manager_start_parent_cb (GObject *self_object, GAsyncResult *result, gpointer user_data) { GabbleAuthManager *self = GABBLE_AUTH_MANAGER (self_object); WockyAuthRegistryStartData *start_data = NULL; GError *error = NULL; if (WOCKY_AUTH_REGISTRY_CLASS (gabble_auth_manager_parent_class)-> start_auth_finish_func (WOCKY_AUTH_REGISTRY (self), result, &start_data, &error)) { g_simple_async_result_set_op_res_gpointer (user_data, start_data, (GDestroyNotify) wocky_auth_registry_start_data_free); } else { g_simple_async_result_set_from_error (user_data, error); g_clear_error (&error); } g_simple_async_result_complete (user_data); g_object_unref (user_data); } static void gabble_auth_manager_start_auth_cb (GObject *channel, GAsyncResult *result, gpointer user_data) { GObject *self_object = g_async_result_get_source_object (user_data); GabbleAuthManager *self = GABBLE_AUTH_MANAGER (self_object); WockyAuthRegistryStartData *start_data = NULL; GError *error = NULL; if (gabble_server_sasl_channel_start_auth_finish ( GABBLE_SERVER_SASL_CHANNEL (channel), result, &start_data, &error)) { if (!tp_strdiff (start_data->mechanism, X_TELEPATHY_PASSWORD)) { /* restart authentication using our own base class */ g_assert (start_data->initial_response != NULL); self->priv->chaining_up = TRUE; WOCKY_AUTH_REGISTRY_CLASS ( gabble_auth_manager_parent_class)->start_auth_async_func ( WOCKY_AUTH_REGISTRY (self), self->priv->mechanisms, self->priv->allow_plain, self->priv->is_secure_channel, self->priv->username, start_data->initial_response->str, self->priv->server, self->priv->session_id, gabble_auth_manager_start_parent_cb, user_data); /* we've transferred ownership of the result */ goto finally; } else { g_simple_async_result_set_op_res_gpointer (user_data, start_data, (GDestroyNotify) wocky_auth_registry_start_data_free); } } else { g_simple_async_result_set_from_error (user_data, error); g_clear_error (&error); } g_simple_async_result_complete (user_data); g_object_unref (user_data); finally: g_object_unref (self_object); } static void gabble_auth_manager_start_auth_async (WockyAuthRegistry *registry, GSList *mechanisms, gboolean allow_plain, gboolean is_secure_channel, const gchar *username, const gchar *password, const gchar *server, const gchar *session_id, GAsyncReadyCallback callback, gpointer user_data) { GabbleAuthManager *self = GABBLE_AUTH_MANAGER (registry); GSimpleAsyncResult *result = g_simple_async_result_new ((GObject *) self, callback, user_data, gabble_auth_manager_start_auth_async); /* assumption: Wocky's API guarantees that we never have more than one * auth request outstanding */ g_assert (self->priv->channel == NULL); if (password == NULL || username == NULL) { GPtrArray *mech_array = g_ptr_array_new (); GSList *iter; if (username == NULL) { g_object_get (self->priv->conn, "username", &self->priv->username, NULL); } else { self->priv->username = g_strdup (username); } for (iter = mechanisms; iter != NULL; iter = iter->next) { self->priv->mechanisms = g_slist_prepend (self->priv->mechanisms, g_strdup (iter->data)); /* skip Wocky-specific pseudo-mechanisms for the D-Bus API */ if (!g_str_has_prefix (iter->data, "X-WOCKY-JABBER-")) g_ptr_array_add (mech_array, iter->data); } if (self->priv->username != NULL && wocky_auth_registry_supports_one_of (registry, mechanisms, allow_plain)) g_ptr_array_add (mech_array, X_TELEPATHY_PASSWORD); g_ptr_array_add (mech_array, NULL); /* we'll use these if we fall back to the base class to use * X-TELEPATHY-PASSWORD */ self->priv->mechanisms = g_slist_reverse (self->priv->mechanisms); self->priv->allow_plain = allow_plain; self->priv->is_secure_channel = is_secure_channel; self->priv->server = g_strdup (server); self->priv->session_id = g_strdup (session_id); self->priv->channel = gabble_server_sasl_channel_new (self->priv->conn, (GStrv) mech_array->pdata, is_secure_channel, session_id); g_ptr_array_unref (mech_array); self->priv->closed_id = tp_g_signal_connect_object (self->priv->channel, "closed", G_CALLBACK (auth_channel_closed_cb), self, 0); gabble_server_sasl_channel_start_auth_async (self->priv->channel, gabble_auth_manager_start_auth_cb, result); g_assert (!tp_base_channel_is_destroyed ( (TpBaseChannel *) self->priv->channel)); g_assert (tp_base_channel_is_registered ( (TpBaseChannel *) self->priv->channel)); tp_channel_manager_emit_new_channel (self, TP_EXPORTABLE_CHANNEL (self->priv->channel), NULL); } else { self->priv->chaining_up = TRUE; WOCKY_AUTH_REGISTRY_CLASS ( gabble_auth_manager_parent_class)->start_auth_async_func ( registry, mechanisms, allow_plain, is_secure_channel, username, password, server, session_id, gabble_auth_manager_start_parent_cb, result); } } static gboolean gabble_auth_manager_start_auth_finish (WockyAuthRegistry *registry, GAsyncResult *result, WockyAuthRegistryStartData **start_data, GError **error) { GabbleAuthManager *self = GABBLE_AUTH_MANAGER (registry); wocky_implement_finish_copy_pointer (self, gabble_auth_manager_start_auth_async, wocky_auth_registry_start_data_dup, start_data); } static void channel_challenge_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { GabbleServerSaslChannel *channel = GABBLE_SERVER_SASL_CHANNEL (source); GSimpleAsyncResult *our_result = G_SIMPLE_ASYNC_RESULT (user_data); GString *response_data = NULL; GError *error = NULL; if (gabble_server_sasl_channel_challenge_finish (channel, result, &response_data, &error)) g_simple_async_result_set_op_res_gpointer (our_result, response_data, (GDestroyNotify) wocky_g_string_free); else g_simple_async_result_take_error (our_result, error); g_simple_async_result_complete (our_result); g_object_unref (our_result); } static void gabble_auth_manager_challenge_async (WockyAuthRegistry *registry, const GString *challenge_data, GAsyncReadyCallback callback, gpointer user_data) { GabbleAuthManager *self = GABBLE_AUTH_MANAGER (registry); if (self->priv->chaining_up) { WOCKY_AUTH_REGISTRY_CLASS ( gabble_auth_manager_parent_class)->challenge_async_func ( registry, challenge_data, callback, user_data); } else { GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, gabble_auth_manager_challenge_async); if (self->priv->channel != NULL) { gabble_server_sasl_channel_challenge_async (self->priv->channel, challenge_data, channel_challenge_cb, result); } else { g_assert (self->priv->error != NULL); g_simple_async_result_set_from_error (result, self->priv->error->wocky_error); g_simple_async_result_complete_in_idle (result); g_object_unref (result); } } } static gboolean gabble_auth_manager_challenge_finish (WockyAuthRegistry *registry, GAsyncResult *result, GString **response, GError **error) { GabbleAuthManager *self = GABBLE_AUTH_MANAGER (registry); if (self->priv->chaining_up) { return WOCKY_AUTH_REGISTRY_CLASS (gabble_auth_manager_parent_class)->challenge_finish_func ( registry, result, response, error); } else { wocky_implement_finish_copy_pointer (self, gabble_auth_manager_challenge_async, wocky_g_string_dup, response); } } static void channel_success_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { GabbleServerSaslChannel *channel = GABBLE_SERVER_SASL_CHANNEL (source); GSimpleAsyncResult *our_result = G_SIMPLE_ASYNC_RESULT (user_data); GError *error = NULL; if (!gabble_server_sasl_channel_success_finish (channel, result, &error)) g_simple_async_result_take_error (our_result, error); g_simple_async_result_complete (our_result); g_object_unref (our_result); } static void gabble_auth_manager_channel_success ( GabbleAuthManager *self, GSimpleAsyncResult *our_result, gboolean need_idle) { GabbleAuthManagerPrivate *priv = self->priv; if (priv->channel != NULL) { gabble_server_sasl_channel_success_async (self->priv->channel, channel_success_cb, our_result); return; } if (priv->error != NULL) g_simple_async_result_set_from_error (our_result, priv->error->wocky_error); if (need_idle) g_simple_async_result_complete_in_idle (our_result); else g_simple_async_result_complete (our_result); g_object_unref (our_result); } static void gabble_auth_manager_success_parent_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { GabbleAuthManager *self = GABBLE_AUTH_MANAGER (source); WockyAuthRegistry *registry = WOCKY_AUTH_REGISTRY (source); GSimpleAsyncResult *our_result = G_SIMPLE_ASYNC_RESULT (user_data); GError *error = NULL; if (!WOCKY_AUTH_REGISTRY_CLASS (gabble_auth_manager_parent_class)-> success_finish_func (registry, result, &error)) { g_simple_async_result_take_error (our_result, error); g_simple_async_result_complete (our_result); g_object_unref (our_result); } else { gabble_auth_manager_channel_success (self, our_result, FALSE); } } static void gabble_auth_manager_success_async (WockyAuthRegistry *registry, GAsyncReadyCallback callback, gpointer user_data) { GabbleAuthManager *self = GABBLE_AUTH_MANAGER (registry); GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, gabble_auth_manager_success_async); /* Annoyingly, in the X-TELEPATHY-PASSWORD case we actually want to both * chain up to the parent class, *and* pass the success notification out to * the client for consistency with other mechanisms. */ if (self->priv->chaining_up) { WOCKY_AUTH_REGISTRY_CLASS ( gabble_auth_manager_parent_class)->success_async_func ( registry, gabble_auth_manager_success_parent_cb, result); } else { gabble_auth_manager_channel_success (self, result, TRUE); } } static gboolean gabble_auth_manager_success_finish (WockyAuthRegistry *registry, GAsyncResult *result, GError **error) { GabbleAuthManager *self = GABBLE_AUTH_MANAGER (registry); wocky_implement_finish_void (self, gabble_auth_manager_success_async); } static void gabble_auth_manager_failure (WockyAuthRegistry *registry, GError *error) { GabbleAuthManager *self = GABBLE_AUTH_MANAGER (registry); if (self->priv->channel != NULL) { gabble_server_sasl_channel_fail (self->priv->channel, error); } if (self->priv->chaining_up) { void (*chain_up)(WockyAuthRegistry *, GError *) = WOCKY_AUTH_REGISTRY_CLASS (gabble_auth_manager_parent_class)-> failure_func; if (chain_up != NULL) chain_up (registry, error); } } static void gabble_auth_manager_class_init (GabbleAuthManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); WockyAuthRegistryClass *registry_class = WOCKY_AUTH_REGISTRY_CLASS (klass); GParamSpec *param_spec; g_type_class_add_private (klass, sizeof (GabbleAuthManagerPrivate)); object_class->constructed = gabble_auth_manager_constructed; object_class->dispose = gabble_auth_manager_dispose; object_class->finalize = gabble_auth_manager_finalize; object_class->get_property = gabble_auth_manager_get_property; object_class->set_property = gabble_auth_manager_set_property; registry_class->start_auth_async_func = gabble_auth_manager_start_auth_async; registry_class->start_auth_finish_func = gabble_auth_manager_start_auth_finish; registry_class->challenge_async_func = gabble_auth_manager_challenge_async; registry_class->challenge_finish_func = gabble_auth_manager_challenge_finish; registry_class->success_async_func = gabble_auth_manager_success_async; registry_class->success_finish_func = gabble_auth_manager_success_finish; registry_class->failure_func = gabble_auth_manager_failure; param_spec = g_param_spec_object ("connection", "GabbleConnection object", "Gabble connection object that owns this manager.", GABBLE_TYPE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); } static void gabble_auth_manager_foreach_channel (TpChannelManager *manager, TpExportableChannelFunc func, gpointer user_data) { GabbleAuthManager *self = GABBLE_AUTH_MANAGER (manager); if (self->priv->channel != NULL) func (TP_EXPORTABLE_CHANNEL (self->priv->channel), user_data); } static void channel_manager_iface_init (gpointer g_iface, gpointer iface_data) { TpChannelManagerIface *iface = g_iface; iface->foreach_channel = gabble_auth_manager_foreach_channel; /* These channels are not requestable. */ iface->ensure_channel = NULL; iface->create_channel = NULL; iface->request_channel = NULL; iface->foreach_channel_class = NULL; } gboolean gabble_auth_manager_get_failure_details (GabbleAuthManager *self, gchar **dbus_error, GHashTable **details, TpConnectionStatusReason *reason) { if (self->priv->channel != NULL) { return gabble_server_sasl_channel_get_failure_details ( self->priv->channel, dbus_error, details, reason, NULL); } else if (self->priv->error != NULL) { if (dbus_error != NULL) *dbus_error = g_strdup (self->priv->error->name); if (details != NULL) *details = g_hash_table_ref (self->priv->error->details); if (reason != NULL) *reason = self->priv->error->reason; return TRUE; } else { /* failure? what failure? I don't know anything about that :-( */ return FALSE; } } ������������������������������telepathy-gabble-0.18.3/src/conn-mail-notif.h�������������������������������������������������������0000644�0001750�0001750�00000002513�11423525546�022136� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * conn-mail-notif.h - Header for Gabble connection mail notification interface * Copyright (C) 2009 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __CONN_EMAIL_NOTIF_H__ #define __CONN_EMAIL_NOTIF_H__ #include <glib-object.h> #include "connection.h" G_BEGIN_DECLS void conn_mail_notif_init (GabbleConnection *conn); void conn_mail_notif_dispose (GabbleConnection *conn); void conn_mail_notif_iface_init (gpointer g_iface, gpointer iface_data); void conn_mail_notif_properties_getter (GObject *object, GQuark interface, GQuark name, GValue *value, gpointer getter_data); G_END_DECLS #endif /* __CONN_EMAIL_NOTIF_H__ */ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/jingle-tp-util.c��������������������������������������������������������0000664�0001750�0001750�00000005072�12332440117�021776� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * jingle-tp-util.c - Telepathy-flavoured Jingle utility functions * Copyright © 2008–2012 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "jingle-tp-util.h" WockyJingleMediaType wocky_jingle_media_type_from_tp (TpMediaStreamType type) { switch (type) { case TP_MEDIA_STREAM_TYPE_AUDIO: return WOCKY_JINGLE_MEDIA_TYPE_AUDIO; case TP_MEDIA_STREAM_TYPE_VIDEO: return WOCKY_JINGLE_MEDIA_TYPE_VIDEO; default: g_return_val_if_reached (WOCKY_JINGLE_MEDIA_TYPE_NONE); } } TpMediaStreamType wocky_jingle_media_type_to_tp (WockyJingleMediaType type) { switch (type) { case WOCKY_JINGLE_MEDIA_TYPE_AUDIO: return TP_MEDIA_STREAM_TYPE_AUDIO; case WOCKY_JINGLE_MEDIA_TYPE_VIDEO: return TP_MEDIA_STREAM_TYPE_VIDEO; default: g_return_val_if_reached (TP_MEDIA_STREAM_TYPE_AUDIO); } } static const gchar * const relay_type_map[] = { /* WOCKY_JINGLE_RELAY_TYPE_UDP */ "udp", /* WOCKY_JINGLE_RELAY_TYPE_TCP */ "tcp", /* WOCKY_JINGLE_RELAY_TYPE_TLS */ "tls", }; GPtrArray * gabble_build_tp_relay_info (GPtrArray *relays) { guint i; GPtrArray *tp_relays = g_ptr_array_sized_new (relays->len); g_ptr_array_set_free_func (tp_relays, (GDestroyNotify) g_hash_table_unref); for (i = 0; i < relays->len; i++) { WockyJingleRelay *relay = g_ptr_array_index (relays, i); g_return_val_if_fail (relay->type < WOCKY_N_JINGLE_RELAY_TYPES, tp_relays); g_ptr_array_add (tp_relays, tp_asv_new ( "type", G_TYPE_STRING, relay_type_map[relay->type], "ip", G_TYPE_STRING, relay->ip, "port", G_TYPE_UINT, relay->port, "username", G_TYPE_STRING, relay->username, "password", G_TYPE_STRING, relay->password, "component", G_TYPE_UINT, relay->component, NULL)); } return tp_relays; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/tube-dbus.c�������������������������������������������������������������0000664�0001750�0001750�00000147501�12332441362�021033� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * tube-dbus.c - Source for GabbleTubeDBus * Copyright (C) 2007-2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "tube-dbus.h" #include <string.h> #include <errno.h> #include <glib/gstdio.h> #include <dbus/dbus-glib.h> #include <dbus/dbus-glib-lowlevel.h> #include <wocky/wocky.h> #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #include "extensions/extensions.h" #define DEBUG_FLAG GABBLE_DEBUG_TUBES #include "bytestream-factory.h" #include "bytestream-ibb.h" #include "bytestream-iface.h" #include "connection.h" #include "debug.h" #include "disco.h" #include "gabble-signals-marshal.h" #include "muc-tube-dbus.h" #include "namespaces.h" #include "presence-cache.h" #include "tube-iface.h" #include "util.h" /* When we receive D-Bus messages to be delivered to the application and the * application is not yet connected to the D-Bus tube, theses D-Bus messages * are queued and delivered when the application connects to the D-Bus tube. * * If the application never connects, there is a risk that the contact sends * too many messages and eat all the memory. To avoid this, there is an * arbitrary limit on the queue size set to 4MB. */ #define MAX_QUEUE_SIZE (4096*1024) static void tube_iface_init (gpointer g_iface, gpointer iface_data); static void dbustube_iface_init (gpointer g_iface, gpointer iface_data); G_DEFINE_TYPE_WITH_CODE (GabbleTubeDBus, gabble_tube_dbus, TP_TYPE_BASE_CHANNEL, G_IMPLEMENT_INTERFACE (GABBLE_TYPE_TUBE_IFACE, tube_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_DBUS_TUBE, dbustube_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_TUBE, NULL); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP, tp_external_group_mixin_iface_init); ); static const gchar * const gabble_tube_dbus_channel_allowed_properties[] = { TP_IFACE_CHANNEL ".TargetHandle", TP_IFACE_CHANNEL ".TargetID", TP_IFACE_CHANNEL_TYPE_DBUS_TUBE ".ServiceName", NULL }; /* signals */ enum { OPENED, CLOSED, OFFERED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; /* properties */ enum { PROP_SELF_HANDLE = 1, PROP_ID, PROP_BYTESTREAM, PROP_STREAM_ID, PROP_TYPE, PROP_SERVICE, PROP_PARAMETERS, PROP_STATE, PROP_DBUS_ADDRESS, PROP_DBUS_NAME, PROP_DBUS_NAMES, PROP_MUC, PROP_SUPPORTED_ACCESS_CONTROLS, LAST_PROPERTY }; struct _GabbleTubeDBusPrivate { TpHandle self_handle; guint64 id; GabbleBytestreamIface *bytestream; gchar *stream_id; gchar *service; GHashTable *parameters; GabbleMucChannel *muc; TpSocketAccessControl access_control; /* GArray of guint */ GArray *supported_access_controls; /* For outgoing tubes, TRUE if the offer has been sent over the network. For * incoming tubes, always TRUE. */ gboolean offered; /* our unique D-Bus name on the virtual tube bus (NULL for 1-1 D-Bus tubes)*/ gchar *dbus_local_name; /* the address that we are listening for D-Bus connections on */ gchar *dbus_srv_addr; /* the path of the UNIX socket used by the D-Bus server */ gchar *socket_path; /* the server that's listening on dbus_srv_addr */ DBusServer *dbus_srv; /* the connection to dbus_srv from a local client, or NULL */ DBusConnection *dbus_conn; /* the queue of D-Bus messages to be delivered to a local client when it * will connect */ GSList *dbus_msg_queue; /* current size of the queue in bytes. The maximum is MAX_QUEUE_SIZE */ unsigned long dbus_msg_queue_size; /* mapping of contact handle -> D-Bus name (empty for 1-1 D-Bus tubes) */ GHashTable *dbus_names; /* mapping of D-Bus name -> contact handle */ GHashTable *dbus_name_to_handle; /* Message reassembly buffer (CONTACT tubes only) */ GString *reassembly_buffer; /* Number of bytes that will be in the next message, 0 if unknown */ guint32 reassembly_bytes_needed; gboolean dispose_has_run; }; #define GABBLE_TUBE_DBUS_GET_PRIVATE(obj) ((obj)->priv) static GPtrArray * gabble_tube_dbus_get_interfaces (TpBaseChannel *base) { GPtrArray *interfaces; interfaces = TP_BASE_CHANNEL_CLASS ( gabble_tube_dbus_parent_class)->get_interfaces (base); g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_TUBE); return interfaces; } static void data_received_cb (GabbleBytestreamIface *stream, TpHandle sender, GString *data, gpointer user_data); /* * Characters used are permissible both in filenames and in D-Bus names. (See * D-Bus specification for restrictions.) */ static void generate_ascii_string (guint len, gchar *buf) { const gchar *chars = "0123456789" "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "_-"; guint i; for (i = 0; i < len; i++) buf[i] = chars[g_random_int_range (0, 64)]; } static DBusHandlerResult filter_cb (DBusConnection *conn, DBusMessage *msg, void *user_data) { GabbleTubeDBus *tube = GABBLE_TUBE_DBUS (user_data); GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (tube); gchar *marshalled = NULL; gint len; if (dbus_message_get_type (msg) == DBUS_MESSAGE_TYPE_SIGNAL && !tp_strdiff (dbus_message_get_interface (msg), "org.freedesktop.DBus.Local") && !tp_strdiff (dbus_message_get_member (msg), "Disconnected")) { /* connection was disconnected */ DEBUG ("connection was disconnected"); dbus_connection_close (priv->dbus_conn); tp_clear_pointer (&priv->dbus_conn, dbus_connection_unref); goto out; } if (priv->dbus_local_name != NULL) { if (!dbus_message_set_sender (msg, priv->dbus_local_name)) DEBUG ("dbus_message_set_sender failed"); } if (!dbus_message_marshal (msg, &marshalled, &len)) goto out; if (GABBLE_IS_BYTESTREAM_MUC (priv->bytestream)) { /* This bytestream support direct send */ const gchar *dest; dest = dbus_message_get_destination (msg); if (dest != NULL) { TpHandle handle; handle = GPOINTER_TO_UINT (g_hash_table_lookup ( priv->dbus_name_to_handle, dest)); if (handle == 0) { DEBUG ("Unknown D-Bus name: %s", dest); goto out; } gabble_bytestream_muc_send_to ( GABBLE_BYTESTREAM_MUC (priv->bytestream), handle, len, marshalled); goto out; } } gabble_bytestream_iface_send (priv->bytestream, len, marshalled); out: if (marshalled != NULL) g_free (marshalled); return DBUS_HANDLER_RESULT_HANDLED; } static dbus_bool_t allow_all_connections (DBusConnection *conn, unsigned long uid, void *data) { return TRUE; } static void new_connection_cb (DBusServer *server, DBusConnection *conn, void *data) { GabbleTubeDBus *tube = GABBLE_TUBE_DBUS (data); GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (tube); guint32 serial; GSList *i; if (priv->dbus_conn != NULL) /* we already have a connection; drop this new one */ /* return without reffing conn means it will be dropped */ return; DEBUG ("got connection"); dbus_connection_ref (conn); dbus_connection_setup_with_g_main (conn, NULL); dbus_connection_add_filter (conn, filter_cb, tube, NULL); priv->dbus_conn = conn; if (priv->access_control == TP_SOCKET_ACCESS_CONTROL_LOCALHOST) { /* By default libdbus use Credentials access control. If user wants * to use the Localhost access control, we need to bypass this check. */ dbus_connection_set_unix_user_function (conn, allow_all_connections, NULL, NULL); } /* We may have received messages to deliver before the local connection is * established. Theses messages are kept in the dbus_msg_queue list and are * delivered as soon as we get the connection. */ DEBUG ("%u messages in the queue (%lu bytes)", g_slist_length (priv->dbus_msg_queue), priv->dbus_msg_queue_size); priv->dbus_msg_queue = g_slist_reverse (priv->dbus_msg_queue); for (i = priv->dbus_msg_queue; i != NULL; i = g_slist_delete_link (i, i)) { DBusMessage *msg = i->data; DEBUG ("delivering queued message from '%s' to '%s' on the " "new connection", dbus_message_get_sender (msg), dbus_message_get_destination (msg)); dbus_connection_send (priv->dbus_conn, msg, &serial); dbus_message_unref (msg); } priv->dbus_msg_queue = NULL; priv->dbus_msg_queue_size = 0; } static void gabble_tube_dbus_close (TpBaseChannel *base) { GabbleTubeDBus *self = GABBLE_TUBE_DBUS (base); GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self); /* Take a ref to ourselves as when we emit tube-closed * GabbleTubesChannel will drop our last ref but we still need to * declare ourselves as destroyed. This is rubbish, but will * disappear when we finally remove the Tubes channel type.. */ g_object_ref (base); if (priv->bytestream != NULL) gabble_bytestream_iface_close (priv->bytestream, NULL); else g_signal_emit (G_OBJECT (self), signals[CLOSED],0); tp_base_channel_destroyed (base); g_object_unref (base); } /* There is two step to enable receiving a D-Bus connection from the local * application: * - listen on the socket * - add the socket in the mainloop * * We need to know the socket path to return from the AcceptDBusTube D-Bus * call but the socket in the mainloop must be added only when we are ready * to receive connections, that is when the bytestream is fully open with the * remote contact. * * See also Bug 13891: * https://bugs.freedesktop.org/show_bug.cgi?id=13891 * */ static gboolean create_dbus_server (GabbleTubeDBus *self, GError **err) { #define SERVER_LISTEN_MAX_TRIES 5 GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self); guint i; if (priv->dbus_srv != NULL) return TRUE; for (i = 0; i < SERVER_LISTEN_MAX_TRIES; i++) { gchar suffix[8]; DBusError error; g_free (priv->dbus_srv_addr); g_free (priv->socket_path); generate_ascii_string (8, suffix); priv->socket_path = g_strdup_printf ("%s/dbus-gabble-%.8s", g_get_tmp_dir (), suffix); priv->dbus_srv_addr = g_strdup_printf ("unix:path=%s", priv->socket_path); dbus_error_init (&error); priv->dbus_srv = dbus_server_listen (priv->dbus_srv_addr, &error); if (priv->dbus_srv != NULL) break; DEBUG ("dbus_server_listen failed (try %u): %s: %s", i, error.name, error.message); dbus_error_free (&error); } if (priv->dbus_srv == NULL) { DEBUG ("all attempts failed. Close the tube"); g_free (priv->dbus_srv_addr); priv->dbus_srv_addr = NULL; g_free (priv->socket_path); priv->socket_path = NULL; g_set_error (err, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "Can't create D-Bus server"); return FALSE; } DEBUG ("listening on %s", priv->dbus_srv_addr); dbus_server_set_new_connection_function (priv->dbus_srv, new_connection_cb, self, NULL); return TRUE; } static void tube_dbus_open (GabbleTubeDBus *self) { GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self); TpBaseChannel *base = TP_BASE_CHANNEL (self); TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base); g_signal_connect (priv->bytestream, "data-received", G_CALLBACK (data_received_cb), self); /* TODO: we should remove this call once muc D-Bus tube new API are * implemented as the server should already exist. */ if (!create_dbus_server (self, NULL)) tp_base_channel_close (TP_BASE_CHANNEL (self)); if (priv->dbus_srv != NULL) { dbus_server_setup_with_g_main (priv->dbus_srv, NULL); } if (cls->target_handle_type == TP_HANDLE_TYPE_ROOM) { /* add yourself in dbus names */ gabble_tube_dbus_add_name (self, priv->self_handle, priv->dbus_local_name); gabble_muc_channel_send_presence (priv->muc); } } static void gabble_tube_dbus_init (GabbleTubeDBus *self) { GabbleTubeDBusPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_TUBE_DBUS, GabbleTubeDBusPrivate); self->priv = priv; } static TpTubeChannelState get_tube_state (GabbleTubeDBus *self) { GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self); GabbleBytestreamState bytestream_state; if (!priv->offered) return TP_TUBE_CHANNEL_STATE_NOT_OFFERED; if (priv->bytestream == NULL) /* bytestream not yet created as we're waiting for the SI reply */ return TP_TUBE_CHANNEL_STATE_REMOTE_PENDING; g_object_get (priv->bytestream, "state", &bytestream_state, NULL); switch (bytestream_state) { case GABBLE_BYTESTREAM_STATE_OPEN: return TP_TUBE_CHANNEL_STATE_OPEN; break; case GABBLE_BYTESTREAM_STATE_LOCAL_PENDING: case GABBLE_BYTESTREAM_STATE_ACCEPTED: return TP_TUBE_CHANNEL_STATE_LOCAL_PENDING; break; case GABBLE_BYTESTREAM_STATE_INITIATING: return TP_TUBE_CHANNEL_STATE_REMOTE_PENDING; break; default: g_return_val_if_reached (0); } } static void bytestream_state_changed_cb (GabbleBytestreamIface *bytestream, GabbleBytestreamState state, gpointer user_data) { GabbleTubeDBus *self = GABBLE_TUBE_DBUS (user_data); GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self); TpBaseChannel *base = TP_BASE_CHANNEL (self); TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base); if (state == GABBLE_BYTESTREAM_STATE_CLOSED) { tp_clear_object (&priv->bytestream); g_signal_emit (G_OBJECT (self), signals[CLOSED], 0); if (cls->target_handle_type == TP_HANDLE_TYPE_ROOM) gabble_muc_channel_send_presence (priv->muc); } else if (state == GABBLE_BYTESTREAM_STATE_OPEN) { tube_dbus_open (self); tp_svc_channel_interface_tube_emit_tube_channel_state_changed (self, TP_TUBE_CHANNEL_STATE_OPEN); g_signal_emit (G_OBJECT (self), signals[OPENED], 0); } } static void gabble_tube_dbus_dispose (GObject *object) { GabbleTubeDBus *self = GABBLE_TUBE_DBUS (object); GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self); DEBUG ("called"); if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; if (priv->bytestream != NULL) gabble_bytestream_iface_close (priv->bytestream, NULL); if (priv->dbus_conn != NULL) dbus_connection_close (priv->dbus_conn); tp_clear_pointer (&priv->dbus_conn, dbus_connection_unref); if (priv->dbus_srv != NULL) dbus_server_disconnect (priv->dbus_srv); tp_clear_pointer (&priv->dbus_srv, dbus_server_unref); if (priv->socket_path != NULL) { if (g_unlink (priv->socket_path) != 0) { DEBUG ("unlink of %s failed: %s", priv->socket_path, g_strerror (errno)); } } if (priv->dbus_msg_queue != NULL) { GSList *i; for (i = priv->dbus_msg_queue; i != NULL; i = g_slist_delete_link (i, i)) { DBusMessage *msg = i->data; dbus_message_unref (msg); } priv->dbus_msg_queue = NULL; priv->dbus_msg_queue_size = 0; } tp_clear_pointer (&priv->dbus_srv_addr, g_free); tp_clear_pointer (&priv->socket_path, g_free); tp_clear_pointer (&priv->dbus_local_name, g_free); tp_clear_pointer (&priv->dbus_names, g_hash_table_unref); tp_clear_pointer (&priv->dbus_name_to_handle, g_hash_table_unref); if (priv->reassembly_buffer) g_string_free (priv->reassembly_buffer, TRUE); if (G_OBJECT_CLASS (gabble_tube_dbus_parent_class)->dispose) G_OBJECT_CLASS (gabble_tube_dbus_parent_class)->dispose (object); } static void gabble_tube_dbus_finalize (GObject *object) { GabbleTubeDBus *self = GABBLE_TUBE_DBUS (object); GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self); g_free (priv->stream_id); g_free (priv->service); g_hash_table_unref (priv->parameters); g_array_unref (priv->supported_access_controls); if (priv->muc != NULL) tp_external_group_mixin_finalize (object); G_OBJECT_CLASS (gabble_tube_dbus_parent_class)->finalize (object); } static void gabble_tube_dbus_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleTubeDBus *self = GABBLE_TUBE_DBUS (object); GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self); switch (property_id) { case PROP_SELF_HANDLE: g_value_set_uint (value, priv->self_handle); break; case PROP_ID: g_value_set_uint64 (value, priv->id); break; case PROP_BYTESTREAM: g_value_set_object (value, priv->bytestream); break; case PROP_STREAM_ID: g_value_set_string (value, priv->stream_id); break; case PROP_TYPE: g_value_set_uint (value, TP_TUBE_TYPE_DBUS); break; case PROP_SERVICE: g_value_set_string (value, priv->service); break; case PROP_PARAMETERS: g_value_set_boxed (value, priv->parameters); break; case PROP_STATE: g_value_set_uint (value, get_tube_state (self)); break; case PROP_DBUS_ADDRESS: g_value_set_string (value, priv->dbus_srv_addr); break; case PROP_DBUS_NAME: g_value_set_string (value, priv->dbus_local_name); break; case PROP_DBUS_NAMES: g_value_set_boxed (value, priv->dbus_names); break; case PROP_MUC: g_value_set_object (value, priv->muc); break; case PROP_SUPPORTED_ACCESS_CONTROLS: g_value_set_boxed (value, priv->supported_access_controls); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_tube_dbus_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleTubeDBus *self = GABBLE_TUBE_DBUS (object); GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self); switch (property_id) { case PROP_SELF_HANDLE: priv->self_handle = g_value_get_uint (value); break; case PROP_ID: priv->id = g_value_get_uint64 (value); break; case PROP_BYTESTREAM: if (priv->bytestream == NULL) { GabbleBytestreamState state; priv->bytestream = g_value_get_object (value); g_object_ref (priv->bytestream); g_object_get (priv->bytestream, "state", &state, NULL); if (state == GABBLE_BYTESTREAM_STATE_OPEN) { tube_dbus_open (self); } g_signal_connect (priv->bytestream, "state-changed", G_CALLBACK (bytestream_state_changed_cb), self); } break; case PROP_STREAM_ID: g_free (priv->stream_id); priv->stream_id = g_value_dup_string (value); break; case PROP_SERVICE: g_free (priv->service); priv->service = g_value_dup_string (value); break; case PROP_PARAMETERS: if (priv->parameters != NULL) g_hash_table_unref (priv->parameters); priv->parameters = g_value_dup_boxed (value); break; case PROP_MUC: priv->muc = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_tube_dbus_constructed (GObject *obj) { GabbleTubeDBus *self = GABBLE_TUBE_DBUS (obj); GabbleTubeDBusPrivate *priv = self->priv; TpBaseChannel *base = TP_BASE_CHANNEL (obj); TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base); TpBaseConnection *base_conn = tp_base_channel_get_connection (base); GabbleConnection *conn = GABBLE_CONNECTION (base_conn); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( base_conn, TP_HANDLE_TYPE_CONTACT); guint access_control; void (*chain_up) (GObject *) = ((GObjectClass *) gabble_tube_dbus_parent_class)->constructed; if (chain_up != NULL) chain_up (obj); priv->dbus_names = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); g_assert (priv->self_handle != 0); if (cls->target_handle_type == TP_HANDLE_TYPE_ROOM) { /* We have to create a pseudo-IBB bytestream that will be * used by this MUC tube to communicate. */ GabbleBytestreamMuc *bytestream; gchar *nick; g_assert (priv->stream_id != NULL); priv->dbus_name_to_handle = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); g_assert (wocky_decode_jid ( tp_handle_inspect (contact_repo, priv->self_handle), NULL, NULL, &nick)); g_assert (nick != NULL); priv->dbus_local_name = _gabble_generate_dbus_unique_name (nick); DEBUG ("local name: %s", priv->dbus_local_name); bytestream = gabble_bytestream_factory_create_muc ( conn->bytestream_factory, tp_base_channel_get_target_handle (base), priv->stream_id, GABBLE_BYTESTREAM_STATE_LOCAL_PENDING); g_object_set (self, "bytestream", bytestream, NULL); g_free (nick); g_assert (priv->muc != NULL); tp_external_group_mixin_init (obj, (GObject *) priv->muc); } else { /* The D-Bus names mapping is used in muc tubes only */ priv->dbus_local_name = NULL; priv->dbus_name_to_handle = NULL; /* For contact (IBB) tubes we need to be able to reassemble messages. */ priv->reassembly_buffer = g_string_new (""); priv->reassembly_bytes_needed = 0; g_assert (priv->muc == NULL); if (tp_base_channel_is_requested (base)) { /* We created this outgoing 1-1 D-Bus tube and so will need SOCKS5 * proxies when we'll offer it. */ gabble_bytestream_factory_query_socks5_proxies ( conn->bytestream_factory); } } /* Tube needs to be offered if we initiated AND requested it. Being * the initiator is not enough as we could re-join a muc containing and old * tube we created when we were in this room some time ago. In that case, we * have to accept it if we want to re-join the tube. */ if (tp_base_channel_get_initiator (base) == priv->self_handle && tp_base_channel_is_requested (base)) { priv->offered = FALSE; } else { /* Incoming tubes have already been offered, as it were. */ priv->offered = TRUE; } /* default access control is Credentials as that's the one used by the old * tube API */ priv->access_control = TP_SOCKET_ACCESS_CONTROL_CREDENTIALS; /* Set SupportedAccessesControl */ priv->supported_access_controls = g_array_sized_new (FALSE, FALSE, sizeof (guint), 1); access_control = TP_SOCKET_ACCESS_CONTROL_CREDENTIALS; g_array_append_val (priv->supported_access_controls, access_control); access_control = TP_SOCKET_ACCESS_CONTROL_LOCALHOST; g_array_append_val (priv->supported_access_controls, access_control); } static void gabble_tube_dbus_fill_immutable_properties (TpBaseChannel *chan, GHashTable *properties) { TpBaseChannelClass *cls = TP_BASE_CHANNEL_CLASS ( gabble_tube_dbus_parent_class); cls->fill_immutable_properties (chan, properties); tp_dbus_properties_mixin_fill_properties_hash ( G_OBJECT (chan), properties, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE, "ServiceName", TP_IFACE_CHANNEL_TYPE_DBUS_TUBE, "SupportedAccessControls", NULL); if (!tp_base_channel_is_requested (chan)) { tp_dbus_properties_mixin_fill_properties_hash ( G_OBJECT (chan), properties, TP_IFACE_CHANNEL_INTERFACE_TUBE, "Parameters", NULL); } } static gchar * gabble_tube_dbus_get_object_path_suffix (TpBaseChannel *base) { GabbleTubeDBus *self = GABBLE_TUBE_DBUS (base); return g_strdup_printf ("DBusTubeChannel/%u/%" G_GUINT64_FORMAT, tp_base_channel_get_target_handle (base), self->priv->id); } static void gabble_tube_dbus_class_init (GabbleTubeDBusClass *gabble_tube_dbus_class) { static TpDBusPropertiesMixinPropImpl dbus_tube_props[] = { { "ServiceName", "service", NULL }, { "DBusNames", "dbus-names", NULL }, { "SupportedAccessControls", "supported-access-controls", NULL }, { NULL } }; static TpDBusPropertiesMixinPropImpl tube_iface_props[] = { { "Parameters", "parameters", NULL }, { "State", "state", NULL }, { NULL } }; static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { { TP_IFACE_CHANNEL_TYPE_DBUS_TUBE, tp_dbus_properties_mixin_getter_gobject_properties, NULL, dbus_tube_props, }, { TP_IFACE_CHANNEL_INTERFACE_TUBE, tp_dbus_properties_mixin_getter_gobject_properties, NULL, tube_iface_props, }, { NULL } }; GObjectClass *object_class = G_OBJECT_CLASS (gabble_tube_dbus_class); TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (gabble_tube_dbus_class); GParamSpec *param_spec; object_class->get_property = gabble_tube_dbus_get_property; object_class->set_property = gabble_tube_dbus_set_property; object_class->constructed = gabble_tube_dbus_constructed; object_class->dispose = gabble_tube_dbus_dispose; object_class->finalize = gabble_tube_dbus_finalize; base_class->channel_type = TP_IFACE_CHANNEL_TYPE_DBUS_TUBE; base_class->get_interfaces = gabble_tube_dbus_get_interfaces; base_class->target_handle_type = TP_HANDLE_TYPE_CONTACT; base_class->close = gabble_tube_dbus_close; base_class->fill_immutable_properties = gabble_tube_dbus_fill_immutable_properties; base_class->get_object_path_suffix = gabble_tube_dbus_get_object_path_suffix; g_type_class_add_private (gabble_tube_dbus_class, sizeof (GabbleTubeDBusPrivate)); g_object_class_override_property (object_class, PROP_SELF_HANDLE, "self-handle"); g_object_class_override_property (object_class, PROP_ID, "id"); g_object_class_override_property (object_class, PROP_TYPE, "type"); g_object_class_override_property (object_class, PROP_SERVICE, "service"); g_object_class_override_property (object_class, PROP_PARAMETERS, "parameters"); g_object_class_override_property (object_class, PROP_STATE, "state"); param_spec = g_param_spec_object ( "bytestream", "Object implementing the GabbleBytestreamIface interface", "Bytestream object used for streaming data for this" "tube object.", G_TYPE_OBJECT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_BYTESTREAM, param_spec); param_spec = g_param_spec_string ( "stream-id", "stream id", "The identifier of this tube's bytestream", "", G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_STREAM_ID, param_spec); param_spec = g_param_spec_string ( "dbus-address", "D-Bus address", "The D-Bus address on which this tube will listen for connections", "", G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_DBUS_ADDRESS, param_spec); param_spec = g_param_spec_string ( "dbus-name", "D-Bus name", "The local D-Bus name on the virtual bus (used for muc tubes only).", "", G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_DBUS_NAME, param_spec); param_spec = g_param_spec_boxed ( "dbus-names", "D-Bus names", "Mapping of contact handles to D-Bus names (used for muc tubes only).", TP_HASH_TYPE_DBUS_TUBE_PARTICIPANTS, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_DBUS_NAMES, param_spec); param_spec = g_param_spec_object ("muc", "GabbleMucChannel object", "Gabble text MUC channel corresponding to this Tube channel object, " "if the handle type is ROOM.", GABBLE_TYPE_MUC_CHANNEL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_MUC, param_spec); param_spec = g_param_spec_boxed ( "supported-access-controls", "Supported access-controls", "GArray containing supported access controls.", DBUS_TYPE_G_UINT_ARRAY, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SUPPORTED_ACCESS_CONTROLS, param_spec); signals[OPENED] = g_signal_new ("tube-opened", G_OBJECT_CLASS_TYPE (gabble_tube_dbus_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[CLOSED] = g_signal_new ("tube-closed", G_OBJECT_CLASS_TYPE (gabble_tube_dbus_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[OFFERED] = g_signal_new ("tube-offered", G_OBJECT_CLASS_TYPE (gabble_tube_dbus_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); gabble_tube_dbus_class->dbus_props_class.interfaces = prop_interfaces; tp_dbus_properties_mixin_class_init (object_class, G_STRUCT_OFFSET (GabbleTubeDBusClass, dbus_props_class)); tp_external_group_mixin_init_dbus_properties (object_class); } static void bytestream_negotiate_cb (GabbleBytestreamIface *bytestream, WockyStanza *msg, GObject *object, gpointer user_data) { GabbleTubeIface *tube = user_data; if (bytestream == NULL) { /* Tube was declined by remote user. Close it */ gabble_tube_iface_close (tube, TRUE); return; } /* Tube was accepted by remote user */ g_object_set (tube, "bytestream", bytestream, NULL); gabble_tube_iface_accept (tube, NULL); } gboolean gabble_tube_dbus_offer (GabbleTubeDBus *tube, GError **error) { GabbleTubeDBusPrivate *priv = tube->priv; TpBaseChannel *base = TP_BASE_CHANNEL (tube); TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base); TpBaseConnection *base_conn = tp_base_channel_get_connection (base); GabbleConnection *conn = GABBLE_CONNECTION (base_conn); if (priv->offered) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Tube has already been offered"); return FALSE; } if (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( base_conn, TP_HANDLE_TYPE_CONTACT); const gchar *jid, *resource; gchar *full_jid; GabblePresence *presence; WockyNode *tube_node, *si_node; WockyStanza *msg; jid = tp_handle_inspect (contact_repo, tp_base_channel_get_target_handle (base)); presence = gabble_presence_cache_get (conn->presence_cache, tp_base_channel_get_target_handle (base)); if (presence == NULL) { DEBUG ("can't find contact %s's presence", jid); g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "can't find contact %s's presence", jid); return FALSE; } resource = gabble_presence_pick_resource_by_caps (presence, 0, gabble_capability_set_predicate_has, NS_TUBES); if (resource == NULL) { DEBUG ("contact %s doesn't have tubes capabilities", jid); g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "contact %s doesn't have tubes capabilities", jid); return FALSE; } full_jid = g_strdup_printf ("%s/%s", jid, resource); msg = gabble_bytestream_factory_make_stream_init_iq (full_jid, priv->stream_id, NS_TUBES); si_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "si", NS_SI); g_assert (si_node != NULL); tube_node = wocky_node_add_child_ns (si_node, "tube", NS_TUBES); gabble_tube_iface_publish_in_node (GABBLE_TUBE_IFACE (tube), base_conn, tube_node); tube->priv->offered = TRUE; gabble_bytestream_factory_negotiate_stream ( conn->bytestream_factory, msg, priv->stream_id, bytestream_negotiate_cb, tube, G_OBJECT (tube)); /* We don't create the bytestream of private D-Bus tube yet. * It will be when we'll receive the answer of the SI request */ g_object_unref (msg); g_free (full_jid); tp_svc_channel_interface_tube_emit_tube_channel_state_changed (tube, TP_TUBE_CHANNEL_STATE_REMOTE_PENDING); } else { tube->priv->offered = TRUE; g_object_set (priv->bytestream, "state", GABBLE_BYTESTREAM_STATE_OPEN, NULL); gabble_muc_channel_send_presence (priv->muc); } if (!create_dbus_server (tube, error)) return FALSE; g_signal_emit (G_OBJECT (tube), signals[OFFERED], 0); return TRUE; } static void message_received (GabbleTubeDBus *tube, TpHandle sender, const char *data, size_t len) { GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (tube); TpBaseChannel *base = TP_BASE_CHANNEL (tube); TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base); DBusMessage *msg; DBusError error = {0,}; const gchar *sender_name; const gchar *destination; guint32 serial; msg = dbus_message_demarshal (data, len, &error); if (msg == NULL) { /* message was corrupted */ DEBUG ("received corrupted message from %d: %s: %s", sender, error.name, error.message); dbus_error_free (&error); return; } if (cls->target_handle_type == TP_HANDLE_TYPE_ROOM) { destination = dbus_message_get_destination (msg); /* If destination is NULL this msg is broadcasted (signals) so we don't * have to check it */ if (destination != NULL && tp_strdiff (priv->dbus_local_name, destination)) { /* This message is not intended for this participant. * Discard it. */ DEBUG ("message not intended for this participant (destination = " "%s)", destination); goto unref; } sender_name = g_hash_table_lookup (priv->dbus_names, GUINT_TO_POINTER (sender)); if (tp_strdiff (sender_name, dbus_message_get_sender (msg))) { DEBUG ("invalid sender %s (expected %s for sender handle %d)", dbus_message_get_sender (msg), sender_name, sender); goto unref; } } if (!priv->dbus_conn) { DEBUG ("no D-Bus connection: queuing the message"); /* If the application never connects to the private dbus connection, we * don't want to eat all the memory. Only queue MAX_QUEUE_SIZE bytes. If * there are more messages, drop them. */ if (priv->dbus_msg_queue_size + len > MAX_QUEUE_SIZE) { DEBUG ("D-Bus message queue size limit reached (%u bytes). " "Ignore this message.", MAX_QUEUE_SIZE); goto unref; } priv->dbus_msg_queue = g_slist_prepend (priv->dbus_msg_queue, msg); priv->dbus_msg_queue_size += len; /* returns without unref the message */ return; } DEBUG ("delivering message from '%s' to '%s'", dbus_message_get_sender (msg), dbus_message_get_destination (msg)); /* XXX: what do do if this returns FALSE? */ dbus_connection_send (priv->dbus_conn, msg, &serial); unref: dbus_message_unref (msg); } static guint32 collect_le32 (char *str) { unsigned char *bytes = (unsigned char *) str; return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24); } static guint32 collect_be32 (char *str) { unsigned char *bytes = (unsigned char *) str; return (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 24) | bytes[3]; } static void data_received_cb (GabbleBytestreamIface *stream, TpHandle sender, GString *data, gpointer user_data) { GabbleTubeDBus *tube = GABBLE_TUBE_DBUS (user_data); GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (tube); TpBaseChannel *base = TP_BASE_CHANNEL (tube); TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base); if (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT) { GString *buf = priv->reassembly_buffer; g_assert (buf != NULL); g_string_append_len (buf, data->str, data->len); DEBUG ("Received %" G_GSIZE_FORMAT " bytes, so we now have %" G_GSIZE_FORMAT " bytes in reassembly buffer", data->len, buf->len); /* Each D-Bus message has a 16-byte fixed header, in which * * * byte 0 is 'l' (ell) or 'B' for endianness * * bytes 4-7 are body length "n" in bytes in that endianness * * bytes 12-15 are length "m" of param array in bytes in that * endianness * * followed by m + n + ((8 - (m % 8)) % 8) bytes of other content. */ while (buf->len >= 16) { guint32 body_length, params_length, m; /* see if we have a whole message and have already calculated * how many bytes it needs */ if (priv->reassembly_bytes_needed != 0) { if (buf->len >= priv->reassembly_bytes_needed) { DEBUG ("Received complete D-Bus message of size %" G_GINT32_FORMAT, priv->reassembly_bytes_needed); message_received (tube, sender, buf->str, priv->reassembly_bytes_needed); g_string_erase (buf, 0, priv->reassembly_bytes_needed); priv->reassembly_bytes_needed = 0; } else { /* we'll have to wait for more data */ break; } } if (buf->len < 16) break; /* work out how big the next message is going to be */ if (buf->str[0] == DBUS_BIG_ENDIAN) { body_length = collect_be32 (buf->str + 4); m = collect_be32 (buf->str + 12); } else if (buf->str[0] == DBUS_LITTLE_ENDIAN) { body_length = collect_le32 (buf->str + 4); m = collect_le32 (buf->str + 12); } else { DEBUG ("D-Bus message has unknown endianness byte 0x%x, " "closing tube", (unsigned int) buf->str[0]); gabble_tube_iface_close ((GabbleTubeIface *) tube, TRUE); return; } /* pad to 8-byte boundary */ params_length = m + ((8 - (m % 8)) % 8); g_assert (params_length % 8 == 0); g_assert (params_length >= m); g_assert (params_length < m + 8); priv->reassembly_bytes_needed = params_length + body_length + 16; /* n.b.: this looks as if it could be simplified to just the third * test, but that would be wrong if the addition had overflowed, so * don't do that. The first and second tests are sufficient to * ensure no overflow on 32-bit platforms */ if (body_length > DBUS_MAXIMUM_MESSAGE_LENGTH || params_length > DBUS_MAXIMUM_ARRAY_LENGTH || priv->reassembly_bytes_needed > DBUS_MAXIMUM_MESSAGE_LENGTH) { DEBUG ("D-Bus message is too large to be valid, closing tube"); gabble_tube_iface_close ((GabbleTubeIface *) tube, TRUE); return; } g_assert (priv->reassembly_bytes_needed != 0); DEBUG ("We need %" G_GINT32_FORMAT " bytes for the next full " "message", priv->reassembly_bytes_needed); } } else { /* MUC bytestreams are message-boundary preserving, which is necessary, * because we can't assume we started at the beginning */ g_assert (GABBLE_IS_BYTESTREAM_MUC (priv->bytestream)); message_received (tube, sender, data->str, data->len); } } GabbleTubeDBus * gabble_tube_dbus_new (GabbleConnection *conn, TpHandle handle, TpHandleType handle_type, TpHandle self_handle, TpHandle initiator, const gchar *service, GHashTable *parameters, const gchar *stream_id, guint64 id, GabbleBytestreamIface *bytestream, GabbleMucChannel *muc, gboolean requested) { GabbleTubeDBus *tube; GType gtype = GABBLE_TYPE_TUBE_DBUS; if (handle_type == TP_HANDLE_TYPE_ROOM) gtype = GABBLE_TYPE_MUC_TUBE_DBUS; tube = g_object_new (gtype, "connection", conn, "handle", handle, "self-handle", self_handle, "initiator-handle", initiator, "service", service, "parameters", parameters, "stream-id", stream_id, "id", id, "muc", muc, "requested", requested, NULL); if (bytestream != NULL) g_object_set (tube, "bytestream", bytestream, NULL); return tube; } static void augment_si_accept_iq (WockyNode *si, gpointer user_data) { wocky_node_add_child_ns (si, "tube", NS_TUBES); } /* * gabble_tube_dbus_accept * * Implements gabble_tube_iface_accept on GabbleTubeIface */ static gboolean gabble_tube_dbus_accept (GabbleTubeIface *tube, GError **error) { GabbleTubeDBus *self = GABBLE_TUBE_DBUS (tube); GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self); TpBaseChannel *base = TP_BASE_CHANNEL (tube); TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base); GabbleBytestreamState state; g_assert (priv->bytestream != NULL); g_object_get (priv->bytestream, "state", &state, NULL); if (state != GABBLE_BYTESTREAM_STATE_LOCAL_PENDING) return TRUE; if (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT) { /* Bytestream was created using a SI request so * we have to accept it */ DEBUG ("accept the SI request"); gabble_bytestream_iface_accept (priv->bytestream, augment_si_accept_iq, self); } else { /* No SI so the bytestream is open */ DEBUG ("no SI, bytestream open"); g_object_set (priv->bytestream, "state", GABBLE_BYTESTREAM_STATE_OPEN, NULL); } if (!create_dbus_server (self, error)) return FALSE; return TRUE; } /* * gabble_tube_iface_dbus_close * * Implements gabble_tube_iface_close on GabbleTubeIface */ static void gabble_tube_iface_dbus_close (GabbleTubeIface *tube, gboolean closed_remotely) { tp_base_channel_close (TP_BASE_CHANNEL (tube)); } /** * gabble_tube_dbus_add_bytestream * * Implements gabble_tube_iface_add_bytestream on GabbleTubeIface */ static void gabble_tube_dbus_add_bytestream (GabbleTubeIface *tube, GabbleBytestreamIface *bytestream) { /* FIXME: should we support this, if we don't have a bytestream yet? */ DEBUG ("D-Bus doesn't support extra bytestream"); gabble_bytestream_iface_close (bytestream, NULL); } gboolean gabble_tube_dbus_add_name (GabbleTubeDBus *self, TpHandle handle, const gchar *name) { GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self); TpBaseChannel *base = TP_BASE_CHANNEL (self); TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base); TpBaseConnection *base_conn = tp_base_channel_get_connection (base); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( base_conn, TP_HANDLE_TYPE_CONTACT); gchar *name_copy; GHashTable *added; GArray *removed; g_assert (cls->target_handle_type == TP_HANDLE_TYPE_ROOM); g_assert (g_hash_table_size (priv->dbus_names) == g_hash_table_size (priv->dbus_name_to_handle)); if (g_hash_table_lookup (priv->dbus_names, GUINT_TO_POINTER (handle)) != NULL) { DEBUG ("contact %d has already announced his D-Bus name", handle); return FALSE; } if (g_hash_table_lookup (priv->dbus_name_to_handle, name) != NULL) { DEBUG ("D-Bus name %s already used", name); return FALSE; } if (g_str_has_prefix (name, ":2.")) { gchar *nick, *supposed_name; const gchar *jid; jid = tp_handle_inspect (contact_repo, handle); g_assert (wocky_decode_jid (jid, NULL, NULL, &nick)); supposed_name = _gabble_generate_dbus_unique_name (nick); g_free (nick); if (tp_strdiff (name, supposed_name)) { DEBUG ("contact %s announces %s as D-Bus name but it should be %s", jid, name, supposed_name); g_free (supposed_name); return FALSE; } g_free (supposed_name); } name_copy = g_strdup (name); g_hash_table_insert (priv->dbus_names, GUINT_TO_POINTER (handle), name_copy); g_hash_table_insert (priv->dbus_name_to_handle, name_copy, GUINT_TO_POINTER (handle)); /* Fire DBusNamesChanged (new API) */ added = g_hash_table_new (g_direct_hash, g_direct_equal); removed = g_array_new (FALSE, FALSE, sizeof (TpHandle)); g_hash_table_insert (added, GUINT_TO_POINTER (handle), (gchar *) name); tp_svc_channel_type_dbus_tube_emit_dbus_names_changed (self, added, removed); g_hash_table_unref (added); g_array_unref (removed); return TRUE; } gboolean gabble_tube_dbus_remove_name (GabbleTubeDBus *self, TpHandle handle) { GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self); TpBaseChannel *base = TP_BASE_CHANNEL (self); TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base); const gchar *name; GHashTable *added; GArray *removed; g_assert (cls->target_handle_type == TP_HANDLE_TYPE_ROOM); name = g_hash_table_lookup (priv->dbus_names, GUINT_TO_POINTER (handle)); if (name == NULL) return FALSE; g_hash_table_remove (priv->dbus_name_to_handle, name); g_hash_table_remove (priv->dbus_names, GUINT_TO_POINTER (handle)); g_assert (g_hash_table_size (priv->dbus_names) == g_hash_table_size (priv->dbus_name_to_handle)); /* Fire DBusNamesChanged (new API) */ added = g_hash_table_new (g_direct_hash, g_direct_equal); removed = g_array_new (FALSE, FALSE, sizeof (TpHandle)); g_array_append_val (removed, handle); tp_svc_channel_type_dbus_tube_emit_dbus_names_changed (self, added, removed); g_hash_table_unref (added); g_array_unref (removed); return TRUE; } gboolean gabble_tube_dbus_handle_in_names (GabbleTubeDBus *self, TpHandle handle) { GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (self); TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (self); g_assert (cls->target_handle_type == TP_HANDLE_TYPE_ROOM); return (g_hash_table_lookup (priv->dbus_names, GUINT_TO_POINTER (handle)) != NULL); } gchar * _gabble_generate_dbus_unique_name (const gchar *nick) { gchar *encoded, *result; size_t len; guint i; len = strlen (nick); if (len <= 186) { encoded = g_base64_encode ((const guchar *) nick, len); } else { guchar sha1[20]; GString *tmp; sha1_bin (nick, len, sha1); tmp = g_string_sized_new (169 + 20); g_string_append_len (tmp, nick, 169); g_string_append_len (tmp, (const gchar *) sha1, 20); encoded = g_base64_encode ((const guchar *) tmp->str, tmp->len); g_string_free (tmp, TRUE); } for (i = 0; encoded[i] != '\0'; i++) { switch (encoded[i]) { case '+': encoded[i] = '_'; break; case '/': encoded[i] = '-'; break; case '=': encoded[i] = 'A'; break; } } result = g_strdup_printf (":2.%s", encoded); g_free (encoded); return result; } const gchar * const * gabble_tube_dbus_channel_get_allowed_properties (void) { return gabble_tube_dbus_channel_allowed_properties; } static gboolean gabble_tube_dbus_check_access_control (GabbleTubeDBus *self, guint access_control, GError **error) { switch (access_control) { case TP_SOCKET_ACCESS_CONTROL_CREDENTIALS: case TP_SOCKET_ACCESS_CONTROL_LOCALHOST: break; default: g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "%u socket access control is not supported", access_control); return FALSE; } return TRUE; } /** * gabble_tube_dbus_offer_async * * Implemnets D-Bus method Offer on interface * org.freedesktop.Telepathy.Channel.Type.DBusTube */ static void gabble_tube_dbus_offer_async (TpSvcChannelTypeDBusTube *self, GHashTable *parameters, guint access_control, DBusGMethodInvocation *context) { GabbleTubeDBus *tube = GABBLE_TUBE_DBUS (self); GabbleTubeDBusPrivate *priv = GABBLE_TUBE_DBUS_GET_PRIVATE (tube); GError *error = NULL; if (!gabble_tube_dbus_check_access_control (tube, access_control, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); return; } priv->access_control = access_control; g_object_set (self, "parameters", parameters, NULL); if (gabble_tube_dbus_offer (tube, &error)) { tp_svc_channel_type_dbus_tube_return_from_offer (context, tube->priv->dbus_srv_addr); } else { g_assert (error != NULL); dbus_g_method_return_error (context, error); g_error_free (error); } } /** * gabble_tube_dbus_accept_async * * Implements D-Bus method Accept on interface * org.freedesktop.Telepathy.Channel.Type.DBusTube */ static void gabble_tube_dbus_accept_async (TpSvcChannelTypeDBusTube *self, guint access_control, DBusGMethodInvocation *context) { GabbleTubeDBus *tube = GABBLE_TUBE_DBUS (self); GError *error = NULL; if (!gabble_tube_dbus_check_access_control (tube, access_control, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); return; } if (gabble_tube_dbus_accept (GABBLE_TUBE_IFACE (tube), &error)) { tp_svc_channel_type_dbus_tube_return_from_accept (context, tube->priv->dbus_srv_addr); ; } else { g_assert (error != NULL); dbus_g_method_return_error (context, error); g_error_free (error); } } static void tube_iface_init (gpointer g_iface, gpointer iface_data) { GabbleTubeIfaceClass *klass = (GabbleTubeIfaceClass *) g_iface; klass->accept = gabble_tube_dbus_accept; klass->close = gabble_tube_iface_dbus_close; klass->add_bytestream = gabble_tube_dbus_add_bytestream; } static void dbustube_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcChannelTypeDBusTubeClass *klass = (TpSvcChannelTypeDBusTubeClass *) g_iface; #define IMPLEMENT(x, suffix) tp_svc_channel_type_dbus_tube_implement_##x (\ klass, gabble_tube_dbus_##x##suffix) IMPLEMENT(offer,_async); IMPLEMENT(accept,_async); #undef IMPLEMENT } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/Makefile.in�������������������������������������������������������������0000664�0001750�0001750�00000133025�12332443655�021045� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ libexec_PROGRAMS = telepathy-gabble$(EXEEXT) noinst_PROGRAMS = write-mgr-file$(EXEEXT) @ENABLE_FILE_TRANSFER_TRUE@am__append_1 = \ @ENABLE_FILE_TRANSFER_TRUE@ ft-channel.c \ @ENABLE_FILE_TRANSFER_TRUE@ ft-channel.h \ @ENABLE_FILE_TRANSFER_TRUE@ ft-manager.c \ @ENABLE_FILE_TRANSFER_TRUE@ ft-manager.h @ENABLE_VOIP_TRUE@am__append_2 = \ @ENABLE_VOIP_TRUE@ base-call-channel.h \ @ENABLE_VOIP_TRUE@ base-call-channel.c \ @ENABLE_VOIP_TRUE@ call-content.h \ @ENABLE_VOIP_TRUE@ call-content.c \ @ENABLE_VOIP_TRUE@ call-channel.h \ @ENABLE_VOIP_TRUE@ call-channel.c \ @ENABLE_VOIP_TRUE@ call-muc-channel.h \ @ENABLE_VOIP_TRUE@ call-muc-channel.c \ @ENABLE_VOIP_TRUE@ call-member.h \ @ENABLE_VOIP_TRUE@ call-member.c \ @ENABLE_VOIP_TRUE@ call-member-content.h \ @ENABLE_VOIP_TRUE@ call-member-content.c \ @ENABLE_VOIP_TRUE@ call-stream.h \ @ENABLE_VOIP_TRUE@ call-stream.c \ @ENABLE_VOIP_TRUE@ jingle-share.h \ @ENABLE_VOIP_TRUE@ jingle-share.c \ @ENABLE_VOIP_TRUE@ jingle-mint.h \ @ENABLE_VOIP_TRUE@ jingle-mint.c \ @ENABLE_VOIP_TRUE@ jingle-tp-util.h \ @ENABLE_VOIP_TRUE@ jingle-tp-util.c \ @ENABLE_VOIP_TRUE@ media-channel.h \ @ENABLE_VOIP_TRUE@ media-channel-internal.h \ @ENABLE_VOIP_TRUE@ media-channel.c \ @ENABLE_VOIP_TRUE@ media-channel-hold.c \ @ENABLE_VOIP_TRUE@ media-stream.h \ @ENABLE_VOIP_TRUE@ media-stream.c \ @ENABLE_VOIP_TRUE@ media-factory.h \ @ENABLE_VOIP_TRUE@ media-factory.c @ENABLE_JINGLE_FILE_TRANSFER_TRUE@am__append_3 = \ @ENABLE_JINGLE_FILE_TRANSFER_TRUE@ gtalk-file-collection.c \ @ENABLE_JINGLE_FILE_TRANSFER_TRUE@ gtalk-file-collection.h DIST_COMMON = $(top_srcdir)/tools/check-coding-style.mk \ $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp # following flag is requied to make getnameinfo work @WINDOWS_TRUE@am__append_4 = -D_WIN32_WINNT=0x0501 subdir = src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_config_dir.m4 \ $(top_srcdir)/m4/compiler.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/tp-compiler-flag.m4 \ $(top_srcdir)/m4/tp-compiler-warnings.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(pluginexeclibdir)" \ "$(DESTDIR)$(libexecdir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(pluginexeclib_LTLIBRARIES) am__DEPENDENCIES_1 = libgabble_convenience_la_DEPENDENCIES = \ $(top_builddir)/extensions/libgabble-extensions.la \ $(top_builddir)/lib/gibber/libgibber.la libgabble-plugins.la \ $(am__DEPENDENCIES_1) am__libgabble_convenience_la_SOURCES_DIST = addressing-util.h \ addressing-util.c auth-manager.h auth-manager.c \ bytestream-factory.h bytestream-factory.c bytestream-ibb.h \ bytestream-ibb.c bytestream-iface.h bytestream-iface.c \ bytestream-muc.h bytestream-muc.c bytestream-multiple.h \ bytestream-multiple.c bytestream-socks5.h bytestream-socks5.c \ capabilities.c caps-hash.h caps-hash.c caps-channel-manager.c \ conn-addressing.h conn-addressing.c conn-aliasing.h \ conn-aliasing.c conn-avatars.h conn-avatars.c \ conn-client-types.h conn-client-types.c conn-contact-info.h \ conn-contact-info.c conn-location.h conn-location.c \ conn-olpc.h conn-olpc.c conn-power-saving.h \ conn-power-saving.c conn-presence.h conn-presence.c \ conn-sidecars.h conn-sidecars.c conn-util.h conn-util.c \ conn-mail-notif.h conn-mail-notif.c connection.h connection.c \ connection-manager.h connection-manager.c debug.h debug.c \ disco.h disco.c error.c error.h gabble.c gabble.h im-channel.h \ im-channel.c im-factory.h im-factory.c legacy-caps.h \ legacy-caps.c message-util.h message-util.c muc-channel.h \ muc-channel.c muc-factory.h muc-factory.c muc-tube-dbus.h \ muc-tube-dbus.c muc-tube-stream.h muc-tube-stream.c \ namespaces.h olpc-activity.h olpc-activity.c plugin-loader.h \ plugin-loader.c presence.h presence.c presence-cache.h \ presence-cache.c protocol.h protocol.c private-tubes-factory.h \ private-tubes-factory.c request-pipeline.h request-pipeline.c \ roster.h roster.c room-config.h room-config.c \ roomlist-channel.h roomlist-channel.c roomlist-manager.h \ roomlist-manager.c search-channel.h search-channel.c \ search-manager.h search-manager.c server-sasl-channel.h \ server-sasl-channel.c server-tls-channel.h \ server-tls-channel.c server-tls-manager.h server-tls-manager.c \ sidecar.c tls-certificate.h tls-certificate.c tube-iface.h \ tube-iface.c tube-dbus.h tube-dbus.c tube-stream.h \ tube-stream.c types.h util.h util.c vcard-manager.h \ vcard-manager.c ft-channel.c ft-channel.h ft-manager.c \ ft-manager.h base-call-channel.h base-call-channel.c \ call-content.h call-content.c call-channel.h call-channel.c \ call-muc-channel.h call-muc-channel.c call-member.h \ call-member.c call-member-content.h call-member-content.c \ call-stream.h call-stream.c jingle-share.h jingle-share.c \ jingle-mint.h jingle-mint.c jingle-tp-util.h jingle-tp-util.c \ media-channel.h media-channel-internal.h media-channel.c \ media-channel-hold.c media-stream.h media-stream.c \ media-factory.h media-factory.c gtalk-file-collection.c \ gtalk-file-collection.h @ENABLE_FILE_TRANSFER_TRUE@am__objects_1 = ft-channel.lo ft-manager.lo @ENABLE_VOIP_TRUE@am__objects_2 = base-call-channel.lo call-content.lo \ @ENABLE_VOIP_TRUE@ call-channel.lo call-muc-channel.lo \ @ENABLE_VOIP_TRUE@ call-member.lo call-member-content.lo \ @ENABLE_VOIP_TRUE@ call-stream.lo jingle-share.lo \ @ENABLE_VOIP_TRUE@ jingle-mint.lo jingle-tp-util.lo \ @ENABLE_VOIP_TRUE@ media-channel.lo media-channel-hold.lo \ @ENABLE_VOIP_TRUE@ media-stream.lo media-factory.lo @ENABLE_JINGLE_FILE_TRANSFER_TRUE@am__objects_3 = \ @ENABLE_JINGLE_FILE_TRANSFER_TRUE@ gtalk-file-collection.lo am_libgabble_convenience_la_OBJECTS = addressing-util.lo \ auth-manager.lo bytestream-factory.lo bytestream-ibb.lo \ bytestream-iface.lo bytestream-muc.lo bytestream-multiple.lo \ bytestream-socks5.lo capabilities.lo caps-hash.lo \ caps-channel-manager.lo conn-addressing.lo conn-aliasing.lo \ conn-avatars.lo conn-client-types.lo conn-contact-info.lo \ conn-location.lo conn-olpc.lo conn-power-saving.lo \ conn-presence.lo conn-sidecars.lo conn-util.lo \ conn-mail-notif.lo connection.lo connection-manager.lo \ debug.lo disco.lo error.lo gabble.lo im-channel.lo \ im-factory.lo legacy-caps.lo message-util.lo muc-channel.lo \ muc-factory.lo muc-tube-dbus.lo muc-tube-stream.lo \ olpc-activity.lo plugin-loader.lo presence.lo \ presence-cache.lo protocol.lo private-tubes-factory.lo \ request-pipeline.lo roster.lo room-config.lo \ roomlist-channel.lo roomlist-manager.lo search-channel.lo \ search-manager.lo server-sasl-channel.lo server-tls-channel.lo \ server-tls-manager.lo sidecar.lo tls-certificate.lo \ tube-iface.lo tube-dbus.lo tube-stream.lo util.lo \ vcard-manager.lo $(am__objects_1) $(am__objects_2) \ $(am__objects_3) am__objects_4 = gabble-signals-marshal.lo gabble-enumtypes.lo nodist_libgabble_convenience_la_OBJECTS = $(am__objects_4) libgabble_convenience_la_OBJECTS = \ $(am_libgabble_convenience_la_OBJECTS) \ $(nodist_libgabble_convenience_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libgabble_plugins_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am_libgabble_plugins_la_OBJECTS = capabilities.lo \ caps-channel-manager.lo debug.lo error.lo plugin.lo \ plugin-connection.lo sidecar.lo libgabble_plugins_la_OBJECTS = $(am_libgabble_plugins_la_OBJECTS) libgabble_plugins_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgabble_plugins_la_LDFLAGS) \ $(LDFLAGS) -o $@ PROGRAMS = $(libexec_PROGRAMS) $(noinst_PROGRAMS) am_telepathy_gabble_OBJECTS = main.$(OBJEXT) telepathy_gabble_OBJECTS = $(am_telepathy_gabble_OBJECTS) telepathy_gabble_DEPENDENCIES = libgabble-convenience.la telepathy_gabble_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(telepathy_gabble_LDFLAGS) $(LDFLAGS) \ -o $@ am_write_mgr_file_OBJECTS = write-mgr-file.$(OBJEXT) write_mgr_file_OBJECTS = $(am_write_mgr_file_OBJECTS) write_mgr_file_DEPENDENCIES = libgabble-convenience.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgabble_convenience_la_SOURCES) \ $(nodist_libgabble_convenience_la_SOURCES) \ $(libgabble_plugins_la_SOURCES) $(telepathy_gabble_SOURCES) \ $(write_mgr_file_SOURCES) DIST_SOURCES = $(am__libgabble_convenience_la_SOURCES_DIST) \ $(libgabble_plugins_la_SOURCES) $(telepathy_gabble_SOURCES) \ $(write_mgr_file_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLIENT_TYPE = @CLIENT_TYPE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_CODING_STYLE_CHECKS = @ENABLE_CODING_STYLE_CHECKS@ ENABLE_PLUGINS = @ENABLE_PLUGINS@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NICE_CFLAGS = @NICE_CFLAGS@ NICE_LIBS = @NICE_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOUP_CFLAGS = @SOUP_CFLAGS@ SOUP_LIBS = @SOUP_LIBS@ STRIP = @STRIP@ TEST_PYTHON = @TEST_PYTHON@ TP_GLIB_CFLAGS = @TP_GLIB_CFLAGS@ TP_GLIB_LIBS = @TP_GLIB_LIBS@ VERSION = @VERSION@ WOCKY_CFLAGS = @WOCKY_CFLAGS@ WOCKY_LIBS = @WOCKY_LIBS@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gabbletestsdir = @gabbletestsdir@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ pluginexecdir = @pluginexecdir@ pluginexeclibdir = @pluginexeclibdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ BUILT_SOURCES = \ gabble-signals-marshal.h \ gabble-signals-marshal.c \ gabble-signals-marshal.list \ gabble-enumtypes.h \ gabble-enumtypes.c CLEANFILES = $(BUILT_SOURCES) EXTRA_DIST = libgabble_convenience_la_SOURCES = addressing-util.h addressing-util.c \ auth-manager.h auth-manager.c bytestream-factory.h \ bytestream-factory.c bytestream-ibb.h bytestream-ibb.c \ bytestream-iface.h bytestream-iface.c bytestream-muc.h \ bytestream-muc.c bytestream-multiple.h bytestream-multiple.c \ bytestream-socks5.h bytestream-socks5.c capabilities.c \ caps-hash.h caps-hash.c caps-channel-manager.c \ conn-addressing.h conn-addressing.c conn-aliasing.h \ conn-aliasing.c conn-avatars.h conn-avatars.c \ conn-client-types.h conn-client-types.c conn-contact-info.h \ conn-contact-info.c conn-location.h conn-location.c \ conn-olpc.h conn-olpc.c conn-power-saving.h \ conn-power-saving.c conn-presence.h conn-presence.c \ conn-sidecars.h conn-sidecars.c conn-util.h conn-util.c \ conn-mail-notif.h conn-mail-notif.c connection.h connection.c \ connection-manager.h connection-manager.c debug.h debug.c \ disco.h disco.c error.c error.h gabble.c gabble.h im-channel.h \ im-channel.c im-factory.h im-factory.c legacy-caps.h \ legacy-caps.c message-util.h message-util.c muc-channel.h \ muc-channel.c muc-factory.h muc-factory.c muc-tube-dbus.h \ muc-tube-dbus.c muc-tube-stream.h muc-tube-stream.c \ namespaces.h olpc-activity.h olpc-activity.c plugin-loader.h \ plugin-loader.c presence.h presence.c presence-cache.h \ presence-cache.c protocol.h protocol.c private-tubes-factory.h \ private-tubes-factory.c request-pipeline.h request-pipeline.c \ roster.h roster.c room-config.h room-config.c \ roomlist-channel.h roomlist-channel.c roomlist-manager.h \ roomlist-manager.c search-channel.h search-channel.c \ search-manager.h search-manager.c server-sasl-channel.h \ server-sasl-channel.c server-tls-channel.h \ server-tls-channel.c server-tls-manager.h server-tls-manager.c \ sidecar.c tls-certificate.h tls-certificate.c tube-iface.h \ tube-iface.c tube-dbus.h tube-dbus.c tube-stream.h \ tube-stream.c types.h util.h util.c vcard-manager.h \ vcard-manager.c $(am__append_1) $(am__append_2) \ $(am__append_3) enumtype_sources = \ $(top_srcdir)/src/connection.h \ $(top_srcdir)/src/room-config.h \ $(top_srcdir)/src/presence.h libgabble_convenience_la_LIBADD = \ $(top_builddir)/extensions/libgabble-extensions.la \ $(top_builddir)/lib/gibber/libgibber.la \ libgabble-plugins.la \ $(ALL_LIBS) nodist_libgabble_convenience_la_SOURCES = \ $(BUILT_SOURCES) write_mgr_file_SOURCES = write-mgr-file.c write_mgr_file_LDADD = libgabble-convenience.la telepathy_gabble_SOURCES = \ main.c check_c_sources = \ $(telepathy_gabble_SOURCES) \ $(libgabble_convenience_la_SOURCES) \ $(write_mgr_file_SOURCES) telepathy_gabble_LDADD = libgabble-convenience.la telepathy_gabble_LDFLAGS = -export-dynamic noinst_LTLIBRARIES = libgabble-convenience.la pluginexeclib_LTLIBRARIES = libgabble-plugins.la # Gabble's plugin API is not stable yet (it can't be, since neither is Wocky), # so use -release to make the SONAME of the plugin library change with every # Gabble release. libgabble_plugins_la_LDFLAGS = \ -no-undefined \ -release $(VERSION) \ $(NULL) libgabble_plugins_la_LIBADD = \ $(ALL_LIBS) libgabble_plugins_la_SOURCES = \ capabilities.c \ caps-channel-manager.c \ debug.c \ error.c \ plugin.c \ plugin-connection.c \ sidecar.c AM_CFLAGS = $(ERROR_CFLAGS) -I$(top_srcdir) -I$(top_builddir) \ @DBUS_CFLAGS@ @GLIB_CFLAGS@ @WOCKY_CFLAGS@ @TP_GLIB_CFLAGS@ \ @SOUP_CFLAGS@ @NICE_CFLAGS@ @GMODULE_CFLAGS@ -I \ $(top_srcdir)/lib -I $(top_builddir)/lib \ -DG_LOG_DOMAIN=\"gabble\" -DPLUGIN_DIR=\"$(pluginexecdir)\" \ $(am__append_4) ALL_LIBS = @DBUS_LIBS@ @GLIB_LIBS@ @WOCKY_LIBS@ @TP_GLIB_LIBS@ \ @SOUP_LIBS@ @NICE_LIBS@ @GMODULE_LIBS@ all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/tools/check-coding-style.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/tools/check-coding-style.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-pluginexeclibLTLIBRARIES: $(pluginexeclib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pluginexeclib_LTLIBRARIES)'; test -n "$(pluginexeclibdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(pluginexeclibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pluginexeclibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pluginexeclibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pluginexeclibdir)"; \ } uninstall-pluginexeclibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pluginexeclib_LTLIBRARIES)'; test -n "$(pluginexeclibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pluginexeclibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pluginexeclibdir)/$$f"; \ done clean-pluginexeclibLTLIBRARIES: -test -z "$(pluginexeclib_LTLIBRARIES)" || rm -f $(pluginexeclib_LTLIBRARIES) @list='$(pluginexeclib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgabble-convenience.la: $(libgabble_convenience_la_OBJECTS) $(libgabble_convenience_la_DEPENDENCIES) $(EXTRA_libgabble_convenience_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libgabble_convenience_la_OBJECTS) $(libgabble_convenience_la_LIBADD) $(LIBS) libgabble-plugins.la: $(libgabble_plugins_la_OBJECTS) $(libgabble_plugins_la_DEPENDENCIES) $(EXTRA_libgabble_plugins_la_DEPENDENCIES) $(AM_V_CCLD)$(libgabble_plugins_la_LINK) -rpath $(pluginexeclibdir) $(libgabble_plugins_la_OBJECTS) $(libgabble_plugins_la_LIBADD) $(LIBS) install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-libexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libexecdir)" && rm -f $$files clean-libexecPROGRAMS: @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list telepathy-gabble$(EXEEXT): $(telepathy_gabble_OBJECTS) $(telepathy_gabble_DEPENDENCIES) $(EXTRA_telepathy_gabble_DEPENDENCIES) @rm -f telepathy-gabble$(EXEEXT) $(AM_V_CCLD)$(telepathy_gabble_LINK) $(telepathy_gabble_OBJECTS) $(telepathy_gabble_LDADD) $(LIBS) write-mgr-file$(EXEEXT): $(write_mgr_file_OBJECTS) $(write_mgr_file_DEPENDENCIES) $(EXTRA_write_mgr_file_DEPENDENCIES) @rm -f write-mgr-file$(EXEEXT) $(AM_V_CCLD)$(LINK) $(write_mgr_file_OBJECTS) $(write_mgr_file_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addressing-util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth-manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/base-call-channel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bytestream-factory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bytestream-ibb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bytestream-iface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bytestream-muc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bytestream-multiple.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bytestream-socks5.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/call-channel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/call-content.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/call-member-content.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/call-member.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/call-muc-channel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/call-stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/capabilities.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/caps-channel-manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/caps-hash.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conn-addressing.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conn-aliasing.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conn-avatars.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conn-client-types.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conn-contact-info.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conn-location.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conn-mail-notif.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conn-olpc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conn-power-saving.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conn-presence.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conn-sidecars.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conn-util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connection-manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/disco.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ft-channel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ft-manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gabble-enumtypes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gabble-signals-marshal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gabble.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtalk-file-collection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/im-channel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/im-factory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jingle-mint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jingle-share.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jingle-tp-util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/legacy-caps.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/media-channel-hold.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/media-channel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/media-factory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/media-stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message-util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/muc-channel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/muc-factory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/muc-tube-dbus.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/muc-tube-stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/olpc-activity.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin-connection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin-loader.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/presence-cache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/presence.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/private-tubes-factory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/request-pipeline.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/room-config.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/roomlist-channel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/roomlist-manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/roster.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search-channel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search-manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server-sasl-channel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server-tls-channel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server-tls-manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sidecar.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls-certificate.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tube-dbus.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tube-iface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tube-stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vcard-manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write-mgr-file.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(pluginexeclibdir)" "$(DESTDIR)$(libexecdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libexecPROGRAMS clean-libtool \ clean-noinstLTLIBRARIES clean-noinstPROGRAMS \ clean-pluginexeclibLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libexecPROGRAMS \ install-pluginexeclibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libexecPROGRAMS \ uninstall-pluginexeclibLTLIBRARIES .MAKE: all check check-am install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am check-local clean \ clean-generic clean-libexecPROGRAMS clean-libtool \ clean-noinstLTLIBRARIES clean-noinstPROGRAMS \ clean-pluginexeclibLTLIBRARIES cscopelist-am ctags ctags-am \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libexecPROGRAMS install-man \ install-pdf install-pdf-am install-pluginexeclibLTLIBRARIES \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-libexecPROGRAMS \ uninstall-pluginexeclibLTLIBRARIES check-coding-style: @fail=0; \ if test -n "$(check_misc_sources)"; then \ tools_dir=$(top_srcdir)/tools \ sh $(top_srcdir)/tools/check-misc.sh \ $(addprefix $(srcdir)/,$(check_misc_sources)) || fail=1; \ fi; \ if test -n "$(check_c_sources)"; then \ tools_dir=$(top_srcdir)/tools \ sh $(top_srcdir)/tools/check-c-style.sh \ $(addprefix $(srcdir)/,$(check_c_sources)) || fail=1; \ fi;\ if test yes = "$(ENABLE_CODING_STYLE_CHECKS)"; then \ exit "$$fail";\ else \ exit 0;\ fi check-local: check-coding-style # build gibber first all: gibber gibber: @${MAKE} -C $(top_builddir)/lib/gibber libgibber.la .PHONY: gibber gabble-signals-marshal.list: $(libgabble_convenience_la_SOURCES) Makefile.am @( cd $(srcdir) && \ sed -n -e 's/.*gabble_marshal_\([[:upper:][:digit:]]*__[[:upper:][:digit:]_]*\).*/\1/p' \ $(libgabble_convenience_la_SOURCES) ) \ | sed -e 's/__/:/' -e 'y/_/,/' | sort -u > $@.tmp @if cmp -s $@.tmp $@; then \ rm $@.tmp; \ else \ mv $@.tmp $@; \ fi %-signals-marshal.h: %-signals-marshal.list Makefile.am $(AM_V_GEN)glib-genmarshal --header --prefix=$(subst -,_,$*)_marshal $< > $@ %-signals-marshal.c: %-signals-marshal.list Makefile.am $(AM_V_GEN){ echo '#include "$*-signals-marshal.h"' && \ glib-genmarshal --body --prefix=$(subst -,_,$*)_marshal $< ; \ } > $@ # rules for making the glib enum objects gabble-enumtypes.h: $(enumtype_sources) Makefile.in $(AM_V_GEN)glib-mkenums \ --fhead "#ifndef __GABBLE_ENUM_TYPES_H__\n#define __GABBLE_ENUM_TYPES_H__\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n" \ --fprod "/* enumerations from \"@filename@\" */\n" \ --vhead "GType @enum_name@_get_type (void);\n#define GABBLE_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ --ftail "G_END_DECLS\n\n#endif /* __GABBLE_ENUM_TYPES_H__ */" \ $(enumtype_sources) > $@ gabble-enumtypes.c: $(enumtype_sources) Makefile.in $(AM_V_GEN)glib-mkenums \ --fhead "#include \"config.h\"\n" \ --fhead "#include <$*.h>" \ --fprod "\n/* enumerations from \"@filename@\" */\n#include \"@filename@\"" \ --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \ $(enumtype_sources) > $@ Android.mk: Makefile.am $(BUILT_SOURCES) androgenizer -:PROJECT telepathy-gabble \ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ -:SHARED gabble-plugins -:TAGS eng debug \ -:SOURCES $(libgabble_plugins_la_SOURCES) \ -:CFLAGS $(DEFS) $(CFLAGS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CFLAGS) \ -:CPPFLAGS $(CPPFLAGS) $(AM_CPPFLAGS) \ -:LDFLAGS $(libgabble_plugins_la_LDFLAGS) \ $(libgabble_plugins_la_LIBADD) \ -:SHARED telepathy-gabble -:TAGS eng debug \ -:SOURCES $(libgabble_convenience_la_SOURCES) \ $(nodist_libgabble_convenience_la_SOURCES) main.c \ -:CFLAGS $(DEFS) $(CFLAGS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CFLAGS) -DBUILD_AS_ANDROID_SERVICE \ -:CPPFLAGS $(CPPFLAGS) $(AM_CPPFLAGS) $(telepathy_gabble_LDFLAGS) \ -:LDFLAGS $(telepathy_gabble_LDADD) $(libgabble_convenience_la_LIBADD) \ $(lib_LTLIBRARIES) \ > $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/bytestream-multiple.c���������������������������������������������������0000664�0001750�0001750�00000051027�12332440117�023143� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * bytestream-multiple.c - Source for GabbleBytestreamMultiple * Copyright (C) 2007-2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "bytestream-multiple.h" #include <dbus/dbus-glib.h> #include <dbus/dbus-glib-lowlevel.h> #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #define DEBUG_FLAG GABBLE_DEBUG_BYTESTREAM #include "bytestream-factory.h" #include "bytestream-iface.h" #include "connection.h" #include "debug.h" #include "disco.h" #include "gabble-signals-marshal.h" #include "namespaces.h" #include "util.h" static void bytestream_iface_init (gpointer g_iface, gpointer iface_data); G_DEFINE_TYPE_WITH_CODE (GabbleBytestreamMultiple, gabble_bytestream_multiple, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GABBLE_TYPE_BYTESTREAM_IFACE, bytestream_iface_init)); /* properties */ enum { PROP_CONNECTION = 1, PROP_PEER_HANDLE, PROP_PEER_HANDLE_TYPE, PROP_STREAM_ID, PROP_STREAM_INIT_ID, PROP_PEER_JID, PROP_PEER_RESOURCE, PROP_STATE, PROP_PROTOCOL, PROP_FACTORY, PROP_SELF_JID, LAST_PROPERTY }; struct _GabbleBytestreamMultiplePrivate { GabbleConnection *conn; TpHandle peer_handle; gchar *stream_id; gchar *stream_init_id; gchar *peer_resource; GabbleBytestreamState state; gchar *peer_jid; GabbleBytestreamFactory *factory; gchar *self_full_jid; /* List of (gchar *) containing the NS of a stream method */ GList *fallback_stream_methods; GabbleBytestreamIface *active_bytestream; gboolean read_blocked; gboolean dispose_has_run; }; #define GABBLE_BYTESTREAM_MULTIPLE_GET_PRIVATE(obj) ((obj)->priv) static void bytestream_activate_next (GabbleBytestreamMultiple *self); static void gabble_bytestream_multiple_init (GabbleBytestreamMultiple *self) { GabbleBytestreamMultiplePrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_BYTESTREAM_MULTIPLE, GabbleBytestreamMultiplePrivate); self->priv = priv; } static void gabble_bytestream_multiple_dispose (GObject *object) { GabbleBytestreamMultiple *self = GABBLE_BYTESTREAM_MULTIPLE (object); GabbleBytestreamMultiplePrivate *priv = GABBLE_BYTESTREAM_MULTIPLE_GET_PRIVATE (self); if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; if (priv->state != GABBLE_BYTESTREAM_STATE_CLOSED) { gabble_bytestream_iface_close (GABBLE_BYTESTREAM_IFACE (self), NULL); } G_OBJECT_CLASS (gabble_bytestream_multiple_parent_class)->dispose (object); } static void gabble_bytestream_multiple_finalize (GObject *object) { GabbleBytestreamMultiple *self = GABBLE_BYTESTREAM_MULTIPLE (object); GabbleBytestreamMultiplePrivate *priv = GABBLE_BYTESTREAM_MULTIPLE_GET_PRIVATE (self); GList *l; for (l = priv->fallback_stream_methods; l != NULL; l = g_list_next (l)) g_free (l->data); g_list_free (priv->fallback_stream_methods); g_free (priv->stream_id); g_free (priv->stream_init_id); g_free (priv->peer_resource); g_free (priv->peer_jid); g_free (priv->self_full_jid); G_OBJECT_CLASS (gabble_bytestream_multiple_parent_class)->finalize (object); } static void gabble_bytestream_multiple_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleBytestreamMultiple *self = GABBLE_BYTESTREAM_MULTIPLE (object); GabbleBytestreamMultiplePrivate *priv = GABBLE_BYTESTREAM_MULTIPLE_GET_PRIVATE (self); switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, priv->conn); break; case PROP_PEER_HANDLE: g_value_set_uint (value, priv->peer_handle); break; case PROP_PEER_HANDLE_TYPE: g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT); break; case PROP_STREAM_ID: g_value_set_string (value, priv->stream_id); break; case PROP_STREAM_INIT_ID: g_value_set_string (value, priv->stream_init_id); break; case PROP_PEER_RESOURCE: g_value_set_string (value, priv->peer_resource); break; case PROP_PEER_JID: g_value_set_string (value, priv->peer_jid); break; case PROP_STATE: g_value_set_uint (value, priv->state); break; case PROP_PROTOCOL: g_value_set_string (value, NS_BYTESTREAMS); break; case PROP_FACTORY: g_value_set_object (value, priv->factory); break; case PROP_SELF_JID: g_value_set_string (value, priv->self_full_jid); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_bytestream_multiple_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleBytestreamMultiple *self = GABBLE_BYTESTREAM_MULTIPLE (object); GabbleBytestreamMultiplePrivate *priv = GABBLE_BYTESTREAM_MULTIPLE_GET_PRIVATE (self); switch (property_id) { case PROP_CONNECTION: priv->conn = g_value_get_object (value); break; case PROP_PEER_HANDLE: priv->peer_handle = g_value_get_uint (value); break; case PROP_STREAM_ID: g_free (priv->stream_id); priv->stream_id = g_value_dup_string (value); break; case PROP_STREAM_INIT_ID: g_free (priv->stream_init_id); priv->stream_init_id = g_value_dup_string (value); break; case PROP_PEER_RESOURCE: g_free (priv->peer_resource); priv->peer_resource = g_value_dup_string (value); break; case PROP_STATE: if (priv->state != g_value_get_uint (value)) { priv->state = g_value_get_uint (value); g_signal_emit_by_name (object, "state-changed", priv->state); } break; case PROP_FACTORY: priv->factory = g_value_get_object (value); break; case PROP_SELF_JID: g_free (priv->self_full_jid); priv->self_full_jid = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static GObject * gabble_bytestream_multiple_constructor (GType type, guint n_props, GObjectConstructParam *props) { GObject *obj; GabbleBytestreamMultiplePrivate *priv; TpHandleRepoIface *contact_repo; const gchar *jid; obj = G_OBJECT_CLASS (gabble_bytestream_multiple_parent_class)-> constructor (type, n_props, props); priv = GABBLE_BYTESTREAM_MULTIPLE_GET_PRIVATE ( GABBLE_BYTESTREAM_MULTIPLE (obj)); g_assert (priv->conn != NULL); g_assert (priv->peer_handle != 0); g_assert (priv->stream_id != NULL); contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); jid = tp_handle_inspect (contact_repo, priv->peer_handle); if (priv->peer_resource != NULL) priv->peer_jid = g_strdup_printf ("%s/%s", jid, priv->peer_resource); else priv->peer_jid = g_strdup (jid); g_assert (priv->self_full_jid != NULL); return obj; } static void gabble_bytestream_multiple_class_init ( GabbleBytestreamMultipleClass *gabble_bytestream_multiple_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_bytestream_multiple_class); GParamSpec *param_spec; g_type_class_add_private (gabble_bytestream_multiple_class, sizeof (GabbleBytestreamMultiplePrivate)); object_class->dispose = gabble_bytestream_multiple_dispose; object_class->finalize = gabble_bytestream_multiple_finalize; object_class->get_property = gabble_bytestream_multiple_get_property; object_class->set_property = gabble_bytestream_multiple_set_property; object_class->constructor = gabble_bytestream_multiple_constructor; g_object_class_override_property (object_class, PROP_CONNECTION, "connection"); g_object_class_override_property (object_class, PROP_PEER_HANDLE, "peer-handle"); g_object_class_override_property (object_class, PROP_PEER_HANDLE_TYPE, "peer-handle-type"); g_object_class_override_property (object_class, PROP_STREAM_ID, "stream-id"); g_object_class_override_property (object_class, PROP_PEER_JID, "peer-jid"); g_object_class_override_property (object_class, PROP_STATE, "state"); g_object_class_override_property (object_class, PROP_PROTOCOL, "protocol"); param_spec = g_param_spec_string ( "peer-resource", "Peer resource", "the resource used by the remote peer during the SI, if any", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_PEER_RESOURCE, param_spec); param_spec = g_param_spec_string ( "stream-init-id", "stream init ID", "the iq ID of the SI request, if any", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_STREAM_INIT_ID, param_spec); param_spec = g_param_spec_object ( "factory", "Factory", "The GabbleBytestreamFactory that created the stream", GABBLE_TYPE_BYTESTREAM_FACTORY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_FACTORY, param_spec); param_spec = g_param_spec_string ( "self-jid", "Our self jid", "Either a contact full jid or a muc jid", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SELF_JID, param_spec); } /* * gabble_bytestream_multiple_send * * Implements gabble_bytestream_iface_send on GabbleBytestreamIface */ static gboolean gabble_bytestream_multiple_send (GabbleBytestreamIface *iface, guint len, const gchar *str) { GabbleBytestreamMultiple *self = GABBLE_BYTESTREAM_MULTIPLE (iface); GabbleBytestreamMultiplePrivate *priv = GABBLE_BYTESTREAM_MULTIPLE_GET_PRIVATE (self); if (priv->state != GABBLE_BYTESTREAM_STATE_OPEN) { DEBUG ("can't send data through a not open bytestream (state: %d)", priv->state); return FALSE; } g_assert (priv->active_bytestream != NULL); return gabble_bytestream_iface_send (priv->active_bytestream, len, str); } /* * gabble_bytestream_multiple_accept * * Implements gabble_bytestream_iface_accept on GabbleBytestreamIface */ static void gabble_bytestream_multiple_accept (GabbleBytestreamIface *iface, GabbleBytestreamAugmentSiAcceptReply func, gpointer user_data) { GabbleBytestreamMultiple *self = GABBLE_BYTESTREAM_MULTIPLE (iface); GabbleBytestreamMultiplePrivate *priv = GABBLE_BYTESTREAM_MULTIPLE_GET_PRIVATE (self); WockyStanza *msg; WockyNode *si; GList *all_methods; gchar *current_method; /* We cannot just call the accept method of the active bytestream because * the result stanza is different if we are using si-multiple */ if (priv->state != GABBLE_BYTESTREAM_STATE_LOCAL_PENDING) { /* The stream was previoulsy or automatically accepted */ return; } g_return_if_fail (priv->active_bytestream != NULL); all_methods = g_list_copy (priv->fallback_stream_methods); g_object_get (priv->active_bytestream, "protocol", ¤t_method, NULL); all_methods = g_list_prepend (all_methods, current_method); msg = gabble_bytestream_factory_make_multi_accept_iq (priv->peer_jid, priv->stream_init_id, all_methods); g_free (current_method); g_list_free (all_methods); si = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "si", NS_SI); g_assert (si != NULL); if (func != NULL) { /* let the caller add his profile specific data */ func (si, user_data); } if (_gabble_connection_send (priv->conn, msg, NULL)) { DEBUG ("stream %s with %s is now accepted", priv->stream_id, priv->peer_jid); g_object_set (priv->active_bytestream, "state", GABBLE_BYTESTREAM_STATE_ACCEPTED, NULL); } g_object_unref (msg); } /* * gabble_bytestream_multiple_close * * Implements gabble_bytestream_iface_close on GabbleBytestreamIface */ static void gabble_bytestream_multiple_close (GabbleBytestreamIface *iface, GError *error) { GabbleBytestreamMultiple *self = GABBLE_BYTESTREAM_MULTIPLE (iface); GabbleBytestreamMultiplePrivate *priv = GABBLE_BYTESTREAM_MULTIPLE_GET_PRIVATE (self); if (priv->state == GABBLE_BYTESTREAM_STATE_CLOSED) /* bytestream already closed, do nothing */ return; if (priv->active_bytestream != NULL) gabble_bytestream_iface_close (priv->active_bytestream, error); else /* It can happen if the bytestream is still empty, i.e. not stream * methods have been added yet */ g_object_set (self, "state", GABBLE_BYTESTREAM_STATE_CLOSED, NULL); } /* * gabble_bytestream_multiple_initiate * * Implements gabble_bytestream_iface_initiate on GabbleBytestreamIface */ static gboolean gabble_bytestream_multiple_initiate (GabbleBytestreamIface *iface) { GabbleBytestreamMultiple *self = GABBLE_BYTESTREAM_MULTIPLE (iface); GabbleBytestreamMultiplePrivate *priv = GABBLE_BYTESTREAM_MULTIPLE_GET_PRIVATE (self); if (priv->state != GABBLE_BYTESTREAM_STATE_INITIATING) { DEBUG ("bytestream is not is the initiating state (state %d)", priv->state); return FALSE; } if (priv->active_bytestream == NULL) { DEBUG ("no bytestreams to initiate"); return FALSE; } return gabble_bytestream_iface_initiate (priv->active_bytestream); } static void bytestream_data_received_cb (GabbleBytestreamIface *bytestream, TpHandle sender, GString *str, gpointer user_data) { GabbleBytestreamMultiple *self = GABBLE_BYTESTREAM_MULTIPLE (user_data); /* Just forward the data */ g_signal_emit_by_name (G_OBJECT (self), "data-received", sender, str); } static void bytestream_state_changed_cb (GabbleBytestreamIface *bytestream, GabbleBytestreamState state, gpointer user_data) { GabbleBytestreamMultiple *self = GABBLE_BYTESTREAM_MULTIPLE (user_data); /* When there is a connection error the state of the sub-bytestream becomes * CLOSED. There is no risk to receive a notification for this kind of * change because the signal handler is previously disconnected in * bytestream_connection_error_cb */ g_object_set (self, "state", state, NULL); } static void bytestream_write_blocked_cb (GabbleBytestreamIface *bytestream, gboolean blocked, gpointer self) { /* Forward signal */ g_signal_emit_by_name (G_OBJECT (self), "write-blocked", blocked); } static void bytestream_connection_error_cb (GabbleBytestreamIface *failed, gpointer user_data) { GabbleBytestreamMultiple *self = GABBLE_BYTESTREAM_MULTIPLE (user_data); GabbleBytestreamMultiplePrivate *priv = GABBLE_BYTESTREAM_MULTIPLE_GET_PRIVATE (self); g_assert (failed == priv->active_bytestream); /* the error signal is only emitted when intiating the bytestream */ g_assert (priv->state == GABBLE_BYTESTREAM_STATE_INITIATING || priv->state == GABBLE_BYTESTREAM_STATE_ACCEPTED); g_signal_handlers_disconnect_by_func (failed, bytestream_connection_error_cb, self); g_signal_handlers_disconnect_by_func (failed, bytestream_data_received_cb, self); g_signal_handlers_disconnect_by_func (failed, bytestream_state_changed_cb, self); g_signal_handlers_disconnect_by_func (failed, bytestream_write_blocked_cb, self); /* We don't have to unref it because the reference is kept by the * factory */ priv->active_bytestream = NULL; if (priv->fallback_stream_methods == NULL) return; DEBUG ("Trying alternative streaming method"); bytestream_activate_next (self); if (priv->state == GABBLE_BYTESTREAM_STATE_INITIATING) /* The previous bytestream failed when initiating it, so now we have to * initiate the new one */ gabble_bytestream_iface_initiate (priv->active_bytestream); } static void bytestream_activate_next (GabbleBytestreamMultiple *self) { GabbleBytestreamMultiplePrivate *priv = GABBLE_BYTESTREAM_MULTIPLE_GET_PRIVATE (self); gchar *stream_method; g_return_if_fail (priv->active_bytestream == NULL); /* The caller has to be sure that there is a fallback method */ g_return_if_fail (priv->fallback_stream_methods != NULL); /* Try the first stream method in the fallback list */ stream_method = priv->fallback_stream_methods->data; priv->fallback_stream_methods = g_list_delete_link ( priv->fallback_stream_methods, priv->fallback_stream_methods); priv->active_bytestream = gabble_bytestream_factory_create_from_method ( priv->factory, stream_method, priv->peer_handle, priv->stream_id, priv->stream_init_id, priv->peer_resource, priv->self_full_jid, priv->state); /* Methods have already been checked so this shouldn't fail */ g_assert (priv->active_bytestream != NULL); g_free (stream_method); /* block the new bytestream if needed */ gabble_bytestream_iface_block_reading (priv->active_bytestream, priv->read_blocked); g_signal_connect (priv->active_bytestream, "connection-error", G_CALLBACK (bytestream_connection_error_cb), self); g_signal_connect (priv->active_bytestream, "data-received", G_CALLBACK (bytestream_data_received_cb), self); g_signal_connect (priv->active_bytestream, "state-changed", G_CALLBACK (bytestream_state_changed_cb), self); g_signal_connect (priv->active_bytestream, "write-blocked", G_CALLBACK (bytestream_write_blocked_cb), self); } /* * gabble_bytestream_multiple_add_bytestream * * Add an alternative stream method. */ void gabble_bytestream_multiple_add_stream_method (GabbleBytestreamMultiple *self, const gchar *method) { GabbleBytestreamMultiplePrivate *priv; g_return_if_fail (GABBLE_IS_BYTESTREAM_MULTIPLE (self)); g_return_if_fail (method != NULL); priv = GABBLE_BYTESTREAM_MULTIPLE_GET_PRIVATE (self); DEBUG ("Add bytestream method %s", method); priv->fallback_stream_methods = g_list_append ( priv->fallback_stream_methods, g_strdup (method)); if (priv->active_bytestream == NULL) bytestream_activate_next (self); } gboolean gabble_bytestream_multiple_has_stream_method (GabbleBytestreamMultiple *self) { GabbleBytestreamMultiplePrivate *priv = GABBLE_BYTESTREAM_MULTIPLE_GET_PRIVATE (self); if (priv->active_bytestream != NULL) return TRUE; return (g_list_length (priv->fallback_stream_methods) != 0); } static void gabble_bytestream_multiple_block_reading (GabbleBytestreamIface *iface, gboolean block) { GabbleBytestreamMultiple *self = GABBLE_BYTESTREAM_MULTIPLE (iface); GabbleBytestreamMultiplePrivate *priv = GABBLE_BYTESTREAM_MULTIPLE_GET_PRIVATE (self); if (priv->read_blocked == block) return; priv->read_blocked = block; g_assert (priv->active_bytestream != NULL); gabble_bytestream_iface_block_reading (priv->active_bytestream, block); } static void bytestream_iface_init (gpointer g_iface, gpointer iface_data) { GabbleBytestreamIfaceClass *klass = (GabbleBytestreamIfaceClass *) g_iface; klass->initiate = gabble_bytestream_multiple_initiate; klass->send = gabble_bytestream_multiple_send; klass->close = gabble_bytestream_multiple_close; klass->accept = gabble_bytestream_multiple_accept; klass->block_reading = gabble_bytestream_multiple_block_reading; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/ft-channel.c������������������������������������������������������������0000664�0001750�0001750�00000213721�12332441362�021156� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * ft-channel.c - Source for GabbleFileTransferChannel * Copyright (C) 2009-2010 Collabora Ltd. * @author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include <glib/gstdio.h> #include <dbus/dbus-glib.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <gibber/gibber-sockets.h> #ifdef HAVE_UNISTD_H # include <unistd.h> #endif #define DEBUG_FLAG GABBLE_DEBUG_FT #include "debug.h" #include <gibber/gibber-listener.h> #include <gibber/gibber-transport.h> #include <gibber/gibber-unix-transport.h> /* just for the feature-test */ #include "connection.h" #include "ft-channel.h" #include "gabble-signals-marshal.h" #include "namespaces.h" #include "presence-cache.h" #include "util.h" #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> static void file_transfer_iface_init (gpointer g_iface, gpointer iface_data); static void transferred_chunk (GabbleFileTransferChannel *self, guint64 count); static gboolean set_bytestream (GabbleFileTransferChannel *self, GabbleBytestreamIface *bytestream); #ifdef ENABLE_JINGLE_FILE_TRANSFER static gboolean set_gtalk_file_collection (GabbleFileTransferChannel *self, GTalkFileCollection *gtalk_file_collection); #endif G_DEFINE_TYPE_WITH_CODE (GabbleFileTransferChannel, gabble_file_transfer_channel, TP_TYPE_BASE_CHANNEL, G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_FILE_TRANSFER, file_transfer_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_CHANNEL_TYPE_FILETRANSFER_FUTURE, NULL); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA, NULL); ); #define GABBLE_UNDEFINED_FILE_SIZE G_MAXUINT64 /* properties */ enum { /* Channel.Type.FileTransfer D-Bus properties */ PROP_STATE = 1, PROP_CONTENT_TYPE, PROP_FILENAME, PROP_SIZE, PROP_CONTENT_HASH_TYPE, PROP_CONTENT_HASH, PROP_DESCRIPTION, PROP_DATE, PROP_AVAILABLE_SOCKET_TYPES, PROP_TRANSFERRED_BYTES, PROP_INITIAL_OFFSET, PROP_RESUME_SUPPORTED, PROP_FILE_COLLECTION, PROP_URI, PROP_CONNECTION, PROP_BYTESTREAM, #ifdef ENABLE_JINGLE_FILE_TRANSFER /* Chan.Type.FileTransfer.FUTURE */ PROP_GTALK_FILE_COLLECTION, #endif /* Chan.Iface.FileTransfer.Metadata */ PROP_SERVICE_NAME, PROP_METADATA, LAST_PROPERTY }; /* private structure */ struct _GabbleFileTransferChannelPrivate { gboolean dispose_has_run; GTimeVal last_transferred_bytes_emitted; guint progress_timer; TpSocketAddressType socket_type; GValue *socket_address; gboolean resume_supported; #ifdef ENABLE_JINGLE_FILE_TRANSFER GTalkFileCollection *gtalk_file_collection; #endif GabbleBytestreamIface *bytestream; GibberListener *listener; GibberTransport *transport; /* properties */ TpFileTransferState state; gchar *content_type; gchar *filename; guint64 size; TpFileHashType content_hash_type; gchar *content_hash; gchar *description; GHashTable *available_socket_types; guint64 transferred_bytes; guint64 initial_offset; guint64 date; gchar *file_collection; gchar *uri; gchar *service_name; GHashTable *metadata; gboolean channel_opened; }; static void gabble_file_transfer_channel_set_state ( TpSvcChannelTypeFileTransfer *iface, TpFileTransferState state, TpFileTransferStateChangeReason reason); static void close_session_and_transport (GabbleFileTransferChannel *self); static void gabble_file_transfer_channel_close (TpBaseChannel *base) { GabbleFileTransferChannel *self = GABBLE_FILE_TRANSFER_CHANNEL (base); if (self->priv->state != TP_FILE_TRANSFER_STATE_COMPLETED && self->priv->state != TP_FILE_TRANSFER_STATE_CANCELLED) { gabble_file_transfer_channel_set_state ( TP_SVC_CHANNEL_TYPE_FILE_TRANSFER (self), TP_FILE_TRANSFER_STATE_CANCELLED, TP_FILE_TRANSFER_STATE_CHANGE_REASON_LOCAL_STOPPED); close_session_and_transport (self); } tp_base_channel_destroyed (base); } static void gabble_file_transfer_channel_init (GabbleFileTransferChannel *obj) { obj->priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, GABBLE_TYPE_FILE_TRANSFER_CHANNEL, GabbleFileTransferChannelPrivate); } static void gabble_file_transfer_channel_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleFileTransferChannel *self = GABBLE_FILE_TRANSFER_CHANNEL (object); switch (property_id) { case PROP_STATE: g_value_set_uint (value, self->priv->state); break; case PROP_CONTENT_TYPE: g_value_set_string (value, self->priv->content_type); break; case PROP_FILENAME: g_value_set_string (value, self->priv->filename); break; case PROP_SIZE: g_value_set_uint64 (value, self->priv->size); break; case PROP_CONTENT_HASH_TYPE: g_value_set_uint (value, self->priv->content_hash_type); break; case PROP_CONTENT_HASH: g_value_set_string (value, self->priv->content_hash); break; case PROP_DESCRIPTION: g_value_set_string (value, self->priv->description); break; case PROP_AVAILABLE_SOCKET_TYPES: g_value_set_boxed (value, self->priv->available_socket_types); break; case PROP_TRANSFERRED_BYTES: g_value_set_uint64 (value, self->priv->transferred_bytes); break; case PROP_INITIAL_OFFSET: g_value_set_uint64 (value, self->priv->initial_offset); break; case PROP_DATE: g_value_set_uint64 (value, self->priv->date); break; case PROP_FILE_COLLECTION: g_value_set_string (value, self->priv->file_collection); break; case PROP_URI: g_value_set_string (value, self->priv->uri != NULL ? self->priv->uri: ""); break; case PROP_RESUME_SUPPORTED: g_value_set_boolean (value, self->priv->resume_supported); break; case PROP_BYTESTREAM: g_value_set_object (value, self->priv->bytestream); break; #ifdef ENABLE_JINGLE_FILE_TRANSFER case PROP_GTALK_FILE_COLLECTION: g_value_set_object (value, self->priv->gtalk_file_collection); break; #endif case PROP_SERVICE_NAME: g_value_set_string (value, self->priv->service_name); break; case PROP_METADATA: { /* We're fine with priv->metadata being NULL but dbus-glib * doesn't like iterating NULL as if it was a hash table. */ if (self->priv->metadata == NULL) { g_value_take_boxed (value, g_hash_table_new (g_str_hash, g_str_equal)); } else { g_value_set_boxed (value, self->priv->metadata); } } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_file_transfer_channel_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleFileTransferChannel *self = GABBLE_FILE_TRANSFER_CHANNEL (object); switch (property_id) { case PROP_STATE: gabble_file_transfer_channel_set_state ( TP_SVC_CHANNEL_TYPE_FILE_TRANSFER (object), g_value_get_uint (value), TP_FILE_TRANSFER_STATE_CHANGE_REASON_NONE); break; case PROP_CONTENT_TYPE: g_free (self->priv->content_type); self->priv->content_type = g_value_dup_string (value); break; case PROP_FILENAME: g_free (self->priv->filename); self->priv->filename = g_value_dup_string (value); break; case PROP_SIZE: self->priv->size = g_value_get_uint64 (value); break; case PROP_CONTENT_HASH_TYPE: self->priv->content_hash_type = g_value_get_uint (value); break; case PROP_CONTENT_HASH: g_free (self->priv->content_hash); self->priv->content_hash = g_value_dup_string (value); break; case PROP_DESCRIPTION: g_free (self->priv->description); self->priv->description = g_value_dup_string (value); break; case PROP_DATE: self->priv->date = g_value_get_uint64 (value); break; case PROP_INITIAL_OFFSET: self->priv->initial_offset = g_value_get_uint64 (value); break; case PROP_FILE_COLLECTION: g_free (self->priv->file_collection); self->priv->file_collection = g_value_dup_string (value); break; case PROP_URI: g_assert (self->priv->uri == NULL); /* construct only */ self->priv->uri = g_value_dup_string (value); break; case PROP_RESUME_SUPPORTED: self->priv->resume_supported = g_value_get_boolean (value); break; case PROP_BYTESTREAM: set_bytestream (self, GABBLE_BYTESTREAM_IFACE (g_value_get_object (value))); break; #ifdef ENABLE_JINGLE_FILE_TRANSFER case PROP_GTALK_FILE_COLLECTION: set_gtalk_file_collection (self, GTALK_FILE_COLLECTION (g_value_get_object (value))); break; #endif case PROP_SERVICE_NAME: self->priv->service_name = g_value_dup_string (value); break; case PROP_METADATA: self->priv->metadata = g_value_dup_boxed (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void free_array (GArray *array) { g_array_unref (array); } static void connection_presences_updated_cb (GabblePresenceCache *cache, GArray *handles, GabbleFileTransferChannel *self) { TpBaseChannel *base = TP_BASE_CHANNEL (self); TpBaseConnection *base_conn = tp_base_channel_get_connection (base); GabbleConnection *conn = GABBLE_CONNECTION (base_conn); guint i; for (i = 0; i < handles->len ; i++) { TpHandle handle; handle = g_array_index (handles, TpHandle, i); if (handle == tp_base_channel_get_target_handle (base)) { GabblePresence *presence; presence = gabble_presence_cache_get ( conn->presence_cache, handle); if (presence == NULL || presence->status < GABBLE_PRESENCE_XA) { /* Contact is disconnected */ if (self->priv->state != TP_FILE_TRANSFER_STATE_COMPLETED && self->priv->state != TP_FILE_TRANSFER_STATE_CANCELLED) { DEBUG ("peer disconnected. FileTransfer is cancelled"); gabble_file_transfer_channel_set_state ( TP_SVC_CHANNEL_TYPE_FILE_TRANSFER (self), TP_FILE_TRANSFER_STATE_CANCELLED, TP_FILE_TRANSFER_STATE_CHANGE_REASON_REMOTE_STOPPED); } } } } } static void gabble_file_transfer_channel_constructed (GObject *obj) { GabbleFileTransferChannel *self = GABBLE_FILE_TRANSFER_CHANNEL (obj); TpBaseChannel *base = TP_BASE_CHANNEL (self); TpBaseConnection *base_conn = tp_base_channel_get_connection (base); GabbleConnection *conn = GABBLE_CONNECTION (base_conn); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( base_conn, TP_HANDLE_TYPE_CONTACT); GArray *socket_access; TpSocketAccessControl access_control; /* Parent constructed chain */ void (*chain_up) (GObject *) = ((GObjectClass *) gabble_file_transfer_channel_parent_class)->constructed; if (chain_up != NULL) chain_up (obj); /* Initialise the available socket types hash table */ self->priv->available_socket_types = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) free_array); #ifdef GIBBER_TYPE_UNIX_TRANSPORT /* Socket_Address_Type_Unix */ socket_access = g_array_sized_new (FALSE, FALSE, sizeof (TpSocketAccessControl), 1); access_control = TP_SOCKET_ACCESS_CONTROL_LOCALHOST; g_array_append_val (socket_access, access_control); g_hash_table_insert (self->priv->available_socket_types, GUINT_TO_POINTER (TP_SOCKET_ADDRESS_TYPE_UNIX), socket_access); #endif /* Socket_Address_Type_IPv4 */ socket_access = g_array_sized_new (FALSE, FALSE, sizeof (TpSocketAccessControl), 1); access_control = TP_SOCKET_ACCESS_CONTROL_LOCALHOST; g_array_append_val (socket_access, access_control); g_hash_table_insert (self->priv->available_socket_types, GUINT_TO_POINTER (TP_SOCKET_ADDRESS_TYPE_IPV4), socket_access); /* Socket_Address_Type_IPv6 */ socket_access = g_array_sized_new (FALSE, FALSE, sizeof (TpSocketAccessControl), 1); access_control = TP_SOCKET_ACCESS_CONTROL_LOCALHOST; g_array_append_val (socket_access, access_control); g_hash_table_insert (self->priv->available_socket_types, GUINT_TO_POINTER (TP_SOCKET_ADDRESS_TYPE_IPV6), socket_access); gabble_signal_connect_weak (conn->presence_cache, "presences-updated", G_CALLBACK (connection_presences_updated_cb), obj); DEBUG ("New FT channel created: %s (contact: %s, initiator: %s, " "file: \"%s\", size: %" G_GUINT64_FORMAT ")", tp_base_channel_get_object_path (base), tp_handle_inspect (contact_repo, tp_base_channel_get_target_handle (base)), tp_handle_inspect (contact_repo, tp_base_channel_get_initiator (base)), self->priv->filename, self->priv->size); if (!tp_base_channel_is_requested (base)) /* Incoming transfer, URI has to be set by the handler */ g_assert (self->priv->uri == NULL); } static void gabble_file_transfer_channel_dispose (GObject *object); static void gabble_file_transfer_channel_finalize (GObject *object); static gboolean file_transfer_channel_properties_setter (GObject *object, GQuark interface, GQuark name, const GValue *value, gpointer setter_data, GError **error) { GabbleFileTransferChannel *self = (GabbleFileTransferChannel *) object; TpBaseChannel *base = TP_BASE_CHANNEL (self); g_return_val_if_fail (interface == TP_IFACE_QUARK_CHANNEL_TYPE_FILE_TRANSFER, FALSE); /* There is only one property with write access. So TpDBusPropertiesMixin * already checked this. */ g_assert (name == g_quark_from_static_string ("URI")); /* TpDBusPropertiesMixin already checked this */ g_assert (G_VALUE_HOLDS_STRING (value)); if (self->priv->uri != NULL) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "URI has already be set"); return FALSE; } if (tp_base_channel_is_requested (base)) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Channel is not an incoming transfer"); return FALSE; } if (self->priv->state != TP_FILE_TRANSFER_STATE_PENDING) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "State is not pending; cannot set URI"); return FALSE; } self->priv->uri = g_value_dup_string (value); tp_svc_channel_type_file_transfer_emit_uri_defined (self, self->priv->uri); return TRUE; } static void gabble_file_transfer_channel_fill_immutable_properties (TpBaseChannel *chan, GHashTable *properties) { TpBaseChannelClass *cls = TP_BASE_CHANNEL_CLASS ( gabble_file_transfer_channel_parent_class); cls->fill_immutable_properties (chan, properties); tp_dbus_properties_mixin_fill_properties_hash ( G_OBJECT (chan), properties, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "State", TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "ContentType", TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "Filename", TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "Size", TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "ContentHashType", TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "ContentHash", TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "Description", TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "Date", TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "AvailableSocketTypes", TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "TransferredBytes", TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "InitialOffset", GABBLE_IFACE_CHANNEL_TYPE_FILETRANSFER_FUTURE, "FileCollection", TP_IFACE_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA, "ServiceName", TP_IFACE_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA, "Metadata", NULL); /* URI is immutable only for outgoing transfers */ if (tp_base_channel_is_requested (chan)) { tp_dbus_properties_mixin_fill_properties_hash (G_OBJECT (chan), properties, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, "URI", NULL); } } static gchar * gabble_file_transfer_channel_get_object_path_suffix (TpBaseChannel *chan) { return g_strdup_printf ("FileTransferChannel/%p", chan); } static GPtrArray * gabble_file_transfer_channel_get_interfaces (TpBaseChannel *base) { GPtrArray *interfaces; interfaces = TP_BASE_CHANNEL_CLASS ( gabble_file_transfer_channel_parent_class)->get_interfaces (base); g_ptr_array_add (interfaces, GABBLE_IFACE_CHANNEL_TYPE_FILETRANSFER_FUTURE); g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA); return interfaces; } static void gabble_file_transfer_channel_class_init ( GabbleFileTransferChannelClass *gabble_file_transfer_channel_class) { GObjectClass *object_class = G_OBJECT_CLASS ( gabble_file_transfer_channel_class); TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS ( gabble_file_transfer_channel_class); GParamSpec *param_spec; static TpDBusPropertiesMixinPropImpl file_props[] = { { "State", "state", NULL }, { "ContentType", "content-type", NULL }, { "Filename", "filename", NULL }, { "Size", "size", NULL }, { "ContentHashType", "content-hash-type", NULL }, { "ContentHash", "content-hash", NULL }, { "Description", "description", NULL }, { "AvailableSocketTypes", "available-socket-types", NULL }, { "TransferredBytes", "transferred-bytes", NULL }, { "InitialOffset", "initial-offset", NULL }, { "Date", "date", NULL }, { "URI", "uri", NULL }, { NULL } }; static TpDBusPropertiesMixinPropImpl file_future_props[] = { { "FileCollection", "file-collection", NULL }, { NULL } }; static TpDBusPropertiesMixinPropImpl file_metadata_props[] = { { "ServiceName", "service-name", NULL }, { "Metadata", "metadata", NULL }, { NULL } }; static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { { TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER, tp_dbus_properties_mixin_getter_gobject_properties, file_transfer_channel_properties_setter, file_props }, { GABBLE_IFACE_CHANNEL_TYPE_FILETRANSFER_FUTURE, tp_dbus_properties_mixin_getter_gobject_properties, NULL, file_future_props }, { TP_IFACE_CHANNEL_INTERFACE_FILE_TRANSFER_METADATA, tp_dbus_properties_mixin_getter_gobject_properties, NULL, file_metadata_props }, { NULL } }; g_type_class_add_private (gabble_file_transfer_channel_class, sizeof (GabbleFileTransferChannelPrivate)); object_class->dispose = gabble_file_transfer_channel_dispose; object_class->finalize = gabble_file_transfer_channel_finalize; object_class->constructed = gabble_file_transfer_channel_constructed; object_class->get_property = gabble_file_transfer_channel_get_property; object_class->set_property = gabble_file_transfer_channel_set_property; base_class->channel_type = TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER; base_class->target_handle_type = TP_HANDLE_TYPE_CONTACT; base_class->get_interfaces = gabble_file_transfer_channel_get_interfaces; base_class->close = gabble_file_transfer_channel_close; base_class->fill_immutable_properties = gabble_file_transfer_channel_fill_immutable_properties; base_class->get_object_path_suffix = gabble_file_transfer_channel_get_object_path_suffix; param_spec = g_param_spec_uint ( "state", "TpFileTransferState state", "State of the file transfer in this channel", 0, NUM_TP_FILE_TRANSFER_STATES, TP_FILE_TRANSFER_STATE_NONE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_STATE, param_spec); param_spec = g_param_spec_string ( "content-type", "gchar *content-type", "ContentType of the file", "application/octet-stream", G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONTENT_TYPE, param_spec); param_spec = g_param_spec_string ( "filename", "gchar *filename", "Name of the file", "", G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_FILENAME, param_spec); param_spec = g_param_spec_uint64 ( "size", "guint size", "Size of the file in bytes", 0, G_MAXUINT64, GABBLE_UNDEFINED_FILE_SIZE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SIZE, param_spec); param_spec = g_param_spec_uint ( "content-hash-type", "TpFileHashType content-hash-type", "Hash type", 0, NUM_TP_FILE_HASH_TYPES, TP_FILE_HASH_TYPE_NONE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONTENT_HASH_TYPE, param_spec); param_spec = g_param_spec_string ( "content-hash", "gchar *content-hash", "Hash of the file contents", "", G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONTENT_HASH, param_spec); param_spec = g_param_spec_string ( "description", "gchar *description", "Description of the file", "", G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_DESCRIPTION, param_spec); param_spec = g_param_spec_boxed ( "available-socket-types", "GabbleSupportedSocketMap available-socket-types", "Available socket types", TP_HASH_TYPE_SUPPORTED_SOCKET_MAP, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_AVAILABLE_SOCKET_TYPES, param_spec); param_spec = g_param_spec_uint64 ( "transferred-bytes", "guint64 transferred-bytes", "Bytes transferred", 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_TRANSFERRED_BYTES, param_spec); param_spec = g_param_spec_uint64 ( "initial-offset", "guint64 initial_offset", "Offset set at the beginning of the transfer", 0, G_MAXUINT64, 0, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INITIAL_OFFSET, param_spec); param_spec = g_param_spec_uint64 ( "date", "Epoch time", "the last modification time of the file being transferred", 0, G_MAXUINT64, 0, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_DATE, param_spec); param_spec = g_param_spec_object ( "bytestream", "Object implementing the GabbleBytestreamIface interface", "Bytestream object used to send the file", G_TYPE_OBJECT, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_BYTESTREAM, param_spec); #ifdef ENABLE_JINGLE_FILE_TRANSFER param_spec = g_param_spec_object ( "gtalk-file-collection", "GTalkFileCollection object for gtalk-compatible file transfer", "GTalk compatible file transfer collection", G_TYPE_OBJECT, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_GTALK_FILE_COLLECTION, param_spec); #endif param_spec = g_param_spec_boolean ( "resume-supported", "resume is supported", "TRUE if resume is supported on this file transfer channel", FALSE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_RESUME_SUPPORTED, param_spec); param_spec = g_param_spec_string ( "file-collection", "gchar *file_colletion", "Token identifying a collection of files", "", G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_FILE_COLLECTION, param_spec); param_spec = g_param_spec_string ( "uri", "URI", "URI of the file being transferred", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_URI, param_spec); param_spec = g_param_spec_string ("service-name", "ServiceName", "The Metadata.ServiceName property of this channel", "", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SERVICE_NAME, param_spec); param_spec = g_param_spec_boxed ("metadata", "Metadata", "The Metadata.Metadata property of this channel", TP_HASH_TYPE_METADATA, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_METADATA, param_spec); gabble_file_transfer_channel_class->dbus_props_class.interfaces = prop_interfaces; tp_dbus_properties_mixin_class_init (object_class, G_STRUCT_OFFSET (GabbleFileTransferChannelClass, dbus_props_class)); } void gabble_file_transfer_channel_dispose (GObject *object) { GabbleFileTransferChannel *self = GABBLE_FILE_TRANSFER_CHANNEL (object); if (self->priv->dispose_has_run) return; DEBUG ("dispose called"); self->priv->dispose_has_run = TRUE; if (self->priv->progress_timer != 0) { g_source_remove (self->priv->progress_timer); self->priv->progress_timer = 0; } close_session_and_transport (self); /* release any references held by the object here */ if (G_OBJECT_CLASS (gabble_file_transfer_channel_parent_class)->dispose) G_OBJECT_CLASS (gabble_file_transfer_channel_parent_class)->dispose (object); } static void erase_socket (GabbleFileTransferChannel *self) { GArray *array; if (self->priv->socket_type != TP_SOCKET_ADDRESS_TYPE_UNIX) /* only UNIX sockets have to be erased */ return; if (self->priv->socket_address == NULL) return; array = g_value_get_boxed (self->priv->socket_address); if (g_unlink (array->data) != 0) { DEBUG ("unlink failed: %s", g_strerror (errno)); } } static void gabble_file_transfer_channel_finalize (GObject *object) { GabbleFileTransferChannel *self = GABBLE_FILE_TRANSFER_CHANNEL (object); /* free any data held directly by the object here */ erase_socket (self); g_free (self->priv->filename); if (self->priv->socket_address != NULL) tp_g_value_slice_free (self->priv->socket_address); g_free (self->priv->content_type); g_free (self->priv->content_hash); g_free (self->priv->description); g_hash_table_unref (self->priv->available_socket_types); g_free (self->priv->file_collection); g_free (self->priv->uri); g_free (self->priv->service_name); if (self->priv->metadata != NULL) g_hash_table_unref (self->priv->metadata); G_OBJECT_CLASS (gabble_file_transfer_channel_parent_class)->finalize (object); } static void close_session_and_transport (GabbleFileTransferChannel *self) { DEBUG ("Closing session and transport"); #ifdef ENABLE_JINGLE_FILE_TRANSFER if (self->priv->gtalk_file_collection != NULL) gtalk_file_collection_terminate (self->priv->gtalk_file_collection, self); tp_clear_object (&self->priv->gtalk_file_collection); #endif if (self->priv->bytestream != NULL) gabble_bytestream_iface_close (self->priv->bytestream, NULL); tp_clear_object (&self->priv->bytestream); tp_clear_object (&self->priv->listener); tp_clear_object (&self->priv->transport); } static gboolean setup_local_socket (GabbleFileTransferChannel *self, TpSocketAddressType address_type, TpSocketAccessControl access_control, const GValue *access_control_param); static void gabble_file_transfer_channel_set_state ( TpSvcChannelTypeFileTransfer *iface, TpFileTransferState state, TpFileTransferStateChangeReason reason) { GabbleFileTransferChannel *self = GABBLE_FILE_TRANSFER_CHANNEL (iface); if (self->priv->state == state) return; self->priv->state = state; tp_svc_channel_type_file_transfer_emit_file_transfer_state_changed (iface, state, reason); } static gboolean check_address_and_access_control (GabbleFileTransferChannel *self, TpSocketAddressType address_type, TpSocketAccessControl access_control, const GValue *access_control_param, GError **error) { GArray *access_arr; guint i; /* Do we support this AddressType? */ access_arr = g_hash_table_lookup (self->priv->available_socket_types, GUINT_TO_POINTER (address_type)); if (access_arr == NULL) { g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "AddressType %u is not implemented", address_type); return FALSE; } /* Do we support this AccessControl? */ for (i = 0; i < access_arr->len; i++) { TpSocketAccessControl control; control = g_array_index (access_arr, TpSocketAccessControl, i); if (control == access_control) return TRUE; } g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "AccesControl %u is not implemented with AddressType %u", access_control, address_type); return FALSE; } static void channel_open (GabbleFileTransferChannel *self) { DEBUG ("Channel open"); /* This is needed in case the ProvideFile wasn't called yet, to know if we should go into OPEN state when ProvideFile gets called. */ self->priv->channel_opened = TRUE; if (self->priv->socket_address != NULL) { /* ProvideFile has already been called. Channel is Open */ tp_svc_channel_type_file_transfer_emit_initial_offset_defined (self, self->priv->initial_offset); gabble_file_transfer_channel_set_state ( TP_SVC_CHANNEL_TYPE_FILE_TRANSFER (self), TP_FILE_TRANSFER_STATE_OPEN, TP_FILE_TRANSFER_STATE_CHANGE_REASON_NONE); if (self->priv->transport != NULL) gibber_transport_block_receiving (self->priv->transport, FALSE); } else { /* Client has to call ProvideFile to open the channel */ gabble_file_transfer_channel_set_state ( TP_SVC_CHANNEL_TYPE_FILE_TRANSFER (self), TP_FILE_TRANSFER_STATE_ACCEPTED, TP_FILE_TRANSFER_STATE_CHANGE_REASON_NONE); } } static void bytestream_closed (GabbleFileTransferChannel *self) { if (self->priv->state != TP_FILE_TRANSFER_STATE_COMPLETED && self->priv->state != TP_FILE_TRANSFER_STATE_CANCELLED) { gboolean receiver = !tp_base_channel_is_requested ( TP_BASE_CHANNEL (self)); /* Something did wrong */ gabble_file_transfer_channel_set_state ( TP_SVC_CHANNEL_TYPE_FILE_TRANSFER (self), TP_FILE_TRANSFER_STATE_CANCELLED, receiver ? TP_FILE_TRANSFER_STATE_CHANGE_REASON_LOCAL_ERROR : TP_FILE_TRANSFER_STATE_CHANGE_REASON_REMOTE_ERROR); } } static void bytestream_state_changed_cb (GabbleBytestreamIface *bytestream, GabbleBytestreamState state, gpointer user_data) { GabbleFileTransferChannel *self = GABBLE_FILE_TRANSFER_CHANNEL (user_data); if (state == GABBLE_BYTESTREAM_STATE_OPEN) { channel_open (self); } else if (state == GABBLE_BYTESTREAM_STATE_CLOSED) { bytestream_closed (self); } } static void bytestream_write_blocked_cb (GabbleBytestreamIface *bytestream, gboolean blocked, GabbleFileTransferChannel *self); static gboolean set_bytestream (GabbleFileTransferChannel *self, GabbleBytestreamIface *bytestream) { if (bytestream == NULL) return FALSE; g_return_val_if_fail (self->priv->bytestream == NULL, FALSE); #ifdef ENABLE_JINGLE_FILE_TRANSFER g_return_val_if_fail (self->priv->gtalk_file_collection == NULL, FALSE); #endif DEBUG ("Setting bytestream to %p", bytestream); self->priv->bytestream = g_object_ref (bytestream); gabble_signal_connect_weak (bytestream, "state-changed", G_CALLBACK (bytestream_state_changed_cb), G_OBJECT (self)); gabble_signal_connect_weak (bytestream, "write-blocked", G_CALLBACK (bytestream_write_blocked_cb), G_OBJECT (self)); return TRUE; } #ifdef ENABLE_JINGLE_FILE_TRANSFER static gboolean set_gtalk_file_collection ( GabbleFileTransferChannel *self, GTalkFileCollection *gtalk_file_collection) { if (gtalk_file_collection == NULL) return FALSE; g_return_val_if_fail (self->priv->bytestream == NULL, FALSE); g_return_val_if_fail (self->priv->gtalk_file_collection == NULL, FALSE); self->priv->gtalk_file_collection = g_object_ref (gtalk_file_collection); /* No need to listen to any signals, the GTalkFileCollection will call our callbacks on his own */ return TRUE; } #endif static void bytestream_negotiate_cb (GabbleBytestreamIface *bytestream, WockyStanza *msg, GObject *object, gpointer user_data) { GabbleFileTransferChannel *self = GABBLE_FILE_TRANSFER_CHANNEL (user_data); WockyNode *si; WockyNode *file = NULL; if (bytestream == NULL) { DEBUG ("receiver refused file offer"); gabble_file_transfer_channel_set_state ( TP_SVC_CHANNEL_TYPE_FILE_TRANSFER (self), TP_FILE_TRANSFER_STATE_CANCELLED, TP_FILE_TRANSFER_STATE_CHANGE_REASON_REMOTE_STOPPED); return; } si = wocky_node_get_child_ns (wocky_stanza_get_top_node (msg), "si", NS_SI); if (si != NULL) file = wocky_node_get_child_ns (si, "file", NULL); if (file != NULL) { WockyNode *range; range = wocky_node_get_child (file, "range"); if (range != NULL) { const gchar *offset_str; offset_str = wocky_node_get_attribute (range, "offset"); if (offset_str != NULL) { self->priv->initial_offset = g_ascii_strtoull (offset_str, NULL, 0); } } } DEBUG ("receiver accepted file offer (offset: %" G_GUINT64_FORMAT ")", self->priv->initial_offset); set_bytestream (self, bytestream); } static void add_metadata_forms (GabbleFileTransferChannel *self, WockyNode *file) { if (!tp_str_empty (self->priv->service_name)) { wocky_node_add_build (file, '(', "x", ':', NS_X_DATA, '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '@', "type", "hidden", '(', "value", '$', NS_TP_FT_METADATA_SERVICE, ')', ')', '(', "field", '@', "var", "ServiceName", '(', "value", '$', self->priv->service_name, ')', ')', ')', NULL); } if (self->priv->metadata != NULL && g_hash_table_size (self->priv->metadata) > 0) { WockyNode *x; GHashTableIter iter; gpointer key, val; wocky_node_add_build (file, '(', "x", ':', NS_X_DATA, '*', &x, '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '@', "type", "hidden", '(', "value", '$', NS_TP_FT_METADATA, ')', ')', ')', NULL); g_hash_table_iter_init (&iter, self->priv->metadata); while (g_hash_table_iter_next (&iter, &key, &val)) { const gchar * const *values = val; WockyNode *field = wocky_node_add_child (x, "field"); wocky_node_set_attribute (field, "var", key); for (; values != NULL && *values != NULL; values++) { wocky_node_add_child_with_content (field, "value", *values); } } } } static void offer_bytestream (GabbleFileTransferChannel *self, const gchar *jid, const gchar *resource) { GabbleConnection *conn = GABBLE_CONNECTION (tp_base_channel_get_connection ( TP_BASE_CHANNEL (self))); WockyStanza *msg; WockyNode *si_node, *file_node; gchar *stream_id, *size_str, *full_jid; if (resource) full_jid = g_strdup_printf ("%s/%s", jid, resource); else full_jid = g_strdup (jid); DEBUG ("Offering SI Bytestream file transfer to %s", full_jid); /* Outgoing FT , we'll need SOCK5 proxies */ gabble_bytestream_factory_query_socks5_proxies ( conn->bytestream_factory); stream_id = gabble_bytestream_factory_generate_stream_id (); msg = gabble_bytestream_factory_make_stream_init_iq (full_jid, stream_id, NS_FILE_TRANSFER); si_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (msg), "si", NS_SI); g_assert (si_node != NULL); size_str = g_strdup_printf ("%" G_GUINT64_FORMAT, self->priv->size); file_node = wocky_node_add_child_ns (si_node, "file", NS_FILE_TRANSFER); wocky_node_set_attributes (file_node, "name", self->priv->filename, "size", size_str, "mime-type", self->priv->content_type, NULL); add_metadata_forms (self, file_node); if (self->priv->content_hash != NULL) wocky_node_set_attribute (file_node, "hash", self->priv->content_hash); if (self->priv->date != 0) { time_t t; struct tm *tm; char date_str[21]; t = (time_t) self->priv->date; tm = gmtime (&t); #ifdef G_OS_WIN32 strftime (date_str, sizeof (date_str), "%Y-%m-%dT%H:%M:%SZ", tm); #else strftime (date_str, sizeof (date_str), "%FT%H:%M:%SZ", tm); #endif wocky_node_set_attribute (file_node, "date", date_str); } wocky_node_add_child_with_content (file_node, "desc", self->priv->description); /* we support resume */ wocky_node_add_child (file_node, "range"); gabble_bytestream_factory_negotiate_stream ( conn->bytestream_factory, msg, stream_id, bytestream_negotiate_cb, self, G_OBJECT (self)); g_object_unref (msg); g_free (stream_id); g_free (size_str); g_free (full_jid); } #ifdef ENABLE_JINGLE_FILE_TRANSFER void gabble_file_transfer_channel_gtalk_file_collection_state_changed ( GabbleFileTransferChannel *self, GTalkFileCollectionState state, gboolean local_terminator) { DEBUG ("gtalk ft state changed to %d", state); switch (state) { case GTALK_FILE_COLLECTION_STATE_PENDING: gabble_file_transfer_channel_set_state ( TP_SVC_CHANNEL_TYPE_FILE_TRANSFER (self), TP_FILE_TRANSFER_STATE_PENDING, TP_FILE_TRANSFER_STATE_CHANGE_REASON_NONE); break; case GTALK_FILE_COLLECTION_STATE_ACCEPTED: if (self->priv->state == TP_FILE_TRANSFER_STATE_PENDING) { gabble_file_transfer_channel_set_state ( TP_SVC_CHANNEL_TYPE_FILE_TRANSFER (self), TP_FILE_TRANSFER_STATE_ACCEPTED, TP_FILE_TRANSFER_STATE_CHANGE_REASON_NONE); } break; case GTALK_FILE_COLLECTION_STATE_OPEN: channel_open (self); break; case GTALK_FILE_COLLECTION_STATE_TERMINATED: if (self->priv->state != TP_FILE_TRANSFER_STATE_COMPLETED && self->priv->state != TP_FILE_TRANSFER_STATE_CANCELLED) { gabble_file_transfer_channel_set_state ( TP_SVC_CHANNEL_TYPE_FILE_TRANSFER (self), TP_FILE_TRANSFER_STATE_CANCELLED, local_terminator ? TP_FILE_TRANSFER_STATE_CHANGE_REASON_LOCAL_STOPPED: TP_FILE_TRANSFER_STATE_CHANGE_REASON_REMOTE_STOPPED); } close_session_and_transport (self); break; case GTALK_FILE_COLLECTION_STATE_ERROR: case GTALK_FILE_COLLECTION_STATE_CONNECTION_FAILED: gabble_file_transfer_channel_set_state ( TP_SVC_CHANNEL_TYPE_FILE_TRANSFER (self), TP_FILE_TRANSFER_STATE_CANCELLED, TP_FILE_TRANSFER_STATE_CHANGE_REASON_LOCAL_ERROR); close_session_and_transport (self); break; case GTALK_FILE_COLLECTION_STATE_COMPLETED: gabble_file_transfer_channel_set_state ( TP_SVC_CHANNEL_TYPE_FILE_TRANSFER (self), TP_FILE_TRANSFER_STATE_COMPLETED, TP_FILE_TRANSFER_STATE_CHANGE_REASON_NONE); if (self->priv->transport && gibber_transport_buffer_is_empty (self->priv->transport)) gibber_transport_disconnect (self->priv->transport); break; } } static gboolean offer_gtalk_file_transfer (GabbleFileTransferChannel *self, const gchar *full_jid, GError **error) { TpBaseChannel *base = TP_BASE_CHANNEL (self); GabbleConnection *conn = GABBLE_CONNECTION ( tp_base_channel_get_connection (base)); WockyJingleFactory *jf; GTalkFileCollection *gtalk_file_collection; DEBUG ("Offering Gtalk file transfer to %s", full_jid); jf = gabble_jingle_mint_get_factory (conn->jingle_mint); g_return_val_if_fail (jf != NULL, FALSE); gtalk_file_collection = gtalk_file_collection_new (self, jf, tp_base_channel_get_target_handle (base), full_jid); g_return_val_if_fail (gtalk_file_collection != NULL, FALSE); set_gtalk_file_collection (self, gtalk_file_collection); gtalk_file_collection_initiate (self->priv->gtalk_file_collection, self); /* We would have gotten a set_gtalk_file_collection so we already hold an additional reference to the object, so we can drop the reference we got from the gtalk_file_collection_new. If we didn't get our set_gtalk_file_collection called, then the ft manager doesn't handle us, so it's best to just destroy it anyways */ g_object_unref (gtalk_file_collection); return TRUE; } #endif gboolean gabble_file_transfer_channel_offer_file (GabbleFileTransferChannel *self, GError **error) { TpBaseChannel *base = TP_BASE_CHANNEL (self); TpBaseConnection *base_conn = tp_base_channel_get_connection (base); GabbleConnection *conn = GABBLE_CONNECTION (base_conn); GabblePresence *presence; gboolean result; TpHandleRepoIface *contact_repo, *room_repo; const gchar *jid; gboolean si = FALSE; gboolean use_si = FALSE; const gchar *si_resource = NULL; #ifdef ENABLE_JINGLE_FILE_TRANSFER gboolean jingle_share = FALSE; const gchar *share_resource = NULL; #endif g_assert (!tp_str_empty (self->priv->filename)); g_assert (self->priv->size != GABBLE_UNDEFINED_FILE_SIZE); g_return_val_if_fail (self->priv->bytestream == NULL, FALSE); #ifdef ENABLE_JINGLE_FILE_TRANSFER g_return_val_if_fail (self->priv->gtalk_file_collection == NULL, FALSE); #endif presence = gabble_presence_cache_get (conn->presence_cache, tp_base_channel_get_target_handle (base)); if (presence == NULL) { DEBUG ("can't find contact's presence"); g_set_error (error, TP_ERROR, TP_ERROR_OFFLINE, "can't find contact's presence"); return FALSE; } if (self->priv->service_name != NULL || self->priv->metadata != NULL) { if (!gabble_presence_has_cap (presence, NS_TP_FT_METADATA)) { DEBUG ("trying to use Metadata properties on a contact " "who doesn't support it"); g_set_error (error, TP_ERROR, TP_ERROR_NOT_CAPABLE, "The specified contact does not support the " "Metadata extension; you should ensure both ServiceName and " "Metadata properties are not present in the channel " "request"); return FALSE; } } contact_repo = tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_CONTACT); room_repo = tp_base_connection_get_handles (base_conn, TP_HANDLE_TYPE_ROOM); jid = tp_handle_inspect (contact_repo, tp_base_channel_get_target_handle (base)); if (gabble_get_room_handle_from_jid (room_repo, jid) == 0) { /* Not a MUC jid, need to get a resource */ /* FIXME: should we check for SI, bytestreams and/or IBB too? * http://bugs.freedesktop.org/show_bug.cgi?id=23777 */ si_resource = gabble_presence_pick_resource_by_caps (presence, 0, gabble_capability_set_predicate_has, NS_FILE_TRANSFER); si = (si_resource != NULL); #ifdef ENABLE_JINGLE_FILE_TRANSFER share_resource = gabble_presence_pick_resource_by_caps (presence, 0, gabble_capability_set_predicate_has, NS_GOOGLE_FEAT_SHARE); jingle_share = (share_resource != NULL); #endif } else { /* MUC jid, we already have the full jid */ si = gabble_presence_has_cap (presence, NS_FILE_TRANSFER); #ifdef ENABLE_JINGLE_FILE_TRANSFER jingle_share = gabble_presence_has_cap (presence, NS_GOOGLE_FEAT_SHARE); #endif } /* Use bytestream if we have SI, but no jingle-share or if we have SI and jingle-share but we have no google relay token */ #ifdef ENABLE_JINGLE_FILE_TRANSFER use_si = si && (!jingle_share || wocky_jingle_info_get_google_relay_token ( gabble_jingle_mint_get_info (conn->jingle_mint)) == NULL); #else use_si = si; #endif if (use_si) { offer_bytestream (self, jid, si_resource); result = TRUE; } #ifdef ENABLE_JINGLE_FILE_TRANSFER else if (jingle_share) { gchar *full_jid = gabble_peer_to_jid (conn, tp_base_channel_get_target_handle (base), share_resource); result = offer_gtalk_file_transfer (self, full_jid, error); g_free (full_jid); } #endif else { DEBUG ("contact doesn't have file transfer capabilities"); g_set_error (error, TP_ERROR, TP_ERROR_NOT_CAPABLE, "contact doesn't have file transfer capabilities"); result = FALSE; } return result; } static void emit_progress_update (GabbleFileTransferChannel *self) { TpSvcChannelTypeFileTransfer *iface = TP_SVC_CHANNEL_TYPE_FILE_TRANSFER (self); g_get_current_time (&self->priv->last_transferred_bytes_emitted); tp_svc_channel_type_file_transfer_emit_transferred_bytes_changed ( iface, self->priv->transferred_bytes); if (self->priv->progress_timer != 0) { g_source_remove (self->priv->progress_timer); self->priv->progress_timer = 0; } } static gboolean emit_progress_update_cb (gpointer user_data) { GabbleFileTransferChannel *self = GABBLE_FILE_TRANSFER_CHANNEL (user_data); emit_progress_update (self); return FALSE; } static void transferred_chunk (GabbleFileTransferChannel *self, guint64 count) { GTimeVal timeval; gint interval; self->priv->transferred_bytes += count; if (self->priv->transferred_bytes + self->priv->initial_offset >= self->priv->size) { /* If the transfer has finished send an update right away */ emit_progress_update (self); return; } if (self->priv->progress_timer != 0) { /* A progress update signal is already scheduled */ return; } /* Only emit the TransferredBytes signal if it has been one second since its * last emission. */ g_get_current_time (&timeval); interval = timeval.tv_sec - self->priv->last_transferred_bytes_emitted.tv_sec; if (interval > 1) { /* At least more then a second apart, emit right away */ emit_progress_update (self); return; } /* Convert interval to milliseconds and calculate it more precisely */ interval *= 1000; interval += (timeval.tv_usec - self->priv->last_transferred_bytes_emitted.tv_usec)/1000; /* Protect against clock skew, if the interval is negative the worst thing * that can happen is that we wait an extra second before emitting the signal */ interval = ABS (interval); if (interval > 1000) emit_progress_update (self); else self->priv->progress_timer = g_timeout_add (1000 - interval, emit_progress_update_cb, self); } static void data_received_cb (GabbleFileTransferChannel *self, const guint8 *data, guint len) { GError *error = NULL; g_assert (self->priv->transport != NULL); if (!gibber_transport_send (self->priv->transport, data, len, &error)) { DEBUG ("sending to transport failed: %s", error->message); g_error_free (error); gabble_file_transfer_channel_set_state ( TP_SVC_CHANNEL_TYPE_FILE_TRANSFER (self), TP_FILE_TRANSFER_STATE_CANCELLED, TP_FILE_TRANSFER_STATE_CHANGE_REASON_LOCAL_ERROR); return; } transferred_chunk (self, (guint64) len); if (self->priv->bytestream != NULL && self->priv->transferred_bytes + self->priv->initial_offset >= self->priv->size) { DEBUG ("Received all the file. Transfer is complete"); gabble_file_transfer_channel_set_state ( TP_SVC_CHANNEL_TYPE_FILE_TRANSFER (self), TP_FILE_TRANSFER_STATE_COMPLETED, TP_FILE_TRANSFER_STATE_CHANGE_REASON_NONE); if (gibber_transport_buffer_is_empty (self->priv->transport)) gibber_transport_disconnect (self->priv->transport); return; } if (!gibber_transport_buffer_is_empty (self->priv->transport)) { /* We don't want to send more data while the buffer isn't empty */ if (self->priv->bytestream != NULL) gabble_bytestream_iface_block_reading (self->priv->bytestream, TRUE); #ifdef ENABLE_JINGLE_FILE_TRANSFER else if (self->priv->gtalk_file_collection != NULL) gtalk_file_collection_block_reading (self->priv->gtalk_file_collection, self, TRUE); #endif } } #ifdef ENABLE_JINGLE_FILE_TRANSFER void gabble_file_transfer_channel_gtalk_file_collection_data_received ( GabbleFileTransferChannel *self, const gchar *data, guint len) { data_received_cb (self, (const guint8 *) data, len); } #endif static void bytestream_data_received_cb (GabbleBytestreamIface *stream, TpHandle sender, GString *data, gpointer user_data) { GabbleFileTransferChannel *self = GABBLE_FILE_TRANSFER_CHANNEL (user_data); data_received_cb (self, (const guint8 *) data->str, data->len); } static void augment_si_reply (WockyNode *si, gpointer user_data) { GabbleFileTransferChannel *self = GABBLE_FILE_TRANSFER_CHANNEL (user_data); WockyNode *file; file = wocky_node_add_child_ns (si, "file", NS_FILE_TRANSFER); if (self->priv->initial_offset != 0) { WockyNode *range; gchar *offset_str; range = wocky_node_add_child (file, "range"); offset_str = g_strdup_printf ("%" G_GUINT64_FORMAT, self->priv->initial_offset); wocky_node_set_attribute (range, "offset", offset_str); /* Don't set "length" attribute as the default is the length of the file * from offset to the end which is what we want when resuming a FT. */ g_free (offset_str); } } /** * gabble_file_transfer_channel_accept_file * * Implements D-Bus method AcceptFile * on interface org.freedesktop.Telepathy.Channel.Type.FileTransfer */ static void gabble_file_transfer_channel_accept_file (TpSvcChannelTypeFileTransfer *iface, guint address_type, guint access_control, const GValue *access_control_param, guint64 offset, DBusGMethodInvocation *context) { GabbleFileTransferChannel *self = GABBLE_FILE_TRANSFER_CHANNEL (iface); TpBaseChannel *base = TP_BASE_CHANNEL (self); GError *error = NULL; if (tp_base_channel_is_requested (base)) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "Channel is not an incoming transfer"); dbus_g_method_return_error (context, error); g_error_free (error); return; } if (self->priv->state != TP_FILE_TRANSFER_STATE_PENDING) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "State is not pending; cannot accept file"); dbus_g_method_return_error (context, error); g_error_free (error); return; } if (!check_address_and_access_control (self, address_type, access_control, access_control_param, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); return; } if (!setup_local_socket (self, address_type, access_control, access_control_param)) { DEBUG ("Could not set up local socket"); g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "Could not set up local socket"); dbus_g_method_return_error (context, error); g_error_free (error); return; } gabble_file_transfer_channel_set_state (iface, TP_FILE_TRANSFER_STATE_ACCEPTED, TP_FILE_TRANSFER_STATE_CHANGE_REASON_REQUESTED); tp_svc_channel_type_file_transfer_return_from_accept_file (context, self->priv->socket_address); if (self->priv->resume_supported) { self->priv->initial_offset = offset; } else { DEBUG ("Resume is not supported on this file transfer"); self->priv->initial_offset = 0; } if (self->priv->bytestream != NULL) { gabble_signal_connect_weak (self->priv->bytestream, "data-received", G_CALLBACK (bytestream_data_received_cb), G_OBJECT (self)); /* Block the bytestream while the user is not connected to the socket */ gabble_bytestream_iface_block_reading (self->priv->bytestream, TRUE); /* channel state will change to open once the bytestream is open */ gabble_bytestream_iface_accept (self->priv->bytestream, augment_si_reply, self); } #ifdef ENABLE_JINGLE_FILE_TRANSFER else if (self->priv->gtalk_file_collection != NULL) { /* Block the gtalk ft stream while the user is not connected to the socket */ gtalk_file_collection_block_reading (self->priv->gtalk_file_collection, self, TRUE); gtalk_file_collection_accept (self->priv->gtalk_file_collection, self); } #endif else { g_assert_not_reached (); } } /** * gabble_file_transfer_channel_provide_file * * Implements D-Bus method ProvideFile * on interface org.freedesktop.Telepathy.Channel.Type.FileTransfer */ static void gabble_file_transfer_channel_provide_file ( TpSvcChannelTypeFileTransfer *iface, guint address_type, guint access_control, const GValue *access_control_param, DBusGMethodInvocation *context) { GabbleFileTransferChannel *self = GABBLE_FILE_TRANSFER_CHANNEL (iface); GError *error = NULL; if (!tp_base_channel_is_requested (TP_BASE_CHANNEL (self))) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "Channel is not an outgoing transfer"); dbus_g_method_return_error (context, error); g_error_free (error); return; } if (self->priv->state != TP_FILE_TRANSFER_STATE_PENDING && self->priv->state != TP_FILE_TRANSFER_STATE_ACCEPTED) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "State is not pending or accepted; cannot provide file"); dbus_g_method_return_error (context, error); g_error_free (error); return; } if (self->priv->socket_address != NULL) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "ProvideFile has already been called for this channel"); dbus_g_method_return_error (context, error); g_error_free (error); return; } if (!check_address_and_access_control (self, address_type, access_control, access_control_param, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); return; } if (!setup_local_socket (self, address_type, access_control, access_control_param)) { DEBUG ("Could not set up local socket"); g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "Could not set up local socket"); dbus_g_method_return_error (context, error); g_error_free (error); return; } if (self->priv->channel_opened) { /* Remote already accepted the file. Channel is Open. * If not channel stay Pending. */ tp_svc_channel_type_file_transfer_emit_initial_offset_defined (self, self->priv->initial_offset); gabble_file_transfer_channel_set_state (iface, TP_FILE_TRANSFER_STATE_OPEN, TP_FILE_TRANSFER_STATE_CHANGE_REASON_REQUESTED); } tp_svc_channel_type_file_transfer_return_from_provide_file (context, self->priv->socket_address); } static void file_transfer_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcChannelTypeFileTransferClass *klass = (TpSvcChannelTypeFileTransferClass *) g_iface; #define IMPLEMENT(x) tp_svc_channel_type_file_transfer_implement_##x (\ klass, gabble_file_transfer_channel_##x) IMPLEMENT (accept_file); IMPLEMENT (provide_file); #undef IMPLEMENT } #ifdef GIBBER_TYPE_UNIX_TRANSPORT static gchar * get_local_unix_socket_path (GabbleFileTransferChannel *self) { TpBaseConnection *base_conn = tp_base_channel_get_connection ( TP_BASE_CHANNEL (self)); GabbleConnection *conn = GABBLE_CONNECTION (base_conn); const gchar *tmp_dir; gchar *path = NULL; gchar *name; struct stat buf; tmp_dir = gabble_ft_manager_get_tmp_dir (conn->ft_manager); if (tmp_dir == NULL) return NULL; name = g_strdup_printf ("ft-channel-%p", self); path = g_build_filename (tmp_dir, name, NULL); g_free (name); if (g_stat (path, &buf) == 0) { /* The file is not supposed to exist */ DEBUG ("file %s already exists", path); g_assert_not_reached (); } return path; } #endif /* * Data is available from the channel so we can send it. */ static void transport_handler (GibberTransport *transport, GibberBuffer *data, gpointer user_data) { GabbleFileTransferChannel *self = GABBLE_FILE_TRANSFER_CHANNEL (user_data); if (self->priv->bytestream != NULL) { if (!gabble_bytestream_iface_send (self->priv->bytestream, data->length, (const gchar *) data->data)) { DEBUG ("Sending failed. Closing the bytestream"); close_session_and_transport (self); return; } } #ifdef ENABLE_JINGLE_FILE_TRANSFER else if (self->priv->gtalk_file_collection != NULL) { if (!gtalk_file_collection_send_data (self->priv->gtalk_file_collection, self, (const gchar *) data->data, data->length)) { DEBUG ("Sending failed. Closing the jingle session"); close_session_and_transport (self); return; } } #endif transferred_chunk (self, (guint64) data->length); if (self->priv->transferred_bytes + self->priv->initial_offset >= self->priv->size) { if (self->priv->bytestream != NULL) { DEBUG ("All the file has been sent. Closing the bytestream"); gabble_file_transfer_channel_set_state ( TP_SVC_CHANNEL_TYPE_FILE_TRANSFER (self), TP_FILE_TRANSFER_STATE_COMPLETED, TP_FILE_TRANSFER_STATE_CHANGE_REASON_NONE); gabble_bytestream_iface_close (self->priv->bytestream, NULL); } #ifdef ENABLE_JINGLE_FILE_TRANSFER else if (self->priv->gtalk_file_collection != NULL) { DEBUG ("All the file has been sent."); gtalk_file_collection_completed (self->priv->gtalk_file_collection, self); } #endif } } static void bytestream_write_blocked_cb (GabbleBytestreamIface *bytestream, gboolean blocked, GabbleFileTransferChannel *self) { if (self->priv->transport != NULL) gibber_transport_block_receiving (self->priv->transport, blocked); } #ifdef ENABLE_JINGLE_FILE_TRANSFER void gabble_file_transfer_channel_gtalk_file_collection_write_blocked ( GabbleFileTransferChannel *self, gboolean blocked) { if (self->priv->transport != NULL) gibber_transport_block_receiving (self->priv->transport, blocked); } #endif static void file_transfer_send (GabbleFileTransferChannel *self) { /* We shouldn't receive data if the bytestream isn't open otherwise it will error out */ if (self->priv->state == TP_FILE_TRANSFER_STATE_OPEN) gibber_transport_block_receiving (self->priv->transport, FALSE); else gibber_transport_block_receiving (self->priv->transport, TRUE); gibber_transport_set_handler (self->priv->transport, transport_handler, self); } static void file_transfer_receive (GabbleFileTransferChannel *self) { /* Client is connected, we can now receive data. Unblock the bytestream */ if (self->priv->bytestream != NULL) gabble_bytestream_iface_block_reading (self->priv->bytestream, FALSE); #ifdef ENABLE_JINGLE_FILE_TRANSFER else if (self->priv->gtalk_file_collection != NULL) gtalk_file_collection_block_reading (self->priv->gtalk_file_collection, self, FALSE); #endif } static void transport_disconnected_cb (GibberTransport *transport, GabbleFileTransferChannel *self) { TpBaseChannel *base = TP_BASE_CHANNEL (self); gboolean requested = tp_base_channel_is_requested (base); DEBUG ("transport to local socket has been disconnected"); /* If we are sending the file, we can expect the transport to be closed as soon as we received all the data. Otherwise, it should only get closed once the channel has gone to state COMPLETED. This allows to make sure we detect an error if the channel is closed while receiving a gtalk-ft folder where the size is an approximation of the real size to be received */ if ((requested && self->priv->transferred_bytes + self->priv->initial_offset < self->priv->size) || (!requested && self->priv->state != TP_FILE_TRANSFER_STATE_COMPLETED)) { gabble_file_transfer_channel_set_state ( TP_SVC_CHANNEL_TYPE_FILE_TRANSFER (self), TP_FILE_TRANSFER_STATE_CANCELLED, TP_FILE_TRANSFER_STATE_CHANGE_REASON_LOCAL_ERROR); close_session_and_transport (self); } } static void transport_buffer_empty_cb (GibberTransport *transport, GabbleFileTransferChannel *self) { /* Buffer is empty so we can unblock the buffer if it was blocked */ if (self->priv->bytestream != NULL) gabble_bytestream_iface_block_reading (self->priv->bytestream, FALSE); #ifdef ENABLE_JINGLE_FILE_TRANSFER if (self->priv->gtalk_file_collection != NULL) gtalk_file_collection_block_reading (self->priv->gtalk_file_collection, self, FALSE); #endif if (self->priv->state > TP_FILE_TRANSFER_STATE_OPEN) gibber_transport_disconnect (transport); } /* * Some client is connecting to the Unix socket. */ static void new_connection_cb (GibberListener *listener, GibberTransport *transport, struct sockaddr_storage *addr, guint size, gpointer user_data) { GabbleFileTransferChannel *self = GABBLE_FILE_TRANSFER_CHANNEL (user_data); TpBaseChannel *base = TP_BASE_CHANNEL (self); DEBUG ("Client connected to local socket"); self->priv->transport = g_object_ref (transport); gabble_signal_connect_weak (transport, "disconnected", G_CALLBACK (transport_disconnected_cb), G_OBJECT (self)); gabble_signal_connect_weak (transport, "buffer-empty", G_CALLBACK (transport_buffer_empty_cb), G_OBJECT (self)); if (!tp_base_channel_is_requested (base)) /* Incoming file transfer */ file_transfer_receive (self); else /* Outgoing file transfer */ file_transfer_send (self); /* stop listening on local socket */ tp_clear_object (&self->priv->listener); } static gboolean setup_local_socket (GabbleFileTransferChannel *self, TpSocketAddressType address_type, TpSocketAccessControl access_control, const GValue *access_control_param) { GError *error = NULL; self->priv->listener = gibber_listener_new (); /* Add this stage the address_type and access_control have been checked and * are supposed to be valid */ #ifdef GIBBER_TYPE_UNIX_TRANSPORT if (address_type == TP_SOCKET_ADDRESS_TYPE_UNIX) { gchar *path; GArray *array; g_assert (access_control == TP_SOCKET_ACCESS_CONTROL_LOCALHOST); path = get_local_unix_socket_path (self); if (path == NULL) return FALSE; if (!gibber_listener_listen_socket (self->priv->listener, (gchar *) path, FALSE, &error)) { DEBUG ("listen_socket failed: %s", error->message); g_error_free (error); tp_clear_object (&self->priv->listener); return FALSE; } array = g_array_sized_new (TRUE, FALSE, sizeof (gchar), strlen (path)); g_array_insert_vals (array, 0, path, strlen (path)); self->priv->socket_address = tp_g_value_slice_new ( DBUS_TYPE_G_UCHAR_ARRAY); g_value_set_boxed (self->priv->socket_address, array); DEBUG ("local socket %s", path); g_free (path); g_array_unref (array); } else #endif if (address_type == TP_SOCKET_ADDRESS_TYPE_IPV4) { int ret; g_assert (access_control == TP_SOCKET_ACCESS_CONTROL_LOCALHOST); ret = gibber_listener_listen_tcp_loopback_af (self->priv->listener, 0, GIBBER_AF_IPV4, &error); if (!ret) { DEBUG ("Error listening on ipv4 socket: %s", error->message); g_error_free (error); return FALSE; } self->priv->socket_address = tp_g_value_slice_new ( TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV4); g_value_take_boxed (self->priv->socket_address, dbus_g_type_specialized_construct ( TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV4)); dbus_g_type_struct_set (self->priv->socket_address, 0, "127.0.0.1", 1, gibber_listener_get_port (self->priv->listener), G_MAXUINT); } else if (address_type == TP_SOCKET_ADDRESS_TYPE_IPV6) { int ret; g_assert (access_control == TP_SOCKET_ACCESS_CONTROL_LOCALHOST); ret = gibber_listener_listen_tcp_loopback_af (self->priv->listener, 0, GIBBER_AF_IPV6, &error); if (!ret) { DEBUG ("Error listening on ipv6 socket: %s", error->message); g_error_free (error); return FALSE; } self->priv->socket_address = tp_g_value_slice_new ( TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV6); g_value_take_boxed (self->priv->socket_address, dbus_g_type_specialized_construct ( TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV6)); dbus_g_type_struct_set (self->priv->socket_address, 0, "::1", 1, gibber_listener_get_port (self->priv->listener), G_MAXUINT); } else { g_assert_not_reached (); } self->priv->socket_type = address_type; gabble_signal_connect_weak (self->priv->listener, "new-connection", G_CALLBACK (new_connection_cb), G_OBJECT (self)); return TRUE; } GabbleFileTransferChannel * gabble_file_transfer_channel_new (GabbleConnection *conn, TpHandle handle, TpHandle initiator_handle, TpFileTransferState state, const gchar *content_type, const gchar *filename, guint64 size, TpFileHashType content_hash_type, const gchar *content_hash, const gchar *description, guint64 date, guint64 initial_offset, gboolean resume_supported, GabbleBytestreamIface *bytestream, #ifdef ENABLE_JINGLE_FILE_TRANSFER GTalkFileCollection *gtalk_file_collection, #else gpointer gtalk_file_collection_dummy, #endif const gchar *file_collection, const gchar *uri, const gchar *service_name, const GHashTable *metadata) { #ifndef ENABLE_JINGLE_FILE_TRANSFER g_assert (gtalk_file_collection_dummy == NULL); #endif return g_object_new (GABBLE_TYPE_FILE_TRANSFER_CHANNEL, "connection", conn, "handle", handle, "initiator-handle", initiator_handle, "requested", (initiator_handle != handle), "state", state, "content-type", content_type, "filename", filename, "size", size, "content-hash-type", content_hash_type, "content-hash", content_hash, "description", description, "date", date, "initial-offset", initial_offset, "resume-supported", resume_supported, "file-collection", file_collection, "bytestream", bytestream, #ifdef ENABLE_JINGLE_FILE_TRANSFER "gtalk-file-collection", gtalk_file_collection, #endif "uri", uri, "service-name", service_name, "metadata", metadata, NULL); } �����������������������������������������������telepathy-gabble-0.18.3/src/write-mgr-file.c��������������������������������������������������������0000664�0001750�0001750�00000027052�12332441362�021771� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * write_mgr_file.c - utility to produce gabble.manager. Part of Gabble. * Copyright (C) 2006-2010 Collabora Ltd. * Copyright (C) 2006-2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include <stdio.h> #include <string.h> #include <dbus/dbus-glib.h> #include <dbus/dbus-protocol.h> #include <telepathy-glib/telepathy-glib.h> #include "extensions/extensions.h" #include "protocol.h" #define WRITE_STR(prop, key) \ { \ const gchar *val = tp_asv_get_string (props, prop); \ g_assert (!tp_str_empty (val)); \ g_key_file_set_string (f, section_name, key, val); \ } static void write_parameters (GKeyFile *f, gchar *section_name, TpBaseProtocol *protocol) { const TpCMParamSpec *parameters = tp_base_protocol_get_parameters (protocol); const TpCMParamSpec *row; for (row = parameters; row->name; row++) { gchar *param_name = g_strdup_printf ("param-%s", row->name); gchar *param_value = g_strdup_printf ("%s%s%s%s", row->dtype, (row->flags & TP_CONN_MGR_PARAM_FLAG_REQUIRED ? " required" : ""), (row->flags & TP_CONN_MGR_PARAM_FLAG_REGISTER ? " register" : ""), (row->flags & TP_CONN_MGR_PARAM_FLAG_SECRET ? " secret" : "")); g_key_file_set_string (f, section_name, param_name, param_value); g_free (param_value); g_free (param_name); } for (row = parameters; row->name; row++) { if (row->flags & TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT) { gchar *default_name = g_strdup_printf ("default-%s", row->name); switch (row->gtype) { case G_TYPE_STRING: g_key_file_set_string (f, section_name, default_name, row->def); break; case G_TYPE_INT: case G_TYPE_UINT: g_key_file_set_integer (f, section_name, default_name, GPOINTER_TO_INT(row->def)); break; case G_TYPE_BOOLEAN: g_key_file_set_boolean (f, section_name, default_name, GPOINTER_TO_INT(row->def) ? 1 : 0); break; default: /* can't be in the case because G_TYPE_STRV is actually a * function */ if (row->gtype == G_TYPE_STRV) { g_key_file_set_string_list (f, section_name, default_name, (const gchar **) row->def, g_strv_length ((gchar **) row->def)); } } g_free (default_name); } } } static void write_rcc_property (GKeyFile *keyfile, const gchar *group_name, const gchar *key, GValue *val) { switch (G_VALUE_TYPE (val)) { case G_TYPE_BOOLEAN: { gchar *kf_key = g_strconcat (key, " " DBUS_TYPE_BOOLEAN_AS_STRING, NULL); g_key_file_set_boolean (keyfile, group_name, kf_key, g_value_get_boolean (val)); g_free (kf_key); break; } case G_TYPE_STRING: { gchar *kf_key = g_strconcat (key, " " DBUS_TYPE_STRING_AS_STRING, NULL); g_key_file_set_string (keyfile, group_name, kf_key, g_value_get_string (val)); g_free (kf_key); break; } case G_TYPE_UINT: { gchar *kf_key = g_strconcat (key, " " DBUS_TYPE_UINT32_AS_STRING, NULL); gchar *kf_val = g_strdup_printf ("%u", g_value_get_uint (val)); g_key_file_set_value (keyfile, group_name, kf_key, kf_val); g_free (kf_key); g_free (kf_val); break; } /* FIXME: when we depend on Glib 2.26, we can use * g_key_file_set_[u]int64 (g.o #614864). */ case G_TYPE_UINT64: { gchar *kf_key = g_strconcat (key, " " DBUS_TYPE_UINT64_AS_STRING, NULL); gchar *kf_val = g_strdup_printf ("%" G_GUINT64_FORMAT, g_value_get_uint64 (val)); g_key_file_set_value (keyfile, group_name, kf_key, kf_val); g_free (kf_key); g_free (kf_val); break; } case G_TYPE_INT: { gchar *kf_key = g_strconcat (key, " " DBUS_TYPE_INT32_AS_STRING, NULL); g_key_file_set_integer (keyfile, group_name, kf_key, g_value_get_int (val)); g_free (kf_key); break; } case G_TYPE_INT64: { gchar *kf_key = g_strconcat (key, " " DBUS_TYPE_UINT64_AS_STRING, NULL); gchar *kf_val = g_strdup_printf ("%" G_GINT64_FORMAT, g_value_get_int64 (val)); g_key_file_set_value (keyfile, group_name, kf_key, kf_val); g_free (kf_key); g_free (kf_val); break; } default: { if (G_VALUE_TYPE (val) == G_TYPE_STRV) { gchar **list = g_value_get_boxed (val); gchar *kf_key = g_strconcat (key, " " DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING, NULL); g_key_file_set_string_list (keyfile, group_name, kf_key, (const gchar **) list, g_strv_length (list)); g_free (kf_key); break; } /* we'd rather crash than forget to write required rcc property */ g_assert_not_reached (); } } } static gchar * generate_group_name (GHashTable *props) { static guint counter = 0; gchar *retval; gchar *chan_type = g_ascii_strdown (tp_asv_get_string (props, TP_PROP_CHANNEL_CHANNEL_TYPE), -1); gchar *chan_type_suffix; gchar *handle_type_name; guint handle_type = tp_asv_get_uint32 (props, TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, NULL); g_assert (chan_type != NULL); chan_type_suffix = strrchr (chan_type, '.'); g_assert (chan_type_suffix != NULL); chan_type_suffix++; switch (handle_type) { case TP_HANDLE_TYPE_CONTACT: handle_type_name = "-1on1"; break; case TP_HANDLE_TYPE_ROOM: handle_type_name = "-multi"; break; case TP_HANDLE_TYPE_GROUP: handle_type_name = "-group"; break; case TP_HANDLE_TYPE_LIST: handle_type_name = "-list"; break; default: handle_type_name = ""; } retval = g_strdup_printf ("%s%s-%d", chan_type_suffix, handle_type_name, ++counter); g_free (chan_type); return retval; } static void write_rccs (GKeyFile *f, const gchar *section_name, GHashTable *props) { GPtrArray *rcc_list = tp_asv_get_boxed (props, TP_PROP_PROTOCOL_REQUESTABLE_CHANNEL_CLASSES, TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST); guint i; gchar **group_names = g_new0 (gchar *, rcc_list->len + 1); for (i = 0; i < rcc_list->len; i++) { gchar **allowed; gchar *group_name; GHashTable *fixed; GHashTableIter iter; gpointer k, v; tp_value_array_unpack (g_ptr_array_index (rcc_list, i), 2, &fixed, &allowed); group_name = generate_group_name (fixed); g_hash_table_iter_init (&iter, fixed); while (g_hash_table_iter_next (&iter, &k, &v)) { const gchar *key = k; GValue *val = v; write_rcc_property (f, group_name, key, val); } /* takes ownership */ group_names[i] = group_name; g_key_file_set_string_list (f, group_name, "allowed", (const gchar **) allowed, g_strv_length (allowed)); } g_key_file_set_string_list (f, section_name, "RequestableChannelClasses", (const gchar **) group_names, rcc_list->len); g_strfreev (group_names); } static gchar * mgr_file_contents (const char *busname, const char *objpath, GSList *protocols, GError **error) { GKeyFile *f = g_key_file_new (); gchar *file_data; g_key_file_set_string (f, "ConnectionManager", "BusName", busname); g_key_file_set_string (f, "ConnectionManager", "ObjectPath", objpath); /* there are no CM interfaces defined yet, so we cheat */ g_key_file_set_string (f, "ConnectionManager", "Interfaces", ""); while (protocols != NULL) { GabbleJabberProtocol *protocol = protocols->data; gchar *section_name; GHashTable *props; const gchar * const *ifaces; const gchar * const *c_ifaces; const gchar * const *addr_vcard_fields; const gchar * const *addr_uri_schemes; const gchar * const *auth_types; g_object_get (G_OBJECT (protocol), "immutable-properties", &props, NULL); section_name = g_strdup_printf ("Protocol %s", tp_base_protocol_get_name (TP_BASE_PROTOCOL (protocol))); ifaces = tp_asv_get_strv (props, TP_PROP_PROTOCOL_INTERFACES); c_ifaces = tp_asv_get_strv (props, TP_PROP_PROTOCOL_CONNECTION_INTERFACES); auth_types = tp_asv_get_strv (props, TP_PROP_PROTOCOL_AUTHENTICATION_TYPES); addr_vcard_fields = tp_asv_get_strv (props, TP_PROP_PROTOCOL_INTERFACE_ADDRESSING_ADDRESSABLE_VCARD_FIELDS); addr_uri_schemes = tp_asv_get_strv (props, TP_PROP_PROTOCOL_INTERFACE_ADDRESSING_ADDRESSABLE_URI_SCHEMES); write_parameters (f, section_name, TP_BASE_PROTOCOL (protocol)); write_rccs (f, section_name, props); g_key_file_set_string_list (f, section_name, "Interfaces", ifaces, g_strv_length ((gchar **) ifaces)); g_key_file_set_string_list (f, section_name, "ConnectionInterfaces", c_ifaces, g_strv_length ((gchar **) c_ifaces)); g_key_file_set_string_list (f, section_name, "AuthenticationTypes", auth_types, g_strv_length ((gchar **) auth_types)); g_key_file_set_string_list (f, section_name, "AddressableVCardFields", addr_vcard_fields, g_strv_length ((gchar **) addr_vcard_fields)); g_key_file_set_string_list (f, section_name, "AddressableURISchemes", addr_uri_schemes, g_strv_length ((gchar **) addr_uri_schemes)); WRITE_STR (TP_PROP_PROTOCOL_VCARD_FIELD, "VCardField"); WRITE_STR (TP_PROP_PROTOCOL_ENGLISH_NAME, "EnglishName"); WRITE_STR (TP_PROP_PROTOCOL_ICON, "Icon"); g_free (section_name); g_hash_table_unref (props); protocols = protocols->next; } file_data = g_key_file_to_data (f, NULL, error); g_key_file_free (f); return file_data; } int main (void) { GError *error = NULL; gchar *s; GSList *protocols = NULL; g_type_init (); dbus_g_type_specialized_init (); protocols = g_slist_prepend (protocols, gabble_jabber_protocol_new ()); s = mgr_file_contents (TP_CM_BUS_NAME_BASE "gabble", TP_CM_OBJECT_PATH_BASE "gabble", protocols, &error); g_object_unref (protocols->data); g_slist_free (protocols); if (!s) { fprintf (stderr, "%s", error->message); g_error_free (error); return 1; } printf ("%s", s); g_free (s); return 0; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/conn-olpc.c�������������������������������������������������������������0000664�0001750�0001750�00000257370�12332440117�021034� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * conn-olpc.c - Gabble OLPC BuddyInfo and ActivityProperties interfaces * Copyright (C) 2007 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "conn-olpc.h" #include <string.h> #include <stdlib.h> #include <telepathy-glib/telepathy-glib.h> #define DEBUG_FLAG GABBLE_DEBUG_OLPC #include <gabble/error.h> #include "debug.h" #include "connection.h" #include "muc-channel.h" #include "presence-cache.h" #include "namespaces.h" #include "disco.h" #include "util.h" #include "olpc-activity.h" /* FIXME: At some point we should audit this code to check which assumptions * it does about buddy and activity and if they are still relevant. * For example, we currently allow the creation of activity objects which * don't have an ID. I'm not sure that really make sense. * Or at some place in the code, we allow user to change the ID of an existing * activity object which is probably bong too. */ static gboolean update_activities_properties (GabbleConnection *conn, const gchar *contact, WockyStanza *msg); /* * This function performs a depth-first search on @node to find any element * named @name in namespace @ns. This is usually not what you want because you * don't want a depth-first search of the entire hierarchy: you know at what * level of nesting you expect to find an element. Using this function rather * than wocky_node_get_child_ns() a couple of times opens you up to accepting * wildly misconstructed stanzas. Please think of the kittens. */ static WockyNode * search_for_child ( WockyNode *node, const gchar *name, const gchar *ns) { WockyNode *found, *child; WockyNodeIter i; found = wocky_node_get_child_ns (node, name, ns); if (found != NULL) return found; wocky_node_iter_init (&i, node, NULL, NULL); while (wocky_node_iter_next (&i, &child)) { found = search_for_child (child, name, ns); if (found != NULL) return found; } return NULL; } /* Returns TRUE if it actually contributed something, else FALSE. */ static gboolean activity_info_contribute_properties (GabbleOlpcActivity *activity, WockyNode *parent, gboolean only_public) { WockyNode *props_node; if (activity->id == NULL || activity->properties == NULL) return FALSE; if (only_public && !gabble_olpc_activity_is_visible (activity)) return FALSE; props_node = wocky_node_add_child_ns (parent, "properties", NS_OLPC_ACTIVITY_PROPS); wocky_node_set_attributes (props_node, "room", gabble_olpc_activity_get_room (activity), "activity", activity->id, NULL); lm_message_node_add_children_from_properties (props_node, activity->properties, "property"); return TRUE; } static void decrement_contacts_activities_set_foreach (TpHandleSet *set, TpHandle handle, gpointer data) { GabbleConnection *conn = data; GabbleOlpcActivity *activity = g_hash_table_lookup ( conn->olpc_activities_info, GUINT_TO_POINTER (handle)); g_object_unref (activity); } /* context may be NULL. */ static gboolean check_pep (GabbleConnection *conn, DBusGMethodInvocation *context) { if (!(conn->features & GABBLE_CONNECTION_FEATURES_PEP)) { GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR, "Server does not support PEP" }; DEBUG ("%s", error.message); if (context != NULL) dbus_g_method_return_error (context, &error); return FALSE; } return TRUE; } static const gchar * inspect_handle (TpBaseConnection *base, DBusGMethodInvocation *context, guint handle, TpHandleRepoIface *handle_repo) { GError *error = NULL; if (!tp_handle_is_valid (handle_repo, handle, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); return NULL; } return tp_handle_inspect (handle_repo, handle); } static const gchar * inspect_contact (TpBaseConnection *base, DBusGMethodInvocation *context, guint contact) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( base, TP_HANDLE_TYPE_CONTACT); return inspect_handle (base, context, contact, contact_repo); } static const gchar * inspect_room (TpBaseConnection *base, DBusGMethodInvocation *context, guint room) { TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( base, TP_HANDLE_TYPE_ROOM); return inspect_handle (base, context, room, room_repo); } /* context may be NULL, since this may be called in response to becoming * connected. */ static gboolean check_publish_reply_msg (WockyStanza *reply_msg, DBusGMethodInvocation *context) { GError *error = NULL; if (wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL)) { GError *tp_error = NULL; gabble_set_tp_error_from_wocky (error, &tp_error); g_prefix_error (&tp_error, "Failed to publish to the PEP node: "); DEBUG ("%s", tp_error->message); if (context != NULL) dbus_g_method_return_error (context, tp_error); g_error_free (tp_error); g_error_free (error); return FALSE; } else { return TRUE; } } static gboolean check_query_reply_msg (WockyStanza *reply_msg, DBusGMethodInvocation *context) { GError *error = NULL; if (wocky_stanza_extract_errors (reply_msg, NULL, &error, NULL, NULL)) { GError *tp_error = NULL; gabble_set_tp_error_from_wocky (error, &tp_error); g_prefix_error (&tp_error, "Failed to query the PEP node: "); DEBUG ("%s", tp_error->message); if (context != NULL) dbus_g_method_return_error (context, tp_error); g_error_free (tp_error); g_error_free (error); return FALSE; } else { return TRUE; } } typedef struct { GabbleConnection *conn; DBusGMethodInvocation *context; } pubsub_query_ctx; static pubsub_query_ctx * pubsub_query_ctx_new (GabbleConnection *conn, DBusGMethodInvocation *context) { pubsub_query_ctx *ctx = g_slice_new (pubsub_query_ctx); ctx->conn = conn; ctx->context = context; return ctx; } static void pubsub_query_ctx_free (pubsub_query_ctx *ctx) { g_slice_free (pubsub_query_ctx, ctx); } static void get_properties_reply_cb (GObject *source, GAsyncResult *res, gpointer user_data) { pubsub_query_ctx *ctx = (pubsub_query_ctx *) user_data; WockyStanza *reply_msg; GError *error = NULL; GHashTable *properties; WockyNode *node; /* FIXME: can we just pass &node in here to get the <properties/>? */ reply_msg = wocky_pep_service_get_finish (WOCKY_PEP_SERVICE (source), res, NULL, &error); if (reply_msg == NULL) { GError err = { TP_ERROR, TP_ERROR_NETWORK_ERROR, "Failed to send property request to server" }; DEBUG ("Query failed: %s", error->message); dbus_g_method_return_error (ctx->context, &err); g_error_free (error); goto out; } if (!check_query_reply_msg (reply_msg, ctx->context)) goto out; node = search_for_child ( wocky_stanza_get_top_node (reply_msg), "properties", NULL); properties = lm_message_node_extract_properties (node, "property"); gabble_svc_olpc_buddy_info_return_from_get_properties (ctx->context, properties); g_hash_table_unref (properties); out: pubsub_query_ctx_free (ctx); if (reply_msg != NULL) g_object_unref (reply_msg); } static void olpc_buddy_info_get_properties (GabbleSvcOLPCBuddyInfo *iface, guint handle, DBusGMethodInvocation *context) { GabbleConnection *conn = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) conn; const gchar *jid; pubsub_query_ctx *ctx; WockyBareContact *contact; DEBUG ("called"); gabble_connection_ensure_capabilities (conn, gabble_capabilities_get_olpc_notify ()); if (!check_pep (conn, context)) return; jid = inspect_contact (base, context, handle); if (jid == NULL) return; ctx = pubsub_query_ctx_new (conn, context); contact = ensure_bare_contact_from_jid (conn, jid); wocky_pep_service_get_async (conn->pep_olpc_buddy_props, contact, NULL, get_properties_reply_cb, ctx); g_object_unref (contact); } /* context may be NULL. */ static void set_properties_reply_cb (GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg, GObject *object, gpointer user_data) { DBusGMethodInvocation *context = user_data; if (!check_publish_reply_msg (reply_msg, context)) return; if (context != NULL) gabble_svc_olpc_buddy_info_return_from_set_properties (context); } /* context may be NULL, in which case it will be NULL in the reply_cb. */ static void transmit_properties (GabbleConnection *conn, GHashTable *properties, DBusGMethodInvocation *context) { WockyStanza *msg; WockyNode *item, *props_node; gabble_connection_ensure_capabilities (conn, gabble_capabilities_get_olpc_notify ()); if (!check_pep (conn, context)) return; msg = wocky_pep_service_make_publish_stanza (conn->pep_olpc_buddy_props, &item); props_node = wocky_node_add_child_ns (item, "properties", NS_OLPC_BUDDY_PROPS); lm_message_node_add_children_from_properties (props_node, properties, "property"); if (!_gabble_connection_send_with_reply (conn, msg, set_properties_reply_cb, NULL, context, NULL)) { GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR, "Failed to send property change request to server" }; DEBUG ("%s", error.message); if (context != NULL) dbus_g_method_return_error (context, &error); } g_object_unref (msg); } static GQuark preload_buddy_properties_quark (void) { static GQuark q = 0; if (q == 0) { q = g_quark_from_static_string ("GabbleConnection.preload_buddy_properties_quark"); } return q; } static GQuark invitees_quark (void) { static GQuark q = 0; if (q == 0) { q = g_quark_from_static_string ("GabbleConnection.conn_olpc_invitees_quark"); } return q; } static void gabble_connection_connected_olpc (GabbleConnection *conn) { GHashTable *preload = g_object_steal_qdata ((GObject *) conn, preload_buddy_properties_quark ()); if (preload != NULL) { transmit_properties (conn, preload, NULL); g_hash_table_unref (preload); } } static void olpc_buddy_info_set_properties (GabbleSvcOLPCBuddyInfo *iface, GHashTable *properties, DBusGMethodInvocation *context) { GabbleConnection *conn = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) conn; DEBUG ("called"); if (tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_CONNECTED) { transmit_properties (conn, properties, context); } else { GHashTable *preload; GQuark preload_quark = preload_buddy_properties_quark (); DEBUG ("Not connected: will perform OLPC buddy property update later"); preload = g_object_get_qdata ((GObject *) conn, preload_quark); if (preload != NULL) { /* throw away any already-preloaded properties - SetProperties * is an overwrite, not an update */ g_hash_table_remove_all (preload); } else { preload = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) tp_g_value_slice_free); g_object_set_qdata_full ((GObject *) conn, preload_quark, preload, (GDestroyNotify) g_hash_table_unref); } tp_g_hash_table_update (preload, properties, (GBoxedCopyFunc) g_strdup, (GBoxedCopyFunc) tp_g_value_slice_dup); gabble_svc_olpc_buddy_info_return_from_set_properties (context); } } static void olpc_buddy_props_pep_node_changed (WockyPepService *pep, WockyBareContact *contact, WockyStanza *stanza, WockyNode *item, GabbleConnection *conn) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); GHashTable *properties; WockyNode *node; TpBaseConnection *base = (TpBaseConnection *) conn; TpHandle handle; const gchar *jid; jid = wocky_bare_contact_get_jid (contact); handle = tp_handle_ensure (contact_repo, jid, NULL, NULL); if (handle == 0) { DEBUG ("Invalid from: %s", jid); return; } if (handle == tp_base_connection_get_self_handle (base)) /* Ignore echoed pubsub notifications */ return; node = search_for_child ( wocky_stanza_get_top_node (stanza), "properties", NULL); properties = lm_message_node_extract_properties (node, "property"); gabble_svc_olpc_buddy_info_emit_properties_changed (conn, handle, properties); g_hash_table_unref (properties); } static void get_activity_properties_reply_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GabbleConnection *conn = GABBLE_CONNECTION (user_data); const gchar *from; WockyStanza *reply_msg; GError *error = NULL; reply_msg = wocky_pep_service_get_finish (WOCKY_PEP_SERVICE (source), res, NULL, &error); if (reply_msg == NULL) { DEBUG ("Failed to send activity properties request to server: %s", error->message); g_error_free (error); return; } from = wocky_node_get_attribute ( wocky_stanza_get_top_node (reply_msg), "from"); update_activities_properties (conn, from, reply_msg); g_object_unref (reply_msg); } static gboolean remove_activity (gpointer key, gpointer value, gpointer activity) { return activity == value; } static void activity_disposed_cb (gpointer _conn, GObject *activity) { GabbleConnection *conn = GABBLE_CONNECTION (_conn); if (conn->olpc_activities_info == NULL) /* We are disposing */ return; g_hash_table_foreach_remove (conn->olpc_activities_info, remove_activity, activity); } static GabbleOlpcActivity * add_activity_info (GabbleConnection *conn, TpHandle handle) { GabbleOlpcActivity *activity; activity = gabble_olpc_activity_new (conn, handle); g_hash_table_insert (conn->olpc_activities_info, GUINT_TO_POINTER (handle), activity); g_object_weak_ref (G_OBJECT (activity), activity_disposed_cb, conn); return activity; } static GPtrArray * get_buddy_activities (GabbleConnection *conn, TpHandle buddy) { TpIntset *all; gboolean free_all = FALSE; GPtrArray *activities = g_ptr_array_new (); TpHandleSet *invited_activities, *pep_activities; invited_activities = g_hash_table_lookup (conn->olpc_invited_activities, GUINT_TO_POINTER (buddy)); pep_activities = g_hash_table_lookup (conn->olpc_pep_activities, GUINT_TO_POINTER (buddy)); if (invited_activities == NULL) { if (pep_activities == NULL) { all = NULL; } else { all = tp_handle_set_peek (pep_activities); } } else { if (pep_activities == NULL) { all = tp_handle_set_peek (invited_activities); } else { all = tp_intset_union (tp_handle_set_peek (invited_activities), tp_handle_set_peek (pep_activities)); free_all = TRUE; } } if (all != NULL) { TpIntsetFastIter iter; guint element; tp_intset_fast_iter_init (&iter, all); while (tp_intset_fast_iter_next (&iter, &element)) { GabbleOlpcActivity *activity = g_hash_table_lookup ( conn->olpc_activities_info, GUINT_TO_POINTER (element)); GValue gvalue = { 0 }; g_assert (activity != NULL); if (activity->id == NULL) { DEBUG ("... activity #%u has no ID, skipping", element); continue; } g_value_init (&gvalue, GABBLE_STRUCT_TYPE_ACTIVITY); g_value_take_boxed (&gvalue, dbus_g_type_specialized_construct (GABBLE_STRUCT_TYPE_ACTIVITY)); dbus_g_type_struct_set (&gvalue, 0, activity->id, 1, activity->room, G_MAXUINT); DEBUG ("... activity #%u (ID %s)", activity->room, activity->id); g_ptr_array_add (activities, g_value_get_boxed (&gvalue)); } } if (free_all) tp_intset_destroy (all); return activities; } static void extract_activities (GabbleConnection *conn, WockyStanza *msg, TpHandle sender) { WockyNode *activities_node; TpHandleSet *activities_set, *old_activities; TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_ROOM); WockyNodeIter i; activities_node = search_for_child ( wocky_stanza_get_top_node (msg), "activities", NULL); activities_set = tp_handle_set_new (room_repo); if (activities_node != NULL) { WockyNode *node; wocky_node_iter_init (&i, activities_node, "activity", NULL); while (wocky_node_iter_next (&i, &node)) { const gchar *act_id; const gchar *room; GabbleOlpcActivity *activity; TpHandle room_handle; act_id = wocky_node_get_attribute (node, "type"); if (act_id == NULL) { NODE_DEBUG (node, "No activity ID, skipping"); continue; } room = wocky_node_get_attribute (node, "room"); if (room == NULL) { NODE_DEBUG (node, "No room name, skipping"); continue; } room_handle = tp_handle_ensure (room_repo, room, NULL, NULL); if (room_handle == 0) { DEBUG ("Invalid room name <%s>, skipping", room); continue; } activity = g_hash_table_lookup (conn->olpc_activities_info, GUINT_TO_POINTER (room_handle)); if (activity == NULL) { activity = add_activity_info (conn, room_handle); g_assert (!tp_handle_set_is_member (activities_set, room_handle)); } else { if (tp_handle_set_is_member (activities_set, room_handle)) { NODE_DEBUG (node, "Room advertised twice, skipping"); continue; } g_object_ref (activity); DEBUG ("ref: %s (%d) refcount: %d\n", gabble_olpc_activity_get_room (activity), activity->room, G_OBJECT (activity)->ref_count); } /* pass ownership to the activities_set */ tp_handle_set_add (activities_set, room_handle); if (tp_strdiff (activity->id, act_id)) { DEBUG ("Assigning new ID <%s> to room #%u <%s>", act_id, room_handle, room); g_object_set (activity, "id", act_id, NULL); } } } old_activities = g_hash_table_lookup (conn->olpc_pep_activities, GUINT_TO_POINTER (sender)); if (old_activities != NULL) { /* We decrement the refcount (and free if needed) all the * activities previously announced by this contact. */ tp_handle_set_foreach (old_activities, decrement_contacts_activities_set_foreach, conn); } /* Update the list of activities associated with this contact. */ g_hash_table_insert (conn->olpc_pep_activities, GUINT_TO_POINTER (sender), activities_set); } static void free_activities (GPtrArray *activities) { guint i; for (i = 0; i < activities->len; i++) g_boxed_free (GABBLE_STRUCT_TYPE_ACTIVITY, activities->pdata[i]); g_ptr_array_unref (activities); } static void check_activity_properties (GabbleConnection *conn, GPtrArray *activities, const gchar *from) { /* XXX: dirty hack! * We use PEP instead of pubsub until we have MEP. * When we request activities from a remote contact we need to check * if we already "know" his activities (we have its properties). * If not, we need to explicitely ask to the user to send them to us. * When we'll have MEP we will be able to request activities * propreties from muc's pubsub node and so avoid all this crack. */ gboolean query_needed = FALSE; guint i; for (i = 0; i < activities->len && !query_needed; i++) { GValue pair = {0,}; guint channel; GabbleOlpcActivity *activity; g_value_init (&pair, GABBLE_STRUCT_TYPE_ACTIVITY); g_value_set_static_boxed (&pair, g_ptr_array_index (activities, i)); dbus_g_type_struct_get (&pair, 1, &channel, G_MAXUINT); activity = g_hash_table_lookup (conn->olpc_activities_info, GUINT_TO_POINTER (channel)); if (activity == NULL || activity->properties == NULL) { query_needed = TRUE; } } if (query_needed) { WockyBareContact *contact = ensure_bare_contact_from_jid (conn, from); wocky_pep_service_get_async (conn->pep_olpc_act_props, contact, NULL, get_activity_properties_reply_cb, conn); g_object_unref (contact); } } static void get_activities_reply_cb (GObject *source, GAsyncResult *res, gpointer user_data) { pubsub_query_ctx *ctx = (pubsub_query_ctx *) user_data; WockyStanza *reply_msg; GError *err = NULL; GPtrArray *activities; const gchar *from; TpHandle from_handle; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) ctx->conn, TP_HANDLE_TYPE_CONTACT); GError *stanza_error = NULL; reply_msg = wocky_pep_service_get_finish (WOCKY_PEP_SERVICE (source), res, NULL, &err); if (reply_msg == NULL) { GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR, "Failed to send property request to server" }; DEBUG ("Query failed: %s", err->message); dbus_g_method_return_error (ctx->context, &error); g_error_free (err); goto out; } from = wocky_node_get_attribute ( wocky_stanza_get_top_node (reply_msg), "from"); if (from == NULL) { GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR, "Error in pubsub reply: no sender" }; dbus_g_method_return_error (ctx->context, &error); goto out; } from_handle = tp_handle_lookup (contact_repo, from, NULL, NULL); if (from_handle == 0) { GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR, "Error in pubsub reply: unknown sender" }; dbus_g_method_return_error (ctx->context, &error); goto out; } if (wocky_stanza_extract_errors (reply_msg, NULL, &stanza_error, NULL, NULL)) { GError *tp_error = NULL; gabble_set_tp_error_from_wocky (stanza_error, &tp_error); g_prefix_error (&tp_error, "Error in pubsub reply: "); dbus_g_method_return_error (ctx->context, tp_error); g_clear_error (&tp_error); g_clear_error (&stanza_error); goto out; } extract_activities (ctx->conn, reply_msg, from_handle); activities = get_buddy_activities (ctx->conn, from_handle); /* FIXME: race between client and PEP */ check_activity_properties (ctx->conn, activities, from); gabble_svc_olpc_buddy_info_return_from_get_activities (ctx->context, activities); free_activities (activities); out: pubsub_query_ctx_free (ctx); if (reply_msg != NULL) g_object_unref (reply_msg); } static void olpc_buddy_info_get_activities (GabbleSvcOLPCBuddyInfo *iface, guint handle, DBusGMethodInvocation *context) { GabbleConnection *conn = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) conn; const gchar *jid; pubsub_query_ctx *ctx; WockyBareContact *contact; DEBUG ("called"); gabble_connection_ensure_capabilities (conn, gabble_capabilities_get_olpc_notify ()); if (!check_pep (conn, context)) return; jid = inspect_contact (base, context, handle); if (jid == NULL) return; ctx = pubsub_query_ctx_new (conn, context); contact = ensure_bare_contact_from_jid (conn, jid); wocky_pep_service_get_async (conn->pep_olpc_activities, contact, NULL, get_activities_reply_cb, ctx); g_object_unref (contact); } /* FIXME: API could be improved */ static gboolean upload_activities_pep (GabbleConnection *conn, GabbleConnectionMsgReplyFunc callback, gpointer user_data, GError **error) { TpBaseConnection *base = (TpBaseConnection *) conn; WockyNode *item, *activities; WockyStanza *msg; TpHandleSet *my_activities = g_hash_table_lookup (conn->olpc_pep_activities, GUINT_TO_POINTER (tp_base_connection_get_self_handle (base))); GError *e = NULL; gboolean ret; msg = wocky_pep_service_make_publish_stanza (conn->pep_olpc_activities, &item); activities = wocky_node_add_child_ns (item, "activities", NS_OLPC_ACTIVITIES); if (my_activities != NULL) { TpIntsetFastIter iter; guint element; tp_intset_fast_iter_init (&iter, tp_handle_set_peek (my_activities)); while (tp_intset_fast_iter_next (&iter, &element)) { GabbleOlpcActivity *activity = g_hash_table_lookup ( conn->olpc_activities_info, GUINT_TO_POINTER (element)); WockyNode *activity_node; g_assert (activity != NULL); if (!gabble_olpc_activity_is_visible (activity)) continue; activity_node = wocky_node_add_child_with_content (activities, "activity", ""); wocky_node_set_attributes (activity_node, "type", activity->id, "room", gabble_olpc_activity_get_room (activity), NULL); } } ret = _gabble_connection_send_with_reply (conn, msg, callback, NULL, user_data, &e); if (!ret) { g_set_error (error, TP_ERROR, TP_ERROR_NETWORK_ERROR, "Failed to send property change request to server: %s", e->message); g_error_free (e); } g_object_unref (msg); return ret; } static void set_activities_reply_cb (GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg, GObject *object, gpointer user_data) { DBusGMethodInvocation *context = user_data; if (!check_publish_reply_msg (reply_msg, context)) return; /* FIXME: emit ActivitiesChanged? */ gabble_svc_olpc_buddy_info_return_from_set_activities (context); } static gboolean add_activity (GabbleConnection *self, const gchar *id, guint channel, GError **error) { TpBaseConnection *base = (TpBaseConnection *) self; TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( base, TP_HANDLE_TYPE_ROOM); TpHandleSet *old_activities = g_hash_table_lookup (self->olpc_pep_activities, GUINT_TO_POINTER (tp_base_connection_get_self_handle (base))); GabbleOlpcActivity *activity; if (!tp_handle_is_valid (room_repo, channel, error)) { DEBUG ("Invalid room handle %d", channel); return FALSE; } if (old_activities != NULL && tp_handle_set_is_member (old_activities, channel)) { *error = g_error_new (TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Can't set twice the same activity: %s", id); DEBUG ("activity already added: %s", id); return FALSE; } activity = g_hash_table_lookup (self->olpc_activities_info, GUINT_TO_POINTER (channel)); if (activity == NULL) { activity = add_activity_info (self, channel); } g_object_ref (activity); DEBUG ("ref: %s (%d) refcount: %d\n", gabble_olpc_activity_get_room (activity), activity->room, G_OBJECT (activity)->ref_count); g_object_set (activity, "id", id, NULL); return TRUE; } static void olpc_buddy_info_set_activities (GabbleSvcOLPCBuddyInfo *iface, const GPtrArray *activities, DBusGMethodInvocation *context) { GabbleConnection *conn = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) conn; TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( base, TP_HANDLE_TYPE_ROOM); guint i; TpHandleSet *activities_set, *old_activities; DEBUG ("called"); gabble_connection_ensure_capabilities (conn, gabble_capabilities_get_olpc_notify ()); if (!check_pep (conn, context)) return; activities_set = tp_handle_set_new (room_repo); for (i = 0; i < activities->len; i++) { GValue pair = {0,}; gchar *id; guint channel; const gchar *room = NULL; GabbleOlpcActivity *activity; GError *error = NULL; g_value_init (&pair, GABBLE_STRUCT_TYPE_ACTIVITY); g_value_set_static_boxed (&pair, g_ptr_array_index (activities, i)); dbus_g_type_struct_get (&pair, 0, &id, 1, &channel, G_MAXUINT); if (!tp_handle_is_valid (room_repo, channel, &error)) { DEBUG ("Invalid room handle"); dbus_g_method_return_error (context, error); /* We have to unref information previously * refed in this loop */ tp_handle_set_foreach (activities_set, decrement_contacts_activities_set_foreach, conn); /* set_activities failed so we don't unref old activities * of the local user */ tp_handle_set_destroy (activities_set); g_error_free (error); g_free (id); return; } room = tp_handle_inspect (room_repo, channel); activity = g_hash_table_lookup (conn->olpc_activities_info, GUINT_TO_POINTER (channel)); if (activity == NULL) { activity = add_activity_info (conn, channel); } else { if (tp_handle_set_is_member (activities_set, channel)) { error = g_error_new (TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Can't set twice the same activity: %s", room); DEBUG ("activity already added: %s", room); dbus_g_method_return_error (context, error); /* We have to unref information previously * refed in this loop */ tp_handle_set_foreach (activities_set, decrement_contacts_activities_set_foreach, conn); /* set_activities failed so we don't unref old activities * of the local user */ tp_handle_set_destroy (activities_set); g_error_free (error); g_free (activity); g_free (id); return; } g_object_ref (activity); DEBUG ("ref: %s (%d) refcount: %d\n", gabble_olpc_activity_get_room (activity), activity->room, G_OBJECT (activity)->ref_count); } g_object_set (activity, "id", id, NULL); g_free (id); tp_handle_set_add (activities_set, channel); } old_activities = g_hash_table_lookup (conn->olpc_pep_activities, GUINT_TO_POINTER (tp_base_connection_get_self_handle (base))); if (old_activities != NULL) { /* We decrement the refcount (and free if needed) all the * activities previously announced by our own contact. */ tp_handle_set_foreach (old_activities, decrement_contacts_activities_set_foreach, conn); } /* Update the list of activities associated with our own contact. */ g_hash_table_insert (conn->olpc_pep_activities, GUINT_TO_POINTER (tp_base_connection_get_self_handle (base)), activities_set); if (!upload_activities_pep (conn, set_activities_reply_cb, context, NULL)) { GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR, "Failed to send property request to server" }; dbus_g_method_return_error (context, &error); } /* FIXME: what if we were advertising properties for things that * we've declared are no longer in our activities list? Strictly speaking * we should probably re-upload our activity properties PEP if that's * the case */ } static void olpc_activities_pep_node_changed (WockyPepService *pep, WockyBareContact *contact, WockyStanza *stanza, WockyNode *item, GabbleConnection *conn) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); GPtrArray *activities; TpBaseConnection *base = (TpBaseConnection *) conn; TpHandle handle; const gchar *jid; jid = wocky_bare_contact_get_jid (contact); handle = tp_handle_ensure (contact_repo, jid, NULL, NULL); if (handle == 0) { DEBUG ("Invalid from: %s", jid); return; } if (handle != tp_base_connection_get_self_handle (base)) extract_activities (conn, stanza, handle); activities = get_buddy_activities (conn, handle); gabble_svc_olpc_buddy_info_emit_activities_changed (conn, handle, activities); free_activities (activities); } static GabbleOlpcActivity * add_activity_info_in_set (GabbleConnection *conn, TpHandle room_handle, const gchar *from, GHashTable *table) { GabbleOlpcActivity *activity; TpHandle from_handle; TpHandleSet *activities_set; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_ROOM); from_handle = tp_handle_lookup (contact_repo, from, NULL, NULL); if (from_handle == 0) { DEBUG ("unknown sender"); return NULL; } activity = add_activity_info (conn, room_handle); /* Add activity information in the list of the contact */ activities_set = g_hash_table_lookup (table, GUINT_TO_POINTER ( from_handle)); if (activities_set == NULL) { activities_set = tp_handle_set_new (room_repo); g_hash_table_insert (table, GUINT_TO_POINTER (from_handle), activities_set); } /* add_activity_info_in_set isn't meant to be called if the * activity already existed */ g_assert (!tp_handle_set_is_member (activities_set, room_handle)); /* the set owns the ref of the newly created activity */ tp_handle_set_add (activities_set, room_handle); return activity; } static GabbleOlpcActivity * extract_current_activity (GabbleConnection *conn, WockyNode *node, const gchar *contact, gboolean create_activity) { const gchar *room, *id; GabbleOlpcActivity *activity; TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_ROOM); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); TpHandle room_handle, contact_handle; if (node == NULL) return NULL; /* For some weird reasons, the PEP protocol use "type" for the activity ID. * We can't change that without breaking compatibility but if there is no * "type" attribute then we can use the "id" one. */ id = wocky_node_get_attribute (node, "type"); if (id == NULL) { id = wocky_node_get_attribute (node, "id"); } room = wocky_node_get_attribute (node, "room"); if (room == NULL || room[0] == '\0') return NULL; room_handle = tp_handle_ensure (room_repo, room, NULL, NULL); if (room_handle == 0) return NULL; contact_handle = tp_handle_lookup (contact_repo, contact, NULL, NULL); if (contact_handle == 0) return NULL; activity = g_hash_table_lookup (conn->olpc_activities_info, GUINT_TO_POINTER (room_handle)); if (activity == NULL && create_activity) { /* Humm we received as current activity an activity we don't know yet. * If the remote user doesn't announce this activity * in his next activities list, information about * it will be freed */ DEBUG ("unknown current activity %s", room); activity = add_activity_info_in_set (conn, room_handle, contact, conn->olpc_pep_activities); } /* update current-activity cache */ if (activity != NULL) { g_object_set (activity, "id", id, NULL); g_hash_table_insert (conn->olpc_current_act, GUINT_TO_POINTER (contact_handle), g_object_ref (activity)); } else { g_hash_table_remove (conn->olpc_current_act, GUINT_TO_POINTER (contact_handle)); } return activity; } static void get_current_activity_reply_cb (GObject *source, GAsyncResult *res, gpointer user_data) { pubsub_query_ctx *ctx = (pubsub_query_ctx *) user_data; WockyStanza *reply_msg; GError *error = NULL; WockyNode *node; const gchar *from; GabbleOlpcActivity *activity; reply_msg = wocky_pep_service_get_finish (WOCKY_PEP_SERVICE (source), res, NULL, &error); if (reply_msg == NULL) { GError err = { TP_ERROR, TP_ERROR_NETWORK_ERROR, "Failed to send property request to server" }; DEBUG ("Query failed: %s", error->message); dbus_g_method_return_error (ctx->context, &err); g_error_free (error); goto out; } if (wocky_stanza_extract_errors (reply_msg, NULL, NULL, NULL, NULL)) { DEBUG ("Failed to query PEP node. No current activity"); gabble_svc_olpc_buddy_info_return_from_get_current_activity (ctx->context, "", 0); goto out; } from = wocky_node_get_attribute ( wocky_stanza_get_top_node (reply_msg), "from"); node = search_for_child ( wocky_stanza_get_top_node (reply_msg), "activity", NULL); activity = extract_current_activity (ctx->conn, node, from, TRUE); if (activity == NULL) { DEBUG ("GetCurrentActivity returns no activity"); gabble_svc_olpc_buddy_info_return_from_get_current_activity (ctx->context, "", 0); } else { DEBUG ("GetCurrentActivity returns (\"%s\", room#%u)", activity->id, activity->room); gabble_svc_olpc_buddy_info_return_from_get_current_activity (ctx->context, activity->id, activity->room); } out: pubsub_query_ctx_free (ctx); if (reply_msg != NULL) g_object_unref (reply_msg); } static void olpc_buddy_info_get_current_activity (GabbleSvcOLPCBuddyInfo *iface, guint handle, DBusGMethodInvocation *context) { GabbleConnection *conn = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) conn; const gchar *jid; GabbleOlpcActivity *activity; pubsub_query_ctx *ctx; WockyBareContact *contact; DEBUG ("called for contact#%u", handle); gabble_connection_ensure_capabilities (conn, gabble_capabilities_get_olpc_notify ()); if (!check_pep (conn, context)) return; jid = inspect_contact (base, context, handle); if (jid == NULL) return; activity = g_hash_table_lookup (conn->olpc_current_act, GUINT_TO_POINTER (handle)); if (activity != NULL) { DEBUG ("found current activity in cache: %s (%u)", activity->id, activity->room); gabble_svc_olpc_buddy_info_return_from_get_current_activity (context, activity->id, activity->room); return; } DEBUG ("current activity not in cache, query PEP node"); ctx = pubsub_query_ctx_new (conn, context); contact = ensure_bare_contact_from_jid (conn, jid); wocky_pep_service_get_async (conn->pep_olpc_current_act, contact, NULL, get_current_activity_reply_cb, ctx); g_object_unref (contact); } static void set_current_activity_reply_cb (GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg, GObject *object, gpointer user_data) { DBusGMethodInvocation *context = user_data; if (!check_publish_reply_msg (reply_msg, context)) return; gabble_svc_olpc_buddy_info_return_from_set_current_activity (context); } /* Check if this activity is in our own activities list */ static gboolean activity_in_own_set (GabbleConnection *conn, const gchar *room) { TpBaseConnection *base = (TpBaseConnection *) conn; TpHandleSet *activities_set; TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_ROOM); TpHandle room_handle; room_handle = tp_handle_lookup (room_repo, room, NULL, NULL); if (room_handle == 0) /* If activity's information was in the list, we would * have found the handle as Activity keep a ref on it */ return FALSE; activities_set = g_hash_table_lookup (conn->olpc_pep_activities, GUINT_TO_POINTER (tp_base_connection_get_self_handle (base))); if (activities_set == NULL || !tp_handle_set_is_member (activities_set, room_handle)) return FALSE; return TRUE; } static void olpc_buddy_info_set_current_activity (GabbleSvcOLPCBuddyInfo *iface, const gchar *activity, guint channel, DBusGMethodInvocation *context) { GabbleConnection *conn = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) conn; WockyStanza *msg; WockyNode *item, *publish; const gchar *room = ""; DEBUG ("called"); gabble_connection_ensure_capabilities (conn, gabble_capabilities_get_olpc_notify ()); if (!check_pep (conn, context)) return; /* if activity == "" there is no current activity */ if (activity[0] != '\0') { room = inspect_room (base, context, channel); if (room == NULL) return; if (!activity_in_own_set (conn, room)) { GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Can't set an activity as current if you're not announcing it" }; dbus_g_method_return_error (context, &error); return; } } msg = wocky_pep_service_make_publish_stanza (conn->pep_olpc_current_act, &item); publish = wocky_node_add_child_ns (item, "activity", NS_OLPC_CURRENT_ACTIVITY); wocky_node_set_attributes (publish, "type", activity, "room", room, NULL); if (!_gabble_connection_send_with_reply (conn, msg, set_current_activity_reply_cb, NULL, context, NULL)) { GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR, "Failed to send property change request to server" }; dbus_g_method_return_error (context, &error); } g_object_unref (msg); } static void olpc_current_act_pep_node_changed (WockyPepService *pep, WockyBareContact *contact, WockyStanza *stanza, WockyNode *item, GabbleConnection *conn) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); TpBaseConnection *base = (TpBaseConnection *) conn; WockyNode *node; GabbleOlpcActivity *activity; TpHandle handle; const gchar *jid; jid = wocky_bare_contact_get_jid (contact); handle = tp_handle_ensure (contact_repo, jid, NULL, NULL); if (handle == 0) { DEBUG ("Invalid from: %s", jid); return; } if (handle == tp_base_connection_get_self_handle (base)) /* Ignore echoed pubsub notifications */ return; node = search_for_child (wocky_stanza_get_top_node (stanza), "activity", NULL); activity = extract_current_activity (conn, node, jid, TRUE); if (activity != NULL) { DEBUG ("emitting CurrentActivityChanged(contact#%u, ID \"%s\", room#%u)", handle, activity->id, activity->room); gabble_svc_olpc_buddy_info_emit_current_activity_changed (conn, handle, activity->id, activity->room); } else { DEBUG ("emitting CurrentActivityChanged(contact#%u, \"\", 0)", handle); gabble_svc_olpc_buddy_info_emit_current_activity_changed (conn, handle, "", 0); } } static void add_activity_reply_cb (GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg, GObject *object, gpointer user_data) { DBusGMethodInvocation *context = user_data; if (!check_publish_reply_msg (reply_msg, context)) return; /* FIXME: emit ActivitiesChanged? */ gabble_svc_olpc_buddy_info_return_from_add_activity (context); } static void olpc_buddy_info_add_activity (GabbleSvcOLPCBuddyInfo *iface, const gchar *id, guint channel, DBusGMethodInvocation *context) { GabbleConnection *self = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) self; TpHandleSet *activities_set = g_hash_table_lookup (self->olpc_pep_activities, GUINT_TO_POINTER (tp_base_connection_get_self_handle (base))); TpHandleRepoIface *room_repo = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_ROOM); GError *error = NULL; gabble_connection_ensure_capabilities (self, gabble_capabilities_get_olpc_notify ()); if (!check_pep (self, context)) return; if (!add_activity (self, id, channel, &error)) { dbus_g_method_return_error (context, error); return; } if (activities_set == NULL) { activities_set = tp_handle_set_new (room_repo); g_hash_table_insert (self->olpc_pep_activities, GUINT_TO_POINTER (tp_base_connection_get_self_handle (base)), activities_set); } tp_handle_set_add (activities_set, channel); if (!upload_activities_pep (self, add_activity_reply_cb, context, NULL)) { error = g_error_new (TP_ERROR, TP_ERROR_NETWORK_ERROR, "Failed to send property request to server"); dbus_g_method_return_error (context, error); } } void olpc_buddy_info_iface_init (gpointer g_iface, gpointer iface_data) { GabbleSvcOLPCBuddyInfoClass *klass = g_iface; #define IMPLEMENT(x) gabble_svc_olpc_buddy_info_implement_##x (\ klass, olpc_buddy_info_##x) IMPLEMENT(get_activities); IMPLEMENT(set_activities); IMPLEMENT(get_properties); IMPLEMENT(set_properties); IMPLEMENT(get_current_activity); IMPLEMENT(set_current_activity); IMPLEMENT(add_activity); #undef IMPLEMENT } /* FIXME: API could be improved */ static gboolean upload_activity_properties_pep (GabbleConnection *conn, GabbleConnectionMsgReplyFunc callback, gpointer user_data, GError **error) { TpBaseConnection *base = (TpBaseConnection *) conn; WockyNode *publish, *item; WockyStanza *msg; GError *e = NULL; gboolean ret; TpHandleSet *my_activities = g_hash_table_lookup (conn->olpc_pep_activities, GUINT_TO_POINTER (tp_base_connection_get_self_handle (base))); msg = wocky_pep_service_make_publish_stanza (conn->pep_olpc_act_props, &item); publish = wocky_node_add_child_ns (item, "activities", NS_OLPC_ACTIVITY_PROPS); if (my_activities != NULL) { TpIntsetFastIter iter; guint element; tp_intset_fast_iter_init (&iter, tp_handle_set_peek (my_activities)); while (tp_intset_fast_iter_next (&iter, &element)) { GabbleOlpcActivity *activity = g_hash_table_lookup ( conn->olpc_activities_info, GUINT_TO_POINTER (element)); activity_info_contribute_properties (activity, publish, TRUE); } } ret = _gabble_connection_send_with_reply (conn, msg, callback, NULL, user_data, &e); if (!ret) { g_set_error (error, TP_ERROR, TP_ERROR_NETWORK_ERROR, "Failed to send property change request to server: %s", e->message); g_error_free (e); } g_object_unref (msg); return ret; } typedef struct { DBusGMethodInvocation *context; gboolean visibility_changed; GabbleOlpcActivity *activity; } set_properties_ctx; static void set_activity_properties_activities_reply_cb (GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg, GObject *object, gpointer user_data) { set_properties_ctx *context = user_data; /* if the SetProperties() call was skipped, both messages are NULL */ g_assert ((sent_msg == NULL) == (reply_msg == NULL)); if (reply_msg != NULL && !check_publish_reply_msg (reply_msg, context->context)) { g_slice_free (set_properties_ctx, context); return; } gabble_svc_olpc_activity_properties_emit_activity_properties_changed ( conn, context->activity->room, context->activity->properties); gabble_svc_olpc_activity_properties_return_from_set_properties ( context->context); g_slice_free (set_properties_ctx, context); return; } static void set_activity_properties_reply_cb (GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg, GObject *object, gpointer user_data) { set_properties_ctx *context = user_data; /* if the SetProperties() call was skipped, both messages are NULL */ g_assert ((sent_msg == NULL) == (reply_msg == NULL)); if (reply_msg != NULL && !check_publish_reply_msg (reply_msg, context->context)) { g_slice_free (set_properties_ctx, context); return; } if (context->visibility_changed) { GError *err = NULL; if (!upload_activities_pep (conn, set_activity_properties_activities_reply_cb, context, &err)) { dbus_g_method_return_error (context->context, err); g_error_free (err); } } else { /* nothing to do, so just "succeed" */ set_activity_properties_activities_reply_cb (conn, NULL, NULL, NULL, context); } } static gboolean refresh_invitations (GabbleConnection *conn, GabbleMucChannel *chan, GabbleOlpcActivity *activity, GError **error) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); TpHandleSet *invitees = g_object_get_qdata ((GObject *) chan, invitees_quark ()); if (invitees != NULL && tp_handle_set_size (invitees) > 0) { TpIntsetFastIter iter; guint element; tp_intset_fast_iter_init (&iter, tp_handle_set_peek (invitees)); while (tp_intset_fast_iter_next (&iter, &element)) { const gchar *to = tp_handle_inspect (contact_repo, element); WockyStanza *msg = wocky_stanza_build ( WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, to, NULL); activity_info_contribute_properties (activity, wocky_stanza_get_top_node (msg), FALSE); if (!_gabble_connection_send (conn, msg, error)) { DEBUG ("Unable to re-send activity properties to invitee %s", to); g_object_unref (msg); return FALSE; } g_object_unref (msg); } } return TRUE; } static void olpc_activity_properties_set_properties (GabbleSvcOLPCActivityProperties *iface, guint room, GHashTable *properties, DBusGMethodInvocation *context) { GabbleConnection *conn = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) conn; WockyStanza *msg; const gchar *jid; GHashTable *properties_copied; GabbleOlpcActivity *activity; GabbleMucChannel *muc_channel; guint state; gboolean was_visible, is_visible; set_properties_ctx *ctx; GError *err = NULL; DEBUG ("called"); gabble_connection_ensure_capabilities (conn, gabble_capabilities_get_olpc_notify ()); if (!check_pep (conn, context)) return; jid = inspect_room (base, context, room); if (jid == NULL) return; if (!activity_in_own_set (conn, jid)) { GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Can't set properties on an activity if you're not announcing it" }; dbus_g_method_return_error (context, &error); return; } muc_channel = gabble_muc_factory_find_text_channel (conn->muc_factory, room); if (muc_channel != NULL) { g_object_get (muc_channel, "state", &state, NULL); } if (muc_channel == NULL || state != MUC_STATE_JOINED) { GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Can't set properties on an activity if you're not in it" }; dbus_g_method_return_error (context, &error); return; } properties_copied = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) tp_g_value_slice_free); tp_g_hash_table_update (properties_copied, properties, (GBoxedCopyFunc) g_strdup, (GBoxedCopyFunc) tp_g_value_slice_dup); activity = g_hash_table_lookup (conn->olpc_activities_info, GUINT_TO_POINTER (room)); was_visible = gabble_olpc_activity_is_visible (activity); g_object_set (activity, "properties", properties_copied, NULL); is_visible = gabble_olpc_activity_is_visible (activity); msg = wocky_stanza_build ( WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_GROUPCHAT, NULL, jid, NULL); activity_info_contribute_properties (activity, wocky_stanza_get_top_node (msg), FALSE); if (!_gabble_connection_send (conn, msg, NULL)) { GError error = { TP_ERROR, TP_ERROR_NETWORK_ERROR, "Failed to send property change notification to chatroom" }; g_object_unref (msg); dbus_g_method_return_error (context, &error); return; } g_object_unref (msg); if (!refresh_invitations (conn, muc_channel, activity, &err)) { dbus_g_method_return_error (context, err); g_error_free (err); return; } ctx = g_slice_new (set_properties_ctx); ctx->context = context; ctx->visibility_changed = (was_visible != is_visible); ctx->activity = activity; if (was_visible || is_visible) { if (!upload_activity_properties_pep (conn, set_activity_properties_reply_cb, ctx, &err)) { g_slice_free (set_properties_ctx, ctx); dbus_g_method_return_error (context, err); g_error_free (err); return; } } else { /* chain straight to the reply callback, which changes our Activities * list */ set_activity_properties_reply_cb (conn, NULL, NULL, NULL, ctx); } } static void olpc_activity_properties_get_properties (GabbleSvcOLPCActivityProperties *iface, guint room, DBusGMethodInvocation *context) { GabbleConnection *conn = GABBLE_CONNECTION (iface); gboolean not_prop = FALSE; GHashTable *properties; GabbleOlpcActivity *activity; DEBUG ("called"); gabble_connection_ensure_capabilities (conn, gabble_capabilities_get_olpc_notify ()); if (!check_pep (conn, context)) return; activity = g_hash_table_lookup (conn->olpc_activities_info, GUINT_TO_POINTER (room)); if (activity == NULL || activity->properties == NULL) { /* no properties */ properties = g_hash_table_new (g_str_hash, g_str_equal); not_prop = TRUE; } else { properties = activity->properties; } gabble_svc_olpc_activity_properties_return_from_get_properties (context, properties); if (not_prop) g_hash_table_unref (properties); } struct _i_hate_g_hash_table_foreach { GHashTable *old_properties; gboolean new_infos; }; static void check_prop_in_old_properties (gpointer key, gpointer value, gpointer user_data) { const gchar *prop = key; GValue *gvalue = value, *old_gvalue; struct _i_hate_g_hash_table_foreach *data = (struct _i_hate_g_hash_table_foreach *) user_data; old_gvalue = g_hash_table_lookup (data->old_properties, prop); if (old_gvalue == NULL) { data->new_infos = TRUE; } else if (G_VALUE_TYPE (gvalue) != G_VALUE_TYPE (old_gvalue)) { data->new_infos = TRUE; } else { if (G_VALUE_TYPE (gvalue) == G_TYPE_STRING) { const gchar *str1, *str2; str1 = g_value_get_string (gvalue); str2 = g_value_get_string (old_gvalue); if (tp_strdiff (str1, str2)) { data->new_infos = TRUE; } } else if (G_VALUE_TYPE (gvalue) == G_TYPE_BOOLEAN) { gboolean bool1, bool2; bool1 = g_value_get_boolean (gvalue); bool2 = g_value_get_boolean (old_gvalue); if (bool1 != bool2) { data->new_infos = TRUE; } } else { /* if in doubt, emit the signal */ data->new_infos = TRUE; } } } static gboolean properties_contains_new_infos (GHashTable *old_properties, GHashTable *new_properties) { struct _i_hate_g_hash_table_foreach data; if (g_hash_table_size (new_properties) > g_hash_table_size (old_properties)) /* New key/value pair(s) */ return TRUE; data.old_properties = old_properties; data.new_infos = FALSE; g_hash_table_foreach (new_properties, check_prop_in_old_properties, &data); return data.new_infos; } static void update_activity_properties (GabbleConnection *conn, const gchar *room, const gchar *contact, WockyNode *properties_node) { GHashTable *new_properties, *old_properties; gboolean new_infos = FALSE; GabbleOlpcActivity *activity; TpHandle room_handle; TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_ROOM); room_handle = tp_handle_ensure (room_repo, room, NULL, NULL); activity = g_hash_table_lookup (conn->olpc_activities_info, GUINT_TO_POINTER (room_handle)); if (activity == NULL) { DEBUG ("unknown activity: %s", room); if (contact != NULL) { /* Humm we received properties for an activity we don't * know yet. * If the remote user doesn't announce this activity * in his next activities list, information about * it will be freed */ activity = add_activity_info_in_set (conn, room_handle, contact, conn->olpc_pep_activities); } else { activity = add_activity_info (conn, room_handle); } } if (activity == NULL) return; old_properties = activity->properties; new_properties = lm_message_node_extract_properties (properties_node, "property"); if (g_hash_table_size (new_properties) == 0) { g_hash_table_unref (new_properties); return; } if (old_properties == NULL || properties_contains_new_infos (old_properties, new_properties)) { new_infos = TRUE; } g_object_set (activity, "properties", new_properties, NULL); if (new_infos) { /* Only emit the signal if we add new values */ gabble_svc_olpc_activity_properties_emit_activity_properties_changed ( conn, activity->room, new_properties); } } static gboolean update_activities_properties (GabbleConnection *conn, const gchar *contact, WockyStanza *msg) { const gchar *room; WockyNode *node; WockyNodeIter i; WockyNode *properties_node; node = search_for_child ( wocky_stanza_get_top_node (msg), "activities", NULL); if (node == NULL) return FALSE; wocky_node_iter_init (&i, node, "properties", NULL); while (wocky_node_iter_next (&i, &properties_node)) { room = wocky_node_get_attribute (properties_node, "room"); if (room == NULL) continue; update_activity_properties (conn, room, contact, properties_node); } return TRUE; } static void olpc_act_props_pep_node_changed (WockyPepService *pep, WockyBareContact *contact, WockyStanza *stanza, WockyNode *item, GabbleConnection *conn) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); TpBaseConnection *base = (TpBaseConnection *) conn; TpHandle handle; const gchar *jid; jid = wocky_bare_contact_get_jid (contact); handle = tp_handle_ensure (contact_repo, jid, NULL, NULL); if (handle == 0) { DEBUG ("Invalid from: %s", jid); return; } if (handle == tp_base_connection_get_self_handle (base)) /* Ignore echoed pubsub notifications */ return; update_activities_properties (conn, jid, stanza); } static void connection_status_changed_cb (GabbleConnection *conn, TpConnectionStatus status, TpConnectionStatusReason reason, gpointer user_data) { if (status == TP_CONNECTION_STATUS_CONNECTED) { /* Well, let's do another crack. * We have to cleanup PEP node to avoid to confuse * remote contacts with old properties from a previous session. */ if (!upload_activities_pep (conn, NULL, NULL, NULL)) { DEBUG ("Failed to send PEP activities reset in response to " "initial connection"); } if (!upload_activity_properties_pep (conn, NULL, NULL, NULL)) { DEBUG ("Failed to send PEP activity props reset in response to " "initial connection"); } gabble_connection_connected_olpc (conn); } } static void pseudo_invite_reply_cb (GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg, GObject *object, gpointer user_data) { if (!check_publish_reply_msg (reply_msg, NULL)) { STANZA_DEBUG (reply_msg, "Failed to make PEP change in " "response to pseudo-invitation message"); STANZA_DEBUG (sent_msg, "The failed request was"); } } gboolean conn_olpc_process_activity_properties_message (GabbleConnection *conn, WockyStanza *msg, const gchar *from) { TpBaseConnection *base = (TpBaseConnection *) conn; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); TpHandleRepoIface *room_repo = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_ROOM); WockyNode *node = search_for_child ( wocky_stanza_get_top_node (msg), "properties", NS_OLPC_ACTIVITY_PROPS); const gchar *id; TpHandle room_handle, contact_handle = 0; GabbleOlpcActivity *activity; TpHandleSet *their_invites, *our_activities; GHashTable *old_properties, *new_properties; gboolean properties_changed, pep_properties_changed, activities_changed; gboolean was_visible, is_visible; GabbleMucChannel *muc_channel = NULL; /* if no <properties xmlns=...>, then not for us */ if (node == NULL) return FALSE; DEBUG ("Found <properties> node in <message>"); id = wocky_node_get_attribute (node, "activity"); if (id == NULL) { NODE_DEBUG (node, "... activity ID missing - ignoring"); return TRUE; } room_handle = gabble_get_room_handle_from_jid (room_repo, from); if (room_handle != 0) { muc_channel = gabble_muc_factory_find_text_channel (conn->muc_factory, room_handle); } if (muc_channel == NULL) { const gchar *room; DEBUG ("Activity properties message was a pseudo-invitation"); /* FIXME: This is stupid. We should ref the handles in a TpHandleSet * per activity, then we could _ensure this handle */ contact_handle = tp_handle_lookup (contact_repo, from, NULL, NULL); if (contact_handle == 0) { DEBUG ("... contact <%s> unknown - ignoring (FIX THIS)", from); return TRUE; } room = wocky_node_get_attribute (node, "room"); if (room == NULL) { NODE_DEBUG (node, "... room name missing - ignoring"); return TRUE; } DEBUG ("... room <%s>", room); room_handle = tp_handle_ensure (room_repo, room, NULL, NULL); if (room_handle == 0) { DEBUG ("... room <%s> invalid - ignoring", room); return TRUE; } muc_channel = gabble_muc_factory_find_text_channel (conn->muc_factory, room_handle); if (muc_channel != NULL) { guint state; g_object_get (muc_channel, "state", &state, NULL); if (state == MUC_STATE_JOINED) { DEBUG ("Ignoring pseudo-invitation to <%s> - we're already " "there", room); return TRUE; } } } else { TpHandle self_handle; DEBUG ("Activity properties message was in a chatroom"); tp_group_mixin_get_self_handle ((GObject *) muc_channel, &self_handle, NULL); if (tp_handle_lookup (contact_repo, from, NULL, NULL) == self_handle) { DEBUG ("Ignoring echoed activity properties message from myself"); return TRUE; } } activity = g_hash_table_lookup (conn->olpc_activities_info, GUINT_TO_POINTER (room_handle)); if (contact_handle != 0) { their_invites = g_hash_table_lookup (conn->olpc_invited_activities, GUINT_TO_POINTER (contact_handle)); if (their_invites == NULL) { activities_changed = TRUE; their_invites = tp_handle_set_new (room_repo); g_hash_table_insert (conn->olpc_invited_activities, GUINT_TO_POINTER (contact_handle), their_invites); } else { activities_changed = !tp_handle_set_is_member (their_invites, room_handle); } if (activity == NULL) { DEBUG ("... creating new Activity"); activity = add_activity_info (conn, room_handle); tp_handle_set_add (their_invites, room_handle); } else if (!tp_handle_set_is_member (their_invites, room_handle)) { DEBUG ("... it's the first time that contact invited me, " "referencing Activity on their behalf"); g_object_ref (activity); tp_handle_set_add (their_invites, room_handle); } } else { activities_changed = FALSE; /* we're in the room, so it ought to have an Activity ref'd */ g_assert (activity != NULL); } new_properties = lm_message_node_extract_properties (node, "property"); g_assert (new_properties); /* before applying the changes, gather enough information to work out * whether anything changed */ old_properties = activity->properties; was_visible = gabble_olpc_activity_is_visible (activity); properties_changed = old_properties == NULL || properties_contains_new_infos (old_properties, new_properties); /* apply the info we found */ if (tp_strdiff (activity->id, id)) { DEBUG ("... recording new activity ID %s", id); g_object_set (activity, "id", id, NULL); } g_object_set (activity, "properties", new_properties, NULL); /* emit signals and amend our PEP nodes, if necessary */ is_visible = gabble_olpc_activity_is_visible (activity); if (is_visible) { pep_properties_changed = properties_changed || !was_visible; } else { pep_properties_changed = was_visible; } if (properties_changed) gabble_svc_olpc_activity_properties_emit_activity_properties_changed (conn, room_handle, new_properties); if (activities_changed) { GPtrArray *activities; g_assert (contact_handle != 0); activities = get_buddy_activities (conn, contact_handle); gabble_svc_olpc_buddy_info_emit_activities_changed (conn, contact_handle, activities); free_activities (activities); } if (properties_changed && muc_channel != NULL) refresh_invitations (conn, muc_channel, activity, NULL); /* If we're announcing this activity, we might need to change our PEP node */ if (pep_properties_changed) { our_activities = g_hash_table_lookup (conn->olpc_pep_activities, GUINT_TO_POINTER (tp_base_connection_get_self_handle (base))); if (our_activities != NULL && tp_handle_set_is_member (our_activities, room_handle)) { if (!upload_activity_properties_pep (conn, pseudo_invite_reply_cb, NULL, NULL)) { DEBUG ("Failed to send PEP properties change in response to " "properties change message"); } } } if (is_visible != was_visible) { our_activities = g_hash_table_lookup (conn->olpc_pep_activities, GUINT_TO_POINTER (tp_base_connection_get_self_handle (base))); if (our_activities != NULL && tp_handle_set_is_member (our_activities, room_handle)) { if (!upload_activities_pep (conn, pseudo_invite_reply_cb, NULL, NULL)) { DEBUG ("Failed to send PEP activities change in response to " "properties change message"); } } } return TRUE; } static void closed_pep_reply_cb (GabbleConnection *conn, WockyStanza *sent_msg, WockyStanza *reply_msg, GObject *object, gpointer user_data) { if (!check_publish_reply_msg (reply_msg, NULL)) { STANZA_DEBUG (reply_msg, "Failed to make PEP change in " "response to channel closure"); STANZA_DEBUG (sent_msg, "The failed request was"); } } static gboolean revoke_invitations (GabbleConnection *conn, GabbleMucChannel *chan, GabbleOlpcActivity *activity, GError **error) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); TpHandleSet *invitees = g_object_get_qdata ((GObject *) chan, invitees_quark ()); if (activity->id == NULL) /* this is not a real OLPC activity */ return TRUE; if (invitees != NULL && tp_handle_set_size (invitees) > 0) { TpIntsetFastIter iter; guint element; tp_intset_fast_iter_init (&iter, tp_handle_set_peek (invitees)); DEBUG ("revoke invitations for activity %s", activity->id); while (tp_intset_fast_iter_next (&iter, &element)) { const gchar *to = tp_handle_inspect (contact_repo, element); WockyStanza *msg = wocky_stanza_build ( WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, to, '(', "uninvite", ':', NS_OLPC_ACTIVITY_PROPS, '@', "room", gabble_olpc_activity_get_room (activity), '@', "id", activity->id, ')', NULL); if (!_gabble_connection_send (conn, msg, error)) { DEBUG ("Unable to send activity invitee revocation %s", to); g_object_unref (msg); return FALSE; } g_object_unref (msg); } } return TRUE; } gboolean conn_olpc_process_activity_uninvite_message (GabbleConnection *conn, WockyStanza *msg, const gchar *from) { TpHandleRepoIface *room_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_ROOM); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); WockyNode *node; const gchar *id, *room; TpHandle room_handle, from_handle; TpHandleSet *rooms; node = search_for_child ( wocky_stanza_get_top_node (msg), "uninvite", NS_OLPC_ACTIVITY_PROPS); /* if no <uninvite xmlns=...>, then not for us */ if (node == NULL) return FALSE; id = wocky_node_get_attribute (node, "id"); if (id == NULL) { DEBUG ("no activity id. Skip"); return TRUE; } room = wocky_node_get_attribute (node, "room"); if (room == NULL) { DEBUG ("no room. Skip"); return TRUE; } room_handle = tp_handle_lookup (room_repo, room, NULL, NULL); if (room_handle == 0) { DEBUG ("room %s unknown", room); return TRUE; } from_handle = tp_handle_lookup (contact_repo, from, NULL, NULL); if (from_handle == 0) { DEBUG ("sender %s unknown", from); return TRUE; } rooms = g_hash_table_lookup (conn->olpc_invited_activities, GUINT_TO_POINTER (from_handle)); if (rooms == NULL) { DEBUG ("No invites associated with contact %d", from_handle); return TRUE; } if (tp_handle_set_remove (rooms, room_handle)) { GabbleOlpcActivity *activity; GPtrArray *activities; activity = g_hash_table_lookup (conn->olpc_activities_info, GUINT_TO_POINTER (room_handle)); if (activity == NULL) { DEBUG ("No info about activity associated with room %s", room); return TRUE; } if (tp_strdiff (id, activity->id)) { DEBUG ("Uninvite's activity id (%s) doesn't match our " "activity id (%s)", id, activity->id); return TRUE; } DEBUG ("remove invite from %s", from); g_object_unref (activity); /* Emit BuddyInfo::ActivitiesChanged */ activities = get_buddy_activities (conn, from_handle); gabble_svc_olpc_buddy_info_emit_activities_changed (conn, from_handle, activities); free_activities (activities); } else { DEBUG ("No invite from %s for activity %s (room %s)", from, id, room); return TRUE; } return TRUE; } static void muc_channel_closed_cb (GabbleMucChannel *chan, GabbleOlpcActivity *activity) { GabbleConnection *conn; TpBaseConnection *base; TpHandleSet *my_activities; gboolean was_in_our_pep = FALSE; /* is the muc channel /actually/ disappearing */ if (!tp_base_channel_is_destroyed (TP_BASE_CHANNEL (chan))) return; g_object_get (activity, "connection", &conn, NULL); base = TP_BASE_CONNECTION (conn); /* Revoke invitations we sent for this activity */ revoke_invitations (conn, chan, activity, NULL); /* remove it from our advertised activities list, unreffing it in the * process if it was in fact advertised */ my_activities = g_hash_table_lookup (conn->olpc_pep_activities, GUINT_TO_POINTER (tp_base_connection_get_self_handle (base))); if (my_activities != NULL) { if (tp_handle_set_remove (my_activities, activity->room)) { was_in_our_pep = gabble_olpc_activity_is_visible (activity); g_object_unref (activity); } } /* unref it again (it was referenced on behalf of the channel) */ g_object_unref (activity); if (was_in_our_pep) { if (!upload_activities_pep (conn, closed_pep_reply_cb, NULL, NULL)) { DEBUG ("Failed to send PEP activities change in response to " "channel close"); } if (!upload_activity_properties_pep (conn, closed_pep_reply_cb, NULL, NULL)) { DEBUG ("Failed to send PEP activity props change in response to " "channel close"); } } g_object_unref (conn); } static void muc_channel_pre_invite_cb (GabbleMucChannel *chan, const gchar *jid, GabbleOlpcActivity *activity) { GabbleConnection *conn; TpHandleRepoIface *contact_repo; GQuark quark = invitees_quark (); TpHandleSet *invitees; /* send them the properties */ WockyStanza *msg; TpHandle handle; GError *error = NULL; g_object_get (activity, "connection", &conn, NULL); contact_repo = tp_base_connection_get_handles ((TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); msg = wocky_stanza_build ( WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, jid, NULL); if (activity_info_contribute_properties (activity, wocky_stanza_get_top_node (msg), FALSE)) { /* not much we can do about errors - but if this fails, the invitation * will too, unless something extremely strange is going on */ if (!_gabble_connection_send (conn, msg, NULL)) { DEBUG ("Unable to send activity properties to invitee"); } } g_object_unref (msg); handle = tp_handle_ensure (contact_repo, jid, NULL, &error); if (handle == 0) { DEBUG ("can't add %s to invitees: %s", jid, error->message); g_error_free (error); g_object_unref (conn); return; } invitees = g_object_get_qdata ((GObject *) chan, quark); if (invitees == NULL) { invitees = tp_handle_set_new (contact_repo); g_object_set_qdata_full ((GObject *) chan, quark, invitees, (GDestroyNotify) tp_handle_set_destroy); } tp_handle_set_add (invitees, handle); g_object_unref (conn); } typedef struct { GabbleConnection *conn; TpHandle room_handle; } remove_invite_foreach_ctx; static void remove_invite_foreach (gpointer key, gpointer value, gpointer user_data) { TpHandle inviter = GPOINTER_TO_UINT (key); TpHandleSet *rooms = (TpHandleSet *) value; remove_invite_foreach_ctx *ctx = (remove_invite_foreach_ctx *) user_data; /* We are now in the activity and so the responsibilty to track * buddies membership is delegated to the PS. At some point, maybe that * should be done by CM's */ if (tp_handle_set_remove (rooms, ctx->room_handle)) { GabbleOlpcActivity *activity; GPtrArray *activities; activity = g_hash_table_lookup (ctx->conn->olpc_activities_info, GUINT_TO_POINTER (ctx->room_handle)); activities = get_buddy_activities (ctx->conn, inviter); gabble_svc_olpc_buddy_info_emit_activities_changed (ctx->conn, inviter, activities); free_activities (activities); g_assert (activity != NULL); DEBUG ("forget invite for activity %s from contact %d", activity->id, inviter); g_object_unref (activity); } } static void forget_activity_invites (GabbleConnection *conn, TpHandle room_handle) { remove_invite_foreach_ctx ctx; ctx.conn = conn; ctx.room_handle = room_handle; g_hash_table_foreach (conn->olpc_invited_activities, remove_invite_foreach, &ctx); } static void muc_channel_contact_join_cb (GabbleMucChannel *chan, TpHandle contact, GabbleOlpcActivity *activity) { GabbleConnection *conn; TpBaseConnection *base; g_object_get (activity, "connection", &conn, NULL); base = TP_BASE_CONNECTION (conn); if (contact == tp_base_connection_get_self_handle (base)) { /* We join the channel, forget about all invites we received about * this activity */ forget_activity_invites (conn, activity->room); } else { GQuark quark = invitees_quark (); TpHandleSet *invitees; invitees = g_object_get_qdata ((GObject *) chan, quark); if (invitees != NULL) { DEBUG ("contact %d joined the muc, remove the invite we sent to him", contact); tp_handle_set_remove (invitees, contact); } } g_object_unref (conn); } static void muc_factory_new_channel_cb (gpointer key, gpointer value, gpointer data) { GabbleConnection *conn = GABBLE_CONNECTION (data); TpExportableChannel *chan = TP_EXPORTABLE_CHANNEL (key); GabbleOlpcActivity *activity; TpHandle room_handle; if (!GABBLE_IS_MUC_CHANNEL (chan)) return; g_object_get (chan, "handle", &room_handle, NULL); /* ref the activity as long as we have a channel open */ activity = g_hash_table_lookup (conn->olpc_activities_info, GUINT_TO_POINTER (room_handle)); if (activity == NULL) { activity = add_activity_info (conn, room_handle); } else { g_object_ref (activity); } g_signal_connect (chan, "closed", G_CALLBACK (muc_channel_closed_cb), activity); g_signal_connect (chan, "pre-invite", G_CALLBACK (muc_channel_pre_invite_cb), activity); g_signal_connect (chan, "contact-join", G_CALLBACK (muc_channel_contact_join_cb), activity); } static void muc_factory_new_channels_cb (GabbleMucFactory *fac, GHashTable *channels, GabbleConnection *conn) { g_hash_table_foreach (channels, muc_factory_new_channel_cb, conn); } static void connection_presence_do_update (GabblePresenceCache *cache, TpHandle handle, GabbleConnection *conn) { GabblePresence *presence; presence = gabble_presence_cache_get (cache, handle); if (presence && presence->status <= GABBLE_PRESENCE_LAST_UNAVAILABLE) { /* Contact becomes unavailable. We have to unref all the information * provided by him */ GPtrArray *empty = g_ptr_array_new (); TpHandleSet *list; list = g_hash_table_lookup (conn->olpc_pep_activities, GUINT_TO_POINTER (handle)); if (list != NULL) tp_handle_set_foreach (list, decrement_contacts_activities_set_foreach, conn); g_hash_table_remove (conn->olpc_pep_activities, GUINT_TO_POINTER (handle)); list = g_hash_table_lookup (conn->olpc_invited_activities, GUINT_TO_POINTER (handle)); if (list != NULL) tp_handle_set_foreach (list, decrement_contacts_activities_set_foreach, conn); g_hash_table_remove (conn->olpc_invited_activities, GUINT_TO_POINTER (handle)); gabble_svc_olpc_buddy_info_emit_activities_changed (conn, handle, empty); g_ptr_array_unref (empty); } } static void connection_presences_updated_cb (GabblePresenceCache *cache, GArray *handles, GabbleConnection *conn) { guint i; for (i = 0; i < handles->len ; i++) { TpHandle handle; handle = g_array_index (handles, TpHandle, i); connection_presence_do_update (cache, handle, conn); } } void conn_olpc_activity_properties_init (GabbleConnection *conn) { /* room TpHandle => borrowed Activity */ conn->olpc_activities_info = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); /* Activity from PEP * * contact TpHandle => TpHandleSet of room handles, * each representing a reference to an Activity * * Special case: the entry for self_handle is the complete list of * activities, not just those from PEP */ conn->olpc_pep_activities = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) tp_handle_set_destroy); /* Activity from pseudo-invitations * * contact TpHandle => TpHandleSet of room handles, * each representing a reference to an Activity * * Special case: there is never an entry for self_handle */ conn->olpc_invited_activities = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) tp_handle_set_destroy); /* Current activity * * contact TpHandle => reffed GabbleOlpcActivity */ conn->olpc_current_act = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_object_unref); g_signal_connect (conn, "status-changed", G_CALLBACK (connection_status_changed_cb), NULL); g_signal_connect (TP_CHANNEL_MANAGER (conn->muc_factory), "new-channels", G_CALLBACK (muc_factory_new_channels_cb), conn); g_signal_connect (conn->presence_cache, "presences-updated", G_CALLBACK (connection_presences_updated_cb), conn); conn->pep_olpc_buddy_props = wocky_pep_service_new (NS_OLPC_BUDDY_PROPS, TRUE); g_signal_connect (conn->pep_olpc_buddy_props, "changed", G_CALLBACK (olpc_buddy_props_pep_node_changed), conn); conn->pep_olpc_activities = wocky_pep_service_new (NS_OLPC_ACTIVITIES, TRUE); g_signal_connect (conn->pep_olpc_activities, "changed", G_CALLBACK (olpc_activities_pep_node_changed), conn); conn->pep_olpc_current_act = wocky_pep_service_new (NS_OLPC_CURRENT_ACTIVITY, TRUE); g_signal_connect (conn->pep_olpc_current_act, "changed", G_CALLBACK (olpc_current_act_pep_node_changed), conn); conn->pep_olpc_act_props = wocky_pep_service_new (NS_OLPC_ACTIVITY_PROPS, TRUE); g_signal_connect (conn->pep_olpc_act_props, "changed", G_CALLBACK (olpc_act_props_pep_node_changed), conn); } static void unref_activities_in_each_set (TpHandle handle, TpHandleSet *set, GabbleConnection *conn) { if (set != NULL) { tp_handle_set_foreach (set, decrement_contacts_activities_set_foreach, conn); } } void conn_olpc_activity_properties_dispose (GabbleConnection *self) { g_hash_table_unref (self->olpc_current_act); self->olpc_current_act = NULL; g_hash_table_foreach (self->olpc_pep_activities, (GHFunc) unref_activities_in_each_set, self); g_hash_table_unref (self->olpc_pep_activities); self->olpc_pep_activities = NULL; g_hash_table_foreach (self->olpc_invited_activities, (GHFunc) unref_activities_in_each_set, self); g_hash_table_unref (self->olpc_invited_activities); self->olpc_invited_activities = NULL; g_hash_table_unref (self->olpc_activities_info); self->olpc_activities_info = NULL; } static GabbleOlpcActivity * find_activity_by_id (GabbleConnection *self, const gchar *activity_id) { GHashTableIter iter; gpointer key, value; g_hash_table_iter_init (&iter, self->olpc_activities_info); while (g_hash_table_iter_next (&iter, &key, &value)) { GabbleOlpcActivity *activity = GABBLE_OLPC_ACTIVITY (value); if (!tp_strdiff (activity->id, activity_id)) return activity; } return NULL; } static void olpc_activity_properties_get_activity (GabbleSvcOLPCActivityProperties *iface, const gchar *activity_id, DBusGMethodInvocation *context) { GabbleConnection *self = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) self; GabbleOlpcActivity *activity; GError *error = NULL; TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); activity = find_activity_by_id (self, activity_id); if (activity == NULL) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "Activity unknown: %s", activity_id); goto error; } gabble_svc_olpc_activity_properties_return_from_get_activity (context, activity->room); return; error: dbus_g_method_return_error (context, error); g_error_free (error); } void olpc_activity_properties_iface_init (gpointer g_iface, gpointer iface_data) { GabbleSvcOLPCActivityPropertiesClass *klass = g_iface; #define IMPLEMENT(x) gabble_svc_olpc_activity_properties_implement_##x (\ klass, olpc_activity_properties_##x) IMPLEMENT(get_properties); IMPLEMENT(set_properties); IMPLEMENT(get_activity); #undef IMPLEMENT } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/im-factory.c������������������������������������������������������������0000664�0001750�0001750�00000060747�12332440117�021216� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * im-factory.c - Source for GabbleImFactory * Copyright (C) 2006 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "im-factory.h" #include <string.h> #include <dbus/dbus-glib.h> #include <dbus/dbus-glib-lowlevel.h> #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #include <wocky/wocky.h> #define DEBUG_FLAG GABBLE_DEBUG_IM #include "extensions/extensions.h" #include "gabble/caps-channel-manager.h" #include "connection.h" #include "debug.h" #include "disco.h" #include "im-channel.h" #include "message-util.h" #include "namespaces.h" static void channel_manager_iface_init (gpointer, gpointer); static void caps_channel_manager_iface_init (gpointer, gpointer); G_DEFINE_TYPE_WITH_CODE (GabbleImFactory, gabble_im_factory, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER, channel_manager_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_CAPS_CHANNEL_MANAGER, caps_channel_manager_iface_init)); /* properties */ enum { PROP_CONNECTION = 1, LAST_PROPERTY }; struct _GabbleImFactoryPrivate { GabbleConnection *conn; guint message_cb_id; guint delivery_report_cb_id; GHashTable *channels; gulong status_changed_id; gboolean dispose_has_run; }; static void gabble_im_factory_init (GabbleImFactory *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_IM_FACTORY, GabbleImFactoryPrivate); self->priv->channels = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); self->priv->conn = NULL; self->priv->dispose_has_run = FALSE; } static void connection_status_changed_cb (GabbleConnection *conn, guint status, guint reason, GabbleImFactory *self); static void porter_available_cb ( GabbleConnection *conn, WockyPorter *porter, gpointer user_data); static void gabble_im_factory_constructed (GObject *obj) { GabbleImFactory *self = GABBLE_IM_FACTORY (obj); GObjectClass *parent_class = gabble_im_factory_parent_class; if (parent_class->constructed != NULL) parent_class->constructed (obj); self->priv->status_changed_id = g_signal_connect (self->priv->conn, "status-changed", (GCallback) connection_status_changed_cb, obj); tp_g_signal_connect_object (self->priv->conn, "porter-available", (GCallback) porter_available_cb, obj, 0); } static void gabble_im_factory_close_all (GabbleImFactory *); static void gabble_im_factory_dispose (GObject *object) { GabbleImFactory *fac = GABBLE_IM_FACTORY (object); GabbleImFactoryPrivate *priv = fac->priv; if (priv->dispose_has_run) return; DEBUG ("dispose called"); priv->dispose_has_run = TRUE; gabble_im_factory_close_all (fac); g_assert (priv->channels == NULL); if (G_OBJECT_CLASS (gabble_im_factory_parent_class)->dispose) G_OBJECT_CLASS (gabble_im_factory_parent_class)->dispose (object); } static void gabble_im_factory_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleImFactory *fac = GABBLE_IM_FACTORY (object); GabbleImFactoryPrivate *priv = fac->priv; switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, priv->conn); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_im_factory_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleImFactory *fac = GABBLE_IM_FACTORY (object); GabbleImFactoryPrivate *priv = fac->priv; switch (property_id) { case PROP_CONNECTION: priv->conn = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_im_factory_class_init (GabbleImFactoryClass *gabble_im_factory_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_im_factory_class); GParamSpec *param_spec; g_type_class_add_private (gabble_im_factory_class, sizeof (GabbleImFactoryPrivate)); object_class->constructed = gabble_im_factory_constructed; object_class->dispose = gabble_im_factory_dispose; object_class->get_property = gabble_im_factory_get_property; object_class->set_property = gabble_im_factory_set_property; param_spec = g_param_spec_object ("connection", "GabbleConnection object", "Gabble connection object that owns this IM channel manager object.", GABBLE_TYPE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); } static GabbleIMChannel *get_channel_for_incoming_message ( GabbleImFactory *self, const gchar *jid, gboolean create_if_missing); /** * im_factory_message_cb: * * Called by Wocky when we get an incoming <message>. */ static gboolean im_factory_message_cb ( WockyPorter *porter, WockyStanza *message, gpointer user_data) { GabbleImFactory *fac = GABBLE_IM_FACTORY (user_data); const gchar *from, *body, *id; time_t stamp; TpChannelTextMessageType msgtype; GabbleIMChannel *chan; gint state; TpChannelTextSendError send_error; TpDeliveryStatus delivery_status; gboolean create_if_missing; if (!gabble_message_util_parse_incoming_message (message, &from, &stamp, &msgtype, &id, &body, &state, &send_error, &delivery_status)) return TRUE; if (body == NULL && state == -1) { return FALSE; } /* We don't want to open up a channel for the sole purpose of reporting a * send error, nor if this is just a chat state notification. */ create_if_missing = (send_error == GABBLE_TEXT_CHANNEL_SEND_NO_ERROR) && (body != NULL); chan = get_channel_for_incoming_message (fac, from, create_if_missing); if (chan == NULL) { if (create_if_missing) STANZA_DEBUG (message, "ignoring message from non-contact JID"); else DEBUG ("ignoring message error or chat state notification from '%s': " "no existing channel", from); return TRUE; } if (send_error != GABBLE_TEXT_CHANNEL_SEND_NO_ERROR) { if (body == NULL) { DEBUG ("ignoring error sending chat state to %s", from); return TRUE; } DEBUG ("got error sending to %s, msgtype %u, body:\n%s", from, msgtype, body); _gabble_im_channel_report_delivery (chan, msgtype, stamp, id, body, send_error, delivery_status); } else if (body != NULL) { _gabble_im_channel_receive (chan, message, msgtype, from, stamp, id, body, state); } else if (state != -1) { _gabble_im_channel_state_receive (chan, (TpChannelChatState) state); } return TRUE; } /* Signals incoming delivery receipts. http://xmpp.org/extensions/xep-0184.html */ static gboolean im_factory_receipt_cb ( WockyPorter *porter, WockyStanza *message, gpointer user_data) { GabbleImFactory *self = GABBLE_IM_FACTORY (user_data); WockyNode *received; const gchar *from, *received_id; GabbleIMChannel *channel; received = wocky_node_get_child_ns (wocky_stanza_get_top_node (message), "received", NS_RECEIPTS); g_return_val_if_fail (received != NULL, FALSE); received_id = wocky_node_get_attribute (received, "id"); if (received_id == NULL) { STANZA_DEBUG (message, "but *what* did you receive?!"); return TRUE; } from = wocky_stanza_get_from (message); channel = get_channel_for_incoming_message (self, from, FALSE); if (channel == NULL) { DEBUG ("no existing channel with '%s'; ignoring receipt", from); return TRUE; } gabble_im_channel_receive_receipt (channel, received_id); return TRUE; } /** * im_channel_closed_cb: * * Signal callback for when an IM channel is closed. Removes the references * that #GabbleConnection holds to them - unless the channel has pending * messages, in which case it is re-announced (so from the perspective of the * D-Bus API, it was replaced by an identical channel). */ static void im_channel_closed_cb (GabbleIMChannel *chan, gpointer user_data) { GabbleImFactory *self = GABBLE_IM_FACTORY (user_data); GabbleImFactoryPrivate *priv = self->priv; TpBaseChannel *base = TP_BASE_CHANNEL (chan); TpHandle contact_handle = tp_base_channel_get_target_handle (base); DEBUG ("%p, channel %p", self, chan); if (tp_base_channel_is_registered (base)) { tp_channel_manager_emit_channel_closed_for_object (self, (TpExportableChannel *) chan); } if (priv->channels != NULL) { if (tp_base_channel_is_destroyed (base)) { DEBUG ("removing channel with handle %u", contact_handle); g_hash_table_remove (priv->channels, GUINT_TO_POINTER (contact_handle)); } else if (tp_base_channel_is_respawning (base)) { DEBUG ("reopening channel with handle %u due to pending messages", contact_handle); tp_channel_manager_emit_new_channel (self, (TpExportableChannel *) chan, NULL); } else { /* this basically means tp_base_channel_disappear() must * have been called; this doesn't have any meaning in this * channel manager. */ g_assert_not_reached (); } } } /* * new_im_channel: * @fac: the factory * @handle: a contact handle, for whom a channel must not yet exist * @request_token: if the channel is being created in response to a channel * request, the associated request token; otherwise, NULL. * * Creates a new 1-1 text channel to a contact. Must only be called when no 1-1 * text channel is already open to that contact. * * Returns: (transfer none): a freshly-constructed channel */ static GabbleIMChannel * new_im_channel (GabbleImFactory *fac, TpHandle handle, gpointer request_token) { GabbleImFactoryPrivate *priv = fac->priv; TpBaseConnection *conn = (TpBaseConnection *) priv->conn; GabbleIMChannel *chan; GSList *request_tokens; TpHandle initiator; g_return_val_if_fail (handle != 0, NULL); if (request_token != NULL) initiator = tp_base_connection_get_self_handle (conn); else initiator = handle; chan = g_object_new (GABBLE_TYPE_IM_CHANNEL, "connection", priv->conn, "handle", handle, "initiator-handle", initiator, "requested", (handle != initiator), NULL); tp_base_channel_register ((TpBaseChannel *) chan); g_signal_connect (chan, "closed", (GCallback) im_channel_closed_cb, fac); g_hash_table_insert (priv->channels, GUINT_TO_POINTER (handle), chan); if (request_token != NULL) request_tokens = g_slist_prepend (NULL, request_token); else request_tokens = NULL; tp_channel_manager_emit_new_channel (fac, (TpExportableChannel *) chan, request_tokens); g_slist_free (request_tokens); return chan; } /* * get_channel_for_incoming_message: * @self: a factory * @jid: a contact's JID * @create_if_missing: if %TRUE, a new channel will be created if there is no * existing channel to @jid * * Retrieves a 1-1 text channel to a particular contact. If no channel is open * to @jid, it will be created only if @create_if_missing is %TRUE. If @jid is * not of the form 'user@domain' (optionally with a resource), no channel will * be opened. * * Returns: an IM channel to @jid, or %NULL */ static GabbleIMChannel * get_channel_for_incoming_message ( GabbleImFactory *self, const gchar *jid, gboolean create_if_missing) { GabbleImFactoryPrivate *priv = self->priv; TpBaseConnection *conn = (TpBaseConnection *) priv->conn; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT); TpHandle handle; GabbleIMChannel *chan; g_return_val_if_fail (jid != NULL, NULL); handle = tp_handle_ensure (contact_repo, jid, NULL, NULL); if (handle == 0) return NULL; chan = g_hash_table_lookup (priv->channels, GUINT_TO_POINTER (handle)); if (chan != NULL) return chan; else if (create_if_missing) return new_im_channel (self, handle, NULL); else return NULL; } static void gabble_im_factory_close_all (GabbleImFactory *self) { /* Use a temporary variable (the macro does this) because we don't want * im_channel_closed_cb to remove the channel from the hash table a * second time */ tp_clear_pointer (&self->priv->channels, g_hash_table_unref); if (self->priv->status_changed_id != 0) { g_signal_handler_disconnect (self->priv->conn, self->priv->status_changed_id); self->priv->status_changed_id = 0; } if (self->priv->message_cb_id != 0) { WockyPorter *porter = gabble_connection_dup_porter (self->priv->conn); wocky_porter_unregister_handler (porter, self->priv->message_cb_id); self->priv->message_cb_id = 0; wocky_porter_unregister_handler (porter, self->priv->delivery_report_cb_id); self->priv->delivery_report_cb_id = 0; g_object_unref (porter); } } static void connection_status_changed_cb (GabbleConnection *conn, guint status, guint reason, GabbleImFactory *self) { switch (status) { case TP_CONNECTION_STATUS_DISCONNECTED: gabble_im_factory_close_all (self); break; } } static gboolean im_factory_own_message_cb ( WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { GabbleImFactory *self = GABBLE_IM_FACTORY (user_data); WockyNode *own_message, *body; const gchar *to; gboolean sent_locally; GabbleIMChannel *chan; /* Our stanza filter should guarantee that these are present. */ own_message = wocky_node_get_child (wocky_stanza_get_top_node (stanza), "own-message"); g_return_val_if_fail (own_message != NULL, FALSE); body = wocky_node_get_child (own_message, "body"); g_return_val_if_fail (body != NULL, FALSE); to = wocky_node_get_attribute (own_message, "to"); if (to == NULL) { DEBUG ("own-message missing to='' attribute; ignoring"); return FALSE; } /* If self='true', the message was sent by the local user on this machine, * rather than by the local user on some other machine. We don't really have * a good way to show this in Messages. Also we don't get told the id='' of * the original message, which is annoying. */ sent_locally = !tp_strdiff ("true", wocky_node_get_attribute (own_message, "self")); DEBUG ("this report is for a message to '%s', sent %s", to, sent_locally ? "locally" : "remotely"); /* Don't create a channel for the sole purpose of reporting an own-message. * This is consistent with not creating a channel to report send errors * (given that both are delivery reports). */ chan = get_channel_for_incoming_message (self, to, FALSE); if (chan != NULL) _gabble_im_channel_report_delivery (chan, TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL, 0, NULL, body->content, GABBLE_TEXT_CHANNEL_SEND_NO_ERROR, TP_DELIVERY_STATUS_ACCEPTED); else DEBUG ("no channel for '%s'; not spawning one just for the delivery report", to); wocky_porter_acknowledge_iq (porter, stanza, NULL); return TRUE; } static void porter_available_cb ( GabbleConnection *conn, WockyPorter *porter, gpointer user_data) { GabbleImFactory *self = GABBLE_IM_FACTORY (user_data); gchar *stream_server; DEBUG ("adding callbacks"); self->priv->message_cb_id = wocky_porter_register_handler_from_anyone (porter, WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, WOCKY_PORTER_HANDLER_PRIORITY_MIN, im_factory_message_cb, self, NULL); self->priv->delivery_report_cb_id = wocky_porter_register_handler_from_anyone (porter, WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, WOCKY_PORTER_HANDLER_PRIORITY_MIN, im_factory_receipt_cb, self, '(', "received", ':', NS_RECEIPTS, ')', NULL); g_object_get (conn, "stream-server", &stream_server, NULL); if (!tp_strdiff (stream_server, "chat.facebook.com")) { wocky_porter_register_handler_from ( porter, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, /* We could use _from_server() if that accepted messages from our * JID's domain, not just from bare JID, full JID, or no sender * specified—which would allow the extension to work on other servers * too—but it doesn't. */ stream_server, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, im_factory_own_message_cb, self, '(', "own-message", ':', NS_FACEBOOK_MESSAGES, '(', "body", ')', ')', NULL); } g_free (stream_server); } static void gabble_im_factory_get_contact_caps (GabbleCapsChannelManager *manager, TpHandle handle, const GabbleCapabilitySet *caps, GPtrArray *arr) { /* We don't need to check this contact's capabilities, we assume every * contact support text channels. */ /* NOTE: if any more contact caps are added here which are not * assumed then be sure to change the implementation of * gabble_connection_get_handle_contact_capabilities, as that uses * this function to fill the contact caps hash for all contacts * (even offline). */ GValue monster = {0, }; GHashTable *fixed_properties; GValue *channel_type_value; GValue *target_handle_type_value; gchar *text_allowed_properties[] = { TP_IFACE_CHANNEL ".TargetHandle", NULL }; g_assert (handle != 0); g_value_init (&monster, TP_STRUCT_TYPE_REQUESTABLE_CHANNEL_CLASS); g_value_take_boxed (&monster, dbus_g_type_specialized_construct ( TP_STRUCT_TYPE_REQUESTABLE_CHANNEL_CLASS)); fixed_properties = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free); channel_type_value = tp_g_value_slice_new (G_TYPE_STRING); g_value_set_static_string (channel_type_value, TP_IFACE_CHANNEL_TYPE_TEXT); g_hash_table_insert (fixed_properties, TP_IFACE_CHANNEL ".ChannelType", channel_type_value); target_handle_type_value = tp_g_value_slice_new (G_TYPE_UINT); g_value_set_uint (target_handle_type_value, TP_HANDLE_TYPE_CONTACT); g_hash_table_insert (fixed_properties, TP_IFACE_CHANNEL ".TargetHandleType", target_handle_type_value); dbus_g_type_struct_set (&monster, 0, fixed_properties, 1, text_allowed_properties, G_MAXUINT); g_hash_table_unref (fixed_properties); g_ptr_array_add (arr, g_value_get_boxed (&monster)); } struct _ForeachData { TpExportableChannelFunc func; gpointer user_data; }; static void _foreach_slave (gpointer key, gpointer value, gpointer user_data) { struct _ForeachData *data = user_data; TpExportableChannel *chan = TP_EXPORTABLE_CHANNEL (value); data->func (chan, data->user_data); } static void gabble_im_factory_foreach_channel (TpChannelManager *manager, TpExportableChannelFunc func, gpointer user_data) { GabbleImFactory *self = GABBLE_IM_FACTORY (manager); struct _ForeachData data; data.user_data = user_data; data.func = func; g_hash_table_foreach (self->priv->channels, _foreach_slave, &data); } static const gchar * const im_channel_fixed_properties[] = { TP_IFACE_CHANNEL ".ChannelType", TP_IFACE_CHANNEL ".TargetHandleType", NULL }; static const gchar * const im_channel_allowed_properties[] = { TP_IFACE_CHANNEL ".TargetHandle", TP_IFACE_CHANNEL ".TargetID", NULL }; static void gabble_im_factory_type_foreach_channel_class (GType type, TpChannelManagerTypeChannelClassFunc func, gpointer user_data) { GHashTable *table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free); GValue *value; value = tp_g_value_slice_new (G_TYPE_STRING); g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_TEXT); g_hash_table_insert (table, (gchar *) im_channel_fixed_properties[0], value); value = tp_g_value_slice_new (G_TYPE_UINT); g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT); g_hash_table_insert (table, (gchar *) im_channel_fixed_properties[1], value); func (type, table, im_channel_allowed_properties, user_data); g_hash_table_unref (table); } static gboolean gabble_im_factory_requestotron (GabbleImFactory *self, gpointer request_token, GHashTable *request_properties, gboolean require_new) { TpHandle handle; GError *error = NULL; TpExportableChannel *channel; if (tp_strdiff (tp_asv_get_string (request_properties, TP_IFACE_CHANNEL ".ChannelType"), TP_IFACE_CHANNEL_TYPE_TEXT)) return FALSE; if (tp_asv_get_uint32 (request_properties, TP_IFACE_CHANNEL ".TargetHandleType", NULL) != TP_HANDLE_TYPE_CONTACT) return FALSE; /* validity already checked by TpBaseConnection */ handle = tp_asv_get_uint32 (request_properties, TP_IFACE_CHANNEL ".TargetHandle", NULL); g_assert (handle != 0); if (tp_channel_manager_asv_has_unknown_properties (request_properties, im_channel_fixed_properties, im_channel_allowed_properties, &error)) goto error; channel = g_hash_table_lookup (self->priv->channels, GUINT_TO_POINTER (handle)); if (channel == NULL) { new_im_channel (self, handle, request_token); return TRUE; } if (require_new) { g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "Already chatting with contact #%u in another channel", handle); goto error; } tp_channel_manager_emit_request_already_satisfied (self, request_token, channel); return TRUE; error: tp_channel_manager_emit_request_failed (self, request_token, error->domain, error->code, error->message); g_error_free (error); return TRUE; } static gboolean gabble_im_factory_create_channel (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties) { GabbleImFactory *self = GABBLE_IM_FACTORY (manager); return gabble_im_factory_requestotron (self, request_token, request_properties, TRUE); } static gboolean gabble_im_factory_request_channel (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties) { GabbleImFactory *self = GABBLE_IM_FACTORY (manager); return gabble_im_factory_requestotron (self, request_token, request_properties, FALSE); } static gboolean gabble_im_factory_ensure_channel (TpChannelManager *manager, gpointer request_token, GHashTable *request_properties) { GabbleImFactory *self = GABBLE_IM_FACTORY (manager); return gabble_im_factory_requestotron (self, request_token, request_properties, FALSE); } static void channel_manager_iface_init (gpointer g_iface, gpointer iface_data) { TpChannelManagerIface *iface = g_iface; iface->foreach_channel = gabble_im_factory_foreach_channel; iface->type_foreach_channel_class = gabble_im_factory_type_foreach_channel_class; iface->create_channel = gabble_im_factory_create_channel; iface->request_channel = gabble_im_factory_request_channel; iface->ensure_channel = gabble_im_factory_ensure_channel; } static void caps_channel_manager_iface_init (gpointer g_iface, gpointer iface_data) { GabbleCapsChannelManagerInterface *iface = g_iface; iface->get_contact_caps = gabble_im_factory_get_contact_caps; } �������������������������telepathy-gabble-0.18.3/src/muc-tube-dbus.h���������������������������������������������������������0000664�0001750�0001750�00000004035�12223562023�021611� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * muc-tube-dbus.h - Header for GabbleMucTubeDBus * Copyright (C) 2012 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_MUC_TUBE_DBUS_H__ #define __GABBLE_MUC_TUBE_DBUS_H__ #include <glib-object.h> #include "tube-dbus.h" G_BEGIN_DECLS typedef struct _GabbleMucTubeDBus GabbleMucTubeDBus; typedef struct _GabbleMucTubeDBusClass GabbleMucTubeDBusClass; struct _GabbleMucTubeDBusClass { GabbleTubeDBusClass parent_class; }; struct _GabbleMucTubeDBus { GabbleTubeDBus parent; }; GType gabble_muc_tube_dbus_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_MUC_TUBE_DBUS \ (gabble_muc_tube_dbus_get_type ()) #define GABBLE_MUC_TUBE_DBUS(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_MUC_TUBE_DBUS, GabbleMucTubeDBus)) #define GABBLE_MUC_TUBE_DBUS_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_MUC_TUBE_DBUS,\ GabbleMucTubeDBusClass)) #define GABBLE_IS_MUC_TUBE_DBUS(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_MUC_TUBE_DBUS)) #define GABBLE_IS_MUC_TUBE_DBUS_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_MUC_TUBE_DBUS)) #define GABBLE_MUC_TUBE_DBUS_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_MUC_TUBE_DBUS,\ GabbleMucTubeDBusClass)) G_END_DECLS #endif /* #ifndef __GABBLE_MUC_TUBE_DBUS_H__ */ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/conn-util.h�������������������������������������������������������������0000644�0001750�0001750�00000002546�11570651566�021067� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * conn-util.h - Header for Gabble connection kitchen-sink code. * Copyright (C) 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GABBLE_CONN_UTIL_H #define GABBLE_CONN_UTIL_H #include <glib.h> #include "connection.h" G_BEGIN_DECLS void conn_util_send_iq_async (GabbleConnection *self, WockyStanza *stanza, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean conn_util_send_iq_finish (GabbleConnection *self, GAsyncResult *result, WockyStanza **response, GError **error); const gchar *conn_util_get_bare_self_jid (GabbleConnection *conn); G_END_DECLS #endif /* GABBLE_CONN_UTIL_H */ ����������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/muc-tube-dbus.c���������������������������������������������������������0000664�0001750�0001750�00000003177�12332440117�021612� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * muc-tube-dbus.c - Source for GabbleMucTubeDBus * Copyright (C) 2012 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "muc-tube-dbus.h" G_DEFINE_TYPE (GabbleMucTubeDBus, gabble_muc_tube_dbus, GABBLE_TYPE_TUBE_DBUS) static GPtrArray * gabble_muc_tube_dbus_get_interfaces (TpBaseChannel *base) { GPtrArray *interfaces; interfaces = TP_BASE_CHANNEL_CLASS ( gabble_muc_tube_dbus_parent_class)->get_interfaces (base); g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_GROUP); return interfaces; } static void gabble_muc_tube_dbus_init (GabbleMucTubeDBus *self) { } static void gabble_muc_tube_dbus_class_init ( GabbleMucTubeDBusClass *gabble_muc_tube_dbus_class) { TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS ( gabble_muc_tube_dbus_class); base_class->get_interfaces = gabble_muc_tube_dbus_get_interfaces; base_class->target_handle_type = TP_HANDLE_TYPE_ROOM; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/roster.c����������������������������������������������������������������0000664�0001750�0001750�00000335266�12332441362�020466� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * roster.c - Source for Gabble roster helper * * Copyright © 2006–2010 Collabora Ltd. * Copyright © 2006–2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "roster.h" #include <string.h> #include <dbus/dbus-glib.h> #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #include <wocky/wocky.h> #define DEBUG_FLAG GABBLE_DEBUG_ROSTER #include "gabble/caps-channel-manager.h" #include "conn-aliasing.h" #include "conn-presence.h" #include "conn-util.h" #include "connection.h" #include "debug.h" #include "namespaces.h" #include "presence-cache.h" #include "util.h" #define GOOGLE_ROSTER_VERSION "2" /* signal enum */ enum { NICKNAMES_UPDATE, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; struct _GabbleRosterPrivate { GabbleConnection *conn; gulong porter_available_id; gulong status_changed_id; GCancellable *cancel_on_disconnect; guint iq_cb; guint presence_cb; GHashTable *items; TpHandleSet *groups; /* set of contacts whose subscription requests will automatically be * accepted during this session */ TpHandleSet *pre_authorized; gboolean received; gboolean dispose_has_run; }; typedef enum { GOOGLE_ITEM_TYPE_INVALID = -1, GOOGLE_ITEM_TYPE_NORMAL = 0, GOOGLE_ITEM_TYPE_BLOCKED, GOOGLE_ITEM_TYPE_HIDDEN, GOOGLE_ITEM_TYPE_PINNED, } GoogleItemType; typedef enum { GABBLE_ROSTER_SUBSCRIPTION_NONE = 0, GABBLE_ROSTER_SUBSCRIPTION_FROM, GABBLE_ROSTER_SUBSCRIPTION_TO, GABBLE_ROSTER_SUBSCRIPTION_BOTH, GABBLE_ROSTER_SUBSCRIPTION_REMOVE, GABBLE_ROSTER_SUBSCRIPTION_INVALID, } GabbleRosterSubscription; typedef struct _GabbleRosterItemEdit GabbleRosterItemEdit; struct _GabbleRosterItemEdit { TpHandleRepoIface *contact_repo; TpHandle handle; /* if TRUE, we must create this roster item, so send the IQ even if we * don't appear to be changing anything */ gboolean create; /* list of reffed GSimpleAsyncResult */ GSList *results; /* if these are ..._INVALID, that means don't edit */ GabbleRosterSubscription new_subscription; GoogleItemType new_google_type; /* owned by the GabbleRosterItemEdit. If NULL, that means don't edit... */ gchar *new_name; /* if TRUE, disregard new_name and remove name='' from the roster item */ gboolean remove_name; TpHandleSet *add_to_groups; TpHandleSet *remove_from_groups; gboolean remove_from_all_other_groups; }; typedef struct _GabbleRosterItem GabbleRosterItem; struct _GabbleRosterItem { GabbleRosterSubscription subscription; gboolean ask_subscribe; GoogleItemType google_type; gchar *name; gchar *alias_for; TpHandleSet *groups; /* if TRUE, an edit attempt is already "in-flight" so we can't send off * edits immediately - instead, store them in unsent_edits */ gboolean edits_in_flight; GabbleRosterItemEdit *unsent_edits; /* Might not match @subscription and @ask_subscribe exactly, in cases where * we're working around server breakage */ TpSubscriptionState subscribe; TpSubscriptionState publish; gchar *publish_request; gboolean stored; gboolean blocked; /* If non-zero, the GSource id for a call to flicker_prevention_timeout. */ guint flicker_prevention_id; }; typedef struct _FlickerPreventionCtx FlickerPreventionCtx; struct _FlickerPreventionCtx { GabbleRoster *roster; TpHandle handle; GabbleRosterItem *item; }; static void roster_item_cancel_flicker_timeout (GabbleRosterItem *item); static void _gabble_roster_item_free (GabbleRosterItem *item); static void item_edit_free (GabbleRosterItemEdit *edits); static void gabble_roster_close_all (GabbleRoster *roster); static void mutable_iface_init (TpMutableContactListInterface *iface); static void blockable_iface_init (TpBlockableContactListInterface *iface); static void contact_groups_iface_init (TpContactGroupListInterface *iface); static void mutable_contact_groups_iface_init ( TpMutableContactGroupListInterface *iface); G_DEFINE_TYPE_WITH_CODE (GabbleRoster, gabble_roster, TP_TYPE_BASE_CONTACT_LIST, G_IMPLEMENT_INTERFACE (TP_TYPE_MUTABLE_CONTACT_LIST, mutable_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_CONTACT_GROUP_LIST, contact_groups_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_MUTABLE_CONTACT_GROUP_LIST, mutable_contact_groups_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_BLOCKABLE_CONTACT_LIST, blockable_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_CAPS_CHANNEL_MANAGER, NULL)) static void gabble_roster_init (GabbleRoster *obj) { GabbleRosterPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, GABBLE_TYPE_ROSTER, GabbleRosterPrivate); obj->priv = priv; priv->items = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) _gabble_roster_item_free); } static void gabble_roster_dispose (GObject *object) { GabbleRoster *self = GABBLE_ROSTER (object); GabbleRosterPrivate *priv = self->priv; if (priv->dispose_has_run) return; DEBUG ("dispose called"); priv->dispose_has_run = TRUE; g_assert (priv->iq_cb == 0); g_assert (priv->presence_cb == 0); gabble_roster_close_all (self); g_assert (priv->groups == NULL); g_assert (priv->pre_authorized == NULL); if (G_OBJECT_CLASS (gabble_roster_parent_class)->dispose) G_OBJECT_CLASS (gabble_roster_parent_class)->dispose (object); } static void gabble_roster_finalize (GObject *object) { GabbleRoster *self = GABBLE_ROSTER (object); GabbleRosterPrivate *priv = self->priv; DEBUG ("called with %p", object); g_hash_table_unref (priv->items); G_OBJECT_CLASS (gabble_roster_parent_class)->finalize (object); } static void _gabble_roster_item_free (GabbleRosterItem *item) { g_assert (item != NULL); tp_handle_set_destroy (item->groups); item_edit_free (item->unsent_edits); g_free (item->name); g_free (item->alias_for); g_free (item->publish_request); roster_item_cancel_flicker_timeout (item); g_slice_free (GabbleRosterItem, item); } static const gchar * _subscription_to_string (GabbleRosterSubscription subscription) { switch (subscription) { case GABBLE_ROSTER_SUBSCRIPTION_NONE: return "none"; case GABBLE_ROSTER_SUBSCRIPTION_FROM: return "from"; case GABBLE_ROSTER_SUBSCRIPTION_TO: return "to"; case GABBLE_ROSTER_SUBSCRIPTION_BOTH: return "both"; case GABBLE_ROSTER_SUBSCRIPTION_REMOVE: return "remove"; default: g_assert_not_reached (); return NULL; } } static GabbleRosterSubscription _parse_item_subscription (WockyNode *item_node) { const gchar *subscription; g_assert (item_node != NULL); subscription = wocky_node_get_attribute (item_node, "subscription"); if (NULL == subscription || 0 == strcmp (subscription, "none")) return GABBLE_ROSTER_SUBSCRIPTION_NONE; else if (0 == strcmp (subscription, "from")) return GABBLE_ROSTER_SUBSCRIPTION_FROM; else if (0 == strcmp (subscription, "to")) return GABBLE_ROSTER_SUBSCRIPTION_TO; else if (0 == strcmp (subscription, "both")) return GABBLE_ROSTER_SUBSCRIPTION_BOTH; else if (0 == strcmp (subscription, "remove")) return GABBLE_ROSTER_SUBSCRIPTION_REMOVE; else { NODE_DEBUG (item_node, "got unexpected subscription value"); return GABBLE_ROSTER_SUBSCRIPTION_NONE; } } static TpHandleSet * _parse_item_groups (WockyNode *item_node, TpBaseConnection *conn) { TpHandleRepoIface *group_repo = tp_base_connection_get_handles ( conn, TP_HANDLE_TYPE_GROUP); TpHandleSet *groups = tp_handle_set_new (group_repo); TpHandle handle; WockyNodeIter i; WockyNode *group_node; wocky_node_iter_init (&i, item_node, "group", NULL); while (wocky_node_iter_next (&i, &group_node)) { const gchar *value = group_node->content; if (NULL == value) continue; handle = tp_handle_ensure (group_repo, value, NULL, NULL); if (!handle) continue; tp_handle_set_add (groups, handle); } return groups; } static const gchar * _google_item_type_to_string (GoogleItemType google_type) { switch (google_type) { case GOOGLE_ITEM_TYPE_NORMAL: return NULL; case GOOGLE_ITEM_TYPE_BLOCKED: return "B"; case GOOGLE_ITEM_TYPE_HIDDEN: return "H"; case GOOGLE_ITEM_TYPE_PINNED: return "P"; case GOOGLE_ITEM_TYPE_INVALID: g_assert_not_reached (); return NULL; } g_assert_not_reached (); return NULL; } static GoogleItemType _parse_google_item_type (WockyNode *item_node) { const gchar *google_type; g_assert (item_node != NULL); google_type = wocky_node_get_attribute_ns (item_node, "t", NS_GOOGLE_ROSTER); if (NULL == google_type) return GOOGLE_ITEM_TYPE_NORMAL; else if (!tp_strdiff (google_type, "B")) return GOOGLE_ITEM_TYPE_BLOCKED; else if (!tp_strdiff (google_type, "H")) return GOOGLE_ITEM_TYPE_HIDDEN; else if (!tp_strdiff (google_type, "P")) return GOOGLE_ITEM_TYPE_PINNED; NODE_DEBUG (item_node, "got unexpected google contact type value"); return GOOGLE_ITEM_TYPE_NORMAL; } static gchar * _extract_google_alias_for (WockyNode *item_node) { return g_strdup (wocky_node_get_attribute_ns (item_node, "alias-for", NS_GOOGLE_ROSTER)); } static gboolean _google_roster_item_should_keep (const gchar *jid, GabbleRosterItem *item) { /* hide hidden items */ if (item->google_type == GOOGLE_ITEM_TYPE_HIDDEN) { DEBUG ("hiding %s: gr:t='H'", jid); return FALSE; } /* allow items that we've requested a subscription from */ if (item->ask_subscribe) return TRUE; if (item->subscription != GABBLE_ROSTER_SUBSCRIPTION_NONE && item->subscription != GABBLE_ROSTER_SUBSCRIPTION_REMOVE) return TRUE; /* discard anything else */ DEBUG ("hiding %s: no subscription", jid); return FALSE; } static GabbleRosterItem * _gabble_roster_item_lookup (GabbleRoster *roster, TpHandle handle) { GabbleRosterPrivate *priv = roster->priv; g_assert (roster != NULL); g_assert (GABBLE_IS_ROSTER (roster)); return g_hash_table_lookup (priv->items, GUINT_TO_POINTER (handle)); } static GabbleRosterItem * _gabble_roster_item_ensure (GabbleRoster *roster, TpHandle handle) { GabbleRosterPrivate *priv = roster->priv; TpHandleRepoIface *group_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_GROUP); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); GabbleRosterItem *item; item = _gabble_roster_item_lookup (roster, handle); g_assert (tp_handle_is_valid (contact_repo, handle, NULL)); if (NULL == item) { GabbleConnectionAliasSource source; gchar *alias = NULL; source = _gabble_connection_get_cached_alias (priv->conn, handle, &alias); g_assert (source < GABBLE_CONNECTION_ALIAS_FROM_ROSTER); if (source <= GABBLE_CONNECTION_ALIAS_FROM_JID) { g_free (alias); alias = NULL; } item = g_slice_new0 (GabbleRosterItem); /* We may want it to be on the roster, but it's not there yet, so the * most accurate description of how to reach this state is "remove". * We'll keep this transient roster item for as long as it has edits * pending, or some other reason to stay around (a pending publish * request, for instance). */ item->subscription = GABBLE_ROSTER_SUBSCRIPTION_REMOVE; item->subscribe = TP_SUBSCRIPTION_STATE_NO; item->publish = TP_SUBSCRIPTION_STATE_NO; item->name = alias; item->groups = tp_handle_set_new (group_repo); g_hash_table_insert (priv->items, GUINT_TO_POINTER (handle), item); } return item; } static gboolean _gabble_roster_item_maybe_remove (GabbleRoster *roster, TpHandle handle) { GabbleRosterPrivate *priv = roster->priv; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); GabbleRosterItem *item; g_assert (roster != NULL); g_assert (GABBLE_IS_ROSTER (roster)); g_assert (tp_handle_is_valid (contact_repo, handle, NULL)); item = _gabble_roster_item_lookup (roster, handle); g_return_val_if_fail (item != NULL, FALSE); /* don't remove items that are really on our server-side roster */ if (item->subscription != GABBLE_ROSTER_SUBSCRIPTION_REMOVE) { DEBUG ("contact#%u is still on the roster", handle); return FALSE; } /* don't remove items that have edits in flight */ if (item->edits_in_flight) { DEBUG ("contact#%u has edits in flight", handle); return FALSE; } /* don't remove transient items that represent publish/subscribe state */ if (item->publish != TP_SUBSCRIPTION_STATE_NO) { DEBUG ("contact#%u has publish=%u", handle, item->publish); return FALSE; } if (item->subscribe != TP_SUBSCRIPTION_STATE_NO) { DEBUG ("contact#%u has subscribe=%u", handle, item->subscribe); return FALSE; } DEBUG ("removing contact#%u", handle); item = NULL; g_hash_table_remove (priv->items, GUINT_TO_POINTER (handle)); return TRUE; } static GabbleRosterItem * _gabble_roster_item_update (GabbleRoster *roster, TpHandle contact_handle, WockyNode *node, gboolean google_roster_mode, gboolean *nickname_updated) { GabbleRosterPrivate *priv = roster->priv; GabbleRosterItem *item; const gchar *ask, *name; TpIntset *new_groups, *added_to, *removed_from, *removed_from2; TpHandleSet *new_groups_handle_set, *old_groups; TpBaseContactList *base = (TpBaseContactList *) roster; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); TpHandleRepoIface *group_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_GROUP); g_assert (roster != NULL); g_assert (GABBLE_IS_ROSTER (roster)); g_assert (tp_handle_is_valid (contact_repo, contact_handle, NULL)); g_assert (node != NULL); item = _gabble_roster_item_ensure (roster, contact_handle); item->subscription = _parse_item_subscription (node); ask = wocky_node_get_attribute (node, "ask"); if (NULL != ask && 0 == strcmp (ask, "subscribe")) item->ask_subscribe = TRUE; else item->ask_subscribe = FALSE; if (google_roster_mode) { item->google_type = _parse_google_item_type (node); g_free (item->alias_for); item->alias_for = _extract_google_alias_for (node); } if (item->subscription == GABBLE_ROSTER_SUBSCRIPTION_REMOVE) name = NULL; else name = wocky_node_get_attribute (node, "name"); if (tp_strdiff (item->name, name)) { g_free (item->name); item->name = g_strdup (name); DEBUG ("name for contact#%u changed to %s", contact_handle, name); *nickname_updated = TRUE; } else { *nickname_updated = FALSE; } new_groups_handle_set = _parse_item_groups (node, (TpBaseConnection *) priv->conn); new_groups = tp_handle_set_peek (new_groups_handle_set); old_groups = tp_handle_set_copy (item->groups); removed_from = tp_intset_difference (tp_handle_set_peek (item->groups), new_groups); added_to = tp_handle_set_update (item->groups, new_groups); removed_from2 = tp_handle_set_difference_update (item->groups, removed_from); if (roster->priv->groups != NULL) { TpIntset *created_groups = tp_handle_set_update (roster->priv->groups, new_groups); /* we don't need to do this work if TpBaseContactList will just be * ignoring it, as it will before we've received the roster */ if (tp_base_contact_list_get_state ((TpBaseContactList *) roster, NULL) == TP_CONTACT_LIST_STATE_SUCCESS && !tp_intset_is_empty (created_groups)) { GPtrArray *strv = g_ptr_array_sized_new (tp_intset_size ( created_groups)); TpIntsetFastIter iter; TpHandle group; tp_intset_fast_iter_init (&iter, created_groups); while (tp_intset_fast_iter_next (&iter, &group)) { const gchar *group_name = tp_handle_inspect (group_repo, group); DEBUG ("Group was just created: #%u '%s'", group, group_name); g_ptr_array_add (strv, (gchar *) group_name); } tp_base_contact_list_groups_created ((TpBaseContactList *) roster, (const gchar * const *) strv->pdata, strv->len); g_ptr_array_unref (strv); } tp_clear_pointer (&created_groups, tp_intset_destroy); } /* We emit one GroupsChanged signal per contact, because that's most natural * for XMPP, where we usually get a roster push for a single contact. * * The exception is when we're receiving our initial roster, but until we do * that we don't need to emit GroupsChanged anyway; TpBaseContactList will * recover state. */ if (tp_base_contact_list_get_state (base, NULL) == TP_CONTACT_LIST_STATE_SUCCESS && (!tp_intset_is_empty (added_to) || !tp_intset_is_empty (removed_from))) { GPtrArray *added_names = g_ptr_array_sized_new (tp_intset_size (added_to)); GPtrArray *removed_names = g_ptr_array_sized_new ( tp_intset_size (removed_from)); TpHandleSet *the_contact = tp_handle_set_new (contact_repo); TpIntsetFastIter iter; TpHandle group; tp_handle_set_add (the_contact, contact_handle); tp_intset_fast_iter_init (&iter, added_to); while (tp_intset_fast_iter_next (&iter, &group)) { const gchar *group_name = tp_handle_inspect (group_repo, group); DEBUG ("Contact #%u added to group #%u '%s'", contact_handle, group, group_name); g_ptr_array_add (added_names, (gchar *) group_name); } tp_intset_fast_iter_init (&iter, removed_from); while (tp_intset_fast_iter_next (&iter, &group)) { const gchar *group_name = tp_handle_inspect (group_repo, group); DEBUG ("Contact #%u removed from group #%u '%s'", contact_handle, group, group_name); g_ptr_array_add (removed_names, (gchar *) group_name); } tp_base_contact_list_groups_changed ((TpBaseContactList *) roster, the_contact, (const gchar * const *) added_names->pdata, added_names->len, (const gchar * const *) removed_names->pdata, removed_names->len); } tp_intset_destroy (added_to); tp_intset_destroy (removed_from); tp_intset_destroy (removed_from2); new_groups = NULL; tp_handle_set_destroy (new_groups_handle_set); tp_handle_set_destroy (old_groups); return item; } #ifdef ENABLE_DEBUG static void _gabble_roster_item_dump_group (guint handle, gpointer user_data) { g_string_append_printf ((GString *) user_data, "group#%u ", handle); } static gchar * _gabble_roster_item_dump (GabbleRosterItem *item) { GString *str; g_assert (item != NULL); str = g_string_new ("subscription: "); g_string_append (str, _subscription_to_string (item->subscription)); if (item->ask_subscribe) g_string_append (str, ", ask: subscribe"); if (item->google_type != GOOGLE_ITEM_TYPE_NORMAL) g_string_append_printf (str, ", google_type: %s", _google_item_type_to_string (item->google_type)); if (item->name) g_string_append_printf (str, ", name: %s", item->name); if (item->groups) { tp_intset_foreach (tp_handle_set_peek (item->groups), _gabble_roster_item_dump_group, str); } return g_string_free (str, FALSE); } #endif /* ENABLE_DEBUG */ static WockyStanza * _gabble_roster_message_new (GabbleRoster *roster, WockyStanzaSubType sub_type, WockyNode **query_return) { GabbleRosterPrivate *priv = roster->priv; WockyStanza *message; WockyNode *query_node; g_assert (roster != NULL); g_assert (GABBLE_IS_ROSTER (roster)); message = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, sub_type, NULL, NULL, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, '*', &query_node, ')', NULL); if (query_return != NULL) *query_return = query_node; if (priv->conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_ROSTER) { GQuark gr = g_quark_from_static_string (NS_GOOGLE_ROSTER); wocky_node_attribute_ns_set_prefix (gr, "gr"); wocky_node_set_attribute_ns (query_node, "ext", GOOGLE_ROSTER_VERSION, NS_GOOGLE_ROSTER); wocky_node_set_attribute_ns (query_node, "include", "all", NS_GOOGLE_ROSTER); } return message; } struct _ItemToMessageContext { TpBaseConnection *conn; WockyNode *item_node; }; static void _gabble_roster_item_put_group_in_message (guint handle, gpointer user_data) { struct _ItemToMessageContext *ctx = (struct _ItemToMessageContext *)user_data; TpHandleRepoIface *group_repo = tp_base_connection_get_handles ( ctx->conn, TP_HANDLE_TYPE_GROUP); const char *name = tp_handle_inspect (group_repo, handle); wocky_node_add_child_with_content (ctx->item_node, "group", name); } /* * _gabble_roster_item_to_message: * @roster: the roster * @item: the state we would like the contact's roster item to have (*not* * the state it currently has!) * @handle: a contact * * Returns: the necessary IQ to change @handle's state to match that of @item */ static WockyStanza * _gabble_roster_item_to_message (GabbleRoster *roster, TpHandle handle, GabbleRosterItem *item) { GabbleRosterPrivate *priv = roster->priv; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); WockyStanza *message; WockyNode *query_node, *item_node; const gchar *jid; struct _ItemToMessageContext ctx = { (TpBaseConnection *) priv->conn, }; g_assert (roster != NULL); g_assert (GABBLE_IS_ROSTER (roster)); g_assert (tp_handle_is_valid (contact_repo, handle, NULL)); g_assert (item != NULL); message = _gabble_roster_message_new (roster, WOCKY_STANZA_SUB_TYPE_SET, &query_node); item_node = wocky_node_add_child (query_node, "item"); ctx.item_node = item_node; jid = tp_handle_inspect (contact_repo, handle); wocky_node_set_attribute (item_node, "jid", jid); if (item->subscription != GABBLE_ROSTER_SUBSCRIPTION_NONE) { const gchar *subscription = _subscription_to_string (item->subscription); wocky_node_set_attribute (item_node, "subscription", subscription); } if (item->subscription == GABBLE_ROSTER_SUBSCRIPTION_REMOVE) goto DONE; if ((priv->conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_ROSTER) && item->google_type != GOOGLE_ITEM_TYPE_NORMAL) { GQuark gr = g_quark_from_static_string (NS_GOOGLE_ROSTER); wocky_node_attribute_ns_set_prefix (gr, "gr"); wocky_node_set_attribute_ns (item_node, "t", _google_item_type_to_string (item->google_type), NS_GOOGLE_ROSTER); } if (item->ask_subscribe) wocky_node_set_attribute (item_node, "ask", "subscribe"); if (item->name) wocky_node_set_attribute (item_node, "name", item->name); if (item->groups) { tp_intset_foreach (tp_handle_set_peek (item->groups), _gabble_roster_item_put_group_in_message, (void *)&ctx); } DONE: return message; } static FlickerPreventionCtx * flicker_prevention_ctx_new (GabbleRoster *roster, TpHandle handle, GabbleRosterItem *item) { FlickerPreventionCtx *ret = g_slice_new (FlickerPreventionCtx); /* Not taking a ref to the roster. The context is owned by the Item (well, by * its timeout) which is owned by the roster. */ ret->roster = roster; /* Not taking a ref to the handle; we borrow the roster's ref, which is * released after the GabbleRosterItem is freed, at which point this context * will be destroyed. */ ret->handle = handle; ret->item = item; return ret; } static void flicker_prevention_ctx_free (gpointer ctx_) { FlickerPreventionCtx *ctx = ctx_; ctx->roster = NULL; ctx->handle = 0; ctx->item = NULL; g_slice_free (FlickerPreventionCtx, ctx); } /* As described in roster/test-google-roster.py, we work around a Google Talk * server bug to avoid contacts flickering off and onto * subscribe:remote-pending when you try to subscribe to someone's presence. * * When we see a roster item with subscription=none/from and ask=subscribe: * * if no call to this function is scheduled, we schedule a call * * if one is already scheduled, we cancel it. * * When we see a roster item with subscription=none/from and no ask=subscribe: * * if a call to this timeout is scheduled, do nothing, in case the contact * flickers back to ask=subscribe before this fires; * * if a call to this timeout is not scheduled, remove the contact from the * subscribe list. * * This way, our subscription being cancelled or our subscription requests * being rescinded will show up on the subscribe list, albeit with a slight lag * in certain situations in case we're just seeing the Google talk server bug. */ static gboolean flicker_prevention_timeout (gpointer ctx_) { FlickerPreventionCtx *ctx = ctx_; GabbleRosterItem *item = ctx->item; DEBUG ("called for %u", ctx->handle); if ((item->subscription == GABBLE_ROSTER_SUBSCRIPTION_REMOVE || item->subscription == GABBLE_ROSTER_SUBSCRIPTION_NONE) && !item->ask_subscribe) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) ctx->roster->priv->conn, TP_HANDLE_TYPE_CONTACT); TpHandleSet *rem = tp_handle_set_new (contact_repo); DEBUG ("removing %u from subscribe", ctx->handle); item->subscribe = TP_SUBSCRIPTION_STATE_NO; tp_handle_set_add (rem, ctx->handle); tp_base_contact_list_contacts_changed ((TpBaseContactList *) ctx->roster, rem, NULL); tp_handle_set_destroy (rem); } else { DEBUG ("subscription=%s and ask_subscribe=%s, nothing to do", _subscription_to_string (item->subscription), item->ask_subscribe ? "true" : "false"); } ctx->item->flicker_prevention_id = 0; return FALSE; } static void roster_item_ensure_flicker_timeout (GabbleRoster *roster, TpHandle handle, GabbleRosterItem *item) { if (item->flicker_prevention_id == 0) { FlickerPreventionCtx *ctx = flicker_prevention_ctx_new (roster, handle, item); item->flicker_prevention_id = g_timeout_add_seconds_full ( G_PRIORITY_DEFAULT, 1, flicker_prevention_timeout, ctx, flicker_prevention_ctx_free); } } static void roster_item_cancel_flicker_timeout (GabbleRosterItem *item) { if (item->flicker_prevention_id != 0) { g_source_remove (item->flicker_prevention_id); item->flicker_prevention_id = 0; } } static gboolean roster_item_set_publish (GabbleRosterItem *item, TpSubscriptionState publish, const gchar *request) { gboolean changed = FALSE; g_assert (publish == TP_SUBSCRIPTION_STATE_ASK || request == NULL); if (item->publish != publish) changed = TRUE; item->publish = publish; if (tp_strdiff (item->publish_request, request)) { changed = TRUE; g_free (item->publish_request); item->publish_request = g_strdup (request); } return changed; } static gboolean roster_item_set_subscribe (GabbleRosterItem *item, TpSubscriptionState subscribe) { if (item->subscribe != subscribe) { item->subscribe = subscribe; return TRUE; } return FALSE; } static gboolean is_google_roster_push ( GabbleRoster *roster, WockyNode *query_node) { if (roster->priv->conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_ROSTER) { const char *gr_ext = wocky_node_get_attribute_ns ( query_node, "ext", NS_GOOGLE_ROSTER); if (!tp_strdiff (gr_ext, GOOGLE_ROSTER_VERSION)) return TRUE; } return FALSE; } /** * validate_roster_item: * @contact_repo: the handle repository for contacts * @item_node: an <item> child of a <query xmlns='jabber:iq:roster'> * @jid_out: location at which to store the roster item's jid, borrowed from * @item_node, if the item is valid. * * Returns: a reference to a handle for the roster item, or 0 if the item seems * to be malformed. */ static TpHandle validate_roster_item ( TpHandleRepoIface *contact_repo, WockyNode *item_node, const gchar **jid_out) { const gchar *jid; TpHandle handle; jid = wocky_node_get_attribute (item_node, "jid"); if (!jid) { NODE_DEBUG (item_node, "item node has no jid, skipping"); return 0; } if (strchr (jid, '/') != NULL) { /* Avoid fd.o #12791 */ NODE_DEBUG (item_node, "item node has resource in jid, skipping"); return 0; } handle = tp_handle_ensure (contact_repo, jid, NULL, NULL); if (handle == 0) { NODE_DEBUG (item_node, "item jid is malformed, skipping"); return 0; } *jid_out = jid; return handle; } /* * process_roster: * @roster: a roster object * @query_node: a <query xmlns='jabber:iq:roster'/> node * * Processes an incoming roster push. */ static void process_roster ( GabbleRoster *roster, WockyNode *query_node) { GabbleRosterPrivate *priv = roster->priv; TpBaseConnection *conn = (TpBaseConnection *) priv->conn; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT); GArray *updated_nicknames = g_array_new (FALSE, FALSE, sizeof (TpHandle)); /* asymmetry is because we don't get locally pending subscription * requests via <roster>, we get it via <presence> */ TpHandleSet *changed = tp_handle_set_new (contact_repo); TpHandleSet *removed = tp_handle_set_new (contact_repo); /* We may not have a deny list */ TpHandleSet *blocking_changed; TpHandleSet *referenced_handles = tp_handle_set_new (contact_repo); gboolean google_roster = is_google_roster_push (roster, query_node); WockyNodeIter j; WockyNode *item_node; if (google_roster) blocking_changed = tp_handle_set_new (contact_repo); else blocking_changed = NULL; /* iterate every <item> sub-node */ wocky_node_iter_init (&j, query_node, "item", NULL); while (wocky_node_iter_next (&j, &item_node)) { const char *jid; TpHandle handle; GabbleRosterItem *item; gboolean nickname_updated; handle = validate_roster_item (contact_repo, item_node, &jid); if (handle == 0) continue; /* transfer ownership of the reference to referenced_handles */ tp_handle_set_add (referenced_handles, handle); item = _gabble_roster_item_update (roster, handle, item_node, google_roster, &nickname_updated); #ifdef ENABLE_DEBUG if (DEBUGGING) { gchar *dump = _gabble_roster_item_dump (item); DEBUG ("jid: %s, %s", jid, dump); g_free (dump); } #endif if (nickname_updated) g_array_append_val (updated_nicknames, handle); /* handle publish list changes */ switch (item->subscription) { case GABBLE_ROSTER_SUBSCRIPTION_FROM: case GABBLE_ROSTER_SUBSCRIPTION_BOTH: if (google_roster && !_google_roster_item_should_keep (jid, item)) { if (roster_item_set_publish (item, TP_SUBSCRIPTION_STATE_NO, NULL)) tp_handle_set_add (changed, handle); } else { if (roster_item_set_publish (item, TP_SUBSCRIPTION_STATE_YES, NULL)) tp_handle_set_add (changed, handle); } break; case GABBLE_ROSTER_SUBSCRIPTION_NONE: case GABBLE_ROSTER_SUBSCRIPTION_TO: case GABBLE_ROSTER_SUBSCRIPTION_REMOVE: /* publish channel is a bit odd, the roster item doesn't tell us * if someone is awaiting our approval - we get this via presence * type=subscribe, so we have to not remove them if they're * already local_pending in our publish channel. NO -> NO is a * no-op, so YES -> NO is the only case left. */ if (item->publish == TP_SUBSCRIPTION_STATE_YES) { tp_handle_set_add (changed, handle); roster_item_set_publish (item, TP_SUBSCRIPTION_STATE_NO, NULL); } break; default: g_assert_not_reached (); } /* handle subscribe list changes */ switch (item->subscription) { case GABBLE_ROSTER_SUBSCRIPTION_TO: case GABBLE_ROSTER_SUBSCRIPTION_BOTH: if (google_roster && !_google_roster_item_should_keep (jid, item)) { if (roster_item_set_subscribe (item, TP_SUBSCRIPTION_STATE_NO)) tp_handle_set_add (changed, handle); } else { if (roster_item_set_subscribe (item, TP_SUBSCRIPTION_STATE_YES)) tp_handle_set_add (changed, handle); } roster_item_cancel_flicker_timeout (item); break; case GABBLE_ROSTER_SUBSCRIPTION_NONE: case GABBLE_ROSTER_SUBSCRIPTION_FROM: if (item->ask_subscribe) { if (item->subscribe == TP_SUBSCRIPTION_STATE_YES) { DEBUG ("not letting gtalk demote member %u to pending", handle); } else { if (item->flicker_prevention_id == 0) roster_item_ensure_flicker_timeout (roster, handle, item); else roster_item_cancel_flicker_timeout (item); if (roster_item_set_subscribe (item, TP_SUBSCRIPTION_STATE_ASK)) tp_handle_set_add (changed, handle); } } else if (item->flicker_prevention_id == 0) { /* We're not expecting this contact's ask=subscribe to * flicker off and on again, so let's remove them immediately. */ if (roster_item_set_subscribe (item, TP_SUBSCRIPTION_STATE_NO)) tp_handle_set_add (changed, handle); } else { DEBUG ("delaying removal of %s from pending", jid); } break; case GABBLE_ROSTER_SUBSCRIPTION_REMOVE: if (roster_item_set_subscribe (item, TP_SUBSCRIPTION_STATE_NO)) tp_handle_set_add (changed, handle); break; default: g_assert_not_reached (); } /* handle stored list changes */ switch (item->subscription) { case GABBLE_ROSTER_SUBSCRIPTION_NONE: case GABBLE_ROSTER_SUBSCRIPTION_TO: case GABBLE_ROSTER_SUBSCRIPTION_FROM: case GABBLE_ROSTER_SUBSCRIPTION_BOTH: if (google_roster && /* Don't hide contacts from stored if they're pending. * This works around two Google Talk issues: * - When you try to subscribe to someone, you get a flickering * ask="subscribe"; * - When somebody tries to subscribe to you, you get a presence * with type="subscribe" followed by a roster update with * subscribe="none". * See test-google-roster.py for more details. */ item->subscribe != TP_SUBSCRIPTION_STATE_ASK && item->publish != TP_SUBSCRIPTION_STATE_ASK && !_google_roster_item_should_keep (jid, item)) { tp_handle_set_remove (changed, handle); tp_handle_set_add (removed, handle); item->stored = FALSE; } else { if (!item->stored) tp_handle_set_add (changed, handle); item->stored = TRUE; } break; case GABBLE_ROSTER_SUBSCRIPTION_REMOVE: tp_handle_set_remove (changed, handle); if (item->stored) tp_handle_set_add (removed, handle); item->stored = FALSE; break; default: g_assert_not_reached (); } /* handle deny list changes */ if (google_roster) { switch (item->subscription) { case GABBLE_ROSTER_SUBSCRIPTION_NONE: case GABBLE_ROSTER_SUBSCRIPTION_TO: case GABBLE_ROSTER_SUBSCRIPTION_FROM: case GABBLE_ROSTER_SUBSCRIPTION_BOTH: if (item->google_type == GOOGLE_ITEM_TYPE_BLOCKED) { if (!item->blocked) tp_handle_set_add (blocking_changed, handle); item->blocked = TRUE; } else { if (item->blocked) tp_handle_set_add (blocking_changed, handle); item->blocked = FALSE; } break; case GABBLE_ROSTER_SUBSCRIPTION_REMOVE: if (item->blocked) tp_handle_set_add (blocking_changed, handle); item->blocked = FALSE; break; default: g_assert_not_reached (); } } _gabble_roster_item_maybe_remove (roster, handle); } if (updated_nicknames->len > 0) g_signal_emit (roster, signals[NICKNAMES_UPDATE], 0, updated_nicknames); tp_base_contact_list_contacts_changed ((TpBaseContactList *) roster, changed, removed); if (google_roster) { tp_base_contact_list_contact_blocking_changed ( (TpBaseContactList *) roster, blocking_changed); tp_handle_set_destroy (blocking_changed); } g_array_unref (updated_nicknames); tp_handle_set_destroy (changed); tp_handle_set_destroy (removed); tp_handle_set_destroy (referenced_handles); } static void roster_item_apply_edits (GabbleRoster *roster, TpHandle contact, GabbleRosterItem *item); /** * got_roster_iq: * * Called by loudmouth when we get an incoming <iq>. This handler * is concerned only with roster queries, and allows other handlers * if queries other than rosters are received. * * Returns: %TRUE if handled, %FALSE to allow more handlers */ static gboolean got_roster_iq (GabbleRoster *roster, WockyStanza *message) { GabbleRosterPrivate *priv = roster->priv; WockyNode *iq_node, *query_node; WockyStanzaSubType sub_type; if (priv->conn == NULL) return FALSE; iq_node = wocky_stanza_get_top_node (message); query_node = wocky_node_get_child_ns (iq_node, "query", WOCKY_XMPP_NS_ROSTER); if (query_node == NULL) return FALSE; wocky_stanza_get_type_info (message, NULL, &sub_type); /* if this is a result, it's from our initial query. if it's a set, * it's a roster push. otherwise, it's not for us. */ if (sub_type != WOCKY_STANZA_SUB_TYPE_RESULT && sub_type != WOCKY_STANZA_SUB_TYPE_SET) { NODE_DEBUG (iq_node, "unhandled roster IQ"); return FALSE; } if (sub_type == WOCKY_STANZA_SUB_TYPE_RESULT && priv->received) { /* <https://bugs.freedesktop.org/show_bug.cgi?id=42186>: some super-buggy * XMPP server running on vk.com sends its reply to our roster query twice. */ DEBUG ("The server sent replied to our roster query more than once! " "Ignoring this reply"); return FALSE; } process_roster (roster, query_node); if (sub_type == WOCKY_STANZA_SUB_TYPE_RESULT) { /* We are handling the response to our initial roster request. */ GHashTableIter iter; gpointer k, v; GArray *members = g_array_sized_new (FALSE, FALSE, sizeof (guint), g_hash_table_size (roster->priv->items)); GSList *edited_items = NULL; /* If we're subscribed to somebody (subscription=to or =both), * and we haven't received presence from them, * we know they're offline. Let clients know that. */ g_hash_table_iter_init (&iter, roster->priv->items); while (g_hash_table_iter_next (&iter, &k, &v)) { GabbleRosterItem *item = v; TpHandle contact = GPOINTER_TO_UINT (k); GabblePresence *presence = gabble_presence_cache_get ( priv->conn->presence_cache, contact); if (item->subscribe == TP_SUBSCRIPTION_STATE_YES && (presence == NULL || presence->status == GABBLE_PRESENCE_UNKNOWN)) { /* The contact might be in the presence cache with UNKNOWN * presence if we've received a message from them before the * roster arrived: an item is forcibly added to stash the * nickname which might have been included in the <message/> in * the presence cache. (This seems like a rather illogical place * to stash such nicknames—if anything, they should live in * GabbleImFactory—but there we go.) * * So if this is the case, we flip their status to OFFLINE. We * don't use gabble_presence_update() because we want to signal * all the unknown→offline transitions together. */ if (presence != NULL) presence->status = GABBLE_PRESENCE_OFFLINE; g_array_append_val (members, contact); } if (item->unsent_edits != NULL) edited_items = g_slist_prepend (edited_items, item); } conn_presence_emit_presence_update (priv->conn, members); g_array_unref (members); /* The roster is now complete and we can emit signals... */ tp_base_contact_list_set_list_received ((TpBaseContactList *) roster); priv->received = TRUE; /* ... and carry out any pending edits */ for (; edited_items != NULL; edited_items = g_slist_delete_link (edited_items, edited_items)) { GabbleRosterItem *item = edited_items->data; roster_item_apply_edits (roster, item->unsent_edits->handle, item); } } else /* WOCKY_STANZA_SUB_TYPE_SET */ { /* acknowledge roster */ _gabble_connection_acknowledge_set_iq (priv->conn, message); } return TRUE; } static gboolean gabble_roster_iq_cb (WockyPorter *porter, WockyStanza *message, gpointer user_data) { GabbleRoster *roster = GABBLE_ROSTER (user_data); return got_roster_iq (roster, message); } static void _gabble_roster_send_presence_ack (GabbleRoster *roster, const gchar *from, WockyStanzaSubType sub_type, gboolean changed) { GabbleRosterPrivate *priv = roster->priv; WockyStanza *reply; if (!changed) { DEBUG ("not sending ack to avoid loop with buggy server"); return; } switch (sub_type) { case WOCKY_STANZA_SUB_TYPE_UNSUBSCRIBE: sub_type = WOCKY_STANZA_SUB_TYPE_UNSUBSCRIBED; break; case WOCKY_STANZA_SUB_TYPE_SUBSCRIBED: sub_type = WOCKY_STANZA_SUB_TYPE_SUBSCRIBE; break; case WOCKY_STANZA_SUB_TYPE_UNSUBSCRIBED: sub_type = WOCKY_STANZA_SUB_TYPE_UNSUBSCRIBE; break; default: g_assert_not_reached (); return; } reply = wocky_stanza_build (WOCKY_STANZA_TYPE_PRESENCE, sub_type, NULL, from, NULL); /* no content */ _gabble_connection_send (priv->conn, reply, NULL); g_object_unref (reply); } static gboolean gabble_roster_handle_subscribed (GabbleRoster *roster, TpHandle handle, const gchar *message, GError **error); static gboolean gabble_roster_presence_cb (WockyPorter *porter, WockyStanza *message, gpointer user_data) { GabbleRoster *roster = GABBLE_ROSTER (user_data); GabbleRosterPrivate *priv = roster->priv; TpBaseConnection *conn = (TpBaseConnection *) priv->conn; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT); WockyNode *pres_node, *child_node; const char *from; WockyStanzaSubType sub_type; TpHandleSet *tmp; TpHandle handle; const gchar *status_message = NULL; gboolean ret; GabbleRosterItem *item; if (priv->conn == NULL) return FALSE; from = wocky_stanza_get_from (message); pres_node = wocky_stanza_get_top_node (message); if (from == NULL) { NODE_DEBUG (pres_node, "presence stanza without from attribute, " "ignoring"); return FALSE; } wocky_stanza_get_type_info (message, NULL, &sub_type); handle = tp_handle_ensure (contact_repo, from, NULL, NULL); if (handle == 0) { NODE_DEBUG (pres_node, "ignoring presence from malformed jid"); return FALSE; } if (handle == tp_base_connection_get_self_handle (conn)) { NODE_DEBUG (pres_node, "ignoring presence from ourselves on another " "resource"); return FALSE; } g_assert (handle != 0); child_node = wocky_node_get_child (pres_node, "status"); if (child_node != NULL) status_message = child_node->content; item = _gabble_roster_item_ensure (roster, handle); switch (sub_type) { case WOCKY_STANZA_SUB_TYPE_SUBSCRIBE: DEBUG ("making %s (handle %u) local pending on the publish channel", from, handle); /* we re-emit ContactsChanged here, even if their state was already ASK * with the same message, because the fact that they've nagged us again * is significant */ roster_item_set_publish (item, TP_SUBSCRIPTION_STATE_ASK, status_message); tmp = tp_handle_set_new (contact_repo); tp_handle_set_add (tmp, handle); tp_base_contact_list_contacts_changed ((TpBaseContactList *) roster, tmp, NULL); if (tp_handle_set_is_member (roster->priv->pre_authorized, handle)) { GError *error = NULL; DEBUG ("%s (handle %u) was pre-authorized, will accept their " "request", from, handle); if (!gabble_roster_handle_subscribed (roster, handle, "", &error)) { DEBUG ("Authorizing pre-authorized request failed: %s", error->message); g_clear_error (&error); } } tp_handle_set_destroy (tmp); ret = TRUE; break; case WOCKY_STANZA_SUB_TYPE_UNSUBSCRIBE: DEBUG ("removing %s (handle %u) from the publish channel", from, handle); if (item->publish == TP_SUBSCRIPTION_STATE_YES || item->publish == TP_SUBSCRIPTION_STATE_ASK) { roster_item_set_publish (item, TP_SUBSCRIPTION_STATE_REMOVED_REMOTELY, NULL); tmp = tp_handle_set_new (contact_repo); tp_handle_set_add (tmp, handle); tp_base_contact_list_contacts_changed ((TpBaseContactList *) roster, tmp, NULL); tp_handle_set_destroy (tmp); _gabble_roster_send_presence_ack (roster, from, sub_type, TRUE); } else { _gabble_roster_send_presence_ack (roster, from, sub_type, FALSE); } ret = TRUE; break; case WOCKY_STANZA_SUB_TYPE_SUBSCRIBED: DEBUG ("adding %s (handle %u) to the subscribe channel", from, handle); if (item->subscribe != TP_SUBSCRIPTION_STATE_YES) { item->subscribe = TP_SUBSCRIPTION_STATE_YES; tmp = tp_handle_set_new (contact_repo); tp_handle_set_add (tmp, handle); tp_base_contact_list_contacts_changed ((TpBaseContactList *) roster, tmp, NULL); tp_handle_set_destroy (tmp); _gabble_roster_send_presence_ack (roster, from, sub_type, TRUE); } else { _gabble_roster_send_presence_ack (roster, from, sub_type, FALSE); } ret = TRUE; break; case WOCKY_STANZA_SUB_TYPE_UNSUBSCRIBED: DEBUG ("removing %s (handle %u) from the subscribe channel", from, handle); if (item->subscribe == TP_SUBSCRIPTION_STATE_YES || item->subscribe == TP_SUBSCRIPTION_STATE_ASK) { item->subscribe = TP_SUBSCRIPTION_STATE_REMOVED_REMOTELY; tmp = tp_handle_set_new (contact_repo); tp_handle_set_add (tmp, handle); tp_base_contact_list_contacts_changed ((TpBaseContactList *) roster, tmp, NULL); tp_handle_set_destroy (tmp); _gabble_roster_send_presence_ack (roster, from, sub_type, TRUE); } else { _gabble_roster_send_presence_ack (roster, from, sub_type, FALSE); } ret = TRUE; break; default: ret = FALSE; } return ret; } static void gabble_roster_close_all (GabbleRoster *self) { GabbleRosterPrivate *priv = self->priv; DEBUG ("closing channels"); if (self->priv->status_changed_id != 0) { g_signal_handler_disconnect (self->priv->conn, self->priv->status_changed_id); self->priv->status_changed_id = 0; } if (self->priv->porter_available_id != 0) { g_signal_handler_disconnect (self->priv->conn, self->priv->porter_available_id); self->priv->porter_available_id = 0; } tp_clear_pointer (&priv->groups, tp_handle_set_destroy); tp_clear_pointer (&priv->pre_authorized, tp_handle_set_destroy); if (self->priv->cancel_on_disconnect != NULL) g_cancellable_cancel (self->priv->cancel_on_disconnect); tp_clear_object (&self->priv->cancel_on_disconnect); if (self->priv->iq_cb != 0) { WockyPorter *porter = gabble_connection_dup_porter (self->priv->conn); DEBUG ("removing callbacks"); g_assert (self->priv->presence_cb != 0); wocky_porter_unregister_handler (porter, self->priv->iq_cb); self->priv->iq_cb = 0; wocky_porter_unregister_handler (porter, self->priv->presence_cb); self->priv->presence_cb = 0; g_object_unref (porter); } } static void roster_received_cb (GObject *source_object, GAsyncResult *result, gpointer weak_ref) { GabbleRoster *self = tp_weak_ref_dup_object (weak_ref); if (self != NULL) { WockyStanza *response; GError *error = NULL; if (conn_util_send_iq_finish ((GabbleConnection *) source_object, result, &response, &error)) { got_roster_iq (self, response); g_object_unref (response); } else { DEBUG ("%s", error->message); g_clear_error (&error); } } tp_clear_object (&self); tp_weak_ref_destroy (weak_ref); } static void gabble_roster_porter_available_cb (GabbleConnection *conn, WockyPorter *porter, GabbleRoster *self) { DEBUG ("adding callbacks"); g_assert (self->priv->iq_cb == 0); g_assert (self->priv->presence_cb == 0); self->priv->iq_cb = wocky_c2s_porter_register_handler_from_server ( WOCKY_C2S_PORTER (porter), WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, gabble_roster_iq_cb, self, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, ')', NULL); self->priv->presence_cb = wocky_porter_register_handler_from_anyone (porter, WOCKY_STANZA_TYPE_PRESENCE, WOCKY_STANZA_SUB_TYPE_NONE, WOCKY_PORTER_HANDLER_PRIORITY_MIN, gabble_roster_presence_cb, self, NULL); } static void connection_status_changed_cb (GabbleConnection *conn, guint status, guint reason, GabbleRoster *self) { switch (status) { case TP_CONNECTION_STATUS_CONNECTED: { WockyStanza *stanza; TpBaseContactList *base = TP_BASE_CONTACT_LIST (self); self->priv->cancel_on_disconnect = g_cancellable_new (); if (tp_base_contact_list_get_download_at_connection (base)) { DEBUG ("requesting roster"); stanza = _gabble_roster_message_new (self, WOCKY_STANZA_SUB_TYPE_GET, NULL); conn_util_send_iq_async (conn, stanza, self->priv->cancel_on_disconnect, roster_received_cb, tp_weak_ref_new (self, NULL, NULL)); g_object_unref (stanza); } else { DEBUG ("don't request the roster because the property" " ContactList.DownloadAtConnection is FALSE"); } } break; case TP_CONNECTION_STATUS_DISCONNECTED: gabble_roster_close_all (self); break; } } static void gabble_roster_constructed (GObject *obj) { GabbleRoster *self = GABBLE_ROSTER (obj); TpBaseContactList *base = TP_BASE_CONTACT_LIST (obj); void (*chain_up)(GObject *) = ((GObjectClass *) gabble_roster_parent_class)->constructed; TpHandleRepoIface *group_repo; TpHandleRepoIface *contact_repo; if (chain_up != NULL) chain_up (obj); /* FIXME: This is not a strong reference because that would create a cycle. * I'd like to have a cyclic reference and break it at disconnect time, * like the contact list example in telepathy-glib does, but we can't do * that because the rest of Gabble assumes that the roster remains useful * until the bitter end (for instance, gabble_im_channel_dispose looks * at the contact's subscription). */ self->priv->conn = GABBLE_CONNECTION (tp_base_contact_list_get_connection ( base, NULL)); g_assert (GABBLE_IS_CONNECTION (self->priv->conn)); group_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_GROUP); contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_CONTACT); self->priv->status_changed_id = g_signal_connect (self->priv->conn, "status-changed", (GCallback) connection_status_changed_cb, obj); self->priv->porter_available_id = g_signal_connect (self->priv->conn, "porter-available", G_CALLBACK (gabble_roster_porter_available_cb), obj); self->priv->groups = tp_handle_set_new (group_repo); self->priv->pre_authorized = tp_handle_set_new (contact_repo); } GabbleRoster * gabble_roster_new (GabbleConnection *conn) { g_return_val_if_fail (conn != NULL, NULL); return g_object_new (GABBLE_TYPE_ROSTER, "connection", conn, NULL); } static GabbleRosterItemEdit * item_edit_new (TpHandleRepoIface *contact_repo, TpHandle handle) { GabbleRosterItemEdit *self = g_slice_new0 (GabbleRosterItemEdit); self->contact_repo = g_object_ref (contact_repo); self->handle = handle; self->new_subscription = GABBLE_ROSTER_SUBSCRIPTION_INVALID; self->new_google_type = GOOGLE_ITEM_TYPE_INVALID; return self; } static void item_edit_free (GabbleRosterItemEdit *edits) { GSList *slist; if (!edits) return; edits->results = g_slist_reverse (edits->results); for (slist = edits->results; slist != NULL; slist = slist->next) { gabble_simple_async_countdown_dec (slist->data); g_object_unref (slist->data); } g_slist_free (edits->results); g_object_unref (edits->contact_repo); tp_clear_pointer (&edits->add_to_groups, tp_handle_set_destroy); tp_clear_pointer (&edits->remove_from_groups, tp_handle_set_destroy); g_free (edits->new_name); g_slice_free (GabbleRosterItemEdit, edits); } static void roster_edited_cb (GObject *, GAsyncResult *, gpointer); static gboolean gabble_roster_handle_subscribed (GabbleRoster *roster, TpHandle handle, const gchar *message, GError **error); /* * Cancel any subscriptions on @item by sending unsubscribe and/or * unsubscribed, as appropriate. */ static gboolean roster_item_cancel_subscriptions ( GabbleRoster *roster, TpHandle contact, GabbleRosterItem *item, GError **error) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) roster->priv->conn, TP_HANDLE_TYPE_CONTACT); const gchar *contact_id = tp_handle_inspect (contact_repo, contact); gboolean ret = TRUE; if (item->subscription == GABBLE_ROSTER_SUBSCRIPTION_FROM || item->subscription == GABBLE_ROSTER_SUBSCRIPTION_BOTH) { DEBUG ("sending unsubscribed"); ret = gabble_connection_send_presence (roster->priv->conn, WOCKY_STANZA_SUB_TYPE_UNSUBSCRIBED, contact_id, NULL, error); } if (ret && (item->subscription == GABBLE_ROSTER_SUBSCRIPTION_TO || item->subscription == GABBLE_ROSTER_SUBSCRIPTION_BOTH)) { DEBUG ("sending unsubscribe"); ret = gabble_connection_send_presence (roster->priv->conn, WOCKY_STANZA_SUB_TYPE_UNSUBSCRIBE, contact_id, NULL, error); } return ret; } /* Apply the unsent edits to the given roster item. * * \param roster The roster * \param contact The contact handle * \param item contact's roster item on roster */ static void roster_item_apply_edits (GabbleRoster *roster, TpHandle contact, GabbleRosterItem *item) { gboolean altered = FALSE; GabbleRosterItem edited_item; TpIntset *intset; GabbleRosterPrivate *priv = roster->priv; TpHandleRepoIface *group_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_GROUP); GabbleRosterItemEdit *edits = item->unsent_edits; WockyStanza *message; if (!priv->received) { DEBUG ("Initial roster has not arrived yet, not editing it"); return; } if (item->edits_in_flight) { DEBUG ("Edits still in flight for contact#%u, not applying more", contact); return; } if (edits == NULL) { DEBUG ("Nothing to do for contact#%u", contact); return; } DEBUG ("Applying edits to contact#%u", contact); memcpy (&edited_item, item, sizeof (GabbleRosterItem)); #ifdef ENABLE_DEBUG if (DEBUGGING) { gchar *dump = _gabble_roster_item_dump (&edited_item); DEBUG ("Before, contact#%u: %s", contact, dump); g_free (dump); } #endif if (edits->create) { DEBUG ("Creating new item"); altered = TRUE; } if (edits->new_google_type != GOOGLE_ITEM_TYPE_INVALID && edits->new_google_type != item->google_type) { DEBUG ("Changing Google type from %d to %d", item->google_type, edits->new_google_type); altered = TRUE; edited_item.google_type = edits->new_google_type; } if (edits->new_subscription != GABBLE_ROSTER_SUBSCRIPTION_INVALID && edits->new_subscription != item->subscription) { /* Here we check the google_type of the *edited* item (as patched in the * block above) to deal correctly with a batch of edits containing both * (un)block and remove. */ if (edits->new_subscription == GABBLE_ROSTER_SUBSCRIPTION_REMOVE && edited_item.google_type == GOOGLE_ITEM_TYPE_BLOCKED) { GError *error = NULL; /* If they're blocked, we can't just remove them from the roster, * because that would unblock them! So instead, we cancel both * subscription directions. */ DEBUG ("contact is blocked; not removing"); if (!roster_item_cancel_subscriptions (roster, contact, item, &error)) { GSList *slist; /* in practice this error will probably be overwritten by one * from the IQ-set later, but if that succeeds for some reason, * we do want to signal error */ for (slist = edits->results; slist != NULL; slist = slist->next) g_simple_async_result_set_from_error (slist->data, error); g_clear_error (&error); } /* deliberately not setting altered: we haven't altered the roster, * as such. */ } else { DEBUG ("Changing subscription from %d to %d", item->subscription, edits->new_subscription); altered = TRUE; edited_item.subscription = edits->new_subscription; } } if (edits->remove_name) { DEBUG ("Removing name='' (was '%s')", item->name); altered = TRUE; edited_item.name = NULL; } else if (edits->new_name != NULL && tp_strdiff (item->name, edits->new_name)) { DEBUG ("Changing name from %s to %s", item->name, edits->new_name); altered = TRUE; edited_item.name = edits->new_name; } if (edits->add_to_groups != NULL || edits->remove_from_groups != NULL || edits->remove_from_all_other_groups) { #ifdef ENABLE_DEBUG if (DEBUGGING) { if (edits->add_to_groups != NULL) { GString *str = g_string_new ("Adding to groups: "); tp_intset_foreach (tp_handle_set_peek (edits->add_to_groups), _gabble_roster_item_dump_group, str); DEBUG("%s", g_string_free (str, FALSE)); } else { DEBUG ("Not adding to any groups"); } if (edits->remove_from_all_other_groups) { DEBUG ("Removing from all other groups"); } if (edits->remove_from_groups != NULL) { GString *str = g_string_new ("Removing from groups: "); tp_intset_foreach (tp_handle_set_peek (edits->remove_from_groups), _gabble_roster_item_dump_group, str); DEBUG("%s", g_string_free (str, FALSE)); } else { DEBUG ("Not removing from any groups"); } } #endif edited_item.groups = tp_handle_set_new (group_repo); if (!edits->remove_from_all_other_groups) { intset = tp_handle_set_update (edited_item.groups, tp_handle_set_peek (item->groups)); tp_intset_destroy (intset); } if (edits->add_to_groups) { intset = tp_handle_set_update (edited_item.groups, tp_handle_set_peek (edits->add_to_groups)); tp_intset_destroy (intset); } if (edits->remove_from_groups) { intset = tp_handle_set_difference_update (edited_item.groups, tp_handle_set_peek (edits->remove_from_groups)); tp_intset_destroy (intset); } if (!tp_intset_is_equal (tp_handle_set_peek (edited_item.groups), tp_handle_set_peek (item->groups))) altered = TRUE; } /* If we changed something about a transient GabbleRosterItem that * wasn't actually on our server-side roster yet, and we weren't actually * trying to delete it, then we need to create it as a side-effect. */ if (altered && edits->new_subscription != GABBLE_ROSTER_SUBSCRIPTION_REMOVE && edited_item.subscription == GABBLE_ROSTER_SUBSCRIPTION_REMOVE) { edits->new_subscription = GABBLE_ROSTER_SUBSCRIPTION_NONE; edited_item.subscription = GABBLE_ROSTER_SUBSCRIPTION_NONE; } #ifdef ENABLE_DEBUG if (DEBUGGING) { gchar *dump = _gabble_roster_item_dump (&edited_item); DEBUG ("After, contact#%u: %s", contact, dump); g_free (dump); } #endif if (!altered) { DEBUG ("Contact#%u not actually changed - nothing to do", contact); item_edit_free (item->unsent_edits); item->unsent_edits = NULL; return; } DEBUG ("Contact#%u did change, sending message", contact); message = _gabble_roster_item_to_message (roster, contact, &edited_item); /* we're sending the unsent edits - on success, roster_edited_cb will own * them */ item->unsent_edits = NULL; item->edits_in_flight = TRUE; conn_util_send_iq_async (priv->conn, message, priv->cancel_on_disconnect, roster_edited_cb, edits); if (edits->new_google_type == GOOGLE_ITEM_TYPE_BLOCKED) gabble_presence_cache_really_remove (priv->conn->presence_cache, contact); if (edited_item.groups != item->groups) { tp_handle_set_destroy (edited_item.groups); } } /* Called when an edit to the roster item has either succeeded or failed. */ static void roster_edited_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { GabbleConnection *conn = GABBLE_CONNECTION (source_object); GabbleRoster *roster = conn->roster; GabbleRosterItemEdit *edit = user_data; GabbleRosterItem *item = NULL; if (edit->results != NULL) { GError *tp_error = NULL; if (!conn_util_send_iq_finish (conn, result, NULL, &tp_error)) { GSList *slist; for (slist = edit->results; slist != NULL; slist = slist->next) g_simple_async_result_set_from_error (slist->data, tp_error); g_clear_error (&tp_error); } } if (roster != NULL) item = _gabble_roster_item_lookup (roster, edit->handle); if (item != NULL) { item->edits_in_flight = FALSE; /* if more edits have been queued since we sent this batch, do them */ roster_item_apply_edits (roster, edit->handle, item); if (item->subscription == GABBLE_ROSTER_SUBSCRIPTION_REMOVE && edit->new_subscription != GABBLE_ROSTER_SUBSCRIPTION_REMOVE) { /* The server claims to have created the item, so we should believe * that the item exists, even though we haven't yet had the roster * push that should confirm it. This will result in * _gabble_roster_item_maybe_remove not removing it. */ item->subscription = edit->new_subscription; } _gabble_roster_item_maybe_remove (roster, edit->handle); } item_edit_free (edit); } static void gabble_roster_handle_set_blocked (GabbleRoster *roster, TpHandle handle, gboolean blocked, GSimpleAsyncResult *result) { GabbleRosterPrivate *priv = roster->priv; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); GabbleRosterItem *item; g_return_if_fail (roster != NULL); g_return_if_fail (GABBLE_IS_ROSTER (roster)); g_return_if_fail (tp_handle_is_valid (contact_repo, handle, NULL)); g_return_if_fail (priv->conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_ROSTER); item = _gabble_roster_item_ensure (roster, handle); if (item->unsent_edits == NULL) item->unsent_edits = item_edit_new (contact_repo, handle); DEBUG ("queue edit to contact#%u - change subscription to blocked=%d", handle, blocked); if (blocked) item->unsent_edits->new_google_type = GOOGLE_ITEM_TYPE_BLOCKED; else item->unsent_edits->new_google_type = GOOGLE_ITEM_TYPE_NORMAL; gabble_simple_async_countdown_inc (result); item->unsent_edits->results = g_slist_prepend ( item->unsent_edits->results, g_object_ref (result)); /* maybe we can apply the edit immediately? */ roster_item_apply_edits (roster, handle, item); } gboolean gabble_roster_handle_has_entry (GabbleRoster *roster, TpHandle handle) { GabbleRosterPrivate *priv = roster->priv; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); GabbleRosterItem *item; g_return_val_if_fail (roster != NULL, FALSE); g_return_val_if_fail (GABBLE_IS_ROSTER (roster), FALSE); g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL), FALSE); item = _gabble_roster_item_lookup (roster, handle); return (NULL != item); } const gchar * gabble_roster_handle_get_name (GabbleRoster *roster, TpHandle handle) { GabbleRosterPrivate *priv = roster->priv; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); GabbleRosterItem *item; g_return_val_if_fail (roster != NULL, NULL); g_return_val_if_fail (GABBLE_IS_ROSTER (roster), NULL); g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL), NULL); item = _gabble_roster_item_lookup (roster, handle); if (NULL == item) return NULL; return item->name; } gboolean gabble_roster_handle_set_name (GabbleRoster *roster, TpHandle handle, const gchar *name, GError **error) { GabbleRosterPrivate *priv = roster->priv; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); GabbleRosterItem *item; g_return_val_if_fail (roster != NULL, FALSE); g_return_val_if_fail (GABBLE_IS_ROSTER (roster), FALSE); g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL), FALSE); item = _gabble_roster_item_ensure (roster, handle); g_return_val_if_fail (item != NULL, FALSE); if (item->unsent_edits == NULL) item->unsent_edits = item_edit_new (contact_repo, handle); tp_clear_pointer (&item->unsent_edits->new_name, g_free); if (name == NULL) { DEBUG ("queue edit to contact#%u - remove name", handle); item->unsent_edits->remove_name = TRUE; } else { DEBUG ("queue edit to contact#%u - set name='%s'", handle, name); item->unsent_edits->remove_name = FALSE; item->unsent_edits->new_name = g_strdup (name); } /* maybe we can apply the edit immediately? */ roster_item_apply_edits (roster, handle, item); /* FIXME: this method should be async so we don't need to assume * success */ return TRUE; } static void gabble_roster_handle_remove (GabbleRoster *roster, TpHandle handle, GSimpleAsyncResult *result) { GabbleRosterPrivate *priv = roster->priv; TpBaseContactList *base = (TpBaseContactList *) roster; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); GabbleRosterItem *item; g_return_if_fail (roster != NULL); g_return_if_fail (GABBLE_IS_ROSTER (roster)); g_return_if_fail (tp_handle_is_valid (contact_repo, handle, NULL)); item = _gabble_roster_item_lookup (roster, handle); if (item == NULL) return; /* If the contact is really stored on the server, deleting their roster item * is sufficient. If they're not, we might have some state resulting from * a publish request or remote removal or something. */ if (item->subscription == GABBLE_ROSTER_SUBSCRIPTION_REMOVE) { /* These will clear a status of REMOVED_REMOTELY or ASK */ roster_item_set_publish (item, TP_SUBSCRIPTION_STATE_NO, NULL); roster_item_set_subscribe (item, TP_SUBSCRIPTION_STATE_NO); /* If there are no edits in-flight, we may just be able to delete the * contact list entry and return early. If there are edits in flight, * we should not return early: the in-flight edit might be * creating the roster item, so we need to queue up a second edit * that will delete it again. */ if (_gabble_roster_item_maybe_remove (roster, handle)) { TpHandleSet *removed = tp_handle_set_new (contact_repo); tp_handle_set_add (removed, handle); tp_base_contact_list_contacts_changed (base, NULL, removed); tp_handle_set_destroy (removed); return; } } if (item->unsent_edits == NULL) item->unsent_edits = item_edit_new (contact_repo, handle); DEBUG ("queue edit to contact#%u - change subscription to REMOVE", handle); item->unsent_edits->new_subscription = GABBLE_ROSTER_SUBSCRIPTION_REMOVE; gabble_simple_async_countdown_inc (result); item->unsent_edits->results = g_slist_prepend ( item->unsent_edits->results, g_object_ref (result)); /* maybe we can apply the edit immediately? */ roster_item_apply_edits (roster, handle, item); } static void gabble_roster_handle_add (GabbleRoster *roster, TpHandle handle, GSimpleAsyncResult *result) { GabbleRosterPrivate *priv = roster->priv; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); GabbleRosterItem *item; gboolean do_add = FALSE; g_return_if_fail (roster != NULL); g_return_if_fail (GABBLE_IS_ROSTER (roster)); g_return_if_fail (tp_handle_is_valid (contact_repo, handle, NULL)); if (!gabble_roster_handle_has_entry (roster, handle)) do_add = TRUE; item = _gabble_roster_item_ensure (roster, handle); if (item->google_type == GOOGLE_ITEM_TYPE_HIDDEN || item->subscription == GABBLE_ROSTER_SUBSCRIPTION_REMOVE) do_add = TRUE; if (!do_add) return; if (item->unsent_edits == NULL) item->unsent_edits = item_edit_new (contact_repo, handle); DEBUG ("queue edit to contact#%u - change google type to NORMAL", handle); item->unsent_edits->create = TRUE; item->unsent_edits->new_google_type = GOOGLE_ITEM_TYPE_NORMAL; if (result != NULL) { gabble_simple_async_countdown_inc (result); item->unsent_edits->results = g_slist_prepend ( item->unsent_edits->results, g_object_ref (result)); } /* maybe we can apply the edit immediately? */ roster_item_apply_edits (roster, handle, item); } static void gabble_roster_handle_add_to_group (GabbleRoster *roster, TpHandle handle, TpHandle group, GSimpleAsyncResult *result) { GabbleRosterPrivate *priv = roster->priv; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); TpHandleRepoIface *group_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_GROUP); GabbleRosterItem *item; g_return_if_fail (roster != NULL); g_return_if_fail (GABBLE_IS_ROSTER (roster)); g_return_if_fail (tp_handle_is_valid (contact_repo, handle, NULL)); g_return_if_fail (tp_handle_is_valid (group_repo, group, NULL)); item = _gabble_roster_item_ensure (roster, handle); if (item->unsent_edits == NULL) item->unsent_edits = item_edit_new (contact_repo, handle); DEBUG ("queue edit to contact#%u - add to group#%u", handle, group); gabble_simple_async_countdown_inc (result); item->unsent_edits->results = g_slist_prepend ( item->unsent_edits->results, g_object_ref (result)); if (!item->unsent_edits->add_to_groups) { item->unsent_edits->add_to_groups = tp_handle_set_new (group_repo); } tp_handle_set_add (item->unsent_edits->add_to_groups, group); if (item->unsent_edits->remove_from_groups) { tp_handle_set_remove (item->unsent_edits->remove_from_groups, group); } /* maybe we can apply the edit immediately? */ roster_item_apply_edits (roster, handle, item); } static void gabble_roster_handle_remove_from_group (GabbleRoster *roster, TpHandle handle, TpHandle group, GSimpleAsyncResult *result) { GabbleRosterPrivate *priv = roster->priv; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT); TpHandleRepoIface *group_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_GROUP); GabbleRosterItem *item; g_return_if_fail (roster != NULL); g_return_if_fail (GABBLE_IS_ROSTER (roster)); g_return_if_fail (tp_handle_is_valid (contact_repo, handle, NULL)); g_return_if_fail (tp_handle_is_valid (group_repo, group, NULL)); item = _gabble_roster_item_ensure (roster, handle); if (item->unsent_edits == NULL) item->unsent_edits = item_edit_new (contact_repo, handle); DEBUG ("queue edit to contact#%u - remove from group#%u", handle, group); gabble_simple_async_countdown_inc (result); item->unsent_edits->results = g_slist_prepend ( item->unsent_edits->results, g_object_ref (result)); if (!item->unsent_edits->remove_from_groups) { item->unsent_edits->remove_from_groups = tp_handle_set_new ( group_repo); } tp_handle_set_add (item->unsent_edits->remove_from_groups, group); if (item->unsent_edits->add_to_groups) { tp_handle_set_remove (item->unsent_edits->add_to_groups, group); } /* maybe we can apply the edit immediately? */ roster_item_apply_edits (roster, handle, item); } static gboolean gabble_roster_handle_subscribed ( GabbleRoster *roster, TpHandle handle, const gchar *message, GError **error) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) roster->priv->conn, TP_HANDLE_TYPE_CONTACT); const gchar *contact_id = tp_handle_inspect (contact_repo, handle); /* send <presence type="subscribed"> */ return gabble_connection_send_presence (roster->priv->conn, WOCKY_STANZA_SUB_TYPE_SUBSCRIBED, contact_id, message, error); } static TpHandleSet * gabble_roster_dup_contacts (TpBaseContactList *base) { GabbleRoster *self = GABBLE_ROSTER (base); TpHandleSet *set; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_CONTACT); GHashTableIter iter; gpointer k, v; set = tp_handle_set_new (contact_repo); g_hash_table_iter_init (&iter, self->priv->items); while (g_hash_table_iter_next (&iter, &k, &v)) { GabbleRosterItem *item = v; /* add all the interesting items */ if (item->stored || item->subscribe != TP_SUBSCRIPTION_STATE_NO || item->publish != TP_SUBSCRIPTION_STATE_NO) tp_handle_set_add (set, GPOINTER_TO_UINT (k)); } return set; } static void gabble_roster_dup_states (TpBaseContactList *base, TpHandle contact, TpSubscriptionState *subscribe, TpSubscriptionState *publish, gchar **publish_request) { GabbleRoster *self = GABBLE_ROSTER (base); GabbleRosterItem *item = _gabble_roster_item_lookup (self, contact); if (item == NULL) { if (subscribe != NULL) *subscribe = TP_SUBSCRIPTION_STATE_NO; if (publish != NULL) *publish = TP_SUBSCRIPTION_STATE_NO; if (publish_request != NULL) *publish_request = NULL; } else { if (subscribe != NULL) *subscribe = item->subscribe; if (publish != NULL) *publish = item->publish; if (publish_request != NULL) *publish_request = g_strdup (item->publish_request); } } typedef struct { GAsyncReadyCallback callback; gpointer user_data; TpHandleSet *contacts; gchar *message; } SubscribeContext; static void gabble_roster_request_subscription_added_cb (GObject *source, GAsyncResult *result, gpointer user_data) { GabbleRoster *self = GABBLE_ROSTER (source); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_CONTACT); SubscribeContext *context = user_data; GError *error = NULL; TpIntsetFastIter iter; TpHandle contact; /* Now that we've added all the contacts, send off all the subscription * requests; stop if we hit an error. */ tp_intset_fast_iter_init (&iter, tp_handle_set_peek (context->contacts)); while (tp_intset_fast_iter_next (&iter, &contact)) { GabbleRosterItem *item = _gabble_roster_item_lookup (self, contact); const gchar *contact_id = tp_handle_inspect (contact_repo, contact); /* Note that we *do* send redundant requests if the contact is in * ask=subscribe state, since those have semantic value - nagging the * contact again. There's no point in requesting subscription if the * contact has already said yes, though. */ if (item != NULL && (item->subscription == GABBLE_ROSTER_SUBSCRIPTION_TO || item->subscription == GABBLE_ROSTER_SUBSCRIPTION_BOTH)) { DEBUG ("Already subscribed to contact#%u '%s', not re-requesting", contact, contact_id); continue; } /* stop trying at the first NetworkError, on the assumption that it'll * be fatal */ if (!gabble_connection_send_presence (self->priv->conn, WOCKY_STANZA_SUB_TYPE_SUBSCRIBE, contact_id, context->message, &error)) break; } gabble_simple_async_succeed_or_fail_in_idle (self, context->callback, context->user_data, NULL, error); g_clear_error (&error); tp_clear_pointer (&context->contacts, tp_handle_set_destroy); g_free (context->message); g_slice_free (SubscribeContext, context); } static void gabble_roster_request_subscription_async (TpBaseContactList *base, TpHandleSet *contacts, const gchar *message, GAsyncReadyCallback callback, gpointer user_data) { GabbleRoster *self = GABBLE_ROSTER (base); SubscribeContext *context = g_slice_new0 (SubscribeContext); GSimpleAsyncResult *result = gabble_simple_async_countdown_new (self, gabble_roster_request_subscription_added_cb, context, gabble_roster_request_subscription_async, 1); TpIntsetFastIter iter; TpHandle contact; /* Before subscribing, add items to the roster * (GTalk depends on this clearing the H flag) */ context->contacts = tp_handle_set_copy (contacts); context->callback = callback; context->user_data = user_data; context->message = g_strdup (message); tp_intset_fast_iter_init (&iter, tp_handle_set_peek (contacts)); while (tp_intset_fast_iter_next (&iter, &contact)) gabble_roster_handle_add (self, contact, result); /* When all of those edits have been applied, the callback will send the * <presence type='subscribe'> requests. */ gabble_simple_async_countdown_dec (result); g_object_unref (result); } static void gabble_roster_authorize_publication_async (TpBaseContactList *base, TpHandleSet *contacts, GAsyncReadyCallback callback, gpointer user_data) { GabbleRoster *self = GABBLE_ROSTER (base); TpIntsetFastIter iter; TpHandle contact; GError *error = NULL; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_CONTACT); tp_intset_fast_iter_init (&iter, tp_handle_set_peek (contacts)); while (tp_intset_fast_iter_next (&iter, &contact)) { GabbleRosterItem *item = _gabble_roster_item_lookup (self, contact); const gchar *contact_id = tp_handle_inspect (contact_repo, contact); if (item == NULL || item->publish == TP_SUBSCRIPTION_STATE_NO || item->publish == TP_SUBSCRIPTION_STATE_REMOVED_REMOTELY) { /* The contact didn't ask for our presence, so we can't usefully * send out <presence type='subscribed'/> (as per RFC3921 §9.2, * our server shouldn't forward it anyway). However, we can * remember this "pre-authorization" and use it later in the * session to auto-approve a subscription request. */ DEBUG ("Noting that contact #%u '%s' is pre-authorized", contact, contact_id); tp_handle_set_add (self->priv->pre_authorized, contact); } else if (item->publish == TP_SUBSCRIPTION_STATE_ASK) { /* stop trying at the first NetworkError, on the assumption that * it'll be fatal */ DEBUG ("Sending <presence type='subscribed'/> to contact#%u '%s'", contact, contact_id); if (!gabble_roster_handle_subscribed (self, contact, "", &error)) break; } else { DEBUG ("contact #%u '%s' already has publish=Y, nothing to do", contact, contact_id); } } gabble_simple_async_succeed_or_fail_in_idle (self, callback, user_data, gabble_roster_authorize_publication_async, error); g_clear_error (&error); } static void gabble_roster_store_contacts_async (TpBaseContactList *base, TpHandleSet *contacts, GAsyncReadyCallback callback, gpointer user_data) { GabbleRoster *self = GABBLE_ROSTER (base); TpIntsetFastIter iter; TpHandle contact; GSimpleAsyncResult *result = gabble_simple_async_countdown_new (self, callback, user_data, gabble_roster_store_contacts_async, 1); tp_intset_fast_iter_init (&iter, tp_handle_set_peek (contacts)); while (tp_intset_fast_iter_next (&iter, &contact)) gabble_roster_handle_add (self, contact, result); gabble_simple_async_countdown_dec (result); g_object_unref (result); } static void gabble_roster_remove_contacts_async (TpBaseContactList *base, TpHandleSet *contacts, GAsyncReadyCallback callback, gpointer user_data) { GabbleRoster *self = GABBLE_ROSTER (base); TpIntsetFastIter iter; TpHandle contact; GSimpleAsyncResult *result = gabble_simple_async_countdown_new (self, callback, user_data, gabble_roster_request_subscription_async, 1); tp_intset_fast_iter_init (&iter, tp_handle_set_peek (contacts)); while (tp_intset_fast_iter_next (&iter, &contact)) gabble_roster_handle_remove (self, contact, result); gabble_simple_async_countdown_dec (result); g_object_unref (result); } static void gabble_roster_unsubscribe_async (TpBaseContactList *base, TpHandleSet *contacts, GAsyncReadyCallback callback, gpointer user_data) { GabbleRoster *self = GABBLE_ROSTER (base); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_CONTACT); TpHandleSet *changed = tp_handle_set_new (contact_repo); TpHandleSet *removed = tp_handle_set_new (contact_repo); TpIntsetFastIter iter; TpHandle contact; GError *error = NULL; tp_intset_fast_iter_init (&iter, tp_handle_set_peek (contacts)); while (tp_intset_fast_iter_next (&iter, &contact)) { const gchar *contact_id = tp_handle_inspect (contact_repo, contact); GabbleRosterItem *item = _gabble_roster_item_lookup (self, contact); if (item == NULL || item->subscribe == TP_SUBSCRIPTION_STATE_NO) { DEBUG ("contact #%u '%s' absent or has subscribe=N, nothing to do", contact, contact_id); } else if (item->subscribe == TP_SUBSCRIPTION_STATE_REMOVED_REMOTELY) { /* just acknowledge remote removal */ DEBUG ("contact #%u '%s' had subscribe=R, moving to publish=N", contact, contact_id); roster_item_set_subscribe (item, TP_SUBSCRIPTION_STATE_NO); if (_gabble_roster_item_maybe_remove (self, contact)) tp_handle_set_add (removed, contact); else tp_handle_set_add (changed, contact); } else { /* Deny a request (if ASK) or revoke previously-granted permission * (if YES). Stop trying at the first NetworkError, on the * assumption that it'll be fatal. Any changes will be signalled when * confirmed by a roster push. */ DEBUG ("Sending <presence type='unsubscribe'/> to contact#%u '%s'", contact, contact_id); if (!gabble_connection_send_presence (self->priv->conn, WOCKY_STANZA_SUB_TYPE_UNSUBSCRIBE, contact_id, "", &error)) break; } } tp_base_contact_list_contacts_changed (base, changed, removed); gabble_simple_async_succeed_or_fail_in_idle (self, callback, user_data, gabble_roster_unsubscribe_async, error); g_clear_error (&error); tp_handle_set_destroy (changed); tp_handle_set_destroy (removed); } static void gabble_roster_unpublish_async (TpBaseContactList *base, TpHandleSet *contacts, GAsyncReadyCallback callback, gpointer user_data) { GabbleRoster *self = GABBLE_ROSTER (base); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_CONTACT); TpHandleSet *changed = tp_handle_set_new (contact_repo); TpHandleSet *removed = tp_handle_set_new (contact_repo); TpIntsetFastIter iter; TpHandle contact; GError *error = NULL; tp_intset_fast_iter_init (&iter, tp_handle_set_peek (contacts)); while (tp_intset_fast_iter_next (&iter, &contact)) { const gchar *contact_id = tp_handle_inspect (contact_repo, contact); GabbleRosterItem *item = _gabble_roster_item_lookup (self, contact); /* If moving from YES to NO, the roster callback will make the change * visible to D-Bus when it actually takes effect. * * If moving from ASK to NO, remove it from publish:local_pending here, * because the roster callback doesn't know if it can * (subscription='none' is used both during request and when it's * rejected). * * If moving from REMOVED_REMOTELY to NO, there's no real change at the * XMPP level, so this is our only chance to make the change visible. */ if (item != NULL && (item->publish == TP_SUBSCRIPTION_STATE_ASK || item->publish == TP_SUBSCRIPTION_STATE_REMOVED_REMOTELY)) { if (item->publish == TP_SUBSCRIPTION_STATE_ASK) DEBUG ("contact #%u '%s' had publish=A, moving to publish=N", contact, contact_id); else DEBUG ("contact #%u '%s' had publish=R, moving to publish=N", contact, contact_id); roster_item_set_publish (item, TP_SUBSCRIPTION_STATE_NO, NULL); if (_gabble_roster_item_maybe_remove (self, contact)) tp_handle_set_add (removed, contact); else tp_handle_set_add (changed, contact); } if (item == NULL || item->publish == TP_SUBSCRIPTION_STATE_NO) { DEBUG ("contact #%u '%s' already has publish=N, nothing to do", contact, contact_id); } else { /* stop trying at the first NetworkError, on the assumption that * it'll be fatal */ DEBUG ("Sending <presence type='unsubscribed'/> to contact#%u '%s'", contact, contact_id); if (!gabble_connection_send_presence (self->priv->conn, WOCKY_STANZA_SUB_TYPE_UNSUBSCRIBED, contact_id, "", &error)) break; } } tp_base_contact_list_contacts_changed (base, changed, removed); gabble_simple_async_succeed_or_fail_in_idle (self, callback, user_data, gabble_roster_unpublish_async, error); g_clear_error (&error); tp_handle_set_destroy (changed); tp_handle_set_destroy (removed); } static void gabble_roster_download_async (TpBaseContactList *base, GAsyncReadyCallback callback, gpointer user_data) { GabbleRoster *self = GABBLE_ROSTER (base); GError *error = NULL; if (!tp_base_contact_list_get_download_at_connection (base)) { WockyStanza *stanza; DEBUG ("Downloading roster requested"); stanza = _gabble_roster_message_new (self, WOCKY_STANZA_SUB_TYPE_GET, NULL); conn_util_send_iq_async (self->priv->conn, stanza, self->priv->cancel_on_disconnect, roster_received_cb, tp_weak_ref_new (self, NULL, NULL)); g_object_unref (stanza); } else { DEBUG ("Downloading roster requested but it is already requested at " "connection. Just do nothing and return."); } gabble_simple_async_succeed_or_fail_in_idle (self, callback, user_data, gabble_roster_download_async, error); g_clear_error (&error); } static TpHandleSet * gabble_roster_dup_blocked_contacts (TpBaseContactList *base) { GabbleRoster *self = GABBLE_ROSTER (base); TpHandleSet *set; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_CONTACT); GHashTableIter iter; gpointer k, v; set = tp_handle_set_new (contact_repo); g_hash_table_iter_init (&iter, self->priv->items); while (g_hash_table_iter_next (&iter, &k, &v)) { GabbleRosterItem *item = v; if (item->blocked) tp_handle_set_add (set, GPOINTER_TO_UINT (k)); } return set; } static gboolean gabble_roster_can_block (TpBaseContactList *base) { GabbleRoster *self = GABBLE_ROSTER (base); return (self->priv->conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_ROSTER) != 0; } static void gabble_roster_block_contacts_async (TpBaseContactList *base, TpHandleSet *contacts, GAsyncReadyCallback callback, gpointer user_data) { GabbleRoster *self = GABBLE_ROSTER (base); TpIntsetFastIter iter; TpHandle contact; GSimpleAsyncResult *result = gabble_simple_async_countdown_new (self, callback, user_data, gabble_roster_request_subscription_async, 1); tp_intset_fast_iter_init (&iter, tp_handle_set_peek (contacts)); while (tp_intset_fast_iter_next (&iter, &contact)) gabble_roster_handle_set_blocked (self, contact, TRUE, result); gabble_simple_async_countdown_dec (result); g_object_unref (result); } static void gabble_roster_unblock_contacts_async (TpBaseContactList *base, TpHandleSet *contacts, GAsyncReadyCallback callback, gpointer user_data) { GabbleRoster *self = GABBLE_ROSTER (base); TpIntsetFastIter iter; TpHandle contact; GSimpleAsyncResult *result = gabble_simple_async_countdown_new (self, callback, user_data, gabble_roster_request_subscription_async, 1); tp_intset_fast_iter_init (&iter, tp_handle_set_peek (contacts)); while (tp_intset_fast_iter_next (&iter, &contact)) gabble_roster_handle_set_blocked (self, contact, FALSE, result); gabble_simple_async_countdown_dec (result); g_object_unref (result); } static GStrv gabble_roster_dup_groups (TpBaseContactList *base) { GabbleRoster *self = GABBLE_ROSTER (base); TpHandleRepoIface *group_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_GROUP); GPtrArray *ret; if (self->priv->groups != NULL) { TpIntsetFastIter iter; TpHandle group; ret = g_ptr_array_sized_new ( tp_handle_set_size (self->priv->groups) + 1); tp_intset_fast_iter_init (&iter, tp_handle_set_peek (self->priv->groups)); while (tp_intset_fast_iter_next (&iter, &group)) { g_ptr_array_add (ret, g_strdup (tp_handle_inspect (group_repo, group))); } } else { ret = g_ptr_array_sized_new (1); } g_ptr_array_add (ret, NULL); return (GStrv) g_ptr_array_free (ret, FALSE); } static GStrv gabble_roster_dup_contact_groups (TpBaseContactList *base, TpHandle contact) { GabbleRoster *self = GABBLE_ROSTER (base); GPtrArray *ret; GabbleRosterItem *item = _gabble_roster_item_lookup (self, contact); if (item != NULL && item->groups != NULL) { TpHandleRepoIface *group_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_GROUP); TpIntsetFastIter iter; TpHandle group; ret = g_ptr_array_sized_new (tp_handle_set_size (item->groups) + 1); tp_intset_fast_iter_init (&iter, tp_handle_set_peek (item->groups)); while (tp_intset_fast_iter_next (&iter, &group)) { g_ptr_array_add (ret, g_strdup (tp_handle_inspect (group_repo, group))); } } else { ret = g_ptr_array_sized_new (1); } g_ptr_array_add (ret, NULL); return (GStrv) g_ptr_array_free (ret, FALSE); } static TpHandleSet * gabble_roster_dup_group_members (TpBaseContactList *base, const gchar *group) { GabbleRoster *self = GABBLE_ROSTER (base); TpHandleSet *set; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_CONTACT); TpHandleRepoIface *group_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_GROUP); TpHandle group_handle; GHashTableIter iter; gpointer k, v; set = tp_handle_set_new (contact_repo); g_hash_table_iter_init (&iter, self->priv->items); group_handle = tp_handle_lookup (group_repo, group, NULL, NULL); if (G_UNLIKELY (group_handle == 0)) { /* clearly it doesn't have members */ return set; } while (g_hash_table_iter_next (&iter, &k, &v)) { GabbleRosterItem *item = v; if (item->groups != NULL && tp_handle_set_is_member (item->groups, group_handle)) tp_handle_set_add (set, GPOINTER_TO_UINT (k)); } return set; } static void gabble_roster_set_contact_groups_async (TpBaseContactList *base, TpHandle contact, const gchar * const *groups, gsize n, GAsyncReadyCallback callback, gpointer user_data) { GabbleRoster *self = GABBLE_ROSTER (base); GabbleRosterItem *item = _gabble_roster_item_ensure (self, contact); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_CONTACT); TpHandleRepoIface *group_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_GROUP); TpHandleSet *groups_set = tp_handle_set_new (group_repo); GPtrArray *groups_created = g_ptr_array_new (); guint i; GSimpleAsyncResult *result = gabble_simple_async_countdown_new (self, callback, user_data, gabble_roster_request_subscription_async, 1); for (i = 0; i < n; i++) { TpHandle group_handle = tp_handle_ensure (group_repo, groups[i], NULL, NULL); if (G_UNLIKELY (group_handle == 0)) continue; tp_handle_set_add (groups_set, group_handle); if (!tp_handle_set_is_member (self->priv->groups, group_handle)) { tp_handle_set_add (self->priv->groups, group_handle); g_ptr_array_add (groups_created, (gchar *) groups[i]); } } if (groups_created->len > 0) { tp_base_contact_list_groups_created (base, (const gchar * const *) groups_created->pdata, groups_created->len); } g_ptr_array_unref (groups_created); if (item->unsent_edits == NULL) item->unsent_edits = item_edit_new (contact_repo, contact); DEBUG ("queue edit to contact#%u - set %" G_GSIZE_FORMAT "contact groups", contact, n); tp_clear_pointer (&item->unsent_edits->add_to_groups, tp_handle_set_destroy); item->unsent_edits->add_to_groups = groups_set; item->unsent_edits->remove_from_all_other_groups = TRUE; tp_clear_pointer (&item->unsent_edits->remove_from_groups, tp_handle_set_destroy); gabble_simple_async_countdown_inc (result); item->unsent_edits->results = g_slist_prepend ( item->unsent_edits->results, g_object_ref (result)); /* maybe we can apply the edit immediately? */ roster_item_apply_edits (self, contact, item); gabble_simple_async_countdown_dec (result); g_object_unref (result); } static void gabble_roster_set_group_members_async (TpBaseContactList *base, const gchar *group, TpHandleSet *contacts, GAsyncReadyCallback callback, gpointer user_data) { GabbleRoster *self = GABBLE_ROSTER (base); TpHandleRepoIface *group_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_GROUP); TpHandle group_handle = tp_handle_ensure (group_repo, group, NULL, NULL); GSimpleAsyncResult *result = gabble_simple_async_countdown_new (self, callback, user_data, gabble_roster_set_group_members_async, 1); GHashTableIter iter; gpointer k; /* You can't add people to an invalid group. */ if (G_UNLIKELY (group_handle == 0)) { g_simple_async_result_set_error (result, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Invalid group name: %s", group); goto finally; } /* we create the group even if @contacts is empty, as the base class * requires */ if (!tp_handle_set_is_member (self->priv->groups, group_handle)) { tp_handle_set_add (self->priv->groups, group_handle); tp_base_contact_list_groups_created (base, &group, 1); } g_hash_table_iter_init (&iter, self->priv->items); while (g_hash_table_iter_next (&iter, &k, NULL)) { TpHandle contact = GPOINTER_TO_UINT (k); if (tp_handle_set_is_member (contacts, contact)) gabble_roster_handle_add_to_group (self, contact, group_handle, result); else gabble_roster_handle_remove_from_group (self, contact, group_handle, result); } finally: gabble_simple_async_countdown_dec (result); g_object_unref (result); } static void gabble_roster_add_to_group_async (TpBaseContactList *base, const gchar *group, TpHandleSet *contacts, GAsyncReadyCallback callback, gpointer user_data) { GabbleRoster *self = GABBLE_ROSTER (base); TpIntsetFastIter iter; TpHandle contact; TpHandleRepoIface *group_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_GROUP); TpHandle group_handle = tp_handle_ensure (group_repo, group, NULL, NULL); GSimpleAsyncResult *result = gabble_simple_async_countdown_new (self, callback, user_data, gabble_roster_add_to_group_async, 1); /* You can't add people to an invalid group. */ if (G_UNLIKELY (group_handle == 0)) { g_simple_async_result_set_error (result, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Invalid group name: %s", group); goto finally; } /* we create the group even if @contacts is empty, as the base class * requires */ if (!tp_handle_set_is_member (self->priv->groups, group_handle)) { tp_handle_set_add (self->priv->groups, group_handle); tp_base_contact_list_groups_created (base, &group, 1); } tp_intset_fast_iter_init (&iter, tp_handle_set_peek (contacts)); while (tp_intset_fast_iter_next (&iter, &contact)) { /* we ignore any NetworkError */ gabble_roster_handle_add_to_group (self, contact, group_handle, result); } finally: gabble_simple_async_countdown_dec (result); g_object_unref (result); } static void gabble_roster_remove_from_group_async (TpBaseContactList *base, const gchar *group, TpHandleSet *contacts, GAsyncReadyCallback callback, gpointer user_data) { GabbleRoster *self = GABBLE_ROSTER (base); TpIntsetFastIter iter; TpHandle contact; TpHandleRepoIface *group_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_GROUP); TpHandle group_handle = tp_handle_lookup (group_repo, group, NULL, NULL); GSimpleAsyncResult *result = gabble_simple_async_countdown_new (self, callback, user_data, gabble_roster_remove_from_group_async, 1); /* if the group didn't exist then we have nothing to do */ if (group_handle == 0) goto finally; tp_intset_fast_iter_init (&iter, tp_handle_set_peek (contacts)); while (tp_intset_fast_iter_next (&iter, &contact)) { gabble_roster_handle_remove_from_group (self, contact, group_handle, result); } finally: gabble_simple_async_countdown_dec (result); g_object_unref (result); } typedef struct { TpHandle group_handle; GAsyncReadyCallback callback; gpointer user_data; TpHandleSet *contacts; } RemoveGroupContext; static void gabble_roster_remove_group_removed_cb (GObject *source, GAsyncResult *result, gpointer user_data) { GabbleRoster *self = GABBLE_ROSTER (source); RemoveGroupContext *context = user_data; if (context->group_handle != 0) { TpHandleRepoIface *group_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_GROUP); const gchar *group = tp_handle_inspect (group_repo, context->group_handle); GHashTableIter iter; gpointer k, v; TpHandle remaining_member = 0; /* Now that we've signalled the group being removed, to be internally * consistent we should believe that the contacts are no longer there; * if a subsequent roster push says they *are* there, we'll just put * them back. * * However, if the group has members that we didn't remove (because * members were added since we sent off the removal requests), we can't * really remove the group. * * We defer the contact removal until after we've signalled group * removal, so that TpBaseContactList can see who used to be in the * group. */ g_hash_table_iter_init (&iter, self->priv->items); while (g_hash_table_iter_next (&iter, &k, &v)) { TpHandle contact = GPOINTER_TO_UINT (k); GabbleRosterItem *item = v; if (item->groups != NULL && tp_handle_set_is_member (item->groups, context->group_handle)) { if (!tp_handle_set_is_member (context->contacts, contact)) remaining_member = contact; } } if (remaining_member == 0) { tp_handle_set_remove (self->priv->groups, context->group_handle); tp_base_contact_list_groups_removed ((TpBaseContactList *) self, &group, 1); g_hash_table_iter_init (&iter, self->priv->items); while (g_hash_table_iter_next (&iter, NULL, &v)) { GabbleRosterItem *item = v; if (item->groups != NULL && tp_handle_set_is_member (item->groups, context->group_handle)) tp_handle_set_remove (item->groups, context->group_handle); } } else { DEBUG ("contact #%u is still a member of group '%s', not removing", remaining_member, group); } } context->callback (source, result, context->user_data); tp_clear_pointer (&context->contacts, tp_handle_set_destroy); g_slice_free (RemoveGroupContext, context); } static void gabble_roster_remove_group_async (TpBaseContactList *base, const gchar *group, GAsyncReadyCallback callback, gpointer user_data) { GabbleRoster *self = GABBLE_ROSTER (base); GHashTableIter iter; gpointer k, v; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_CONTACT); TpHandleRepoIface *group_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_GROUP); GSimpleAsyncResult *result; RemoveGroupContext *context; context = g_slice_new0 (RemoveGroupContext); context->group_handle = tp_handle_lookup (group_repo, group, NULL, NULL); context->callback = callback; context->user_data = user_data; context->contacts = tp_handle_set_new (contact_repo); result = gabble_simple_async_countdown_new (self, gabble_roster_remove_group_removed_cb, context, gabble_roster_remove_group_async, 1); /* if the group didn't exist then we have nothing to do */ if (context->group_handle == 0 || !tp_handle_set_is_member (self->priv->groups, context->group_handle)) goto finally; g_hash_table_iter_init (&iter, self->priv->items); while (g_hash_table_iter_next (&iter, &k, &v)) { TpHandle contact = GPOINTER_TO_UINT (k); GabbleRosterItem *item = v; if (item->groups != NULL && tp_handle_set_is_member (item->groups, context->group_handle)) { tp_handle_set_add (context->contacts, contact); gabble_roster_handle_remove_from_group (self, contact, context->group_handle, result); } } finally: gabble_simple_async_countdown_dec (result); g_object_unref (result); } static void mutable_iface_init (TpMutableContactListInterface *iface) { iface->request_subscription_async = gabble_roster_request_subscription_async; iface->authorize_publication_async = gabble_roster_authorize_publication_async; iface->store_contacts_async = gabble_roster_store_contacts_async; iface->remove_contacts_async = gabble_roster_remove_contacts_async; iface->unsubscribe_async = gabble_roster_unsubscribe_async; iface->unpublish_async = gabble_roster_unpublish_async; /* we use the default _finish functions, which assume a GSimpleAsyncResult */ } static void blockable_iface_init (TpBlockableContactListInterface *iface) { iface->can_block = gabble_roster_can_block; iface->dup_blocked_contacts = gabble_roster_dup_blocked_contacts; iface->block_contacts_async = gabble_roster_block_contacts_async; iface->unblock_contacts_async = gabble_roster_unblock_contacts_async; /* we use the default _finish functions, which assume a GSimpleAsyncResult */ } static void contact_groups_iface_init (TpContactGroupListInterface *iface) { iface->dup_groups = gabble_roster_dup_groups; iface->dup_contact_groups = gabble_roster_dup_contact_groups; iface->dup_group_members = gabble_roster_dup_group_members; } static void mutable_contact_groups_iface_init (TpMutableContactGroupListInterface *iface) { iface->set_contact_groups_async = gabble_roster_set_contact_groups_async; iface->set_group_members_async = gabble_roster_set_group_members_async; iface->add_to_group_async = gabble_roster_add_to_group_async; iface->remove_from_group_async = gabble_roster_remove_from_group_async; iface->remove_group_async = gabble_roster_remove_group_async; /* we use the default _finish functions, which assume a GSimpleAsyncResult */ } static void gabble_roster_class_init (GabbleRosterClass *cls) { GObjectClass *object_class = G_OBJECT_CLASS (cls); TpBaseContactListClass *base_class = TP_BASE_CONTACT_LIST_CLASS (cls); g_type_class_add_private (cls, sizeof (GabbleRosterPrivate)); object_class->constructed = gabble_roster_constructed; object_class->dispose = gabble_roster_dispose; object_class->finalize = gabble_roster_finalize; base_class->dup_states = gabble_roster_dup_states; base_class->dup_contacts = gabble_roster_dup_contacts; base_class->download_async = gabble_roster_download_async; signals[NICKNAMES_UPDATE] = g_signal_new ( "nicknames-update", G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, DBUS_TYPE_G_UINT_ARRAY); } gboolean gabble_roster_handle_sends_presence_to_us (GabbleRoster *self, TpHandle handle) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_CONTACT); GabbleRosterItem *item; g_return_val_if_fail (GABBLE_IS_ROSTER (self), FALSE); g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL), FALSE); item = _gabble_roster_item_lookup (self, handle); if (item == NULL) return FALSE; return (item->subscription == GABBLE_ROSTER_SUBSCRIPTION_TO || item->subscription == GABBLE_ROSTER_SUBSCRIPTION_BOTH); } gboolean gabble_roster_handle_gets_presence_from_us (GabbleRoster *self, TpHandle handle) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) self->priv->conn, TP_HANDLE_TYPE_CONTACT); GabbleRosterItem *item; g_return_val_if_fail (GABBLE_IS_ROSTER (self), FALSE); g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL), FALSE); item = _gabble_roster_item_lookup (self, handle); if (item == NULL) return FALSE; if (item->blocked) return FALSE; return (item->subscription == GABBLE_ROSTER_SUBSCRIPTION_FROM || item->subscription == GABBLE_ROSTER_SUBSCRIPTION_BOTH); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/conn-addressing.h�������������������������������������������������������0000664�0001750�0001750�00000002216�12332440117�022212� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * conn-addressing.h - Header for Gabble connection code handling addressing. * Copyright (C) 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GABBLE_CONN_ADDRESSING_H #define GABBLE_CONN_ADDRESSING_H #include <glib.h> #include "connection.h" G_BEGIN_DECLS void conn_addressing_iface_init (gpointer g_iface, gpointer iface_data); void conn_addressing_init (GabbleConnection *self); G_END_DECLS #endif /* GABBLE_CONN_ADDRESSING_H */ ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/muc-tube-stream.c�������������������������������������������������������0000664�0001750�0001750�00000003235�12332440117�022143� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * muc-tube-stream.c - Source for GabbleMucTubeStream * Copyright (C) 2012 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "muc-tube-stream.h" G_DEFINE_TYPE (GabbleMucTubeStream, gabble_muc_tube_stream, GABBLE_TYPE_TUBE_STREAM) static GPtrArray * gabble_muc_tube_stream_get_interfaces (TpBaseChannel *base) { GPtrArray *interfaces; interfaces = TP_BASE_CHANNEL_CLASS ( gabble_muc_tube_stream_parent_class)->get_interfaces (base); g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_GROUP); return interfaces; } static void gabble_muc_tube_stream_init (GabbleMucTubeStream *self) { } static void gabble_muc_tube_stream_class_init ( GabbleMucTubeStreamClass *gabble_muc_tube_stream_class) { TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS ( gabble_muc_tube_stream_class); base_class->get_interfaces = gabble_muc_tube_stream_get_interfaces; base_class->target_handle_type = TP_HANDLE_TYPE_ROOM; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/search-manager.h��������������������������������������������������������0000644�0001750�0001750�00000004233�11423525546�022022� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * search-manager.h - Header for GabbleSearchManager * Copyright (C) 2009 Collabora Ltd. * Copyright (C) 2009 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __SEARCH_MANAGER_H__ #define __SEARCH_MANAGER_H__ #include <glib-object.h> G_BEGIN_DECLS typedef struct _GabbleSearchManager GabbleSearchManager; typedef struct _GabbleSearchManagerClass GabbleSearchManagerClass; typedef struct _GabbleSearchManagerPrivate GabbleSearchManagerPrivate; struct _GabbleSearchManagerClass { GObjectClass parent_class; }; struct _GabbleSearchManager { GObject parent; GabbleSearchManagerPrivate *priv; }; GType gabble_search_manager_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_SEARCH_MANAGER \ (gabble_search_manager_get_type ()) #define GABBLE_SEARCH_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_SEARCH_MANAGER, GabbleSearchManager)) #define GABBLE_SEARCH_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_SEARCH_MANAGER,\ GabbleSearchManagerClass)) #define GABBLE_IS_SEARCH_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_SEARCH_MANAGER)) #define GABBLE_IS_SEARCH_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_SEARCH_MANAGER)) #define GABBLE_SEARCH_MANAGER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_SEARCH_MANAGER,\ GabbleSearchManagerClass)) G_END_DECLS #endif /* #ifndef __SEARCH_MANAGER_H__ */ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/tube-dbus.h�������������������������������������������������������������0000664�0001750�0001750�00000006241�12332440117�021030� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * tube-dbus.h - Header for GabbleTubeDBus * Copyright (C) 2007 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_TUBE_DBUS_H__ #define __GABBLE_TUBE_DBUS_H__ #include <glib-object.h> #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #include "connection.h" #include "bytestream-iface.h" #include "extensions/extensions.h" #include "muc-channel.h" G_BEGIN_DECLS typedef struct _GabbleTubeDBus GabbleTubeDBus; typedef struct _GabbleTubeDBusClass GabbleTubeDBusClass; typedef struct _GabbleTubeDBusPrivate GabbleTubeDBusPrivate; struct _GabbleTubeDBusClass { TpBaseChannelClass parent_class; TpDBusPropertiesMixinClass dbus_props_class; TpGroupMixinClass group_class; }; struct _GabbleTubeDBus { TpBaseChannel parent; TpGroupMixin group; GabbleTubeDBusPrivate *priv; }; GType gabble_tube_dbus_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_TUBE_DBUS \ (gabble_tube_dbus_get_type ()) #define GABBLE_TUBE_DBUS(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_TUBE_DBUS, GabbleTubeDBus)) #define GABBLE_TUBE_DBUS_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_TUBE_DBUS,\ GabbleTubeDBusClass)) #define GABBLE_IS_TUBE_DBUS(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_TUBE_DBUS)) #define GABBLE_IS_TUBE_DBUS_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_TUBE_DBUS)) #define GABBLE_TUBE_DBUS_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_TUBE_DBUS,\ GabbleTubeDBusClass)) GabbleTubeDBus *gabble_tube_dbus_new (GabbleConnection *conn, TpHandle handle, TpHandleType handle_type, TpHandle self_handle, TpHandle initiator, const gchar *service, GHashTable *parameters, const gchar *stream_id, guint64 id, GabbleBytestreamIface *bytestream, GabbleMucChannel *muc, gboolean requested); gboolean gabble_tube_dbus_add_name (GabbleTubeDBus *tube, TpHandle handle, const gchar *name); gboolean gabble_tube_dbus_remove_name (GabbleTubeDBus *tube, TpHandle handle); gboolean gabble_tube_dbus_handle_in_names (GabbleTubeDBus *tube, TpHandle handle); gboolean gabble_tube_dbus_offer (GabbleTubeDBus *tube, GError **error); const gchar * const * gabble_tube_dbus_channel_get_allowed_properties (void); /* Only extern for the benefit of tests/test-dtube-unique-names.c */ gchar *_gabble_generate_dbus_unique_name (const gchar *nick); G_END_DECLS #endif /* #ifndef __GABBLE_TUBE_DBUS_H__ */ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/conn-contact-info.c�����������������������������������������������������0000664�0001750�0001750�00000111711�12332440117�022447� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * conn-contact-info.c - Gabble connection ContactInfo interface * Copyright (C) 2009-2010 Collabora Ltd. * Copyright (C) 2009-2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "conn-contact-info.h" #include <string.h> #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #include "vcard-manager.h" #define DEBUG_FLAG GABBLE_DEBUG_CONNECTION #include "debug.h" #include "util.h" /* Arbitrary lengths for supported fields' types, increase as necessary when * adding new fields */ #define MAX_TYPES 14 #define MAX_ELEMENTS 8 #define MAX_TYPE_PARAM_LEN 8 /* strlen ("internet") in "type=internet" */ typedef enum { /* in Telepathy: one value per field; in XMPP: one value per field */ FIELD_SIMPLE, /* same as FIELD_SIMPLE but may not be repeated */ FIELD_SIMPLE_ONCE, /* in Telepathy: exactly n_elements values; in XMPP: a child element for * each entry in elements, in that order */ FIELD_STRUCTURED, /* same as FIELD_STRUCTURED but may not be repeated */ FIELD_STRUCTURED_ONCE, /* Special cases: */ /* in Telepathy, one multi-line value; in XMPP, a sequence of <LINE>s */ FIELD_LABEL, /* same as FIELD_STRUCTURED except the last element may repeat n times */ FIELD_ORG, /* a field we intentionally ignore */ FIELD_IGNORED } FieldBehaviour; typedef struct { /* Name in XEP-0054, vcard-temp (upper-case as per the DTD) */ const gchar *xmpp_name; /* Name in Telepathy's vCard representation (lower-case), or NULL * to lower-case the XEP-0054 name automatically */ const gchar *vcard_name; /* General type of field */ FieldBehaviour behaviour; /* Telepathy flags for this field (none are applicable to XMPP yet) */ TpContactInfoFieldFlags tp_flags; /* Valid values for the TYPE type-parameter, in upper case */ const gchar * const types[MAX_TYPES]; /* Child elements for structured/repeating fields, in upper case */ const gchar * const elements[MAX_ELEMENTS]; } VCardField; static VCardField known_fields[] = { /* Simple fields */ { "FN", NULL, FIELD_SIMPLE_ONCE, 0, { NULL }, { NULL } }, { "BDAY", NULL, FIELD_SIMPLE, 0, { NULL }, { NULL } }, { "MAILER", NULL, FIELD_SIMPLE, 0, { NULL }, { NULL } }, { "TZ", NULL, FIELD_SIMPLE, 0, { NULL }, { NULL } }, { "TITLE", NULL, FIELD_SIMPLE, 0, { NULL }, { NULL } }, { "ROLE", NULL, FIELD_SIMPLE, 0, { NULL }, { NULL } }, { "NOTE", NULL, FIELD_SIMPLE, 0, { NULL }, { NULL } }, { "PRODID", NULL, FIELD_SIMPLE, 0, { NULL }, { NULL } }, { "REV", NULL, FIELD_SIMPLE, 0, { NULL }, { NULL } }, { "SORT-STRING", NULL, FIELD_SIMPLE, 0, { NULL }, { NULL } }, { "UID", NULL, FIELD_SIMPLE, 0, { NULL }, { NULL } }, { "URL", NULL, FIELD_SIMPLE, 0, { NULL }, { NULL } }, { "NICKNAME", NULL, FIELD_SIMPLE, 0, { NULL }, { NULL } }, /* Simple fields which are Jabber-specific */ { "JABBERID", "x-jabber", FIELD_SIMPLE, 0, { NULL }, { NULL } }, { "DESC", "x-desc", FIELD_SIMPLE, 0, { NULL }, { NULL } }, /* Structured fields */ { "N", NULL, FIELD_STRUCTURED_ONCE, 0, { NULL }, { "FAMILY", "GIVEN", "MIDDLE", "PREFIX", "SUFFIX", NULL } }, { "ADR", NULL, FIELD_STRUCTURED, 0, { "type=home", "type=work", "type=postal", "type=parcel", "type=dom", "type=intl", "type=pref", NULL }, { "POBOX", "EXTADD", "STREET", "LOCALITY", "REGION", "PCODE", "CTRY", NULL } }, { "GEO", NULL, FIELD_STRUCTURED_ONCE, 0, { NULL }, { "LAT", "LON", NULL } }, /* TEL and EMAIL are like structured fields: they have exactly one child * per occurrence */ { "TEL", NULL, FIELD_STRUCTURED, 0, { "type=home", "type=work", "type=voice", "type=fax", "type=pager", "type=msg", "type=cell", "type=video", "type=bbs", "type=modem", "type=isdn", "type=pcs", "type=pref", NULL }, { "NUMBER", NULL } }, { "EMAIL", NULL, FIELD_STRUCTURED, 0, { "type=home", "type=work", "type=internet", "type=pref", "type=x400", NULL }, { "USERID", NULL } }, /* Special cases with their own semantics */ { "LABEL", NULL, FIELD_LABEL, 0, { "type=home", "type=work", "type=postal", "type=parcel", "type=dom", "type=intl", "type=pref", NULL }, { NULL } }, { "ORG", NULL, FIELD_ORG, 0, { NULL }, { NULL } }, /* Things we don't handle: */ /* PHOTO is handled by the Avatar code */ { "PHOTO", NULL, FIELD_IGNORED }, /* KEY: is Base64 (perhaps? hard to tell from the XEP) */ /* LOGO: can be base64 or a URL */ /* SOUND: can be base64, URL, or phonetic (!) */ /* AGENT: is an embedded vCard (!) */ /* CATEGORIES: same vCard encoding as NICKNAME, but split into KEYWORDs * in XMPP; nobody is likely to use it on XMPP */ /* CLASS: if you're putting non-PUBLIC vCards on your XMPP account, * you're probably Doing It Wrong */ { NULL } }; /* static XML element name => static VCardField */ static GHashTable *known_fields_xmpp = NULL; /* g_strdup'd Telepathy pseudo-vCard element name => static VCardField */ static GHashTable *known_fields_vcard = NULL; /* * _insert_contact_field: * @contact_info: an array of Contact_Info_Field structures * @field_name: a vCard field name in any case combination * @field_params: a list of vCard type-parameters, typically of the form * type=xxx; must be in lower-case if case-insensitive * @field_values: for unstructured fields, an array containing one element; * for structured fields, the elements of the field in order */ static void _insert_contact_field (GPtrArray *contact_info, const gchar *field_name, const gchar * const *field_params, const gchar * const *field_values) { gchar *field_name_down = g_ascii_strdown (field_name, -1); g_ptr_array_add (contact_info, tp_value_array_build (3, G_TYPE_STRING, field_name_down, G_TYPE_STRV, field_params, G_TYPE_STRV, field_values, G_TYPE_INVALID)); g_free (field_name_down); } static void _create_contact_field_extended (GPtrArray *contact_info, WockyNode *node, const gchar * const *supported_types, const gchar * const *mandatory_fields) { guint i; WockyNode *child_node; GPtrArray *field_params = NULL; gchar **field_values = NULL; guint supported_types_size = 0; guint mandatory_fields_size = 0; if (supported_types != NULL) supported_types_size = g_strv_length ((gchar **) supported_types); field_params = g_ptr_array_new (); /* we can simply omit a type if not found */ for (i = 0; i < supported_types_size; ++i) { guint j; gchar child_name[MAX_TYPE_PARAM_LEN + 1] = { '\0' }; /* the +5 is to skip over "type=" - all type-parameters we support have * type=, which is verified in conn_contact_info_build_supported_fields */ for (j = 0; j < MAX_TYPE_PARAM_LEN && supported_types[i][j + 5] != '\0'; j++) { child_name[j] = g_ascii_toupper (supported_types[i][j + 5]); } child_node = wocky_node_get_child (node, child_name); if (child_node != NULL) g_ptr_array_add (field_params, (gchar *) supported_types[i]); } g_ptr_array_add (field_params, NULL); if (mandatory_fields != NULL) { mandatory_fields_size = g_strv_length ((gchar **) mandatory_fields); /* the mandatory field values need to be ordered properly */ field_values = g_new0 (gchar *, mandatory_fields_size + 1); for (i = 0; i < mandatory_fields_size; ++i) { child_node = wocky_node_get_child (node, mandatory_fields[i]); if (child_node != NULL) field_values[i] = child_node->content; else field_values[i] = ""; } } _insert_contact_field (contact_info, node->name, (const gchar * const *) field_params->pdata, (const gchar * const *) field_values); /* The strings in both arrays are borrowed, so we just need to free the * arrays themselves. */ g_ptr_array_unref (field_params); g_free (field_values); } static GPtrArray * _parse_vcard (WockyNode *vcard_node, GError **error) { GPtrArray *contact_info = dbus_g_type_specialized_construct ( TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST); WockyNodeIter i; WockyNode *node; wocky_node_iter_init (&i, vcard_node, NULL, NULL); while (wocky_node_iter_next (&i, &node)) { const VCardField *field = g_hash_table_lookup (known_fields_xmpp, node->name); if (field == NULL) { DEBUG ("unknown vCard node in XML: %s", node->name); continue; } switch (field->behaviour) { case FIELD_SIMPLE: case FIELD_SIMPLE_ONCE: { const gchar * const field_values[2] = { node->content, NULL }; _insert_contact_field (contact_info, node->name, NULL, field_values); } break; case FIELD_STRUCTURED: case FIELD_STRUCTURED_ONCE: { _create_contact_field_extended (contact_info, node, field->types, field->elements); } break; case FIELD_ORG: { WockyNode *orgname = wocky_node_get_child (node, "ORGNAME"); WockyNodeIter orgunit_iter; WockyNode *orgunit; GPtrArray *field_values; const gchar *value; if (orgname == NULL) { DEBUG ("ignoring <ORG> with no <ORGNAME>"); break; } field_values = g_ptr_array_new (); value = orgname->content; if (value == NULL) value = ""; g_ptr_array_add (field_values, (gpointer) value); wocky_node_iter_init (&orgunit_iter, node, "ORGUNIT", NULL); while (wocky_node_iter_next (&orgunit_iter, &orgunit)) { value = orgunit->content; if (value == NULL) value = ""; g_ptr_array_add (field_values, (gpointer) value); } g_ptr_array_add (field_values, NULL); _insert_contact_field (contact_info, "org", NULL, (const gchar * const *) field_values->pdata); g_ptr_array_unref (field_values); } break; case FIELD_LABEL: { WockyNodeIter line_iter; WockyNode *line_node; gchar *field_values[2] = { NULL, NULL }; GString *text = g_string_new (""); wocky_node_iter_init (&line_iter, node, "LINE", NULL); while (wocky_node_iter_next (&line_iter, &line_node)) { const gchar *line = line_node->content; if (line != NULL) { g_string_append (text, line); } if (line == NULL || ! g_str_has_suffix (line, "\n")) { g_string_append_c (text, '\n'); } } field_values[0] = g_string_free (text, FALSE); _insert_contact_field (contact_info, "label", NULL, (const gchar * const *) field_values); g_free (field_values[0]); } break; case FIELD_IGNORED: break; default: g_assert_not_reached (); } } return contact_info; } static void _emit_contact_info_changed (TpSvcConnectionInterfaceContactInfo *iface, TpHandle contact, WockyNode *vcard_node) { GPtrArray *contact_info; contact_info = _parse_vcard (vcard_node, NULL); if (contact_info == NULL) return; tp_svc_connection_interface_contact_info_emit_contact_info_changed ( iface, contact, contact_info); g_boxed_free (TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST, contact_info); } static void _request_vcards_cb (GabbleVCardManager *manager, GabbleVCardManagerRequest *request, TpHandle handle, WockyNode *vcard_node, GError *vcard_error, gpointer user_data) { GabbleConnection *conn = GABBLE_CONNECTION (user_data); g_assert (g_hash_table_lookup (conn->vcard_requests, GUINT_TO_POINTER (handle))); g_hash_table_remove (conn->vcard_requests, GUINT_TO_POINTER (handle)); /* No need to signal ContactInfoChanged here because it'll get done * in vcard_updated. */ } /** * gabble_connection_get_contact_info * * Implements D-Bus method GetContactInfo * on interface org.freedesktop.Telepathy.Connection.Interface.ContactInfo * * @context: The D-Bus invocation context to use to return values * or throw an error. */ static void gabble_connection_get_contact_info ( TpSvcConnectionInterfaceContactInfo *iface, const GArray *contacts, DBusGMethodInvocation *context) { GabbleConnection *self = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) self; TpHandleRepoIface *contacts_repo = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); GError *error = NULL; guint i; GHashTable *ret; TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (TP_BASE_CONNECTION (iface), context); if (!tp_handles_are_valid (contacts_repo, contacts, FALSE, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); return; } ret = dbus_g_type_specialized_construct (TP_HASH_TYPE_CONTACT_INFO_MAP); for (i = 0; i < contacts->len; i++) { WockyNode *vcard_node; TpHandle contact = g_array_index (contacts, TpHandle, i); if (gabble_vcard_manager_get_cached (self->vcard_manager, contact, &vcard_node)) { GPtrArray *contact_info = _parse_vcard (vcard_node, NULL); /* we have the cached vcard but it cannot be parsed, skipping */ if (contact_info == NULL) { DEBUG ("contact %d vcard is cached but cannot be parsed, " "skipping.", contact); continue; } g_hash_table_insert (ret, GUINT_TO_POINTER (contact), contact_info); } } tp_svc_connection_interface_contact_info_return_from_get_contact_info ( context, ret); g_boxed_free (TP_HASH_TYPE_CONTACT_INFO_MAP, ret); } static void _return_from_request_contact_info (WockyNode *vcard_node, GError *vcard_error, DBusGMethodInvocation *context) { GError *error = NULL; GPtrArray *contact_info; if (NULL == vcard_node) { GError tp_error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE, vcard_error->message }; if (vcard_error->domain == WOCKY_XMPP_ERROR) { switch (vcard_error->code) { case WOCKY_XMPP_ERROR_NOT_AUTHORIZED: case WOCKY_XMPP_ERROR_FORBIDDEN: tp_error.code = TP_ERROR_PERMISSION_DENIED; break; case WOCKY_XMPP_ERROR_ITEM_NOT_FOUND: tp_error.code = TP_ERROR_DOES_NOT_EXIST; break; } /* what other mappings make sense here? */ } dbus_g_method_return_error (context, &tp_error); return; } contact_info = _parse_vcard (vcard_node, &error); if (contact_info == NULL) { dbus_g_method_return_error (context, error); g_error_free (error); return; } tp_svc_connection_interface_contact_info_return_from_request_contact_info ( context, contact_info); g_boxed_free (TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST, contact_info); } static void _request_vcard_cb (GabbleVCardManager *self, GabbleVCardManagerRequest *request, TpHandle handle, WockyNode *vcard_node, GError *vcard_error, gpointer user_data) { DBusGMethodInvocation *context = user_data; _return_from_request_contact_info (vcard_node, vcard_error, context); } /** * gabble_connection_refresh_contact_info * * Implements D-Bus method RefreshContactInfo * on interface org.freedesktop.Telepathy.Connection.Interface.ContactInfo * * @context: The D-Bus invocation context to use to return values * or throw an error. */ static void gabble_connection_refresh_contact_info (TpSvcConnectionInterfaceContactInfo *iface, const GArray *contacts, DBusGMethodInvocation *context) { GabbleConnection *self = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) self; TpHandleRepoIface *contacts_repo = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); GError *error = NULL; guint i; TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (TP_BASE_CONNECTION (iface), context); if (!tp_handles_are_valid (contacts_repo, contacts, FALSE, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); return; } for (i = 0; i < contacts->len; i++) { TpHandle contact = g_array_index (contacts, TpHandle, i); if (g_hash_table_lookup (self->vcard_requests, GUINT_TO_POINTER (contact)) == NULL) { GabbleVCardManagerRequest *request; gabble_vcard_manager_invalidate_cache (self->vcard_manager, contact); request = gabble_vcard_manager_request (self->vcard_manager, contact, 0, _request_vcards_cb, self, NULL); g_hash_table_insert (self->vcard_requests, GUINT_TO_POINTER (contact), request); } } tp_svc_connection_interface_contact_info_return_from_refresh_contact_info ( context); } /** * gabble_connection_request_contact_info * * Implements D-Bus method RequestContactInfo * on interface org.freedesktop.Telepathy.Connection.Interface.ContactInfo * * @context: The D-Bus invocation context to use to return values * or throw an error. */ static void gabble_connection_request_contact_info (TpSvcConnectionInterfaceContactInfo *iface, guint contact, DBusGMethodInvocation *context) { GabbleConnection *self = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) self; TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); GError *err = NULL; WockyNode *vcard_node; TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); if (!tp_handle_is_valid (contact_handles, contact, &err)) { dbus_g_method_return_error (context, err); g_error_free (err); return; } if (gabble_vcard_manager_get_cached (self->vcard_manager, contact, &vcard_node)) _return_from_request_contact_info (vcard_node, NULL, context); else gabble_vcard_manager_request (self->vcard_manager, contact, 0, _request_vcard_cb, context, NULL); } static GabbleVCardManagerEditInfo * conn_contact_info_new_edit (const VCardField *field, const gchar *value, const gchar * const *field_params, GError **error) { GabbleVCardManagerEditInfo *edit_info; GabbleVCardEditType edit_type = GABBLE_VCARD_EDIT_APPEND; const gchar * const *p; if (field->behaviour == FIELD_STRUCTURED_ONCE || field->behaviour == FIELD_SIMPLE_ONCE) edit_type = GABBLE_VCARD_EDIT_REPLACE; edit_info = gabble_vcard_manager_edit_info_new (field->xmpp_name, value, edit_type, NULL); if (field_params == NULL) return edit_info; if (field->types[0] == NULL && field_params[0] != NULL) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "%s vCard field expects no type-parameters", field->xmpp_name); gabble_vcard_manager_edit_info_free (edit_info); return NULL; } for (p = field_params; *p != NULL; ++p) { guint i; gboolean used = FALSE; for (i = 0; field->types[i] != NULL; i++) { if (!tp_strdiff (field->types[i], *p)) { /* the +5 is to skip over "type=" - all type-parameters we * support have type=, which is verified in * conn_contact_info_build_supported_fields */ gchar *tmp = g_ascii_strup (field->types[i] + 5, -1); gabble_vcard_manager_edit_info_add_child (edit_info, tmp, NULL); g_free (tmp); used = TRUE; break; } } if (!used) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "%s vCard field does not support type-parameter %s", field->xmpp_name, *p); gabble_vcard_manager_edit_info_free (edit_info); return NULL; } } return edit_info; } static void _set_contact_info_cb (GabbleVCardManager *vcard_manager, GabbleVCardManagerEditRequest *request, WockyNode *vcard_node, GError *vcard_error, gpointer user_data) { DBusGMethodInvocation *context = user_data; if (vcard_node == NULL) { GError tp_error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE, vcard_error->message }; if (vcard_error->domain == WOCKY_XMPP_ERROR) if (vcard_error->code == WOCKY_XMPP_ERROR_BAD_REQUEST || vcard_error->code == WOCKY_XMPP_ERROR_NOT_ACCEPTABLE) tp_error.code = TP_ERROR_INVALID_ARGUMENT; dbus_g_method_return_error (context, &tp_error); } else { tp_svc_connection_interface_contact_info_return_from_set_contact_info ( context); } } /** * gabble_connection_set_contact_info * * Implements D-Bus method SetContactInfo * on interface org.freedesktop.Telepathy.Connection.Interface.ContactInfo * * @context: The D-Bus invocation context to use to return values * or throw an error. */ static void gabble_connection_set_contact_info (TpSvcConnectionInterfaceContactInfo *iface, const GPtrArray *contact_info, DBusGMethodInvocation *context) { GabbleConnection *self = GABBLE_CONNECTION (iface); TpBaseConnection *base = (TpBaseConnection *) self; GList *edits = NULL; guint i; GError *error = NULL; TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); for (i = 0; i < contact_info->len; i++) { GValueArray *structure = g_ptr_array_index (contact_info, i); guint n_field_values = 0; VCardField *field; const gchar *field_name; const gchar * const *field_params; const gchar * const *field_values; GabbleVCardManagerEditInfo *edit_info; field_name = g_value_get_string (structure->values + 0); field_params = g_value_get_boxed (structure->values + 1); field_values = g_value_get_boxed (structure->values + 2); if (field_values != NULL) n_field_values = g_strv_length ((gchar **) field_values); field = g_hash_table_lookup (known_fields_vcard, field_name); if (field == NULL) { g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "unknown vCard field from D-Bus: %s", field_name); goto finally; } if (!gabble_vcard_manager_can_use_vcard_field (self->vcard_manager, field->xmpp_name)) { g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "%s vCard field is not supported by this server", field->xmpp_name); goto finally; } switch (field->behaviour) { case FIELD_SIMPLE: case FIELD_SIMPLE_ONCE: { if (n_field_values != 1) { g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "%s vCard field expects one value but got %u", field->xmpp_name, n_field_values); goto finally; } edit_info = conn_contact_info_new_edit (field, field_values[0], field_params, &error); if (edit_info == NULL) { goto finally; } } break; case FIELD_STRUCTURED: case FIELD_STRUCTURED_ONCE: { guint n_elements = g_strv_length ((gchar **) field->elements); guint j; if (n_field_values != n_elements) { g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "%s vCard field expects %u values but got %u", field->xmpp_name, n_elements, n_field_values); goto finally; } edit_info = conn_contact_info_new_edit (field, NULL, field_params, &error); if (edit_info == NULL) { goto finally; } for (j = 0; j < n_elements; ++j) gabble_vcard_manager_edit_info_add_child (edit_info, field->elements[j], field_values[j]); } break; case FIELD_ORG: { guint j; if (n_field_values == 0) { g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "ORG vCard field expects at least one value but got 0"); goto finally; } edit_info = conn_contact_info_new_edit (field, NULL, field_params, &error); if (edit_info == NULL) { goto finally; } gabble_vcard_manager_edit_info_add_child (edit_info, "ORGNAME", field_values[0]); for (j = 1; field_values[j] != NULL; j++) { gabble_vcard_manager_edit_info_add_child (edit_info, "ORGUNIT", field_values[j]); } } break; case FIELD_LABEL: { gchar **lines; guint j; if (n_field_values != 1) { g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "%s vCard field expects one value but got %u", field->xmpp_name, n_field_values); goto finally; } edit_info = conn_contact_info_new_edit (field, NULL, field_params, &error); if (edit_info == NULL) { goto finally; } lines = g_strsplit (field_values[0], "\n", 0); for (j = 0; lines[j] != NULL; j++) { /* don't emit a trailing empty line if the label ended * with \n */ if (lines[j][0] == '\0' && lines[j + 1] == NULL) continue; gabble_vcard_manager_edit_info_add_child (edit_info, "LINE", lines[j]); } g_strfreev (lines); } break; default: g_assert_not_reached (); } g_assert (edit_info != NULL); edits = g_list_append (edits, edit_info); } finally: if (error != NULL) { DEBUG ("%s", error->message); g_list_foreach (edits, (GFunc) gabble_vcard_manager_edit_info_free, NULL); dbus_g_method_return_error (context, error); g_error_free (error); } else { edits = g_list_prepend (edits, gabble_vcard_manager_edit_info_new (NULL, NULL, GABBLE_VCARD_EDIT_CLEAR, NULL)); /* fix the alias (if missing) afterwards */ edits = g_list_append (edits, gabble_vcard_manager_edit_info_new (NULL, NULL, GABBLE_VCARD_EDIT_SET_ALIAS, NULL)); gabble_vcard_manager_edit (self->vcard_manager, 0, _set_contact_info_cb, context, G_OBJECT (self), edits); } } static void _vcard_updated (GObject *object, TpHandle contact, gpointer user_data) { GabbleConnection *conn = GABBLE_CONNECTION (user_data); WockyNode *vcard_node; if (conn->vcard_manager != NULL && gabble_vcard_manager_get_cached (conn->vcard_manager, contact, &vcard_node)) { _emit_contact_info_changed ( TP_SVC_CONNECTION_INTERFACE_CONTACT_INFO (conn), contact, vcard_node); } } static GPtrArray * conn_contact_info_build_supported_fields (GabbleConnection *conn, GabbleVCardManager *vcard_manager) { GPtrArray *fields = dbus_g_type_specialized_construct ( TP_ARRAY_TYPE_FIELD_SPECS); VCardField *field; for (field = known_fields; field->xmpp_name != NULL; field++) { GValueArray *va; gchar *vcard_name; guint max_times; guint i; TpContactInfoFieldFlags tp_flags = field->tp_flags; if (field->behaviour == FIELD_IGNORED) continue; /* Shorthand to avoid having to put it in the struct initialization: * on XMPP, there is no field that supports arbitrary type-parameters. * Setting Parameters_Mandatory eliminates the special case that an * empty list means arbitrary parameters. */ if (field->types[0] == NULL) { tp_flags |= TP_CONTACT_INFO_FIELD_FLAG_PARAMETERS_EXACT; } #ifndef G_DISABLE_ASSERT for (i = 0; field->types[i] != NULL; i++) { /* All type-parameters XMPP currently supports are of the form type=, * which is assumed in _create_contact_field_extended and * conn_contact_info_edit_add_type_params */ g_assert (g_str_has_prefix (field->types[i], "type=")); g_assert_cmpuint ((guint) strlen (field->types[i]), <=, MAX_TYPE_PARAM_LEN + 5); } #endif if (!gabble_vcard_manager_can_use_vcard_field (vcard_manager, field->xmpp_name)) { continue; } if (field->vcard_name != NULL) vcard_name = g_strdup (field->vcard_name); else vcard_name = g_ascii_strdown (field->xmpp_name, -1); /* On Google, your full name in your VCard *is* your alias, so * SetAliases and setting FN will do exactly the same thing. As * a result, we should set the Overwritten_By_Nickname flag on * the FN VCard field if we're on Google. * * If we're not on Google, your nickname in your VCard is your * alias and the same stuff applies, so we should set the same * flag. * * Doing this means that UIs can omit fields from ContactInfo * dialogs with this flag set so they can just display one * widget to set the alias. It's confusing to have an entry * widget which gets overridden and can screw up your alias * setting anyway. */ if (conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_ROSTER) { if (!tp_strdiff (vcard_name, "fn")) tp_flags |= TP_CONTACT_INFO_FIELD_FLAG_OVERWRITTEN_BY_NICKNAME; } else { if (!tp_strdiff (vcard_name, "nickname")) tp_flags |= TP_CONTACT_INFO_FIELD_FLAG_OVERWRITTEN_BY_NICKNAME; } switch (field->behaviour) { case FIELD_SIMPLE_ONCE: case FIELD_STRUCTURED_ONCE: max_times = 1; break; default: max_times = G_MAXUINT32; } va = tp_value_array_build (4, G_TYPE_STRING, vcard_name, G_TYPE_STRV, field->types, G_TYPE_UINT, tp_flags, G_TYPE_UINT, max_times, G_TYPE_INVALID); g_free (vcard_name); g_ptr_array_add (fields, va); } return fields; } void conn_contact_info_class_init (GabbleConnectionClass *klass) { VCardField *field; /* These are never freed; they're only allocated once per run of Gabble. * The destructor in the latter is only set for completeness */ known_fields_xmpp = g_hash_table_new (g_str_hash, g_str_equal); known_fields_vcard = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); for (field = known_fields; field->xmpp_name != NULL; field++) { gchar *vcard_name; if (field->vcard_name != NULL) vcard_name = g_strdup (field->vcard_name); else vcard_name = g_ascii_strdown (field->xmpp_name, -1); g_hash_table_insert (known_fields_xmpp, (gchar *) field->xmpp_name, field); g_hash_table_insert (known_fields_vcard, vcard_name, field); } } static void conn_contact_info_status_changed_cb (GabbleConnection *conn, guint status, guint reason, gpointer user_data G_GNUC_UNUSED) { if (status != TP_CONNECTION_STATUS_CONNECTED) return; if (gabble_vcard_manager_has_limited_vcard_fields (conn->vcard_manager)) { g_boxed_free (TP_ARRAY_TYPE_FIELD_SPECS, conn->contact_info_fields); conn->contact_info_fields = conn_contact_info_build_supported_fields ( conn, conn->vcard_manager); } } static void conn_contact_info_fill_contact_attributes (GObject *obj, const GArray *contacts, GHashTable *attributes_hash) { guint i; GabbleConnection *self = GABBLE_CONNECTION (obj); g_assert (self->vcard_manager != NULL); for (i = 0; i < contacts->len; i++) { TpHandle contact = g_array_index (contacts, TpHandle, i); WockyNode *vcard_node; if (gabble_vcard_manager_get_cached (self->vcard_manager, contact, &vcard_node)) { GPtrArray *contact_info = _parse_vcard (vcard_node, NULL); if (contact_info != NULL) { GValue *val = tp_g_value_slice_new_take_boxed ( TP_ARRAY_TYPE_CONTACT_INFO_FIELD_LIST, contact_info); tp_contacts_mixin_set_contact_attribute (attributes_hash, contact, TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO"/info", val); } } } } void conn_contact_info_init (GabbleConnection *conn) { g_assert (conn->vcard_manager != NULL); tp_contacts_mixin_add_contact_attributes_iface (G_OBJECT (conn), TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO, conn_contact_info_fill_contact_attributes); conn->contact_info_fields = conn_contact_info_build_supported_fields (conn, conn->vcard_manager); g_signal_connect (conn->vcard_manager, "vcard-update", G_CALLBACK (_vcard_updated), conn); g_signal_connect (conn, "status-changed", G_CALLBACK (conn_contact_info_status_changed_cb), NULL); } void conn_contact_info_finalize (GabbleConnection *conn) { g_boxed_free (TP_ARRAY_TYPE_FIELD_SPECS, conn->contact_info_fields); conn->contact_info_fields = NULL; } void conn_contact_info_iface_init (gpointer g_iface, gpointer iface_data) { TpSvcConnectionInterfaceContactInfoClass *klass = g_iface; #define IMPLEMENT(x) tp_svc_connection_interface_contact_info_implement_##x (\ klass, gabble_connection_##x) IMPLEMENT(get_contact_info); IMPLEMENT(refresh_contact_info); IMPLEMENT(request_contact_info); IMPLEMENT(set_contact_info); #undef IMPLEMENT } static TpDBusPropertiesMixinPropImpl props[] = { { "ContactInfoFlags", GUINT_TO_POINTER (TP_CONTACT_INFO_FLAG_CAN_SET), NULL }, { "SupportedFields", NULL, NULL }, { NULL } }; TpDBusPropertiesMixinPropImpl *conn_contact_info_properties = props; void conn_contact_info_properties_getter (GObject *object, GQuark interface, GQuark name, GValue *value, gpointer getter_data) { GabbleConnection *conn = GABBLE_CONNECTION (object); GQuark q_supported_fields = g_quark_from_static_string ( "SupportedFields"); if (name == q_supported_fields) { g_value_set_boxed (value, conn->contact_info_fields); } else { g_value_set_uint (value, GPOINTER_TO_UINT (getter_data)); } } �������������������������������������������������������telepathy-gabble-0.18.3/src/main.c������������������������������������������������������������������0000664�0001750�0001750�00000002022�11665647177�020075� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * main.c - simple wrapper calling gabble_main * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "gabble.h" int #ifdef BUILD_AS_ANDROID_SERVICE telepathy_gabble_main #else main #endif (int argc, char **argv) { gabble_init (); return gabble_main (argc, argv); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/gabble.h����������������������������������������������������������������0000644�0001750�0001750�00000002147�11423525546�020363� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gabble.h - entry point and utility functions for telepathy-gabble * Copyright (C) 2005 Collabora Ltd. * Copyright (C) 2005 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_H__ #define __GABBLE_H__ #include <dbus/dbus-glib.h> G_BEGIN_DECLS int gabble_main (int argc, char **argv); /* To be used only by tests */ void gabble_init (void); G_END_DECLS #endif /* #ifndef __GABBLE_H__*/ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/jingle-mint.h�����������������������������������������������������������0000664�0001750�0001750�00000004454�12223562023�021357� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * jingle-mint.h - creates and configures a WockyJingleFactory * Copyright ©2012 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GABBLE_JINGLE_MINT_H #define GABBLE_JINGLE_MINT_H #include <glib-object.h> #include "types.h" #include <wocky/wocky.h> typedef struct _GabbleJingleMint GabbleJingleMint; typedef struct _GabbleJingleMintClass GabbleJingleMintClass; typedef struct _GabbleJingleMintPrivate GabbleJingleMintPrivate; struct _GabbleJingleMintClass { GObjectClass parent_class; }; struct _GabbleJingleMint { GObject parent; GabbleJingleMintPrivate *priv; }; GType gabble_jingle_mint_get_type (void); GabbleJingleMint *gabble_jingle_mint_new ( GabbleConnection *connection); WockyJingleFactory *gabble_jingle_mint_get_factory ( GabbleJingleMint *self); WockyJingleInfo *gabble_jingle_mint_get_info ( GabbleJingleMint *self); /* TYPE MACROS */ #define GABBLE_TYPE_JINGLE_MINT \ (gabble_jingle_mint_get_type ()) #define GABBLE_JINGLE_MINT(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_JINGLE_MINT, GabbleJingleMint)) #define GABBLE_JINGLE_MINT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_JINGLE_MINT,\ GabbleJingleMintClass)) #define GABBLE_IS_JINGLE_MINT(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_JINGLE_MINT)) #define GABBLE_IS_JINGLE_MINT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_JINGLE_MINT)) #define GABBLE_JINGLE_MINT_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_JINGLE_MINT, \ GabbleJingleMintClass)) #endif /* GABBLE_JINGLE_MINT_H */ ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/call-channel.h����������������������������������������������������������0000644�0001750�0001750�00000004241�11423525545�021464� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gabble-call-channel.h - Header for GabbleCallChannel * Copyright (C) 2009 Collabora Ltd. * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_CALL_CHANNEL_H__ #define __GABBLE_CALL_CHANNEL_H__ #include <glib-object.h> #include "base-call-channel.h" G_BEGIN_DECLS typedef struct _GabbleCallChannel GabbleCallChannel; typedef struct _GabbleCallChannelPrivate GabbleCallChannelPrivate; typedef struct _GabbleCallChannelClass GabbleCallChannelClass; struct _GabbleCallChannelClass { GabbleBaseCallChannelClass parent_class; }; struct _GabbleCallChannel { GabbleBaseCallChannel parent; GabbleCallChannelPrivate *priv; }; GType gabble_call_channel_get_type (void); /* TYPE MACROS */ #define GABBLE_TYPE_CALL_CHANNEL \ (gabble_call_channel_get_type ()) #define GABBLE_CALL_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ GABBLE_TYPE_CALL_CHANNEL, GabbleCallChannel)) #define GABBLE_CALL_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), \ GABBLE_TYPE_CALL_CHANNEL, GabbleCallChannelClass)) #define GABBLE_IS_CALL_CHANNEL(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_CALL_CHANNEL)) #define GABBLE_IS_CALL_CHANNEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_CALL_CHANNEL)) #define GABBLE_CALL_CHANNEL_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ GABBLE_TYPE_CALL_CHANNEL, GabbleCallChannelClass)) G_END_DECLS #endif /* #ifndef __GABBLE_CALL_CHANNEL_H__*/ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/vcard-manager.c���������������������������������������������������������0000664�0001750�0001750�00000147154�12332441362�021654� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * vcard-manager.c - Source for Gabble vCard lookup helper * * Copyright (C) 2007-2010 Collabora Ltd. * Copyright (C) 2006-2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "vcard-manager.h" #include <string.h> #include <telepathy-glib/telepathy-glib.h> #include <wocky/wocky.h> #define DEBUG_FLAG GABBLE_DEBUG_VCARD #include "conn-aliasing.h" #include "conn-contact-info.h" #include "connection.h" #include "debug.h" #include "namespaces.h" #include "request-pipeline.h" #include "util.h" static guint default_request_timeout = 180; #define VCARD_CACHE_ENTRY_TTL 60 /* When the server reply with XMPP_ERROR_RESOURCE_CONSTRAINT, wait * request_wait_delay seconds before allowing a vCard request to be sent to * the same recipient */ static guint request_wait_delay = 5 * 60; static const gchar *NO_ALIAS = "none"; struct _GabbleVCardManagerEditInfo { /* name of element to edit */ gchar *element_name; /* If REPLACE, the first element with this name (if any) will be updated; * if APPEND, an element with this name will be added; * if DELETE, all elements with this name will be removed; * if CLEAR, everything except PHOTO and NICKNAME will be deleted, in * preparation for a SetContactInfo operation * if SET_ALIAS and new_alias is NULL, set the best alias we have * as the NICKNAME or FN (as appropriate) if that field doesn't already * have a value * if SET_ALIAS and new_alias is non-NULL, set that * as the NICKNAME or FN (as appropriate), overriding anything already * there */ GabbleVCardEditType edit_type; /* the element to fill in, if edit_type is REPLACE or APPEND. */ WockyNodeTree *element; /* only meaningful if edit_type is SET_ALIAS; see above. */ gchar *new_alias; }; /* signal enum */ enum { NICKNAME_UPDATE, VCARD_UPDATE, GOT_SELF_INITIAL_AVATAR, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; /* Properties */ enum { PROP_CONNECTION = 1, PROP_HAVE_SELF_AVATAR, LAST_PROPERTY }; G_DEFINE_TYPE(GabbleVCardManager, gabble_vcard_manager, G_TYPE_OBJECT); typedef struct _GabbleVCardCacheEntry GabbleVCardCacheEntry; struct _GabbleVCardManagerPrivate { gboolean dispose_has_run; GabbleConnection *connection; /* TpHandle borrowed from the entry => owned (GabbleVCardCacheEntry *) */ GHashTable *cache; /* Those (GabbleVCardCacheEntry *) s that have not expired, ordered by * increasing expiry time; borrowed from @cache */ TpHeap *timed_cache; /* Timer which runs out when the first item in the @timed_cache expires */ guint cache_timer; /* Things to do with my own vCard, which is somewhat special - mainly because * we can edit it. There's only one self_handle, so there's no point * bloating every cache entry with these fields. */ gboolean have_self_avatar; /* list of pending edits (GabbleVCardManagerEditInfo structures) */ GList *edits; /* Contains RequestPipelineItem for our SET vCard request, or NULL if we * don't have SET request in the pipeline already. At most one SET request * can be in pipeline at any given time. */ GabbleRequestPipelineItem *edit_pipeline_item; /* List of all pending edit requests that we got. */ GList *edit_requests; /* Patched vCard that we sent to the server to update, but haven't * got confirmation yet. We don't want to store it in cache (visible * to others) before we're sure the server accepts it. */ WockyNodeTree *patched_vcard; }; struct _GabbleVCardManagerRequest { GabbleVCardManager *manager; GabbleVCardCacheEntry *entry; guint timer_id; guint timeout; GabbleVCardManagerCb callback; gpointer user_data; GObject *bound_object; }; struct _GabbleVCardManagerEditRequest { GabbleVCardManager *manager; GabbleVCardManagerEditCb callback; gpointer user_data; GObject *bound_object; /* Set if we have already patched vCard with data from this request, * and sent a SET request to the server to replace the vCard. */ gboolean set_in_pipeline; }; /* An entry in the vCard cache. These exist only as long as: * * 1) the cached message which has not yet expired; and/or * 2) a network request is in the pipeline; and/or * 3) there are requests pending. */ struct _GabbleVCardCacheEntry { /* Parent object */ GabbleVCardManager *manager; /* Referenced handle */ TpHandle handle; /* Pipeline item for our <iq type="get"> if one is in progress */ GabbleRequestPipelineItem *pipeline_item; /* List of (GabbleVCardManagerRequest *) borrowed from priv->requests */ GSList *pending_requests; /* When requests for this entry receive an error of type "wait", we suspend * further requests and retry again after request_wait_delay seconds. * 0 if not suspended. */ guint suspended_timer_id; /* VCard node for this entry (owned reference), or NULL if there's no node */ WockyNodeTree *vcard_node; /* If @vcard_node is not NULL, the time the message will expire */ time_t expires; }; GQuark gabble_vcard_manager_error_quark (void) { static GQuark quark = 0; if (!quark) quark = g_quark_from_static_string ("gabble-vcard-manager-error"); return quark; } GQuark gabble_vcard_manager_cache_quark (void) { static GQuark quark = 0; if (!quark) quark = g_quark_from_static_string ("gabble-vcard-manager-cache"); return quark; } static void cache_entry_free (void *data); static gint cache_entry_compare (gconstpointer a, gconstpointer b); static void manager_patch_vcard ( GabbleVCardManager *self, WockyNode *vcard_node); static void request_send (GabbleVCardManagerRequest *request, guint timeout); static void gabble_vcard_manager_init (GabbleVCardManager *obj) { GabbleVCardManagerPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, GABBLE_TYPE_VCARD_MANAGER, GabbleVCardManagerPrivate); obj->priv = priv; priv->cache = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, cache_entry_free); /* no destructor here - the hash table is responsible for freeing it */ priv->timed_cache = tp_heap_new (cache_entry_compare, NULL); priv->cache_timer = 0; priv->have_self_avatar = FALSE; priv->edits = NULL; } static void gabble_vcard_manager_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec); static void gabble_vcard_manager_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec); static void gabble_vcard_manager_dispose (GObject *object); static void gabble_vcard_manager_finalize (GObject *object); static void gabble_vcard_manager_class_init (GabbleVCardManagerClass *cls) { GObjectClass *object_class = G_OBJECT_CLASS (cls); GParamSpec *param_spec; g_type_class_add_private (cls, sizeof (GabbleVCardManagerPrivate)); object_class->get_property = gabble_vcard_manager_get_property; object_class->set_property = gabble_vcard_manager_set_property; object_class->dispose = gabble_vcard_manager_dispose; object_class->finalize = gabble_vcard_manager_finalize; param_spec = g_param_spec_object ("connection", "GabbleConnection object", "Gabble connection object that owns this vCard lookup helper object.", GABBLE_TYPE_CONNECTION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); param_spec = g_param_spec_boolean ("have-self-avatar", "Have our own avatar", "TRUE after the local user's own vCard has been retrieved in order to " "get their initial avatar.", FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_HAVE_SELF_AVATAR, param_spec); /* signal definitions */ signals[NICKNAME_UPDATE] = g_signal_new ("nickname-update", G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals[VCARD_UPDATE] = g_signal_new ("vcard-update", G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); signals[GOT_SELF_INITIAL_AVATAR] = g_signal_new ("got-self-initial-avatar", G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); } static void gabble_vcard_manager_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleVCardManager *self = GABBLE_VCARD_MANAGER (object); GabbleVCardManagerPrivate *priv = self->priv; switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, priv->connection); break; case PROP_HAVE_SELF_AVATAR: g_value_set_boolean (value, priv->have_self_avatar); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_vcard_manager_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleVCardManager *self = GABBLE_VCARD_MANAGER (object); GabbleVCardManagerPrivate *priv = self->priv; switch (property_id) { case PROP_CONNECTION: priv->connection = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void delete_request (GabbleVCardManagerRequest *request); static void cancel_request (GabbleVCardManagerRequest *request); static void cancel_all_edit_requests (GabbleVCardManager *manager); static gint cache_entry_compare (gconstpointer a, gconstpointer b) { const GabbleVCardCacheEntry *foo = a; const GabbleVCardCacheEntry *bar = b; return foo->expires - bar->expires; } static void cache_entry_free (gpointer data) { GabbleVCardCacheEntry *entry = data; g_assert (entry != NULL); while (entry->pending_requests) { cancel_request (entry->pending_requests->data); } if (entry->pipeline_item) { gabble_request_pipeline_item_cancel (entry->pipeline_item); } g_clear_object (&entry->vcard_node); g_slice_free (GabbleVCardCacheEntry, entry); } static GabbleVCardCacheEntry * cache_entry_get (GabbleVCardManager *manager, TpHandle handle) { GabbleVCardManagerPrivate *priv = manager->priv; GabbleVCardCacheEntry *entry; entry = g_hash_table_lookup (priv->cache, GUINT_TO_POINTER (handle)); if (entry) return entry; entry = g_slice_new0 (GabbleVCardCacheEntry); entry->manager = manager; entry->handle = handle; g_hash_table_insert (priv->cache, GUINT_TO_POINTER (handle), entry); return entry; } static gboolean cache_entry_timeout (gpointer data) { GabbleVCardManager *manager = data; GabbleVCardManagerPrivate *priv = manager->priv; GabbleVCardCacheEntry *entry; time_t now = time (NULL); while (NULL != (entry = tp_heap_peek_first (priv->timed_cache))) { if (entry->expires > now) break; /* shouldn't have in-flight request nor any pending requests */ g_assert (entry->pipeline_item == NULL); gabble_vcard_manager_invalidate_cache (manager, entry->handle); } priv->cache_timer = 0; if (entry) { priv->cache_timer = g_timeout_add_seconds ( entry->expires - time (NULL), cache_entry_timeout, manager); } return FALSE; } static void cache_entry_attempt_to_free (GabbleVCardCacheEntry *entry) { GabbleVCardManagerPrivate *priv = entry->manager->priv; TpBaseConnection *base = (TpBaseConnection *) priv->connection; if (entry->vcard_node != NULL) { DEBUG ("Not freeing vCard cache entry %p: it has a cached vCard %p", entry, entry->vcard_node); return; } if (entry->pipeline_item != NULL) { DEBUG ("Not freeing vCard cache entry %p: it has a pipeline_item %p", entry, entry->pipeline_item); return; } if (entry->pending_requests != NULL) { DEBUG ("Not freeing vCard cache entry %p: it has pending requests", entry); return; } /* If there is a suspended request, it must be in entry-> pending_requests */ g_assert (entry->suspended_timer_id == 0); if (entry->handle == tp_base_connection_get_self_handle (base)) { /* if we do have some pending edits, we should also have * some pipeline items or pending requests */ g_assert (priv->edit_pipeline_item || priv->edits == NULL); } tp_heap_remove (priv->timed_cache, entry); g_hash_table_remove (priv->cache, GUINT_TO_POINTER (entry->handle)); } void gabble_vcard_manager_invalidate_cache (GabbleVCardManager *manager, TpHandle handle) { GabbleVCardManagerPrivate *priv = manager->priv; GabbleVCardCacheEntry *entry = g_hash_table_lookup (priv->cache, GUINT_TO_POINTER (handle)); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->connection, TP_HANDLE_TYPE_CONTACT); g_return_if_fail (tp_handle_is_valid (contact_repo, handle, NULL)); if (!entry) return; tp_heap_remove (priv->timed_cache, entry); g_clear_object (&entry->vcard_node); cache_entry_attempt_to_free (entry); } static void complete_one_request (GabbleVCardManagerRequest *request, WockyNode *vcard_node, GError *error); static void cache_entry_complete_requests (GabbleVCardCacheEntry *entry, GError *error) { GSList *cur, *tmp; WockyNode *vcard_node = NULL; tmp = g_slist_copy (entry->pending_requests); if (entry->vcard_node != NULL) vcard_node = wocky_node_tree_get_top_node (entry->vcard_node); for (cur = tmp; cur != NULL; cur = cur->next) { GabbleVCardManagerRequest *request = cur->data; complete_one_request (request, error ? NULL : vcard_node, error); } g_slist_free (tmp); } static void complete_one_request (GabbleVCardManagerRequest *request, WockyNode *vcard_node, GError *error) { if (request->callback) { (request->callback) (request->manager, request, request->entry->handle, vcard_node, error, request->user_data); } delete_request (request); } static void disconnect_entry_foreach (gpointer handle, gpointer value, gpointer unused) { GError err = { TP_ERROR, TP_ERROR_DISCONNECTED, "Connection closed" }; GabbleVCardCacheEntry *entry = value; if (entry->suspended_timer_id) { g_source_remove (entry->suspended_timer_id); entry->suspended_timer_id = 0; } cache_entry_complete_requests (entry, &err); if (entry->pipeline_item) { gabble_request_pipeline_item_cancel (entry->pipeline_item); entry->pipeline_item = NULL; } } static void gabble_vcard_manager_dispose (GObject *object) { GabbleVCardManager *self = GABBLE_VCARD_MANAGER (object); GabbleVCardManagerPrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; DEBUG ("%p", object); if (priv->edits != NULL) { g_list_foreach (priv->edits, (GFunc) gabble_vcard_manager_edit_info_free, NULL); g_list_free (priv->edits); } priv->edits = NULL; if (priv->cache_timer) g_source_remove (priv->cache_timer); g_hash_table_foreach (priv->cache, disconnect_entry_foreach, NULL); tp_heap_destroy (priv->timed_cache); g_hash_table_unref (priv->cache); if (priv->edit_pipeline_item) gabble_request_pipeline_item_cancel (priv->edit_pipeline_item); cancel_all_edit_requests (self); if (G_OBJECT_CLASS (gabble_vcard_manager_parent_class)->dispose) G_OBJECT_CLASS (gabble_vcard_manager_parent_class)->dispose (object); } static void gabble_vcard_manager_finalize (GObject *object) { DEBUG ("%p", object); G_OBJECT_CLASS (gabble_vcard_manager_parent_class)->finalize (object); } gchar * vcard_get_avatar_sha1 (WockyNode *vcard) { gchar *sha1; const gchar *binval_value; guchar *avatar; gsize outlen; WockyNode *node; WockyNode *binval; node = wocky_node_get_child (vcard, "PHOTO"); if (!node) return g_strdup (""); DEBUG ("Our vCard has a PHOTO %p", node); binval = wocky_node_get_child (node, "BINVAL"); if (!binval) return g_strdup (""); binval_value = binval->content; if (!binval_value) return g_strdup (""); avatar = g_base64_decode (binval_value, &outlen); if (avatar) { sha1 = sha1_hex ((gchar *) avatar, outlen); g_free (avatar); DEBUG ("Successfully decoded PHOTO.BINVAL, SHA-1 %s", sha1); } else { DEBUG ("Avatar is in garbled Base64, ignoring it!"); sha1 = g_strdup (""); } return sha1; } /* Called during connection. */ static void initial_request_cb (GabbleVCardManager *self, GabbleVCardManagerRequest *request, TpHandle handle, WockyNode *vcard, GError *error, gpointer user_data) { GabbleVCardManagerPrivate *priv = self->priv; gchar *alias = user_data; gchar *sha1; if (vcard) { /* We now have our own avatar (or lack thereof) so can answer * GetAvatarTokens([self_handle]) */ priv->have_self_avatar = TRUE; /* Do we have an avatar already? If so, the presence cache ought to be * told (anyone else's avatar SHA-1 we'd get from their presence, * but unless we have another XEP-0153 resource connected, we never * see our own presence) */ sha1 = vcard_get_avatar_sha1 (vcard); g_signal_emit (self, signals[GOT_SELF_INITIAL_AVATAR], 0, sha1); g_free (sha1); } g_free (alias); } static void status_changed_cb (GObject *object, guint status, guint reason, gpointer user_data) { GabbleVCardManager *self = GABBLE_VCARD_MANAGER (user_data); GabbleVCardManagerPrivate *priv = self->priv; GabbleConnection *conn = GABBLE_CONNECTION (object); TpBaseConnection *base = (TpBaseConnection *) conn; if (status == TP_CONNECTION_STATUS_CONNECTED) { gchar *alias; GabbleConnectionAliasSource alias_src; /* if we have a better alias, patch it into our vCard on the server */ alias_src = _gabble_connection_get_cached_alias (conn, tp_base_connection_get_self_handle (base), &alias); if (alias_src >= GABBLE_CONNECTION_ALIAS_FROM_VCARD) { priv->edits = g_list_append (priv->edits, gabble_vcard_manager_edit_info_new (NULL, alias, GABBLE_VCARD_EDIT_SET_ALIAS, NULL)); } g_free (alias); /* FIXME: we happen to know that synchronous errors can't happen */ gabble_vcard_manager_request (self, tp_base_connection_get_self_handle (base), 0, initial_request_cb, NULL, (GObject *) self); } } /** * gabble_vcard_manager_new: * @conn: The #GabbleConnection to use for vCard lookup * * Creates an object to use for Jabber vCard lookup (JEP 0054). * There should be one of these per connection */ GabbleVCardManager * gabble_vcard_manager_new (GabbleConnection *conn) { GabbleVCardManager *self; g_return_val_if_fail (GABBLE_IS_CONNECTION (conn), NULL); self = GABBLE_VCARD_MANAGER (g_object_new (GABBLE_TYPE_VCARD_MANAGER, "connection", conn, NULL)); g_signal_connect (conn, "status-changed", G_CALLBACK (status_changed_cb), self); return self; } static void notify_delete_request (gpointer data, GObject *obj); static void notify_delete_edit_request (gpointer data, GObject *obj); static void delete_request (GabbleVCardManagerRequest *request) { GabbleVCardManager *manager = request->manager; DEBUG ("Discarding request %p", request); g_assert (NULL != request); g_assert (NULL != manager); g_assert (NULL != request->entry); g_assert (GABBLE_IS_VCARD_MANAGER (manager)); /* poison the request, so assertions about it will fail if there's a * dangling reference */ request->manager = NULL; request->entry->pending_requests = g_slist_remove (request->entry->pending_requests, request); cache_entry_attempt_to_free (request->entry); if (NULL != request->bound_object) { g_object_weak_unref (request->bound_object, notify_delete_request, request); } if (0 != request->timer_id) { g_source_remove (request->timer_id); } g_slice_free (GabbleVCardManagerRequest, request); } static gboolean timeout_request (gpointer data) { GabbleVCardManagerRequest *request = (GabbleVCardManagerRequest *) data; g_return_val_if_fail (data != NULL, FALSE); DEBUG ("Request %p timed out, notifying callback %p", request, request->callback); request->timer_id = 0; /* The pipeline machinery will call our callback with the error "canceled" */ gabble_request_pipeline_item_cancel (request->entry->pipeline_item); return FALSE; } static void cancel_request (GabbleVCardManagerRequest *request) { GError err = { GABBLE_VCARD_MANAGER_ERROR, GABBLE_VCARD_MANAGER_ERROR_CANCELLED, "Request cancelled" }; g_assert (request != NULL); DEBUG ("Request %p cancelled, notifying callback %p", request, request->callback); complete_one_request (request, NULL, &err); } static gchar * extract_nickname (WockyNode *vcard_node) { WockyNode *node; const gchar *nick; node = wocky_node_get_child (vcard_node, "NICKNAME"); if (node == NULL) return NULL; nick = node->content; return g_strdup (nick); } static void observe_vcard (GabbleConnection *conn, GabbleVCardManager *manager, TpHandle handle, WockyNode *vcard_node) { TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) conn, TP_HANDLE_TYPE_CONTACT); const gchar *field = "<NICKNAME>"; gchar *alias; const gchar *old_alias; alias = extract_nickname (vcard_node); if (alias == NULL) { WockyNode *fn_node = wocky_node_get_child (vcard_node, "FN"); if (fn_node != NULL) { const gchar *fn = fn_node->content; if (!tp_str_empty (fn)) { field = "<FN>"; alias = g_strdup (fn); } } } g_signal_emit (G_OBJECT (manager), signals[VCARD_UPDATE], 0, handle); old_alias = gabble_vcard_manager_get_cached_alias (manager, handle); if (old_alias != NULL && !tp_strdiff (old_alias, alias)) { DEBUG ("no change to vCard alias \"%s\" for handle %u", alias, handle); g_free (alias); return; } if (alias != NULL) { DEBUG ("got vCard alias \"%s\" for handle %u from %s", alias, handle, field); /* takes ownership of alias */ tp_handle_set_qdata (contact_repo, handle, gabble_vcard_manager_cache_quark (), alias, g_free); } else { DEBUG ("got no vCard alias for handle %u", handle); tp_handle_set_qdata (contact_repo, handle, gabble_vcard_manager_cache_quark (), (gchar *) NO_ALIAS, NULL); } if ((old_alias != NULL) || (alias != NULL)) g_signal_emit (G_OBJECT (manager), signals[NICKNAME_UPDATE], 0, handle); } /* Called when a pre-set get request failed, or when a set request succeeded * or failed. */ static void replace_reply_cb (GabbleConnection *conn, WockyStanza *reply_msg, gpointer user_data, GError *error) { GabbleVCardManager *self = GABBLE_VCARD_MANAGER (user_data); GabbleVCardManagerPrivate *priv = self->priv; TpBaseConnection *base = (TpBaseConnection *) conn; GList *li; WockyNode *node = NULL; /* If we sent a SET request, it's dead now. */ priv->edit_pipeline_item = NULL; DEBUG ("called: %s error", (error) ? "some" : "no"); if (error) { /* We won't need our patched vcard after all */ g_clear_object (&priv->patched_vcard); } else { GabbleVCardCacheEntry *entry = cache_entry_get (self, tp_base_connection_get_self_handle (base)); /* We must have patched vcard by now */ g_assert (priv->patched_vcard != NULL); /* Finally we may put the new vcard in the cache. */ g_clear_object (&entry->vcard_node); entry->vcard_node = priv->patched_vcard; priv->patched_vcard = NULL; node = wocky_node_tree_get_top_node (entry->vcard_node); /* observe it so we pick up alias updates */ observe_vcard (conn, self, tp_base_connection_get_self_handle (base), node); } /* Scan all edit requests, call and remove ones whose data made it * into SET request that just returned. */ li = priv->edit_requests; while (li) { GabbleVCardManagerEditRequest *req = li->data; li = g_list_next (li); if (req->set_in_pipeline || error) { if (req->callback) { (req->callback) (req->manager, req, node, error, req->user_data); } gabble_vcard_manager_remove_edit_request (req); } } if (error != NULL) { if (priv->edits != NULL) { /* All the requests for these edits have just been cancelled. */ g_list_foreach (priv->edits, (GFunc) gabble_vcard_manager_edit_info_free, NULL); g_list_free (priv->edits); priv->edits = NULL; } } else { /* If we've received more edit requests in the meantime, send them off. */ manager_patch_vcard (self, node); } } /* This function must return TRUE for any significant change, but may also * return TRUE for insignificant changes, as long as they aren't commonly done * (NICKNAME, PHOTO and in future FN are the problematic ones). */ static gboolean gabble_vcard_manager_replace_is_significant (GabbleVCardManagerEditInfo *info, WockyNode *old_vcard) { gboolean seen = FALSE; WockyNodeIter i; WockyNode *node, *replacement_node; g_return_val_if_fail (info->element != NULL, FALSE); replacement_node = wocky_node_tree_get_top_node (info->element); /* Find the first node matching the one we want to edit */ wocky_node_iter_init (&i, old_vcard, info->element_name, NULL); while (wocky_node_iter_next (&i, &node)) { /* if there are >= 2 copies of this field, we're going to reduce that * to 1 */ if (seen) return TRUE; seen = TRUE; /* This depends on PHOTO's children being TYPE, BINVAL in the correct * order—which is required by the vcard-temp schema, soooo... */ if (!wocky_node_equal (node, replacement_node)) return TRUE; } /* if there are no copies of this field, we're going to add one; otherwise, * seen == TRUE implies we've seen exactly one copy, and it matched what * we want */ return !seen; } static gboolean remove_all_children_named ( WockyNode *node, const gchar *name) { WockyNodeIter iter; gboolean changed = FALSE; wocky_node_iter_init (&iter, node, name, NULL); while (wocky_node_iter_next (&iter, NULL)) { wocky_node_iter_remove (&iter); changed = TRUE; } return changed; } static gboolean gabble_vcard_manager_edit_info_apply_replace ( GabbleVCardManagerEditInfo *info, WockyNode *vcard_node, GabbleVCardManager *vcard_manager) { g_return_val_if_fail (info->edit_type == GABBLE_VCARD_EDIT_REPLACE, FALSE); if (!gabble_vcard_manager_can_use_vcard_field (vcard_manager, info->element_name)) { DEBUG ("ignoring vcard node %s because this server doesn't " "support it", info->element_name); return FALSE; } /* A special case for replacing one field with another: we detect no-op * changes more actively, because we make changes of this type quite * frequently (on every login), and as well as wasting bandwidth, setting * the vCard too often can cause a memory leak in OpenFire (see fd.o#25341). */ if (! gabble_vcard_manager_replace_is_significant (info, vcard_node)) { DEBUG ("ignoring no-op vCard %s replacement", info->element_name); return FALSE; } remove_all_children_named (vcard_node, info->element_name); wocky_node_add_node_tree (vcard_node, info->element); return TRUE; } static gboolean gabble_vcard_manager_edit_info_apply_append ( GabbleVCardManagerEditInfo *info, WockyNode *vcard_node, GabbleVCardManager *vcard_manager) { if (!gabble_vcard_manager_can_use_vcard_field (vcard_manager, info->element_name)) { DEBUG ("ignoring vcard node %s because this server doesn't " "support it", info->element_name); return FALSE; } wocky_node_add_node_tree (vcard_node, info->element); return TRUE; } static gboolean gabble_vcard_manager_edit_info_apply_delete ( GabbleVCardManagerEditInfo *info, WockyNode *vcard_node, GabbleVCardManager *vcard_manager) { return remove_all_children_named (vcard_node, info->element_name); } static gboolean gabble_vcard_manager_edit_info_apply_clear ( GabbleVCardManagerEditInfo *info, WockyNode *vcard_node, GabbleVCardManager *vcard_manager) { /* Blow almost everything away! As a special case, the photo gets left in * place from the old vCard, because SetContactInfo doesn't touch * photos, and CLEAR is only used by SetContactInfo */ WockyNodeIter iter; WockyNode *node; gboolean changed = FALSE; wocky_node_iter_init (&iter, vcard_node, NULL, NULL); while (wocky_node_iter_next (&iter, &node)) { if (tp_strdiff (node->name, "PHOTO")) { wocky_node_iter_remove (&iter); changed = TRUE; } } return changed; } /* SET_ALIAS is shorthand for a REPLACE operation or nothing */ static gboolean gabble_vcard_manager_edit_info_apply_set_alias ( GabbleVCardManagerEditInfo *info, WockyNode *old_vcard, GabbleVCardManager *vcard_manager) { GabbleConnection *conn = vcard_manager->priv->connection; TpBaseConnection *base = (TpBaseConnection *) conn; g_assert (info->element_name == NULL); if (gabble_vcard_manager_can_use_vcard_field (vcard_manager, "NICKNAME")) { info->element_name = g_strdup ("NICKNAME"); } else { /* Google Talk servers won't let us set a NICKNAME; recover by * setting the FN */ info->element_name = g_strdup ("FN"); } if (info->new_alias == NULL) { /* We're just trying to fix a possibly-incomplete SetContactInfo() */ WockyNode *node = wocky_node_get_child (old_vcard, info->element_name); gchar *alias; /* If the user has set this field explicitly via SetContactInfo(), * that takes precedence */ if (node != NULL) return FALSE; if (_gabble_connection_get_cached_alias (conn, tp_base_connection_get_self_handle (base), &alias) < GABBLE_CONNECTION_ALIAS_FROM_VCARD) { /* not good enough to want to put it in the vCard */ g_free (alias); return FALSE; } info->new_alias = alias; } info->element = wocky_node_tree_new (info->element_name, NS_VCARD_TEMP, '$', info->new_alias, NULL); info->edit_type = GABBLE_VCARD_EDIT_REPLACE; return gabble_vcard_manager_edit_info_apply_replace (info, old_vcard, vcard_manager); } typedef gboolean (*EditFunction) ( GabbleVCardManagerEditInfo *info, WockyNode *vcard_node, GabbleVCardManager *vcard_manager); static const EditFunction edit_functions[] = { gabble_vcard_manager_edit_info_apply_replace, gabble_vcard_manager_edit_info_apply_append, gabble_vcard_manager_edit_info_apply_delete, gabble_vcard_manager_edit_info_apply_clear, gabble_vcard_manager_edit_info_apply_set_alias, }; static gboolean gabble_vcard_manager_edit_info_apply (GabbleVCardManagerEditInfo *info, WockyNode *vcard_node, GabbleVCardManager *vcard_manager) { return edit_functions[info->edit_type] (info, vcard_node, vcard_manager); } static void manager_patch_vcard (GabbleVCardManager *self, WockyNode *old_vcard_node) { GabbleVCardManagerPrivate *priv = self->priv; WockyNodeTree *vcard_node_tree; WockyNode *vcard_node; WockyStanza *msg; GList *li; gboolean changed = FALSE; /* Bail out if we don't have outstanding edits to make, or if we already * have a set request in progress. */ if (priv->edits == NULL || priv->edit_pipeline_item != NULL) return; vcard_node_tree = wocky_node_tree_new_from_node (old_vcard_node); vcard_node = wocky_node_tree_get_top_node (vcard_node_tree); /* Apply any unsent edits to the patched vCard */ for (li = priv->edits; li != NULL; li = li->next) { if (gabble_vcard_manager_edit_info_apply (li->data, vcard_node, self)) changed = TRUE; } if (!changed) { DEBUG ("nothing really changed, not updating vCard"); g_clear_object (&vcard_node_tree); goto out; } DEBUG("patching vcard"); /* We'll save the patched vcard, and if the server says * we're ok, put it into the cache. But we want to leave the * original vcard in the cache until that happens. */ priv->patched_vcard = vcard_node_tree; msg = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL, NULL); wocky_node_add_node_tree (wocky_stanza_get_top_node (msg), vcard_node_tree); priv->edit_pipeline_item = gabble_request_pipeline_enqueue ( priv->connection->req_pipeline, msg, default_request_timeout, replace_reply_cb, self); g_object_unref (msg); out: /* We've applied those, forget about them */ g_list_foreach (priv->edits, (GFunc) gabble_vcard_manager_edit_info_free, NULL); g_list_free (priv->edits); priv->edits = NULL; /* Current edit requests are in the pipeline, remember it so we * know which ones we may complete when the SET returns */ for (li = priv->edit_requests; li; li = g_list_next (li)) { GabbleVCardManagerEditRequest *edit = (GabbleVCardManagerEditRequest *) li->data; edit->set_in_pipeline = TRUE; } } static gboolean suspended_request_timeout_cb (gpointer data) { GabbleVCardManagerRequest *request = data; /* Send the request again */ request->entry->suspended_timer_id = 0; request_send (request, request->timeout); return FALSE; } static gboolean is_item_not_found (const GError *error) { return (error->domain == WOCKY_XMPP_ERROR && error->code == WOCKY_XMPP_ERROR_ITEM_NOT_FOUND); } /* Called when a GET request in the pipeline has either succeeded or failed. */ static void pipeline_reply_cb (GabbleConnection *conn, WockyStanza *reply_msg, gpointer user_data, GError *error) { GabbleVCardManagerRequest *request = user_data; GabbleVCardCacheEntry *entry = request->entry; GabbleVCardManager *self = GABBLE_VCARD_MANAGER (entry->manager); GabbleVCardManagerPrivate *priv = self->priv; TpBaseConnection *base = (TpBaseConnection *) conn; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); WockyNode *vcard_node = NULL; DEBUG("called for entry %p", entry); g_assert (tp_handle_is_valid (contact_repo, entry->handle, NULL)); g_assert (entry->pipeline_item != NULL); g_assert (entry->suspended_timer_id == 0); entry->pipeline_item = NULL; /* XEP-0054 says that the server MUST return <item-not-found/> if you have no * vCard set, so we should treat that case identically to the server * returning success but with no <vCard/> node. */ if (error != NULL && !is_item_not_found (error)) { /* First, handle the error "wait": suspend the request and replay it * later */ WockyXmppErrorType error_type = WOCKY_XMPP_ERROR_TYPE_CANCEL; GError *stanza_error = NULL; if (reply_msg != NULL && wocky_stanza_extract_errors (reply_msg, &error_type, &stanza_error, NULL, NULL)) { if (error_type == WOCKY_XMPP_ERROR_TYPE_WAIT) { DEBUG ("%s", g_quark_to_string (stanza_error->domain)); DEBUG ("Retrieving %u's vCard returned a temporary <%s/> error; " "trying againg in %u seconds", entry->handle, wocky_xmpp_stanza_error_to_string (stanza_error), request_wait_delay); g_source_remove (request->timer_id); request->timer_id = 0; entry->suspended_timer_id = g_timeout_add_seconds ( request_wait_delay, suspended_request_timeout_cb, request); g_error_free (stanza_error); return; } g_error_free (stanza_error); } /* If request for our own vCard failed, and we do have * pending edits to make, cancel those and return error * to the user */ if (entry->handle == tp_base_connection_get_self_handle (base) && priv->edits != NULL) { /* We won't have a chance to apply those, might as well forget them */ g_list_foreach (priv->edits, (GFunc) gabble_vcard_manager_edit_info_free, NULL); g_list_free (priv->edits); priv->edits = NULL; replace_reply_cb (conn, reply_msg, self, error); } /* Complete pending GET requests */ cache_entry_complete_requests (entry, error); return; } g_assert (reply_msg != NULL); vcard_node = wocky_node_get_child ( wocky_stanza_get_top_node (reply_msg), "vCard"); if (NULL == vcard_node) { /* We need a vCard node for the current API */ DEBUG ("successful lookup response contained no <vCard> node, " "creating an empty one"); vcard_node = wocky_node_add_child_ns ( wocky_stanza_get_top_node (reply_msg), "vCard", NS_VCARD_TEMP); } /* Put the message in the cache */ entry->vcard_node = wocky_node_tree_new_from_node (vcard_node); entry->expires = time (NULL) + VCARD_CACHE_ENTRY_TTL; tp_heap_add (priv->timed_cache, entry); if (priv->cache_timer == 0) { GabbleVCardCacheEntry *first = tp_heap_peek_first (priv->timed_cache); priv->cache_timer = g_timeout_add_seconds ( first->expires - time (NULL), cache_entry_timeout, self); } /* We have freshly updated cache for our vCard, edit it if * there are any pending edits and no outstanding set request. */ if (entry->handle == tp_base_connection_get_self_handle (base)) { manager_patch_vcard (self, vcard_node); } /* Observe the vCard as it goes past */ observe_vcard (priv->connection, self, entry->handle, vcard_node); /* Complete all pending requests successfully */ cache_entry_complete_requests (entry, NULL); } static void notify_delete_request (gpointer data, GObject *obj) { GabbleVCardManagerRequest *request = data; request->bound_object = NULL; delete_request (request); } static void request_send (GabbleVCardManagerRequest *request, guint timeout) { GabbleVCardCacheEntry *entry = request->entry; GabbleConnection *conn = entry->manager->priv->connection; TpBaseConnection *base = (TpBaseConnection *) conn; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); g_assert (request->timer_id == 0); if (entry->pipeline_item) { DEBUG ("adding to cache entry %p with <iq> already pending", entry); } else if (entry->suspended_timer_id != 0) { DEBUG ("adding to cache entry %p with <iq> suspended", entry); } else { const char *jid; WockyStanza *msg; request->timer_id = g_timeout_add_seconds (request->timeout, timeout_request, request); if (entry->handle == tp_base_connection_get_self_handle (base)) { DEBUG ("Cache entry %p is my own, not setting @to", entry); jid = NULL; } else { jid = tp_handle_inspect (contact_repo, entry->handle); DEBUG ("Cache entry %p is not mine, @to = %s", entry, jid); } msg = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, jid, '(', "vCard", ':', NS_VCARD_TEMP, ')', NULL); entry->pipeline_item = gabble_request_pipeline_enqueue ( conn->req_pipeline, msg, timeout, pipeline_reply_cb, request); g_object_unref (msg); DEBUG ("adding request to cache entry %p and queueing the <iq>", entry); } } /* Request the vCard for the given handle. When it arrives, call the given * callback. * * The callback may be NULL if you just want the side-effect of this * operation, which is to update the cached alias. * * Note: this method assumes that vCard for the given handle is not available * already. Before using it either check that the vCard is not available * using gabble_vcard_manager_get_cached(), or explicitly invalidate the * cache using gabble_vcard_manager_invalidate_cache() to request cache * refresh. * * FIXME: the timeout is not always obeyed when there is already a request * on the same handle. It should perhaps be removed. * * The connection must be connected. */ GabbleVCardManagerRequest * gabble_vcard_manager_request (GabbleVCardManager *self, TpHandle handle, guint timeout, GabbleVCardManagerCb callback, gpointer user_data, GObject *object) { GabbleVCardManagerPrivate *priv = self->priv; TpBaseConnection *base = (TpBaseConnection *) priv->connection; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base, TP_HANDLE_TYPE_CONTACT); GabbleVCardManagerRequest *request; GabbleVCardCacheEntry *entry = cache_entry_get (self, handle); g_return_val_if_fail (tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_CONNECTED, NULL); g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL), NULL); g_assert (entry->vcard_node == NULL); if (timeout == 0) timeout = default_request_timeout; request = g_slice_new0 (GabbleVCardManagerRequest); DEBUG ("Created request %p to retrieve <%u>'s vCard", request, handle); request->timeout = timeout; request->manager = self; request->entry = entry; request->callback = callback; request->user_data = user_data; request->bound_object = object; if (NULL != object) g_object_weak_ref (object, notify_delete_request, request); request->entry->pending_requests = g_slist_prepend (request->entry->pending_requests, request); request_send (request, timeout); return request; } /* Add a pending request to edit the vCard. When it finishes, call the given * callback. The callback may be NULL. * * The method takes over the ownership of the callers reference to \a edits and * its contents. * * The connection must be connected to call this method. */ GabbleVCardManagerEditRequest * gabble_vcard_manager_edit (GabbleVCardManager *self, guint timeout, GabbleVCardManagerEditCb callback, gpointer user_data, GObject *object, GList *edits) { GabbleVCardManagerPrivate *priv = self->priv; TpBaseConnection *base = (TpBaseConnection *) priv->connection; GabbleVCardManagerEditRequest *req; GabbleVCardCacheEntry *entry; g_return_val_if_fail (tp_base_connection_get_status (base) == TP_CONNECTION_STATUS_CONNECTED, NULL); /* Invalidate our current vCard and ensure that we're going to get * it in the near future */ DEBUG ("called; invalidating cache"); gabble_vcard_manager_invalidate_cache (self, tp_base_connection_get_self_handle (base)); DEBUG ("checking if we have pending requests already"); entry = cache_entry_get (self, tp_base_connection_get_self_handle (base)); if (!priv->edit_pipeline_item && !entry->pending_requests) { DEBUG ("we don't, create one"); /* create dummy GET request if neccessary */ gabble_vcard_manager_request (self, tp_base_connection_get_self_handle (base), 0, NULL, NULL, NULL); } priv->edits = g_list_concat (priv->edits, edits); req = g_slice_new (GabbleVCardManagerEditRequest); req->manager = self; req->callback = callback; req->user_data = user_data; req->set_in_pipeline = FALSE; req->bound_object = object; if (NULL != object) g_object_weak_ref (object, notify_delete_edit_request, req); priv->edit_requests = g_list_append (priv->edit_requests, req); return req; } void gabble_vcard_manager_remove_edit_request (GabbleVCardManagerEditRequest *request) { GabbleVCardManagerPrivate *priv = request->manager->priv; DEBUG("request == %p", request); g_return_if_fail (request != NULL); g_assert (NULL != g_list_find (priv->edit_requests, request)); if (request->bound_object) g_object_weak_unref (request->bound_object, notify_delete_edit_request, request); g_slice_free (GabbleVCardManagerEditRequest, request); priv->edit_requests = g_list_remove (priv->edit_requests, request); } static void notify_delete_edit_request (gpointer data, GObject *obj) { GabbleVCardManagerEditRequest *request = data; DEBUG("request == %p", request); request->bound_object = NULL; gabble_vcard_manager_remove_edit_request (request); } static void cancel_all_edit_requests (GabbleVCardManager *self) { GabbleVCardManagerPrivate *priv = self->priv; GError cancelled = { GABBLE_VCARD_MANAGER_ERROR, GABBLE_VCARD_MANAGER_ERROR_CANCELLED, "Request cancelled" }; while (priv->edit_requests) { GabbleVCardManagerEditRequest *req = priv->edit_requests->data; if (req->callback) { (req->callback) (req->manager, req, NULL, &cancelled, req->user_data); } gabble_vcard_manager_remove_edit_request (req); } } void gabble_vcard_manager_cancel_request (GabbleVCardManager *self, GabbleVCardManagerRequest *request) { g_return_if_fail (GABBLE_IS_VCARD_MANAGER (self)); g_return_if_fail (NULL != request); g_return_if_fail (self == request->manager); cancel_request (request); } /** * Return cached message for the handle's vCard if it's available. */ gboolean gabble_vcard_manager_get_cached (GabbleVCardManager *self, TpHandle handle, WockyNode **node) { GabbleVCardManagerPrivate *priv = self->priv; GabbleVCardCacheEntry *entry = g_hash_table_lookup (priv->cache, GUINT_TO_POINTER (handle)); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->connection, TP_HANDLE_TYPE_CONTACT); g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL), FALSE); if ((entry == NULL) || (entry->vcard_node == NULL)) return FALSE; if (node != NULL) *node = wocky_node_tree_get_top_node (entry->vcard_node); return TRUE; } /** * Return the cached alias derived from the vCard for the given handle, * if any. If there is no cached alias, return NULL. */ const gchar * gabble_vcard_manager_get_cached_alias (GabbleVCardManager *self, TpHandle handle) { GabbleVCardManagerPrivate *priv; TpHandleRepoIface *contact_repo; const gchar *s; g_return_val_if_fail (GABBLE_IS_VCARD_MANAGER (self), NULL); priv = self->priv; contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->connection, TP_HANDLE_TYPE_CONTACT); g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL), NULL); s = tp_handle_get_qdata (contact_repo, handle, gabble_vcard_manager_cache_quark ()); if (s == NO_ALIAS) s = NULL; return s; } /** * Return TRUE if we've tried looking up an alias for this handle before. */ gboolean gabble_vcard_manager_has_cached_alias (GabbleVCardManager *self, TpHandle handle) { GabbleVCardManagerPrivate *priv; TpHandleRepoIface *contact_repo; gpointer p; g_return_val_if_fail (GABBLE_IS_VCARD_MANAGER (self), FALSE); priv = self->priv; contact_repo = tp_base_connection_get_handles ( (TpBaseConnection *) priv->connection, TP_HANDLE_TYPE_CONTACT); g_return_val_if_fail (tp_handle_is_valid (contact_repo, handle, NULL), FALSE); p = tp_handle_get_qdata (contact_repo, handle, gabble_vcard_manager_cache_quark ()); return p != NULL; } /* For unit tests only */ void gabble_vcard_manager_set_suspend_reply_timeout (guint timeout) { request_wait_delay = timeout; } void gabble_vcard_manager_set_default_request_timeout (guint timeout) { default_request_timeout = timeout; } GabbleVCardManagerEditInfo * gabble_vcard_manager_edit_info_new (const gchar *element_name, const gchar *element_value, GabbleVCardEditType edit_type, ...) { GabbleVCardManagerEditInfo *info; va_list ap; info = g_slice_new0 (GabbleVCardManagerEditInfo); info->element_name = g_strdup (element_name); info->edit_type = edit_type; va_start (ap, edit_type); switch (edit_type) { case GABBLE_VCARD_EDIT_REPLACE: case GABBLE_VCARD_EDIT_APPEND: g_return_val_if_fail (element_name != NULL, NULL); info->element = wocky_node_tree_new_va (element_name, NS_VCARD_TEMP, ap); va_end (ap); if (element_value != NULL) wocky_node_set_content (wocky_node_tree_get_top_node (info->element), element_value); break; case GABBLE_VCARD_EDIT_SET_ALIAS: g_return_val_if_fail (element_name == NULL, NULL); info->new_alias = g_strdup (element_value); element_value = NULL; /* deliberate fall-through to check the varargs... */ case GABBLE_VCARD_EDIT_DELETE: case GABBLE_VCARD_EDIT_CLEAR: { const gchar *first_edit = NULL; g_return_val_if_fail (element_value == NULL, NULL); first_edit = va_arg (ap, const gchar *); va_end (ap); g_return_val_if_fail (first_edit == NULL, NULL); break; } } return info; } void gabble_vcard_manager_edit_info_add_child ( GabbleVCardManagerEditInfo *edit_info, const gchar *key, const gchar *value) { g_return_if_fail (edit_info->element != NULL); wocky_node_add_child_with_content ( wocky_node_tree_get_top_node (edit_info->element), key, value); } void gabble_vcard_manager_edit_info_free (GabbleVCardManagerEditInfo *info) { g_free (info->element_name); g_free (info->new_alias); g_clear_object (&info->element); g_slice_free (GabbleVCardManagerEditInfo, info); } gboolean gabble_vcard_manager_has_limited_vcard_fields (GabbleVCardManager *self) { if (self->priv->connection->features & GABBLE_CONNECTION_FEATURES_GOOGLE_ROSTER) return TRUE; return FALSE; } gboolean gabble_vcard_manager_can_use_vcard_field (GabbleVCardManager *self, const gchar *field_name) { if (self->priv->connection->features & GABBLE_CONNECTION_FEATURES_GOOGLE_ROSTER) { /* Google's server only allows N, FN, PHOTO and URL */ if (tp_strdiff (field_name, "N") && tp_strdiff (field_name, "FN") && tp_strdiff (field_name, "PHOTO") && tp_strdiff (field_name, "URL")) { return FALSE; } } return TRUE; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/server-sasl-channel.c���������������������������������������������������0000664�0001750�0001750�00000103075�12332441362�023013� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * server-sasl-channel.c - Source for GabbleServerSaslChannel * Copyright (C) 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "server-sasl-channel.h" #include "gabble-signals-marshal.h" #include <errno.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> #ifdef HAVE_UNISTD_H # include <unistd.h> #endif #include <glib/gstdio.h> #include <gio/gio.h> #include <dbus/dbus-glib.h> #include <wocky/wocky.h> #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #define DEBUG_FLAG GABBLE_DEBUG_AUTH #include <gabble/error.h> #include "connection.h" #include "debug.h" #include "namespaces.h" #include "util.h" static void sasl_auth_iface_init (gpointer, gpointer); G_DEFINE_TYPE_WITH_CODE (GabbleServerSaslChannel, gabble_server_sasl_channel, TP_TYPE_BASE_CHANNEL, G_IMPLEMENT_INTERFACE ( TP_TYPE_SVC_CHANNEL_TYPE_SERVER_AUTHENTICATION, NULL); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_SECURABLE, NULL); G_IMPLEMENT_INTERFACE ( TP_TYPE_SVC_CHANNEL_INTERFACE_SASL_AUTHENTICATION, sasl_auth_iface_init)); enum { /* server authentication channel */ PROP_AUTH_METHOD = 1, /* sasl authentication channel */ PROP_AVAILABLE_MECHANISMS, PROP_HAS_INITIAL_DATA, PROP_CAN_TRY_AGAIN, PROP_SECURE, PROP_SASL_STATUS, PROP_SASL_ERROR, PROP_SASL_ERROR_DETAILS, PROP_AUTHORIZATION_IDENTITY, PROP_DEFAULT_USERNAME, PROP_DEFAULT_REALM, LAST_PROPERTY, }; /* private structure */ struct _GabbleServerSaslChannelPrivate { /* Immutable SASL properties */ GStrv available_mechanisms; gboolean secure; /* Mutable SASL properties */ TpSASLStatus sasl_status; gchar *sasl_error; GHashTable *sasl_error_details; /* Given to the Connection on request */ TpConnectionStatusReason disconnect_reason; GError *wocky_auth_error /* = NULL */; GSimpleAsyncResult *result; }; static GPtrArray * gabble_server_sasl_channel_get_interfaces (TpBaseChannel *base) { GPtrArray *interfaces; interfaces = TP_BASE_CHANNEL_CLASS ( gabble_server_sasl_channel_parent_class)->get_interfaces (base); g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION); g_ptr_array_add (interfaces, TP_IFACE_CHANNEL_INTERFACE_SECURABLE); return interfaces; } static void gabble_server_sasl_channel_init (GabbleServerSaslChannel *self) { GabbleServerSaslChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_SERVER_SASL_CHANNEL, GabbleServerSaslChannelPrivate); self->priv = priv; priv->sasl_status = TP_SASL_STATUS_NOT_STARTED; priv->sasl_error = NULL; priv->sasl_error_details = tp_asv_new (NULL, NULL); /* a safe assumption if we don't set anything else */ priv->disconnect_reason = TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED; } static void gabble_server_sasl_channel_fill_immutable_properties (TpBaseChannel *channel, GHashTable *properties) { TP_BASE_CHANNEL_CLASS (gabble_server_sasl_channel_parent_class) ->fill_immutable_properties (channel, properties); tp_dbus_properties_mixin_fill_properties_hash (G_OBJECT (channel), properties, TP_IFACE_CHANNEL_TYPE_SERVER_AUTHENTICATION, "AuthenticationMethod", TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION, "AvailableMechanisms", TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION, "HasInitialData", TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION, "CanTryAgain", TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION, "AuthorizationIdentity", TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION, "DefaultRealm", TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION, "DefaultUsername", TP_IFACE_CHANNEL_INTERFACE_SECURABLE, "Encrypted", TP_IFACE_CHANNEL_INTERFACE_SECURABLE, "Verified", NULL); } static gchar * gabble_server_sasl_channel_get_object_path_suffix (TpBaseChannel *channel) { return g_strdup ("ServerSASLChannel"); } static void gabble_server_sasl_channel_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { TpBaseChannel *channel = TP_BASE_CHANNEL (object); GabbleServerSaslChannel *self = GABBLE_SERVER_SASL_CHANNEL (object); GabbleServerSaslChannelPrivate *priv = self->priv; switch (property_id) { case PROP_SASL_STATUS: g_value_set_uint (value, priv->sasl_status); break; case PROP_SASL_ERROR: g_value_set_string (value, priv->sasl_error); break; case PROP_SASL_ERROR_DETAILS: g_value_set_boxed (value, priv->sasl_error_details); break; case PROP_AUTH_METHOD: g_value_set_static_string (value, TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION); break; case PROP_AVAILABLE_MECHANISMS: g_value_set_boxed (value, priv->available_mechanisms); break; case PROP_SECURE: g_value_set_boolean (value, priv->secure); break; case PROP_CAN_TRY_AGAIN: /* Wocky can't retry SASL authentication (although XMPP can) */ g_value_set_boolean (value, FALSE); break; case PROP_HAS_INITIAL_DATA: /* Yes, XMPP has "initial data" in its SASL */ g_value_set_boolean (value, TRUE); break; case PROP_AUTHORIZATION_IDENTITY: /* As per RFC 3920, the authorization identity for c2s connections * is the desired JID. We can't use conn_util_get_bare_self_jid at * this stage of the connection process, because it hasn't been * initialized yet. */ { gchar *jid, *username, *stream_server; g_object_get (tp_base_channel_get_connection (channel), "username", &username, "stream-server", &stream_server, NULL); jid = g_strconcat (username, "@", stream_server, NULL); g_free (username); g_free (stream_server); g_value_take_string (value, jid); } break; case PROP_DEFAULT_REALM: /* Like WockySaslDigestMd5, we use the stream server as the default * realm, for interoperability with servers that fail to supply a * realm but expect us to have this default. */ g_object_get_property ( G_OBJECT (tp_base_channel_get_connection (channel)), "stream-server", value); break; case PROP_DEFAULT_USERNAME: /* In practice, XMPP servers normally want us to authenticate as the * local-part of the JID. */ g_object_get_property ( G_OBJECT (tp_base_channel_get_connection (channel)), "username", value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_server_sasl_channel_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleServerSaslChannel *chan = GABBLE_SERVER_SASL_CHANNEL (object); GabbleServerSaslChannelPrivate *priv = chan->priv; switch (property_id) { case PROP_SECURE: priv->secure = g_value_get_boolean (value); break; case PROP_AVAILABLE_MECHANISMS: priv->available_mechanisms = g_value_dup_boxed (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_server_sasl_channel_finalize (GObject *object) { GabbleServerSaslChannel *self = GABBLE_SERVER_SASL_CHANNEL (object); GabbleServerSaslChannelPrivate *priv = self->priv; /* a ref is held for the channel's lifetime */ g_assert (tp_base_channel_is_destroyed ((TpBaseChannel *) self)); g_assert (priv->result == NULL); g_strfreev (priv->available_mechanisms); g_free (priv->sasl_error); g_hash_table_unref (priv->sasl_error_details); g_clear_error (&priv->wocky_auth_error); if (G_OBJECT_CLASS (gabble_server_sasl_channel_parent_class)->finalize) G_OBJECT_CLASS (gabble_server_sasl_channel_parent_class)->finalize (object); } static void gabble_server_sasl_channel_close (TpBaseChannel *channel); static void gabble_server_sasl_channel_class_init (GabbleServerSaslChannelClass *klass) { static TpDBusPropertiesMixinPropImpl server_auth_props[] = { { "AuthenticationMethod", "auth-method", NULL }, { NULL } }; static TpDBusPropertiesMixinPropImpl sasl_auth_props[] = { { "AvailableMechanisms", "available-mechanisms", NULL }, { "HasInitialData", "has-initial-data", NULL }, { "CanTryAgain", "can-try-again", NULL }, { "SASLStatus", "sasl-status", NULL }, { "SASLError", "sasl-error", NULL }, { "SASLErrorDetails", "sasl-error-details", NULL }, { "AuthorizationIdentity", "authorization-identity", NULL }, { "DefaultRealm", "default-realm", NULL }, { "DefaultUsername", "default-username", NULL }, { NULL } }; static TpDBusPropertiesMixinPropImpl securable_props[] = { /* For the moment we only have a unified "secure" property, which * implies we're both encrypted and verified */ { "Encrypted", "secure", NULL }, { "Verified", "secure", NULL }, { NULL } }; static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { { TP_IFACE_CHANNEL_TYPE_SERVER_AUTHENTICATION, tp_dbus_properties_mixin_getter_gobject_properties, NULL, server_auth_props, }, { TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION, tp_dbus_properties_mixin_getter_gobject_properties, NULL, sasl_auth_props, }, { TP_IFACE_CHANNEL_INTERFACE_SECURABLE, tp_dbus_properties_mixin_getter_gobject_properties, NULL, securable_props, }, { NULL } }; GObjectClass *object_class = G_OBJECT_CLASS (klass); TpBaseChannelClass *channel_class = TP_BASE_CHANNEL_CLASS (klass); GParamSpec *param_spec; g_type_class_add_private (klass, sizeof (GabbleServerSaslChannelPrivate)); object_class->get_property = gabble_server_sasl_channel_get_property; object_class->set_property = gabble_server_sasl_channel_set_property; object_class->finalize = gabble_server_sasl_channel_finalize; channel_class->channel_type = TP_IFACE_CHANNEL_TYPE_SERVER_AUTHENTICATION; channel_class->get_interfaces = gabble_server_sasl_channel_get_interfaces; channel_class->target_handle_type = TP_HANDLE_TYPE_NONE; channel_class->fill_immutable_properties = gabble_server_sasl_channel_fill_immutable_properties; channel_class->get_object_path_suffix = gabble_server_sasl_channel_get_object_path_suffix; channel_class->close = gabble_server_sasl_channel_close; param_spec = g_param_spec_string ("auth-method", "Authentication method", "Method of authentication (D-Bus interface)", TP_IFACE_CHANNEL_INTERFACE_SASL_AUTHENTICATION, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_AUTH_METHOD, param_spec); param_spec = g_param_spec_string ("authorization-identity", "AuthorizationIdentity", "Identity for which we wish to be authorized", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_AUTHORIZATION_IDENTITY, param_spec); param_spec = g_param_spec_string ("default-realm", "DefaultRealm", "Default realm if the server does not supply one", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_DEFAULT_REALM, param_spec); param_spec = g_param_spec_string ("default-username", "DefaultUsername", "Default simple username if the user does not supply one", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_DEFAULT_USERNAME, param_spec); param_spec = g_param_spec_uint ("sasl-status", "SASLStatus", "Status of this channel", 0, NUM_TP_SASL_STATUSES, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SASL_STATUS, param_spec); param_spec = g_param_spec_string ("sasl-error", "SASLError", "D-Bus error name", "", G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SASL_ERROR, param_spec); param_spec = g_param_spec_boxed ("sasl-error-details", "SASLErrorDetails", "Extra details of a SASL error", TP_HASH_TYPE_STRING_VARIANT_MAP, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SASL_ERROR_DETAILS, param_spec); param_spec = g_param_spec_boxed ("available-mechanisms", "Available authentication mechanisms", "The set of mechanisms the server advertised.", G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_AVAILABLE_MECHANISMS, param_spec); param_spec = g_param_spec_boolean ("can-try-again", "CanTryAgain", "True if failed SASL can be retried without reconnecting", FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CAN_TRY_AGAIN, param_spec); param_spec = g_param_spec_boolean ("has-initial-data", "HasInitialData", "True if SASL has initial data", TRUE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_HAS_INITIAL_DATA, param_spec); param_spec = g_param_spec_boolean ("secure", "Is secure", "Is this channel secure (encrypted and verified)?", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SECURE, param_spec); klass->dbus_props_class.interfaces = prop_interfaces; tp_dbus_properties_mixin_class_init (object_class, G_STRUCT_OFFSET (GabbleServerSaslChannelClass, dbus_props_class)); } static void set_errors ( GabbleServerSaslChannel *self, const gchar *dbus_error, const gchar *debug_message, const GError *error) { g_free (self->priv->sasl_error); self->priv->sasl_error = g_strdup (dbus_error); g_hash_table_remove_all (self->priv->sasl_error_details); if (debug_message != NULL) tp_asv_set_string (self->priv->sasl_error_details, "debug-message", debug_message); g_clear_error (&self->priv->wocky_auth_error); self->priv->wocky_auth_error = g_error_copy (error); } static void change_current_state (GabbleServerSaslChannel *self, TpSASLStatus status) { self->priv->sasl_status = status; tp_svc_channel_interface_sasl_authentication_emit_sasl_status_changed ( self, self->priv->sasl_status, self->priv->sasl_error, self->priv->sasl_error_details); } static void complete_operation ( GabbleServerSaslChannel *self, gboolean in_idle) { GabbleServerSaslChannelPrivate *priv = self->priv; GSimpleAsyncResult *r = priv->result; g_return_if_fail (priv->result != NULL); priv->result = NULL; if (in_idle) g_simple_async_result_complete_in_idle (r); else g_simple_async_result_complete (r); g_object_unref (r); } /** * SASL Authentication Channel Interface */ static void gabble_server_sasl_channel_raise ( DBusGMethodInvocation *context, TpError code, const gchar *message, ...) G_GNUC_PRINTF (3, 4); static void gabble_server_sasl_channel_raise (DBusGMethodInvocation *context, TpError code, const gchar *message, ...) { va_list ap; GError *error = NULL; va_start (ap, message); error = g_error_new_valist (TP_ERROR, code, message, ap); va_end (ap); dbus_g_method_return_error (context, error); g_error_free (error); } /* When called from start_mechanism, initial_data can be NULL. When called * from D-Bus as StartMechanismWithData, it can't. */ static void gabble_server_sasl_channel_start_mechanism_with_data ( TpSvcChannelInterfaceSASLAuthentication *iface, const gchar *in_Mechanism, const GArray *in_InitialData, DBusGMethodInvocation *context) { GabbleServerSaslChannel *self = GABBLE_SERVER_SASL_CHANNEL (iface); GabbleServerSaslChannelPrivate *priv = self->priv; WockyAuthRegistryStartData *start_data; GString *initial_data = NULL; if (self->priv->sasl_status != TP_SASL_STATUS_NOT_STARTED) { gabble_server_sasl_channel_raise (context, TP_ERROR_NOT_AVAILABLE, "Mechanisms can only be started in state Not_Started, not %u", self->priv->sasl_status); DEBUG ("cannot start: state %u != Not_Started", self->priv->sasl_status); return; } /* NotStarted state is entered by creating the channel: the caller must * call start_auth_async immediately */ g_assert (priv->result != NULL); g_assert (g_simple_async_result_is_valid (G_ASYNC_RESULT (priv->result), G_OBJECT (self), gabble_server_sasl_channel_start_auth_async)); if (tp_strv_contains ((const gchar * const *) priv->available_mechanisms, in_Mechanism)) { if (in_InitialData != NULL) { /* The initial data might be secret (for PLAIN etc.), and also might * not be UTF-8 or even text, so we just output the length */ DEBUG ("Starting %s authentication with %u bytes of initial data", in_Mechanism, in_InitialData->len); initial_data = g_string_new_len (in_InitialData->data, in_InitialData->len); } else { DEBUG ("Starting %s authentication without initial data", in_Mechanism); } change_current_state (self, TP_SASL_STATUS_IN_PROGRESS); dbus_g_method_return (context); start_data = wocky_auth_registry_start_data_new (in_Mechanism, initial_data); g_simple_async_result_set_op_res_gpointer (priv->result, start_data, (GDestroyNotify) wocky_auth_registry_start_data_free); complete_operation (self, TRUE); if (initial_data != NULL) g_string_free (initial_data, TRUE); } else { DEBUG ("cannot start: %s is not a supported mechanism", in_Mechanism); gabble_server_sasl_channel_raise (context, TP_ERROR_NOT_IMPLEMENTED, "Selected mechanism is not available."); } } static void gabble_server_sasl_channel_start_mechanism ( TpSvcChannelInterfaceSASLAuthentication *iface, const gchar *mech, DBusGMethodInvocation *context) { gabble_server_sasl_channel_start_mechanism_with_data (iface, mech, NULL, context); } static void gabble_server_sasl_channel_respond ( TpSvcChannelInterfaceSASLAuthentication *channel, const GArray *in_Response_Data, DBusGMethodInvocation *context) { GabbleServerSaslChannel *self = GABBLE_SERVER_SASL_CHANNEL (channel); GabbleServerSaslChannelPrivate *priv = self->priv; GString *response_data; if (self->priv->sasl_status != TP_SASL_STATUS_IN_PROGRESS) { gabble_server_sasl_channel_raise (context, TP_ERROR_NOT_AVAILABLE, "You can only respond to challenges in state In_Progress, not %u", self->priv->sasl_status); DEBUG ("cannot respond: state %u != In_Progress", self->priv->sasl_status); return; } if (priv->result == NULL) { gabble_server_sasl_channel_raise (context, TP_ERROR_NOT_AVAILABLE, "You already responded to the most recent challenge"); DEBUG ("cannot respond: already responded"); return; } g_assert (g_simple_async_result_is_valid (G_ASYNC_RESULT (priv->result), G_OBJECT (self), gabble_server_sasl_channel_challenge_async)); /* The response might be secret (for PLAIN etc.), and also might * not be UTF-8 or even text, so we just output the length */ DEBUG ("responding with %u bytes", in_Response_Data->len); if (in_Response_Data->len > 0) response_data = g_string_new_len (in_Response_Data->data, in_Response_Data->len); else response_data = NULL; g_simple_async_result_set_op_res_gpointer (priv->result, response_data, (GDestroyNotify) wocky_g_string_free); complete_operation (self, TRUE); tp_svc_channel_interface_sasl_authentication_return_from_respond ( context); } static void gabble_server_sasl_channel_accept_sasl ( TpSvcChannelInterfaceSASLAuthentication *channel, DBusGMethodInvocation *context) { GabbleServerSaslChannel *self = GABBLE_SERVER_SASL_CHANNEL (channel); GabbleServerSaslChannelPrivate *priv = self->priv; const gchar *message = NULL; switch (self->priv->sasl_status) { case TP_SASL_STATUS_NOT_STARTED: message = "Authentication has not yet begun (Not_Started)"; break; case TP_SASL_STATUS_IN_PROGRESS: /* In this state, the only valid time to call this method is in response * to a challenge, to indicate that, actually, that challenge was * additional data for a successful authentication. */ if (priv->result == NULL) { message = "In_Progress, but you already responded to the last " "challenge"; } else { DEBUG ("client says the last challenge was actually final data " "and has accepted it"); g_assert (g_simple_async_result_is_valid (G_ASYNC_RESULT (priv->result), G_OBJECT (self), gabble_server_sasl_channel_challenge_async)); change_current_state (self, TP_SASL_STATUS_CLIENT_ACCEPTED); } break; case TP_SASL_STATUS_SERVER_SUCCEEDED: /* The server has already said yes, and the caller is waiting for * success_async(), i.e. waiting for the UI to check whether it's * happy too. AcceptSASL means that it is. */ DEBUG ("client has accepted server's success"); g_assert (g_simple_async_result_is_valid (G_ASYNC_RESULT (priv->result), G_OBJECT (self), gabble_server_sasl_channel_success_async)); change_current_state (self, TP_SASL_STATUS_SUCCEEDED); break; case TP_SASL_STATUS_CLIENT_ACCEPTED: message = "Client already accepted authentication (Client_Accepted)"; break; case TP_SASL_STATUS_SUCCEEDED: message = "Authentication already succeeded (Succeeded)"; break; case TP_SASL_STATUS_SERVER_FAILED: message = "Authentication has already failed (Server_Failed)"; break; case TP_SASL_STATUS_CLIENT_FAILED: message = "Authentication has already been aborted (Client_Failed)"; break; default: g_assert_not_reached (); } if (message != NULL) { DEBUG ("cannot accept SASL: %s", message); gabble_server_sasl_channel_raise (context, TP_ERROR_NOT_AVAILABLE, "%s", message); return; } if (priv->result != NULL) { /* This is a bit weird - this code is run for two different async * results. In the In_Progress case, this code results in * success with the GSimpleAsyncResult's op_res left as NULL, which * is what Wocky wants for an empty response. In the Server_Succeeded * response, the async result is just success or error - we succeed. */ /* We want want to complete not in an idle because if we do we * will hit fd.o#32278. This is safe because we're being called * from dbus-glib in the main loop. */ complete_operation (self, FALSE); } tp_svc_channel_interface_sasl_authentication_return_from_accept_sasl ( context); } static void gabble_server_sasl_channel_abort_sasl ( TpSvcChannelInterfaceSASLAuthentication *channel, guint in_Reason, const gchar *in_Debug_Message, DBusGMethodInvocation *context) { GabbleServerSaslChannel *self = GABBLE_SERVER_SASL_CHANNEL (channel); GabbleServerSaslChannelPrivate *priv = self->priv; const gchar *dbus_error; switch (self->priv->sasl_status) { case TP_SASL_STATUS_SERVER_FAILED: case TP_SASL_STATUS_CLIENT_FAILED: DEBUG ("ignoring attempt to abort: we already failed"); break; case TP_SASL_STATUS_SUCCEEDED: case TP_SASL_STATUS_CLIENT_ACCEPTED: DEBUG ("cannot abort: client already called AcceptSASL"); gabble_server_sasl_channel_raise (context, TP_ERROR_NOT_AVAILABLE, "Authentication has already succeeded - too late to abort"); return; case TP_SASL_STATUS_NOT_STARTED: case TP_SASL_STATUS_IN_PROGRESS: case TP_SASL_STATUS_SERVER_SUCCEEDED: { GError *error = NULL; switch (in_Reason) { case TP_SASL_ABORT_REASON_INVALID_CHALLENGE: g_set_error (&error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, "invalid challenge (%s)", in_Debug_Message); dbus_error = TP_ERROR_STR_SERVICE_CONFUSED; break; case TP_SASL_ABORT_REASON_USER_ABORT: g_set_error (&error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_FAILURE, "user aborted auth (%s)", in_Debug_Message); dbus_error = TP_ERROR_STR_CANCELLED; break; default: g_set_error (&error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_FAILURE, "unknown reason code %u, treating as User_Abort (%s)", in_Reason, in_Debug_Message); dbus_error = TP_ERROR_STR_CANCELLED; break; } DEBUG ("%s", error->message); set_errors (self, dbus_error, in_Debug_Message, error); change_current_state (self, TP_SASL_STATUS_CLIENT_FAILED); if (priv->result != NULL) { /* If Not_Started, we're returning failure from start_auth_async. * If In_Progress, we might be returning failure from * challenge_async, if one is outstanding. * If Server_Succeeded, we're returning failure from success_async. */ g_simple_async_result_set_from_error (priv->result, error); complete_operation (self, TRUE); } g_error_free (error); break; } default: g_assert_not_reached (); } tp_svc_channel_interface_sasl_authentication_return_from_abort_sasl ( context); } static void sasl_auth_iface_init (gpointer klass, gpointer unused G_GNUC_UNUSED) { #define IMPLEMENT(x) \ tp_svc_channel_interface_sasl_authentication_implement_##x ( \ klass, gabble_server_sasl_channel_##x) IMPLEMENT (start_mechanism); IMPLEMENT (start_mechanism_with_data); IMPLEMENT (respond); IMPLEMENT (accept_sasl); IMPLEMENT (abort_sasl); #undef IMPLEMENT } void gabble_server_sasl_channel_start_auth_async (GabbleServerSaslChannel *self, GAsyncReadyCallback callback, gpointer user_data) { GabbleServerSaslChannelPrivate *priv = self->priv; g_assert (priv->result == NULL); g_assert (priv->sasl_status == TP_SASL_STATUS_NOT_STARTED); DEBUG ("Starting authentication"); priv->result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, gabble_server_sasl_channel_start_auth_async); tp_base_channel_register (TP_BASE_CHANNEL (self)); } gboolean gabble_server_sasl_channel_start_auth_finish (GabbleServerSaslChannel *self, GAsyncResult *result, WockyAuthRegistryStartData **start_data, GError **error) { wocky_implement_finish_copy_pointer (self, gabble_server_sasl_channel_start_auth_async, wocky_auth_registry_start_data_dup, start_data); } void gabble_server_sasl_channel_challenge_async (GabbleServerSaslChannel *self, const GString *challenge_data, GAsyncReadyCallback callback, gpointer user_data) { GabbleServerSaslChannelPrivate *priv = self->priv; GArray *challenge_ay; g_assert (!tp_base_channel_is_destroyed ((TpBaseChannel *) self)); g_assert (priv->result == NULL); /* it might be sensitive, and also might not be UTF-8 text, so just print * the length */ DEBUG ("New challenge, %" G_GSIZE_FORMAT " bytes", challenge_data->len); priv->result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, gabble_server_sasl_channel_challenge_async); switch (priv->sasl_status) { case TP_SASL_STATUS_IN_PROGRESS: challenge_ay = g_array_sized_new (FALSE, FALSE, sizeof (gchar), challenge_data->len); g_array_append_vals (challenge_ay, challenge_data->str, challenge_data->len); tp_svc_channel_interface_sasl_authentication_emit_new_challenge ( self, challenge_ay); break; case TP_SASL_STATUS_CLIENT_FAILED: g_return_if_fail (priv->wocky_auth_error != NULL); g_simple_async_result_set_from_error (priv->result, priv->wocky_auth_error); complete_operation (self, TRUE); return; default: g_assert_not_reached (); } } gboolean gabble_server_sasl_channel_challenge_finish (GabbleServerSaslChannel *self, GAsyncResult *result, GString **response, GError **error) { wocky_implement_finish_copy_pointer (self, gabble_server_sasl_channel_challenge_async, wocky_g_string_dup, response); } void gabble_server_sasl_channel_success_async (GabbleServerSaslChannel *self, GAsyncReadyCallback callback, gpointer user_data) { GabbleServerSaslChannelPrivate *priv = self->priv; g_assert (!tp_base_channel_is_destroyed ((TpBaseChannel *) self)); g_assert (priv->result == NULL); priv->result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, gabble_server_sasl_channel_success_async); DEBUG (""); if (self->priv->sasl_status != TP_SASL_STATUS_CLIENT_ACCEPTED) { change_current_state (self, TP_SASL_STATUS_SERVER_SUCCEEDED); } else { change_current_state (self, TP_SASL_STATUS_SUCCEEDED); complete_operation (self, TRUE); } } gboolean gabble_server_sasl_channel_success_finish (GabbleServerSaslChannel *self, GAsyncResult *result, GError **error) { wocky_implement_finish_void (self, gabble_server_sasl_channel_success_async); } void gabble_server_sasl_channel_fail (GabbleServerSaslChannel *self, const GError *error) { GError *tp_error = NULL; TpConnectionStatusReason conn_reason; if (self->priv->sasl_error != NULL) { DEBUG ("already failed, ignoring further error: %s", error->message); return; } gabble_set_tp_conn_error_from_wocky (error, TP_CONNECTION_STATUS_CONNECTING, &conn_reason, &tp_error); g_assert (tp_error->domain == TP_ERROR); DEBUG ("auth failed: %s", tp_error->message); set_errors (self, tp_error_get_dbus_name (tp_error->code), tp_error->message, error); change_current_state (self, TP_SASL_STATUS_SERVER_FAILED); self->priv->disconnect_reason = conn_reason; } /* * Public */ GabbleServerSaslChannel * gabble_server_sasl_channel_new (GabbleConnection *conn, GStrv available_mechanisms, gboolean secure, const gchar *session_id) { GabbleServerSaslChannel *obj; g_return_val_if_fail (GABBLE_IS_CONNECTION (conn), NULL); obj = GABBLE_SERVER_SASL_CHANNEL ( g_object_new (GABBLE_TYPE_SERVER_SASL_CHANNEL, "connection", conn, "available-mechanisms", available_mechanisms, "secure", secure, NULL)); return obj; } static void gabble_server_sasl_channel_close (TpBaseChannel *channel) { GabbleServerSaslChannel *self = GABBLE_SERVER_SASL_CHANNEL (channel); GabbleServerSaslChannelPrivate *priv = self->priv; GError error = { WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_FAILURE, "Client aborted authentication." }; DEBUG ("called on %p", self); switch (priv->sasl_status) { case TP_SASL_STATUS_NOT_STARTED: case TP_SASL_STATUS_IN_PROGRESS: case TP_SASL_STATUS_SERVER_SUCCEEDED: set_errors (self, TP_ERROR_STR_AUTHENTICATION_FAILED, "Close() called", &error); break; case TP_SASL_STATUS_CLIENT_ACCEPTED: case TP_SASL_STATUS_SUCCEEDED: /* Hooray! */ break; case TP_SASL_STATUS_SERVER_FAILED: case TP_SASL_STATUS_CLIENT_FAILED: g_warn_if_fail (priv->sasl_error != NULL); break; } if (priv->result != NULL) { DEBUG ("closed channel"); g_simple_async_result_set_from_error (priv->result, &error); complete_operation (self, TRUE); } tp_base_channel_destroyed (channel); } /** * @dbus_error: (out) (transfer full): the D-Bus error name * @details: (out) (transfer full) (element-type utf8 GObject.Value): the * error details * @reason: (out): the reason with which to disconnect * @error: (out): an error in a domain Wocky understands describing what went * wrong * * Returns: %TRUE if an error was copied; %FALSE leaving the 'out' parameters * untouched if there is no error */ gboolean gabble_server_sasl_channel_get_failure_details (GabbleServerSaslChannel *self, gchar **dbus_error, GHashTable **details, TpConnectionStatusReason *reason, GError **error) { if (self->priv->sasl_error != NULL) { if (dbus_error != NULL) *dbus_error = g_strdup (self->priv->sasl_error); if (details != NULL) *details = g_hash_table_ref (self->priv->sasl_error_details); if (reason != NULL) *reason = self->priv->disconnect_reason; if (error != NULL) *error = g_error_copy (self->priv->wocky_auth_error); return TRUE; } else { return FALSE; } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/src/call-stream.c�����������������������������������������������������������0000664�0001750�0001750�00000043665�12332441362�021353� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gabble-call-stream.c - Source for GabbleCallStream * Copyright (C) 2009 Collabora Ltd. * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include <stdio.h> #include <stdlib.h> #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #include "call-stream.h" #include "connection.h" #include "jingle-tp-util.h" #include "util.h" #define DEBUG_FLAG GABBLE_DEBUG_MEDIA #include "debug.h" static GPtrArray *gabble_call_stream_add_candidates ( TpBaseMediaCallStream *stream, const GPtrArray *candidates, GError **error); static gboolean gabble_call_stream_set_sending (TpBaseMediaCallStream *stream, gboolean sending, GError **error); static void gabble_call_stream_request_receiving (TpBaseMediaCallStream *stream, TpHandle contact, gboolean receive); G_DEFINE_TYPE(GabbleCallStream, gabble_call_stream, TP_TYPE_BASE_MEDIA_CALL_STREAM) /* properties */ enum { PROP_JINGLE_CONTENT = 1, /* Media interface properties */ PROP_LOCAL_CANDIDATES, PROP_ENDPOINTS, PROP_TRANSPORT, PROP_STUN_SERVERS, PROP_RELAY_INFO, PROP_HAS_SERVER_INFO, PROP_CAN_REQUEST_RECEIVING }; #if 0 /* signal enum */ enum { LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; #endif /* private structure */ struct _GabbleCallStreamPrivate { gboolean dispose_has_run; WockyJingleContent *content; }; static void gabble_call_stream_init (GabbleCallStream *self) { GabbleCallStreamPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_CALL_STREAM, GabbleCallStreamPrivate); self->priv = priv; } static void gabble_call_stream_dispose (GObject *object); static void gabble_call_stream_finalize (GObject *object); static GPtrArray * get_stun_servers (GabbleCallStream *self) { GPtrArray *arr; WockyJingleFactory *jf; GList *stun_servers; arr = g_ptr_array_new_with_free_func ((GDestroyNotify) g_value_array_free); jf = wocky_jingle_session_get_factory (self->priv->content->session); stun_servers = wocky_jingle_info_get_stun_servers ( wocky_jingle_factory_get_jingle_info (jf)); while (stun_servers != NULL) { WockyStunServer *stun_server = stun_servers->data; GValueArray *va = tp_value_array_build (2, G_TYPE_STRING, stun_server->address, G_TYPE_UINT, (guint) stun_server->port, G_TYPE_INVALID); g_ptr_array_add (arr, va); stun_servers = g_list_delete_link (stun_servers, stun_servers); } return arr; } static void gabble_call_stream_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleCallStream *stream = GABBLE_CALL_STREAM (object); GabbleCallStreamPrivate *priv = stream->priv; switch (property_id) { case PROP_JINGLE_CONTENT: g_value_set_object (value, priv->content); break; case PROP_CAN_REQUEST_RECEIVING: { WockyJingleDialect dialect = wocky_jingle_session_get_dialect (priv->content->session); g_value_set_boolean (value, !WOCKY_JINGLE_DIALECT_IS_GOOGLE (dialect)); } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gabble_call_stream_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleCallStream *stream = GABBLE_CALL_STREAM (object); GabbleCallStreamPrivate *priv = stream->priv; switch (property_id) { case PROP_JINGLE_CONTENT: priv->content = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void google_relay_session_cb (GPtrArray *relays, gpointer user_data) { TpWeakRef *weak_ref = user_data; TpBaseMediaCallStream *stream = TP_BASE_MEDIA_CALL_STREAM ( tp_weak_ref_dup_object (weak_ref)); if (stream != NULL) { GPtrArray *tp_relays = gabble_build_tp_relay_info (relays); tp_base_media_call_stream_set_relay_info (stream, tp_relays); g_ptr_array_unref (tp_relays); g_object_unref (stream); } tp_weak_ref_destroy (weak_ref); } static void content_state_changed_cb (WockyJingleContent *content, GParamSpec *spec, gpointer user_data) { GabbleCallStream *self = GABBLE_CALL_STREAM (user_data); gabble_call_stream_update_member_states (self); } static void content_remote_members_changed_cb (WockyJingleContent *content, GParamSpec *spec, gpointer user_data) { GabbleCallStream *self = GABBLE_CALL_STREAM (user_data); gabble_call_stream_update_member_states (self); } static void jingle_info_stun_server_changed_cb ( WockyJingleInfo *jingle_info, const gchar *stun_server, guint stun_port, GabbleCallStream *self) { GPtrArray *stun_servers = get_stun_servers (self); tp_base_media_call_stream_set_stun_servers ( TP_BASE_MEDIA_CALL_STREAM (self), stun_servers); g_ptr_array_unref (stun_servers); } static void _new_candidates_cb ( WockyJingleContent *content, GList *candidates, TpCallStreamEndpoint *endpoint) { GPtrArray *tp_candidates; gchar *ufrag, *pwd; if (candidates == NULL) return; if (wocky_jingle_content_get_credentials (content, &ufrag, &pwd)) tp_call_stream_endpoint_set_remote_credentials (endpoint, ufrag, pwd); tp_candidates = gabble_call_candidates_to_array (candidates); tp_call_stream_endpoint_add_new_candidates (endpoint, tp_candidates); g_boxed_free (TP_ARRAY_TYPE_CANDIDATE_LIST, tp_candidates); } static void _endpoint_state_changed_cb ( TpCallStreamEndpoint *endpoint, GParamSpec *spec, WockyJingleContent *content) { TpMediaStreamState state; /* We only care about connecting RTP, RTCP is optional */ state = tp_call_stream_endpoint_get_state (endpoint, 1); wocky_jingle_content_set_transport_state (content, state); } static TpCallStreamEndpoint * _hook_up_endpoint (GabbleCallStream *self, const gchar *path, WockyJingleContent *content) { TpBaseCallStream *base = (TpBaseCallStream *) self; TpBaseConnection *conn = tp_base_call_stream_get_connection (base); TpDBusDaemon *bus = tp_base_connection_get_dbus_daemon (conn); TpCallStreamEndpoint *endpoint; TpStreamTransportType type = 0; GPtrArray *tp_candidates; GList *candidates; gchar *ufrag, *pwd; switch (wocky_jingle_content_get_transport_type (content)) { case JINGLE_TRANSPORT_GOOGLE_P2P: type = TP_STREAM_TRANSPORT_TYPE_GTALK_P2P; break; case JINGLE_TRANSPORT_RAW_UDP: type = TP_STREAM_TRANSPORT_TYPE_RAW_UDP; break; case JINGLE_TRANSPORT_ICE_UDP: type = TP_STREAM_TRANSPORT_TYPE_ICE; break; case JINGLE_TRANSPORT_UNKNOWN: default: g_assert_not_reached (); } /* FIXME: ice??? */ endpoint = tp_call_stream_endpoint_new (bus, path, type, FALSE); if (wocky_jingle_content_get_credentials (content, &ufrag, &pwd)) tp_call_stream_endpoint_set_remote_credentials (endpoint, ufrag, pwd); candidates = wocky_jingle_content_get_remote_candidates (content); tp_candidates = gabble_call_candidates_to_array (candidates); tp_call_stream_endpoint_add_new_candidates (endpoint, tp_candidates); g_boxed_free (TP_ARRAY_TYPE_CANDIDATE_LIST, tp_candidates); tp_g_signal_connect_object (content, "new-candidates", G_CALLBACK (_new_candidates_cb), endpoint, 0); tp_g_signal_connect_object (endpoint, "notify::endpoint-state", G_CALLBACK(_endpoint_state_changed_cb), content, 0); return endpoint; } static void gabble_call_stream_constructed (GObject *obj) { GabbleCallStream *self = GABBLE_CALL_STREAM (obj); TpBaseCallStream *base = (TpBaseCallStream *) self; TpBaseMediaCallStream *media_base = (TpBaseMediaCallStream *) self; GabbleCallStreamPrivate *priv = self->priv; GabbleConnection *conn; TpCallStreamEndpoint *endpoint; gchar *path; WockyJingleTransportType transport; GPtrArray *stun_servers; gboolean locally_created; if (G_OBJECT_CLASS (gabble_call_stream_parent_class)->constructed != NULL) G_OBJECT_CLASS (gabble_call_stream_parent_class)->constructed (obj); conn = GABBLE_CONNECTION (tp_base_call_stream_get_connection (base)); g_object_get (priv->content, "locally-created", &locally_created, NULL); if (locally_created && wocky_jingle_content_sending (priv->content)) tp_base_media_call_stream_set_local_sending ( TP_BASE_MEDIA_CALL_STREAM (self), TRUE); /* Currently we'll only have one endpoint we know right away */ path = g_strdup_printf ("%s/Endpoint", tp_base_call_stream_get_object_path (base)); endpoint = _hook_up_endpoint (self, path, priv->content); tp_base_media_call_stream_add_endpoint (media_base, endpoint); g_object_unref (endpoint); g_free (path); transport = wocky_jingle_content_get_transport_type (priv->content); if (transport == JINGLE_TRANSPORT_GOOGLE_P2P) { DEBUG ("Attempting to create Google relay session"); /* See if our server is Google, and if it is, ask them for a relay. * We ask for enough relays for 2 components (RTP and RTCP) since we * don't yet know whether there will be RTCP. */ wocky_jingle_info_create_google_relay_session ( gabble_jingle_mint_get_info (conn->jingle_mint), 2, google_relay_session_cb, tp_weak_ref_new (self, NULL, NULL)); } else { GPtrArray *relays = g_ptr_array_new (); tp_base_media_call_stream_set_relay_info (media_base, relays); g_ptr_array_unref (relays); } stun_servers = get_stun_servers (self); tp_base_media_call_stream_set_stun_servers ( TP_BASE_MEDIA_CALL_STREAM (self), stun_servers); g_ptr_array_unref (stun_servers); gabble_call_stream_update_member_states (GABBLE_CALL_STREAM (obj)); gabble_signal_connect_weak (priv->content, "notify::state", G_CALLBACK (content_state_changed_cb), obj); gabble_signal_connect_weak (priv->content, "notify::senders", G_CALLBACK (content_remote_members_changed_cb), obj); gabble_signal_connect_weak ( gabble_jingle_mint_get_info (conn->jingle_mint), "stun-server-changed", G_CALLBACK (jingle_info_stun_server_changed_cb), obj); } void gabble_call_stream_update_member_states (GabbleCallStream *self) { TpBaseCallStream *base = TP_BASE_CALL_STREAM (self); TpBaseMediaCallStream *bmcs = TP_BASE_MEDIA_CALL_STREAM (self); GabbleCallStreamPrivate *priv = self->priv; WockyJingleContentState state; TpSendingState local_state; TpSendingState remote_state; TpBaseConnection *conn = tp_base_call_stream_get_connection (base); TpHandleRepoIface *contact_repo = tp_base_connection_get_handles ( conn, TP_HANDLE_TYPE_CONTACT); TpHandle peer; g_object_get (priv->content, "state", &state, NULL); if (state == WOCKY_JINGLE_CONTENT_STATE_REMOVING) return; local_state = tp_base_call_stream_get_local_sending_state (base); remote_state = tp_base_call_stream_get_remote_sending_state (base, 0); if (wocky_jingle_content_sending (priv->content)) { if (tp_base_media_call_stream_get_local_sending (bmcs)) local_state = TP_SENDING_STATE_SENDING; else local_state = TP_SENDING_STATE_PENDING_SEND; } else { if (tp_base_media_call_stream_get_local_sending (bmcs)) local_state = TP_SENDING_STATE_PENDING_STOP_SENDING; else local_state = TP_SENDING_STATE_NONE; } if (wocky_jingle_content_receiving (priv->content)) { remote_state = TP_SENDING_STATE_SENDING; } else { remote_state = TP_SENDING_STATE_NONE; } DEBUG ("State: %d Local: %d Remote: %d", state, local_state, remote_state); tp_base_call_stream_update_local_sending_state (base, local_state, 0, TP_CALL_STATE_CHANGE_REASON_PROGRESS_MADE, "", ""); peer = tp_handle_ensure (contact_repo, wocky_jingle_session_get_peer_jid (priv->content->session), NULL, NULL); tp_base_call_stream_update_remote_sending_state (base, peer, remote_state, 0, TP_CALL_STATE_CHANGE_REASON_PROGRESS_MADE, "", ""); } static void gabble_call_stream_class_init (GabbleCallStreamClass *gabble_call_stream_class) { GObjectClass *object_class = G_OBJECT_CLASS (gabble_call_stream_class); TpBaseMediaCallStreamClass *bmcs_class = TP_BASE_MEDIA_CALL_STREAM_CLASS (gabble_call_stream_class); GParamSpec *param_spec; g_type_class_add_private (gabble_call_stream_class, sizeof (GabbleCallStreamPrivate)); object_class->set_property = gabble_call_stream_set_property; object_class->get_property = gabble_call_stream_get_property; object_class->dispose = gabble_call_stream_dispose; object_class->finalize = gabble_call_stream_finalize; object_class->constructed = gabble_call_stream_constructed; param_spec = g_param_spec_object ("jingle-content", "Jingle Content", "The Jingle Content related to this content object", WOCKY_TYPE_JINGLE_CONTENT, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_JINGLE_CONTENT, param_spec); g_object_class_override_property (object_class, PROP_CAN_REQUEST_RECEIVING, "can-request-receiving"); bmcs_class->add_local_candidates = gabble_call_stream_add_candidates; bmcs_class->set_sending = gabble_call_stream_set_sending; bmcs_class->request_receiving = gabble_call_stream_request_receiving; } void gabble_call_stream_dispose (GObject *object) { GabbleCallStream *self = GABBLE_CALL_STREAM (object); GabbleCallStreamPrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; tp_clear_object (&priv->content); if (G_OBJECT_CLASS (gabble_call_stream_parent_class)->dispose) G_OBJECT_CLASS (gabble_call_stream_parent_class)->dispose (object); } void gabble_call_stream_finalize (GObject *object) { G_OBJECT_CLASS (gabble_call_stream_parent_class)->finalize (object); } static GPtrArray * gabble_call_stream_add_candidates (TpBaseMediaCallStream *stream, const GPtrArray *candidates, GError **error) { GabbleCallStream *self = GABBLE_CALL_STREAM (stream); GabbleCallStreamPrivate *priv = self->priv; GPtrArray *accepted_candidates = g_ptr_array_sized_new (candidates->len); GList *l = NULL; guint i; for (i = 0; i < candidates->len ; i++) { GValueArray *va; WockyJingleCandidate *c; GHashTable *info; guint tptype; WockyJingleCandidateType type; /* borrowed strings, owned by other people. */ const gchar *username; const gchar *password; const gchar *foundation; va = g_ptr_array_index (candidates, i); info = g_value_get_boxed (va->values + 3); tptype = tp_asv_get_uint32 (info, "type", NULL); switch (tptype) { default: /* Anything else is local */ case TP_CALL_STREAM_CANDIDATE_TYPE_HOST: type = WOCKY_JINGLE_CANDIDATE_TYPE_LOCAL; break; case TP_CALL_STREAM_CANDIDATE_TYPE_SERVER_REFLEXIVE: type = WOCKY_JINGLE_CANDIDATE_TYPE_STUN; break; case TP_CALL_STREAM_CANDIDATE_TYPE_RELAY: type = WOCKY_JINGLE_CANDIDATE_TYPE_RELAY; break; } username = tp_asv_get_string (info, "username"); if (username == NULL) username = tp_base_media_call_stream_get_username (stream); password = tp_asv_get_string (info, "password"); if (password == NULL) password = tp_base_media_call_stream_get_password (stream); foundation = tp_asv_get_string (info, "foundation"); if (foundation == NULL) foundation = "1"; c = wocky_jingle_candidate_new ( /* transport protocol */ tp_asv_get_uint32 (info, "protocol", NULL), /* Candidate type */ type, /* id/foundation */ foundation, /* component */ g_value_get_uint (va->values + 0), /* ip */ g_value_get_string (va->values + 1), /* port */ g_value_get_uint (va->values + 2), /* generation */ 0, /* preference */ tp_asv_get_uint32 (info, "priority", NULL), /* username, password */ username, password, /* network */ 0); l = g_list_append (l, c); g_ptr_array_add (accepted_candidates, va); } wocky_jingle_content_add_candidates (priv->content, l); if (accepted_candidates->len == 0 && candidates->len != 0) { g_set_error_literal (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "All candidates had the wrong Type"); tp_clear_pointer (&accepted_candidates, g_ptr_array_unref); } return accepted_candidates; } static gboolean gabble_call_stream_set_sending (TpBaseMediaCallStream *stream, gboolean sending, GError **error) { GabbleCallStream *self = GABBLE_CALL_STREAM (stream); if (sending) tp_base_media_call_stream_set_local_sending (stream, TRUE); wocky_jingle_content_set_sending (self->priv->content, sending); return TRUE; } static void gabble_call_stream_request_receiving (TpBaseMediaCallStream *stream, TpHandle contact, gboolean receive) { GabbleCallStream *self = GABBLE_CALL_STREAM (stream); wocky_jingle_content_request_receiving (self->priv->content, receive); } WockyJingleContent * gabble_call_stream_get_jingle_content (GabbleCallStream *stream) { return stream->priv->content; } ���������������������������������������������������������������������������telepathy-gabble-0.18.3/src/plugin.c����������������������������������������������������������������0000664�0001750�0001750�00000014522�12223562023�020430� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * plugin.c — API for telepathy-gabble plugins * Copyright © 2009 Collabora Ltd. * Copyright © 2009 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "gabble/plugin.h" #include <telepathy-glib/telepathy-glib.h> #define DEBUG_FLAG GABBLE_DEBUG_PLUGINS #include "debug.h" GType gabble_plugin_get_type (void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof (GabblePluginInterface), NULL, /* base_init */ NULL, /* base_finalize */ NULL, /* class_init */ NULL, /* class_finalize */ NULL, /* class_data */ 0, 0, /* n_preallocs */ NULL /* instance_init */ }; type = g_type_register_static (G_TYPE_INTERFACE, "GabblePlugin", &info, 0); } return type; } const gchar * gabble_plugin_get_name (GabblePlugin *plugin) { GabblePluginInterface *iface = GABBLE_PLUGIN_GET_INTERFACE (plugin); return iface->name; } const gchar * gabble_plugin_get_version (GabblePlugin *plugin) { GabblePluginInterface *iface = GABBLE_PLUGIN_GET_INTERFACE (plugin); return iface->version; } const gchar * const * gabble_plugin_get_sidecar_interfaces (GabblePlugin *plugin) { GabblePluginInterface *iface = GABBLE_PLUGIN_GET_INTERFACE (plugin); return iface->sidecar_interfaces; } gboolean gabble_plugin_implements_sidecar ( GabblePlugin *plugin, const gchar *sidecar_interface) { GabblePluginInterface *iface = GABBLE_PLUGIN_GET_INTERFACE (plugin); return tp_strv_contains (iface->sidecar_interfaces, sidecar_interface); } /** * gabble_plugin_create_sidecar: * @plugin: a plugin * @sidecar_interface: the primary D-Bus interface implemented by the sidecar, * which must be a member of the list returned by * gabble_plugin_get_sidecar_interfaces () * @callback: function to call when the new sidecar has been created, or an * unrecoverable error has occured * @user_data: data to pass to @callback */ void gabble_plugin_create_sidecar_async ( GabblePlugin *plugin, const gchar *sidecar_interface, GabblePluginConnection *plugin_connection, WockySession *session, GAsyncReadyCallback callback, gpointer user_data) { GabblePluginInterface *iface = GABBLE_PLUGIN_GET_INTERFACE (plugin); if (!gabble_plugin_implements_sidecar (plugin, sidecar_interface)) g_simple_async_report_error_in_idle (G_OBJECT (plugin), callback, user_data, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "Gabble is buggy: '%s' doesn't implement sidecar %s", iface->name, sidecar_interface); else if (iface->create_sidecar_async == NULL) g_simple_async_report_error_in_idle (G_OBJECT (plugin), callback, user_data, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "'%s' is buggy: it claims to implement %s, but does not implement " "create_sidecar_async", iface->name, sidecar_interface); else if (iface->create_sidecar_finish == NULL) g_simple_async_report_error_in_idle (G_OBJECT (plugin), callback, user_data, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "'%s' is buggy: does not imlement create_sidecar_finish", iface->name); else iface->create_sidecar_async (plugin, sidecar_interface, plugin_connection, session, callback, user_data); } GabbleSidecar * gabble_plugin_create_sidecar_finish ( GabblePlugin *plugin, GAsyncResult *result, GError **error) { GabblePluginInterface *iface = GABBLE_PLUGIN_GET_INTERFACE (plugin); GabbleSidecar *sidecar; if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) return NULL; if (iface->create_sidecar_finish == NULL) { WARNING ("'%s' is buggy: does not implement create_sidecar_finish", iface->name); return NULL; } sidecar = iface->create_sidecar_finish (plugin, result, error); return g_object_ref (sidecar); } const TpPresenceStatusSpec * gabble_plugin_get_custom_presence_statuses ( GabblePlugin *plugin) { GabblePluginInterface *iface = GABBLE_PLUGIN_GET_INTERFACE (plugin); return iface->presence_statuses; } gboolean gabble_plugin_implements_presence_status ( GabblePlugin *plugin, const gchar *status) { GabblePluginInterface *iface = GABBLE_PLUGIN_GET_INTERFACE (plugin); gint i; if (iface->presence_statuses == NULL) return FALSE; for (i = 0; iface->presence_statuses[i].name; i++) { if (!tp_strdiff (status, iface->presence_statuses[i].name)) return TRUE; } return FALSE; } const gchar * gabble_plugin_presence_status_for_privacy_list ( GabblePlugin *plugin, const gchar *list_name) { GabblePluginInterface *iface = GABBLE_PLUGIN_GET_INTERFACE (plugin); int i; if (iface->privacy_list_map == NULL) return NULL; for (i = 0; iface->privacy_list_map[i].privacy_list_name; i++) { if (!tp_strdiff (list_name, iface->privacy_list_map[i].privacy_list_name)) { DEBUG ("Plugin %s links presence %s with privacy list %s", iface->name, iface->privacy_list_map[i].privacy_list_name, iface->privacy_list_map[i].presence_status_name); return iface->privacy_list_map[i].presence_status_name; } } DEBUG ("No plugins link presence to privacy list %s", list_name); return NULL; } GPtrArray * gabble_plugin_create_channel_managers (GabblePlugin *plugin, GabblePluginConnection *plugin_connection) { GabblePluginInterface *iface = GABBLE_PLUGIN_GET_INTERFACE (plugin); GabblePluginCreateChannelManagersImpl func = iface->create_channel_managers; GPtrArray *out = NULL; if (func != NULL) out = func (plugin, plugin_connection); return out; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/Makefile.am�����������������������������������������������������������������0000664�0001750�0001750�00000001153�12332441362�020232� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ACLOCAL_AMFLAGS = -I m4 SUBDIRS = docs tools extensions lib src data m4 plugins tests gabble DISTCHECK_CONFIGURE_FLAGS = --disable-debug --enable-gtk-doc CLEANFILES = FIXME.out check-twisted: all $(MAKE) -C tests/twisted check-twisted check-all: check check-twisted check-local:: egrep -A 5 '[F]IXME|[T]ODO|[X]XX' $(srcdir)/src/*.[ch] \ > FIXME.out || true include tools/lcov.am LCOV_CHECK_ARGS = CHECK_TWISTED_SLEEP=6 CHANGELOG_RANGE = telepathy-gabble-0.12.0.. CHECK_FOR_UNRELEASED = \ $(srcdir)/NEWS \ $(wildcard $(srcdir)/gabble/*.[ch]) \ $(wildcard $(srcdir)/src/*.[ch]) include tools/telepathy.am ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/missing���������������������������������������������������������������������0000755�0001750�0001750�00000015331�12332443655�017605� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2012-06-26.16; # UTC # Copyright (C) 1996-2013 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996. # 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, see <http://www.gnu.org/licenses/>. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to <bug-automake@gnu.org>." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=http://www.perl.org/ flex_URL=http://flex.sourceforge.net/ gnu_software_URL=http://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'automa4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/INSTALL���������������������������������������������������������������������0000644�0001750�0001750�00000036605�12332443655�017246� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������Installation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX `make' updates targets which have the same time stamps as their prerequisites, which makes it generally unusable when shipped generated files such as `configure' are involved. Use GNU `make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `<wchar.h>' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf limitation. Until the limitation is lifted, you can use this workaround: CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. ���������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/extensions/�����������������������������������������������������������������0000775�0001750�0001750�00000000000�12332445272�020401� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/extensions/OLPC_Activity_Properties.xml�������������������������������������0000664�0001750�0001750�00000011320�12332440117�025736� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" ?> <node name="/OLPC_Activity_Properties" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> <tp:copyright> Copyright (C) 2007 Collabora Limited </tp:copyright> <tp:license xmlns="http://www.w3.org/1999/xhtml"> <p>This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.</p> <p>This library 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 Lesser General Public License for more details.</p> <p>You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA</p> </tp:license> <interface name="org.laptop.Telepathy.ActivityProperties"> <tp:requires interface="org.freedesktop.Telepathy.Connection"/> <method name="SetProperties" tp:name-for-bindings="Set_Properties"> <arg direction="in" name="room" type="u"> <tp:docstring> An integer handle representing the room of the activity </tp:docstring> </arg> <arg direction="in" name="properties" type="a{sv}"> <tp:docstring> A dictionary mapping properties names to the desired values </tp:docstring> </arg> <tp:docstring> Set the properties of the activity associated to the given room for this connection. You have to be the owner of this activity. </tp:docstring> <tp:possible-errors> <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> <tp:error name="org.freedesktop.Telepathy.Error.PermissionDenied"/> </tp:possible-errors> </method> <method name="GetProperties" tp:name-for-bindings="Get_Properties"> <arg direction="in" name="room" type="u"> <tp:docstring> An integer handle for the activity's room to request his properties for </tp:docstring> </arg> <arg direction="out" name="properties" type="a{sv}"> <tp:docstring> A dictionary mapping properties names to their values </tp:docstring> </arg> <tp:docstring> Get the properties of a particular activity. </tp:docstring> <tp:possible-errors> <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> </tp:possible-errors> </method> <method name="GetActivity" tp:name-for-bindings="Get_Activity"> <arg direction="in" name="activity_id" type="s"> <tp:docstring> An activity id </tp:docstring> </arg> <arg direction="out" name="room" type="u"> <tp:docstring> A room handle </tp:docstring> </arg> <tp:docstring> Returns the handle of the room associated with this activity <tp:rationale> <p>When an activity starts up, it knows its activity_id but doesn't know yet if it's shared or not, much less the room.</p> </tp:rationale> </tp:docstring> <tp:possible-errors> <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> </tp:possible-errors> </method> <signal name="ActivityPropertiesChanged" tp:name-for-bindings="Activity_Properties_Changed"> <arg name="room" type="u"> <tp:docstring> An integer handle representing the room of the activity </tp:docstring> </arg> <arg name="properties" type="a{sv}"> <tp:docstring> A dictionary mapping properties names to their new values </tp:docstring> </arg> <tp:docstring> Signal emitted when the properties of an activity are changed. </tp:docstring> </signal> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>An interface on connections to associate OLPC activity properties with rooms.</p> <p>The following types and names are used to request and set properties:</p> <dl> <dt>s:color</dt> <dd>The color of the activity. Format used is #RRGGBB,#RRGGBB (stroke,fill).</dd> <dt>s:name</dt> <dd>The name of the activity.</dd> <dt>s:type</dt> <dd>The type of the activity.</dd> </dl> </tp:docstring> </interface> </node> <!-- vim:set sw=2 sts=2 et ft=xml: --> ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/extensions/Channel_Type_FileTransfer_Future.xml�����������������������������0000664�0001750�0001750�00000006253�12332441362�027474� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" ?> <node name="/Channel_Type_FileTransfer_Future" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> <tp:copyright>Copyright (C) 2010 Collabora Ltd.</tp:copyright> <tp:license xmlns="http://www.w3.org/1999/xhtml"> <p>This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.</p> <p>This library 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 Lesser General Public License for more details.</p> <p>You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</p> </tp:license> <interface name="org.freedesktop.Telepathy.Channel.Type.FileTransfer.FUTURE" tp:causes-havoc="a staging area for future File Transfer Channel functionality"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>This interface contains functionality which we intend to incorporate into the File Transfer Channel interface in future. It should be considered to be conceptually part of the core File Transfer Channel interface, but without API or ABI guarantees.</p> <tp:rationale> <p>If we add new functionality to the Channel interface, libraries that use generated code (notably telepathy-glib) will have it as part of their ABI forever, meaning we can't make incompatible changes. By using this interface as a staging area for future Channel functionality, we can try out new properties, signals and methods as application-specific extensions, then merge them into the core Channel interface when we have enough implementation experience to declare them to be stable.</p> <p>The name is by analogy to Python's <code>__future__</code> pseudo-module.</p> </tp:rationale> </tp:docstring> <property name="FileCollection" tp:name-for-bindings="FileCollection" type="s" access="read"> <tp:added version="0.19.2">(in Channel.Type.FileTransfer.FUTURE pseudo-interface)</tp:added> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>The FileCollection to which this channel belongs.</p> <p>A channel's FileCollection property can never change.</p> <p>At least on GTalk and apparently also on iChat the user can send a set of files to a contact and that contact can then pick and choose which files to actually receive. The CM should emit all new FT channels belonging to one collection at the same time, UIs supporting this feature can then bundle all these channels together in some way and show a nice UI. UIs not supporting it will treat them as seperate transfers, which is not great but a reasonable fallback</p> </tp:docstring> </property> </interface> </node> <!-- vim:set sw=2 sts=2 et ft=xml: --> �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/extensions/Makefile.am������������������������������������������������������0000664�0001750�0001750�00000006564�12332441362�022444� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������tools_dir = $(top_srcdir)/tools EXTRA_DIST = \ all.xml \ Channel_Type_FileTransfer_Future.xml \ Connection_Future.xml \ Connection_Interface_Addressing.xml \ Connection_Interface_Gabble_Decloak.xml \ Gabble_Plugin_Console.xml \ Gabble_Plugin_Gateways.xml \ Gabble_Plugin_Test.xml \ OLPC_Activity_Properties.xml \ OLPC_Buddy_Info.xml \ $(NULL) noinst_LTLIBRARIES = libgabble-extensions.la libgabble_extensions_la_SOURCES = \ extensions.c \ extensions.h nodist_libgabble_extensions_la_SOURCES = \ _gen/enums.h \ _gen/enums-gtk-doc.h \ _gen/gtypes.h \ _gen/gtypes-body.h \ _gen/gtypes-gtk-doc.h \ _gen/interfaces.h \ _gen/interfaces-body.h \ _gen/interfaces-gtk-doc.h \ _gen/svc.h \ _gen/svc.c \ _gen/svc-gtk-doc.h \ $(NULL) BUILT_SOURCES = \ _gen/all.xml \ $(nodist_libgabble_extensions_la_SOURCES) \ extensions.html CLEANFILES = $(BUILT_SOURCES) AM_CFLAGS = $(ERROR_CFLAGS) @DBUS_CFLAGS@ @GLIB_CFLAGS@ @TP_GLIB_CFLAGS@ AM_LDFLAGS = @DBUS_LIBS@ @GLIB_LIBS@ @TP_GLIB_LIBS@ # Generated stuff DROP_NAMESPACE = sed -e 's@xmlns:tp="http://telepathy\.freedesktop\.org/wiki/DbusSpec.extensions-v0"@@g' XSLTPROCFLAGS = --nonet --novalid _gen/all.xml: all.xml $(wildcard *.xml) Makefile.am @$(mkdir_p) _gen $(AM_V_GEN)$(PYTHON) $(tools_dir)/xincludator.py \ $< > $@.tmp && mv $@.tmp $@ extensions.html: _gen/all.xml $(tools_dir)/doc-generator.xsl Makefile.am $(AM_V_GEN)$(XSLTPROC) $(XSLTPROCFLAGS) \ --param "allow-undefined-interfaces" "true()" \ $(tools_dir)/doc-generator.xsl \ $< > $@ _gen/svc.h: _gen/svc.c @: # do nothing, output as a side-effect _gen/svc-gtk-doc.h: _gen/svc.c @: # do nothing, output as a side-effect _gen/svc.c: _gen/all.xml $(tools_dir)/glib-ginterface-gen.py Makefile.am $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-ginterface-gen.py \ --filename=_gen/svc \ --include='<telepathy-glib/telepathy-glib.h>' \ --allow-unstable \ --not-implemented-func='tp_dbus_g_method_return_not_implemented' \ $< Gabble_Svc_ _gen/enums-gtk-doc.h: _gen/enums.h @: # do nothing, output as a side-effect _gen/enums.h: _gen/all.xml $(tools_dir)/c-constants-gen.py Makefile.am $(AM_V_GEN)$(PYTHON) $(tools_dir)/c-constants-gen.py Gabble $< _gen/enums _gen/interfaces-body.h: _gen/interfaces.h @: # do nothing, output as a side-effect _gen/interfaces-gtk-doc.h: _gen/interfaces.h @: # do nothing, output as a side-effect _gen/interfaces.h: _gen/all.xml $(tools_dir)/glib-interfaces-gen.py Makefile.am $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-interfaces-gen.py \ Gabble _gen/interfaces-body.h _gen/interfaces.h $< _gen/gtypes.h: _gen/gtypes-body.h @: # do nothing, output as a side-effect _gen/gtypes-gtk-doc.h: _gen/gtypes-body.h @: # do nothing, output as a side-effect _gen/gtypes-body.h: _gen/all.xml $(tools_dir)/glib-gtypes-generator.py Makefile.am $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-gtypes-generator.py \ $< _gen/gtypes Gabble Android.mk: Makefile.am $(BUILT_SOURCES) androgenizer -:PROJECT telepathy-gabble -:STATIC gabble-extensions -:TAGS eng debug \ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ -:SOURCES $(libgabble_extensions_la_SOURCES) \ $(nodist_libgabble_extensions_la_SOURCES) \ -:CFLAGS $(DEFS) $(CFLAGS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CFLAGS) \ -:CPPFLAGS $(CPPFLAGS) $(AM_CPPFLAGS) \ -:LDFLAGS $(libgabble_extensions_la_LIBADD) \ > $@ ��������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/extensions/Gabble_Plugin_Gateways.xml���������������������������������������0000664�0001750�0001750�00000006421�12332440117�025455� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" ?> <node name="/Gabble_Plugin_Gateways" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> <tp:copyright>Copyright © 2010 Collabora Ltd.</tp:copyright> <tp:license xmlns="http://www.w3.org/1999/xhtml"> <p>This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.</p> <p>This library 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 Lesser General Public License for more details.</p> <p>You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</p> </tp:license> <interface name="org.freedesktop.Telepathy.Gabble.Plugin.Gateways"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>A sidecar interface to register with XEP-0100 gateways.</p> </tp:docstring> <method name="Register" tp:name-for-bindings="Register"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>Register with a gateway, as per XEP-0100 §4.1. This method does not allow for all the parameters that gateways can potentially have, and indeed doesn't even allow the required or allowed parameters to be discovered, but it should work in practice for nearly all gateways to other IM protocols.</p> <tp:rationale> <p>Username and password are enough information to sign in to many IM protocols, and this method has a high "return on investment" in terms of being easy to implement and easy to write UI for.</p> </tp:rationale> </tp:docstring> <arg direction="in" type="s" name="Gateway"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>The gateway (XMPP component) with which to register, e.g. "sip-transport.example.com".</p> </tp:docstring> </arg> <arg direction="in" type="s" name="Username"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>The username with which to register, in whatever format is required by the specified gateway; for instance, this might be a number, the username part of a SIP URI, a complete SIP URI, etc.</p> </tp:docstring> </arg> <arg direction="in" type="s" name="Password"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>The password with which to register.</p> </tp:docstring> </arg> <tp:possible-errors> <tp:error name="org.freedesktop.Telepathy.Error.NetworkError"/> <tp:error name="org.freedesktop.Telepathy.Error.NotAvailable"/> <tp:error name="org.freedesktop.Telepathy.Error.NotImplemented"/> <tp:error name="org.freedesktop.Telepathy.Error.PermissionDenied"/> </tp:possible-errors> </method> </interface> </node> <!-- vim:set sw=2 sts=2 et ft=xml: --> �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/extensions/extensions.h�����������������������������������������������������0000644�0001750�0001750�00000000414�11165152371�022744� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef _GABBLE_EXTENSIONS_H #define _GABBLE_EXTENSIONS_H #include "extensions/_gen/enums.h" #include "extensions/_gen/svc.h" G_BEGIN_DECLS #include "extensions/_gen/gtypes.h" #include "extensions/_gen/interfaces.h" G_END_DECLS #endif /* _GABBLE_EXTENSIONS_H */ ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/extensions/Gabble_Plugin_Console.xml����������������������������������������0000664�0001750�0001750�00000011051�12332441362�025271� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" ?> <node name="/Gabble_Plugin_Console" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> <tp:copyright>Copyright © 2011 Collabora Ltd.</tp:copyright> <tp:license xmlns="http://www.w3.org/1999/xhtml"> <p>This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.</p> <p>This library 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 Lesser General Public License for more details.</p> <p>You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</p> </tp:license> <interface name="org.freedesktop.Telepathy.Gabble.Plugin.Console"> <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>A sidecar interface providing an XMPP console.</p> </tp:docstring> <method name="SendIQ" tp:name-for-bindings="Send_IQ"> <arg direction="in" name="Type" type="s"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> The type of IQ request to send; either <code>"get"</code> or <code>"set"</code>. </tp:docstring> </arg> <arg direction="in" name="To" type="s"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> The recipient for the IQ; or the empty string to send an IQ to the server (with no recipient specified). </tp:docstring> </arg> <arg direction="in" name="Body" type="s"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> An XML fragment for the body of the IQ, which MUST have exactly one top-level element. </tp:docstring> </arg> <arg direction="out" name="Reply_Type" type="s"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> The type of IQ reply; either <code>"result"</code> or <code>"error"</code>. </tp:docstring> </arg> <arg direction="out" name="Body" type="s"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> An XML fragment for the body of the response, which MUST have between zero and two top-level elements (the query element, an error element, both, or neither). </tp:docstring> </arg> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> Hai. </tp:docstring> </method> <method name="SendStanza" tp:name-for-bindings="Send_Stanza"> <arg direction="in" name="Stanza" type="s"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> A complete stanza. </tp:docstring> </arg> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> Sends a stanza, yo. </tp:docstring> </method> <signal name="StanzaSent" tp:name-for-bindings="Stanza_Sent"> <arg name="Stanza" type="s"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> The stanza, in glorious XML. </tp:docstring> </arg> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> Emitted whenever a stanza is sent and <tp:member-ref>SpewStanzas</tp:member-ref> is <code>True</code>. </tp:docstring> </signal> <signal name="StanzaReceived" tp:name-for-bindings="Stanza_Received"> <arg name="Stanza" type="s"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> The stanza, in glorious XML. </tp:docstring> </arg> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> Emitted whenever a stanza is received and <tp:member-ref>SpewStanzas</tp:member-ref> is <code>True</code>. </tp:docstring> </signal> <property name="SpewStanzas" type="b" access="readwrite" tp:name-for-bindings="Spew_Stanzas"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> If <code>True</code>, <tp:member-ref>StanzaReceived</tp:member-ref> and <tp:member-ref>StanzaSent</tp:member-ref> will be emitted, drowning your session bus in a sea of XML. </tp:docstring> </property> </interface> </node> <!-- vim:set sw=2 sts=2 et ft=xml: --> ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/extensions/Connection_Future.xml��������������������������������������������0000664�0001750�0001750�00000012402�12332441362�024547� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" ?> <node name="/Connection_FUTURE" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" > <tp:copyright>Copyright © 2009 Collabora Limited</tp:copyright> <tp:copyright>Copyright © 2009 Nokia Corporation</tp:copyright> <tp:license xmlns="http://www.w3.org/1999/xhtml"> <p>This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.</p> <p>This library 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 Lesser General Public License for more details.</p> <p>You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</p> </tp:license> <interface name="org.freedesktop.Telepathy.Connection.FUTURE" tp:causes-havoc='experimental'> <tp:requires interface="org.freedesktop.Telepathy.Connection"/> <method name="EnsureSidecar" tp:name-for-bindings="Ensure_Sidecar"> <tp:added version="0.19.UNRELEASED"/> <arg direction="in" name="Main_Interface" type="s" tp:type="DBus_Interface"> <tp:docstring> The "primary" interface implemented by an object attached to a connection. For example, a Gabble plugin implementing fine-grained control of XEP-0016 privacy lists might expose an object implementing <tt>com.example.PrivacyLists</tt>. </tp:docstring> </arg> <arg direction="out" name="Path" type="o"> <tp:docstring>The object path of the sidecar, exported by the same bus name as the Connection to which it is attached.</tp:docstring> </arg> <arg direction="out" name="Properties" type="a{sv}" tp:type="Qualified_Property_Value_Map"> <tp:docstring>Immutable properties of the sidecar.</tp:docstring> </arg> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>Request an object with a particular interface providing additional connection-specific functionality, together with its immutable properties. These will often be implemented by plug-ins to the connection managers; for example, support for an XMPP XEP for which no generic Telepathy interface exists might be implemented by a Gabble plugin exposing a sidecar with a particular interface.</p> <p>This method may be called at any point during the lifetime of a connection, even before its <tp:type>Connection_Status</tp:type> changes to Connected. It MAY take a long time to return—perhaps it needs to wait for a connection to be established and for all the services supported by the server to be discovered before determining whether necessary server-side support is available—so callers SHOULD override the default method timeout (25 seconds) with a much higher value (perhaps even MAX_INT32, meaning “no timeout” in recent versions of libdbus).</p> <tp:rationale> <p>There is an implicit assumption that any connection manager plugin will only want to export one “primary” object per feature it implements, since there is a one-to-one mapping between interface and object. This is reasonable since Sidecars are (intended to be) analogous to extra interfaces on the connection, providing once-per-connection shared functionality; it also makes client code straightforward (look up the interface you care about in a dictionary, build a proxy object from the value). More “plural” plugins are likely to want to implement new types of <tp:dbus-ref namespace="org.freedesktop.Telepathy">Channel</tp:dbus-ref> instead.</p> </tp:rationale> </tp:docstring> <tp:error name="org.freedesktop.Telepathy.Error.NotImplemented"> <tp:docstring> The requested sidecar is not implemented by this connection manager, or a necessary server-side component does not exist. (FIXME: split these two errors out? Then again, once we list the guaranteed and possible sidecars on a Protocol object, clients can tell the difference themselves, because they shouldn't be calling this in the first case.) </tp:docstring> </tp:error> <tp:error name="org.freedesktop.Telepathy.Error.ServiceBusy"> <tp:docstring> A server-side component needed by the requested sidecar reported it is currently too busy, or did not respond for some implementation-defined time. The caller may wish to try again later. </tp:docstring> </tp:error> <tp:error name="org.freedesktop.Telepathy.Error.Cancelled"> <tp:docstring> The connection was disconnected while the sidecar was being set up. </tp:docstring> </tp:error> </method> </interface> </node> ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/extensions/Connection_Interface_Addressing.xml������������������������������0000664�0001750�0001750�00000025474�12332441362�027355� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" ?> <node name="/Connection_Interface_Addressing" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> <tp:copyright> Copyright (C) 2010 Collabora Limited </tp:copyright> <tp:license xmlns="http://www.w3.org/1999/xhtml"> <p>This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.</p> <p>This library 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 Lesser General Public License for more details.</p> <p>You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</p> </tp:license> <interface name="org.freedesktop.Telepathy.Connection.Interface.Addressing1" tp:causes-havoc="experimental"> <tp:requires interface="org.freedesktop.Telepathy.Connection"/> <tp:requires interface="org.freedesktop.Telepathy.Connection.Interface.Contacts"/> <tp:added version="0.19.12">(as draft)</tp:added> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>This interface deals with the multiple address types that can refer to the same contact, such as vCard fields and URIs.</p> <p>It can be used to retrieve contacts with a specific addresses through <tp:member-ref>GetContactsByVCardField</tp:member-ref> and <tp:member-ref>GetContactsByURI</tp:member-ref>, as well as defining the various addressing methods for a given contact through this interface's contact attributes.</p> </tp:docstring> <method name="GetContactsByVCardField" tp:name-for-bindings="Get_Contacts_By_VCard_Field"> <arg direction="in" name="Field" type="s"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>The vCard field of the addresses we are requesting. The field name SHOULD be in lower case. Supported fields can be found in <tp:dbus-ref namespace="org.freedesktop.Telepathy.Protocol.Interface.Addressing">AddressableVCardFields</tp:dbus-ref>.</p> <p>The <code>url</code> vCard field MUST NOT appear here; see <tp:member-ref>GetContactsByURI</tp:member-ref> instead.</p> <tp:rationale> <p>In practice, protocols have a limited set of URI schemes that make sense to resolve as a contact.</p> </tp:rationale> </tp:docstring> </arg> <arg direction="in" name="Addresses" type="as"> <tp:docstring> The addresses to get contact handles for. The address types should match the given vCard field. </tp:docstring> </arg> <arg direction="in" name="Interfaces" type="as" tp:type="DBus_Interface[]"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>A list of strings indicating which D-Bus interfaces the calling process is interested in. All supported attributes from these interfaces, whose values can be obtained without additional network activity, will be in the reply.</p> <p>Attributes from this interface and from <tp:dbus-ref>org.freedesktop.Telepathy.Connection</tp:dbus-ref> are always returned, and need not be requested explicitly.</p> <p>The behavior of this parameter is similar to the same parameter in <tp:dbus-ref namespace="org.freedesktop.Telepathy.Connection.Interface">Contacts.GetContactAttributes</tp:dbus-ref>.</p> </tp:docstring> </arg> <arg direction="out" type="a{su}" name="Requested" tp:type="Addressing_Normalization_Map"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>A mapping from requested vCard addresses to the corresponding contact handles.</p> <p>Requested addresses that are not valid or understood for this protocol MUST be omitted from the mapping.</p> </tp:docstring> </arg> <arg direction="out" type="a{ua{sv}}" name="Attributes" tp:type="Contact_Attributes_Map"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>A dictionary mapping the contact handles to contact attributes. If any of the requested addresses are in fact invalid, they are simply omitted from this mapping. If contact attributes are not immediately known, the behaviour is defined by the interface; the attribute should either be omitted from the result or replaced with a default value.</p> <p>Requested addresses that are not valid or understood for this protocol MUST be omitted from the mapping.</p> <p>Each contact's attributes will always include at least the identifier that would be obtained by inspecting the handle (<code>org.freedesktop.Telepathy.Connection/contact-id</code>). </p> </tp:docstring> </arg> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>Request contacts and retrieve their attributes using a given field in their vCards.</p> <p>The connection manager should record that these handles are in use by the client who invokes this method, and must not deallocate the handles until the client disconnects from the bus or calls the <tp:dbus-ref namespace="org.freedesktop.Telepathy">Connection.ReleaseHandles</tp:dbus-ref> method.</p> </tp:docstring> <tp:possible-errors> <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> </tp:possible-errors> </method> <method name="GetContactsByURI" tp:name-for-bindings="Get_Contacts_By_URI"> <arg direction="in" name="URIs" type="as"> <tp:docstring> The URI addresses to get contact handles for. Supported schemes can be found in <tp:dbus-ref namespace="org.freedesktop.Telepathy.Protocol.Interface.Addressing">AddressableURISchemes</tp:dbus-ref>. </tp:docstring> </arg> <arg direction="in" name="Interfaces" type="as" tp:type="DBus_Interface[]"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>A list of strings indicating which D-Bus interfaces the calling process is interested in. All supported attributes from these interfaces, whose values can be obtained without additional network activity, will be in the reply.</p> <p>Attributes from this interface and from <tp:dbus-ref>org.freedesktop.Telepathy.Connection</tp:dbus-ref> are always returned, and need not be requested explicitly.</p> <p>The behavior of this parameter is similar to the same parameter in <tp:dbus-ref namespace="org.freedesktop.Telepathy.Connection.Interface">Contacts.GetContactAttributes</tp:dbus-ref>.</p> </tp:docstring> </arg> <arg direction="out" type="a{su}" name="Requested" tp:type="Addressing_Normalization_Map"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>A mapping of requested URIs to the corresponding contact handles.</p> <p>Requested URIs that are not valid or understood for this protocol MUST be omitted from the mapping.</p> </tp:docstring> </arg> <arg direction="out" type="a{ua{sv}}" name="Attributes" tp:type="Contact_Attributes_Map"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>A dictionary mapping the contact handles to contact attributes. If any of the requested addresses are in fact invalid, they are simply omitted from this mapping. If contact attributes are not immediately known, the behaviour is defined by the interface; the attribute should either be omitted from the result or replaced with a default value.</p> <p>Requested URIs that are not valid or understood for this protocol MUST be omitted from the mapping.</p> <p>Each contact's attributes will always include at least the identifier that would be obtained by inspecting the handle (<code>org.freedesktop.Telepathy.Connection/contact-id</code>). </p> </tp:docstring> </arg> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>Request contacts and retrieve their attributes using URI addresses.</p> <p>The connection manager should record that these handles are in use by the client who invokes this method, and must not deallocate the handles until the client disconnects from the bus or calls the <tp:dbus-ref namespace="org.freedesktop.Telepathy">Connection.ReleaseHandles</tp:dbus-ref> method.</p> </tp:docstring> <tp:possible-errors> <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> </tp:possible-errors> </method> <tp:mapping name="VCard_Field_Address_Map" array-name=""> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>A mapping of vCard fields and addresses that repreent the given contact.</p> </tp:docstring> <tp:member type="s" name="VCard_Field"/> <tp:member type="s" name="Address"/> </tp:mapping> <tp:contact-attribute name="addresses" type="a{ss}" tp:type="VCard_Field_Address_Map"> <tp:docstring> The various vCard addresses that identify this contact. </tp:docstring> </tp:contact-attribute> <tp:contact-attribute name="uris" type="as"> <tp:docstring> The various URI addresses that identify this contact. </tp:docstring> </tp:contact-attribute> <tp:mapping name="Addressing_Normalization_Map"> <tp:docstring> A map from URIs/vCard addresses to the corresponding handle. </tp:docstring> <tp:added version="0.25.UNRELEASED"/> <tp:member type="s" name="Requested_String"> <tp:docstring> The URI or vCard address that has been requested by <tp:member-ref>GetContactsByVCardField</tp:member-ref> or <tp:member-ref>GetContactsByURI</tp:member-ref>. </tp:docstring> </tp:member> <tp:member type="u" name="Handle" tp:type="Contact_Handle"> <tp:docstring> A nonzero handle. </tp:docstring> </tp:member> </tp:mapping> </interface> </node> <!-- vim:set sw=2 sts=2 et ft=xml: --> ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/extensions/all.xml����������������������������������������������������������0000664�0001750�0001750�00000015546�12332441362�021702� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<tp:spec xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" xmlns:xi="http://www.w3.org/2001/XInclude"> <tp:title>Gabble-specific extensions to the Telepathy interfaces</tp:title> <tp:copyright>Copyright (C) 2007 Collabora Limited</tp:copyright> <tp:license xmlns="http://www.w3.org/1999/xhtml"> <p>This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.</p> <p>This library 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 Lesser General Public License for more details.</p> <p>You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA</p> </tp:license> <tp:generic-types> <tp:external-type name="Room_Handle" type="u" from="Telepathy specification"/> <tp:external-type name="Handle_Type" type="u" from="Telepathy specification"/> <tp:external-type name="Contact_Handle" type="u" from="Telepathy specification"/> <tp:external-type name="DBus_Unique_Name" type="s" from="Telepathy specification"/> </tp:generic-types> <xi:include href="Connection_Interface_Addressing.xml"/> <xi:include href="OLPC_Buddy_Info.xml"/> <xi:include href="OLPC_Activity_Properties.xml"/> <xi:include href="Channel_Type_FileTransfer_Future.xml"/> <xi:include href="Connection_Interface_Gabble_Decloak.xml"/> <xi:include href="Connection_Future.xml"/> <xi:include href="Gabble_Plugin_Console.xml"/> <xi:include href="Gabble_Plugin_Gateways.xml"/> <xi:include href="Gabble_Plugin_Test.xml"/> <tp:generic-types> <tp:external-type name="Contact_Handle" type="u" from="Telepathy specification"/> <tp:external-type name="DBus_Interface" type="s" from="Telepathy specification"/> <tp:external-type name="DBus_Qualified_Member" type="s" from="Telepathy specification"/> <tp:external-type name="Qualified_Property_Value_Map" type="a{sv}" from="Telepathy specification"/> <tp:external-type name="DBus_Error_Name" type="s" from="Telepathy specification"/> <tp:external-type name="DBus_Well_Known_Name" type="s" from="Telepathy specification"/> <tp:external-type name="Handler_Capability_Token" type="s" from="Telepathy specification"/> <tp:external-type name="VCard_Field" type="s" from="Telepathy specification"/> <tp:external-type name="VCard_Type_Parameter" type="s" from="Telepathy specification"/> <tp:external-type name="Contact_Info_Field" type="(sasas)" from="Telepathy specification"/> <!-- for localisation --> <tp:external-type name="Rich_Presence_Access_Control_Type" type="u" from="Telepathy specification"/> <tp:external-type name="Rich_Presence_Access_Control" type="(uv)" from="Telepathy specification"/> <tp:external-type name="Unix_Timestamp64" type="x" from="Telepathy specification"/> <tp:external-type name="Unix_Timestamp" type="u" from="Telepathy specification"/> <tp:external-type name="String_String_Map" type="a{ss}" from="Telepathy specification"/> <tp:external-type name="String_Variant_Map" type="a{sv}" from="Telepathy specification"/> <!-- use types from Connection_Interface_Contacts --> <tp:external-type name="Contact_Attributes_Map" type="a{ua{sv}}" from="Telepathy specification"/> <!-- use types from Connection_Interface_Requests --> <tp:external-type name="Channel_Class" type="a{sv}" from="Telepathy specification"/> <!-- use types from Channel_Type_Tubes --> <tp:external-type name="Socket_Address_Type" type="u" from="Telepathy specification"/> <tp:external-type name="Socket_Access_Control" type="u" from="Telepathy specification"/> <tp:external-type name="Supported_Socket_Map" type="a{uau}" from="Telepathy specification"/> <tp:external-type name="DBus_Tube_Member" type="(us)" from="Telepathy specification"/> <!-- use types from Connection_Interface_Contact_Capabilities --> <tp:external-type name="Requestable_Channel_Class" type="(a{sv}as)" from="Telepathy specification"/> <tp:external-type name="Connection_Status" type="u" from="Telepathy specification"/> <!-- use types from Channel_Type_Streamed_Media.xml --> <tp:enum name="Media_Stream_Type" type="u" array-name="Media_Stream_Type_List"> <tp:enumvalue suffix="Audio" value="0"> <tp:docstring>An audio stream</tp:docstring> </tp:enumvalue> <tp:enumvalue suffix="Video" value="1"> <tp:docstring>A video stream</tp:docstring> </tp:enumvalue> </tp:enum> <!-- use types from generic-types.xml --> <tp:struct name="Socket_Address_IP" array-name="Socket_Address_IP_List"> <tp:docstring>An IP address and port.</tp:docstring> <tp:member type="s" name="Address"> <tp:docstring>Either a dotted-quad IPv4 address literal as for <tp:type>Socket_Address_IPv4</tp:type>, or an RFC2373 IPv6 address as for <tp:type>Socket_Address_IPv6</tp:type>. </tp:docstring> </tp:member> <tp:member type="q" name="Port"> <tp:docstring>The TCP or UDP port number.</tp:docstring> </tp:member> </tp:struct> <tp:struct name="Socket_Address_IPv4"> <tp:docstring>An IPv4 address and port.</tp:docstring> <tp:member type="s" name="Address"> <tp:docstring>A dotted-quad IPv4 address literal: four ASCII decimal numbers, each between 0 and 255 inclusive, e.g. "192.168.0.1".</tp:docstring> </tp:member> <tp:member type="q" name="Port"> <tp:docstring>The TCP or UDP port number.</tp:docstring> </tp:member> </tp:struct> <tp:struct name="Socket_Address_IPv6"> <tp:docstring>An IPv6 address and port.</tp:docstring> <tp:member type="s" name="Address"> <tp:docstring>An IPv6 address literal as specified by RFC2373 section 2.2, e.g. "2001:DB8::8:800:200C:4171".</tp:docstring> </tp:member> <tp:member type="q" name="Port"> <tp:docstring>The TCP or UDP port number.</tp:docstring> </tp:member> </tp:struct> <tp:enum name="Media_Stream_State" type="u"> <tp:enumvalue suffix="Disconnected" value="0"> <tp:docstring>The stream is disconnected.</tp:docstring> </tp:enumvalue> <tp:enumvalue suffix="Connecting" value="1"> <tp:docstring>The stream is trying to connect.</tp:docstring> </tp:enumvalue> <tp:enumvalue suffix="Connected" value="2"> <tp:docstring>The stream is connected.</tp:docstring> </tp:enumvalue> </tp:enum> <tp:simple-type name="Handle" type="u" array-name="Handle_List"> <tp:docstring>An unsigned 32-bit integer representing a handle</tp:docstring> </tp:simple-type> </tp:generic-types> </tp:spec> ����������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/extensions/extensions.c�����������������������������������������������������0000664�0001750�0001750�00000000210�12223562023�022726� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "config.h" #include "extensions.h" /* auto-generated stubs */ #include "_gen/gtypes-body.h" #include "_gen/interfaces-body.h" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/extensions/Gabble_Plugin_Test.xml�������������������������������������������0000664�0001750�0001750�00000002405�12332440117�024606� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" ?> <node name="/Gabble_Plugin_Test" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> <tp:copyright>Copyright © 2009 Collabora Ltd.</tp:copyright> <tp:license xmlns="http://www.w3.org/1999/xhtml"> <p>This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.</p> <p>This library 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 Lesser General Public License for more details.</p> <p>You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</p> </tp:license> <interface name="org.freedesktop.Telepathy.Gabble.Plugin.Test"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>A sidecar interface implemented by a plugin used by the test suite.</p> </tp:docstring> </interface> </node> <!-- vim:set sw=2 sts=2 et ft=xml: --> �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/extensions/Makefile.in������������������������������������������������������0000664�0001750�0001750�00000055346�12332443655�022466� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = extensions DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_config_dir.m4 \ $(top_srcdir)/m4/compiler.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/tp-compiler-flag.m4 \ $(top_srcdir)/m4/tp-compiler-warnings.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libgabble_extensions_la_LIBADD = am_libgabble_extensions_la_OBJECTS = extensions.lo nodist_libgabble_extensions_la_OBJECTS = svc.lo libgabble_extensions_la_OBJECTS = \ $(am_libgabble_extensions_la_OBJECTS) \ $(nodist_libgabble_extensions_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgabble_extensions_la_SOURCES) \ $(nodist_libgabble_extensions_la_SOURCES) DIST_SOURCES = $(libgabble_extensions_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLIENT_TYPE = @CLIENT_TYPE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_CODING_STYLE_CHECKS = @ENABLE_CODING_STYLE_CHECKS@ ENABLE_PLUGINS = @ENABLE_PLUGINS@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NICE_CFLAGS = @NICE_CFLAGS@ NICE_LIBS = @NICE_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOUP_CFLAGS = @SOUP_CFLAGS@ SOUP_LIBS = @SOUP_LIBS@ STRIP = @STRIP@ TEST_PYTHON = @TEST_PYTHON@ TP_GLIB_CFLAGS = @TP_GLIB_CFLAGS@ TP_GLIB_LIBS = @TP_GLIB_LIBS@ VERSION = @VERSION@ WOCKY_CFLAGS = @WOCKY_CFLAGS@ WOCKY_LIBS = @WOCKY_LIBS@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gabbletestsdir = @gabbletestsdir@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ pluginexecdir = @pluginexecdir@ pluginexeclibdir = @pluginexeclibdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ tools_dir = $(top_srcdir)/tools EXTRA_DIST = \ all.xml \ Channel_Type_FileTransfer_Future.xml \ Connection_Future.xml \ Connection_Interface_Addressing.xml \ Connection_Interface_Gabble_Decloak.xml \ Gabble_Plugin_Console.xml \ Gabble_Plugin_Gateways.xml \ Gabble_Plugin_Test.xml \ OLPC_Activity_Properties.xml \ OLPC_Buddy_Info.xml \ $(NULL) noinst_LTLIBRARIES = libgabble-extensions.la libgabble_extensions_la_SOURCES = \ extensions.c \ extensions.h nodist_libgabble_extensions_la_SOURCES = \ _gen/enums.h \ _gen/enums-gtk-doc.h \ _gen/gtypes.h \ _gen/gtypes-body.h \ _gen/gtypes-gtk-doc.h \ _gen/interfaces.h \ _gen/interfaces-body.h \ _gen/interfaces-gtk-doc.h \ _gen/svc.h \ _gen/svc.c \ _gen/svc-gtk-doc.h \ $(NULL) BUILT_SOURCES = \ _gen/all.xml \ $(nodist_libgabble_extensions_la_SOURCES) \ extensions.html CLEANFILES = $(BUILT_SOURCES) AM_CFLAGS = $(ERROR_CFLAGS) @DBUS_CFLAGS@ @GLIB_CFLAGS@ @TP_GLIB_CFLAGS@ AM_LDFLAGS = @DBUS_LIBS@ @GLIB_LIBS@ @TP_GLIB_LIBS@ # Generated stuff DROP_NAMESPACE = sed -e 's@xmlns:tp="http://telepathy\.freedesktop\.org/wiki/DbusSpec.extensions-v0"@@g' XSLTPROCFLAGS = --nonet --novalid all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu extensions/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu extensions/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgabble-extensions.la: $(libgabble_extensions_la_OBJECTS) $(libgabble_extensions_la_DEPENDENCIES) $(EXTRA_libgabble_extensions_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libgabble_extensions_la_OBJECTS) $(libgabble_extensions_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extensions.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/svc.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< svc.lo: _gen/svc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT svc.lo -MD -MP -MF $(DEPDIR)/svc.Tpo -c -o svc.lo `test -f '_gen/svc.c' || echo '$(srcdir)/'`_gen/svc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/svc.Tpo $(DEPDIR)/svc.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='_gen/svc.c' object='svc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o svc.lo `test -f '_gen/svc.c' || echo '$(srcdir)/'`_gen/svc.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: all check install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am _gen/all.xml: all.xml $(wildcard *.xml) Makefile.am @$(mkdir_p) _gen $(AM_V_GEN)$(PYTHON) $(tools_dir)/xincludator.py \ $< > $@.tmp && mv $@.tmp $@ extensions.html: _gen/all.xml $(tools_dir)/doc-generator.xsl Makefile.am $(AM_V_GEN)$(XSLTPROC) $(XSLTPROCFLAGS) \ --param "allow-undefined-interfaces" "true()" \ $(tools_dir)/doc-generator.xsl \ $< > $@ _gen/svc.h: _gen/svc.c @: # do nothing, output as a side-effect _gen/svc-gtk-doc.h: _gen/svc.c @: # do nothing, output as a side-effect _gen/svc.c: _gen/all.xml $(tools_dir)/glib-ginterface-gen.py Makefile.am $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-ginterface-gen.py \ --filename=_gen/svc \ --include='<telepathy-glib/telepathy-glib.h>' \ --allow-unstable \ --not-implemented-func='tp_dbus_g_method_return_not_implemented' \ $< Gabble_Svc_ _gen/enums-gtk-doc.h: _gen/enums.h @: # do nothing, output as a side-effect _gen/enums.h: _gen/all.xml $(tools_dir)/c-constants-gen.py Makefile.am $(AM_V_GEN)$(PYTHON) $(tools_dir)/c-constants-gen.py Gabble $< _gen/enums _gen/interfaces-body.h: _gen/interfaces.h @: # do nothing, output as a side-effect _gen/interfaces-gtk-doc.h: _gen/interfaces.h @: # do nothing, output as a side-effect _gen/interfaces.h: _gen/all.xml $(tools_dir)/glib-interfaces-gen.py Makefile.am $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-interfaces-gen.py \ Gabble _gen/interfaces-body.h _gen/interfaces.h $< _gen/gtypes.h: _gen/gtypes-body.h @: # do nothing, output as a side-effect _gen/gtypes-gtk-doc.h: _gen/gtypes-body.h @: # do nothing, output as a side-effect _gen/gtypes-body.h: _gen/all.xml $(tools_dir)/glib-gtypes-generator.py Makefile.am $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-gtypes-generator.py \ $< _gen/gtypes Gabble Android.mk: Makefile.am $(BUILT_SOURCES) androgenizer -:PROJECT telepathy-gabble -:STATIC gabble-extensions -:TAGS eng debug \ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ -:SOURCES $(libgabble_extensions_la_SOURCES) \ $(nodist_libgabble_extensions_la_SOURCES) \ -:CFLAGS $(DEFS) $(CFLAGS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CFLAGS) \ -:CPPFLAGS $(CPPFLAGS) $(AM_CPPFLAGS) \ -:LDFLAGS $(libgabble_extensions_la_LIBADD) \ > $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/extensions/OLPC_Buddy_Info.xml����������������������������������������������0000664�0001750�0001750�00000025313�12332440117�023757� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" ?> <node name="/OLPC_Buddy_Info" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> <tp:copyright> Copyright (C) 2007 Collabora Limited </tp:copyright> <tp:license xmlns="http://www.w3.org/1999/xhtml"> <p>This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.</p> <p>This library 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 Lesser General Public License for more details.</p> <p>You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA</p> </tp:license> <interface name="org.laptop.Telepathy.BuddyInfo"> <tp:requires interface="org.freedesktop.Telepathy.Connection"/> <method name="SetProperties" tp:name-for-bindings="Set_Properties"> <arg direction="in" name="properties" type="a{sv}"> <tp:docstring> A dictionary mapping information names to the desired values. This replaces any existing buddy properties completely: any keys which were previously present, but are not present in this dictionary, are deleted. </tp:docstring> </arg> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>Set the information of the local user for this connection.</p> <p>This method may be called before Connect(), in which case the given properties will be advertised as soon as possible after connection (possibly immediately).</p> </tp:docstring> <tp:possible-errors> <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> </tp:possible-errors> </method> <method name="GetProperties" tp:name-for-bindings="Get_Properties"> <arg direction="in" name="contact" type="u"> <tp:docstring> An integer handle for the contact to request his properties for </tp:docstring> </arg> <arg direction="out" name="properties" type="a{sv}"> <tp:docstring> A dictionary mapping information names to their values </tp:docstring> </arg> <tp:docstring> Get the properties of a particular contact. </tp:docstring> <tp:possible-errors> <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> </tp:possible-errors> </method> <signal name="PropertiesChanged" tp:name-for-bindings="Properties_Changed"> <arg name="contact" type="u"> <tp:docstring> An integer handle representing the contact </tp:docstring> </arg> <arg name="properties" type="a{sv}"> <tp:docstring> A dictionary mapping property names to their new values. All properties are included, not just those that have changed. </tp:docstring> </arg> <tp:docstring> Signal emitted when the properties of a contact from your 'subscribe' contact list are changed. </tp:docstring> </signal> <tp:struct name="Activity" array-name="Activity_List"> <tp:docstring>A struct containing: <ul> <li>the identifier of the activity</li> <li>the room handle of the activity channel</li> </ul> </tp:docstring> <tp:member type="s" name="id"/> <tp:member type="u" tp:type="Room_Handle" name="room"/> </tp:struct> <method name="SetActivities" tp:name-for-bindings="Set_Activities"> <arg direction="in" name="activities" type="a(su)" tp:type="Activity[]"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> An array of structs containing: <ul> <li>the identifier of the activity</li> <li>the room handle of the activity channel</li> </ul> </tp:docstring> </arg> <tp:docstring> Set the activities of the local user for this connection. </tp:docstring> <tp:possible-errors> <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> </tp:possible-errors> </method> <method name="AddActivity" tp:name-for-bindings="Add_Activity"> <arg direction="in" name="id" type="s"> <tp:docstring> An activity id </tp:docstring> </arg> <arg direction="in" name="handle" type="u"> <tp:docstring> A room handle </tp:docstring> </arg> <tp:docstring> Advertise an activity associated to a muc room <tp:rationale> <p>Once an activity shares itself, needs to be advertised if it's not private. SetActivities could be used for this but it would mean that the activity would need to call GetActivities then add itself.</p> </tp:rationale> </tp:docstring> <tp:possible-errors> <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> </tp:possible-errors> </method> <method name="GetActivities" tp:name-for-bindings="Get_Activities"> <arg direction="in" name="contact" type="u"> <tp:docstring> An integer handle for the contact whose activities are to be returned </tp:docstring> </arg> <arg direction="out" name="activities" type="a(su)" tp:type="Activity[]"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> An array of structs containing: <ul> <li>the identifier of the activity</li> <li>the room handle of the activity channel</li> </ul> </tp:docstring> </arg> <tp:docstring> Get the activities of a particular contact. </tp:docstring> <tp:possible-errors> <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> </tp:possible-errors> </method> <signal name="ActivitiesChanged" tp:name-for-bindings="Activities_Changed"> <arg name="contact" type="u"> <tp:docstring> An integer handle representing the contact </tp:docstring> </arg> <arg name="activities" type="a(su)" tp:type="Activity[]"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> An array of structs containing: <ul> <li>the identifier of the activity</li> <li>the handle of the activity channel</li> </ul> </tp:docstring> </arg> <tp:docstring> Signal emitted when the activities of a contact from your 'subscribe' contact list are changed. </tp:docstring> </signal> <method name="SetCurrentActivity" tp:name-for-bindings="Set_Current_Activity"> <arg direction="in" name="activity" type="s"> <tp:docstring> The identifier of the activity, or the empty string if there is no current activity </tp:docstring> </arg> <arg direction="in" name="channel" type="u"> <tp:docstring> The room handle of the activity channel, or 0 if there is no current activity </tp:docstring> </arg> <tp:docstring> Set the current activity of the local user for this connection. </tp:docstring> <tp:possible-errors> <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> </tp:possible-errors> </method> <method name="GetCurrentActivity" tp:name-for-bindings="Get_Current_Activity"> <arg direction="in" name="contact" type="u"> <tp:docstring> An integer handle for the contact whose current activity is to be returned </tp:docstring> </arg> <arg direction="out" name="activity" type="s"> <tp:docstring> The identifier of the activity, or "" if there is no current activity </tp:docstring> </arg> <arg direction="out" name="channel" type="u"> <tp:docstring> The room handle of the activity, or 0 if there is no current activity </tp:docstring> </arg> <tp:docstring> Get the current activity of a particular contact. </tp:docstring> <tp:possible-errors> <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> </tp:possible-errors> </method> <signal name="CurrentActivityChanged" tp:name-for-bindings="Current_Activity_Changed"> <arg name="contact" type="u"> <tp:docstring> An integer handle representing the contact </tp:docstring> </arg> <arg name="activity" type="s"> <tp:docstring> The identifier of the activity, or "" if there is no current activity </tp:docstring> </arg> <arg name="channel" type="u"> <tp:docstring> The room handle of the activity channel, or 0 if there is no current activity </tp:docstring> </arg> <tp:docstring> Signal emitted when the current activity of a contact from your 'subscribe' contact list is changed. </tp:docstring> </signal> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>An interface on connections to associate OLPC buddy information with contacts, providing methods for the user to set their own information and retrieve information of contacts. The user is automatically notified when information of contacts that are in his 'subscribe' contact list change.</p> <p>The following types and names are used to request and set information (except for activities):</p> <dl> <dt>s:color</dt> <dd>The color name of the buddy. Format used is #RRGGBB,#RRGGBB (stroke,fill). </dd> <dt>ay:key</dt> <dd>The public key of the buddy.</dd> <dt>s:jid</dt> <dd>For link-local connections, the JID of the buddy's server account.</dd> </dl> <p>Activities are represented by a struct containing:</p> <ul> <li>the identifier of the activity</li> <li>the handle of the activity channel</li> </ul> </tp:docstring> </interface> </node> <!-- vim:set sw=2 sts=2 et ft=xml: --> ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/extensions/Connection_Interface_Gabble_Decloak.xml��������������������������0000664�0001750�0001750�00000011403�12332440117�030050� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" ?> <node name="/Connection_Interface_Gabble_Decloak" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> <tp:copyright>Copyright © 2010 Collabora Ltd.</tp:copyright> <tp:license xmlns="http://www.w3.org/1999/xhtml"> <p>This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.</p> <p>This library 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 Lesser General Public License for more details.</p> <p>You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</p> </tp:license> <interface name="org.freedesktop.Telepathy.Connection.Interface.Gabble.Decloak" tp:causes-havoc="experimental"> <tp:added version="Gabble 0.9.4">(Gabble-specific)</tp:added> <tp:requires interface="org.freedesktop.Telepathy.Connection"/> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> A simple D-Bus API for <a href="http://xmpp.org/extensions/xep-0276.html">XEP-0276 Temporary Presence Sharing</a>. See the XEP for more details. </tp:docstring> <property name="DecloakAutomatically" tp:name-for-bindings="Decloak_Automatically" type="b" access="readwrite"> <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> <p>If true, the connection manager will automatically disclose the local user's capabilities (and hence the fact that they are online, but no further presence information) on request from any remote XMPP user.</p> <tp:rationale> <p>This is necessary to allow incoming calls from arbitrary users.</p> </tp:rationale> <p>This property SHOULD also be available as a connection manager parameter, with the DBus_Property flag. The default SHOULD be false since this constitutes a deliberate presence leak.</p> </tp:docstring> </property> <signal name="DecloakRequested" tp:name-for-bindings="Decloak_Requested"> <tp:docstring> Emitted when a remote contact asks for the local user's capabilities and basic presence to be disclosed. </tp:docstring> <arg name="Contact" type="u" tp:type="Contact_Handle"> <tp:docstring> The contact asking for presence disclosure </tp:docstring> </arg> <arg name="Reason" type="s"> <tp:docstring> A code indicating the reason that decloaking is requested, or the empty string if no reason code was given. As per the proto-XEP, well-known values are 'media' (remote contact wants to call local user), 'text' (remote contact wants to establish a text messaging session, perhaps end-to-end encrypted), and 'file' (remote contact wants to send the local user a file). </tp:docstring> </arg> <arg name="Decloaked" type="b"> <tp:docstring> If true, the connection manager automatically disclosed the local user's capabilities and basic presence in response to the request, and this signal is merely for information. If false, presence was not automatically disclosed; a user interface MAY respond by calling <tp:member-ref>SendDirectedPresence</tp:member-ref>. </tp:docstring> </arg> </signal> <method name="SendDirectedPresence" tp:name-for-bindings="Send_Directed_Presence"> <tp:docstring> Send directed presence to a contact. This MAY be called at any time, but will typically be used as a response to <tp:member-ref>DecloakRequested</tp:member-ref> </tp:docstring> <arg direction="in" name="Contact" type="u" tp:type="Contact_Handle"> <tp:docstring> The contact to send directed presence to. </tp:docstring> </arg> <arg direction="in" name="Full" type="b"> <tp:docstring> If true, full presence (status, message, avatar hash etc.) will be directed to the specified contact. If false, only capabilities and the fact that the user is online at all will be directed to the specified contact (the local user will appear to that contact as being in 'available' status). </tp:docstring> </arg> </method> </interface> </node> <!-- vim:set sw=2 sts=2 et ft=xml: --> �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/configure�������������������������������������������������������������������0000775�0001750�0001750�00001760740�12332443654�020132� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for Telepathy Gabble 0.18.3. # # Report bugs to <https://bugs.freedesktop.org/enter_bug.cgi?product=Telepathy&component=gabble>. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and $0: https://bugs.freedesktop.org/enter_bug.cgi?product=Telepathy&component=gabble $0: about your system, including any error possibly output $0: before this message. Then install a modern shell, or $0: manually run the script under such a shell if you do $0: have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 </dev/null exec 6>&1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='Telepathy Gabble' PACKAGE_TARNAME='telepathy-gabble' PACKAGE_VERSION='0.18.3' PACKAGE_STRING='Telepathy Gabble 0.18.3' PACKAGE_BUGREPORT='https://bugs.freedesktop.org/enter_bug.cgi?product=Telepathy&component=gabble' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include <stdio.h> #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> #endif #ifdef HAVE_SYS_STAT_H # include <sys/stat.h> #endif #ifdef STDC_HEADERS # include <stdlib.h> # include <stddef.h> #else # ifdef HAVE_STDLIB_H # include <stdlib.h> # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include <memory.h> # endif # include <string.h> #endif #ifdef HAVE_STRINGS_H # include <strings.h> #endif #ifdef HAVE_INTTYPES_H # include <inttypes.h> #endif #ifdef HAVE_STDINT_H # include <stdint.h> #endif #ifdef HAVE_UNISTD_H # include <unistd.h> #endif" ac_header_list= enable_option_checking=no ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS ENABLE_JINGLE_FILE_TRANSFER_FALSE ENABLE_JINGLE_FILE_TRANSFER_TRUE NICE_LIBS NICE_CFLAGS ENABLE_VOIP_FALSE ENABLE_VOIP_TRUE ENABLE_FILE_TRANSFER_FALSE ENABLE_FILE_TRANSFER_TRUE ENABLE_GOOGLE_RELAY_FALSE ENABLE_GOOGLE_RELAY_TRUE SOUP_LIBS SOUP_CFLAGS WOCKY_LIBS WOCKY_CFLAGS WANT_TWISTED_TESTS_FALSE WANT_TWISTED_TESTS_TRUE TEST_PYTHON pkgpyexecdir pyexecdir pkgpythondir pythondir PYTHON_PLATFORM PYTHON_EXEC_PREFIX PYTHON_PREFIX PYTHON_VERSION PYTHON XSLTPROC TP_GLIB_LIBS TP_GLIB_CFLAGS DBUS_LIBS DBUS_CFLAGS ENABLE_CHANNEL_TYPE_CALL_FALSE ENABLE_CHANNEL_TYPE_CALL_TRUE ENABLE_PLUGIN_API_FALSE ENABLE_PLUGIN_API_TRUE ENABLE_PLUGINS ENABLE_PLUGINS_FALSE ENABLE_PLUGINS_TRUE pluginexecdir pluginexeclibdir GLIB_GENMARSHAL GMODULE_LIBS GMODULE_CFLAGS GLIB_LIBS GLIB_CFLAGS PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG ENABLE_GTK_DOC_FALSE ENABLE_GTK_DOC_TRUE ENABLE_FATAL_CRITICALS_FALSE ENABLE_FATAL_CRITICALS_TRUE CLIENT_TYPE gabbletestsdir ENABLE_INSTALLED_TESTS_FALSE ENABLE_INSTALLED_TESTS_TRUE ENABLE_CODING_STYLE_CHECKS ENABLE_DEBUG_FALSE ENABLE_DEBUG_TRUE WINDOWS_FALSE WINDOWS_TRUE ERROR_CFLAGS OFFICIAL_RELEASE_FALSE OFFICIAL_RELEASE_TRUE OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB ac_ct_AR AR DLLTOOL OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP SED host_os host_vendor host_cpu host build_os build_vendor build_cpu build LIBTOOL EGREP GREP CPP am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_dependency_tracking enable_shared enable_static with_pic enable_fast_install with_gnu_ld with_sysroot enable_libtool_lock enable_compiler_optimisations enable_compiler_coverage enable_Werror with_ca_certificates enable_debug enable_coding_style_checks enable_installed_tests enable_is_a_phone enable_fatal_criticals enable_gtk_doc enable_plugins enable_plugin_api enable_channel_type_call enable_submodules enable_google_relay enable_file_transfer enable_voip ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR GLIB_CFLAGS GLIB_LIBS GMODULE_CFLAGS GMODULE_LIBS pluginexeclibdir pluginexecdir DBUS_CFLAGS DBUS_LIBS TP_GLIB_CFLAGS TP_GLIB_LIBS PYTHON WOCKY_CFLAGS WOCKY_LIBS SOUP_CFLAGS SOUP_LIBS NICE_CFLAGS NICE_LIBS' ac_subdirs_all='lib/ext/wocky' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= 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=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -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_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$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 ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$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 | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$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 ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) 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 | -n) 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 ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$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_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=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 ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # 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 the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` 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 test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # 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 <<_ACEOF \`configure' configures Telepathy Gabble 0.18.3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/telepathy-gabble] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --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 System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of Telepathy Gabble 0.18.3:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --disable-compiler-optimisations Disable compiler optimisations --enable-compiler-coverage Enable generation of coverage data --disable-Werror compile without -Werror (normally enabled in development builds) --disable-debug compile without debug code --enable-coding-style-checks check coding style using grep --enable-installed-tests make tests installable --enable-is-a-phone advertise that we are a phone, not a PC --disable-fatal-criticals do not assert because of critical warnings --enable-gtk-doc does not actually do anything --disable-plugins disable plugin loader --enable-plugin-api install headers for third-party plugins (experimental) --disable-channel-type-call disable support for the draft Channel.Type.Call --disable-submodules Use system versions of Wocky, rather than submodules --disable-google-relay disable Google Jingle relay support --disable-file-transfer disable file transfer support --disable-voip disable VoIP support (and, consequently, Jingle-based file transfer support Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot=DIR Search for dependent libraries within DIR (or the compiler's sysroot if not specified). --with-ca-certificates=[path] path to system Certificate Authority list Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a nonstandard directory <lib dir> LIBS libraries to pass to the linker, e.g. -l<library> CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if you have headers in a nonstandard directory <include dir> CPP C preprocessor PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path GLIB_CFLAGS C compiler flags for GLIB, overriding pkg-config GLIB_LIBS linker flags for GLIB, overriding pkg-config GMODULE_CFLAGS C compiler flags for GMODULE, overriding pkg-config GMODULE_LIBS linker flags for GMODULE, overriding pkg-config pluginexeclibdir pluginexecdir DBUS_CFLAGS C compiler flags for DBUS, overriding pkg-config DBUS_LIBS linker flags for DBUS, overriding pkg-config TP_GLIB_CFLAGS C compiler flags for TP_GLIB, overriding pkg-config TP_GLIB_LIBS linker flags for TP_GLIB, overriding pkg-config PYTHON the Python interpreter WOCKY_CFLAGS C compiler flags for WOCKY, overriding pkg-config WOCKY_LIBS linker flags for WOCKY, overriding pkg-config SOUP_CFLAGS C compiler flags for SOUP, overriding pkg-config SOUP_LIBS linker flags for SOUP, overriding pkg-config NICE_CFLAGS C compiler flags for NICE, overriding pkg-config NICE_LIBS linker flags for NICE, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to <https://bugs.freedesktop.org/enter_bug.cgi?product=Telepathy&component=gabble>. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF Telepathy Gabble configure 0.18.3 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## -------------------------------------------------------------------------------------------- ## ## Report this to https://bugs.freedesktop.org/enter_bug.cgi?product=Telepathy&component=gabble ## ## -------------------------------------------------------------------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case <limits.h> declares $2. For example, HP-UX 11i <limits.h> declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by Telepathy Gabble $as_me 0.18.3, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi as_fn_append ac_header_list " arpa/inet.h" as_fn_append ac_header_list " arpa/nameser.h" as_fn_append ac_header_list " fcntl.h" as_fn_append ac_header_list " ifaddrs.h" as_fn_append ac_header_list " netdb.h" as_fn_append ac_header_list " netinet/in.h" as_fn_append ac_header_list " sys/ioctl.h" as_fn_append ac_header_list " sys/un.h" as_fn_append ac_header_list " unistd.h" # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu am__api_version='1.13' 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 elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # 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 # AmigaOS /C/install, which installs bootblocks on floppy discs # 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" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /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 for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir 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. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&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}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # 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 ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $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". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file 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" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='telepathy-gabble' VERSION='0.18.3' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> # <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> mkdir_p='$(MKDIR_P)' # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar plaintar pax cpio none' # The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether UID '$am_uid' is supported by ustar format" >&5 $as_echo_n "checking whether UID '$am_uid' is supported by ustar format... " >&6; } if test $am_uid -le $am_max_uid; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } _am_tools=none fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GID '$am_gid' is supported by ustar format" >&5 $as_echo_n "checking whether GID '$am_gid' is supported by ustar format... " >&6; } if test $am_gid -le $am_max_gid; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } _am_tools=none fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a ustar tar archive" >&5 $as_echo_n "checking how to create a ustar tar archive... " >&6; } # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_ustar-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do { echo "$as_me:$LINENO: $_am_tar --version" >&5 ($_am_tar --version) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && break done am__tar="$_am_tar --format=ustar -chf - "'"$$tardir"' am__tar_="$_am_tar --format=ustar -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x ustar -w "$$tardir"' am__tar_='pax -L -x ustar -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H ustar -L' am__tar_='find "$tardir" -print | cpio -o -H ustar -L' am__untar='cpio -i -H ustar -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_ustar}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5 (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } rm -rf conftest.dir if test -s conftest.tar; then { echo "$as_me:$LINENO: $am__untar <conftest.tar" >&5 ($am__untar <conftest.tar) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { echo "$as_me:$LINENO: cat conftest.dir/file" >&5 (cat conftest.dir/file) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } grep GrepMe conftest.dir/file >/dev/null 2>&1 && break fi done rm -rf conftest.dir if ${am_cv_prog_tar_ustar+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_prog_tar_ustar=$_am_tool fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_ustar" >&5 $as_echo "$am_cv_prog_tar_ustar" >&6; } ac_config_headers="$ac_config_headers config.h" DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_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 $# != 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 ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdio.h> int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdarg.h> #include <stdio.h> struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since # <limits.h> exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <ac_nonexistent.h> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since # <limits.h> exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <ac_nonexistent.h> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <float.h> int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <string.h> _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdlib.h> _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <ctype.h> #include <stdlib.h> #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" if test "x$ac_cv_header_minix_config_h" = xyes; then : MINIX=yes else MINIX= fi if test "$MINIX" = yes; then $as_echo "#define _POSIX_SOURCE 1" >>confdefs.h $as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h $as_echo "#define _MINIX 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 $as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } if ${ac_cv_safe_to_define___extensions__+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # define __EXTENSIONS__ 1 $ac_includes_default int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_safe_to_define___extensions__=yes else ac_cv_safe_to_define___extensions__=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 $as_echo "$ac_cv_safe_to_define___extensions__" >&6; } test $ac_cv_safe_to_define___extensions__ = yes && $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h $as_echo "#define _ALL_SOURCE 1" >>confdefs.h $as_echo "#define _GNU_SOURCE 1" >>confdefs.h $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_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 $# != 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 ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdarg.h> #include <stdio.h> struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi case $ac_cv_prog_cc_stdc in #( no) : ac_cv_prog_cc_c99=no; ac_cv_prog_cc_c89=no ;; #( *) : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 $as_echo_n "checking for $CC option to accept ISO C99... " >&6; } if ${ac_cv_prog_cc_c99+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdarg.h> #include <stdbool.h> #include <stdlib.h> #include <wchar.h> #include <stdio.h> // Check varargs macros. These examples are taken from C99 6.10.3.5. #define debug(...) fprintf (stderr, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK your preprocessor is broken; #endif #if BIG_OK #else your preprocessor is broken; #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // See if C++-style comments work. // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\0'; ++i) continue; return 0; } // Check varargs and va_copy. static void test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str; int number; float fnumber; while (*format) { switch (*format++) { case 's': // string str = va_arg (args_copy, const char *); break; case 'd': // int number = va_arg (args_copy, int); break; case 'f': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); } int main () { // Check bool. _Bool success = false; // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. test_varargs ("s, d' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' || dynamic_array[ni.number - 1] != 543); ; return 0; } _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c99" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c99" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 $as_echo "$ac_cv_prog_cc_c99" >&6; } ;; esac if test "x$ac_cv_prog_cc_c99" != xno; then : ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdarg.h> #include <stdio.h> struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 else ac_cv_prog_cc_stdc=no fi fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO Standard C" >&5 $as_echo_n "checking for $CC option to accept ISO Standard C... " >&6; } if ${ac_cv_prog_cc_stdc+:} false; then : $as_echo_n "(cached) " >&6 fi case $ac_cv_prog_cc_stdc in #( no) : { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; #( '') : { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; #( *) : { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_stdc" >&5 $as_echo "$ac_cv_prog_cc_stdc" >&6; } ;; esac case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.2' macro_revision='1.3337' ltmain="$ac_aux_dir/ltmain.sh" # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case "$ECHO" in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in *GNU* | *'with BFD'*) test "$with_gnu_ld" != no && break ;; *) test "$with_gnu_ld" != yes && break ;; esac fi done IFS="$lt_save_ifs" else lt_cv_path_LD="$LD" # Let the user override the test with a path. fi fi LD="$lt_cv_path_LD" if test -n "$LD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 </dev/null` in *GNU* | *'with BFD'*) lt_cv_prog_gnu_ld=yes ;; *) lt_cv_prog_gnu_ld=no ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n $lt_cv_sys_max_cmd_len ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 $as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 $as_echo "$xsi_shell" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 $as_echo_n "checking whether the shell understands \"+=\"... " >&6; } lt_shell_append=no ( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 $as_echo "$lt_shell_append" >&6; } if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test "$GCC" != yes; then reload_cmds=false fi ;; darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} : ${AR_FLAGS=cru} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 $as_echo "${with_sysroot}" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD="${LD-ld}_sol2" fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR cru libconftest.a conftest.o" >&5 $AR cru libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[012]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done # Set options enable_dlopen=no enable_win32_dll=no # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac else enable_shared=yes fi # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for lt_pkg in $withval; do IFS="$lt_save_ifs" if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS="$lt_save_ifs" ;; esac else pic_mode=default fi test -z "$pic_mode" && pic_mode=default # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac else enable_fast_install=yes fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' if test -n "$lt_prog_compiler_pic"; then lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ F* | *Sun*Fortran*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Intel*\ [CF]*Compiler*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; *Portland\ Group*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test x"$lt_cv_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach <jrb3@best.com> says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='${wl}--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' link_all_deplibs=yes ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi export_dynamic_flag_spec='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test "$lt_cv_ld_force_load" = "yes"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test x"$lt_cv_prog_compiler__b" = xyes; then archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_irix_exported_symbol=yes else lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test "$lt_cv_irix_exported_symbol" = yes; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='${wl}-z,text' allow_undefined_flag='${wl}-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='${wl}-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test "$ld_shlibs" = no && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([A-Za-z]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib<name>.so # instead of lib<name>.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Add ABI-specific directories to the system library path. sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test "$hardcode_action" = relink || test "$inherit_rpath" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen="shl_load" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen="dlopen" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include <dlfcn.h> #endif #include <stdio.h> #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include <dlfcn.h> #endif #include <stdio.h> #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report which library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" ac_config_commands="$ac_config_commands libtool" # Only expand once: for ac_header in $ac_header_list do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # on Darwin, these headers are interdependent, according to autoconf.info for ac_header in sys/socket.h do : ac_fn_c_check_header_compile "$LINENO" "sys/socket.h" "ac_cv_header_sys_socket_h" " #include <stdio.h> #include <stdlib.h> #include <sys/types.h> " if test "x$ac_cv_header_sys_socket_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SYS_SOCKET_H 1 _ACEOF fi done for ac_header in net/if.h do : ac_fn_c_check_header_compile "$LINENO" "net/if.h" "ac_cv_header_net_if_h" " #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #ifdef HAVE_SYS_SOCKET_H # include <sys/socket.h> #endif " if test "x$ac_cv_header_net_if_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NET_IF_H 1 _ACEOF fi done # Autoconf has a handy macro for this, since it tends to have dependencies for ac_header in sys/types.h netinet/in.h arpa/nameser.h netdb.h resolv.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#ifdef HAVE_SYS_TYPES_H # include <sys/types.h> #endif #ifdef HAVE_NETINET_IN_H # include <netinet/in.h> /* inet_ functions / structs */ #endif #ifdef HAVE_ARPA_NAMESER_H # include <arpa/nameser.h> /* DNS HEADER struct */ #endif #ifdef HAVE_NETDB_H # include <netdb.h> #endif " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Check whether --enable-compiler-optimisations was given. if test "${enable_compiler_optimisations+set}" = set; then : enableval=$enable_compiler_optimisations; if test "x$enable_compiler_optimisations" = "xno"; then CFLAGS=`echo "$CFLAGS" | sed -e "s/ -O[1-9]*\b/ -O0/g"` fi fi # Check whether --enable-compiler-coverage was given. if test "${enable_compiler_coverage+set}" = set; then : enableval=$enable_compiler_coverage; if test "x$enable_compiler_coverage" = "xyes"; then if test "x$GCC" = "xyes"; then CFLAGS="$CFLAGS -fprofile-arcs -ftest-coverage" fi fi fi official_release=yes if test "x$official_release" = xyes; then OFFICIAL_RELEASE_TRUE= OFFICIAL_RELEASE_FALSE='#' else OFFICIAL_RELEASE_TRUE='#' OFFICIAL_RELEASE_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands " >&5 $as_echo_n "checking to see if compiler understands ... " >&6; } save_CFLAGS="$CFLAGS" save_CXXFLAGS="$CXXFLAGS" CFLAGS="$CFLAGS " CXXFLAGS="$CXXFLAGS " cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : flag_ok=yes else flag_ok=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" CXXFLAGS="$save_CXXFLAGS" if test "X$flag_ok" = Xyes ; then true else true fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 $as_echo "$flag_ok" >&6; } tp_warnings="" for tp_flag in all \ extra \ declaration-after-statement \ shadow \ strict-prototypes \ missing-declarations \ missing-prototypes \ sign-compare \ nested-externs \ pointer-arith \ format-security \ init-self; do { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -W$tp_flag" >&5 $as_echo_n "checking to see if compiler understands -W$tp_flag... " >&6; } save_CFLAGS="$CFLAGS" save_CXXFLAGS="$CXXFLAGS" CFLAGS="$CFLAGS -W$tp_flag" CXXFLAGS="$CXXFLAGS -W$tp_flag" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : flag_ok=yes else flag_ok=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" CXXFLAGS="$save_CXXFLAGS" if test "X$flag_ok" = Xyes ; then tp_warnings="$tp_warnings -W$tp_flag" true else true fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 $as_echo "$flag_ok" >&6; } done tp_error_flags="-Werror" { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror" >&5 $as_echo_n "checking to see if compiler understands -Werror... " >&6; } save_CFLAGS="$CFLAGS" save_CXXFLAGS="$CXXFLAGS" CFLAGS="$CFLAGS -Werror" CXXFLAGS="$CXXFLAGS -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : flag_ok=yes else flag_ok=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" CXXFLAGS="$save_CXXFLAGS" if test "X$flag_ok" = Xyes ; then tp_werror=yes true else tp_werror=no true fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 $as_echo "$flag_ok" >&6; } for tp_flag in missing-field-initializers \ deprecated-declarations \ unused-parameter; do { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Wno-$tp_flag" >&5 $as_echo_n "checking to see if compiler understands -Wno-$tp_flag... " >&6; } save_CFLAGS="$CFLAGS" save_CXXFLAGS="$CXXFLAGS" CFLAGS="$CFLAGS -Wno-$tp_flag" CXXFLAGS="$CXXFLAGS -Wno-$tp_flag" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : flag_ok=yes else flag_ok=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" CXXFLAGS="$save_CXXFLAGS" if test "X$flag_ok" = Xyes ; then tp_warnings="$tp_warnings -Wno-$tp_flag" true else true fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 $as_echo "$flag_ok" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Wno-error=$tp_flag" >&5 $as_echo_n "checking to see if compiler understands -Wno-error=$tp_flag... " >&6; } save_CFLAGS="$CFLAGS" save_CXXFLAGS="$CXXFLAGS" CFLAGS="$CFLAGS -Wno-error=$tp_flag" CXXFLAGS="$CXXFLAGS -Wno-error=$tp_flag" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : flag_ok=yes else flag_ok=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" CXXFLAGS="$save_CXXFLAGS" if test "X$flag_ok" = Xyes ; then tp_error_flags="$tp_error_flags -Wno-error=$tp_flag" true else tp_werror=no true fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 $as_echo "$flag_ok" >&6; } done # Check whether --enable-Werror was given. if test "${enable_Werror+set}" = set; then : enableval=$enable_Werror; tp_werror=$enableval else : fi if test "x$tp_werror" = xyes && test "x$official_release" = xno; then ERROR_CFLAGS="$tp_warnings $tp_error_flags" else ERROR_CFLAGS="$tp_warnings" fi #------------------------------------------------------------ # Detect Operating system based on $host #------------------------------------------------------------ { $as_echo "$as_me:${as_lineno-$LINENO}: checking operating system" >&5 $as_echo_n "checking operating system... " >&6; } case "$host" in *-*-*mingw*|*-*-*cygwin*) platform=win32 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $platform" >&5 $as_echo "$platform" >&6; } ;; *) platform=unix { $as_echo "$as_me:${as_lineno-$LINENO}: result: $platform" >&5 $as_echo "$platform" >&6; } ;; esac if test "$platform" = "win32"; then WINDOWS_TRUE= WINDOWS_FALSE='#' else WINDOWS_TRUE='#' WINDOWS_FALSE= fi # ----------------------------------------------------------- # Make CA certificates path configurable # Stolen from GIO's TLS # ----------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking location of system Certificate Authority list" >&5 $as_echo_n "checking location of system Certificate Authority list... " >&6; } # Check whether --with-ca-certificates was given. if test "${with_ca_certificates+set}" = set; then : withval=$with_ca_certificates; fi if test "$with_ca_certificates" = "no"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 $as_echo "disabled" >&6; } else if test -z "$with_ca_certificates"; then for f in /etc/pki/tls/certs/ca-bundle.crt \ /etc/ssl/certs/ca-certificates.crt; do if test -f "$f"; then with_ca_certificates="$f" fi done if test -z "$with_ca_certificates"; then as_fn_error $? "could not find. Use --with-ca-certificates=path to set, or --without-ca-certificates to disable" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_ca_certificates" >&5 $as_echo "$with_ca_certificates" >&6; } cat >>confdefs.h <<_ACEOF #define GTLS_SYSTEM_CA_CERTIFICATES "$with_ca_certificates" _ACEOF fi if test -n "$with_ca_certificates"; then if ! test -f "$with_ca_certificates"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Specified certificate authority file '$with_ca_certificates' does not exist" >&5 $as_echo "$as_me: WARNING: Specified certificate authority file '$with_ca_certificates' does not exist" >&2;} fi fi # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then : enableval=$enable_debug; enable_debug=$enableval else enable_debug=yes fi # Gabble is version x.y.z - disable coding style checks by default # Check whether --enable-coding-style-checks was given. if test "${enable_coding_style_checks+set}" = set; then : enableval=$enable_coding_style_checks; ENABLE_CODING_STYLE_CHECKS=$enableval else ENABLE_CODING_STYLE_CHECKS=no fi if test x$enable_debug = xyes; then $as_echo "#define ENABLE_DEBUG /**/" >>confdefs.h fi if test "x$enable_debug" = xyes; then ENABLE_DEBUG_TRUE= ENABLE_DEBUG_FALSE='#' else ENABLE_DEBUG_TRUE='#' ENABLE_DEBUG_FALSE= fi # Check whether --enable-installed-tests was given. if test "${enable_installed_tests+set}" = set; then : enableval=$enable_installed_tests; installed_tests=$enableval else installed_tests=no fi if test x$installed_tests = xyes; then $as_echo "#define ENABLE_INSTALLED_TESTS /**/" >>confdefs.h fi if test "x$installed_tests" = xyes; then ENABLE_INSTALLED_TESTS_TRUE= ENABLE_INSTALLED_TESTS_FALSE='#' else ENABLE_INSTALLED_TESTS_TRUE='#' ENABLE_INSTALLED_TESTS_FALSE= fi gabbletestsdir=${libdir}/telepathy-gabble-tests # Check whether --enable-is-a-phone was given. if test "${enable_is_a_phone+set}" = set; then : enableval=$enable_is_a_phone; is_a_phone=$enableval else is_a_phone=no fi if test x$is_a_phone = xyes; then $as_echo "#define CLIENT_TYPE \"phone\"" >>confdefs.h CLIENT_TYPE=phone else $as_echo "#define CLIENT_TYPE \"pc\"" >>confdefs.h CLIENT_TYPE=pc fi # whether to assert when g_critical() is used # Check whether --enable-fatal-criticals was given. if test "${enable_fatal_criticals+set}" = set; then : enableval=$enable_fatal_criticals; fatal_criticals=$enableval else fatal_criticals=yes fi if test x$fatal_criticals = xyes; then $as_echo "#define ENABLE_FATAL_CRITICALS /**/" >>confdefs.h fi if test "x$fatal_criticals" = xyes; then ENABLE_FATAL_CRITICALS_TRUE= ENABLE_FATAL_CRITICALS_FALSE='#' else ENABLE_FATAL_CRITICALS_TRUE='#' ENABLE_FATAL_CRITICALS_FALSE= fi # Check whether --enable-gtk-doc was given. if test "${enable_gtk_doc+set}" = set; then : enableval=$enable_gtk_doc; enable_gtk_doc=yes else enable_gtk_doc=no fi if test "x$enable_gtk_doc" = xyes; then ENABLE_GTK_DOC_TRUE= ENABLE_GTK_DOC_FALSE='#' else ENABLE_GTK_DOC_TRUE='#' ENABLE_GTK_DOC_FALSE= fi if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 $as_echo "$ac_pt_PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 $as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } PKG_CONFIG="" fi fi pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB" >&5 $as_echo_n "checking for GLIB... " >&6; } if test -n "$GLIB_CFLAGS"; then pkg_cv_GLIB_CFLAGS="$GLIB_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.32, gobject-2.0, gthread-2.0, gio-2.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.32, gobject-2.0, gthread-2.0, gio-2.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GLIB_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 >= 2.32, gobject-2.0, gthread-2.0, gio-2.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$GLIB_LIBS"; then pkg_cv_GLIB_LIBS="$GLIB_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.32, gobject-2.0, gthread-2.0, gio-2.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.32, gobject-2.0, gthread-2.0, gio-2.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GLIB_LIBS=`$PKG_CONFIG --libs "glib-2.0 >= 2.32, gobject-2.0, gthread-2.0, gio-2.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0 >= 2.32, gobject-2.0, gthread-2.0, gio-2.0" 2>&1` else GLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0 >= 2.32, gobject-2.0, gthread-2.0, gio-2.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$GLIB_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (glib-2.0 >= 2.32, gobject-2.0, gthread-2.0, gio-2.0) were not met: $GLIB_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables GLIB_CFLAGS and GLIB_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables GLIB_CFLAGS and GLIB_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see <http://pkg-config.freedesktop.org/>. See \`config.log' for more details" "$LINENO" 5; } else GLIB_CFLAGS=$pkg_cv_GLIB_CFLAGS GLIB_LIBS=$pkg_cv_GLIB_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GMODULE" >&5 $as_echo_n "checking for GMODULE... " >&6; } if test -n "$GMODULE_CFLAGS"; then pkg_cv_GMODULE_CFLAGS="$GMODULE_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gmodule-2.0 >= 2.32\""; } >&5 ($PKG_CONFIG --exists --print-errors "gmodule-2.0 >= 2.32") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GMODULE_CFLAGS=`$PKG_CONFIG --cflags "gmodule-2.0 >= 2.32" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$GMODULE_LIBS"; then pkg_cv_GMODULE_LIBS="$GMODULE_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gmodule-2.0 >= 2.32\""; } >&5 ($PKG_CONFIG --exists --print-errors "gmodule-2.0 >= 2.32") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GMODULE_LIBS=`$PKG_CONFIG --libs "gmodule-2.0 >= 2.32" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then GMODULE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gmodule-2.0 >= 2.32" 2>&1` else GMODULE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gmodule-2.0 >= 2.32" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$GMODULE_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (gmodule-2.0 >= 2.32) were not met: $GMODULE_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables GMODULE_CFLAGS and GMODULE_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables GMODULE_CFLAGS and GMODULE_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see <http://pkg-config.freedesktop.org/>. See \`config.log' for more details" "$LINENO" 5; } else GMODULE_CFLAGS=$pkg_cv_GMODULE_CFLAGS GMODULE_LIBS=$pkg_cv_GMODULE_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi $as_echo "#define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_30" >>confdefs.h $as_echo "#define GLIB_VERSION_MAX_ALLOWED GLIB_VERSION_2_32" >>confdefs.h GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` # These must contain "exec" for automake to work right (install-exec, # not install-data). # # Private directory for Wocky and the gabble-plugins library if test "x$pluginexeclibdir" = x; then pluginexeclibdir='${libdir}/telepathy/gabble-0/lib' fi # The actual plugins if test "x$pluginexecdir" = x; then pluginexecdir='${libdir}/telepathy/gabble-0/plugins' fi # Check whether --enable-plugins was given. if test "${enable_plugins+set}" = set; then : enableval=$enable_plugins; enable_plugins=$enableval else enable_plugins=yes fi if test x$enable_plugins = xyes; then $as_echo "#define ENABLE_PLUGINS /**/" >>confdefs.h pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GMODULE" >&5 $as_echo_n "checking for GMODULE... " >&6; } if test -n "$GMODULE_CFLAGS"; then pkg_cv_GMODULE_CFLAGS="$GMODULE_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gmodule-2.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "gmodule-2.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GMODULE_CFLAGS=`$PKG_CONFIG --cflags "gmodule-2.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$GMODULE_LIBS"; then pkg_cv_GMODULE_LIBS="$GMODULE_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gmodule-2.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "gmodule-2.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GMODULE_LIBS=`$PKG_CONFIG --libs "gmodule-2.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then GMODULE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gmodule-2.0" 2>&1` else GMODULE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gmodule-2.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$GMODULE_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (gmodule-2.0) were not met: $GMODULE_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables GMODULE_CFLAGS and GMODULE_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables GMODULE_CFLAGS and GMODULE_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see <http://pkg-config.freedesktop.org/>. See \`config.log' for more details" "$LINENO" 5; } else GMODULE_CFLAGS=$pkg_cv_GMODULE_CFLAGS GMODULE_LIBS=$pkg_cv_GMODULE_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # Check whether --enable-plugin-api was given. if test "${enable_plugin_api+set}" = set; then : enableval=$enable_plugin_api; enable_plugin_api=$enableval wocky_install_headers_dir="${includedir}/telepathy-gabble-0" else enable_plugin_api=no fi fi if test x$enable_plugins = xyes; then ENABLE_PLUGINS_TRUE= ENABLE_PLUGINS_FALSE='#' else ENABLE_PLUGINS_TRUE='#' ENABLE_PLUGINS_FALSE= fi if test x$enable_plugin_api = xyes; then ENABLE_PLUGIN_API_TRUE= ENABLE_PLUGIN_API_FALSE='#' else ENABLE_PLUGIN_API_TRUE='#' ENABLE_PLUGIN_API_FALSE= fi # Check whether --enable-channel-type-call was given. if test "${enable_channel_type_call+set}" = set; then : enableval=$enable_channel_type_call; enable_channel_type_call=$enableval else enable_channel_type_call=yes fi if test x$enable_channel_type_call = xyes; then $as_echo "#define ENABLE_CHANNEL_TYPE_CALL /**/" >>confdefs.h fi if test x$enable_channel_type_call = xyes; then ENABLE_CHANNEL_TYPE_CALL_TRUE= ENABLE_CHANNEL_TYPE_CALL_FALSE='#' else ENABLE_CHANNEL_TYPE_CALL_TRUE='#' ENABLE_CHANNEL_TYPE_CALL_FALSE= fi pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DBUS" >&5 $as_echo_n "checking for DBUS... " >&6; } if test -n "$DBUS_CFLAGS"; then pkg_cv_DBUS_CFLAGS="$DBUS_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"dbus-1 >= 1.1.0, dbus-glib-1 >= 0.82\""; } >&5 ($PKG_CONFIG --exists --print-errors "dbus-1 >= 1.1.0, dbus-glib-1 >= 0.82") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_DBUS_CFLAGS=`$PKG_CONFIG --cflags "dbus-1 >= 1.1.0, dbus-glib-1 >= 0.82" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$DBUS_LIBS"; then pkg_cv_DBUS_LIBS="$DBUS_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"dbus-1 >= 1.1.0, dbus-glib-1 >= 0.82\""; } >&5 ($PKG_CONFIG --exists --print-errors "dbus-1 >= 1.1.0, dbus-glib-1 >= 0.82") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_DBUS_LIBS=`$PKG_CONFIG --libs "dbus-1 >= 1.1.0, dbus-glib-1 >= 0.82" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then DBUS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "dbus-1 >= 1.1.0, dbus-glib-1 >= 0.82" 2>&1` else DBUS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "dbus-1 >= 1.1.0, dbus-glib-1 >= 0.82" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$DBUS_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (dbus-1 >= 1.1.0, dbus-glib-1 >= 0.82) were not met: $DBUS_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables DBUS_CFLAGS and DBUS_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables DBUS_CFLAGS and DBUS_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see <http://pkg-config.freedesktop.org/>. See \`config.log' for more details" "$LINENO" 5; } else DBUS_CFLAGS=$pkg_cv_DBUS_CFLAGS DBUS_LIBS=$pkg_cv_DBUS_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi $as_echo "#define TP_SEAL_ENABLE /**/" >>confdefs.h $as_echo "#define TP_DISABLE_SINGLE_INCLUDE /**/" >>confdefs.h $as_echo "#define TP_VERSION_MIN_REQUIRED TP_VERSION_0_18" >>confdefs.h $as_echo "#define TP_VERSION_MAX_ALLOWED TP_VERSION_0_20" >>confdefs.h pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TP_GLIB" >&5 $as_echo_n "checking for TP_GLIB... " >&6; } if test -n "$TP_GLIB_CFLAGS"; then pkg_cv_TP_GLIB_CFLAGS="$TP_GLIB_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"telepathy-glib >= 0.19.9\""; } >&5 ($PKG_CONFIG --exists --print-errors "telepathy-glib >= 0.19.9") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_TP_GLIB_CFLAGS=`$PKG_CONFIG --cflags "telepathy-glib >= 0.19.9" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$TP_GLIB_LIBS"; then pkg_cv_TP_GLIB_LIBS="$TP_GLIB_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"telepathy-glib >= 0.19.9\""; } >&5 ($PKG_CONFIG --exists --print-errors "telepathy-glib >= 0.19.9") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_TP_GLIB_LIBS=`$PKG_CONFIG --libs "telepathy-glib >= 0.19.9" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then TP_GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "telepathy-glib >= 0.19.9" 2>&1` else TP_GLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "telepathy-glib >= 0.19.9" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$TP_GLIB_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (telepathy-glib >= 0.19.9) were not met: $TP_GLIB_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables TP_GLIB_CFLAGS and TP_GLIB_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables TP_GLIB_CFLAGS and TP_GLIB_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see <http://pkg-config.freedesktop.org/>. See \`config.log' for more details" "$LINENO" 5; } else TP_GLIB_CFLAGS=$pkg_cv_TP_GLIB_CFLAGS TP_GLIB_LIBS=$pkg_cv_TP_GLIB_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi XSLTPROC= for ac_prog in xsltproc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_XSLTPROC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$XSLTPROC"; then ac_cv_prog_XSLTPROC="$XSLTPROC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_XSLTPROC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi XSLTPROC=$ac_cv_prog_XSLTPROC if test -n "$XSLTPROC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XSLTPROC" >&5 $as_echo "$XSLTPROC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$XSLTPROC" && break done if test -z "$XSLTPROC"; then as_fn_error $? "xsltproc (from the libxslt source package) is required" "$LINENO" 5 fi if test -n "$PYTHON"; then # If the user set $PYTHON, use it and don't search something else. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $PYTHON version is >= 2.5" >&5 $as_echo_n "checking whether $PYTHON version is >= 2.5... " >&6; } prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '2.5'.split('.'))) + [0, 0, 0] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i] sys.exit(sys.hexversion < minverhex)" if { echo "$as_me:$LINENO: $PYTHON -c "$prog"" >&5 ($PYTHON -c "$prog") >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "Python interpreter is too old" "$LINENO" 5 fi am_display_PYTHON=$PYTHON else # Otherwise, try each interpreter until we find one that satisfies # VERSION. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a Python interpreter with version >= 2.5" >&5 $as_echo_n "checking for a Python interpreter with version >= 2.5... " >&6; } if ${am_cv_pathless_PYTHON+:} false; then : $as_echo_n "(cached) " >&6 else for am_cv_pathless_PYTHON in python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 none; do test "$am_cv_pathless_PYTHON" = none && break prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '2.5'.split('.'))) + [0, 0, 0] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i] sys.exit(sys.hexversion < minverhex)" if { echo "$as_me:$LINENO: $am_cv_pathless_PYTHON -c "$prog"" >&5 ($am_cv_pathless_PYTHON -c "$prog") >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then : break fi done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_pathless_PYTHON" >&5 $as_echo "$am_cv_pathless_PYTHON" >&6; } # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. if test "$am_cv_pathless_PYTHON" = none; then PYTHON=: else # Extract the first word of "$am_cv_pathless_PYTHON", so it can be a program name with args. set dummy $am_cv_pathless_PYTHON; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PYTHON+:} false; then : $as_echo_n "(cached) " >&6 else case $PYTHON in [\\/]* | ?:[\\/]*) ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PYTHON=$ac_cv_path_PYTHON if test -n "$PYTHON"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5 $as_echo "$PYTHON" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi am_display_PYTHON=$am_cv_pathless_PYTHON fi if test "$PYTHON" = :; then as_fn_error $? "no suitable Python interpreter found" "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON version" >&5 $as_echo_n "checking for $am_display_PYTHON version... " >&6; } if ${am_cv_python_version+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[:3])"` fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_version" >&5 $as_echo "$am_cv_python_version" >&6; } PYTHON_VERSION=$am_cv_python_version PYTHON_PREFIX='${prefix}' PYTHON_EXEC_PREFIX='${exec_prefix}' { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON platform" >&5 $as_echo_n "checking for $am_display_PYTHON platform... " >&6; } if ${am_cv_python_platform+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"` fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_platform" >&5 $as_echo "$am_cv_python_platform" >&6; } PYTHON_PLATFORM=$am_cv_python_platform # Just factor out some code duplication. am_python_setup_sysconfig="\ import sys # Prefer sysconfig over distutils.sysconfig, for better compatibility # with python 3.x. See automake bug#10227. try: import sysconfig except ImportError: can_use_sysconfig = 0 else: can_use_sysconfig = 1 # Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: # <https://github.com/pypa/virtualenv/issues/118> try: from platform import python_implementation if python_implementation() == 'CPython' and sys.version[:3] == '2.7': can_use_sysconfig = 0 except ImportError: pass" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON script directory" >&5 $as_echo_n "checking for $am_display_PYTHON script directory... " >&6; } if ${am_cv_python_pythondir+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$prefix" = xNONE then am_py_prefix=$ac_default_prefix else am_py_prefix=$prefix fi am_cv_python_pythondir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pythondir in $am_py_prefix*) am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` ;; *) case $am_py_prefix in /usr|/System*) ;; *) am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pythondir" >&5 $as_echo "$am_cv_python_pythondir" >&6; } pythondir=$am_cv_python_pythondir pkgpythondir=\${pythondir}/$PACKAGE { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory" >&5 $as_echo_n "checking for $am_display_PYTHON extension module directory... " >&6; } if ${am_cv_python_pyexecdir+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$exec_prefix" = xNONE then am_py_exec_prefix=$am_py_prefix else am_py_exec_prefix=$exec_prefix fi am_cv_python_pyexecdir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pyexecdir in $am_py_exec_prefix*) am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` ;; *) case $am_py_exec_prefix in /usr|/System*) ;; *) am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pyexecdir" >&5 $as_echo "$am_cv_python_pyexecdir" >&6; } pyexecdir=$am_cv_python_pyexecdir pkgpyexecdir=\${pyexecdir}/$PACKAGE fi # Check for a Python >= 2.5 with Twisted, to run the tests { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python with Twisted and XMPP protocol support" >&5 $as_echo_n "checking for Python with Twisted and XMPP protocol support... " >&6; } if $PYTHON -c "import twisted.words.xish.domish, twisted.words.protocols.jabber, twisted.internet.reactor" >/dev/null 2>&1; then TEST_PYTHON="$PYTHON" else TEST_PYTHON=false fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TEST_PYTHON" >&5 $as_echo "$TEST_PYTHON" >&6; } if test false != "$TEST_PYTHON"; then WANT_TWISTED_TESTS_TRUE= WANT_TWISTED_TESTS_FALSE='#' else WANT_TWISTED_TESTS_TRUE='#' WANT_TWISTED_TESTS_FALSE= fi # We have to run Wocky's configure *before* looking for it with PKG_CHECK_MODULES so wocky-uninstalled.pc has been generated # If you don't specify --prefix, it starts off as NONE. Autoconf # would normally do this defaulting for us later, but that's too # late to help Wocky. if test "x${prefix}" = "xNONE"; then prefix=/usr/local fi # We tell Wocky to install its headers alongside gabble's so that an actual # separate Wocky installation won't clash with them. This is a bit of a hack. # AX_CONFIG_DIR doesn't make it very easy to pass extra arguments to the # submodule's configure. prev_ac_configure_args=$ac_configure_args ac_configure_args="$ac_configure_args --with-installed-headers=${wocky_install_headers_dir} --enable-shared-suffix=${PACKAGE}-${VERSION} --libdir=${pluginexeclibdir}" if test "x$ENABLE_CODING_STYLE_CHECKS" = xyes ; then ac_configure_args="$ac_configure_args --enable-coding-style-checks" else ac_configure_args="$ac_configure_args --disable-coding-style-checks" fi if test "x$tp_werror" = xyes && test "x$official_release" = xno; then ac_configure_args="$ac_configure_args --enable-Werror" else ac_configure_args="$ac_configure_args --disable-Werror" fi prev_top_build_prefix=$ac_top_build_prefix # Remove --cache-file and --srcdir arguments so they do not pile up. ax_sub_configure_args= ax_prev= eval "set x $ac_configure_args" shift for ax_arg do if test -n "$ax_prev"; then ax_prev= continue fi case $ax_arg in -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ax_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \ | --c=*) ;; --config-cache | -C) ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ax_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ax_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) ;; *) case $ax_arg in *\'*) ax_arg=`echo "$ax_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac ax_sub_configure_args="$ax_sub_configure_args '$ax_arg'" ;; esac done # Always prepend --prefix to ensure using the same prefix # in subdir configurations. ax_arg="--prefix=$prefix" case $ax_arg in *\'*) ax_arg=`echo "$ax_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac ax_sub_configure_args="'$ax_arg' $ax_sub_configure_args" # Pass --silent if test "$silent" = yes; then ax_sub_configure_args="--silent $ax_sub_configure_args" fi ax_popdir=`pwd` { $as_echo "$as_me:${as_lineno-$LINENO}: Configuring sources in lib/ext/wocky" >&5 $as_echo "$as_me: Configuring sources in lib/ext/wocky" >&6;} as_dir="lib/ext/wocky"; as_fn_mkdir_p ac_builddir=. case "lib/ext/wocky" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "lib/ext/wocky" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "lib/ext/wocky" # Check for guested configure; otherwise get Cygnus style configure. if test -f "configure.gnu"; then ax_sub_configure=$ac_srcdir/configure.gnu elif test -f "$ac_srcdir/configure"; then ax_sub_configure=$ac_srcdir/configure elif test -f "$ac_srcdir/configure.in"; then # This should be Cygnus configure. ax_sub_configure=$ac_aux_dir/configure else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no configuration information is in lib/ext/wocky" >&5 $as_echo "$as_me: WARNING: no configuration information is in lib/ext/wocky" >&2;} ax_sub_configure= fi # The recursion is here. if test -n "$ax_sub_configure"; then # Make the cache file name correct relative to the subdirectory. case $cache_file in [\\/]* | ?:[\\/]* ) ax_sub_cache_file=$cache_file ;; *) # Relative name. ax_sub_cache_file=$ac_top_build_prefix$cache_file ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: running $SHELL $ax_sub_configure $ax_sub_configure_args --cache-file=$ax_sub_cache_file --srcdir=$ac_srcdir" >&5 $as_echo "$as_me: running $SHELL $ax_sub_configure $ax_sub_configure_args --cache-file=$ax_sub_cache_file --srcdir=$ac_srcdir" >&6;} # The eval makes quoting arguments work. eval "\$SHELL \"\$ax_sub_configure\" $ax_sub_configure_args \ --cache-file=\"\$ax_sub_cache_file\" --srcdir=\"\$ax_srcdir\"" fi cd "$ax_popdir" { $as_echo "$as_me:${as_lineno-$LINENO}: Done configuring in lib/ext/wocky" >&5 $as_echo "$as_me: Done configuring in lib/ext/wocky" >&6;} ac_top_build_prefix=$prev_top_build_prefix ac_configure_args=$prev_ac_configure_args # Check whether --enable-submodules was given. if test "${enable_submodules+set}" = set; then : enableval=$enable_submodules; build_submodules=$enableval else build_submodules=yes fi # re-enable once Wocky has been released as a lib if test x$build_submodules = xyes; then export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:"$ac_top_build_prefix"lib/ext/wocky/wocky fi pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for WOCKY" >&5 $as_echo_n "checking for WOCKY... " >&6; } if test -n "$WOCKY_CFLAGS"; then pkg_cv_WOCKY_CFLAGS="$WOCKY_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"wocky >= 0.0.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "wocky >= 0.0.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_WOCKY_CFLAGS=`$PKG_CONFIG --cflags "wocky >= 0.0.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$WOCKY_LIBS"; then pkg_cv_WOCKY_LIBS="$WOCKY_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"wocky >= 0.0.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "wocky >= 0.0.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_WOCKY_LIBS=`$PKG_CONFIG --libs "wocky >= 0.0.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then WOCKY_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "wocky >= 0.0.0" 2>&1` else WOCKY_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "wocky >= 0.0.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$WOCKY_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (wocky >= 0.0.0) were not met: $WOCKY_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables WOCKY_CFLAGS and WOCKY_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables WOCKY_CFLAGS and WOCKY_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see <http://pkg-config.freedesktop.org/>. See \`config.log' for more details" "$LINENO" 5; } else WOCKY_CFLAGS=$pkg_cv_WOCKY_CFLAGS WOCKY_LIBS=$pkg_cv_WOCKY_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi # Check whether --enable-google-relay was given. if test "${enable_google_relay+set}" = set; then : enableval=$enable_google_relay; enable_google_relay=$enableval else enable_google_relay=yes fi if test x$enable_google_relay = xyes; then $as_echo "#define ENABLE_GOOGLE_RELAY /**/" >>confdefs.h pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SOUP" >&5 $as_echo_n "checking for SOUP... " >&6; } if test -n "$SOUP_CFLAGS"; then pkg_cv_SOUP_CFLAGS="$SOUP_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsoup-2.4\""; } >&5 ($PKG_CONFIG --exists --print-errors "libsoup-2.4") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_SOUP_CFLAGS=`$PKG_CONFIG --cflags "libsoup-2.4" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$SOUP_LIBS"; then pkg_cv_SOUP_LIBS="$SOUP_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsoup-2.4\""; } >&5 ($PKG_CONFIG --exists --print-errors "libsoup-2.4") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_SOUP_LIBS=`$PKG_CONFIG --libs "libsoup-2.4" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then SOUP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsoup-2.4" 2>&1` else SOUP_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsoup-2.4" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$SOUP_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (libsoup-2.4) were not met: $SOUP_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables SOUP_CFLAGS and SOUP_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables SOUP_CFLAGS and SOUP_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see <http://pkg-config.freedesktop.org/>. See \`config.log' for more details" "$LINENO" 5; } else SOUP_CFLAGS=$pkg_cv_SOUP_CFLAGS SOUP_LIBS=$pkg_cv_SOUP_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi else SOUP_CFLAGS= SOUP_LIBS= fi if test "x$enable_google_relay" = xyes; then ENABLE_GOOGLE_RELAY_TRUE= ENABLE_GOOGLE_RELAY_FALSE='#' else ENABLE_GOOGLE_RELAY_TRUE='#' ENABLE_GOOGLE_RELAY_FALSE= fi # Check whether --enable-file-transfer was given. if test "${enable_file_transfer+set}" = set; then : enableval=$enable_file_transfer; enable_ft=$enableval else enable_ft=yes fi if test x$enable_ft = xyes; then $as_echo "#define ENABLE_FILE_TRANSFER /**/" >>confdefs.h fi if test "x$enable_ft" = xyes; then ENABLE_FILE_TRANSFER_TRUE= ENABLE_FILE_TRANSFER_FALSE='#' else ENABLE_FILE_TRANSFER_TRUE='#' ENABLE_FILE_TRANSFER_FALSE= fi # Check whether --enable-voip was given. if test "${enable_voip+set}" = set; then : enableval=$enable_voip; enable_voip=$enableval else enable_voip=yes fi if test x$enable_voip = xyes; then $as_echo "#define ENABLE_VOIP /**/" >>confdefs.h fi if test "x$enable_voip" = xyes; then ENABLE_VOIP_TRUE= ENABLE_VOIP_FALSE='#' else ENABLE_VOIP_TRUE='#' ENABLE_VOIP_FALSE= fi if test x$enable_voip = xyes -a x$enable_ft = xyes; then enable_jingle_ft=yes $as_echo "#define ENABLE_JINGLE_FILE_TRANSFER /**/" >>confdefs.h pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NICE" >&5 $as_echo_n "checking for NICE... " >&6; } if test -n "$NICE_CFLAGS"; then pkg_cv_NICE_CFLAGS="$NICE_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"nice >= 0.0.11\""; } >&5 ($PKG_CONFIG --exists --print-errors "nice >= 0.0.11") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_NICE_CFLAGS=`$PKG_CONFIG --cflags "nice >= 0.0.11" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$NICE_LIBS"; then pkg_cv_NICE_LIBS="$NICE_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"nice >= 0.0.11\""; } >&5 ($PKG_CONFIG --exists --print-errors "nice >= 0.0.11") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_NICE_LIBS=`$PKG_CONFIG --libs "nice >= 0.0.11" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then NICE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "nice >= 0.0.11" 2>&1` else NICE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "nice >= 0.0.11" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$NICE_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (nice >= 0.0.11) were not met: $NICE_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables NICE_CFLAGS and NICE_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables NICE_CFLAGS and NICE_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see <http://pkg-config.freedesktop.org/>. See \`config.log' for more details" "$LINENO" 5; } else NICE_CFLAGS=$pkg_cv_NICE_CFLAGS NICE_LIBS=$pkg_cv_NICE_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi else enable_jingle_ft=no NICE_CFLAGS= NICE_LIBS= fi if test "x$enable_jingle_ft" = xyes; then ENABLE_JINGLE_FILE_TRANSFER_TRUE= ENABLE_JINGLE_FILE_TRANSFER_FALSE='#' else ENABLE_JINGLE_FILE_TRANSFER_TRUE='#' ENABLE_JINGLE_FILE_TRANSFER_FALSE= fi for ac_func in getifaddrs memset select strndup setresuid setreuid strerror do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done ac_config_files="$ac_config_files Makefile docs/Makefile extensions/Makefile src/Makefile m4/Makefile data/Makefile tests/Makefile tools/Makefile tests/suppressions/Makefile tests/twisted/Makefile lib/Makefile lib/ext/Makefile lib/gibber/Makefile plugins/Makefile gabble/Makefile gabble/telepathy-gabble-uninstalled.pc gabble/telepathy-gabble.pc" cat >confcache <<\_ACEOF # 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, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # 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. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${OFFICIAL_RELEASE_TRUE}" && test -z "${OFFICIAL_RELEASE_FALSE}"; then as_fn_error $? "conditional \"OFFICIAL_RELEASE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WINDOWS_TRUE}" && test -z "${WINDOWS_FALSE}"; then as_fn_error $? "conditional \"WINDOWS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_DEBUG_TRUE}" && test -z "${ENABLE_DEBUG_FALSE}"; then as_fn_error $? "conditional \"ENABLE_DEBUG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_INSTALLED_TESTS_TRUE}" && test -z "${ENABLE_INSTALLED_TESTS_FALSE}"; then as_fn_error $? "conditional \"ENABLE_INSTALLED_TESTS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_FATAL_CRITICALS_TRUE}" && test -z "${ENABLE_FATAL_CRITICALS_FALSE}"; then as_fn_error $? "conditional \"ENABLE_FATAL_CRITICALS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_GTK_DOC_TRUE}" && test -z "${ENABLE_GTK_DOC_FALSE}"; then as_fn_error $? "conditional \"ENABLE_GTK_DOC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_PLUGINS_TRUE}" && test -z "${ENABLE_PLUGINS_FALSE}"; then as_fn_error $? "conditional \"ENABLE_PLUGINS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_PLUGIN_API_TRUE}" && test -z "${ENABLE_PLUGIN_API_FALSE}"; then as_fn_error $? "conditional \"ENABLE_PLUGIN_API\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_CHANNEL_TYPE_CALL_TRUE}" && test -z "${ENABLE_CHANNEL_TYPE_CALL_FALSE}"; then as_fn_error $? "conditional \"ENABLE_CHANNEL_TYPE_CALL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WANT_TWISTED_TESTS_TRUE}" && test -z "${WANT_TWISTED_TESTS_FALSE}"; then as_fn_error $? "conditional \"WANT_TWISTED_TESTS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_GOOGLE_RELAY_TRUE}" && test -z "${ENABLE_GOOGLE_RELAY_FALSE}"; then as_fn_error $? "conditional \"ENABLE_GOOGLE_RELAY\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_FILE_TRANSFER_TRUE}" && test -z "${ENABLE_FILE_TRANSFER_FALSE}"; then as_fn_error $? "conditional \"ENABLE_FILE_TRANSFER\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_VOIP_TRUE}" && test -z "${ENABLE_VOIP_FALSE}"; then as_fn_error $? "conditional \"ENABLE_VOIP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_JINGLE_FILE_TRANSFER_TRUE}" && test -z "${ENABLE_JINGLE_FILE_TRANSFER_FALSE}"; then as_fn_error $? "conditional \"ENABLE_JINGLE_FILE_TRANSFER\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by Telepathy Gabble $as_me 0.18.3, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to <https://bugs.freedesktop.org/enter_bug.cgi?product=Telepathy&component=gabble>." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ Telepathy Gabble config.status 0.18.3 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in SHELL \ ECHO \ PATH_SEPARATOR \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ nm_file_list_spec \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ sys_lib_dlsearch_path_spec; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' xsi_shell='$xsi_shell' lt_shell_append='$lt_shell_append' # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "docs/Makefile") CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;; "extensions/Makefile") CONFIG_FILES="$CONFIG_FILES extensions/Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "m4/Makefile") CONFIG_FILES="$CONFIG_FILES m4/Makefile" ;; "data/Makefile") CONFIG_FILES="$CONFIG_FILES data/Makefile" ;; "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; "tools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;; "tests/suppressions/Makefile") CONFIG_FILES="$CONFIG_FILES tests/suppressions/Makefile" ;; "tests/twisted/Makefile") CONFIG_FILES="$CONFIG_FILES tests/twisted/Makefile" ;; "lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;; "lib/ext/Makefile") CONFIG_FILES="$CONFIG_FILES lib/ext/Makefile" ;; "lib/gibber/Makefile") CONFIG_FILES="$CONFIG_FILES lib/gibber/Makefile" ;; "plugins/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/Makefile" ;; "gabble/Makefile") CONFIG_FILES="$CONFIG_FILES gabble/Makefile" ;; "gabble/telepathy-gabble-uninstalled.pc") CONFIG_FILES="$CONFIG_FILES gabble/telepathy-gabble-uninstalled.pc" ;; "gabble/telepathy-gabble.pc") CONFIG_FILES="$CONFIG_FILES gabble/telepathy-gabble.pc" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' <conf$$subs.awk | sed ' /^[^""]/{ N s/\n// } ' >>$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' <confdefs.h | sed ' s/'"$ac_delim"'/"\\\ "/g' >>$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; "libtool":C) # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool 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. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # The names of the tagged configurations supported by this script. available_tags="" # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The PATH separator for the build system. PATH_SEPARATOR=$lt_PATH_SEPARATOR # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # DLL creation program. DLLTOOL=$lt_DLLTOOL # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and in which our libraries should be installed. lt_sysroot=$lt_sysroot # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain="$ac_aux_dir/ltmain.sh" # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) if test x"$xsi_shell" = xyes; then sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ func_dirname ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ } # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_basename ()$/,/^} # func_basename /c\ func_basename ()\ {\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ func_dirname_and_basename ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ func_stripname ()\ {\ \ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ \ # positional parameters, so assign one to ordinary parameter first.\ \ func_stripname_result=${3}\ \ func_stripname_result=${func_stripname_result#"${1}"}\ \ func_stripname_result=${func_stripname_result%"${2}"}\ } # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ func_split_long_opt ()\ {\ \ func_split_long_opt_name=${1%%=*}\ \ func_split_long_opt_arg=${1#*=}\ } # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ func_split_short_opt ()\ {\ \ func_split_short_opt_arg=${1#??}\ \ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ } # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ func_lo2o ()\ {\ \ case ${1} in\ \ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ \ *) func_lo2o_result=${1} ;;\ \ esac\ } # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_xform ()$/,/^} # func_xform /c\ func_xform ()\ {\ func_xform_result=${1%.*}.lo\ } # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_arith ()$/,/^} # func_arith /c\ func_arith ()\ {\ func_arith_result=$(( $* ))\ } # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_len ()$/,/^} # func_len /c\ func_len ()\ {\ func_len_result=${#1}\ } # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$lt_shell_append" = xyes; then sed -e '/^func_append ()$/,/^} # func_append /c\ func_append ()\ {\ eval "${1}+=\\${2}"\ } # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ func_append_quoted ()\ {\ \ func_quote_for_eval "${2}"\ \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ } # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 $as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} fi mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi if test false != "$TEST_PYTHON"; then tests_enabled=yes else tests_enabled=no fi echo " Configure summary: Compiler....................: ${CC} Compiler Flags..............: ${CFLAGS} ${ERROR_CFLAGS} Prefix......................: ${prefix} Coding style checks.........: ${ENABLE_CODING_STYLE_CHECKS} Enable debug................: ${enable_debug} Python tests................: ${tests_enabled} Install unit tests..........: ${installed_tests} Features: Client type.................: \"${CLIENT_TYPE}\" Plugin support..............: ${enable_plugins} Plugin headers installed....: ${enable_plugin_api} Channel.Type.Call support...: ${enable_channel_type_call} Google relay support........: ${enable_google_relay} File transfer support.......: ${enable_ft} Jingle file transfer support: ${enable_jingle_ft} VoIP support................: ${enable_voip} " ��������������������������������telepathy-gabble-0.18.3/tests/����������������������������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�017347� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/README����������������������������������������������������������������0000664�0001750�0001750�00000005332�12223562023�020220� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������To run all tests: make check or with coverage info: ./configure --enable-compiler-coverage make lcov-check == C tests == To run all C tests (assuming the current directory is $top_srcdir): make -C tests check-TESTS To run an individual test: make -C tests check-TESTS TESTS=test-handles To run tests under Valgrind: make -C tests check-valgrind To run an individual test under Valgrind: make -C tests check-valgrind TESTS=test-handles == Twisted tests == To run all Twisted tests: make check-twisted To run an individual Twisted test: make -C tests/twisted check-twisted TWISTED_TESTS=connect/test-success.py or: cd tests/twisted sh tools/with-session-bus.sh --config-file=tools/servicedir-uninstalled/tmp-session-bus.conf \ -- python connect/test-success.py To run with debug information: make -C tests/twisted check-twisted TWISTED_TESTS=connect/test-success.py \ CHECK_TWISTED_VERBOSE=1 or: cd tests/twisted sh tools/with-session-bus.sh --config-file=tools/servicedir-uninstalled/tmp-session-bus.conf \ -- python connect/test-success.py -v To debug an individual test you can set one of the following env variable: * GABBLE_TEST_VALGRIND : to run Gabble inside valgrind. The report is added to tools/gabble-testing.log. export GABBLE_TEST_VALGRIND=1 * GABBLE_TEST_REFDBG : to run Gabble inside refdbg. The report is written to tools/refdbg.log. You can change GABBLE_WRAPPER to use an alternative refdbg and change REFDBG_OPTIONS to set your own parameters. Example: export GABBLE_TEST_REFDBG=1 export GABBLE_WRAPPER="/path/to/refdbg" export REFDBG_OPTIONS="btnum=16" * GABBLE_WRAPPER="nemiver" : to run Gabble inside the graphical debugger nemiver. You'll be able to set up breakpoints; then hit the "continue" button to launch Gabble. * GABBLE_TEST_STRACE : to run Gabble inside strace. The report is written to tools/strace.log. export GABBLE_TEST_STRACE=1 * GABBLE_TEST_BUSTLE : to run bustle-dbus-monitor in the temporary bus daemon. The logs are saved to tools/*bustle-logs. export GABBLE_TEST_BUSTLE=1 * GABBLE_NODELAY : to run any Gabble test with TCP_NODELAY set on both Wocky and Twisted's socket. This can speed up tests significantly. export GABBLE_NODELAY=1 == Jingle tests == Various jingle tests run the same tests with different dialects. To only test certain dialects use the JINGLE_DIALECTS environment variable. Currently supported are jingle015, jingle031, gtalk03 and gtalk04. For example to only run generic tests with the two jingle dialects you can do: make -C tests/twisted check-twisted TWISTED_TESTS=jingle/\*.py \ JINGLE_DIALECTS=jingle015,jingle031 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/tp-error-from-wocky.c�������������������������������������������������0000664�0001750�0001750�00000006464�12332440117�023360� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "config.h" #include <gabble/gabble.h> static void test_remap (GQuark domain, gint code, const gchar *message, TpConnectionStatus prev_status, gint exp_code, const gchar *exp_message, TpConnectionStatusReason exp_reason) { GError *error = NULL; GError wocky_error = { domain, code, (gchar *) message }; TpConnectionStatusReason conn_reason; gabble_set_tp_conn_error_from_wocky (&wocky_error, prev_status, &conn_reason, &error); g_assert (error != NULL); g_assert_cmpstr (g_quark_to_string (error->domain), ==, g_quark_to_string (TP_ERROR)); g_assert_cmpint (error->code, ==, exp_code); g_assert_cmpint (conn_reason, ==, exp_reason); if (exp_message != NULL) g_assert_cmpstr (error->message, ==, exp_message); g_error_free (error); } #define TEST_XMPP(nick, n, message, exp_code, exp_reason) \ test_remap (WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_ ## nick, message, \ TP_CONNECTION_STATUS_CONNECTED, \ exp_code, \ "WOCKY_XMPP_ERROR_" #nick " (#" #n "): " \ message, \ exp_reason) int main (void) { g_type_init (); test_remap (WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_FORBIDDEN, "computer says no", TP_CONNECTION_STATUS_CONNECTED, TP_ERROR_PERMISSION_DENIED, "WOCKY_XMPP_ERROR_FORBIDDEN (#8): computer says no", TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED); /* shorthand version of the above */ TEST_XMPP (FORBIDDEN, 8, "computer says no", TP_ERROR_PERMISSION_DENIED, TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED); /* more mappings */ TEST_XMPP (RESOURCE_CONSTRAINT, 19, "shut up!", TP_ERROR_SERVICE_BUSY, TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED); TEST_XMPP (FEATURE_NOT_IMPLEMENTED, 20, "what?", TP_ERROR_NOT_AVAILABLE, TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED); /* ConnectionReplaced, AlreadyConnected are mapped depending on the * connection status */ test_remap (WOCKY_XMPP_STREAM_ERROR, WOCKY_XMPP_STREAM_ERROR_CONFLICT, "go away", TP_CONNECTION_STATUS_CONNECTED, TP_ERROR_CONNECTION_REPLACED, "WOCKY_XMPP_STREAM_ERROR_CONFLICT (#2): go away", TP_CONNECTION_STATUS_REASON_NAME_IN_USE); test_remap (WOCKY_XMPP_STREAM_ERROR, WOCKY_XMPP_STREAM_ERROR_CONFLICT, "no you don't", TP_CONNECTION_STATUS_CONNECTING, TP_ERROR_ALREADY_CONNECTED, "WOCKY_XMPP_STREAM_ERROR_CONFLICT (#2): no you don't", TP_CONNECTION_STATUS_REASON_NAME_IN_USE); /* out-of-range is handled gracefully */ test_remap (WOCKY_XMPP_ERROR, 12345678, "lalala I am broken", TP_CONNECTION_STATUS_CONNECTED, TP_ERROR_NOT_AVAILABLE, "unknown WockyXmppError code (#12345678): lalala I am broken", TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED); /* GIOError is NetworkError, for now */ test_remap (G_IO_ERROR, G_IO_ERROR_TIMED_OUT, "network fail", TP_CONNECTION_STATUS_CONNECTED, TP_ERROR_NETWORK_ERROR, "G_IO_ERROR_TIMED_OUT (#24): network fail", TP_CONNECTION_STATUS_REASON_NETWORK_ERROR); /* other domains do something basically sane (the message will be something * vaguely helpful) */ test_remap (G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_PARSE, "what's this doing here?", TP_CONNECTION_STATUS_CONNECTED, TP_ERROR_NOT_AVAILABLE, NULL, TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED); return 0; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/Makefile.am�����������������������������������������������������������0000664�0001750�0001750�00000003237�12223562023�021376� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������SUBDIRS = twisted suppressions tests_list = \ test-dtube-unique-names \ test-gabble-idle-weak \ test-handles \ test-jid-decode \ test-parse-message \ test-presence \ test-tp-error-from-wocky gabble-C-tests.list: $(AM_V_GEN)echo $(tests_list) > $@ if ENABLE_INSTALLED_TESTS gabbletests_PROGRAMS = $(tests_list) gabbletests_DATA = gabble-C-tests.list else noinst_PROGRAMS = $(tests_list) endif LDADD = $(top_builddir)/src/libgabble-convenience.la AM_CFLAGS = $(ERROR_CFLAGS) @DBUS_CFLAGS@ @GLIB_CFLAGS@ @WOCKY_CFLAGS@ \ @TP_GLIB_CFLAGS@ \ -I $(top_srcdir) -I $(top_builddir) \ -I $(top_srcdir)/lib -I $(top_builddir)/lib TESTS = $(tests_list) TESTS_ENVIRONMENT = \ abs_top_builddir=@abs_top_builddir@ \ G_DEBUG=fatal-warnings,fatal-criticals \ sh $(top_srcdir)/tests/twisted/tools/with-session-bus.sh \ --config-file=$(top_builddir)/tests/twisted/tools/servicedir-uninstalled/tmp-session-bus.conf -- check-valgrind: $(TESTS) G_SLICE=always-malloc \ G_DEBUG=gc-friendly \ $(MAKE) \ TESTS_ENVIRONMENT="$(TESTS_ENVIRONMENT) \ libtool --mode=execute valgrind \ --leak-check=full \ --show-reachable=no \ --gen-suppressions=all \ --num-callers=20 \ --suppressions=@abs_top_srcdir@/tests/suppressions/gabble.supp \ --suppressions=@abs_top_srcdir@/tests/suppressions/tp-glib.supp \ --error-exitcode=1" \ check-TESTS check_c_sources = \ $(dbus_test_sources) \ test-dtube-unique-names.c \ test-presence.c \ test-jid-decode.c \ test-handles.c \ test-parse-message.c \ tp-error-from-wocky.c test_tp_error_from_wocky_SOURCES = tp-error-from-wocky.c include $(top_srcdir)/tools/check-coding-style.mk check-local: check-coding-style �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/test-dtube-unique-names.c���������������������������������������������0000644�0001750�0001750�00000004353�11600130473�024167� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ #include "config.h" #include <string.h> #ifdef HAVE_UNISTD_H # include <unistd.h> #endif #include <glib.h> #include "src/tube-dbus.h" int main (int argc, char **argv) { guint i; const gchar *nicknames[] = { "short", "FirstWitch", "Second witch", "012345678901234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345", /* 186 */ "012345678901234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "012345678901234567890123456", /* 187 */ "012345678901234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "01234567890123456789012345678901234567890123456789" "0123456789012345678901234567890123456789", /* 200 */ NULL }; const gchar *results[] = { ":2.c2hvcnQA", ":2.Rmlyc3RXaXRjaAAA", ":2.U2Vjb25kIHdpdGNo", ":2.MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkw" "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxM" "jM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMz" "Q1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1", ":2.MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkw" "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxM" "jM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMz" "Q1Njc4OTAxMjM0NTY3OEVd9C5NgmmRD6jp1ftG6XUEc11x", ":2.MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkw" "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxM" "jM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMz" "Q1Njc4OTAxMjM0NTY3OO-utwRnwcoUFhnJVMKg5pm9Hxal", NULL }; for (i = 0; nicknames[i] != NULL; i++) { gchar *name; name = _gabble_generate_dbus_unique_name (nicknames[i]); g_assert (strcmp (name, results[i]) == 0); g_free (name); } return 0; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/��������������������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�021032� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/addressing.py�������������������������������������������������0000664�0001750�0001750�00000016220�12332441362�023521� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test Gabble's different addressing interfaces. """ import dbus from servicetest import unwrap, tp_path_prefix, assertEquals, ProxyWrapper, \ assertContains, assertSameSets, assertDoesNotContain, pretty from gabbletest import exec_test, call_async import constants as cs import ns import time def test_protocol(q, bus, conn, stream): proto = ProxyWrapper( bus.get_object(cs.CM + '.gabble', tp_path_prefix + '/ConnectionManager/gabble/jabber'), cs.PROTOCOL, {"Addressing" : cs.PROTOCOL_IFACE_ADDRESSING}) # AddressableVCardFields and AddressableURISchemes addr_props = proto.Properties.GetAll(cs.PROTOCOL_IFACE_ADDRESSING) assertEquals(sorted(["x-jabber", "x-facebook-id"]), sorted(addr_props["AddressableVCardFields"])) assertEquals(["xmpp"], addr_props["AddressableURISchemes"]) # NormalizeVCardAddress normalized_address = proto.Addressing.NormalizeVCardAddress( "X-JABBER", "eitan@EXAMPLE.com/somewhere") assertEquals("eitan@example.com", normalized_address) normalized_address = proto.Addressing.NormalizeVCardAddress( "X-FACEBOOK-ID", "12345") assertEquals("12345", normalized_address) normalized_address = proto.Addressing.NormalizeVCardAddress( "x-facebook-id", "12345") assertEquals("12345", normalized_address) call_async(q, proto.Addressing, "NormalizeVCardAddress", "x-facebook-id", "abcde") q.expect('dbus-error', method="NormalizeVCardAddress", name=cs.INVALID_ARGUMENT) call_async(q, proto.Addressing, "NormalizeVCardAddress", "X-WEIRD-FIELD", "eitan@example.com") q.expect('dbus-error', method="NormalizeVCardAddress", name=cs.NOT_IMPLEMENTED) call_async(q, proto.Addressing, "NormalizeVCardAddress", "X-JABBER", "eitan!example.com") q.expect('dbus-error', method="NormalizeVCardAddress", name=cs.INVALID_ARGUMENT) call_async(q, proto.Addressing, "NormalizeVCardAddress", "X-FACEBOOK-ID", "-12345!chat.facebook.com") q.expect('dbus-error', method="NormalizeVCardAddress", name=cs.INVALID_ARGUMENT) call_async(q, proto.Addressing, "NormalizeVCardAddress", "X-FACEBOOK-ID", "12345@chat.facebook.com") q.expect('dbus-error', method="NormalizeVCardAddress", name=cs.INVALID_ARGUMENT) call_async(q, proto.Addressing, "NormalizeVCardAddress", "X-FACEBOOK-ID", "-12345@chat.facebook.com") q.expect('dbus-error', method="NormalizeVCardAddress", name=cs.INVALID_ARGUMENT) call_async(q, proto.Addressing, "NormalizeVCardAddress", "X-FACEBOOK-ID", "-12345@example.com") q.expect('dbus-error', method="NormalizeVCardAddress", name=cs.INVALID_ARGUMENT) call_async(q, proto.Addressing, "NormalizeVCardAddress", "X-FACEBOOK-ID", "12345@example.com") q.expect('dbus-error', method="NormalizeVCardAddress", name=cs.INVALID_ARGUMENT) call_async(q, proto.Addressing, "NormalizeVCardAddress", "X-FACEBOOK-ID", "-12345@example.com") q.expect('dbus-error', method="NormalizeVCardAddress", name=cs.INVALID_ARGUMENT) # NormalizeContactURI normalized_uri = proto.Addressing.NormalizeContactURI( "xmpp:EITAN?@example.COM/resource") assertEquals("xmpp:eitan%3F@example.com", normalized_uri) normalized_uri = proto.Addressing.NormalizeContactURI( "xmpp:EITAN?@example.COM/resourc?e") assertEquals("xmpp:eitan%3F@example.com", normalized_uri) call_async(q, proto.Addressing, "NormalizeContactURI", "Something that is far from a URI") q.expect('dbus-error', method="NormalizeContactURI", name=cs.INVALID_ARGUMENT) call_async(q, proto.Addressing, "NormalizeContactURI", "http://this@isnotawebbrowser") q.expect('dbus-error', method="NormalizeContactURI", name=cs.NOT_IMPLEMENTED) call_async(q, proto.Addressing, "NormalizeContactURI", "xmpp:something") q.expect('dbus-error', method="NormalizeContactURI", name=cs.INVALID_ARGUMENT) def test_connection(q, bus, conn, stream): event = q.expect('stream-iq', query_ns=ns.ROSTER) event.stanza['type'] = 'result' normalized_buddies = ['amy@foo.com', 'bob@foo.com', 'che@foo.com'] buddies = ['AMY@foo.com', 'bob@FOO.com', 'che@foo.com/resource'] for buddy in normalized_buddies: item = event.query.addElement('item') item['jid'] = buddy item['subscription'] = 'both' stream.send(event.stanza) requested, attributes = conn.Addressing.GetContactsByVCardField( "X-JABBER", buddies[:2] + ['bad!jid'] + buddies[2:], []) addresses = [] assertEquals(3, len(attributes)) assertEquals(3, len(requested)) for attr in attributes.values(): assertContains(cs.CONN_IFACE_ADDRESSING + '/addresses', attr.keys()) assertContains('x-jabber', attr[cs.CONN_IFACE_ADDRESSING + '/addresses'].keys()) addresses.append(attr[cs.CONN_IFACE_ADDRESSING + '/addresses']['x-jabber']) assertSameSets(normalized_buddies, addresses) assertSameSets(buddies, requested.keys()); normalized_buddies = ['12345', '54321'] buddies = ['12345', '54321'] bad_jid_buddies = ['-12345!CHAT.facebook.com', '12345@chat.facebook.com'] for buddy in buddies: item = event.query.addElement('item') item['jid'] = buddy item['subscription'] = 'both' stream.send(event.stanza) requested, attributes = conn.Addressing.GetContactsByVCardField( "X-FACEBOOK-ID", buddies + bad_jid_buddies, []) addresses = [] for attr in attributes.values(): assertContains(cs.CONN_IFACE_ADDRESSING + '/addresses', attr.keys()) assertContains('x-facebook-id', attr[cs.CONN_IFACE_ADDRESSING + '/addresses'].keys()) addr = attr[cs.CONN_IFACE_ADDRESSING + '/addresses']['x-facebook-id'] addresses.append(addr) assertEquals(attr[cs.CONN + '/contact-id'], "-" + addr + "@chat.facebook.com") assertSameSets(normalized_buddies, addresses) assertSameSets(buddies, requested.keys()); normalized_buddies = ['amy%3F@foo.com', 'bob@foo.com', 'che@foo.com'] buddies = ['AMY?@foo.com', 'bob@FOO.com', 'che@foo.com/resource'] normalized_schemes = ["xmpp", "xmpp", "http"] schemes = ["xmpp", "XMPP", "http"] valid_schemes = ["xmpp", "XMPP"] request_uris = [a + ":" + b for a, b in zip(schemes, buddies)] valid_request_uris = [a + ":" + b for a, b in zip(valid_schemes, buddies)] normalized_request_uris = [a + ":" + b for a, b in zip(normalized_schemes, normalized_buddies)] requested, attributes = conn.Addressing.GetContactsByURI(request_uris, []) assertEquals(2, len(attributes)) assertEquals(2, len(requested)) for attr in attributes.values(): assertContains(attr[cs.CONN_IFACE_ADDRESSING + '/uris'][0], normalized_request_uris) assertContains(cs.CONN_IFACE_ADDRESSING + '/uris', attr.keys()) assertSameSets(valid_request_uris, requested.keys()) if __name__ == '__main__': exec_test(test_protocol) exec_test(test_connection) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/text/���������������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�022016� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/text/send-error.py��������������������������������������������0000664�0001750�0001750�00000015336�12332441362�024451� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test that an incoming <message><error/></> for a contact gives both a SendError and a delivery report on a 1-1 text channel to that contact. """ from twisted.words.xish import domish from gabbletest import exec_test from servicetest import call_async, EventPattern import constants as cs import ns def test_temporary_error(q, bus, conn, stream): self_handle = conn.GetSelfHandle() jid = 'foo@bar.com' call_async(q, conn, 'RequestHandles', 1, [jid]) event = q.expect('dbus-return', method='RequestHandles') foo_handle = event.value[0][0] path = conn.Requests.CreateChannel( { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: foo_handle, })[0] text_chan = bus.get_object(conn.bus_name, path) # <message from='foo@bar.com' type='error'> # <body>what is up, my good sir?</body> # <error type='wait'> # <resource-constraint xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> # </error> # </message> message_body = 'what is up, my good sir?' m = domish.Element((None, 'message')) m['from'] = 'foo@bar.com' m['id'] = '1845a1a9-f7bc-4a2e-a885-633aadc81e1b' m['type'] = 'error' m.addElement('body', content=message_body) e = domish.Element((None, 'error')) e['type'] = 'wait' e.addElement((ns.STANZA, 'resource-constraint')) m.addChild(e) stream.send(m) send_error, received, message_received = q.expect_many( EventPattern('dbus-signal', signal='SendError'), EventPattern('dbus-signal', signal='Received'), EventPattern('dbus-signal', signal='MessageReceived'), ) expected_send_error = 4 # Too_Long assert send_error.args[0] == expected_send_error, send_error.args # FIXME: It doesn't look like it's possible to know what the original # message type is, given that the type attribute of <message> is 'error' # for error reports. #assert send_error.args[2] == 0, send_error.args assert send_error.args[3] == message_body, send_error.args assert received.args[2] == foo_handle, (received.args, foo_handle) assert received.args[3] == 4, received.args # Channel_Text_Message_Type_Delivery_Report assert received.args[4] == 2, received.args # Channel_Text_Message_Flag_Non_Text_Content assert received.args[5] == '', received.args delivery_report = message_received.args[0] assert len(delivery_report) == 1, delivery_report header = delivery_report[0] assert header['message-sender'] == foo_handle, header assert header['message-type'] == 4, header # Channel_Text_Message_Type_Delivery_Report assert header['delivery-status'] == 2, header # Delivery_Status_Temporarily_Failed assert header['delivery-token'] == '1845a1a9-f7bc-4a2e-a885-633aadc81e1b',\ header assert header['delivery-error'] == expected_send_error, header delivery_echo = header['delivery-echo'] assert len(delivery_echo) == 2, delivery_echo assert delivery_echo[0]['message-sender'] == self_handle, delivery_echo assert delivery_echo[0]['message-token'] == \ '1845a1a9-f7bc-4a2e-a885-633aadc81e1b', delivery_echo # FIXME: see above #assert delivery_echo[0]['message-type'] == 0, delivery_echo assert delivery_echo[1]['content-type'] == "text/plain", delivery_echo assert delivery_echo[1]['content'] == message_body, delivery_echo def test_permanent_error(q, bus, conn, stream): self_handle = conn.GetSelfHandle() jid = 'wee@ninja.jp' call_async(q, conn, 'RequestHandles', 1, [jid]) event = q.expect('dbus-return', method='RequestHandles') ninja_handle = event.value[0][0] path = conn.Requests.CreateChannel( { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: ninja_handle, })[0] text_chan = bus.get_object(conn.bus_name, path) # <message from='wee@ninja.jp' type='error'> # <body>hello? is there anyone there?</body> # <error type='cancel'> # <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> # </error> # </message> message_body = 'hello? is there anyone there?' m = domish.Element((None, 'message')) m['from'] = 'wee@ninja.jp' m['type'] = 'error' m.addElement('body', content=message_body) e = domish.Element((None, 'error')) e['type'] = 'cancel' e.addElement((ns.STANZA, 'item-not-found')) m.addChild(e) stream.send(m) send_error, received, message_received = q.expect_many( EventPattern('dbus-signal', signal='SendError'), EventPattern('dbus-signal', signal='Received'), EventPattern('dbus-signal', signal='MessageReceived'), ) expected_send_error = 2 # Invalid_Contact assert send_error.args[0] == expected_send_error, send_error.args # FIXME: It doesn't look like it's possible to know what the original # message type is, given that the type attribute of <message> is 'error' # for error reports. #assert send_error.args[2] == 0, send_error.args assert send_error.args[3] == message_body, send_error.args assert received.args[2] == ninja_handle, (received.args, ninja_handle) assert received.args[3] == 4, received.args # Channel_Text_Message_Type_Delivery_Report assert received.args[4] == 2, received.args # Channel_Text_Message_Flag_Non_Text_Content assert received.args[5] == '', received.args delivery_report = message_received.args[0] assert len(delivery_report) == 1, delivery_report header = delivery_report[0] assert header['message-sender'] == ninja_handle, header assert header['message-type'] == 4, header # Channel_Text_Message_Type_Delivery_Report assert header['delivery-status'] == 3, header # Delivery_Status_Permanently_Failed # the error has no ID, therefore its Telepathy rendition has no # delivery-token assert 'delivery-token' not in header, header assert header['delivery-error'] == expected_send_error, header delivery_echo = header['delivery-echo'] assert len(delivery_echo) == 2, delivery_echo assert delivery_echo[0]['message-sender'] == self_handle, delivery_echo # the error has no ID, therefore the echo's Telepathy rendition has no # message-token assert 'message-token' not in delivery_echo[0], delivery_echo # FIXME: see above #assert delivery_echo[0]['message-type'] == 0, delivery_echo assert delivery_echo[1]['content-type'] == "text/plain", delivery_echo assert delivery_echo[1]['content'] == message_body, delivery_echo def test(q, bus, conn, stream): test_temporary_error(q, bus, conn, stream) test_permanent_error(q, bus, conn, stream) if __name__ == '__main__': exec_test(test) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/text/send-to-correct-resource.py������������������������������0000664�0001750�0001750�00000004372�12332441362�027224� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Regression test for https://bugs.freedesktop.org/show_bug.cgi?id=22369. """ from twisted.words.xish import domish from servicetest import wrap_channel from gabbletest import exec_test import constants as cs import ns def test(q, bus, conn, stream): # <wjt> I need a random name generator # <fledermaus> Macro-Variable Spin Gel contact = 'macro-variable.spin.gel@example.com' contact_a = '%s/n810' % contact contact_b = '%s/laptop' % contact path, _ = conn.Requests.CreateChannel({ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: contact, }) chan = wrap_channel(bus.get_object(conn.bus_name, path), 'Text') # When we start a conversation, Gabble should send to the bare JID. chan.Text.Send(0, 'hey, you around?') q.expect('stream-message', to=contact) # A particular resource replies. m = domish.Element((None, 'message')) m['from'] = contact_a m['type'] = 'chat' m.addElement('body', content="i'm on a beach at Gran Canaria!") stream.send(m) q.expect('dbus-signal', signal='Received') # Now that we got a reply from a particular resource, Gabble should reply # there. chan.Text.Send(0, 'nice') q.expect('stream-message', to=contact_a) # Now another resource messages us m = domish.Element((None, 'message')) m['from'] = contact_b m['type'] = 'chat' m.addElement('body', content="I brought my laptop to the Empathy hackfest") stream.send(m) q.expect('dbus-signal', signal='Received') # Gabble should have updated the resource it's sending to. chan.Text.Send(0, "don't get sand in the keyboard") e = q.expect('stream-message', to=contact_b) # But actually that resource has gone offline: m = e.stanza m['from'] = contact_b m['type'] = 'error' del m['to'] err = m.addElement((None, 'error')) err['type'] = 'cancel' err.addElement((ns.STANZA, 'item-not-found')) stream.send(m) q.expect('dbus-signal', signal='SendError') # So as a result, Gabble should send the next message to the bare JID. chan.Text.Send(0, "... i guess my warning was too late") q.expect('stream-message', to=contact) if __name__ == '__main__': exec_test(test) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/text/test-text-no-body.py�������������������������������������0000664�0001750�0001750�00000001704�12332441362�025671� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test that <message>s with a chat state notification but no body don't create a new text channel. """ from twisted.words.xish import domish from gabbletest import exec_test import constants as cs import ns def test(q, bus, conn, stream): # message without body m = domish.Element((None, 'message')) m['from'] = 'alice@foo.com' m['type'] = 'chat' m.addElement((ns.CHAT_STATES, 'composing')) stream.send(m) # message with body m = domish.Element((None, 'message')) m['from'] = 'bob@foo.com' m['type'] = 'chat' m.addElement((ns.CHAT_STATES, 'active')) m.addElement('body', content='hello') stream.send(m) # first message should be from Bob, not Alice event = q.expect('dbus-signal', signal='NewChannel') assert event.args[1] == cs.CHANNEL_TYPE_TEXT jid = conn.InspectHandles(cs.HT_CONTACT, [event.args[3]])[0] assert jid == 'bob@foo.com' if __name__ == '__main__': exec_test(test) ������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/text/test-text-delayed.py�������������������������������������0000664�0001750�0001750�00000003027�12332441362�025731� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test receiving delayed (offline) messages on a text channel. """ import datetime from twisted.words.xish import domish from gabbletest import exec_test from servicetest import EventPattern import constants as cs def test(q, bus, conn, stream): m = domish.Element((None, 'message')) m['from'] = 'foo@bar.com' m['type'] = 'chat' m.addElement('body', content='hello') # add timestamp information x = m.addElement(('jabber:x:delay', 'x')) x['stamp'] = '20070517T16:15:01' stream.send(m) event = q.expect('dbus-signal', signal='NewChannel') assert event.args[1] == cs.CHANNEL_TYPE_TEXT assert event.args[2] == cs.HT_CONTACT jid = conn.InspectHandles(cs.HT_CONTACT, [event.args[3]])[0] assert jid == 'foo@bar.com' received, message_received = q.expect_many( EventPattern('dbus-signal', signal='Received'), EventPattern('dbus-signal', signal='MessageReceived'), ) assert (str(datetime.datetime.utcfromtimestamp(received.args[1])) == '2007-05-17 16:15:01') assert received.args[5] == 'hello' message = message_received.args[0] header = message[0] message_sent_timestamp = header['message-sent'] assert str(datetime.datetime.utcfromtimestamp(message_sent_timestamp) == '2007-05-17 16:15:01'), header message_received_timestamp = header['message-received'] assert message_received_timestamp > message_sent_timestamp, header assert message[1]['content'] == 'hello', message if __name__ == '__main__': exec_test(test) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/text/receipts.py����������������������������������������������0000664�0001750�0001750�00000015064�12332441362�024205� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# coding=utf-8 """ Test XEP-0184 receipts. """ from servicetest import ( EventPattern, assertEquals, assertLength, sync_dbus, wrap_channel, ) from gabbletest import exec_test, elem, sync_stream, acknowledge_iq import constants as cs import ns import caps_helper import rostertest from presence.invisible_helper import Xep0186Stream GUYBRUSH = 'guybrush@mi.lit' GUYBRUSH_FULL_JID = GUYBRUSH + '/Sea Cucumber' def send_received_report(stream, jid, received_id): stream.send( elem('message', from_=jid)( elem(ns.RECEIPTS, 'received', id=received_id) )) def report_received_on_open_channel(q, bus, conn, stream, chan): received_id = 'fine-leather-jackets' send_received_report(stream, GUYBRUSH, received_id) e = q.expect('dbus-signal', signal='MessageReceived', path=chan.object_path) message, = e.args header, = message assertEquals(cs.MT_DELIVERY_REPORT, header['message-type']) assertEquals(cs.DELIVERY_STATUS_DELIVERED, header['delivery-status']) assertEquals(received_id, header['delivery-token']) def report_ignored_without_channel(q, bus, conn, stream): q.forbid_events([EventPattern('dbus-signal', signal='MessageReceived')]) send_received_report(stream, 'marley@mi.gov', 'only-one-candidate') sync_dbus(bus, q, conn) q.unforbid_all() def not_sending_request_to_contact(q, bus, conn, stream, chan): message = [ { 'message-type': cs.MT_NORMAL, }, { 'content-type': 'text/plain', 'content': 'Mancomb Seepgood?', }] chan.Messages.SendMessage(message, 0) e = q.expect('stream-message', to=GUYBRUSH) assertLength(0, list(e.stanza.elements(uri=ns.RECEIPTS, name='request'))) def sending_request_to_presenceless_contact(q, bus, conn, stream, chan): """ Initially we know nothing of Guybrush's presence, so should just try our level best if asked to. """ message = [ { 'message-type': cs.MT_NORMAL, }, { 'content-type': 'text/plain', 'content': 'Thriftweed?', }] chan.Messages.SendMessage(message, cs.MSG_SENDING_FLAGS_REPORT_DELIVERY) e = q.expect('stream-message', to=GUYBRUSH) assertLength(1, list(e.stanza.elements(uri=ns.RECEIPTS, name='request'))) def sending_request_to_cappy_contact(q, bus, conn, stream, chan): """ Test that Gabble requests a receipt from a contact whom we know supports this extension, but only if asked. """ # Convince Gabble that Guybrush supports this extension caps = { 'node': 'http://whatever', 'ver': caps_helper.compute_caps_hash([], [ns.RECEIPTS], {}), 'hash': 'sha-1', } caps_helper.presence_and_disco(q, conn, stream, GUYBRUSH_FULL_JID, disco=True, client=caps['node'], caps=caps, features=[ns.RECEIPTS]) sync_stream(q, stream) # Don't ask, don't tell — even if we know Guybrush does support this. not_sending_request_to_contact(q, bus, conn, stream, chan) # Ask, tell. message = [ { 'message-type': cs.MT_NORMAL, }, { 'content-type': 'text/plain', 'content': 'Ulysses?', }] chan.Messages.SendMessage(message, cs.MSG_SENDING_FLAGS_REPORT_DELIVERY) e = q.expect('stream-message', to=GUYBRUSH) assertLength(1, list(e.stanza.elements(uri=ns.RECEIPTS, name='request'))) def replying_to_requests(q, bus, conn, stream): jid = 'lechuck@lucasarts.lit' # We shouldn't send receipts to people who aren't on our roster. q.forbid_events([EventPattern('stream-message', to=jid)]) stream.send( elem('message', from_=jid, type='chat', id='alpha')( elem('body')( u"You didn't kill me, you moron!" ), elem(ns.RECEIPTS, 'request') )) q.expect('dbus-signal', signal='MessageReceived') sync_stream(q, stream) q.unforbid_all() # We should send receipts to people on our roster, seeing as we're not # invisible. rostertest.send_roster_push(stream, jid, subscription='from') stream.send( elem('message', from_=jid, type='chat', id='beta')( elem('body')( u"You've just destroyed my spiritual essences." ), elem(ns.RECEIPTS, 'request') )) q.expect('dbus-signal', signal='MessageReceived') e = q.expect('stream-message', to=jid) receipt = e.stanza.elements(uri=ns.RECEIPTS, name='received').next() assertEquals('beta', receipt['id']) # We would like requests in messages without id=''s not to crash Gabble, # and also for it not to send a reply. q.forbid_events([EventPattern('stream-message', to=jid)]) stream.send( elem('message', from_=jid, type='chat')( # NB. no id='' attribute elem('body')( u"A favor that I shall now return!" ), elem(ns.RECEIPTS, 'request') )) q.expect('dbus-signal', signal='MessageReceived') sync_stream(q, stream) q.unforbid_all() # If we're invisible, LeChuck shouldn't get receipts. conn.SimplePresence.SetPresence("hidden", "") event = q.expect('stream-iq', query_name='invisible') acknowledge_iq(stream, event.stanza) q.forbid_events([EventPattern('stream-message', to=jid)]) stream.send( elem('message', from_=jid, type='chat', id='epsilon')( elem('body')( u"… but where am I going to find a duck wearing burlap chaps?" ), elem(ns.RECEIPTS, 'request') )) q.expect('dbus-signal', signal='MessageReceived') sync_stream(q, stream) q.unforbid_all() def test(q, bus, conn, stream): path = conn.Requests.CreateChannel( { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: GUYBRUSH, })[0] chan = wrap_channel(bus.get_object(conn.bus_name, path), 'Text', ['Messages']) # Let's start out with an empty roster, eh? e = q.expect('stream-iq', iq_type='get', query_ns=ns.ROSTER) e.stanza['type'] = 'result' stream.send(e.stanza) report_received_on_open_channel(q, bus, conn, stream, chan) report_ignored_without_channel(q, bus, conn, stream) not_sending_request_to_contact(q, bus, conn, stream, chan) # FIXME: This test is disabled because of stupidity in the presence cache. # See the comment in receipts_conceivably_supported(). #sending_request_to_presenceless_contact(q, bus, conn, stream, chan) sending_request_to_cappy_contact(q, bus, conn, stream, chan) replying_to_requests(q, bus, conn, stream) if __name__ == '__main__': exec_test(test, protocol=Xep0186Stream) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/text/ensure.py������������������������������������������������0000664�0001750�0001750�00000013065�12332441362�023667� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test text channel initiated by me, using Requests.EnsureChannel """ import dbus from gabbletest import exec_test from servicetest import call_async, EventPattern import constants as cs def test(q, bus, conn, stream): self_handle = conn.GetSelfHandle() jids = ['foo@bar.com', 'truc@cafe.fr'] call_async(q, conn, 'RequestHandles', 1, jids) event = q.expect('dbus-return', method='RequestHandles') handles = event.value[0] properties = conn.GetAll( cs.CONN_IFACE_REQUESTS, dbus_interface=cs.PROPERTIES_IFACE) assert properties.get('Channels') == [], properties['Channels'] assert ({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, }, [cs.TARGET_HANDLE, cs.TARGET_ID], ) in properties.get('RequestableChannelClasses'),\ properties['RequestableChannelClasses'] test_ensure_ensure(q, conn, self_handle, jids[0], handles[0]) test_request_ensure(q, conn, self_handle, jids[1], handles[1]) def test_ensure_ensure(q, conn, self_handle, jid, handle): """ Test ensuring a non-existant channel twice. The first call should succeed with Yours=True; the subsequent call should succeed with Yours=False """ # Check that Ensuring a channel that doesn't exist succeeds call_async(q, conn.Requests, 'EnsureChannel', request_props (handle)) ret, old_sig, new_sig = q.expect_many( EventPattern('dbus-return', method='EnsureChannel'), EventPattern('dbus-signal', signal='NewChannel'), EventPattern('dbus-signal', signal='NewChannels'), ) assert len(ret.value) == 3 yours, path, emitted_props = ret.value # The channel was created in response to the call, and we were the only # requestor, so we should get Yours=True assert yours, ret.value check_props(emitted_props, self_handle, handle, jid) assert len(old_sig.args) == 5 old_path, old_ct, old_ht, old_h, old_sh = old_sig.args assert old_path == path assert old_ct == cs.CHANNEL_TYPE_TEXT assert old_ht == cs.HT_CONTACT assert old_h == handle assert old_sh == True # suppress handler assert len(new_sig.args) == 1 assert len(new_sig.args[0]) == 1 # one channel assert len(new_sig.args[0][0]) == 2 # two struct members assert new_sig.args[0][0][0] == path assert new_sig.args[0][0][1] == emitted_props properties = conn.GetAll( cs.CONN_IFACE_REQUESTS, dbus_interface=dbus.PROPERTIES_IFACE) assert new_sig.args[0][0] in properties['Channels'], \ (new_sig.args[0][0], properties['Channels']) # Now try Ensuring a channel which already exists call_async(q, conn.Requests, 'EnsureChannel', request_props(handle)) ret_ = q.expect('dbus-return', method='EnsureChannel') assert len(ret_.value) == 3 yours_, path_, emitted_props_ = ret_.value # Someone's already responsible for this channel, so we should get # Yours=False assert not yours_, ret_.value assert path == path_, (path, path_) assert emitted_props == emitted_props_, (emitted_props, emitted_props_) def test_request_ensure(q, conn, self_handle, jid, handle): """ Test Creating a non-existant channel, then Ensuring the same channel. The call to Ensure should succeed with Yours=False. """ call_async(q, conn.Requests, 'CreateChannel', request_props(handle)) ret, old_sig, new_sig = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('dbus-signal', signal='NewChannel'), EventPattern('dbus-signal', signal='NewChannels'), ) assert len(ret.value) == 2 path, emitted_props = ret.value check_props(emitted_props, self_handle, handle, jid) assert len(old_sig.args) == 5 old_path, old_ct, old_ht, old_h, old_sh = old_sig.args assert old_path == path assert old_ct == cs.CHANNEL_TYPE_TEXT assert old_ht == cs.HT_CONTACT assert old_h == handle assert old_sh == True # suppress handler assert len(new_sig.args) == 1 assert len(new_sig.args[0]) == 1 # one channel assert len(new_sig.args[0][0]) == 2 # two struct members assert new_sig.args[0][0][0] == path assert new_sig.args[0][0][1] == emitted_props properties = conn.GetAll( cs.CONN_IFACE_REQUESTS, dbus_interface=dbus.PROPERTIES_IFACE) assert new_sig.args[0][0] in properties['Channels'], \ (new_sig.args[0][0], properties['Channels']) # Now try Ensuring that same channel. call_async(q, conn.Requests, 'EnsureChannel', request_props(handle)) ret_ = q.expect('dbus-return', method='EnsureChannel') assert len(ret_.value) == 3 yours_, path_, emitted_props_ = ret_.value # Someone's already responsible for this channel, so we should get # Yours=False assert not yours_, ret_.value assert path == path_, (path, path_) assert emitted_props == emitted_props_, (emitted_props, emitted_props_) def check_props(props, self_handle, handle, jid): assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT assert props[cs.TARGET_HANDLE_TYPE] == cs.HT_CONTACT assert props[cs.TARGET_HANDLE] == handle assert props[cs.TARGET_ID] == jid assert props[cs.REQUESTED] == True assert props[cs.INITIATOR_HANDLE] == self_handle assert props[cs.INITIATOR_ID] == 'test@localhost' def request_props(handle): return { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: handle, } if __name__ == '__main__': exec_test(test) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/text/test-chat-state.py���������������������������������������0000664�0001750�0001750�00000033372�12332441362�025403� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# coding=utf-8 """ Test that chat state notifications are correctly sent and received on text channels. """ from twisted.words.xish import domish from servicetest import (assertEquals, assertNotEquals, assertLength, wrap_channel, EventPattern, call_async, sync_dbus) from gabbletest import exec_test, make_result_iq, sync_stream, make_presence import constants as cs import ns def check_state_notification(elem, name, allow_body=False): assertEquals('message', elem.name) assertEquals('chat', elem['type']) children = list(elem.elements()) notification = [x for x in children if x.uri == ns.CHAT_STATES][0] assert notification.name == name, notification.toXml() if not allow_body: assert len(children) == 1, elem.toXml() def make_message(jid, body=None, state=None): m = domish.Element((None, 'message')) m['from'] = jid m['type'] = 'chat' if state is not None: m.addElement((ns.CHAT_STATES, state)) if body is not None: m.addElement('body', content=body) return m def test(q, bus, conn, stream): self_handle = conn.GetSelfHandle() jid = 'foo@bar.com' full_jid = 'foo@bar.com/Foo' foo_handle = conn.RequestHandles(cs.HT_CONTACT, [jid])[0] path = conn.Requests.CreateChannel( { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: foo_handle, })[0] chan = wrap_channel(bus.get_object(conn.bus_name, path), 'Text', ['ChatState', 'Destroyable']) presence = make_presence(full_jid, status='hello', caps={ 'node': 'http://telepathy.freedesktop.org/homeopathy', 'ver' : '0.1', }) stream.send(presence) version_event = q.expect('stream-iq', to=full_jid, query_ns=ns.DISCO_INFO, query_node='http://telepathy.freedesktop.org/homeopathy#0.1') result = make_result_iq(stream, version_event.stanza) query = result.firstChildElement() feature = query.addElement('feature') feature['var'] = ns.CHAT_STATES stream.send(result) sync_stream(q, stream) states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates') assertEquals(cs.CHAT_STATE_INACTIVE, states.get(self_handle, cs.CHAT_STATE_INACTIVE)) assertEquals(cs.CHAT_STATE_INACTIVE, states.get(foo_handle, cs.CHAT_STATE_INACTIVE)) # Receiving chat states: # Composing... stream.send(make_message(full_jid, state='composing')) changed = q.expect('dbus-signal', signal='ChatStateChanged', path=chan.object_path) handle, state = changed.args assertEquals(foo_handle, handle) assertEquals(cs.CHAT_STATE_COMPOSING, state) states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates') assertEquals(cs.CHAT_STATE_INACTIVE, states.get(self_handle, cs.CHAT_STATE_INACTIVE)) assertEquals(cs.CHAT_STATE_COMPOSING, states.get(foo_handle, cs.CHAT_STATE_INACTIVE)) # Message! stream.send(make_message(full_jid, body='hello', state='active')) changed = q.expect('dbus-signal', signal='ChatStateChanged', path=chan.object_path) handle, state = changed.args assertEquals(foo_handle, handle) assertEquals(cs.CHAT_STATE_ACTIVE, state) states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates') assertEquals(cs.CHAT_STATE_INACTIVE, states.get(self_handle, cs.CHAT_STATE_INACTIVE)) assertEquals(cs.CHAT_STATE_ACTIVE, states.get(foo_handle, cs.CHAT_STATE_INACTIVE)) # Assert that a redundant chat-state change doesn't emit a signal forbidden = [EventPattern('dbus-signal', signal='ChatStateChanged', args=[foo_handle, cs.CHAT_STATE_ACTIVE])] q.forbid_events(forbidden) m = domish.Element((None, 'message')) m['from'] = 'foo@bar.com/Foo' m['type'] = 'chat' m.addElement((ns.CHAT_STATES, 'active')) m.addElement('body', content='hello') stream.send(m) sync_dbus(bus, q, conn) sync_stream(q, stream) q.unforbid_events(forbidden) # Sending chat states: # Composing... chan.ChatState.SetChatState(cs.CHAT_STATE_COMPOSING) stream_message = q.expect('stream-message') check_state_notification(stream_message.stanza, 'composing') states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates') assertEquals(cs.CHAT_STATE_COMPOSING, states.get(self_handle, cs.CHAT_STATE_INACTIVE)) assertEquals(cs.CHAT_STATE_ACTIVE, states.get(foo_handle, cs.CHAT_STATE_INACTIVE)) # XEP 0085: # every content message SHOULD contain an <active/> notification. chan.Text.Send(0, 'hi.') stream_message = q.expect('stream-message') elem = stream_message.stanza assertEquals('chat', elem['type']) check_state_notification(elem, 'active', allow_body=True) states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates') assertEquals(cs.CHAT_STATE_ACTIVE, states.get(self_handle, cs.CHAT_STATE_INACTIVE)) assertEquals(cs.CHAT_STATE_ACTIVE, states.get(foo_handle, cs.CHAT_STATE_INACTIVE)) def is_body(e): if e.name == 'body': assert e.children[0] == u'hi.', e.toXml() return True return False assert len([x for x in elem.elements() if is_body(x)]) == 1, elem.toXml() # Close the channel without acking the received message. The peer should # get a <gone/> notification, and the channel should respawn. chan.Close() gone, _, _ = q.expect_many( EventPattern('stream-message'), EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='NewChannel'), ) check_state_notification(gone.stanza, 'gone') # Reusing the proxy object because we happen to know it'll be at the same # path... # Destroy the channel. The peer shouldn't get a <gone/> notification, since # we already said we were gone and haven't sent them any messages to the # contrary. es = [EventPattern('stream-message')] q.forbid_events(es) chan.Destroyable.Destroy() sync_stream(q, stream) # Make the channel anew. path = conn.Requests.CreateChannel( { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: foo_handle, })[0] chan = wrap_channel(bus.get_object(conn.bus_name, path), 'Text', ['ChatState', 'Destroyable']) # Close it immediately; the peer should again not get a <gone/> # notification, since we haven't sent any notifications on that channel. chan.Close() sync_stream(q, stream) q.unforbid_events(es) # XEP-0085 §5.1 defines how to negotiate support for chat states with a # contact in the absence of capabilities. This is useful when talking to # invisible contacts, for example. # First, if we receive a message from a contact, containing an <active/> # notification, they support chat states, so we should send them. jid = 'i@example.com' full_jid = jid + '/GTalk' path = conn.Requests.CreateChannel( { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: jid, })[0] chan = wrap_channel(bus.get_object(conn.bus_name, path), 'Text', ['ChatState']) stream.send(make_message(full_jid, body='i am invisible', state='active')) changed = q.expect('dbus-signal', signal='ChatStateChanged', path=chan.object_path) assertEquals(cs.CHAT_STATE_ACTIVE, changed.args[1]) # We've seen them send a chat state notification, so we should send them # notifications when the UI tells us to. chan.ChatState.SetChatState(cs.CHAT_STATE_COMPOSING) stream_message = q.expect('stream-message', to=full_jid) check_state_notification(stream_message.stanza, 'composing') changed = q.expect('dbus-signal', signal='ChatStateChanged', path=chan.object_path) handle, state = changed.args assertEquals(cs.CHAT_STATE_COMPOSING, state) assertEquals(self_handle, handle) chan.Text.Send(0, 'very convincing') stream_message = q.expect('stream-message', to=full_jid) check_state_notification(stream_message.stanza, 'active', allow_body=True) # Now, test the case where we start the negotiation, and the contact # turns out to support chat state notifications. jid = 'c@example.com' full_jid = jid + '/GTalk' path = conn.Requests.CreateChannel( { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: jid, })[0] chan = wrap_channel(bus.get_object(conn.bus_name, path), 'Text', ['ChatState']) # We shouldn't send any notifications until we actually send a message. # But ChatStateChanged is still emitted locally e = EventPattern('stream-message', to=jid) q.forbid_events([e]) for i in [cs.CHAT_STATE_ACTIVE, cs.CHAT_STATE_COMPOSING, cs.CHAT_STATE_PAUSED, cs.CHAT_STATE_INACTIVE ]: chan.ChatState.SetChatState(i) changed = q.expect('dbus-signal', signal='ChatStateChanged', path=chan.object_path) handle, state = changed.args assertEquals(i, state) assertEquals(self_handle, handle) sync_stream(q, stream) q.unforbid_events([e]) # When we send a message, say we're active. chan.Text.Send(0, 'is anyone there?') stream_message = q.expect('stream-message', to=jid) check_state_notification(stream_message.stanza, 'active', allow_body=True) # The D-Bus property changes, too changed = q.expect('dbus-signal', signal='ChatStateChanged', path=chan.object_path) handle, state = changed.args assertEquals(cs.CHAT_STATE_ACTIVE, state) assertEquals(self_handle, handle) # We get a notification back from our contact. stream.send(make_message(full_jid, state='composing')) # Wait until gabble tells us the chat-state of the remote party has # changed so we know gabble knows chat state notification are supported changed = q.expect('dbus-signal', signal='ChatStateChanged', path=chan.object_path) handle, state = changed.args assertEquals(cs.CHAT_STATE_COMPOSING, state) assertNotEquals(foo_handle, handle) # So now we know they support notification, so should send notifications. chan.ChatState.SetChatState(cs.CHAT_STATE_COMPOSING) # This doesn't check whether we're sending to the bare jid, or the # jid+resource. In fact, the notification is sent to the bare jid, because # we only update which jid we send to when we actually receive a message, # not when we receive a notification. wjt thinks this is less surprising # than the alternative: # # • I'm talking to you on my N900, and signed in on my laptop; # • I enter one character in a tab to you on my laptop, and then delete # it; # • Now your messages to me appear on my laptop (until I send you another # one from my N900)! stream_message = q.expect('stream-message') check_state_notification(stream_message.stanza, 'composing') # The D-Bus property changes, too changed = q.expect('dbus-signal', signal='ChatStateChanged', path=chan.object_path) handle, state = changed.args assertEquals(cs.CHAT_STATE_COMPOSING, state) assertEquals(self_handle, handle) # But! Now they start messaging us from a different client, which *doesn't* # support notifications. other_jid = jid + '/Library' stream.send(make_message(other_jid, body='grr, library computers')) q.expect('dbus-signal', signal='Received') # Okay, we should stop sending typing notifications. e = EventPattern('stream-message', to=other_jid) q.forbid_events([e]) for i in [cs.CHAT_STATE_COMPOSING, cs.CHAT_STATE_INACTIVE, cs.CHAT_STATE_PAUSED, cs.CHAT_STATE_ACTIVE]: chan.ChatState.SetChatState(i) sync_stream(q, stream) q.unforbid_events([e]) # Now, test the case where we start the negotiation, and the contact # does not support chat state notifications jid = 'twitterbot@example.com' full_jid = jid + '/Nonsense' path = conn.Requests.CreateChannel( { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: jid, })[0] chan = wrap_channel(bus.get_object(conn.bus_name, path), 'Text', ['ChatState']) # We shouldn't send any notifications until we actually send a message. e = EventPattern('stream-message', to=jid) q.forbid_events([e]) for i in [cs.CHAT_STATE_COMPOSING, cs.CHAT_STATE_INACTIVE, cs.CHAT_STATE_PAUSED, cs.CHAT_STATE_ACTIVE]: chan.ChatState.SetChatState(i) sync_stream(q, stream) q.unforbid_events([e]) # When we send a message, say we're active. chan.Text.Send(0, '#n900 #maemo #zomg #woo #yay http://bit.ly/n900') stream_message = q.expect('stream-message', to=jid) check_state_notification(stream_message.stanza, 'active', allow_body=True) # They reply without a chat state. stream.send(make_message(full_jid, body="posted.")) q.expect('dbus-signal', signal='Received') # Okay, we shouldn't send any more. e = EventPattern('stream-message', to=other_jid) q.forbid_events([e]) for i in [cs.CHAT_STATE_COMPOSING, cs.CHAT_STATE_INACTIVE, cs.CHAT_STATE_PAUSED, cs.CHAT_STATE_ACTIVE]: chan.ChatState.SetChatState(i) sync_stream(q, stream) q.unforbid_events([e]) chan.Text.Send(0, '@stephenfry simmer down') message = q.expect('stream-message') states = [x for x in message.stanza.elements() if x.uri == ns.CHAT_STATES] assertLength(0, states) if __name__ == '__main__': exec_test(test) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/text/respawn.py�����������������������������������������������0000664�0001750�0001750�00000013051�12332441362�024040� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test text channel being recreated because there are still pending messages. """ import dbus from twisted.words.xish import domish from gabbletest import exec_test from servicetest import call_async, EventPattern, assertEquals import constants as cs def test(q, bus, conn, stream): self_handle = conn.GetSelfHandle() jid = 'foo@bar.com' foo_handle = conn.RequestHandles(cs.HT_CONTACT, [jid])[0] call_async(q, conn, 'RequestChannel', cs.CHANNEL_TYPE_TEXT, cs.HT_CONTACT, foo_handle, True) ret, old_sig, new_sig = q.expect_many( EventPattern('dbus-return', method='RequestChannel'), EventPattern('dbus-signal', signal='NewChannel'), EventPattern('dbus-signal', signal='NewChannels'), ) text_chan = bus.get_object(conn.bus_name, ret.value[0]) chan_iface = dbus.Interface(text_chan, cs.CHANNEL) text_iface = dbus.Interface(text_chan, cs.CHANNEL_TYPE_TEXT) assert old_sig.args[0] == ret.value[0] assert old_sig.args[1] == cs.CHANNEL_TYPE_TEXT assert old_sig.args[2] == cs.HT_CONTACT assert old_sig.args[3] == foo_handle assert old_sig.args[4] == True # suppress handler assert len(new_sig.args) == 1 assert len(new_sig.args[0]) == 1 # one channel assert len(new_sig.args[0][0]) == 2 # two struct members assert new_sig.args[0][0][0] == ret.value[0] emitted_props = new_sig.args[0][0][1] assert emitted_props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT assert emitted_props[cs.TARGET_HANDLE_TYPE] == cs.HT_CONTACT assert emitted_props[cs.TARGET_HANDLE] == foo_handle assert emitted_props[cs.TARGET_ID] == jid assert emitted_props[cs.REQUESTED] == True assert emitted_props[cs.INITIATOR_HANDLE] == self_handle assert emitted_props[cs.INITIATOR_ID] == 'test@localhost' channel_props = text_chan.GetAll( cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE) assert channel_props['TargetID'] == jid,\ (channel_props['TargetID'], jid) assert channel_props['Requested'] == True assert channel_props['InitiatorHandle'] == self_handle,\ (channel_props['InitiatorHandle'], self_handle) assert channel_props['InitiatorID'] == 'test@localhost',\ channel_props['InitiatorID'] text_iface.Send(0, 'hey') event = q.expect('stream-message') elem = event.stanza assert elem.name == 'message' assert elem['type'] == 'chat' body = list(event.stanza.elements())[0] assert body.name == 'body' assert body.children[0] == u'hey' # <message type="chat"><body>hello</body</message> m = domish.Element((None, 'message')) m['from'] = 'foo@bar.com/Pidgin' m['type'] = 'chat' m.addElement('body', content='hello') stream.send(m) event = q.expect('dbus-signal', signal='Received') hello_message_id = event.args[0] hello_message_time = event.args[1] assert event.args[2] == foo_handle # message type: normal assert event.args[3] == 0 # flags: none assert event.args[4] == 0 # body assert event.args[5] == 'hello' messages = text_chan.ListPendingMessages(False, dbus_interface=cs.CHANNEL_TYPE_TEXT) assert messages == \ [(hello_message_id, hello_message_time, foo_handle, 0, 0, 'hello')], messages # close the channel without acking the message; it comes back call_async(q, chan_iface, 'Close') old, new = q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed'), ) assert old.path == text_chan.object_path,\ (old.path, text_chan.object_path) assert new.args[0] == text_chan.object_path,\ (new.args[0], text_chan.object_path) event = q.expect('dbus-signal', signal='NewChannel') assert event.args[0] == text_chan.object_path assert event.args[1] == cs.CHANNEL_TYPE_TEXT assert event.args[2] == cs.HT_CONTACT assert event.args[3] == foo_handle assert event.args[4] == False # suppress handler event = q.expect('dbus-return', method='Close') # it now behaves as if the message had initiated it channel_props = text_chan.GetAll( cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE) assert channel_props['TargetID'] == jid,\ (channel_props['TargetID'], jid) assert channel_props['Requested'] == False assert channel_props['InitiatorHandle'] == foo_handle,\ (channel_props['InitiatorHandle'], foo_handle) assert channel_props['InitiatorID'] == 'foo@bar.com',\ channel_props['InitiatorID'] # the message is still there messages = text_chan.ListPendingMessages(False, dbus_interface=cs.CHANNEL_TYPE_TEXT) assertEquals( [(hello_message_id, hello_message_time, foo_handle, 0, 8, 'hello')], messages) # acknowledge it text_chan.AcknowledgePendingMessages([hello_message_id], dbus_interface=cs.CHANNEL_TYPE_TEXT) messages = text_chan.ListPendingMessages(False, dbus_interface=cs.CHANNEL_TYPE_TEXT) assert messages == [] # close the channel again call_async(q, chan_iface, 'Close') event = q.expect('dbus-signal', signal='Closed') assert event.path == text_chan.object_path,\ (event.path, text_chan.object_path) event = q.expect('dbus-return', method='Close') # assert that it stays dead this time! try: chan_iface.GetChannelType() except dbus.DBusException: pass else: raise AssertionError("Why won't it die?") if __name__ == '__main__': exec_test(test) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/text/test-text.py���������������������������������������������0000664�0001750�0001750�00000015402�12332441362�024324� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test text channel. """ import dbus from twisted.words.xish import domish from gabbletest import exec_test, elem from servicetest import ( EventPattern, wrap_channel, assertEquals, assertNotEquals, assertLength, ) import constants as cs def test(q, bus, conn, stream): id = '1845a1a9-f7bc-4a2e-a885-633aadc81e1b' # <message type="chat"><body>hello</body</message> m = domish.Element((None, 'message')) m['from'] = 'foo@bar.com/Pidgin' m['id'] = id m['type'] = 'chat' m.addElement('body', content='hello') stream.send(m) event = q.expect('dbus-signal', signal='NewChannel') text_chan = wrap_channel( bus.get_object(conn.bus_name, event.args[0]), 'Text', ['Messages']) assert event.args[1] == cs.CHANNEL_TYPE_TEXT assert event.args[2] == cs.HT_CONTACT foo_at_bar_dot_com_handle = event.args[3] jid = conn.InspectHandles(1, [foo_at_bar_dot_com_handle])[0] assert jid == 'foo@bar.com' assert event.args[4] == False # suppress handler # Exercise basic Channel Properties from spec 0.17.7 channel_props = text_chan.Properties.GetAll(cs.CHANNEL) assert channel_props.get('TargetHandle') == event.args[3],\ (channel_props.get('TargetHandle'), event.args[3]) assert channel_props.get('TargetHandleType') == cs.HT_CONTACT,\ channel_props.get('TargetHandleType') assert channel_props.get('ChannelType') == \ cs.CHANNEL_TYPE_TEXT,\ channel_props.get('ChannelType') assert cs.CHANNEL_IFACE_CHAT_STATE in \ channel_props.get('Interfaces', ()), \ channel_props.get('Interfaces') assert cs.CHANNEL_IFACE_MESSAGES in \ channel_props.get('Interfaces', ()), \ channel_props.get('Interfaces') assert channel_props['TargetID'] == jid,\ (channel_props['TargetID'], jid) assert channel_props['Requested'] == False assert channel_props['InitiatorHandle'] == event.args[3],\ (channel_props['InitiatorHandle'], event.args[3]) assert channel_props['InitiatorID'] == jid,\ (channel_props['InitiatorID'], jid) received, message_received = q.expect_many( EventPattern('dbus-signal', signal='Received'), EventPattern('dbus-signal', signal='MessageReceived'), ) # Check that C.T.Text.Received looks right # message type: normal assert received.args[3] == 0 # flags: none assert received.args[4] == 0 # body assert received.args[5] == 'hello' # Check that C.I.Messages.MessageReceived looks right. message = message_received.args[0] # message should have two parts: the header and one content part assert len(message) == 2, message header, body = message assert header['message-sender'] == foo_at_bar_dot_com_handle, header # the spec says that message-type "MAY be omitted for normal chat # messages." assert 'message-type' not in header or header['message-type'] == 0, header # We don't make any uniqueness guarantees about the tokens on incoming # messages, so we use the id='' provided at the protocol level. assertEquals(id, header['message-token']) assert body['content-type'] == 'text/plain', body assert body['content'] == 'hello', body # Remove the message from the pending message queue, and check that # PendingMessagesRemoved fires. message_id = header['pending-message-id'] text_chan.Text.AcknowledgePendingMessages([message_id]) removed = q.expect('dbus-signal', signal='PendingMessagesRemoved') removed_ids = removed.args[0] assert len(removed_ids) == 1, removed_ids assert removed_ids[0] == message_id, (removed_ids, message_id) # Send a Notice using the Messages API greeting = [ dbus.Dictionary({ 'message-type': 2, # Notice }, signature='sv'), { 'content-type': 'text/plain', 'content': u"what up", } ] sent_token = text_chan.Messages.SendMessage(greeting, dbus.UInt32(0)) stream_message, sent, message_sent = q.expect_many( EventPattern('stream-message'), EventPattern('dbus-signal', signal='Sent'), EventPattern('dbus-signal', signal='MessageSent'), ) elt = stream_message.stanza assert elt.name == 'message' assert elt['type'] == 'normal' body = list(stream_message.stanza.elements())[0] assert body.name == 'body' assert body.children[0] == u'what up' sent_message = message_sent.args[0] assert len(sent_message) == 2, sent_message header = sent_message[0] assert header['message-type'] == 2, header # Notice assert header['message-token'] == sent_token, header assertEquals(conn.GetSelfHandle(), header['message-sender']) assertEquals('test@localhost', header['message-sender-id']) body = sent_message[1] assert body['content-type'] == 'text/plain', body assert body['content'] == u'what up', body assert message_sent.args[2] == sent_token assert sent.args[1] == 2, sent.args # Notice assert sent.args[2] == u'what up', sent.args # Send a message using Channel.Type.Text API text_chan.Text.Send(0, 'goodbye') stream_message, sent, message_sent = q.expect_many( EventPattern('stream-message'), EventPattern('dbus-signal', signal='Sent'), EventPattern('dbus-signal', signal='MessageSent'), ) elt = stream_message.stanza assert elt.name == 'message' assert elt['type'] == 'chat' body = list(stream_message.stanza.elements())[0] assert body.name == 'body' assert body.children[0] == u'goodbye' sent_message = message_sent.args[0] assert len(sent_message) == 2, sent_message header = sent_message[0] # the spec says that message-type "MAY be omitted for normal chat # messages." assert 'message-type' not in header or header['message-type'] == 0, header body = sent_message[1] assert body['content-type'] == 'text/plain', body assert body['content'] == u'goodbye', body assert sent.args[1] == 0, sent.args # message type normal assert sent.args[2] == u'goodbye', sent.args # And now let's try a message with a malformed type='' attribute. malformed = elem( 'message', from_='foo@bar.com/fubber', type="'")( elem('body')(u'Internettt!'), elem('subject')(u'xyzzy'), elem('thread')(u'6666'), ) stream.send(malformed) event = q.expect('dbus-signal', signal='MessageReceived') message, = event.args assertLength(2, message) header, body = message # Gabble should treat the unparseable type as if it were 'normal' or # omitted (not to be confused with Telepathy's Normal, which is 'chat' in # XMPP...) assertEquals(cs.MT_NOTICE, header['message-type']) if __name__ == '__main__': exec_test(test) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/text/facebook-own-message.py����������������������������������0000664�0001750�0001750�00000005153�12332441362�026361� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Tests exposing Facebook's own-message extension via delivery reports. I would say that this has been reverse-engineered, but reading the completely trivial protocol out of debug logs is hardly reverse-engineering. It isn't documented anywhere I can find, mind you. """ from servicetest import ( assertEquals, assertLength, assertContains, wrap_channel, EventPattern, sync_dbus, ) from gabbletest import exec_test, elem, elem_iq import constants as cs NS_FACEBOOK_MESSAGES = "http://www.facebook.com/xmpp/messages" def test(q, bus, conn, stream): def send_own_message(to, text): iq = elem_iq(stream, 'set', from_='chat.facebook.com')( elem(NS_FACEBOOK_MESSAGES, 'own-message', to=to, self='false')( elem('body')(text) ) ) stream.send(iq) q.expect('stream-iq', iq_type='result', iq_id=iq['id']) # First, test receiving an own-message stanza for a message sent to a # contact we have an open channel for. jid = '-5678@chat.facebook.com' _, path, props = conn.Requests.EnsureChannel({ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: jid, }) channel = wrap_channel(bus.get_object(conn.bus_name, path), 'Text', ['Messages']) handle = props[cs.TARGET_HANDLE] text = u'omg omg its ur birthdayy <3 <3 xoxoxoxo' send_own_message(to=jid, text=text) e = q.expect('dbus-signal', signal='MessageReceived') message, = e.args assertLength(1, message) header = message[0] assertEquals(handle, header['message-sender']) assertEquals(cs.MT_DELIVERY_REPORT, header['message-type']) assertEquals(cs.DELIVERY_STATUS_ACCEPTED, header['delivery-status']) assertContains('delivery-echo', header) echo = header['delivery-echo'] echo_header, echo_body = echo assertEquals(conn.GetSelfHandle(), echo_header['message-sender']) assertEquals('text/plain', echo_body['content-type']) assertEquals(text, echo_body['content']) channel.Text.AcknowledgePendingMessages([header['pending-message-id']]) channel.Close() # Now test receiving an own-message stanza for a message sent to a contact # we don't have a channel open for. It should be ignored (but acked). This # is consistent with delivery failure reports. q.forbid_events([EventPattern('dbus-signal', signal='MessageReceived')]) send_own_message(to='-393939@chat.facebook.com', text=u'please ignore this message') sync_dbus(bus, q, conn) if __name__ == '__main__': exec_test(test, params={'account': 'test@chat.facebook.com'}) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/text/initiate-requestotron.py���������������������������������0000664�0001750�0001750�00000005343�12332441362�026744� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test text channel initiated by me, using Requests. """ import dbus from gabbletest import exec_test from servicetest import (call_async, EventPattern, assertContains, assertEquals) import constants as cs def test(q, bus, conn, stream): self_handle = conn.GetSelfHandle() jid = 'foo@bar.com' foo_handle = conn.RequestHandles(cs.HT_CONTACT, [jid])[0] properties = conn.GetAll( cs.CONN_IFACE_REQUESTS, dbus_interface=dbus.PROPERTIES_IFACE) assert properties.get('Channels') == [], properties['Channels'] assert ({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, }, [cs.TARGET_HANDLE, cs.TARGET_ID], ) in properties.get('RequestableChannelClasses'),\ properties['RequestableChannelClasses'] call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: foo_handle, }) ret, old_sig, new_sig = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('dbus-signal', signal='NewChannel'), EventPattern('dbus-signal', signal='NewChannels'), ) assert len(ret.value) == 2 emitted_props = ret.value[1] assert emitted_props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT assert emitted_props[cs.TARGET_HANDLE_TYPE] == cs.HT_CONTACT assert emitted_props[cs.TARGET_HANDLE] == foo_handle assert emitted_props[cs.TARGET_ID] == jid assert emitted_props[cs.REQUESTED] == True assert emitted_props[cs.INITIATOR_HANDLE] == self_handle assert emitted_props[cs.INITIATOR_ID] == 'test@localhost' assertContains('text/plain', emitted_props[cs.SUPPORTED_CONTENT_TYPES]) assertEquals(0, emitted_props[cs.MESSAGE_PART_SUPPORT_FLAGS]) assertEquals(cs.DELIVERY_REPORTING_SUPPORT_FLAGS_RECEIVE_FAILURES, emitted_props[cs.DELIVERY_REPORTING_SUPPORT]) assert old_sig.args[0] == ret.value[0] assert old_sig.args[1] == cs.CHANNEL_TYPE_TEXT assert old_sig.args[2] == cs.HT_CONTACT assert old_sig.args[3] == foo_handle assert old_sig.args[4] == True # suppress handler assert len(new_sig.args) == 1 assert len(new_sig.args[0]) == 1 # one channel assert len(new_sig.args[0][0]) == 2 # two struct members assert new_sig.args[0][0][0] == ret.value[0] assert new_sig.args[0][0][1] == ret.value[1] properties = conn.GetAll( cs.CONN_IFACE_REQUESTS, dbus_interface=dbus.PROPERTIES_IFACE) assert new_sig.args[0][0] in properties['Channels'], \ (new_sig.args[0][0], properties['Channels']) if __name__ == '__main__': exec_test(test) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/text/destroy.py�����������������������������������������������0000664�0001750�0001750�00000007777�12332441362�024074� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test text channel not being recreated because although there were still pending messages, we destroyed it with extreme prejudice. """ import dbus from twisted.words.xish import domish from gabbletest import exec_test from servicetest import call_async, EventPattern import constants as cs def test(q, bus, conn, stream): self_handle = conn.GetSelfHandle() jid = 'foo@bar.com' call_async(q, conn, 'RequestHandles', 1, [jid]) event = q.expect('dbus-return', method='RequestHandles') foo_handle = event.value[0][0] call_async(q, conn, 'RequestChannel', cs.CHANNEL_TYPE_TEXT, cs.HT_CONTACT, foo_handle, True) ret, old_sig, new_sig = q.expect_many( EventPattern('dbus-return', method='RequestChannel'), EventPattern('dbus-signal', signal='NewChannel'), EventPattern('dbus-signal', signal='NewChannels'), ) text_chan = bus.get_object(conn.bus_name, ret.value[0]) chan_iface = dbus.Interface(text_chan, cs.CHANNEL) text_iface = dbus.Interface(text_chan, cs.CHANNEL_TYPE_TEXT) destroyable_iface = dbus.Interface(text_chan, cs.CHANNEL_IFACE_DESTROYABLE) assert old_sig.args[0] == ret.value[0] assert old_sig.args[1] == cs.CHANNEL_TYPE_TEXT assert old_sig.args[2] == cs.HT_CONTACT assert old_sig.args[3] == foo_handle assert old_sig.args[4] == True # suppress handler assert len(new_sig.args) == 1 assert len(new_sig.args[0]) == 1 # one channel assert len(new_sig.args[0][0]) == 2 # two struct members assert new_sig.args[0][0][0] == ret.value[0] emitted_props = new_sig.args[0][0][1] assert emitted_props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT assert emitted_props[cs.TARGET_HANDLE_TYPE] == cs.HT_CONTACT assert emitted_props[cs.TARGET_HANDLE] == foo_handle assert emitted_props[cs.TARGET_ID] == jid assert emitted_props[cs.REQUESTED] == True assert emitted_props[cs.INITIATOR_HANDLE] == self_handle assert emitted_props[cs.INITIATOR_ID] == 'test@localhost' channel_props = text_chan.GetAll( cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE) assert channel_props['TargetID'] == jid, (channel_props['TargetID'], jid) assert channel_props['Requested'] == True assert channel_props['InitiatorHandle'] == self_handle,\ (channel_props['InitiatorHandle'], self_handle) assert channel_props['InitiatorID'] == 'test@localhost',\ channel_props['InitiatorID'] text_iface.Send(0, 'hey') event = q.expect('stream-message') elem = event.stanza assert elem.name == 'message' assert elem['type'] == 'chat' body = list(event.stanza.elements())[0] assert body.name == 'body' assert body.children[0] == u'hey' # <message type="chat"><body>hello</body</message> m = domish.Element((None, 'message')) m['from'] = 'foo@bar.com/Pidgin' m['type'] = 'chat' m.addElement('body', content='hello') stream.send(m) event = q.expect('dbus-signal', signal='Received') hello_message_id = event.args[0] hello_message_time = event.args[1] assert event.args[2] == foo_handle # message type: normal assert event.args[3] == 0 # flags: none assert event.args[4] == 0 # body assert event.args[5] == 'hello' messages = text_chan.ListPendingMessages(False, dbus_interface=cs.CHANNEL_TYPE_TEXT) assert messages == \ [(hello_message_id, hello_message_time, foo_handle, 0, 0, 'hello')], messages # destroy the channel without acking the message; it does not come back call_async(q, destroyable_iface, 'Destroy') event = q.expect('dbus-signal', signal='Closed') assert event.path == text_chan.object_path,\ (event.path, text_chan.object_path) event = q.expect('dbus-return', method='Destroy') # assert that it stays dead try: chan_iface.GetChannelType() except dbus.DBusException: pass else: raise AssertionError("Why won't it die?") if __name__ == '__main__': exec_test(test) �telepathy-gabble-0.18.3/tests/twisted/text/initiate.py����������������������������������������������0000664�0001750�0001750�00000005571�12332441362�024177� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test text channel initiated by me. """ import dbus from twisted.words.xish import domish from gabbletest import exec_test from servicetest import call_async, EventPattern import constants as cs def test(q, bus, conn, stream): self_handle = conn.GetSelfHandle() jid = 'foo@bar.com' call_async(q, conn, 'RequestHandles', cs.HT_CONTACT, [jid]) event = q.expect('dbus-return', method='RequestHandles') foo_handle = event.value[0][0] call_async(q, conn, 'RequestChannel', cs.CHANNEL_TYPE_TEXT, cs.HT_CONTACT, foo_handle, True) ret, sig = q.expect_many( EventPattern('dbus-return', method='RequestChannel'), EventPattern('dbus-signal', signal='NewChannel'), ) text_chan = bus.get_object(conn.bus_name, ret.value[0]) assert sig.args[0] == ret.value[0], \ (sig.args[0], ret.value[0]) assert sig.args[1] == cs.CHANNEL_TYPE_TEXT, sig.args[1] # check that handle type == contact handle assert sig.args[2] == 1, sig.args[1] assert sig.args[3] == foo_handle, (sig.args[3], foo_handle) assert sig.args[4] == True # suppress handler # Exercise basic Channel Properties from spec 0.17.7 channel_props = text_chan.GetAll( cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE) assert channel_props.get('TargetHandle') == foo_handle,\ (channel_props.get('TargetHandle'), foo_handle) assert channel_props.get('TargetHandleType') == 1,\ channel_props.get('TargetHandleType') assert channel_props.get('ChannelType') == \ cs.CHANNEL_TYPE_TEXT,\ channel_props.get('ChannelType') assert cs.CHANNEL_IFACE_CHAT_STATE in \ channel_props.get('Interfaces', ()), \ channel_props.get('Interfaces') assert channel_props['TargetID'] == jid,\ (channel_props['TargetID'], jid) assert channel_props['Requested'] == True assert channel_props['InitiatorHandle'] == self_handle,\ (channel_props['InitiatorHandle'], self_handle) assert channel_props['InitiatorID'] == 'test@localhost',\ channel_props['InitiatorID'] dbus.Interface(text_chan, cs.CHANNEL_TYPE_TEXT).Send(0, 'hey') event = q.expect('stream-message') elem = event.stanza assert elem.name == 'message' assert elem['type'] == 'chat' body = list(event.stanza.elements())[0] assert body.name == 'body' assert body.children[0] == u'hey' # <message type="chat"><body>hello</body</message> m = domish.Element((None, 'message')) m['from'] = 'foo@bar.com/Pidgin' m['type'] = 'chat' m.addElement('body', content='hello') stream.send(m) event = q.expect('dbus-signal', signal='Received') # message type: normal assert event.args[3] == 0 # flags: none assert event.args[4] == 0 # body assert event.args[5] == 'hello' if __name__ == '__main__': exec_test(test) ���������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/file-transfer/������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�023573� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/file-transfer/test-receive-file-decline.py��������������������0000664�0001750�0001750�00000002114�12225363340�031051� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from servicetest import EventPattern from twisted.words.xish import xpath import constants as cs from file_transfer_helper import ReceiveFileTest, exec_file_transfer_test from config import FILE_TRANSFER_ENABLED if not FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer" raise SystemExit(77) class ReceiveFileDeclineTest(ReceiveFileTest): def accept_file(self): # decline FT self.channel.Close() state_event, iq_event, _ = self.q.expect_many( EventPattern('dbus-signal', signal='FileTransferStateChanged'), EventPattern('stream-iq', iq_type='error'), EventPattern('dbus-signal', signal='Closed'), ) error_node = xpath.queryForNodes('/iq/error', iq_event.stanza)[0] assert error_node['code'] == '403' state, reason = state_event.args assert state == cs.FT_STATE_CANCELLED assert reason == cs.FT_STATE_CHANGE_REASON_LOCAL_STOPPED # stop test return True if __name__ == '__main__': exec_file_transfer_test(ReceiveFileDeclineTest) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/file-transfer/test-receive-file-and-disconnect.py�������������0000664�0001750�0001750�00000001072�12225363340�032341� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ from file_transfer_helper import exec_file_transfer_test, ReceiveFileTest from config import FILE_TRANSFER_ENABLED if not FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer" raise SystemExit(77) class ReceiveFileAndDisconnectTest(ReceiveFileTest): def receive_file(self): s = self.create_socket() s.connect(self.address) # return True so the test will be ended and the connection # disconnected return True if __name__ == '__main__': exec_file_transfer_test(ReceiveFileAndDisconnectTest) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/file-transfer/file_transfer_helper.py�������������������������0000664�0001750�0001750�00000055763�12332441362�030340� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import dbus import socket import hashlib import time import datetime import os from servicetest import EventPattern, assertEquals, assertSameSets, call_async from gabbletest import exec_test, sync_stream, make_result_iq import ns from bytestream import create_from_si_offer, announce_socks5_proxy import bytestream from caps_helper import extract_data_forms, add_data_forms from twisted.words.xish import domish, xpath import constants as cs class File(object): DEFAULT_DATA = "What a nice file" DEFAULT_NAME = "The foo.txt" DEFAULT_CONTENT_TYPE = 'text/plain' DEFAULT_DESCRIPTION = "A nice file to test" def __init__(self, data=DEFAULT_DATA, name=DEFAULT_NAME, content_type=DEFAULT_CONTENT_TYPE, description=DEFAULT_DESCRIPTION, hash_type=cs.FILE_HASH_TYPE_MD5): self.data = data self.size = len(self.data) self.name = name self.content_type = content_type self.description = description self.date = int(time.time()) self.compute_hash(hash_type) self.offset = 0 self.uri = 'file:///tmp/%s' % self.name def compute_hash(self, hash_type): assert hash_type == cs.FILE_HASH_TYPE_MD5 self.hash_type = hash_type self.hash = hashlib.md5(self.data).hexdigest() class FileTransferTest(object): CONTACT_NAME = 'test-ft@localhost' CONTACT_FULL_JID = 'test-ft@localhost/Telepathy' service_name = 'a.wacky.service.name' metadata = {'loads': ['of', 'blahblah', 'stuff'], 'mental': ['data', 'sidf']} def __init__(self, bytestream_cls, file, address_type, access_control, access_control_param): self.file = file self.bytestream_cls = bytestream_cls self.address_type = address_type self.access_control = access_control self.access_control_param = access_control_param def check_platform_socket_types(self, sock_types): assertEquals(sock_types.get(cs.SOCKET_ADDRESS_TYPE_IPV4), [cs.SOCKET_ACCESS_CONTROL_LOCALHOST]) assertEquals(sock_types.get(cs.SOCKET_ADDRESS_TYPE_IPV6), [cs.SOCKET_ACCESS_CONTROL_LOCALHOST]) if os.name == 'posix': # true on at least Linux assertEquals(sock_types.get(cs.SOCKET_ADDRESS_TYPE_UNIX), [cs.SOCKET_ACCESS_CONTROL_LOCALHOST]) def connect(self): vcard_event, roster_event, disco_event = self.q.expect_many( EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', query_ns=ns.ROSTER), EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS)) roster = make_result_iq(self.stream, roster_event.stanza) query = roster.firstChildElement() item = query.addElement('item') item['jid'] = self.CONTACT_FULL_JID item['subscription'] = 'both' self.stream.send(roster) announce_socks5_proxy(self.q, self.stream, disco_event.stanza) self.self_handle = self.conn.GetSelfHandle() self.self_handle_name = self.conn.InspectHandles(cs.HT_CONTACT, [self.self_handle])[0] def announce_contact(self, name=CONTACT_NAME, metadata=True): self.contact_name = name self.contact_full_jid = '%s/Telepathy' % name self.handle = self.conn.RequestHandles(cs.HT_CONTACT, [name])[0] presence = domish.Element(('jabber:client', 'presence')) presence['from'] = self.contact_full_jid presence['to'] = 'test@localhost/Resource' c = presence.addElement('c') c['xmlns'] = 'http://jabber.org/protocol/caps' c['node'] = 'http://example.com/ISupportFT' c['ver'] = '1.0' self.stream.send(presence) disco_event, presence_event = self.q.expect_many( EventPattern('stream-iq', iq_type='get', query_ns='http://jabber.org/protocol/disco#info', to=self.contact_full_jid), EventPattern('dbus-signal', signal='PresencesChanged', args=[ {self.handle: (cs.PRESENCE_AVAILABLE, u'available', u'')}])) assert disco_event.query['node'] == \ 'http://example.com/ISupportFT#1.0' result = make_result_iq(self.stream, disco_event.stanza) query = result.firstChildElement() feature = query.addElement('feature') feature['var'] = ns.FILE_TRANSFER if metadata: feature = query.addElement('feature') feature['var'] = ns.TP_FT_METADATA self.stream.send(result) sync_stream(self.q, self.stream) def create_ft_channel(self): ft_chan = self.bus.get_object(self.conn.object.bus_name, self.ft_path) self.channel = dbus.Interface(ft_chan, cs.CHANNEL) self.ft_channel = dbus.Interface(ft_chan, cs.CHANNEL_TYPE_FILE_TRANSFER) self.ft_props = dbus.Interface(ft_chan, cs.PROPERTIES_IFACE) def close_channel(self): self.channel.Close() self.q.expect('dbus-signal', signal='Closed') def done(self): pass def test(self, q, bus, conn, stream): self.q = q self.bus = bus self.conn = conn self.stream = stream for fct in self._actions: # stop if a function returns True if fct(): break def create_socket(self): if self.address_type == cs.SOCKET_ADDRESS_TYPE_UNIX: return socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) elif self.address_type == cs.SOCKET_ADDRESS_TYPE_IPV4: return socket.socket(socket.AF_INET, socket.SOCK_STREAM) elif self.address_type == cs.SOCKET_ADDRESS_TYPE_IPV6: return socket.socket(socket.AF_INET6, socket.SOCK_STREAM) else: assert False class ReceiveFileTest(FileTransferTest): def __init__(self, bytestream_cls, file, address_type, access_control, access_control_param): FileTransferTest.__init__(self, bytestream_cls, file, address_type, access_control, access_control_param) self._actions = [self.connect, self.announce_contact, self.send_ft_offer_iq, self.check_new_channel, self.create_ft_channel, self.set_uri, self.accept_file, self.receive_file, self.close_channel, self.done] def send_ft_offer_iq(self): self.bytestream = self.bytestream_cls(self.stream, self.q, 'alpha', self.contact_full_jid, 'test@localhost/Resource', True) iq, si = self.bytestream.create_si_offer(ns.FILE_TRANSFER) file_node = si.addElement((ns.FILE_TRANSFER,'file')) file_node['name'] = self.file.name file_node['size'] = str(self.file.size) file_node['mime-type'] = self.file.content_type file_node['hash'] = self.file.hash date = datetime.datetime.utcfromtimestamp(self.file.date).strftime('%FT%H:%M:%SZ') file_node['date'] = date file_node.addElement('desc', content=self.file.description) # we support range transfer file_node.addElement('range') # Metadata if self.service_name: service_form = {ns.TP_FT_METADATA_SERVICE: {'ServiceName': [self.service_name]}} add_data_forms(file_node, service_form) if self.metadata: metadata_form = {ns.TP_FT_METADATA: self.metadata} add_data_forms(file_node, metadata_form) # so... lunch? iq.send() def check_new_channel(self): def is_ft_channel_event(event): channels, = event.args if len(channels) > 1: return False path, props = channels[0] return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_FILE_TRANSFER e = self.q.expect('dbus-signal', signal='NewChannels', path=self.conn.object.object_path, predicate=is_ft_channel_event) channels = e.args[0] assert len(channels) == 1 path, props = channels[0] # check channel properties # org.freedesktop.Telepathy.Channel D-Bus properties assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_FILE_TRANSFER assertSameSets( [ cs.CHANNEL_IFACE_FILE_TRANSFER_METADATA, cs.CHANNEL_TYPE_FILE_TRANSFER + '.FUTURE', ], props[cs.INTERFACES]) assert props[cs.TARGET_HANDLE] == self.handle assert props[cs.TARGET_ID] == self.contact_name assert props[cs.TARGET_HANDLE_TYPE] == cs.HT_CONTACT assert props[cs.REQUESTED] == False assert props[cs.INITIATOR_HANDLE] == self.handle assert props[cs.INITIATOR_ID] == self.contact_name # org.freedesktop.Telepathy.Channel.Type.FileTransfer D-Bus properties assert props[cs.FT_STATE] == cs.FT_STATE_PENDING assert props[cs.FT_CONTENT_TYPE] == self.file.content_type assert props[cs.FT_FILENAME] == self.file.name assert props[cs.FT_SIZE] == self.file.size # FT's protocol doesn't allow us the send the hash info assert props[cs.FT_CONTENT_HASH_TYPE] == cs.FILE_HASH_TYPE_MD5 assert props[cs.FT_CONTENT_HASH] == self.file.hash assert props[cs.FT_DESCRIPTION] == self.file.description assert props[cs.FT_DATE] == self.file.date assert props[cs.FT_TRANSFERRED_BYTES] == 0 assert props[cs.FT_INITIAL_OFFSET] == 0 self.check_platform_socket_types(props[cs.FT_AVAILABLE_SOCKET_TYPES]) assertEquals(self.service_name, props[cs.FT_SERVICE_NAME]) assertEquals(self.metadata, props[cs.FT_METADATA]) self.ft_path = path def set_uri(self): ft_props = dbus.Interface(self.ft_channel, cs.PROPERTIES_IFACE) # URI is not set yet uri = ft_props.Get(cs.CHANNEL_TYPE_FILE_TRANSFER, 'URI') assertEquals('', uri) # Setting URI call_async(self.q, ft_props, 'Set', cs.CHANNEL_TYPE_FILE_TRANSFER, 'URI', self.file.uri) self.q.expect('dbus-signal', signal='URIDefined', args=[self.file.uri]) self.q.expect('dbus-return', method='Set') # Check it has the right value now uri = ft_props.Get(cs.CHANNEL_TYPE_FILE_TRANSFER, 'URI') assertEquals(self.file.uri, uri) # We can't change it once it has been set call_async(self.q, ft_props, 'Set', cs.CHANNEL_TYPE_FILE_TRANSFER, 'URI', 'badger://snake') self.q.expect('dbus-error', method='Set', name=cs.INVALID_ARGUMENT) def accept_file(self): try: self.address = self.ft_channel.AcceptFile(self.address_type, self.access_control, self.access_control_param, self.file.offset, byte_arrays=True) except dbus.DBusException, e: if self.address_type == cs.SOCKET_ADDRESS_TYPE_IPV6 and \ e.get_dbus_name() == cs.NOT_AVAILABLE and \ e.get_dbus_message() == "Could not set up local socket": print "Ignoring error for ipv6 address space" return True else: raise e state_event, iq_event = self.q.expect_many( EventPattern('dbus-signal', signal='FileTransferStateChanged'), EventPattern('stream-iq', iq_type='result')) state, reason = state_event.args assert state == cs.FT_STATE_ACCEPTED assert reason == cs.FT_STATE_CHANGE_REASON_REQUESTED # Got SI reply self.bytestream.check_si_reply(iq_event.stanza) if self.file.offset != 0: range = xpath.queryForNodes('/iq/si/file/range', iq_event.stanza)[0] assert range['offset'] == str(self.file.offset) _, events = self.bytestream.open_bytestream([], [ EventPattern('dbus-signal', signal='InitialOffsetDefined'), EventPattern('dbus-signal', signal='FileTransferStateChanged')]) offset_event, state_event = events offset = offset_event.args[0] assert offset == self.file.offset state, reason = state_event.args assert state == cs.FT_STATE_OPEN assert reason == cs.FT_STATE_CHANGE_REASON_NONE # send the beginning of the file (client didn't connect to socket yet) self.bytestream.send_data(self.file.data[self.file.offset:self.file.offset + 2]) def receive_file(self): # Connect to Gabble's socket s = self.create_socket() s.connect(self.address) # send the rest of the file i = self.file.offset + 2 self.bytestream.send_data(self.file.data[i:]) self._read_file_from_socket(s) def _read_file_from_socket(self, s): # Read the file from Gabble's socket data = '' read = 0 to_receive = self.file.size - self.file.offset e = self.q.expect('dbus-signal', signal='TransferredBytesChanged') count = e.args[0] while True: received = s.recv(1024) if len(received) == 0: break data += received assert data == self.file.data[self.file.offset:] while count < to_receive: # Catch TransferredBytesChanged until we transfered all the data e = self.q.expect('dbus-signal', signal='TransferredBytesChanged') count = e.args[0] e = self.q.expect('dbus-signal', signal='FileTransferStateChanged') state, reason = e.args assert state == cs.FT_STATE_COMPLETED assert reason == cs.FT_STATE_CHANGE_REASON_NONE class SendFileTest(FileTransferTest): def __init__(self, bytestream_cls, file, address_type, access_control, acces_control_param): FileTransferTest.__init__(self, bytestream_cls, file, address_type, access_control, acces_control_param) self._actions = [self.connect, self.announce_contact, self.check_ft_available, self.request_ft_channel, self.create_ft_channel, self.got_send_iq, self.provide_file, self.client_accept_file, self.send_file, self.close_channel, self.done] def check_ft_available(self): properties = self.conn.GetAll(cs.CONN_IFACE_REQUESTS, dbus_interface=cs.PROPERTIES_IFACE) # general FT class assert ({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_FILE_TRANSFER, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT}, [cs.FT_CONTENT_HASH_TYPE, cs.TARGET_HANDLE, cs.TARGET_ID, cs.FT_CONTENT_TYPE, cs.FT_FILENAME, cs.FT_SIZE, cs.FT_CONTENT_HASH, cs.FT_DESCRIPTION, cs.FT_DATE, cs.FT_URI, cs.FT_SERVICE_NAME, cs.FT_METADATA] ) in properties.get('RequestableChannelClasses'),\ properties['RequestableChannelClasses'] # FT class with MD5 as HashType assert ({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_FILE_TRANSFER, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.FT_CONTENT_HASH_TYPE: cs.FILE_HASH_TYPE_MD5}, [cs.TARGET_HANDLE, cs.TARGET_ID, cs.FT_CONTENT_TYPE, cs.FT_FILENAME, cs.FT_SIZE, cs.FT_CONTENT_HASH, cs.FT_DESCRIPTION, cs.FT_DATE, cs.FT_URI, cs.FT_SERVICE_NAME, cs.FT_METADATA] ) in properties.get('RequestableChannelClasses'),\ properties['RequestableChannelClasses'] def request_ft_channel(self, uri=True): request = { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_FILE_TRANSFER, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: self.handle, cs.FT_CONTENT_TYPE: self.file.content_type, cs.FT_FILENAME: self.file.name, cs.FT_SIZE: self.file.size, cs.FT_CONTENT_HASH_TYPE: self.file.hash_type, cs.FT_CONTENT_HASH: self.file.hash, cs.FT_DESCRIPTION: self.file.description, cs.FT_DATE: self.file.date, cs.FT_INITIAL_OFFSET: 0, cs.FT_SERVICE_NAME: self.service_name, cs.FT_METADATA: dbus.Dictionary(self.metadata, signature='sas')} if uri: request[cs.FT_URI] = self.file.uri self.ft_path, props = self.conn.Requests.CreateChannel(request) # org.freedesktop.Telepathy.Channel D-Bus properties assertEquals(cs.CHANNEL_TYPE_FILE_TRANSFER, props[cs.CHANNEL_TYPE]) assertSameSets( [ cs.CHANNEL_IFACE_FILE_TRANSFER_METADATA, cs.CHANNEL_TYPE_FILE_TRANSFER + '.FUTURE', ], props[cs.INTERFACES]) assertEquals(self.handle, props[cs.TARGET_HANDLE]) assertEquals(self.contact_name, props[cs.TARGET_ID]) assertEquals(cs.HT_CONTACT, props[cs.TARGET_HANDLE_TYPE]) assert props[cs.REQUESTED] assertEquals(self.self_handle, props[cs.INITIATOR_HANDLE]) assertEquals(self.self_handle_name, props[cs.INITIATOR_ID]) # org.freedesktop.Telepathy.Channel.Type.FileTransfer D-Bus properties assertEquals(cs.FT_STATE_PENDING, props[cs.FT_STATE]) assertEquals(self.file.content_type, props[cs.FT_CONTENT_TYPE]) assertEquals(self.file.name, props[cs.FT_FILENAME]) assertEquals(self.file.size, props[cs.FT_SIZE]) assertEquals(self.file.hash_type, props[cs.FT_CONTENT_HASH_TYPE]) assertEquals(self.file.hash, props[cs.FT_CONTENT_HASH]) assertEquals(self.file.description, props[cs.FT_DESCRIPTION]) assertEquals(self.file.date, props[cs.FT_DATE]) assertEquals(0, props[cs.FT_TRANSFERRED_BYTES]) assertEquals(0, props[cs.FT_INITIAL_OFFSET]) assertEquals(self.service_name, props[cs.FT_SERVICE_NAME]) assertEquals(self.metadata, props[cs.FT_METADATA]) if uri: assertEquals(self.file.uri, props[cs.FT_URI]) else: assertEquals('', props[cs.FT_URI]) self.check_platform_socket_types(props[cs.FT_AVAILABLE_SOCKET_TYPES]) def got_send_iq(self): iq_event = self.q.expect('stream-iq', to=self.contact_full_jid) self._check_file_transfer_offer_iq(iq_event) def _check_file_transfer_offer_iq(self, iq_event): self.iq = iq_event.stanza self.bytestream, profile = create_from_si_offer(self.stream, self.q, self.bytestream_cls, iq_event.stanza, 'test@localhost/Resource') assert self.iq['to'] == self.contact_full_jid assert profile == ns.FILE_TRANSFER file_node = xpath.queryForNodes('/iq/si/file', self.iq)[0] assert file_node['name'] == self.file.name assert file_node['size'] == str(self.file.size) assert file_node['mime-type'] == self.file.content_type assert file_node['hash'] == self.file.hash date = datetime.datetime.utcfromtimestamp(self.file.date).strftime('%FT%H:%M:%SZ') assert file_node['date'] == date, file_node['date'] desc_node = xpath.queryForNodes("/iq/si/file/desc", self.iq)[0] self.desc = desc_node.children[0] assert self.desc == self.file.description # Gabble supports resume range = xpath.queryForNodes('/iq/si/file/range', self.iq)[0] assert range is not None # Metadata forms forms = extract_data_forms(xpath.queryForNodes('/iq/si/file/x', self.iq)) if self.service_name: assertEquals({'ServiceName': [self.service_name]}, forms[ns.TP_FT_METADATA_SERVICE]) else: assert ns.TP_FT_METADATA_SERVICE not in forms if self.metadata: assertEquals(self.metadata, forms[ns.TP_FT_METADATA]) else: assert ns.TP_FT_METADATA not in forms def provide_file(self): try: self.address = self.ft_channel.ProvideFile(self.address_type, self.access_control, self.access_control_param, byte_arrays=True) except dbus.DBusException, e: if self.address_type == cs.SOCKET_ADDRESS_TYPE_IPV6 and \ e.get_dbus_name() == cs.NOT_AVAILABLE and \ e.get_dbus_message() == "Could not set up local socket": print "Ignoring error for ipv6 address space" return True else: raise e def client_accept_file(self): # accept SI offer result, si = self.bytestream.create_si_reply(self.iq) file_node = si.addElement((ns.FILE_TRANSFER, 'file')) range = file_node.addElement('range') range['offset'] = str(self.file.offset) self.stream.send(result) self.bytestream.wait_bytestream_open() def send_file(self): s = self.create_socket() s.connect(self.address) s.send(self.file.data[self.file.offset:]) to_receive = self.file.size - self.file.offset self.count = 0 def bytes_changed_cb(bytes): self.count = bytes self.ft_channel.connect_to_signal('TransferredBytesChanged', bytes_changed_cb) # FileTransferStateChanged can be fired while we are receiving data # (in the SOCKS5 case for example) self.completed = False def ft_state_changed_cb(state, reason): if state == cs.FT_STATE_COMPLETED: self.completed = True self.ft_channel.connect_to_signal('FileTransferStateChanged', ft_state_changed_cb) # get data from bytestream data = '' while len(data) < to_receive: data += self.bytestream.get_data() assert data == self.file.data[self.file.offset:] if self.completed: # FileTransferStateChanged has already been received waiting = [] else: waiting = [EventPattern('dbus-signal', signal='FileTransferStateChanged')] events = self.bytestream.wait_bytestream_closed(waiting) # If not all the bytes transferred have been announced using # TransferredBytesChanged, wait for them while self.count < to_receive: self.q.expect('dbus-signal', signal='TransferredBytesChanged') assert self.count == to_receive if len(waiting) > 1: state, reason = events[0].args assert state == cs.FT_STATE_COMPLETED assert reason == cs.FT_STATE_CHANGE_REASON_NONE def platform_impls(): impls = [ (cs.SOCKET_ADDRESS_TYPE_IPV4, cs.SOCKET_ACCESS_CONTROL_LOCALHOST, ""), (cs.SOCKET_ADDRESS_TYPE_IPV6, cs.SOCKET_ACCESS_CONTROL_LOCALHOST, ""), ] if os.name == 'posix': impls.append((cs.SOCKET_ADDRESS_TYPE_UNIX, cs.SOCKET_ACCESS_CONTROL_LOCALHOST, "")) return impls def exec_file_transfer_test(test_cls, one_run=False): for bytestream_cls in [ bytestream.BytestreamIBBMsg, bytestream.BytestreamS5B, bytestream.BytestreamS5BPidgin, bytestream.BytestreamSIFallbackS5CannotConnect, bytestream.BytestreamSIFallbackS5WrongHash, bytestream.BytestreamS5BRelay, bytestream.BytestreamS5BRelayBugged]: for addr_type, access_control, access_control_param in platform_impls(): file = File() test = test_cls(bytestream_cls, file, addr_type, access_control, access_control_param) exec_test(test.test) # test resume file.offset = 5 test = test_cls(bytestream_cls, file, addr_type, access_control, access_control_param) exec_test(test.test) if one_run: return �������������telepathy-gabble-0.18.3/tests/twisted/file-transfer/test-uri.py�������������������������������������0000664�0001750�0001750�00000005463�12225363340�025722� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# The 'normal' cases are tested with test-receive-file.py and test-send-file-provide-immediately.py # This file tests some corner cases import dbus from file_transfer_helper import exec_file_transfer_test, ReceiveFileTest, SendFileTest from servicetest import assertEquals, call_async import constants as cs from config import FILE_TRANSFER_ENABLED if not FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer" raise SystemExit(77) def assertNoURI(ft_channel): ft_props = dbus.Interface(ft_channel, cs.PROPERTIES_IFACE) uri = ft_props.Get(cs.CHANNEL_TYPE_FILE_TRANSFER, 'URI') assertEquals('', uri) class SetURIAfterAccepting(ReceiveFileTest): def __init__(self, bytestream_cls, file, address_type, access_control, access_control_param): ReceiveFileTest.__init__(self, bytestream_cls, file, address_type, access_control, access_control_param) self._actions = [self.connect, self.announce_contact, self.send_ft_offer_iq, self.check_new_channel, self.create_ft_channel, self.accept_file, self.set_uri, self.done] def set_uri(self): ft_props = dbus.Interface(self.ft_channel, cs.PROPERTIES_IFACE) # URI is not set yet assertNoURI(self.ft_channel) # Setting URI call_async(self.q, ft_props, 'Set', cs.CHANNEL_TYPE_FILE_TRANSFER, 'URI', self.file.uri) # too late... self.q.expect('dbus-error', method='Set', name=cs.INVALID_ARGUMENT) class ReceiveFileTestNoURI(ReceiveFileTest): def __init__(self, bytestream_cls, file, address_type, access_control, access_control_param): ReceiveFileTest.__init__(self, bytestream_cls, file, address_type, access_control, access_control_param) self._actions = [self.connect, self.announce_contact, self.send_ft_offer_iq, self.check_new_channel, self.create_ft_channel, self.accept_file, self.receive_file, self.close_channel, self.done] def accept_file(self): # URI is not set assertNoURI(self.ft_channel) ReceiveFileTest.accept_file(self) def close_channel(self): # Still no URI assertNoURI(self.ft_channel) ReceiveFileTest.close_channel(self) class SendFileNoURI(SendFileTest): def request_ft_channel(self): SendFileTest.request_ft_channel(self, False) def close_channel(self): # Still no URI assertNoURI(self.ft_channel) SendFileTest.close_channel(self) if __name__ == '__main__': # We don't define an URI before accepting the file and try to set it after exec_file_transfer_test(SetURIAfterAccepting, True) # Don't define any URI when receiving a file exec_file_transfer_test(ReceiveFileTestNoURI, True) # Don't define any URI when sending a file exec_file_transfer_test(SendFileNoURI, True) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/file-transfer/test-send-file-to-unknown-contact.py������������0000664�0001750�0001750�00000002043�12332441362�032526� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import dbus import constants as cs from file_transfer_helper import SendFileTest, exec_file_transfer_test from config import FILE_TRANSFER_ENABLED if not FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer" raise SystemExit(77) class SendFileTransferToUnknownContactTest(SendFileTest): def __init__(self, bytestream_cls, file, address_type, access_control, acces_control_param): SendFileTest.__init__(self, bytestream_cls, file, address_type, access_control, acces_control_param) self._actions = [self.connect, self.check_ft_available, self.my_request_ft_channel] def my_request_ft_channel(self): self.contact_name = 'jean@localhost' self.handle = self.conn.RequestHandles(cs.HT_CONTACT, [self.contact_name])[0] try: self.request_ft_channel() except dbus.DBusException, e: assert e.get_dbus_name() == cs.OFFLINE else: assert False if __name__ == '__main__': exec_file_transfer_test(SendFileTransferToUnknownContactTest) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/file-transfer/test-send-file-provide-immediately.py�����������0000664�0001750�0001750�00000003022�12225363340�032725� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import dbus import constants as cs from file_transfer_helper import SendFileTest, exec_file_transfer_test from config import FILE_TRANSFER_ENABLED if not FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer" raise SystemExit(77) class SendFileTransferProvideImmediately(SendFileTest): def provide_file(self): # try to accept our outgoing file transfer try: self.ft_channel.AcceptFile(self.address_type, self.access_control, self.access_control_param, self.file.offset, byte_arrays=True) except dbus.DBusException, e: assert e.get_dbus_name() == cs.NOT_AVAILABLE else: assert False if SendFileTest.provide_file(self): return True # state is still Pending as remote didn't accept the transfer yet state = self.ft_props.Get(cs.CHANNEL_TYPE_FILE_TRANSFER, 'State') assert state == cs.FT_STATE_PENDING def client_accept_file(self): SendFileTest.client_accept_file(self) e = self.q.expect('dbus-signal', signal='InitialOffsetDefined') offset = e.args[0] assert offset == self.file.offset # Channel is open. We can start to send the file e = self.q.expect('dbus-signal', signal='FileTransferStateChanged') state, reason = e.args assert state == cs.FT_STATE_OPEN assert reason == cs.FT_STATE_CHANGE_REASON_NONE if __name__ == '__main__': exec_file_transfer_test(SendFileTransferProvideImmediately) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������test-receive-file-and-close-socket-while-receiving.py�����������������������������������������������0000664�0001750�0001750�00000001702�12225363340�035603� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000�telepathy-gabble-0.18.3/tests/twisted/file-transfer�������������������������������������������������������������������������������������������������������������������� import constants as cs from file_transfer_helper import exec_file_transfer_test, ReceiveFileTest from config import FILE_TRANSFER_ENABLED if not FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer" raise SystemExit(77) class ReceiveFileAndCancelWhileReceiving(ReceiveFileTest): def receive_file(self): # Connect to Gabble's socket s = self.create_socket() s.connect(self.address) # for some reason the socket is closed s.close() # we receive one more byte from the sender self.bytestream.send_data(self.file.data[2:3]) self.q.expect('dbus-signal', signal='FileTransferStateChanged', args=[cs.FT_STATE_CANCELLED, cs.FT_STATE_CHANGE_REASON_LOCAL_ERROR]) self.channel.Close() self.q.expect('dbus-signal', signal='Closed') return True if __name__ == '__main__': exec_file_transfer_test(ReceiveFileAndCancelWhileReceiving) ��������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/file-transfer/test-caps-file-transfer.py����������������������0000664�0001750�0001750�00000010775�12332441362�030612� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import dbus from twisted.words.xish import xpath from servicetest import assertEquals from gabbletest import exec_test, make_result_iq, sync_stream, make_presence import constants as cs from caps_helper import compute_caps_hash, text_fixed_properties,\ text_allowed_properties, stream_tube_fixed_properties,\ stream_tube_allowed_properties, dbus_tube_fixed_properties,\ dbus_tube_allowed_properties, ft_fixed_properties, ft_allowed_properties import ns from config import FILE_TRANSFER_ENABLED if not FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer" raise SystemExit(77) def test_ft_caps_from_contact(q, bus, conn, stream, contact, contact_handle, client): conn_caps_iface = dbus.Interface(conn, cs.CONN_IFACE_CONTACT_CAPS) conn_contacts_iface = dbus.Interface(conn, cs.CONN_IFACE_CONTACTS) # send presence with no FT cap presence = make_presence(contact, status='hello') c = presence.addElement((ns.CAPS, 'c')) c['node'] = client c['ver'] = compute_caps_hash([], [], {}) c['hash'] = 'sha-1' stream.send(presence) # Gabble looks up our capabilities event = q.expect('stream-iq', to=contact, query_ns=ns.DISCO_INFO) query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assert query_node.attributes['node'] == \ client + '#' + c['ver'] # send good reply result = make_result_iq(stream, event.stanza) query = result.firstChildElement() query['node'] = client + '#' + c['ver'] stream.send(result) # no change in ContactCapabilities, so no signal ContactCapabilitiesChanged sync_stream(q, stream) # no special capabilities basic_caps = dbus.Dictionary({contact_handle: [(text_fixed_properties, text_allowed_properties)]}) caps = conn_caps_iface.GetContactCapabilities([contact_handle]) assert caps == basic_caps, caps # test again, to check GetContactCapabilities does not have side effect caps = conn_caps_iface.GetContactCapabilities([contact_handle]) assert caps == basic_caps, caps # check the Contacts interface give the same caps caps_via_contacts_iface = conn_contacts_iface.GetContactAttributes( [contact_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [contact_handle][cs.ATTR_CONTACT_CAPABILITIES] assert caps_via_contacts_iface == caps[contact_handle], \ caps_via_contacts_iface # send presence with ft capa presence = make_presence(contact, status='hello') c = presence.addElement((ns.CAPS, 'c')) c['node'] = client c['ver'] = compute_caps_hash([], [ns.FILE_TRANSFER], {}) c['hash'] = 'sha-1' stream.send(presence) # Gabble looks up our capabilities event = q.expect('stream-iq', to=contact, query_ns=ns.DISCO_INFO) query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assert query_node.attributes['node'] == \ client + '#' + c['ver'] # send good reply result = make_result_iq(stream, event.stanza) query = result.firstChildElement() query['node'] = client + '#' + c['ver'] feature = query.addElement('feature') feature['var'] = ns.FILE_TRANSFER stream.send(result) generic_tubes_caps = dbus.Dictionary({contact_handle: [(text_fixed_properties, text_allowed_properties), (ft_fixed_properties, ft_allowed_properties)]}) event = q.expect('dbus-signal', signal='ContactCapabilitiesChanged') assert len(event.args) == 1 assert event.args[0] == generic_tubes_caps caps = conn_caps_iface.GetContactCapabilities([contact_handle]) assert caps == generic_tubes_caps, caps # test again, to check GetContactCapabilities does not have side effect caps = conn_caps_iface.GetContactCapabilities([contact_handle]) assert caps == generic_tubes_caps, caps # check the Contacts interface give the same caps caps_via_contacts_iface = conn_contacts_iface.GetContactAttributes( [contact_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [contact_handle][cs.ATTR_CONTACT_CAPABILITIES] assert caps_via_contacts_iface == caps[contact_handle], \ caps_via_contacts_iface def test(q, bus, conn, stream): client = 'http://telepathy.freedesktop.org/fake-ft-client' test_ft_caps_from_contact(q, bus, conn, stream, 'bilbo1@foo.com/Foo', 2L, client) # our own capabilities, formerly tested here, are now in # tests/twisted/caps/advertise-contact-capabilities.py if __name__ == '__main__': exec_test(test) ���telepathy-gabble-0.18.3/tests/twisted/file-transfer/test-send-file-send-before-accept.py������������0000664�0001750�0001750�00000004605�12332441362�032412� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import dbus import constants as cs from servicetest import EventPattern from file_transfer_helper import SendFileTest, exec_file_transfer_test from twisted.words.xish import domish import ns from config import FILE_TRANSFER_ENABLED if not FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer" raise SystemExit(77) class SendFileSendBeforeAccept(SendFileTest): def client_accept_file_empty(self): return False client_accept_file_orig = SendFileTest.client_accept_file client_accept_file = client_accept_file_empty def send_file(self): s = self.create_socket() s.connect(self.address) s.send(self.file.data[self.file.offset:]) # Accept the file now that we've sent our data... self.client_accept_file_orig() to_receive = self.file.size - self.file.offset self.count = 0 def bytes_changed_cb(bytes): self.count = bytes self.ft_channel.connect_to_signal('TransferredBytesChanged', bytes_changed_cb) # FileTransferStateChanged can be fired while we are receiving data # (in the SOCKS5 case for example) self.completed = False def ft_state_changed_cb(state, reason): if state == cs.FT_STATE_COMPLETED: self.completed = True self.ft_channel.connect_to_signal('FileTransferStateChanged', ft_state_changed_cb) # get data from bytestream data = '' while len(data) < to_receive: data += self.bytestream.get_data() assert data == self.file.data[self.file.offset:] if self.completed: # FileTransferStateChanged has already been received waiting = [] else: waiting = [EventPattern('dbus-signal', signal='FileTransferStateChanged')] events = self.bytestream.wait_bytestream_closed(waiting) # If not all the bytes transferred have been announced using # TransferredBytesChanged, wait for them while self.count < to_receive: self.q.expect('dbus-signal', signal='TransferredBytesChanged') assert self.count == to_receive if len(waiting) > 1: state, reason = events[0].args assert state == cs.FT_STATE_COMPLETED assert reason == cs.FT_STATE_CHANGE_REASON_NONE if __name__ == '__main__': exec_file_transfer_test(SendFileSendBeforeAccept) ���������������������������������������������������������������������������������������������������������������������������test-receive-file-and-sender-disconnect-while-pending.py��������������������������������������������0000664�0001750�0001750�00000002662�12225363340�036276� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000�telepathy-gabble-0.18.3/tests/twisted/file-transfer��������������������������������������������������������������������������������������������������������������������import dbus from twisted.words.xish import domish import constants as cs from file_transfer_helper import exec_file_transfer_test, ReceiveFileTest from config import FILE_TRANSFER_ENABLED if not FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer" raise SystemExit(77) class ReceiveFileAndSenderDisconnectWhilePendingTest(ReceiveFileTest): def accept_file(self): # The sender of the file disconnects presence = domish.Element(('jabber:client', 'presence')) presence['from'] = self.contact_full_jid presence['to'] = 'test@localhost/Resource' presence['type'] = 'unavailable' self.stream.send(presence) e = self.q.expect('dbus-signal', signal='FileTransferStateChanged') state, reason = e.args assert state == cs.FT_STATE_CANCELLED assert reason == cs.FT_STATE_CHANGE_REASON_REMOTE_STOPPED # We can't accept the transfer now try: # IPv4 is always guaranteed to be available self.ft_channel.AcceptFile(cs.SOCKET_ADDRESS_TYPE_IPV4, cs.SOCKET_ACCESS_CONTROL_LOCALHOST, "", 0) except dbus.DBusException, e: assert e.get_dbus_name() == cs.NOT_AVAILABLE else: assert False self.close_channel() # stop the test return True if __name__ == '__main__': exec_file_transfer_test(ReceiveFileAndSenderDisconnectWhilePendingTest) ������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/file-transfer/ft-client-caps.py�������������������������������0000664�0001750�0001750�00000031331�12332441362�026750� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test FT capabilities with Connection.Interface.ContactCapabilities 1. Receive presence and caps from contacts and check that GetContactCapabilities works correctly and that ContactCapabilitiesChanged is correctly received. Also check that GetContactAttributes gives the same results. - no FT cap at all - FT caps without metadata extension - FT caps with metadata extension - 1 FT cap with a service name - 2 FT caps with service names - 1 FT cap again, to test whether the caps cache works with FT services 2. Test UpdateCapabilities and test that a presence stanza is sent to the contacts, test that the D-Bus signal ContactCapabilitiesChanged is fired for the self handle, ask Gabble for its caps with an iq request, check the reply is correct, and ask Gabble for its caps using D-Bus method GetContactCapabilities. Also check that GetContactAttributes gives the same results. Ensure that just a Requested=True channel class in a client filter doesn't make a FT service advertised as a cap. - no FT cap at all - 1 FT cap with no service name - 1 Requested=True FT cap with service name - 1 FT cap with service name - 1 FT cap with service name + 1 FT cap with no service name - 2 FT caps with service names - 1 FT cap with service name again, just for fun """ import dbus from twisted.words.xish import xpath from servicetest import assertEquals, assertLength, assertContains,\ assertDoesNotContain, sync_dbus from gabbletest import exec_test, make_result_iq, sync_stream, make_presence import constants as cs from caps_helper import compute_caps_hash, text_fixed_properties,\ text_allowed_properties, stream_tube_fixed_properties, stream_tube_allowed_properties,\ dbus_tube_fixed_properties, dbus_tube_allowed_properties, receive_presence_and_ask_caps,\ caps_contain, ft_fixed_properties, ft_allowed_properties, ft_allowed_properties_with_metadata, \ presence_and_disco import ns from config import FILE_TRANSFER_ENABLED if not FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer" raise SystemExit(77) def dict_union(a, b): return dbus.Dictionary(a.items() + b.items(), signature='sv') no_service_fixed_properties = { cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_FILE_TRANSFER, } bidir_daap_fixed_properties = dict_union(no_service_fixed_properties, { cs.FT_SERVICE_NAME: 'daap' }) outgoing_daap_fixed_properties = dict_union(bidir_daap_fixed_properties, { cs.REQUESTED : True, }) incoming_daap_fixed_properties = dict_union(bidir_daap_fixed_properties, { cs.REQUESTED : False, }) http_fixed_properties = dict_union(no_service_fixed_properties, { cs.FT_SERVICE_NAME: 'http', }) xiangqi_fixed_properties = dict_union(no_service_fixed_properties, { cs.FT_SERVICE_NAME: 'com.example.Xiangqi', }) go_fixed_properties = dict_union(no_service_fixed_properties, { cs.FT_SERVICE_NAME: 'com.example.Go', }) client = 'http://telepathy.freedesktop.org/another-fake-client' def assertSameElements(a, b): assertEquals(sorted(a), sorted(b)) def receive_caps(q, conn, stream, contact, contact_handle, features, expected_caps, expect_disco=True, expect_ccc=True): caps = {'node': client, 'ver': compute_caps_hash([], features, {}), 'hash': 'sha-1'} presence_and_disco(q, conn, stream, contact, expect_disco, client, caps, features, initial=False) if expect_ccc: event = q.expect('dbus-signal', signal='ContactCapabilitiesChanged') announced_ccs, = event.args assertSameElements(expected_caps, announced_ccs[contact_handle]) else: # Make sure Gabble's got the caps sync_stream(q, stream) caps = conn.ContactCapabilities.GetContactCapabilities([contact_handle]) assertSameElements(expected_caps, caps[contact_handle]) # test again, to check GetContactCapabilities does not have side effect caps = conn.ContactCapabilities.GetContactCapabilities([contact_handle]) assertSameElements(expected_caps, caps[contact_handle]) # check the Contacts interface give the same caps caps_via_contacts_iface = conn.Contacts.GetContactAttributes( [contact_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [contact_handle][cs.ATTR_CONTACT_CAPABILITIES] assertSameElements(caps[contact_handle], caps_via_contacts_iface) def test_ft_caps_from_contact(q, bus, conn, stream, contact): contact_handle = conn.RequestHandles(cs.HT_CONTACT, [contact])[0] # Check that we don't crash if we haven't seen any caps/presence for this # contact yet. caps = conn.ContactCapabilities.GetContactCapabilities([contact_handle]) basic_caps = [(text_fixed_properties, text_allowed_properties)] # Since we don't know their caps, they should be omitted from the dict, # rather than present with no caps, but all contacts have text chat caps. assertEquals(basic_caps, caps[contact_handle]) # send presence with no FT cap # We don't expect ContactCapabilitiesChanged to be emitted here: we always # assume people can do text channels. receive_caps(q, conn, stream, contact, contact_handle, [], basic_caps, expect_ccc=False) # send presence with no mention of metadata no_metadata_ft_caps = [ (text_fixed_properties, text_allowed_properties), (ft_fixed_properties, ft_allowed_properties) ] receive_caps(q, conn, stream, contact, contact_handle, [ns.FILE_TRANSFER], no_metadata_ft_caps) # send presence with generic FT caps including metadata from now on generic_ft_caps = [ (text_fixed_properties, text_allowed_properties), (ft_fixed_properties, ft_allowed_properties_with_metadata) ] generic_ft_features = [ns.FILE_TRANSFER, ns.TP_FT_METADATA] receive_caps(q, conn, stream, contact, contact_handle, generic_ft_features, generic_ft_caps) # send presence with 1 FT cap with a service daap_caps = generic_ft_caps + [ (bidir_daap_fixed_properties, ft_allowed_properties + [cs.FT_METADATA])] receive_caps(q, conn, stream, contact, contact_handle, generic_ft_features + [ns.TP_FT_METADATA + '#daap'], daap_caps) # send presence with 2 FT caps daap_xiangqi_caps = daap_caps + [ (xiangqi_fixed_properties, ft_allowed_properties + [cs.FT_METADATA])] receive_caps(q, conn, stream, contact, contact_handle, generic_ft_features + [ns.TP_FT_METADATA + '#com.example.Xiangqi', ns.TP_FT_METADATA + '#daap', ], daap_xiangqi_caps) # send presence with 1 FT cap again # Gabble does not look up our capabilities because of the cache receive_caps(q, conn, stream, contact, contact_handle, generic_ft_features + [ns.TP_FT_METADATA + '#daap'], daap_caps, expect_disco=False) def advertise_caps(q, bus, conn, stream, filters, expected_features, unexpected_features, expected_caps): # make sure nothing from a previous update is still running sync_dbus(bus, q, conn) self_handle = conn.GetSelfHandle() ret_caps = conn.ContactCapabilities.UpdateCapabilities( [(cs.CLIENT + '.Foo', filters, [])]) # Expect Gabble to reply with the correct caps event, namespaces, _, signaled_caps = receive_presence_and_ask_caps(q, stream) assertSameElements(expected_caps, signaled_caps[self_handle]) assertContains(ns.TP_FT_METADATA, namespaces) for var in expected_features: assertContains(var, namespaces) for var in unexpected_features: assertDoesNotContain(var, namespaces) # Check our own caps caps = conn.ContactCapabilities.GetContactCapabilities([self_handle]) assertSameElements(expected_caps, caps[self_handle]) # check the Contacts interface give the same caps caps_via_contacts_iface = conn.Contacts.GetContactAttributes( [self_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [self_handle][cs.ATTR_CONTACT_CAPABILITIES] assertSameElements(caps[self_handle], caps_via_contacts_iface) def test_ft_caps_to_contact(q, bus, conn, stream): self_handle = conn.GetSelfHandle() basic_caps = [ (text_fixed_properties, text_allowed_properties), (stream_tube_fixed_properties, stream_tube_allowed_properties), (dbus_tube_fixed_properties, dbus_tube_allowed_properties), ] simple_ft_caps = basic_caps + [ (ft_fixed_properties, ft_allowed_properties_with_metadata), ] daap_caps = simple_ft_caps + [ (bidir_daap_fixed_properties, ft_allowed_properties + [cs.FT_METADATA]), ] xiangqi_caps = simple_ft_caps + [ (xiangqi_fixed_properties, ft_allowed_properties + [cs.FT_METADATA]), ] xiangqi_go_caps = xiangqi_caps + [ (go_fixed_properties, ft_allowed_properties + [cs.FT_METADATA]), ] go_caps = simple_ft_caps + [ (go_fixed_properties, ft_allowed_properties + [cs.FT_METADATA]), ] # # Check our own caps; we should have no FT caps # caps = conn.ContactCapabilities.GetContactCapabilities([self_handle]) assertEquals(basic_caps, caps[self_handle]) # check the Contacts interface give the same caps caps_via_contacts_iface = conn.Contacts.GetContactAttributes( [self_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [self_handle][cs.ATTR_CONTACT_CAPABILITIES] assertEquals(caps[self_handle], caps_via_contacts_iface) # # Advertise nothing # conn.ContactCapabilities.UpdateCapabilities( [(cs.CLIENT + '.Foo', {}, [])]) # Check our own caps caps = conn.ContactCapabilities.GetContactCapabilities([self_handle]) assertLength(1, caps) assertEquals(basic_caps, caps[self_handle]) # check the Contacts interface give the same caps caps_via_contacts_iface = conn.Contacts.GetContactAttributes( [self_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [self_handle][cs.ATTR_CONTACT_CAPABILITIES] assertEquals(caps[self_handle], caps_via_contacts_iface) sync_stream(q, stream) # # Advertise FT but with no service name # conn.ContactCapabilities.UpdateCapabilities( [(cs.CLIENT + '.Foo', [no_service_fixed_properties], [])]) # Check our own caps caps = conn.ContactCapabilities.GetContactCapabilities([self_handle]) assertLength(1, caps) assertEquals(simple_ft_caps, caps[self_handle]) # check the Contacts interface give the same caps caps_via_contacts_iface = conn.Contacts.GetContactAttributes( [self_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [self_handle][cs.ATTR_CONTACT_CAPABILITIES] assertEquals(caps[self_handle], caps_via_contacts_iface) sync_stream(q, stream) # # Advertise a Requested=True FT cap # conn.ContactCapabilities.UpdateCapabilities( [(cs.CLIENT + '.Foo', [outgoing_daap_fixed_properties], [])]) # Check our own caps caps = conn.ContactCapabilities.GetContactCapabilities([self_handle]) assertLength(1, caps) assertEquals(simple_ft_caps, caps[self_handle]) # check the Contacts interface give the same caps caps_via_contacts_iface = conn.Contacts.GetContactAttributes( [self_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [self_handle][cs.ATTR_CONTACT_CAPABILITIES] assertEquals(caps[self_handle], caps_via_contacts_iface) advertise_caps(q, bus, conn, stream, [bidir_daap_fixed_properties], [ns.TP_FT_METADATA + '#daap'], [ns.TP_FT_METADATA + '#http', ns.TP_FT_METADATA + '#com.example.Go', ns.TP_FT_METADATA + '#com.example.Xiangqi', ], daap_caps) advertise_caps(q, bus, conn, stream, [xiangqi_fixed_properties, no_service_fixed_properties], [ns.TP_FT_METADATA + '#com.example.Xiangqi'], [ns.TP_FT_METADATA + '#daap', ns.TP_FT_METADATA + '#http', ns.TP_FT_METADATA + '#com.example.Go', ], xiangqi_caps) advertise_caps(q, bus, conn, stream, [xiangqi_fixed_properties, go_fixed_properties], [ns.TP_FT_METADATA + '#com.example.Xiangqi', ns.TP_FT_METADATA + '#com.example.Go', ], [ns.TP_FT_METADATA + '#http', ns.TP_FT_METADATA + '#daap', ], xiangqi_go_caps) advertise_caps(q, bus, conn, stream, [go_fixed_properties], [ns.TP_FT_METADATA + '#com.example.Go', ], [ns.TP_FT_METADATA + '#http', ns.TP_FT_METADATA + '#daap', ns.TP_FT_METADATA + '#com.example.Xiangqi', ], go_caps) def test(q, bus, conn, stream): test_ft_caps_from_contact(q, bus, conn, stream, 'bilbo1@foo.com/Foo') test_ft_caps_to_contact(q, bus, conn, stream) if __name__ == '__main__': exec_test(test) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/file-transfer/test-ibb-too-early.py���������������������������0000664�0001750�0001750�00000001745�12332441362�027567� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from gabbletest import exec_test import bytestream from file_transfer_helper import ReceiveFileTest, File from servicetest import EventPattern import constants as cs from config import FILE_TRANSFER_ENABLED if not FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer" raise SystemExit(77) class IbbTooEarlyTest (ReceiveFileTest): def __init__ (self): ReceiveFileTest.__init__ (self, bytestream.BytestreamIBBMsg, File (), cs.SOCKET_ADDRESS_TYPE_UNIX, cs.SOCKET_ACCESS_CONTROL_LOCALHOST, "") def accept_file (self): # Instead of us accepting the other side starts sending the iq open # skip the open step explicitely self.bytestream.checked = True event = self.bytestream.open_bytestream( expected_after = [ EventPattern ('stream-iq', iq_type = 'error') ] ) return True if __name__ == '__main__': exec_test (IbbTooEarlyTest().test) ���������������������������telepathy-gabble-0.18.3/tests/twisted/file-transfer/test-send-file-declined.py����������������������0000664�0001750�0001750�00000003416�12332441362�030532� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import dbus import constants as cs from file_transfer_helper import SendFileTest, exec_file_transfer_test from twisted.words.xish import domish import ns from config import FILE_TRANSFER_ENABLED if not FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer" raise SystemExit(77) class SendFileDeclinedTest(SendFileTest): def got_send_iq(self): SendFileTest.got_send_iq(self) # Receiver declines the file offer reply = domish.Element(('jabber:client', 'iq')) reply['to'] = 'test@localhost/Resource' reply['from'] = self.iq['to'] reply['type'] = 'error' reply['id'] = self.iq['id'] error = reply.addElement((None, 'error')) error['code'] = '403' error['type'] = 'cancel' forbidden = error.addElement((ns.STANZA, 'forbidden')) text = error.addElement((ns.STANZA, 'text'), content='Offer Declined') self.stream.send(reply) e = self.q.expect('dbus-signal', signal='FileTransferStateChanged') state, reason = e.args assert state == cs.FT_STATE_CANCELLED, state assert reason == cs.FT_STATE_CHANGE_REASON_REMOTE_STOPPED transferred = self.ft_props.Get(cs.CHANNEL_TYPE_FILE_TRANSFER, 'TransferredBytes') # no byte has been transferred as the file was declined assert transferred == 0 # try to provide the file, assert that this finishes the test (e.g. # couldn't go further because of ipv6) or that it raises # cs.NOT_AVAILABLE try: assert self.provide_file() except dbus.DBusException, e: assert e.get_dbus_name() == cs.NOT_AVAILABLE # stop test return True if __name__ == '__main__': exec_file_transfer_test(SendFileDeclinedTest) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/file-transfer/test-send-file-and-cancel-immediately.py��������0000664�0001750�0001750�00000001654�12225363340�033253� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import constants as cs from file_transfer_helper import SendFileTest, exec_file_transfer_test from config import FILE_TRANSFER_ENABLED if not FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer" raise SystemExit(77) class SendFileAndCancelImmediatelyTest(SendFileTest): def provide_file(self): SendFileTest.provide_file(self) # cancel the transfer before the receiver accepts it self.channel.Close() e = self.q.expect('dbus-signal', signal='FileTransferStateChanged') state, reason = e.args assert state == cs.FT_STATE_CANCELLED assert reason == cs.FT_STATE_CHANGE_REASON_LOCAL_STOPPED self.q.expect('dbus-signal', signal='Closed') # XEP-0096 doesn't have a way to inform receiver we cancelled the # transfer... return True if __name__ == '__main__': exec_file_transfer_test(SendFileAndCancelImmediatelyTest) ������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/file-transfer/test-receive-file.py����������������������������0000664�0001750�0001750�00000000452�12225363340�027453� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from file_transfer_helper import exec_file_transfer_test, ReceiveFileTest from config import FILE_TRANSFER_ENABLED if not FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer" raise SystemExit(77) if __name__ == '__main__': exec_file_transfer_test(ReceiveFileTest) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/file-transfer/test-send-file-wait-to-provide.py���������������0000664�0001750�0001750�00000003576�12225363340�032024� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import constants as cs from file_transfer_helper import SendFileTest, exec_file_transfer_test from config import FILE_TRANSFER_ENABLED if not FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer" raise SystemExit(77) class SendFileTransferWaitToProvideTest(SendFileTest): def __init__(self, bytestream_cls, file, address_type, access_control, acces_control_param): SendFileTest.__init__(self, bytestream_cls, file, address_type, access_control, acces_control_param) self._actions = [self.connect, self.check_ft_available, self.announce_contact, self.check_ft_available, self.request_ft_channel, self.create_ft_channel, self.got_send_iq, self.client_accept_file, self.provide_file, self.send_file, self.close_channel] def client_accept_file(self): # state is still Pending as remote didn't accept the transfer yet state = self.ft_props.Get(cs.CHANNEL_TYPE_FILE_TRANSFER, 'State') assert state == cs.FT_STATE_PENDING SendFileTest.client_accept_file(self) # Remote accepted the transfer e = self.q.expect('dbus-signal', signal='FileTransferStateChanged') state, reason = e.args assert state == cs.FT_STATE_ACCEPTED, state assert reason == cs.FT_STATE_CHANGE_REASON_NONE def provide_file(self): if SendFileTest.provide_file(self): return True e = self.q.expect('dbus-signal', signal='InitialOffsetDefined') offset = e.args[0] assert offset == self.file.offset # Channel is open. We can start to send the file e = self.q.expect('dbus-signal', signal='FileTransferStateChanged') state, reason = e.args assert state == cs.FT_STATE_OPEN assert reason == cs.FT_STATE_CHANGE_REASON_REQUESTED if __name__ == '__main__': exec_file_transfer_test(SendFileTransferWaitToProvideTest) ����������������������������������������������������������������������������������������������������������������������������������test-receive-file-and-sender-disconnect-while-transfering.py����������������������������������������0000664�0001750�0001750�00000001767�12225363340�037201� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000�telepathy-gabble-0.18.3/tests/twisted/file-transfer��������������������������������������������������������������������������������������������������������������������from twisted.words.xish import domish import constants as cs from file_transfer_helper import exec_file_transfer_test, ReceiveFileTest from config import FILE_TRANSFER_ENABLED if not FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer" raise SystemExit(77) class ReceiveFileAndSenderDisconnectWhileTransfering(ReceiveFileTest): def accept_file(self): ReceiveFileTest.accept_file(self) presence = domish.Element(('jabber:client', 'presence')) presence['from'] = self.contact_full_jid presence['to'] = 'test@localhost/Resource' presence['type'] = 'unavailable' self.stream.send(presence) e = self.q.expect('dbus-signal', signal='FileTransferStateChanged') state, reason = e.args assert state == cs.FT_STATE_CANCELLED assert reason == cs.FT_STATE_CHANGE_REASON_REMOTE_STOPPED return True if __name__ == '__main__': exec_file_transfer_test(ReceiveFileAndSenderDisconnectWhileTransfering) ���������telepathy-gabble-0.18.3/tests/twisted/file-transfer/metadata.py�������������������������������������0000664�0001750�0001750�00000006435�12332441362�025726� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# The 'normal' cases are tested with test-receive-file.py and test-send-file-provide-immediately.py # This file tests some corner cases import dbus from file_transfer_helper import exec_file_transfer_test, ReceiveFileTest, SendFileTest from servicetest import assertEquals, call_async import constants as cs from config import FILE_TRANSFER_ENABLED if not FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer" raise SystemExit(77) class SendFileNoMetadata(SendFileTest): # this is basically the equivalent of calling CreateChannel # without these two properties service_name = '' metadata = {} class ReceiveFileNoMetadata(ReceiveFileTest): service_name = '' metadata = {} class SendFileOddMetadata(SendFileTest): service_name = '' metadata = {'loldongs': []} class ReceiveFileOddMetadata(ReceiveFileTest): service_name = '' metadata = {'loldongs': []} class SendFileBadProps(SendFileTest): metadata = {'FORM_TYPE': ['this shouldnt be allowed']} def request_ft_channel(self): request = { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_FILE_TRANSFER, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: self.handle, cs.FT_CONTENT_TYPE: self.file.content_type, cs.FT_FILENAME: self.file.name, cs.FT_SIZE: self.file.size, cs.FT_CONTENT_HASH_TYPE: self.file.hash_type, cs.FT_CONTENT_HASH: self.file.hash, cs.FT_DESCRIPTION: self.file.description, cs.FT_DATE: self.file.date, cs.FT_INITIAL_OFFSET: 0, cs.FT_SERVICE_NAME: self.service_name, cs.FT_METADATA: dbus.Dictionary(self.metadata, signature='sas')} call_async(self.q, self.conn.Requests, 'CreateChannel', request) # FORM_TYPE is not allowed, soz self.q.expect('dbus-error', method='CreateChannel', name=cs.INVALID_ARGUMENT) return True class SendFileBadContact(SendFileTest): def announce_contact(self): SendFileTest.announce_contact(self, metadata=False) def request_ft_channel(self): request = { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_FILE_TRANSFER, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: self.handle, cs.FT_CONTENT_TYPE: self.file.content_type, cs.FT_FILENAME: self.file.name, cs.FT_SIZE: self.file.size, cs.FT_CONTENT_HASH_TYPE: self.file.hash_type, cs.FT_CONTENT_HASH: self.file.hash, cs.FT_DESCRIPTION: self.file.description, cs.FT_DATE: self.file.date, cs.FT_INITIAL_OFFSET: 0, cs.FT_SERVICE_NAME: self.service_name, cs.FT_METADATA: dbus.Dictionary(self.metadata, signature='sas')} call_async(self.q, self.conn.Requests, 'CreateChannel', request) # no support for metadata, soz self.q.expect('dbus-error', method='CreateChannel', name=cs.NOT_CAPABLE) return True if __name__ == '__main__': exec_file_transfer_test(SendFileNoMetadata, True) exec_file_transfer_test(ReceiveFileNoMetadata, True) exec_file_transfer_test(SendFileOddMetadata, True) exec_file_transfer_test(ReceiveFileOddMetadata, True) exec_file_transfer_test(SendFileBadProps, True) exec_file_transfer_test(SendFileBadContact, True) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/dataforms.py��������������������������������������������������0000664�0001750�0001750�00000002456�12332441362�023364� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test dataforms """ from servicetest import sync_dbus, assertEquals from gabbletest import exec_test, sync_stream import ns import constants as cs from caps_helper import receive_presence_and_ask_caps from config import VOIP_ENABLED # For historical reasons we advertise some bonus caps until the first call # to UpdateCapabilities or AdvertiseCapabilities. These caps are all related # to VoIP, so disabling VoIP breaks the assumptions this test is based on. if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test(q, bus, conn, stream): q.expect('stream-presence') # gabble won't try to represent the client if doesn't have any # RCCs or HCTs, so let's add some conn.ContactCapabilities.UpdateCapabilities( [ ('dataformtest', [], ['banan', 'hi']) ]) _, _, forms, _ = receive_presence_and_ask_caps(q, stream) assertEquals({'gabble:test:channel:manager:data:form': {'cheese': ['omgnothorriblecheese'], 'running_out_of': ['ideas', 'cake'], 'favourite_crane': ['a tall one', 'a short one'], 'animal': ['badger', 'snake', 'weasel'] } }, forms) if __name__ == '__main__': exec_test(test) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/main-debug.c��������������������������������������������������0000664�0001750�0001750�00000007406�12223562023�023203� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * main.c - entry point for telepathy-gabble-debug used by tests * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include <stdlib.h> #include <glib.h> #ifdef G_OS_UNIX #include <netinet/in.h> #include <netinet/tcp.h> #endif #include "gabble.h" #include "connection.h" #include "vcard-manager.h" #ifdef ENABLE_JINGLE_FILE_TRANSFER #include "gtalk-file-collection.h" #endif #include "test-resolver.h" #include <dbus/dbus.h> #ifdef G_OS_UNIX static gboolean connection_established_cb (GSignalInvocationHint *ihint, guint n_param_values, const GValue *param_values, gpointer user_data) { GSocketConnection *conn; GSocket *sock; gint flag, ret, fd; conn = g_value_get_object (param_values + 1); sock = g_socket_connection_get_socket (conn); flag = 1; fd = g_socket_get_fd (sock); ret = setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (const char *) &flag, sizeof (flag)); if (ret == -1) /* not the worst thing ever. */ g_print ("Couldn't setsockopt(TCP_NODELAY) on the connection; ain't so bad.\n"); return TRUE; } #endif int main (int argc, char **argv) { int ret = 1; GResolver *kludged; #ifdef G_OS_UNIX gpointer cls; #endif gabble_init (); /* needed for connect/disco-no-reply.py */ gabble_connection_set_disco_reply_timeout (3); /* needed for test-avatar-async.py */ gabble_vcard_manager_set_suspend_reply_timeout (3); gabble_vcard_manager_set_default_request_timeout (3); /* hook up the fake DNS resolver that lets us divert A and SRV queries * * into our local cache before asking the real DNS */ kludged = g_object_new (TEST_TYPE_RESOLVER, NULL); g_resolver_set_default (kludged); g_object_unref (kludged); test_resolver_add_A (TEST_RESOLVER (kludged), "resolves-to-5.4.3.2", "5.4.3.2"); test_resolver_add_A (TEST_RESOLVER (kludged), "resolves-to-1.2.3.4", "1.2.3.4"); test_resolver_add_A (TEST_RESOLVER (kludged), "localhost", "127.0.0.1"); test_resolver_add_A (TEST_RESOLVER (kludged), "stun.telepathy.im", "6.7.8.9"); test_resolver_add_SRV (TEST_RESOLVER (kludged), "stun", "udp", "stunning.localhost", "resolves-to-5.4.3.2", 1); #ifdef ENABLE_VOIP wocky_jingle_info_set_test_mode (); #endif #ifdef ENABLE_JINGLE_FILE_TRANSFER gtalk_file_collection_set_test_mode (); #endif #ifdef G_OS_UNIX /* We want to set TCP_NODELAY on the socket as soon as possible in * the connector so let's use ::connection-established. We need to * ref the class type as it's not loaded yet. */ cls = g_type_class_ref (WOCKY_TYPE_CONNECTOR); if (g_getenv ("GABBLE_NODELAY") != NULL) { g_signal_add_emission_hook ( g_signal_lookup ("connection-established", WOCKY_TYPE_CONNECTOR), 0, connection_established_cb, NULL, NULL); } #endif ret = gabble_main (argc, argv); /* Hack, remove the ref g_resolver has on this object, atm there is no way to * unset a custom resolver */ g_object_unref (kludged); #ifdef G_OS_UNIX g_type_class_unref (cls); #endif dbus_shutdown (); return ret; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/sidecar-own-caps.py�������������������������������������������0000664�0001750�0001750�00000004020�12332441362�024530� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test Gabble's implementation of sidecars own caps, using the test plugin. """ from twisted.words.protocols.jabber.client import IQ from twisted.words.xish import xpath from servicetest import call_async, EventPattern, assertEquals, assertContains from gabbletest import exec_test, acknowledge_iq from caps_helper import compute_caps_hash import constants as cs import ns from config import PLUGINS_ENABLED TEST_PLUGIN_IFACE = "org.freedesktop.Telepathy.Gabble.Plugin.Test" if not PLUGINS_ENABLED: print "NOTE: built without --enable-plugins, skipping" raise SystemExit(77) # which makes the test show up as skipped def test(q, bus, conn, stream): # This sidecar sends a stanza, and waits for a reply, before being # created. pattern = EventPattern('stream-iq', to='sidecar.example.com', query_ns='http://example.com/sidecar') call_async(q, conn.Future, 'EnsureSidecar', TEST_PLUGIN_IFACE + ".IQ") e = q.expect_many(pattern)[0] # The server said yes, so we should get a sidecar back! acknowledge_iq(stream, e.stanza) q.expect('dbus-return', method='EnsureSidecar') identities = ["test/app-list//Test"] features = ["com.example.test1", "com.example.test2"] ver = compute_caps_hash(identities, features, {}) iq = IQ(stream, "get") id = iq['id'] query = iq.addElement((ns.DISCO_INFO, 'query')) query['node'] = ns.GABBLE_CAPS + '#' + ver stream.send(iq) e = q.expect('stream-iq', query_ns='http://jabber.org/protocol/disco#info') returned_features = [feature['var'] for feature in xpath.queryForNodes('/iq/query/feature', e.stanza)] assertEquals(features, returned_features) returned_identities = [identity['category'] + "/" + identity['type']+"//" + identity['name'] for identity in xpath.queryForNodes('/iq/query/identity', e.stanza)] assertEquals(identities, returned_identities) new_ver = compute_caps_hash(returned_identities, returned_features, {}) assertEquals(new_ver, ver) if __name__ == '__main__': exec_test(test) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/muc/����������������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�021616� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/muc/send-error.py���������������������������������������������0000664�0001750�0001750�00000013575�12332441362�024254� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test incoming error messages in MUC channels. """ import warnings import dbus from gabbletest import exec_test from servicetest import EventPattern, assertEquals, assertLength, assertContains import constants as cs import ns from mucutil import join_muc_and_check def test(q, bus, conn, stream): muc = 'chat@conf.localhost' _, text_chan, test_handle, bob_handle = \ join_muc_and_check(q, bus, conn, stream, muc) # Suppose we don't have permission to speak in this MUC. Send a message to # the channel, and have the MUC reject it as unauthorized. send_message_and_expect_error(q, stream, text_chan, test_handle, bob_handle, u"hi r ther ne warez n this chanel?", '401', 'auth', 'not-authorized', delivery_status=cs.DELIVERY_STATUS_PERMANENTLY_FAILED, send_error_value=cs.SendError.PERMISSION_DENIED) # This time, we get rate-limited. # <https://bugs.freedesktop.org/show_bug.cgi?id=43166> send_message_and_expect_error(q, stream, text_chan, test_handle, bob_handle, "faster faster", '500', 'wait', 'resource-constraint', delivery_status=cs.DELIVERY_STATUS_TEMPORARILY_FAILED, # Yuck this isn't a very good name is it? send_error_value=cs.SendError.TOO_LONG) # How about an error message in the reply? This is from Prosody. See # https://bugs.freedesktop.org/show_bug.cgi?id=43166#c9 send_message_and_expect_error(q, stream, text_chan, test_handle, bob_handle, content=u"fair enough", code=None, type_='wait', element='policy-violation', error_message='The room is currently overactive, please try again later', delivery_status=cs.DELIVERY_STATUS_TEMPORARILY_FAILED, # Maybe we should expand the SendError codes some day, because this one # is l-a-m-e. send_error_value=cs.SendError.PERMISSION_DENIED) def send_message_and_expect_error(q, stream, text_chan, test_handle, bob_handle, content, code=None, type_=None, element=None, error_message=None, delivery_status=None, send_error_value=None): greeting = [ dbus.Dictionary({ }, signature='sv'), { 'content-type': 'text/plain', 'content': content, } ] sent_token = text_chan.Messages.SendMessage(greeting, dbus.UInt32(0)) stream_message, _, _ = q.expect_many( EventPattern('stream-message'), EventPattern('dbus-signal', signal='Sent'), EventPattern('dbus-signal', signal='MessageSent'), ) # computer says no elem = stream_message.stanza elem['from'] = 'chat@conf.localhost' elem['to'] = 'chat@conf.localhost/test' elem['type'] = 'error' error = elem.addElement('error') if code is not None: error['code'] = code if type_ is not None: error['type'] = type_ if element is not None: error.addElement((ns.STANZA, element)) if error_message is not None: error.addElement((ns.STANZA, 'text')).addContent(error_message) stream.send(elem) # check that we got a failed delivery report and a SendError send_error, received, message_received = q.expect_many( EventPattern('dbus-signal', signal='SendError'), EventPattern('dbus-signal', signal='Received'), EventPattern('dbus-signal', signal='MessageReceived'), ) err, timestamp, type, text = send_error.args assertEquals(send_error_value, err) # there's no way to tell when the original message was sent from the error stanza assertEquals(0, timestamp) # Gabble can't determine the type of the original message; see muc/test-muc.py # assert type == 0, send_error.args assertEquals(content, text) # The Text.Received signal should be a "you're not tall enough" stub id, timestamp, sender, type, flags, text = received.args assertEquals(0, sender) assertEquals(type, cs.MT_DELIVERY_REPORT) if flags == 0: warnings.warn("ignoring tp-glib bug #61254") else: assertEquals(cs.MessageFlag.NON_TEXT_CONTENT, flags) if error_message is None: assertEquals('', text) else: assertEquals(error_message, text) # Check that the Messages.MessageReceived signal was a failed delivery report assertLength(1, message_received.args) parts = message_received.args[0] if error_message is None: # The delivery report should just be a header, no body. assertLength(1, parts) else: assertLength(2, parts) part = parts[0] # The intended recipient was the MUC, so there's no contact handle # suitable for being 'message-sender'. assertEquals(0, part.get('message-sender', 0)) assertEquals(cs.MT_DELIVERY_REPORT, part['message-type']) assertEquals(delivery_status, part['delivery-status']) assertEquals(send_error_value, part['delivery-error']) assertEquals(sent_token, part['delivery-token']) # Check that the included echo is from us, and matches all the keys in the # message we sent. assertContains('delivery-echo', part) echo = part['delivery-echo'] assertLength(len(greeting), echo) echo_header = echo[0] assertEquals(test_handle, echo_header['message-sender']) assertEquals(sent_token, echo_header['message-token']) for i in range(0, len(echo)): for key in greeting[i]: assert key in echo[i], (i, key, echo) assert echo[i][key] == greeting[i][key], (i, key, echo, greeting) if error_message is not None: body = parts[1] assertEquals('text/plain', body['content-type']) assertEquals(error_message, body['content']) if __name__ == '__main__': exec_test(test) �����������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/muc/password.py�����������������������������������������������0000664�0001750�0001750�00000006001�12332441362�024020� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from gabbletest import exec_test, elem, request_muc_handle, make_muc_presence from servicetest import call_async, EventPattern, wrap_channel, assertEquals import constants as cs import ns def expect_attempt(q, expected_muc_jid, expected_password): e = q.expect('stream-presence', to=expected_muc_jid) x = e.stanza.elements(uri=ns.MUC, name='x').next() p = x.firstChildElement() assertEquals(expected_password, str(p)) def test(q, bus, conn, stream): room = 'chat@conf.localhost' handle = request_muc_handle(q, conn, stream, room) call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_HANDLE: handle}) expected_muc_jid = '%s/%s' % (room, 'test') q.expect('stream-presence', to=expected_muc_jid) # tell gabble the room needs a password denied = \ elem('jabber:client', 'presence', from_=expected_muc_jid, type='error')( elem(ns.MUC, 'x'), elem('error', type='auth')( elem(ns.STANZA, 'not-authorized'), ), ) stream.send(denied) cc, _, _ = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('dbus-signal', signal='NewChannels'), EventPattern('dbus-signal', signal='PasswordFlagsChanged', args=[cs.PASSWORD_FLAG_PROVIDE, 0])) chan = wrap_channel(bus.get_object(conn.bus_name, cc.value[0]), 'Text', ['Password']) flags = chan.Password.GetPasswordFlags() assertEquals(cs.PASSWORD_FLAG_PROVIDE, flags) call_async(q, chan.Password, 'ProvidePassword', 'brand new benz') expect_attempt(q, expected_muc_jid, 'brand new benz') # Try again while the first attempt is outstanding. Gabble should say no. call_async(q, chan.Password, 'ProvidePassword', 'faster faster') q.expect('dbus-error', method='ProvidePassword') # Sorry, wrong password. stream.send(denied) ret = q.expect('dbus-return', method='ProvidePassword') assert not ret.value[0] call_async(q, chan.Password, 'ProvidePassword', 'bougie friends') expect_attempt(q, expected_muc_jid, 'bougie friends') # Well, this may be the right password, but actually that nick is in use. presence = elem('presence', from_=expected_muc_jid, type='error')( elem(ns.MUC, 'x'), elem('error', type='cancel')( elem(ns.STANZA, 'conflict'), )) stream.send(presence) # Okay, so Gabble tries again, with a new JID *and the same password*. expected_muc_jid = expected_muc_jid + '_' expect_attempt(q, expected_muc_jid, 'bougie friends') # Hey this worked. stream.send(make_muc_presence('none', 'participant', room, 'test_')) ret, _ = q.expect_many( EventPattern('dbus-return', method='ProvidePassword'), EventPattern('dbus-signal', signal='PasswordFlagsChanged', args=[0, cs.PASSWORD_FLAG_PROVIDE])) assert ret.value[0] if __name__ == '__main__': exec_test(test) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/muc/chat-states.py��������������������������������������������0000664�0001750�0001750�00000012156�12332441362�024406� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Regression test for <https://bugs.freedesktop.org/show_bug.cgi?id=32952>, wherein chat states in MUCs were misparsed, and MUC chat states in general. """ from servicetest import assertEquals, assertLength, EventPattern from gabbletest import exec_test, elem, make_muc_presence, sync_stream from mucutil import join_muc_and_check import ns import constants as cs MUC = 'ohai@groupchat.google.com' BOB = MUC + '/bob' def get_state_notification(stanza): for x in stanza.elements(): if x.uri == ns.CHAT_STATES: return x return None def check_state_notification(elem, name, allow_body=False): assertEquals('message', elem.name) assertEquals('groupchat', elem['type']) notification = get_state_notification(elem) assert notification is not None, elem.toXml() assert notification.name == name, notification.toXml() if not allow_body: assert len(elem.children) == 1, elem.toXml() def test(q, bus, conn, stream): (muc_handle, chan, user, bob) = join_muc_and_check(q, bus, conn, stream, MUC) states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates') assertEquals(cs.CHAT_STATE_INACTIVE, states.get(user, cs.CHAT_STATE_INACTIVE)) assertEquals(cs.CHAT_STATE_INACTIVE, states.get(bob, cs.CHAT_STATE_INACTIVE)) stream.send( elem('message', from_=BOB, to='test@localhost/Resource', type='groupchat', jid='bob@bob.bob')( elem(ns.CHAT_STATES, 'composing'), elem('google:nosave', 'x', value='disabled'), elem('http://jabber.org/protocol/archive', 'record', otr='false'), )) e = q.expect('dbus-signal', signal='ChatStateChanged') contact, state = e.args assertEquals(bob, contact) assertEquals(cs.CHAT_STATE_COMPOSING, state) states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates') assertEquals(cs.CHAT_STATE_INACTIVE, states.get(user, cs.CHAT_STATE_INACTIVE)) assertEquals(cs.CHAT_STATE_COMPOSING, states.get(bob, cs.CHAT_STATE_INACTIVE)) stream.send( elem('message', from_=BOB, to='test@localhost/Resource', type='groupchat', jid='bob@bob.bob')( elem(ns.CHAT_STATES, 'paused'), elem('google:nosave', 'x', value='disabled'), elem('http://jabber.org/protocol/archive', 'record', otr='false'), )) e = q.expect('dbus-signal', signal='ChatStateChanged') contact, state = e.args assertEquals(bob, contact) assertEquals(cs.CHAT_STATE_PAUSED, state) states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates') assertEquals(cs.CHAT_STATE_INACTIVE, states.get(user, cs.CHAT_STATE_INACTIVE)) assertEquals(cs.CHAT_STATE_PAUSED, states.get(bob, cs.CHAT_STATE_INACTIVE)) # Bob leaves presence = make_muc_presence('owner', 'none', MUC, 'bob') presence['type'] = 'unavailable' stream.send(presence) e = q.expect('dbus-signal', signal='ChatStateChanged') contact, state = e.args assertEquals(bob, contact) assertEquals(cs.CHAT_STATE_GONE, state) states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates') assertEquals(cs.CHAT_STATE_INACTIVE, states.get(user, cs.CHAT_STATE_INACTIVE)) # Bob no longer has any chat state at all assertEquals(None, states.get(bob, None)) # Sending chat states: # Composing... chan.ChatState.SetChatState(cs.CHAT_STATE_COMPOSING) stream_message = q.expect('stream-message') check_state_notification(stream_message.stanza, 'composing') states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates') assertEquals(cs.CHAT_STATE_COMPOSING, states.get(user, cs.CHAT_STATE_INACTIVE)) # XEP 0085: # every content message SHOULD contain an <active/> notification. chan.Text.Send(0, 'hi.') stream_message = q.expect('stream-message') stanza = stream_message.stanza check_state_notification(stanza, 'active', allow_body=True) states = chan.Properties.Get(cs.CHANNEL_IFACE_CHAT_STATE, 'ChatStates') assertEquals(cs.CHAT_STATE_ACTIVE, states.get(user, cs.CHAT_STATE_INACTIVE)) bodies = list(stanza.elements(uri=ns.CLIENT, name='body')) assertLength(1, bodies) assertEquals(u'hi.', bodies[0].children[0]) # If we get an error with type='wait', stop sending chat states. stanza['type'] = 'error' stanza['from'] = MUC stanza['to'] = 'test@localhost/Resource' error = stanza.addElement('error') error['type'] = 'wait' error.addElement((ns.STANZA, 'resource-constraint')) stream.send(stanza) q.expect('dbus-signal', signal='MessageReceived', predicate=lambda e: e.args[0][0]['message-type'] == cs.MT_DELIVERY_REPORT) q.forbid_events([ EventPattern('stream-message', to=MUC, predicate=lambda e: get_state_notification(e.stanza) is not None) ]) # User starts typing again but nothing should be seen or heard on the stream. chan.ChatState.SetChatState(cs.CHAT_STATE_COMPOSING) sync_stream(q, stream) if __name__ == '__main__': exec_test(test) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/muc/scrollback.py���������������������������������������������0000664�0001750�0001750�00000004410�12332441362�024277� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Regression test for https://bugs.freedesktop.org/show_bug.cgi?id=27913 where scrollback messages from contacts not currently in the MUC don't show up in the MUC; instead, they seemed to show up on IM channels whose target is the MUC's bare JID. Also acts as a scrollback messages in general! """ import dbus from servicetest import assertEquals, assertContains from gabbletest import exec_test, elem import constants as cs import ns from mucutil import join_muc_and_check def test(q, bus, conn, stream): room = 'chat@conf.localhost' our_jid = room + '/test' bob_jid = room + '/bob' marco_jid = room + '/marco' room_handle, chan, test_handle, bob_handle = \ join_muc_and_check(q, bus, conn, stream, room) # Here are a few scrollback messages. One from us; one from bob; and one # from marco, who's no longer in the room. stream.send( elem('message', from_=our_jid, type='groupchat')( elem('body')( u'i really hate the muc xep' ), elem(ns.X_DELAY, 'x', from_=room, stamp='20090910T12:34:56') ) ) stream.send( elem('message', from_=bob_jid, type='groupchat')( elem('body')( u'yeah, it totally sucks' ), elem(ns.X_DELAY, 'x', from_=room, stamp='20090910T12:45:56') ) ) stream.send( elem('message', from_=marco_jid, type='groupchat')( elem('body')( u'we should start a riot' ), elem(ns.X_DELAY, 'x', from_=room, stamp='20090910T12:56:56') ) ) m1 = q.expect('dbus-signal', signal='MessageReceived') m2 = q.expect('dbus-signal', signal='MessageReceived') m3 = q.expect('dbus-signal', signal='MessageReceived') def badger(event): assertEquals(chan.object_path, event.path) message, = event.args header = message[0] assertContains('scrollback', header) assert header['scrollback'] assertContains('message-sender', header) return header['message-sender'] me = badger(m1) bob = badger(m2) marco = badger(m3) assertEquals([our_jid, bob_jid, marco_jid], conn.InspectHandles(cs.HT_CONTACT, [ me, bob, marco ])) if __name__ == '__main__': exec_test(test) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/muc/presence-before-closing.py��������������������������������0000664�0001750�0001750�00000012317�12332441362�026665� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test for fd.o#19930. """ import dbus from twisted.words.xish import domish from gabbletest import ( exec_test, make_result_iq, request_muc_handle, wrap_channel, elem, ) from servicetest import (EventPattern, assertEquals, assertLength, assertContains, sync_dbus, call_async) import constants as cs import ns from mucutil import join_muc, echo_muc_presence def test(q, bus, conn, stream): room = 'test@conf.localhost' room_handle, chan, path, props, disco = join_muc(q, bus, conn, stream, room, also_capture=[EventPattern('stream-iq', iq_type='get', query_name='query', query_ns=ns.DISCO_INFO, to=room)]) sync_dbus(bus, q, conn) # we call Close... call_async(q, chan, 'Close') q.expect('dbus-return', method='Close') # ...so gabble announces our unavailable presence to the MUC. event = q.expect('stream-presence', to=room + '/test') elem = event.stanza assertEquals('unavailable', elem['type']) # while we wait for the conference server to echo our unavailable # presence, we try and create the same channel again... call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: room }) # ...which should fail because the channel hasn't closed yet. q.expect('dbus-error', method='CreateChannel', name=cs.NOT_AVAILABLE) # the conference server finally gets around to echoing our # unavailable presence... echo_muc_presence(q, stream, elem, 'none', 'participant') # ...and only now is the channel closed. q.expect_many(EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed')) # now that the channel has finally closed, let's try and request # it again which should succeed! _, chan, _, _ = join_muc(q, bus, conn, stream, room) # let's clear up though. chan.Close() event = q.expect('stream-presence', to=room + '/test') echo_muc_presence(q, stream, event.stanza, 'none', 'participant') q.expect_many(EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed')) def test_then_disconnect(q, bus, conn, stream): room = 'test@conf.localhost' room_handle, chan, path, props, disco = join_muc(q, bus, conn, stream, room, also_capture=[EventPattern('stream-iq', iq_type='get', query_name='query', query_ns=ns.DISCO_INFO, to=room)]) sync_dbus(bus, q, conn) # we call Close... call_async(q, chan, 'Close') q.expect('dbus-return', method='Close') # ...so gabble announces our unavailable presence to the MUC. event = q.expect('stream-presence', to=room + '/test') elem = event.stanza assertEquals('unavailable', elem['type']) # oh no, but now we want to disconnect. call_async(q, conn, 'Disconnect') # the muc factory is told to close everything, so it does so # without announcing it to the channel because it does it # forcibly, so the channels disappear. q.expect_many(EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed')) # now echo the unavailable presence; this shouldn't be handled # because the channel has already closed. echo_muc_presence(q, stream, elem, 'none', 'participant') # send the stream footer so that the connection thinks it's # property disconnected now. stream.sendFooter() # finally, Disconnect returns q.expect('dbus-return', method='Disconnect') def test_with_password(q, bus, conn, stream): room = 'chat@conf.localhost' handle = request_muc_handle(q, conn, stream, room) call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_HANDLE: handle}) expected_muc_jid = '%s/%s' % (room, 'test') q.expect('stream-presence', to=expected_muc_jid) # tell gabble the room needs a password stream.send( elem('jabber:client', 'presence', from_=expected_muc_jid, type='error')( elem(ns.MUC, 'x'), elem('error', type='auth')( elem(ns.STANZA, 'not-authorized'), ), )) cc, _ = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('dbus-signal', signal='PasswordFlagsChanged', args=[cs.PASSWORD_FLAG_PROVIDE, 0])) chan = wrap_channel(bus.get_object(conn.bus_name, cc.value[0]), 'Text') forbidden = [EventPattern('stream-presence', to=expected_muc_jid)] q.forbid_events(forbidden) # we call Close... call_async(q, chan, 'Close') # ...but this time no unavailable presence because we were in the # auth state, so the channel closes immediately. q.expect_many(EventPattern('dbus-return', method='Close'), EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed')) q.unforbid_events(forbidden) if __name__ == '__main__': exec_test(test) exec_test(test_then_disconnect) exec_test(test_with_password) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/muc/test-muc.py�����������������������������������������������0000664�0001750�0001750�00000024464�12332441362�023734� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# vim: set fileencoding=utf-8 : Python sucks! """ Test MUC support. """ import dbus from twisted.words.xish import domish, xpath from gabbletest import exec_test from servicetest import ( EventPattern, assertEquals, assertLength, assertContains, assertDoesNotContain, ) import constants as cs import ns from mucutil import join_muc_and_check def test(q, bus, conn, stream): room = 'chat@conf.localhost' room_handle, chan, test_handle, bob_handle = \ join_muc_and_check(q, bus, conn, stream, room) # Exercise basic Channel Properties from spec 0.17.7 channel_props = chan.Properties.GetAll(cs.CHANNEL) assertEquals(room_handle, channel_props.get('TargetHandle')) assertEquals(cs.HT_ROOM, channel_props.get('TargetHandleType')) assertEquals(cs.CHANNEL_TYPE_TEXT, channel_props.get('ChannelType')) interfaces = channel_props.get('Interfaces') assertContains(cs.CHANNEL_IFACE_GROUP, interfaces) assertContains(cs.CHANNEL_IFACE_PASSWORD, interfaces) assertDoesNotContain(cs.TP_AWKWARD_PROPERTIES, interfaces) assertContains(cs.CHANNEL_IFACE_CHAT_STATE, interfaces) assertContains(cs.CHANNEL_IFACE_MESSAGES, interfaces) assert channel_props['TargetID'] == 'chat@conf.localhost', channel_props assert channel_props['Requested'] == True assert channel_props['InitiatorID'] == 'test@localhost' assert channel_props['InitiatorHandle'] == conn.GetSelfHandle() # Exercise Group Properties from spec 0.17.6 (in a basic way) group_props = chan.Properties.GetAll(cs.CHANNEL_IFACE_GROUP) assert 'HandleOwners' in group_props, group_props assert 'Members' in group_props, group_props assert 'LocalPendingMembers' in group_props, group_props assert 'RemotePendingMembers' in group_props, group_props assert 'GroupFlags' in group_props, group_props # Test receiving a message from Bob in the MUC message = domish.Element((None, 'message')) message['from'] = 'chat@conf.localhost/bob' message['type'] = 'groupchat' body = message.addElement('body', content='hello') stream.send(message) received, message_received = q.expect_many( EventPattern('dbus-signal', signal='Received'), EventPattern('dbus-signal', signal='MessageReceived'), ) # Check Channel.Type.Text.Received: # sender: bob assert received.args[2] == bob_handle # message type: normal assert received.args[3] == 0 # flags: none assert received.args[4] == 0 # body assert received.args[5] == 'hello' # Check Channel.Interface.Messages.MessageReceived: message = message_received.args[0] # message should have two parts: the header and one content part assert len(message) == 2, message header, body = message assert header['message-sender'] == bob_handle, header # the spec says that message-type "SHOULD be omitted for normal chat # messages." assert 'message-type' not in header, header assert body['content-type'] == 'text/plain', body assert body['content'] == 'hello', body # Remove the message from the pending message queue, and check that # PendingMessagesRemoved fires. message_id = header['pending-message-id'] chan.Text.AcknowledgePendingMessages([message_id]) removed = q.expect('dbus-signal', signal='PendingMessagesRemoved') removed_ids = removed.args[0] assert len(removed_ids) == 1, removed_ids assert removed_ids[0] == message_id, (removed_ids, message_id) # Send an action using the Messages API greeting = [ dbus.Dictionary({ 'message-type': 1, # Action }, signature='sv'), { 'content-type': 'text/plain', 'content': u"peers through a gap in the curtains", } ] # We ask for delivery reports (which MUCs provide) and read reports (which # MUCs do not provide). sent_token = chan.Messages.SendMessage(greeting, cs.MSG_SENDING_FLAGS_REPORT_DELIVERY | cs.MSG_SENDING_FLAGS_REPORT_READ) assert sent_token stream_message, sent, message_sent = q.expect_many( EventPattern('stream-message'), EventPattern('dbus-signal', signal='Sent'), EventPattern('dbus-signal', signal='MessageSent'), ) sent_message, flags, token = message_sent.args assert len(sent_message) == 2, sent_message header = sent_message[0] assert header['message-type'] == 1, header # Action assertEquals(test_handle, header['message-sender']) assertEquals('chat@conf.localhost/test', header['message-sender-id']) body = sent_message[1] assert body['content-type'] == 'text/plain', body assert body['content'] == u'peers through a gap in the curtains', body # Of the flags passed to SendMessage, Gabble should only report the # DELIVERY flag, since the other is not supported. assertEquals(cs.MSG_SENDING_FLAGS_REPORT_DELIVERY, flags) assertEquals(sent_token, token) assert sent.args[1] == 1, sent.args # Action assert sent.args[2] == u'peers through a gap in the curtains', sent.args assert message_sent.args[2] == sent_token elem = stream_message.stanza assert elem.name == 'message' assert elem['type'] == 'groupchat', repr(elem) assert elem['id'] == sent_token, repr(elem) assert elem['to'] == 'chat@conf.localhost', repr(elem) for sub_elem in stream_message.stanza.elements(): if sub_elem.name == 'body': found_body = True assert sub_elem.children[0] == u'/me peers through a gap in the curtains' break assert found_body # reflect the sent message back to the MUC elem['from'] = 'chat@conf.localhost/test' stream.send(elem) # Check that we got the corresponding delivery report report, old_received = q.expect_many( EventPattern('dbus-signal', signal='MessageReceived'), EventPattern('dbus-signal', signal='Received'), ) assert len(report.args) == 1, report.args parts = report.args[0] # The delivery report should just be a header, no body. assert len(parts) == 1, parts part = parts[0] # The intended recipient was the MUC, so there's no contact handle # suitable for being 'message-sender'. assert 'message-sender' not in part or part['message-sender'] == 0, part assert part['message-type'] == 4, part # Message_Type_Delivery_Report assert part['delivery-status'] == 1, part # Delivery_Status_Delivered assert part['delivery-token'] == sent_token, part assert 'delivery-error' not in part, part assert 'delivery-echo' in part, part # Check that the included echo is from us, and matches all the keys in the # message we sent. echo = part['delivery-echo'] assert len(echo) == len(greeting), (echo, greeting) assert echo[0]['message-sender'] == test_handle, echo[0] assert echo[0]['message-token'] == sent_token, echo[0] for i in range(0, len(echo)): for key in greeting[i]: assert key in echo[i], (i, key, echo) assert echo[i][key] == greeting[i][key], (i, key, echo, greeting) # The Text.Received signal should be a "you're not tall enough" stub id, timestamp, sender, type, flags, text = old_received.args assert sender == 0, old_received.args assert type == 4, old_received.args # Message_Type_Delivery_Report assert flags == 2, old_received.args # Non_Text_Content assert text == '', old_received.args # Send a normal message using the Channel.Type.Text API chan.Text.Send(0, 'goodbye') event, sent, message_sent = q.expect_many( EventPattern('stream-message'), EventPattern('dbus-signal', signal='Sent'), EventPattern('dbus-signal', signal='MessageSent'), ) sent_message, flags, _ = message_sent.args assert len(sent_message) == 2, sent_message header = sent_message[0] assert 'message-type' not in header, header # Normal body = sent_message[1] assert body['content-type'] == 'text/plain', body assert body['content'] == u'goodbye', body # The caller didn't ask for delivery reports (how could they? they're using # the old API), but the server's going to send us an echo anyway, so # Gabble's within its rights to pretend that the caller asked. assert flags in [0, cs.MSG_SENDING_FLAGS_REPORT_DELIVERY], flags assert sent.args[1] == 0, sent.args # Normal assert sent.args[2] == u'goodbye', sent.args sent_token = message_sent.args[2] elem = event.stanza assert elem.name == 'message' assert elem['type'] == 'groupchat' assert elem['id'] == message_sent.args[2] body = list(event.stanza.elements())[0] assert body.name == 'body' assert body.children[0] == u'goodbye' # reflect the sent message back to the MUC elem['from'] = 'chat@conf.localhost/test' stream.send(elem) # TODO: check for a delivery report. # test that presence changes are sent via the MUC conn.SimplePresence.SetPresence('away', 'hurrah') event = q.expect('stream-presence', to='chat@conf.localhost/test') elem = event.stanza show = [e for e in elem.elements() if e.name == 'show'][0] assert show assert show.children[0] == u'away' status = [e for e in elem.elements() if e.name == 'status'][0] assert status assert status.children[0] == u'hurrah' # Check that there's no <x xmlns='.../muc'/> element in the <presence> # stanza when we're just updating our presence, as opposed to joining the # MUC in the first place. This is a regression test for # <https://bugs.freedesktop.org/show_bug.cgi?id=29147>. XEP-0045 §7.4 shows # that you do not need to include this element in presence updates; if we # erroneously include it, some implementations take this to mean that we're # trying to join the MUC again and helpfully send us all the scrollback # again. x_muc_nodes = xpath.queryForNodes('/presence/x[@xmlns="%s"]' % ns.MUC, elem) assert x_muc_nodes is None, elem.toXml() # test that leaving the channel results in an unavailable message chan.Group.RemoveMembers([chan.Group.GetSelfHandle()], 'booo') event = q.expect('stream-presence', to='chat@conf.localhost/test') elem = event.stanza assert elem['type'] == 'unavailable' status = [e for e in elem.elements() if e.name == 'status'] assertLength(1, status) assertEquals(status[0].children[0], u'booo') if __name__ == '__main__': exec_test(test) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/muc/renamed.py������������������������������������������������0000664�0001750�0001750�00000005745�12332441362�023607� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test dealing with the server giving you a nick you didn't ask for. """ import dbus from gabbletest import ( exec_test, make_muc_presence, request_muc_handle ) from servicetest import call_async, unwrap from constants import ( HT_CONTACT, HT_ROOM, CONN_IFACE_REQUESTS, CHANNEL_TYPE_TEXT, CHANNEL_IFACE_GROUP, CHANNEL_TYPE, TARGET_HANDLE_TYPE, TARGET_HANDLE, ) import constants as cs def test(q, bus, conn, stream): self_handle = conn.GetSelfHandle() requests = dbus.Interface(conn, CONN_IFACE_REQUESTS) room_jid = 'chat@conf.localhost' room_handle = request_muc_handle(q, conn, stream, room_jid) call_async(q, requests, 'CreateChannel', dbus.Dictionary({ CHANNEL_TYPE: CHANNEL_TYPE_TEXT, TARGET_HANDLE_TYPE: HT_ROOM, TARGET_HANDLE: room_handle, }, signature='sv')) expected_jid = '%s/%s' % (room_jid, 'test') q.expect('stream-presence', to=expected_jid) # Send presence for another member of the MUC stream.send(make_muc_presence('owner', 'moderator', room_jid, 'liz')) # This is a themed discussion, so the MUC server forces you to have an # appropriate name. self_presence = make_muc_presence('none', 'participant', room_jid, 'toofer') x = [elt for elt in self_presence.elements() if elt.name == 'x'][0] status = x.addElement('status') status['code'] = '110' # "This is you" status = x.addElement('status') status['code'] = '210' # "I renamed you. Muahaha." stream.send(self_presence) # Gabble should figure out from 110 that it's in the room, and from 210 # that we've been renamed. event = q.expect('dbus-return', method='CreateChannel') path, props = event.value text_chan = bus.get_object(conn.bus_name, path) group_props = unwrap(text_chan.GetAll(CHANNEL_IFACE_GROUP, dbus_interface=dbus.PROPERTIES_IFACE)) liz, toofer, expected_handle = conn.RequestHandles(HT_CONTACT, ["%s/%s" % (room_jid, m) for m in ['liz', 'toofer', 'test']]) # Check that Gabble think our nickname in the room is toofer not test muc_self_handle = group_props['SelfHandle'] assert muc_self_handle == toofer, (muc_self_handle, toofer, expected_handle) members = group_props['Members'] # Check there are exactly two members (liz and toofer) expected_members = [liz, toofer] assert sorted(members) == sorted(expected_members), \ (members, expected_members) # There should be no pending members. assert len(group_props['LocalPendingMembers']) == 0, group_props assert len(group_props['RemotePendingMembers']) == 0, group_props # Check that toofer's handle owner is us, and that liz has # no owner. handle_owners = group_props['HandleOwners'] assert handle_owners[toofer] == self_handle, \ (handle_owners, toofer, handle_owners[toofer], self_handle) assert handle_owners[liz] == 0, (handle_owners, liz) if __name__ == '__main__': exec_test(test) ���������������������������telepathy-gabble-0.18.3/tests/twisted/muc/conference.py���������������������������������������������0000664�0001750�0001750�00000005342�12332441362�024274� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test the different ways to request a channel using the Conference interface """ from gabbletest import exec_test, make_muc_presence from servicetest import (call_async, EventPattern, assertEquals, assertContains) import constants as cs import dbus import re def test(q, bus, conn, stream): # Wait for us to be fully logged in q.expect('stream-presence') test_create_pmuc(q, conn, stream) test_create_pmuc_with_invitee(q, conn, stream) def create_pmuc(q, conn, stream, extra_props=None): """ Request a PMUC just for ourselves. """ props = { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_NONE, cs.CONFERENCE_INITIAL_CHANNELS: dbus.Array([], signature='o'), } if extra_props: props.update(extra_props) call_async(q, conn.Requests, 'CreateChannel', props) # wait for the MUC name, so we can inject a reply r = q.expect('stream-presence') pmuc_name = r.to.split('/', 2)[0] assert re.match( r'^private-chat-\w{8}-\w{4}-\w{4}-\w{4}-\w{12}@conf.localhost$', pmuc_name), pmuc_name stream.send(make_muc_presence('owner', 'moderator', pmuc_name, 'test')) # wait for the method return r = q.expect('dbus-return', method='CreateChannel') assert len(r.value) == 2 path, out_props = r.value assert out_props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT assert out_props[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM assert out_props[cs.TARGET_ID] == pmuc_name assertContains(cs.CHANNEL_IFACE_CONFERENCE, out_props[cs.INTERFACES]) assertEquals(props[cs.CONFERENCE_INITIAL_CHANNELS], out_props[cs.CONFERENCE_INITIAL_CHANNELS]) return pmuc_name, path, out_props def test_create_pmuc(q, conn, stream): pmuc_name, path, props = create_pmuc(q, conn, stream) assertEquals([], props[cs.CONFERENCE_INITIAL_INVITEE_IDS]) assertEquals([], props[cs.CONFERENCE_INITIAL_INVITEE_HANDLES]) def test_create_pmuc_with_invitee(q, conn, stream): # Open an initial 1-to-1 connection props = { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: 'bob@localhost', } call_async(q, conn.Requests, 'EnsureChannel', props) r = q.expect('dbus-return', method='EnsureChannel') assert len(r.value) == 3 yours, path, props = r.value pmuc_name, path, props = create_pmuc(q, conn, stream, { cs.CONFERENCE_INITIAL_CHANNELS: dbus.Array([path], signature='o'), }) # FIXME: check for stream-message containing invite for Bob assertEquals(['bob@localhost'], props[cs.CONFERENCE_INITIAL_INVITEE_IDS]) if __name__ == '__main__': exec_test(test, params={ 'fallback-conference-server': 'conf.localhost' } ) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/muc/banned.py�������������������������������������������������0000644�0001750�0001750�00000001475�12225363340�023415� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Tests the server refusing to let us join a MUC. This is a regression test for <https://bugs.freedesktop.org/show_bug.cgi?id=35120> where Gabble would crash in this situation. """ from gabbletest import exec_test, elem from mucutil import try_to_join_muc import constants as cs import ns MUC = 'deerhoof@evil.lit' def test(q, bus, conn, stream): try_to_join_muc(q, bus, conn, stream, MUC) stream.send( elem('presence', from_=MUC, type='error')( elem(ns.MUC, 'x'), elem('error', code='403', type='auth')( elem(ns.STANZA, 'forbidden'), elem(ns.STANZA, 'text')( u'Access denied by service policy', ) ) )) q.expect('dbus-error', method='CreateChannel', name=cs.BANNED) if __name__ == '__main__': exec_test(test) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/muc/room.py���������������������������������������������������0000664�0001750�0001750�00000016546�12332441362�023151� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test the different ways to request a channel using the Room interface """ from gabbletest import exec_test, make_muc_presence from servicetest import (call_async, EventPattern, assertEquals, assertContains) import constants as cs import dbus import re def create_muc(q, conn, stream, props): call_async(q, conn.Requests, 'CreateChannel', props) r = q.expect('stream-presence') muc_name = r.to.split('/', 2)[0] stream.send(make_muc_presence('owner', 'moderator', muc_name, 'test')) r = q.expect('dbus-return', method='CreateChannel') assertEquals(2, len(r.value)) return r.value[1] def test(q, bus, conn, stream): q.expect('stream-presence') # First create a channel with human-readable name like normal. jid = 'booyakasha@conf.localhost' props = create_muc(q, conn, stream, { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: jid, }) assertEquals(cs.CHANNEL_TYPE_TEXT, props[cs.CHANNEL_TYPE]) assertEquals(cs.HT_ROOM, props[cs.TARGET_HANDLE_TYPE]) assertEquals(jid, props[cs.TARGET_ID]) assertEquals(jid.split('@')[0], props[cs.ROOM_NAME]) assertEquals(jid.split('@')[1], props[cs.ROOM_SERVER]) # Next create a similar human-readable channel but using the new # properties. jid = 'indahouse@conf.localhost' props = create_muc(q, conn, stream, { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.ROOM_NAME: jid.split('@')[0], cs.ROOM_SERVER: jid.split('@')[1], }) assertEquals(cs.CHANNEL_TYPE_TEXT, props[cs.CHANNEL_TYPE]) assertEquals(cs.HT_ROOM, props[cs.TARGET_HANDLE_TYPE]) assertEquals(jid, props[cs.TARGET_ID]) assertEquals(jid.split('@')[0], props[cs.ROOM_NAME]) assertEquals(jid.split('@')[1], props[cs.ROOM_SERVER]) # Next create a similar human-readable channel but using the new # RoomName property and leave out Server. jid = 'indahouse@fallback.conf.localhost' props = create_muc(q, conn, stream, { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.ROOM_NAME: jid.split('@')[0], }) assertEquals(cs.CHANNEL_TYPE_TEXT, props[cs.CHANNEL_TYPE]) assertEquals(cs.HT_ROOM, props[cs.TARGET_HANDLE_TYPE]) assertEquals(jid, props[cs.TARGET_ID]) assertEquals(jid.split('@')[0], props[cs.ROOM_NAME]) assertEquals(jid.split('@')[1], props[cs.ROOM_SERVER]) # Now create a uniquely-named channel. conf_server = 'conf.localhost' props = create_muc(q, conn, stream, { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.ROOM_NAME: '', cs.ROOM_SERVER: conf_server, }) assertEquals(cs.CHANNEL_TYPE_TEXT, props[cs.CHANNEL_TYPE]) assertEquals(cs.HT_ROOM, props[cs.TARGET_HANDLE_TYPE]) assert re.match( r'^private-chat-\w{8}-\w{4}-\w{4}-\w{4}-\w{12}@' + conf_server + '$', props[cs.TARGET_ID]), props[cs.TARGET_ID] assertEquals('', props[cs.ROOM_NAME]) assertEquals(conf_server, props[cs.ROOM_SERVER]) # Now create a uniquely-named channel with no server. conf_server = 'fallback.conf.localhost' props = create_muc(q, conn, stream, { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.ROOM_NAME: '', }) assertEquals(cs.CHANNEL_TYPE_TEXT, props[cs.CHANNEL_TYPE]) assertEquals(cs.HT_ROOM, props[cs.TARGET_HANDLE_TYPE]) assert re.match( r'^private-chat-\w{8}-\w{4}-\w{4}-\w{4}-\w{12}@' + conf_server + '$', props[cs.TARGET_ID]), props[cs.TARGET_ID] assertEquals('', props[cs.ROOM_NAME]) assertEquals(conf_server, props[cs.ROOM_SERVER]) # Now a channel with non-human-readable name that we set ourselves. jid = 'asdf@conf.localhost' props = create_muc(q, conn, stream, { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: jid, cs.ROOM_NAME: '', cs.ROOM_SERVER: 'conf.localhost', }) assertEquals(cs.CHANNEL_TYPE_TEXT, props[cs.CHANNEL_TYPE]) assertEquals(cs.HT_ROOM, props[cs.TARGET_HANDLE_TYPE]) assertEquals(jid, props[cs.TARGET_ID]) assertEquals('', props[cs.ROOM_NAME]) assertEquals(jid.split('@')[1], props[cs.ROOM_SERVER]) # Now a channel with non-human-readable name that we set ourselves # and no server property. jid = 'hjkl@conf.localhost' props = create_muc(q, conn, stream, { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: jid, cs.ROOM_NAME: '', }) assertEquals(cs.CHANNEL_TYPE_TEXT, props[cs.CHANNEL_TYPE]) assertEquals(cs.HT_ROOM, props[cs.TARGET_HANDLE_TYPE]) assertEquals(jid, props[cs.TARGET_ID]) assertEquals('', props[cs.ROOM_NAME]) assertEquals(jid.split('@')[1], props[cs.ROOM_SERVER]) # Now a channel with non-human-readable name (with no conf server # in the TargetID) that we set ourselves and no server property. jid = 'qwerty' props = create_muc(q, conn, stream, { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: jid, cs.ROOM_NAME: '', }) assertEquals(cs.CHANNEL_TYPE_TEXT, props[cs.CHANNEL_TYPE]) assertEquals(cs.HT_ROOM, props[cs.TARGET_HANDLE_TYPE]) assertEquals(jid + '@fallback.conf.localhost', props[cs.TARGET_ID]) assertEquals('', props[cs.ROOM_NAME]) assertEquals('fallback.conf.localhost', props[cs.ROOM_SERVER]) # Now a channel which already exists (any of the above) with # RoomName set to a non-harmful value jid = 'booyakasha@conf.localhost' call_async(q, conn.Requests, 'EnsureChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: jid, cs.ROOM_NAME: '', }) q.expect('dbus-return', method='EnsureChannel') # Now a channel which already exists (any of the above) with # a conflicting RoomName set. jid = 'booyakasha@conf.localhost' call_async(q, conn.Requests, 'EnsureChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: jid, cs.ROOM_NAME: 'happynewyear', }) q.expect('dbus-error', name=cs.INVALID_ARGUMENT, method='EnsureChannel') # Now a channel which already exists (any of the above) with # a non-conflicting Server set. jid = 'booyakasha@conf.localhost' call_async(q, conn.Requests, 'EnsureChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: jid, cs.ROOM_SERVER: 'conf.localhost', }) q.expect('dbus-return', method='EnsureChannel') # Now a channel which already exists (any of the above) with # a conflicting Server set. jid = 'booyakasha@conf.localhost' call_async(q, conn.Requests, 'EnsureChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: jid, cs.ROOM_SERVER: 'lol.conf.localhost', }) q.expect('dbus-error', name=cs.INVALID_ARGUMENT, method='EnsureChannel') if __name__ == '__main__': exec_test(test, params={ 'fallback-conference-server': 'fallback.conf.localhost' } ) ����������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/muc/kicked.py�������������������������������������������������0000664�0001750�0001750�00000003217�12332441362�023416� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Tests the user being kicked from a MUC. Another symptom of the underlying bug behind <https://bugs.freedesktop.org/show_bug.cgi?id=35120> was that this would crash. """ from servicetest import assertEquals, assertContains from gabbletest import exec_test, elem from mucutil import join_muc import constants as cs import ns MUC = 'deerhoof@evil.lit' def test(q, bus, conn, stream): # The user happily joins a MUC _, chan, _, _ = join_muc(q, bus, conn, stream, MUC) muc_self_handle = chan.Group.GetSelfHandle() muc_self_jid, = conn.InspectHandles(cs.HT_CONTACT, [muc_self_handle]) # But then Bob kicks us. bob_jid = '%s/bob' % MUC bob_handle, = conn.RequestHandles(cs.HT_CONTACT, [bob_jid]) stream.send( elem('presence', from_=muc_self_jid, type='unavailable')( elem(ns.MUC_USER, 'x')( elem('item', affiliation='none', role='none')( elem('actor', jid=bob_jid), elem('reason')( u'bye' ) ), elem('status', code='307'), ) )) mcd_event = q.expect('dbus-signal', signal='MembersChangedDetailed') added, removed, local_pending, remote_pending, details = mcd_event.args assertEquals([], added) assertEquals([muc_self_handle], removed) assertEquals([], local_pending) assertEquals([], remote_pending) assertContains('actor', details) assertEquals(bob_handle, details['actor']) assertEquals(cs.GC_REASON_KICKED, details['change-reason']) assertEquals('bye', details['message']) q.expect('dbus-signal', signal='ChannelClosed') if __name__ == '__main__': exec_test(test) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/muc/roomlist.py�����������������������������������������������0000664�0001750�0001750�00000015417�12332441362�024041� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test MUC support. """ import dbus from gabbletest import make_result_iq, exec_test, sync_stream, disconnect_conn from servicetest import call_async, EventPattern, tp_name_prefix import constants as cs def test(q, bus, conn, stream): event = q.expect('stream-iq', to='localhost', query_ns='http://jabber.org/protocol/disco#items') result = make_result_iq(stream, event.stanza) item = result.firstChildElement().addElement('item') item['jid'] = 'conf.localhost' stream.send(result) event = q.expect('stream-iq', to='conf.localhost', query_ns='http://jabber.org/protocol/disco#info') result = make_result_iq(stream, event.stanza) feature = result.firstChildElement().addElement('feature') feature['var'] = 'http://jabber.org/protocol/muc' identity = result.firstChildElement().addElement('identity') identity['category'] = 'conference' identity['name'] = 'conference service' identity['type'] = 'text' stream.send(result) # Make sure the stream has been processed sync_stream(q, stream) properties = conn.GetAll( tp_name_prefix + '.Connection.Interface.Requests', dbus_interface=dbus.PROPERTIES_IFACE) assert properties.get('Channels') == [], properties['Channels'] assert ({tp_name_prefix + '.Channel.ChannelType': tp_name_prefix + '.Channel.Type.RoomList', tp_name_prefix + '.Channel.TargetHandleType': 0, }, [tp_name_prefix + '.Channel.Type.RoomList.Server'], ) in properties.get('RequestableChannelClasses'),\ properties['RequestableChannelClasses'] call_async(q, conn, 'RequestChannel', tp_name_prefix + '.Channel.Type.RoomList', 0, 0, True) ret, old_sig, new_sig = q.expect_many( EventPattern('dbus-return', method='RequestChannel'), EventPattern('dbus-signal', signal='NewChannel'), EventPattern('dbus-signal', signal='NewChannels'), ) bus = dbus.SessionBus() path1 = ret.value[0] chan = bus.get_object(conn.bus_name, path1) assert new_sig.args[0][0][0] == path1 props = new_sig.args[0][0][1] assert props[tp_name_prefix + '.Channel.ChannelType'] ==\ tp_name_prefix + '.Channel.Type.RoomList' assert props[tp_name_prefix + '.Channel.TargetHandleType'] == 0 assert props[tp_name_prefix + '.Channel.TargetHandle'] == 0 assert props[tp_name_prefix + '.Channel.TargetID'] == '' assert props[tp_name_prefix + '.Channel.Requested'] == True assert props[tp_name_prefix + '.Channel.InitiatorHandle'] \ == conn.GetSelfHandle() assert props[tp_name_prefix + '.Channel.InitiatorID'] \ == 'test@localhost' assert props[tp_name_prefix + '.Channel.Type.RoomList.Server'] == \ 'conf.localhost' assert old_sig.args[0] == path1 assert old_sig.args[1] == tp_name_prefix + '.Channel.Type.RoomList' assert old_sig.args[2] == 0 # handle type assert old_sig.args[3] == 0 # handle assert old_sig.args[4] == 1 # suppress handler # Exercise basic Channel Properties from spec 0.17.7 channel_props = chan.GetAll( tp_name_prefix + '.Channel', dbus_interface=dbus.PROPERTIES_IFACE) assert channel_props.get('TargetHandle') == 0,\ channel_props.get('TargetHandle') assert channel_props['TargetID'] == '', channel_props assert channel_props.get('TargetHandleType') == 0,\ channel_props.get('TargetHandleType') assert channel_props.get('ChannelType') == \ tp_name_prefix + '.Channel.Type.RoomList',\ channel_props.get('ChannelType') assert channel_props['Requested'] == True assert channel_props['InitiatorID'] == 'test@localhost' assert channel_props['InitiatorHandle'] == conn.GetSelfHandle() assert chan.Get( tp_name_prefix + '.Channel.Type.RoomList', 'Server', dbus_interface=dbus.PROPERTIES_IFACE) == \ 'conf.localhost' # FIXME: actually list the rooms! call_async(q, conn.Requests, 'CreateChannel', { tp_name_prefix + '.Channel.ChannelType': tp_name_prefix + '.Channel.Type.RoomList', tp_name_prefix + '.Channel.TargetHandleType': 0, tp_name_prefix + '.Channel.Type.RoomList.Server': 'conference.example.net', }) ret, old_sig, new_sig = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('dbus-signal', signal='NewChannel'), EventPattern('dbus-signal', signal='NewChannels'), ) path2 = ret.value[0] chan = bus.get_object(conn.bus_name, path2) props = ret.value[1] assert props[tp_name_prefix + '.Channel.ChannelType'] ==\ tp_name_prefix + '.Channel.Type.RoomList' assert props[tp_name_prefix + '.Channel.TargetHandleType'] == 0 assert props[tp_name_prefix + '.Channel.TargetHandle'] == 0 assert props[tp_name_prefix + '.Channel.TargetID'] == '' assert props[tp_name_prefix + '.Channel.Requested'] == True assert props[tp_name_prefix + '.Channel.InitiatorHandle'] \ == conn.GetSelfHandle() assert props[tp_name_prefix + '.Channel.InitiatorID'] \ == 'test@localhost' assert props[tp_name_prefix + '.Channel.Type.RoomList.Server'] == \ 'conference.example.net' assert new_sig.args[0][0][0] == path2 assert new_sig.args[0][0][1] == props assert old_sig.args[0] == path2 assert old_sig.args[1] == tp_name_prefix + '.Channel.Type.RoomList' assert old_sig.args[2] == 0 # handle type assert old_sig.args[3] == 0 # handle assert old_sig.args[4] == 1 # suppress handler assert chan.Get( tp_name_prefix + '.Channel.Type.RoomList', 'Server', dbus_interface=dbus.PROPERTIES_IFACE) == \ 'conference.example.net' # FIXME: actually list the rooms! call_async(q, conn.Requests, 'EnsureChannel', { tp_name_prefix + '.Channel.ChannelType': tp_name_prefix + '.Channel.Type.RoomList', tp_name_prefix + '.Channel.TargetHandleType': 0, tp_name_prefix + '.Channel.Type.RoomList.Server': 'conference.example.net', }) ret = q.expect('dbus-return', method='EnsureChannel') yours, ensured_path, ensured_props = ret.value assert not yours assert ensured_path == path2, (ensured_path, path2) disconnect_conn(q, conn, stream, [ EventPattern('dbus-signal', signal='Closed', path=path1), EventPattern('dbus-signal', signal='Closed', path=path2), EventPattern('dbus-signal', signal='ChannelClosed', args=[path1]), EventPattern('dbus-signal', signal='ChannelClosed', args=[path2])]) if __name__ == '__main__': exec_test(test) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/muc/test-ensure.py��������������������������������������������0000664�0001750�0001750�00000012314�12332441362�024440� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test that EnsureChannel works for MUCs, particularly in the case when there are several pending requests for the same MUC. """ from gabbletest import make_result_iq, exec_test, make_muc_presence from servicetest import (call_async, EventPattern, assertContains, assertEquals) import constants as cs def test(q, bus, conn, stream): # Need to call this asynchronously as it involves Gabble sending us a # query. jids = ['chat@conf.localhost', 'chien@conf.localhost'] call_async(q, conn, 'RequestHandles', 2, jids) event = q.expect('dbus-return', method='RequestHandles') room_handles = event.value[0] test_create_ensure(q, conn, bus, stream, jids[0], room_handles[0]) test_ensure_ensure(q, conn, bus, stream, jids[1], room_handles[1]) def test_create_ensure(q, conn, bus, stream, room_jid, room_handle): # Call both Create and Ensure for the same channel. call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_HANDLE: room_handle, }) call_async(q, conn.Requests, 'EnsureChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_HANDLE: room_handle, }) mc, _ = q.expect_many( EventPattern('dbus-signal', signal='MembersChanged'), EventPattern('stream-presence', to=('%s/test' % room_jid))) msg, added, removed, local_pending, remote_pending, actor, reason = mc.args assert added == [], mc.args assert removed == [], mc.args assert local_pending == [], mc.args assert len(remote_pending) == 1, mc.args # Send presence for other member of room. stream.send(make_muc_presence('owner', 'moderator', room_jid, 'bob')) # Send presence for own membership of room. stream.send(make_muc_presence('none', 'participant', room_jid, 'test')) mc = q.expect('dbus-signal', signal='MembersChanged') msg, added, removed, local_pending, remote_pending, actor, reason = mc.args assert len(added) == 2, mc.args assert removed == [], mc.args assert local_pending == [], mc.args assert remote_pending == [], mc.args members = conn.InspectHandles(1, added) members.sort() assert members == ['%s/bob' % room_jid, '%s/test' % room_jid], members create_event, ensure_event = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('dbus-return', method='EnsureChannel')) assert len(create_event.value) == 2 c_path, c_props = create_event.value assert len(ensure_event.value) == 3 yours, e_path, e_props = ensure_event.value assert c_path == e_path, (c_path, e_path) assert c_props == e_props, (c_props, e_props) assert not yours assertContains('text/plain', c_props[cs.SUPPORTED_CONTENT_TYPES]) assertEquals(0, c_props[cs.MESSAGE_PART_SUPPORT_FLAGS]) assertEquals( cs.DELIVERY_REPORTING_SUPPORT_FLAGS_RECEIVE_FAILURES | cs.DELIVERY_REPORTING_SUPPORT_FLAGS_RECEIVE_SUCCESSES, c_props[cs.DELIVERY_REPORTING_SUPPORT]) def test_ensure_ensure(q, conn, bus, stream, room_jid, room_handle): # Call Ensure twice for the same channel. call_async(q, conn.Requests, 'EnsureChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_HANDLE: room_handle, }) call_async(q, conn.Requests, 'EnsureChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_HANDLE: room_handle, }) mc, _ = q.expect_many( EventPattern('dbus-signal', signal='MembersChanged'), EventPattern('stream-presence', to=('%s/test' % room_jid))) msg, added, removed, local_pending, remote_pending, actor, reason = mc.args assert added == [], mc.args assert removed == [], mc.args assert local_pending == [], mc.args assert len(remote_pending) == 1, mc.args # Send presence for other member of room. stream.send(make_muc_presence('owner', 'moderator', room_jid, 'bob')) # Send presence for own membership of room. stream.send(make_muc_presence('none', 'participant', room_jid, 'test')) mc = q.expect('dbus-signal', signal='MembersChanged') msg, added, removed, local_pending, remote_pending, actor, reason = mc.args assert len(added) == 2, mc.args assert removed == [], mc.args assert local_pending == [], mc.args assert remote_pending == [], mc.args members = conn.InspectHandles(1, added) members.sort() assert members == ['%s/bob' % room_jid, '%s/test' % room_jid], members # We should get two EnsureChannel returns es = [] while len(es) < 2: e = q.expect('dbus-return', method='EnsureChannel') es.append(e) e1, e2 = es assert len(e1.value) == 3 yours1, path1, props1 = e1.value assert len(e2.value) == 3 yours2, path2, props2 = e2.value # Exactly one Ensure should get Yours=True. assert (yours1 == (not yours2)) assert path1 == path2, (path1, path2) assert props1 == props2, (props1, props2) if __name__ == '__main__': exec_test(test) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/muc/subject.py������������������������������������������������0000664�0001750�0001750�00000015132�12332441362�023622� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test Channel.Interface.Subject on MUC channels """ import dbus from twisted.words.xish import domish from gabbletest import exec_test, make_result_iq, make_muc_presence from servicetest import (EventPattern, assertEquals, assertLength, assertContains, call_async) import constants as cs import ns from mucutil import join_muc def test(q, bus, conn, stream): # 3x2x2 possible combinations of change_subject, send_first, moderator: # unrolling the loop here so we'll get better Python tracebacks on failure test_subject(q, bus, conn, stream, None, False, False) test_subject(q, bus, conn, stream, None, False, True) test_subject(q, bus, conn, stream, None, True, False) test_subject(q, bus, conn, stream, None, False, True) test_subject(q, bus, conn, stream, True, False, False) test_subject(q, bus, conn, stream, True, False, True) test_subject(q, bus, conn, stream, True, True, False) test_subject(q, bus, conn, stream, True, False, True) test_subject(q, bus, conn, stream, False, False, False) test_subject(q, bus, conn, stream, False, False, True) test_subject(q, bus, conn, stream, False, True, False) test_subject(q, bus, conn, stream, False, False, True) def check_subject_props(chan, subject_str, actor, flags, signal=None): if signal is not None: assertEquals(subject_str, signal.args[0]) assertEquals(actor, signal.args[1]) assertEquals(flags, signal.args[3]) props = chan.GetAll(cs.CHANNEL_IFACE_SUBJECT, dbus_interface=dbus.PROPERTIES_IFACE) subject = props['Subject'] subject_actor = props['Actor'] subject_can_set = props['CanSet'] def test_subject(q, bus, conn, stream, change_subject, send_first, moderator): room = 'test@conf.localhost' room_handle, chan, path, props, disco = join_muc(q, bus, conn, stream, room, also_capture=[EventPattern('stream-iq', iq_type='get', query_name='query', query_ns=ns.DISCO_INFO, to=room)], role=(moderator and 'moderator' or 'participant')) assert chan.Properties.Get(cs.CHANNEL_IFACE_SUBJECT, "CanSet") if send_first: # Someone sets a subject. message = domish.Element((None, 'message')) message['from'] = room + '/bob' message['type'] = 'groupchat' message.addElement('subject', content='Testing') stream.send(message) q.expect('dbus-signal', interface=cs.PROPERTIES_IFACE, signal='PropertiesChanged', predicate=lambda e: e.args[0] == cs.CHANNEL_IFACE_SUBJECT) check_subject_props(chan, 'Testing', room + '/bob', True) # Reply to the disco iq = make_result_iq(stream, disco.stanza) query = iq.firstChildElement() feat = query.addElement('feature') feat['var'] = 'muc_public' x = query.addElement((ns.X_DATA, 'x')) x['type'] = 'result' if change_subject is not None: # When fd.o #13157 has been fixed, this will actually do something. field = x.addElement('field') field['var'] = 'muc#roomconfig_changesubject' field.addElement('value', content=(change_subject and 'true' or 'false')) stream.send(iq) # Someone sets a subject. message = domish.Element((None, 'message')) message['from'] = room + '/bob' message['type'] = 'groupchat' message.addElement('subject', content='lalala') stream.send(message) q.expect('dbus-signal', interface=cs.PROPERTIES_IFACE, signal='PropertiesChanged', predicate=lambda e: e.args[0] == cs.CHANNEL_IFACE_SUBJECT) check_subject_props(chan, 'lalala', room + '/bob', True) # test changing the subject call_async(q, chan, 'SetSubject', 'le lolz', dbus_interface=cs.CHANNEL_IFACE_SUBJECT) e = q.expect('stream-message', to=room) elem = e.stanza assertEquals('groupchat', elem['type']) assertEquals(1, len(elem.children)) assertEquals(elem.children[0].name, 'subject') assertEquals(str(elem.children[0]), 'le lolz') elem['from'] = room + '/test' stream.send(elem) q.expect_many(EventPattern('dbus-signal', interface=cs.PROPERTIES_IFACE, signal='PropertiesChanged', predicate=lambda e: e.args[0] == cs.CHANNEL_IFACE_SUBJECT), EventPattern('dbus-return', method='SetSubject'), ) check_subject_props(chan, 'le lolz', room + '/test', True) # Test changing the subject and getting an error back. call_async(q, chan, 'SetSubject', 'CHICKEN MAN', dbus_interface=cs.CHANNEL_IFACE_SUBJECT) e = q.expect('stream-message', to=room) elem = e.stanza elem['from'] = room elem['type'] = 'error' error = elem.addElement((None, 'error')) error['type'] = 'auth' error.addElement((ns.STANZA, 'forbidden')) stream.send(elem) q.expect('dbus-error', method='SetSubject', name=cs.PERMISSION_DENIED) # Test changing the subject and getting an error back which doesn't echo # the <subject> element. call_async(q, chan, 'SetSubject', 'CHICKEN MAN', dbus_interface=cs.CHANNEL_IFACE_SUBJECT) e = q.expect('stream-message', to=room) message = domish.Element((None, 'message')) message['from'] = room message['id'] = e.stanza['id'] message['type'] = 'error' error = message.addElement((None, 'error')) error.addElement((ns.STANZA, 'forbidden')) stream.send(message) q.expect('dbus-error', method='SetSubject', name=cs.PERMISSION_DENIED) # Test changing the subject just before we leave the room (and hence not # getting a reply). While we're here, check that you can't have more than # one call in flight at a time. call_async(q, chan, 'SetSubject', 'le lolz', dbus_interface=cs.CHANNEL_IFACE_SUBJECT) e = q.expect('stream-message', to=room) call_async(q, chan, 'SetSubject', 'le lolz', dbus_interface=cs.CHANNEL_IFACE_SUBJECT) q.expect('dbus-error', method='SetSubject', name=cs.NOT_AVAILABLE) chan.Close() event = q.expect('stream-presence', to=room + '/test') elem = event.stanza assertEquals('unavailable', elem['type']) q.expect('dbus-error', method='SetSubject', name=cs.CANCELLED) call_async(q, chan, 'SetSubject', 'how about now?', dbus_interface=cs.CHANNEL_IFACE_SUBJECT) q.expect('dbus-error', method='SetSubject', name=cs.NOT_AVAILABLE) # The MUC confirms that we've left the room. echo = make_muc_presence('member', 'none', room, 'test') echo['type'] = 'unavailable' stream.send(echo) q.expect('dbus-signal', signal='ChannelClosed') if __name__ == '__main__': exec_test(test) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/muc/test-muc-ownership.py�������������������������������������0000664�0001750�0001750�00000007702�12332441362�025744� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test support for the HANDLE_OWNERS_NOT_AVAILABLE group flag, and calling GetHandleOwners on MUC members. By default, MUC channels should have the flag set. The flag should be unset when presence is received that includes the MUC JID's owner JID. """ import dbus from gabbletest import make_result_iq, exec_test, make_muc_presence from servicetest import ( call_async, EventPattern, assertEquals, assertFlagsSet, assertFlagsUnset, wrap_channel, ) import constants as cs def test(q, bus, conn, stream): self_handle = conn.GetSelfHandle() room_handle = conn.RequestHandles(cs.HT_ROOM, ['chat@conf.localhost'])[0] call_async(q, conn, 'RequestChannel', cs.CHANNEL_TYPE_TEXT, cs.HT_ROOM, room_handle, True) gfc, _, _, _ = q.expect_many( # Initial group flags EventPattern('dbus-signal', signal='GroupFlagsChanged', predicate=lambda e: e.args[0] != 0), EventPattern('dbus-signal', signal='MembersChanged', args=[u'', [], [], [], [2], 0, 0]), # Removing CAN_ADD EventPattern('dbus-signal', signal='GroupFlagsChanged', args = [0, cs.GF_CAN_ADD], predicate=lambda e: e.args[0] == 0), EventPattern('stream-presence', to='chat@conf.localhost/test')) assert gfc.args[1] == 0 # Send presence for anonymous other member of room. stream.send(make_muc_presence('owner', 'moderator', 'chat@conf.localhost', 'bob')) # Send presence for anonymous other member of room (2) stream.send(make_muc_presence('owner', 'moderator', 'chat@conf.localhost', 'brian')) # Send presence for nonymous other member of room. stream.send(make_muc_presence('none', 'participant', 'chat@conf.localhost', 'che', 'che@foo.com')) # Send presence for nonymous other member of room (2) stream.send(make_muc_presence('none', 'participant', 'chat@conf.localhost', 'chris', 'chris@foo.com')) # Send presence for own membership of room. stream.send(make_muc_presence('none', 'participant', 'chat@conf.localhost', 'test')) # Since we received MUC presence that contains an owner JID, the # OWNERS_NOT_AVAILABLE flag should be removed. event = q.expect('dbus-signal', signal='GroupFlagsChanged', args = [0, cs.GF_HANDLE_OWNERS_NOT_AVAILABLE ]) event = q.expect('dbus-signal', signal='HandleOwnersChanged') owners = event.args[0] event = q.expect('dbus-signal', signal='MembersChanged') added = event.args[1] [test, bob, brian, che, che_owner, chris, chris_owner] = \ conn.RequestHandles(cs.HT_CONTACT, [ 'chat@conf.localhost/test', 'chat@conf.localhost/bob', 'chat@conf.localhost/brian', 'chat@conf.localhost/che', 'che@foo.com', 'chat@conf.localhost/chris', 'chris@foo.com', ]) expected_members = sorted([test, bob, brian, che, chris]) expected_owners = { test: self_handle, bob: 0, brian: 0, che: che_owner, chris: chris_owner } assertEquals(expected_members, sorted(added)) assertEquals(expected_owners, owners) event = q.expect('dbus-return', method='RequestChannel') chan = wrap_channel(bus.get_object(conn.bus_name, event.value[0]), 'Text') # Exercise GetHandleOwners assertEquals([che_owner, chris_owner], chan.Group.GetHandleOwners([che, chris])) # Exercise D-Bus properties all = chan.Properties.GetAll(cs.CHANNEL_IFACE_GROUP) assert all[u'LocalPendingMembers'] == [], all assert sorted(all[u'Members']) == expected_members, all assert all[u'RemotePendingMembers'] == [], all assert all[u'SelfHandle'] == test, all assert all[u'HandleOwners'] == expected_owners, all flags = all[u'GroupFlags'] assertFlagsSet(cs.GF_PROPERTIES | cs.GF_CHANNEL_SPECIFIC_HANDLES, flags) assertFlagsUnset(cs.GF_HANDLE_OWNERS_NOT_AVAILABLE, flags) if __name__ == '__main__': exec_test(test) ��������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/muc/room-config.py��������������������������������������������0000664�0001750�0001750�00000035014�12332441362�024403� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# vim: fileencoding=utf-8 : """ Test the RoomConfig interface on MUC channels. """ import dbus from twisted.words.xish import xpath from gabbletest import ( exec_test, make_result_iq, acknowledge_iq, make_muc_presence, request_muc_handle, sync_stream, disconnect_conn) from servicetest import ( call_async, wrap_channel, EventPattern, assertEquals, assertSameSets, assertContains, ) from mucutil import join_muc import constants as cs import ns ROOM_NAME = "A place to bury strangers" ROOM_DESCRIPTION = "I hate noise-rock." def get_default_form(): return { 'password': [''], 'password_protected': ['0'], 'muc#roomconfig_persistentroom': ['0'], # We have to include this field here to convince Gabble that the # description can be modified by owners. As far as wjt can # determine, this is a question of uneven server support: see # 6f20080. 'muc#roomconfig_roomdesc': [ROOM_DESCRIPTION], # Gabble doesn't understand this field; we include it to verify # that Gabble can correctly echo multi-value fields. 'muc#roomconfig_presencebroadcast': ['moderator', 'participant', 'visitor'], } def parse_form(stanza): fields = xpath.queryForNodes('/iq/query/x/field', stanza) form = {} for field in fields: values = xpath.queryForNodes('/field/value', field) form[field['var']] = [str(v) for v in values] return form def add_field(elem, type, var, value): field = elem.addElement('field') if type is not None: field['type'] = type field['var'] = var value = field.addElement('value', content=value) def handle_muc_owner_get_iq(stream, stanza): iq = make_result_iq(stream, stanza) query = iq.firstChildElement() x = query.addElement(('jabber:x:data', 'x')) x['type'] = 'form' for var, values in get_default_form().iteritems(): if len(values) > 1: field = x.addElement('field') field['type'] = 'list-multi' field['var'] = var for v in values: field.addElement('value', content=v) field.addElement('option', content=v) elif values[0] == '0' or values[0] == '1': add_field(x, 'boolean', var, values[0]) else: add_field(x, 'text', var, values[0]) stream.send(iq) def handle_muc_owner_set_iq(stream, stanza, fields): form = parse_form(stanza) # Check that Gabble echoed back the fields it didn't understand (or want to # change) with their previous values. expected_form = get_default_form() expected_form.update(fields) assertEquals(expected_form, form) acknowledge_iq(stream, stanza) def handle_disco_info_iq(stream, stanza): iq = make_result_iq(stream, stanza) query = iq.firstChildElement() # Title identity = query.addElement('identity') identity['category'] = 'conference' identity['type'] = 'text' identity['name'] = ROOM_NAME for var in [ns.MUC, 'muc_anonymous', # Anonymous 'muc_open', # ¬InviteOnly # Limit lives in the data form 'muc_moderated', # Moderated # Title is above # Description is below 'muc_temporary', # ¬Persistent 'muc_hidden', # Private 'muc_unsecure', # ¬PasswordProtected # Password is in the owner form. ]: f = query.addElement('feature') f['var'] = var # Description x = query.addElement((ns.X_DATA, 'x')) x['type'] = 'result' add_field(x, 'hidden', 'FORM_TYPE', ns.MUC_ROOMINFO) add_field(x, None, 'muc#roominfo_description', ROOM_DESCRIPTION) stream.send(iq) def test_some_stuff(q, bus, conn, stream): _, text_chan, _, _, disco_iq, owner_iq, _ = join_muc(q, bus, conn, stream, 'chat@conf.localhost', role='moderator', affiliation='owner', also_capture=[ EventPattern('stream-iq', to='chat@conf.localhost', iq_type='get', query_ns=ns.DISCO_INFO), EventPattern('stream-iq', to='chat@conf.localhost', iq_type='get', query_ns=ns.MUC_OWNER), # We discovered that we're an owner. Emitting a signal seems # acceptable, although technically this happens before the channel # request finishes so the channel could just as well not be on the bus. EventPattern('dbus-signal', signal='PropertiesChanged', args=[cs.CHANNEL_IFACE_ROOM_CONFIG, {'CanUpdateConfiguration': True}, [] ]), ]) # This tells Gabble that the MUC is well-behaved and lets owners modify the # room description. Technically we could also pull the description out of # here, but as an implementation detail we only read configuration out of # the disco reply. handle_muc_owner_get_iq(stream, owner_iq.stanza) pc = q.expect('dbus-signal', signal='PropertiesChanged', predicate=lambda e: e.args[0] == cs.CHANNEL_IFACE_ROOM_CONFIG) _, changed, invalidated = pc.args assertEquals(['MutableProperties'], changed.keys()) assertContains('Description', changed['MutableProperties']) handle_disco_info_iq(stream, disco_iq.stanza) pc = q.expect('dbus-signal', signal='PropertiesChanged', predicate=lambda e: e.args[0] == cs.CHANNEL_IFACE_ROOM_CONFIG) q.expect('dbus-signal', signal='PropertiesChanged', args=[cs.CHANNEL_IFACE_ROOM_CONFIG, {'ConfigurationRetrieved': True}, [] ]) _, changed, invalidated = pc.args assertEquals( { 'Anonymous': True, 'Moderated': True, 'Title': ROOM_NAME, 'Description': ROOM_DESCRIPTION, 'Private': True, }, changed) assertEquals([], invalidated) config = text_chan.Properties.GetAll(cs.CHANNEL_IFACE_ROOM_CONFIG) # Verify that all of the config properties (besides the password ones) # correspond to the flags set in handle_disco_info_iq(). assertEquals(True, config['Anonymous']) assertEquals(False, config['InviteOnly']) assertEquals(0, config['Limit']) assertEquals(True, config['Moderated']) assertEquals(ROOM_NAME, config['Title']) assertEquals(ROOM_DESCRIPTION, config['Description']) assertEquals(False, config['Persistent']) assertEquals(True, config['Private']) # This is affirmed to be false both by the disco reply and by the muc#owner # reply. assertEquals(False, config['PasswordProtected']) # This comes from the muc#owner reply. assertEquals('', config['Password']) # We're a room owner, so we should be able to modify the room configuration assertEquals(True, config['CanUpdateConfiguration']) assertSameSets( ['Anonymous', 'InviteOnly', # TODO: when we understand member limit fields, add Limit 'Moderated', 'Title', 'Description', 'Persistent', 'Private', 'PasswordProtected', 'Password', ], config['MutableProperties']) props = dbus.Dictionary( { 'Password': 'foo', 'PasswordProtected': True, }, signature='sv') call_async(q, text_chan.RoomConfig1, 'UpdateConfiguration', props) event = q.expect('stream-iq', to='chat@conf.localhost', iq_type='get', query_ns=ns.MUC_OWNER) handle_muc_owner_get_iq(stream, event.stanza) event = q.expect('stream-iq', to='chat@conf.localhost', iq_type='set', query_ns=ns.MUC_OWNER) handle_muc_owner_set_iq(stream, event.stanza, {'password': ['foo'], 'password_protected': ['1'], }) pc, _ = q.expect_many( EventPattern('dbus-signal', signal='PropertiesChanged', predicate=lambda e: e.args[0] == cs.CHANNEL_IFACE_ROOM_CONFIG), EventPattern('dbus-return', method='UpdateConfiguration'), ) _, changed, invalidated = pc.args assertEquals(props, changed) assertEquals([], invalidated) config = text_chan.Properties.GetAll(cs.CHANNEL_IFACE_ROOM_CONFIG) assertEquals(True, config['PasswordProtected']) assertEquals('foo', config['Password']) # Check unknown fields are rejected. props = dbus.Dictionary( { 'PasswordProtected': True, 'Riding on a donkey': True, }, signature='sv') call_async(q, text_chan.RoomConfig1, 'UpdateConfiguration', props) q.expect('dbus-error', name=cs.INVALID_ARGUMENT) # Check that mis-typed fields are rejected. props = dbus.Dictionary( { 'PasswordProtected': 'foo', 'Password': True, }, signature='sv') call_async(q, text_chan.RoomConfig1, 'UpdateConfiguration', props) q.expect('dbus-error', name=cs.INVALID_ARGUMENT) # Updating no fields should be a no-op, and not wait on any network # traffic. text_chan.RoomConfig1.UpdateConfiguration({}) def test_role_changes(q, bus, conn, stream): # The test user joins a room. Bob is an owner (and moderator); the test # user starts out with no affiliation and the rôle of participant. MUC = 'aoeu@snth' _, chan, _, immutable_props, disco = join_muc(q, bus, conn, stream, MUC, role='participant', also_capture=[ EventPattern('stream-iq', to=MUC, iq_type='get', query_ns=ns.DISCO_INFO), ]) assertContains(cs.CHANNEL_IFACE_ROOM_CONFIG, immutable_props[cs.INTERFACES]) handle_disco_info_iq(stream, disco.stanza) q.expect('dbus-signal', signal='PropertiesChanged', args=[cs.CHANNEL_IFACE_ROOM_CONFIG, {'ConfigurationRetrieved': True}, [] ]) # If we try to change the configuration, Gabble should say no: it knows # we're not allowed to do that. call_async(q, chan.RoomConfig1, 'UpdateConfiguration', {}) q.expect('dbus-error', name=cs.PERMISSION_DENIED) config = chan.Properties.GetAll(cs.CHANNEL_IFACE_ROOM_CONFIG) assert not config['CanUpdateConfiguration'], config # If we acquire affiliation='owner', this should be signalled as our # becoming able to modify the channel configuration. stream.send(make_muc_presence('owner', 'moderator', MUC, 'test')) q.expect('dbus-signal', signal='PropertiesChanged', args=[cs.CHANNEL_IFACE_ROOM_CONFIG, {'CanUpdateConfiguration': True}, [] ]) # Due to silliness, Gabble has to grab the owner configuration form to see # whether it's possible to change the room description. owner_iq = q.expect('stream-iq', to=MUC, iq_type='get', query_ns=ns.MUC_OWNER) handle_muc_owner_get_iq(stream, owner_iq.stanza) # Bob's ownership rights being taken away should have no effect. stream.send(make_muc_presence('none', 'participant', MUC, 'bob')) # So now we're an owner, and CanUpdateConfiguration is True, we should be # able to change some configuration. props = dbus.Dictionary( { 'Persistent': True, }, signature='sv') call_async(q, chan.RoomConfig1, 'UpdateConfiguration', props) owner_iq = q.expect('stream-iq', to=MUC, iq_type='get', query_ns=ns.MUC_OWNER) handle_muc_owner_get_iq(stream, owner_iq.stanza) event = q.expect('stream-iq', to=MUC, iq_type='set', query_ns=ns.MUC_OWNER) handle_muc_owner_set_iq(stream, event.stanza, {'muc#roomconfig_persistentroom': ['1']}) q.expect_many( EventPattern('dbus-return', method='UpdateConfiguration'), EventPattern('dbus-signal', signal='PropertiesChanged', args=[cs.CHANNEL_IFACE_ROOM_CONFIG, {'Persistent': True}, [] ])) # If we lose our affiliation, that should be signalled too. stream.send(make_muc_presence('none', 'participant', MUC, 'test')) q.expect('dbus-signal', signal='PropertiesChanged', args=[cs.CHANNEL_IFACE_ROOM_CONFIG, {'CanUpdateConfiguration': False}, [] ]) # Gabble should once again reject attempts to change the configuration call_async(q, chan.RoomConfig1, 'UpdateConfiguration', {}) q.expect('dbus-error', name=cs.PERMISSION_DENIED) def test_broken_server(q, bus, conn, stream): MUC = 'bro@ken' _, chan, _ , _ = join_muc(q, bus, conn, stream, MUC, affiliation='owner') owner_iq = q.expect('stream-iq', to=MUC, iq_type='get', query_ns=ns.MUC_OWNER) handle_muc_owner_get_iq(stream, owner_iq.stanza) call_async(q, chan.RoomConfig1, 'UpdateConfiguration', {'Private': False}) e = q.expect('stream-iq', to=MUC, iq_type='get', query_ns=ns.MUC_OWNER) handle_muc_owner_get_iq(stream, e.stanza) # The server doesn't actually have a form field for configuring whether the # room is private or not. q.expect('dbus-error', method='UpdateConfiguration', name=cs.SERVICE_CONFUSED) def test_disconnect_during_update_configuration(q, bus, conn, stream): """ Test disconnecting while a pair of UpdateConfiguration requests are in flight: one waiting for the muc#owner form, and the other waiting for its changes to be acked. """ def join_me_up_buttercup(muc): _, chan, _, _ = join_muc(q, bus, conn, stream, muc, affiliation='owner') # Gabble grabs the owner configuration form to see whether it's # possible to change the room description. owner_iq = q.expect('stream-iq', to=muc, iq_type='get', query_ns=ns.MUC_OWNER) handle_muc_owner_get_iq(stream, owner_iq.stanza) call_async(q, chan.RoomConfig1, 'UpdateConfiguration', {'Persistent': True}) e = q.expect('stream-iq', to=muc, iq_type='get', query_ns=ns.MUC_OWNER) return chan, e ONE = '1@ttt' one, _ = join_me_up_buttercup(ONE) TWO = '2@ttt' two, e = join_me_up_buttercup(TWO) handle_muc_owner_get_iq(stream, e.stanza) q.expect('stream-iq', to=TWO, iq_type='set', query_ns=ns.MUC_OWNER) disconnect_conn(q, conn, stream, expected_after=[ # Buh. We can't match on paths or on message serials … but we know # there are two of them! EventPattern('dbus-error', method='UpdateConfiguration', name=cs.CANCELLED), EventPattern('dbus-error', method='UpdateConfiguration', name=cs.CANCELLED), ]) def test(q, bus, conn, stream): test_some_stuff(q, bus, conn, stream) test_role_changes(q, bus, conn, stream) test_broken_server(q, bus, conn, stream) test_disconnect_during_update_configuration(q, bus, conn, stream) if __name__ == '__main__': exec_test(test) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/muc/test-muc-alias.py�����������������������������������������0000664�0001750�0001750�00000003234�12332441362�025013� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test that our alias is used to create MUC JIDs. """ from gabbletest import exec_test, make_muc_presence, request_muc_handle, \ expect_and_handle_get_vcard, expect_and_handle_set_vcard from servicetest import call_async, EventPattern import constants as cs def test(q, bus, conn, stream): expect_and_handle_get_vcard(q, stream) self_handle = conn.GetSelfHandle() conn.Aliasing.SetAliases({self_handle: 'lala'}) expect_and_handle_set_vcard(q, stream) event = q.expect('dbus-signal', signal='AliasesChanged', args=[[(self_handle, u'lala')]]) room_jid = 'chat@conf.localhost' room_handle = request_muc_handle(q, conn, stream, room_jid) call_async(q, conn, 'RequestChannel', cs.CHANNEL_TYPE_TEXT, cs.HT_ROOM, room_handle, True) gfc, _, _ = q.expect_many( EventPattern('dbus-signal', signal='GroupFlagsChanged'), EventPattern('dbus-signal', signal='MembersChanged', args=[u'', [], [], [], [2], 0, 0]), EventPattern('stream-presence', to='%s/lala' % room_jid)) assert gfc.args[1] == 0 # Send presence for other member of room. stream.send(make_muc_presence('owner', 'moderator', room_jid, 'bob')) # Send presence for own membership of room. stream.send(make_muc_presence('none', 'participant', room_jid, 'lala')) event = q.expect('dbus-signal', signal='MembersChanged', args=[u'', [2, 3], [], [], [], 0, 0]) assert conn.InspectHandles(1, [2]) == ['chat@conf.localhost/lala'] assert conn.InspectHandles(1, [3]) == ['chat@conf.localhost/bob'] event = q.expect('dbus-return', method='RequestChannel') if __name__ == '__main__': exec_test(test) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/muc/test-muc-invitation.py������������������������������������0000664�0001750�0001750�00000010735�12332441362�026112� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test MUC invitations. """ import dbus from twisted.words.xish import domish, xpath from gabbletest import exec_test, make_muc_presence from servicetest import call_async, EventPattern import constants as cs def test(q, bus, conn, stream): # Bob has invited us to an activity. message = domish.Element((None, 'message')) message['from'] = 'chat@conf.localhost' message['to'] = 'test@localhost' x = message.addElement(('http://jabber.org/protocol/muc#user', 'x')) invite = x.addElement((None, 'invite')) invite['from'] = 'bob@localhost' reason = invite.addElement((None, 'reason')) reason.addContent('No good reason') stream.send(message) event = q.expect('dbus-signal', signal='NewChannel') assert event.args[1] == cs.CHANNEL_TYPE_TEXT assert event.args[2] == 2 # handle type assert event.args[3] == 1 # handle room_handle = 1 text_chan = bus.get_object(conn.bus_name, event.args[0]) group_iface = dbus.Interface(text_chan, cs.CHANNEL_IFACE_GROUP) members = group_iface.GetMembers() local_pending = group_iface.GetLocalPendingMembers() remote_pending = group_iface.GetRemotePendingMembers() assert len(members) == 1 assert conn.InspectHandles(1, members)[0] == 'bob@localhost' bob_handle = members[0] assert len(local_pending) == 1 # FIXME: the username-part-is-nickname assumption assert conn.InspectHandles(1, local_pending)[0] == \ 'chat@conf.localhost/test' assert len(remote_pending) == 0 room_self_handle = group_iface.GetSelfHandle() assert room_self_handle == local_pending[0] channel_props = text_chan.GetAll( cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE) assert channel_props['TargetID'] == 'chat@conf.localhost', channel_props assert channel_props['Requested'] == False assert channel_props['InitiatorID'] == 'bob@localhost' assert channel_props['InitiatorHandle'] == bob_handle # set ourselves to away and back again, to check that we don't send any # presence to the MUC before the invite has been accepted conn.SimplePresence.SetPresence('away', 'failure') conn.SimplePresence.SetPresence('available', 'success') # accept the invitation call_async(q, group_iface, 'AddMembers', [room_self_handle], 'Oh, OK then') event, event2, _ = q.expect_many( EventPattern('stream-presence', to='chat@conf.localhost/test'), EventPattern('dbus-signal', signal='MembersChanged'), EventPattern('dbus-return', method='AddMembers') ) # check that the status we joined with was available / success elem = event.stanza show = [e for e in elem.elements() if e.name == 'show'] assert not show status = [e for e in elem.elements() if e.name == 'status'][0] assert status assert status.children[0] == u'success' # We are added as remote pending while joining the room. The inviter (Bob) # is removed for now. It will be re-added with his channel specific handle # once we have joined. assert event2.args == ['', [], [bob_handle], [], [room_self_handle], 0, cs.GC_REASON_INVITED] # Send presence for Bob's membership of room. stream.send(make_muc_presence('owner', 'moderator', 'chat@conf.localhost', 'bob')) # Send presence for own membership of room. stream.send(make_muc_presence('owner', 'moderator', 'chat@conf.localhost', 'test')) event = q.expect('dbus-signal', signal='MembersChanged') room_bob_handle = conn.RequestHandles(cs.HT_CONTACT, ['chat@conf.localhost/bob'])[0] assert event.args == ['', [room_self_handle, room_bob_handle], [], [], [], 0, 0] # Test sending an invitation alice_handle = conn.RequestHandles(1, ['alice@localhost'])[0] call_async(q, group_iface, 'AddMembers', [alice_handle], 'I want to test invitations') event = q.expect('stream-message', to='chat@conf.localhost') message = event.stanza x = xpath.queryForNodes('/message/x', message) assert (x is not None and len(x) == 1), repr(x) assert x[0].uri == 'http://jabber.org/protocol/muc#user' invites = xpath.queryForNodes('/x/invite', x[0]) assert (invites is not None and len(invites) == 1), repr(invites) assert invites[0]['to'] == 'alice@localhost' reasons = xpath.queryForNodes('/invite/reason', invites[0]) assert (reasons is not None and len(reasons) == 1), repr(reasons) assert str(reasons[0]) == 'I want to test invitations' if __name__ == '__main__': exec_test(test) �����������������������������������telepathy-gabble-0.18.3/tests/twisted/muc/name-conflict.py������������������������������������������0000664�0001750�0001750�00000020456�12332441362�024707� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# vim: fileencoding=utf-8 : """ Test gabble trying alternative nicknames when the nick you wanted is already in use in a MUC you try to join. """ import dbus from gabbletest import ( exec_test, make_muc_presence, sync_stream, elem, ) from servicetest import ( call_async, unwrap, sync_dbus, assertEquals, assertSameSets, wrap_channel, EventPattern, ) import constants as cs import ns def test(q, bus, conn, stream): test_join(q, bus, conn, stream, 'chat@conf.localhost', False) test_join(q, bus, conn, stream, 'chien@conf.localhost', True) test_gtalk_weirdness(q, bus, conn, stream, 'private-chat-massive-uuid@groupchat.google.com') def test_join(q, bus, conn, stream, room_jid, transient_conflict): """ Tells Gabble to join a MUC, but make the first nick it tries conflict with an existing member of the MUC. If transient_conflict is True, then when Gabble successfully joins with a different nick the originally conflicting user turns out not actually to be in the room (they left while we were retrying). """ # Implementation detail: Gabble uses the first part of your jid (if you # don't have an alias) as your room nickname, and appends an underscore a # few times before giving up. member, member_ = [room_jid + '/' + x for x in ['test', 'test_']] call_async(q, conn.Requests, 'CreateChannel', dbus.Dictionary({ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: room_jid, }, signature='sv')) # Gabble first tries to join as test q.expect('stream-presence', to=member) # MUC says no: there's already someone called test in room_jid presence = elem('presence', from_=member, type='error')( elem(ns.MUC, 'x'), elem('error', type='cancel')( elem(ns.STANZA, 'conflict'), )) stream.send(presence) # Gabble tries again as test_ q.expect('stream-presence', to=member_) # MUC says yes! if not transient_conflict: # Send the other member of the room's presence. This is the nick we # originally wanted. stream.send(make_muc_presence('owner', 'moderator', room_jid, 'test')) # If gabble erroneously thinks the other user's presence is our own, it'll # think that it's got the whole userlist now. If so, syncing here will make # CreateChannel incorrectly return here. sync_stream(q, stream) sync_dbus(bus, q, conn) # Send presence for own membership of room. stream.send(make_muc_presence('none', 'participant', room_jid, 'test_')) # Only now should we have finished joining the room. event = q.expect('dbus-return', method='CreateChannel') path, props = event.value text_chan = wrap_channel(bus.get_object(conn.bus_name, path), 'Text') group_props = unwrap(text_chan.Properties.GetAll(cs.CHANNEL_IFACE_GROUP)) t, t_ = conn.RequestHandles(cs.HT_CONTACT, [member, member_]) # Check that Gabble think our nickname in the room is test_, not test muc_self_handle = group_props['SelfHandle'] assert muc_self_handle == t_, (muc_self_handle, t_, t) members = group_props['Members'] if transient_conflict: # The user we originally conflicted with isn't actually here; check # there's exactly one member (test_). assert members == [t_], (members, t_, t) else: # Check there are exactly two members (test and test_) assertSameSets([t, t_], members) # In either case, there should be no pending members. assert len(group_props['LocalPendingMembers']) == 0, group_props assert len(group_props['RemotePendingMembers']) == 0, group_props # Check that test_'s handle owner is us, and that test (if it's there) has # no owner. handle_owners = group_props['HandleOwners'] assertEquals (conn.GetSelfHandle(), handle_owners[t_]) if not transient_conflict: assertEquals (0, handle_owners[t]) # test that closing the channel results in an unavailable message to the # right jid text_chan.Close() event = q.expect('stream-presence', to=member_) assertEquals('unavailable', event.stanza['type']) def test_gtalk_weirdness(q, bus, conn, stream, room_jid): """ There's a strange bug in the Google Talk MUC server where it sends the <conflict/> stanza twice. This has been reported to their server team; but in any case it triggered a crazy bug in Gabble, so here's a regression test. """ # Implementation detail: Gabble uses the first part of your jid (if you # don't have an alias) as your room nickname, and appends an underscore a # few times before giving up. jids = ['%s/test%s' % (room_jid, x) for x in ['', '_', '__']] member, member_, member__ = jids # Gabble should never get as far as trying to join as 'test__' since # joining as 'test_' will succeed. q.forbid_events([ EventPattern('stream-presence', to=member__) ]) call_async(q, conn.Requests, 'CreateChannel', dbus.Dictionary({ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: room_jid, }, signature='sv')) # Gabble first tries to join as test q.expect('stream-presence', to=member) # Google Talk says no from 'test', twice. presence = elem('presence', from_=member, type='error')( elem(ns.MUC, 'x'), elem('error', type='cancel')( elem(ns.STANZA, 'conflict'), )) stream.send(presence) stream.send(presence) # Gabble should try to join again as test_ q.expect('stream-presence', to=member_) # Since 'test_' is not in use in the MUC, joining should succeed. According # to XEP-0045 §7.1.3 <http://xmpp.org/extensions/xep-0045.html#enter-pres>: # The service MUST first send the complete list of the existing occupants # to the new occupant and only then send the new occupant's own presence # to the new occupant # but groupchat.google.com cheerfully violates this. stream.send(make_muc_presence('none', 'participant', room_jid, 'test_')) # Here's some other random person, who owns the MUC. stream.send(make_muc_presence('owner', 'moderator', room_jid, 'foobar_gmail.com')) # And here's our hypothetical other self. stream.send(make_muc_presence('none', 'participant', room_jid, 'test')) # The Gabble bug makes this time out: because Gabble thinks it's joining as # test__ it ignores the presence for test_, since it's not flagged with # code='210' to say “this is you”. (This is acceptable behaviour by the # server: it only needs to include code='210' if it's assigned the client a # name other than the one it asked for. # # The forbidden stream-presence event above doesn't blow up here because # servicetest doesn't process events on the 'stream-*' queue at all when # we're not waiting for one. But during disconnection in the test clean-up, # the forbidden event is encountered and correctly flagged up. event = q.expect('dbus-return', method='CreateChannel') path, _ = event.value text_chan = wrap_channel(bus.get_object(conn.bus_name, path), 'Text') # As far as Gabble's concerned, the two other participants joined # immediately after we did. We can't request handles for them before we # try to join the MUC, because until we do so, Gabble doesn't know that # room_jid is a MUC, and so considers these three JIDs to be different # resources of the same contact. There is no race between this method # returning and MembersChangedDetailed firing, because libdbus reorders # messages when you make blocking calls. handle, handle_, handle__, foobar_handle = conn.RequestHandles( cs.HT_CONTACT, jids + ['%s/foobar_gmail.com' % room_jid]) q.expect('dbus-signal', signal='MembersChangedDetailed', predicate=lambda e: e.args[0:4] == [[foobar_handle], [], [], []]) q.expect('dbus-signal', signal='MembersChangedDetailed', predicate=lambda e: e.args[0:4] == [[handle], [], [], []]) group_props = text_chan.Properties.GetAll(cs.CHANNEL_IFACE_GROUP) assertEquals(handle_, group_props['SelfHandle']) assertSameSets([handle, handle_, foobar_handle], group_props['Members']) if __name__ == '__main__': exec_test(test) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/muc/avatars.py������������������������������������������������0000664�0001750�0001750�00000014452�12332441362�023630� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# vim: set fileencoding=utf-8 # Tests publishing an avatar in MUCs, and getting tokens for ourselves and # others. Serves as a regression test for # <https://bugs.freedesktop.org/show_bug.cgi?id=32017>, where our MUC-specific # self handle would have an empty avatar token even though we're publishing our # avatar on the wire correctly. import hashlib from servicetest import ( call_async, EventPattern, assertEquals, assertLength, sync_dbus, wrap_channel, ) from gabbletest import ( exec_test, expect_and_handle_get_vcard, expect_and_handle_set_vcard, make_muc_presence, elem, ) from twisted.words.xish import xpath import ns import constants as cs from mucutil import try_to_join_muc AVATAR_1_DATA = 'nyan' AVATAR_1_SHA1 = hashlib.sha1(AVATAR_1_DATA).hexdigest() AVATAR_1_MIME_TYPE = 'image/x-pop-tart' AVATAR_2_DATA = 'NYAN' AVATAR_2_SHA1 = hashlib.sha1(AVATAR_2_DATA).hexdigest() AVATAR_2_MIME_TYPE = 'image/x-pop-tart' MUC = 'taco-dog@nyan.cat' def extract_hash_from_presence(stanza): return xpath.queryForString( '/presence/x[@xmlns="%s"]/photo' % ns.VCARD_TEMP_UPDATE, stanza) def test(q, bus, conn, stream): self_handle = conn.GetSelfHandle() # When Gabble initially requests its avatar from the server, it discovers # it has none. expect_and_handle_get_vcard(q, stream) handle, signalled_token = q.expect('dbus-signal', signal='AvatarUpdated').args assertEquals(self_handle, handle) assertEquals('', signalled_token) # The user sets an avatar. call_async(q, conn.Avatars, 'SetAvatar', AVATAR_1_DATA, AVATAR_1_MIME_TYPE) expect_and_handle_get_vcard(q, stream) expect_and_handle_set_vcard(q, stream) # It's signalled on D-Bus … set_ret, avatar_updated = q.expect_many( EventPattern('dbus-return', method='SetAvatar'), EventPattern('dbus-signal', signal='AvatarUpdated'), ) returned_token, = set_ret.value handle, signalled_token = avatar_updated.args assertEquals(self_handle, handle) assertEquals(returned_token, signalled_token) # … and also on XMPP. broadcast = q.expect('stream-presence', to=None) broadcast_hash = extract_hash_from_presence(broadcast.stanza) assertEquals(AVATAR_1_SHA1, broadcast_hash) # If applications ask Gabble for information about the user's own avatar, # it should be able to answer. (Strictly speaking, expecting Gabble to know # the avatar data is risky because Gabble discards cached vCards after a # while, but we happen to know it takes 20 seconds or so for that to # happen.) known = conn.Avatars.GetKnownAvatarTokens([self_handle]) assertEquals({self_handle: signalled_token}, known) conn.Avatars.RequestAvatars([self_handle]) retrieved = q.expect('dbus-signal', signal='AvatarRetrieved') handle, token, data, mime_type = retrieved.args assertEquals(self_handle, handle) assertEquals(signalled_token, token) assertEquals(AVATAR_1_DATA, data) assertEquals(AVATAR_1_MIME_TYPE, mime_type) # Well, that was quite easy. How about we join a MUC? XEP-0153 §4.1 says: # If a client supports the protocol defined herein, it […] SHOULD # also include the update child in directed presence stanzas (e.g., # directed presence sent when joining Multi-User Chat [5] rooms). # — http://xmpp.org/extensions/xep-0153.html#bizrules-presence join_event = try_to_join_muc(q, bus, conn, stream, MUC) directed_hash = extract_hash_from_presence(join_event.stanza) assertEquals(AVATAR_1_SHA1, directed_hash) # There are two others in the MUC: fredrik has no avatar, wendy has an # avatar. We, of course, have our own avatar. stream.send(make_muc_presence('none', 'participant', MUC, 'fredrik')) stream.send(make_muc_presence('none', 'participant', MUC, 'wendy', photo=AVATAR_2_SHA1)) stream.send(make_muc_presence('owner', 'moderator', MUC, 'test', photo=AVATAR_1_SHA1)) path, _ = q.expect('dbus-return', method='CreateChannel').value chan = wrap_channel(bus.get_object(conn.bus_name, path), 'Text', ['Messages']) members = chan.Properties.Get(cs.CHANNEL_IFACE_GROUP, 'Members') assertLength(3, members) fredrik, wendy, muc_self_handle = conn.RequestHandles(cs.HT_CONTACT, ['%s/%s' % (MUC, x) for x in ["fredrik", "wendy", "test"]]) known = conn.Avatars.GetKnownAvatarTokens(members) # <https://bugs.freedesktop.org/show_bug.cgi?id=32017>: this assertion # failed, the MUC self handle's token was the empty string. assertEquals(AVATAR_1_SHA1, known[muc_self_handle]) assertEquals(AVATAR_2_SHA1, known[wendy]) assertEquals('', known[fredrik]) # 'k, cool. Wendy loves our avatar and switches to it. stream.send(make_muc_presence('none', 'participant', MUC, 'wendy', photo=AVATAR_1_SHA1)) # Okay this is technically assuming that we just expose the SHA1 sums # directly which is not guaranteed … but we do. q.expect('dbus-signal', signal='AvatarUpdated', args=[wendy, AVATAR_1_SHA1]) # Fredrik switches too. stream.send(make_muc_presence('none', 'participant', MUC, 'fredrik', photo=AVATAR_1_SHA1)) q.expect('dbus-signal', signal='AvatarUpdated', args=[fredrik, AVATAR_1_SHA1]) # And we switch to some other avatar. Gabble should update its vCard, and # then update its MUC presence (which the test, acting as the MUC server, # must echo). call_async(q, conn.Avatars, 'SetAvatar', AVATAR_2_DATA, AVATAR_2_MIME_TYPE) expect_and_handle_get_vcard(q, stream) expect_and_handle_set_vcard(q, stream) muc_presence = q.expect('stream-presence', to=('%s/test' % MUC)) directed_hash = extract_hash_from_presence(muc_presence.stanza) stream.send(make_muc_presence('owner', 'moderator', MUC, 'test', photo=directed_hash)) # Gabble should signal an avatar update for both our global self-handle and # our MUC self-handle. (The first of these of course does not need to wait # for the MUC server to echo our presence.) q.expect_many( EventPattern('dbus-signal', signal='AvatarUpdated', args=[self_handle, AVATAR_2_SHA1]), EventPattern('dbus-signal', signal='AvatarUpdated', args=[muc_self_handle, AVATAR_2_SHA1]), ) if __name__ == '__main__': exec_test(test) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/test-register.py����������������������������������������������0000644�0001750�0001750�00000012176�12225363340�024203� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test registration. """ from gabbletest import ( exec_test, make_result_iq, acknowledge_iq, send_error_reply, ) from servicetest import assertEquals from twisted.words.xish import domish, xpath import ns import constants as cs def connect_and_send_form(q, conn, stream): conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) event = q.expect('stream-iq', query_ns=ns.REGISTER) result = make_result_iq(stream, event.stanza) query = result.firstChildElement() query.addElement('username') query.addElement('password') stream.send(result) event = q.expect('stream-iq') iq = event.stanza assert xpath.queryForString('/iq/query/username', iq) == 'test' assert xpath.queryForString('/iq/query/password', iq) == 'pass' return iq def test_success(q, bus, conn, stream): iq = connect_and_send_form(q, conn, stream) acknowledge_iq(stream, iq) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) def test_conflict(q, bus, conn, stream): iq = connect_and_send_form(q, conn, stream) error = domish.Element((None, 'error')) error['code'] = '409' error['type'] = 'cancel' error.addElement((ns.STANZA, 'conflict')) send_error_reply(stream, iq, error) e = q.expect('dbus-signal', signal='ConnectionError') assertEquals(cs.REGISTRATION_EXISTS, e.args[0]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_NAME_IN_USE]) def test_with_email(q, bus, conn, stream): # The form requires <email/>; so, Gabble should give up. conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) event = q.expect('stream-iq', query_ns=ns.REGISTER) result = make_result_iq(stream, event.stanza) query = result.firstChildElement() query.addElement('username') query.addElement('password') query.addElement('email') stream.send(result) # This is really WOCKY_CONNECTOR_ERROR_REGISTRATION_REJECTED e = q.expect('dbus-signal', signal='ConnectionError') assertEquals(cs.PERMISSION_DENIED, e.args[0]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_AUTHENTICATION_FAILED]) def test_data_forms(q, bus, conn, stream): conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) event = q.expect('stream-iq', query_ns=ns.REGISTER) result = make_result_iq(stream, event.stanza) query = result.firstChildElement() query.addElement((None, 'instructions')).addChild("Hope you like x:data") # Use the same element names as in jabber:iq:register as per XEP 0077's # Extensibility section. x = query.addElement((ns.X_DATA, 'x')) x['type'] = 'form' x.addElement((None, 'title')).addChild("Account Registration") x.addElement((None, 'instructions')).addChild( "This is gratuitously a data form!") form_type = x.addElement((None, 'field')) form_type['type'] = 'hidden' form_type['var'] = 'FORM_TYPE' form_type.addElement((None, 'value')).addChild(ns.REGISTER) first = x.addElement((None, 'field')) first['type'] = 'text-single' first['label'] = 'Username' first['var'] = 'username' first.addElement((None, 'required')) first = x.addElement((None, 'field')) first['type'] = 'text-single' first['label'] = 'Password' first['var'] = 'password' first.addElement((None, 'required')) stream.send(result) # This is really WOCKY_CONNECTOR_ERROR_REGISTRATION_UNSUPPORTED e = q.expect('dbus-signal', signal='ConnectionError') assertEquals(cs.NOT_AVAILABLE, e.args[0]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_AUTHENTICATION_FAILED]) def test_redirection(q, bus, conn, stream): conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) event = q.expect('stream-iq', query_ns=ns.REGISTER) result = make_result_iq(stream, event.stanza) query = result.firstChildElement() query.addElement((None, 'instructions')).addChild("Sigh.") # Tell the user to go to some website url = query.addElement((ns.X_OOB, 'x')).addElement((None, 'url')) url.addChild("http://foogle.talk.example/newaccount") stream.send(result) # This is really WOCKY_CONNECTOR_ERROR_REGISTRATION_UNSUPPORTED e = q.expect('dbus-signal', signal='ConnectionError') assertEquals(cs.NOT_AVAILABLE, e.args[0]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_AUTHENTICATION_FAILED]) if __name__ == '__main__': exec_test(test_success, {'register': True}, do_connect=False) exec_test(test_conflict, {'register': True}, do_connect=False) exec_test(test_with_email, {'register': True}, do_connect=False) exec_test(test_data_forms, {'register': True}, do_connect=False) exec_test(test_redirection, {'register': True}, do_connect=False) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/Makefile.am���������������������������������������������������0000664�0001750�0001750�00000035275�12332441362�023073� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������TWISTED_TESTS = \ addressing.py \ avatar-requirements.py \ caps/advertise-contact-caps.py \ caps/advertise-legacy.py \ caps/broken-reply.py \ caps/caps-cache.py \ caps/caps-persistent-cache.py \ caps/compat-bundles.py \ caps/disco-without-node.py \ caps/double-disco.py \ caps/from-bare-jid.py \ caps/hashed-caps.py \ caps_helper.py \ caps/initial-caps.py \ caps/jingle-caps.py \ caps/offline.py \ caps/receive-jingle.py \ caps/trust-thyself.py \ caps/tube-caps.py \ client-types.py \ cm/protocol.py \ connect/disco-error-from-bare-jid.py \ connect/disco-facebook.py \ connect/disconnect-timeout.py \ connect/disco-no-reply.py \ connect/network-error.py \ connect/stream-closed.py \ connect/test-connection-params.py \ connect/test-fail.py \ connect/test-nonblocking-tls.py \ connect/test-success.py \ connect/test-twice.py \ console.py \ dataforms.py \ gateways.py \ last-activity.py \ mail-notification.py \ muc/avatars.py \ muc/banned.py \ muc/chat-states.py \ muc/conference.py \ muc/kicked.py \ muc/name-conflict.py \ muc/password.py \ muc/presence-before-closing.py \ muc/renamed.py \ muc/room-config.py \ muc/roomlist.py \ muc/room.py \ muc/scrollback.py \ muc/send-error.py \ muc/subject.py \ muc/test-ensure.py \ muc/test-muc-alias.py \ muc/test-muc-invitation.py \ muc/test-muc-ownership.py \ muc/test-muc.py \ olpc/change-notifications.py \ olpc/current-activity.py \ olpc/olpc-muc-invitation.py \ olpc/olpc-muc-prop-change.py \ olpc/test-olpc-bundle.py \ olpc/test-olpc-set-props-preload.py \ pep-support.py \ plugin-channel-managers.py \ power-save.py \ presence/decloak.py \ presence/error.py \ presence/initial-contact-presence.py \ presence/initial-presence.py \ presence/invisible_xep_0126.py \ presence/invisible_xep_0186.py \ presence/plugins.py \ presence/presence.py \ presence/set-idempotence.py \ presence/shared-status.py \ pubsub.py \ roster/authorize.py \ roster/edit-before-roster.py \ roster/ensure.py \ roster/groups-12791.py \ roster/groups.py \ roster/initial-aliases.py \ roster/push-from-contact.py \ roster/push-without-id.py \ roster/removed-from-rp-subscribe.py \ roster/request-group-after-roster.py \ roster/request-group-before-roster.py \ roster/test-google-roster.py \ roster/test-roster-item-deletion.py \ roster/test-roster.py \ roster/test-roster-subscribe.py \ roster/test-save-alias-to-roster.py \ sasl/abort.py \ sasl/close.py \ sasl/complex.py \ sasl/jabber_auth.py \ sasl/plain.py \ sasl/telepathy-password.py \ search/ceci-nest-pas-un-serveur.py \ search/extended.py \ search/no-server-property.py \ search/unextended.py \ servicetest.py \ sidecar-own-caps.py \ sidecars.py \ test-debug.py \ test-fallback-socks5-proxy.py \ test-location.py \ test-register.py \ text/destroy.py \ text/ensure.py \ text/facebook-own-message.py \ text/initiate.py \ text/initiate-requestotron.py \ text/receipts.py \ text/respawn.py \ text/send-error.py \ text/send-to-correct-resource.py \ text/test-chat-state.py \ text/test-text-delayed.py \ text/test-text-no-body.py \ text/test-text.py \ tls/legacy-jabber.py \ tls/server-tls-channel.py \ version.py \ $(NULL) TWISTED_TUBE_TESTS = \ tubes/accept-muc-dbus-tube.py \ tubes/accept-muc-stream-tube.py \ tubes/accept-private-dbus-tube.py \ tubes/accept-private-stream-tube.py \ tubes/check-create-tube-return.py \ tubes/close-muc-with-closed-tube.py \ tubes/create-invalid-tube-channels.py \ tubes/ensure-si-tube.py \ tubes/offer-muc-dbus-tube.py \ tubes/offer-muc-stream-tube.py \ tubes/offer-no-caps.py \ tubes/offer-private-dbus-tube.py \ tubes/offer-private-stream-tube.py \ tubes/request-invalid-dbus-tube.py \ tubes/test-get-available-tubes.py \ tubes/test-socks5-muc.py \ $(NULL) TWISTED_VCARD_TESTS = \ vcard/clear-avatar.py \ vcard/disconnect-during-pep.py \ vcard/get-contact-info.py \ vcard/item-not-found.py \ vcard/overlapping-sets.py \ vcard/redundant-set.py \ vcard/refresh-contact-info.py \ vcard/set-avatar.py \ vcard/set-contact-info.py \ vcard/set-set-disconnect.py \ vcard/supported-fields.py \ vcard/test-alias-empty-vcard.py \ vcard/test-alias-message.py \ vcard/test-alias-pep.py \ vcard/test-alias.py \ vcard/test-avatar-async.py \ vcard/test-avatar-multiple-resources.py \ vcard/test-avatar.py \ vcard/test-avatar-retrieved.py \ vcard/test-avatar-tokens.py \ vcard/test-save-alias-to-vcard.py \ vcard/test-set-alias.py \ vcard/test-vcard-cache.py \ vcard/test-vcard-race.py \ vcard/update-get-failed.py \ vcard/update-rejected.py \ $(NULL) TWISTED_JINGLE_TESTS = \ jingle/accept-extra-stream.py \ jingle/call-basics.py \ jingle/call-codecoffer.py \ jingle/call-content-adding-removal.py \ jingle/call-dtmf.py \ jingle/call-google-relay.py \ jingle/call-hold-audio.py \ jingle/call-hold-av.py \ jingle/call-muc-cancel.py \ jingle/call-muc.py \ jingle/call-muc-re-re-request.py \ jingle/call-state.py \ jingle/decloak-peer.py \ jingle/dtmf-no-audio.py \ jingle/dtmf.py \ jingle/google-relay.py \ jingle/hold-audio.py \ jingle/hold-av.py \ jingle/incoming-basics.py \ jingle/incoming-call-stream-error.py \ jingle/incoming-gmail-modern-jingle.py \ jingle/initial-audio-video.py \ jingle/misuse.py \ jingle/outgoing-basics.py \ jingle/outgoing-ensure.py \ jingle/outgoing-many-streams.py \ jingle/payload-types.py \ jingle/preload-caps-crash.py \ jingle/session-id-collision.py \ jingle/stream-errors-on-content-reject.py \ jingle/stream-errors-on-terminate.py \ jingle/stream-handler-error.py \ jingle/stun-server.py \ jingle/test-content-adding-removal.py \ jingle/test-content-complex.py \ jingle/test-description-info.py \ jingle/test-incoming-call-reject.py \ jingle/test-incoming-iceudp.py \ jingle/test-outgoing-call-rejected.py \ jingle/test-outgoing-iceudp.py \ jingle/test-wait-for-caps-incomplete.py \ jingle/test-wait-for-caps.py \ jingle/transport-info-parsing.py \ jingle/unknown-session.py \ $(NULL) TWISTED_FT_TESTS = \ file-transfer/test-caps-file-transfer.py \ file-transfer/test-ibb-too-early.py \ file-transfer/test-receive-file-and-close-socket-while-receiving.py \ file-transfer/test-receive-file-and-disconnect.py \ file-transfer/test-receive-file-and-sender-disconnect-while-pending.py \ file-transfer/test-receive-file-and-sender-disconnect-while-transfering.py \ file-transfer/test-receive-file-decline.py \ file-transfer/test-receive-file.py \ file-transfer/test-send-file-and-cancel-immediately.py \ file-transfer/test-send-file-declined.py \ file-transfer/test-send-file-provide-immediately.py \ file-transfer/test-send-file-send-before-accept.py \ file-transfer/test-send-file-to-unknown-contact.py \ file-transfer/test-send-file-wait-to-provide.py \ file-transfer/test-uri.py \ file-transfer/metadata.py \ file-transfer/ft-client-caps.py \ jingle-share/test-caps-file-transfer.py \ jingle-share/test-multift.py \ jingle-share/test-receive-file-and-close-socket-while-receiving.py \ jingle-share/test-receive-file-and-disconnect.py \ jingle-share/test-receive-file-and-sender-disconnect-while-pending.py \ jingle-share/test-receive-file-and-sender-disconnect-while-transfering.py \ jingle-share/test-receive-file-decline.py \ jingle-share/test-send-file-and-cancel-immediately.py \ jingle-share/test-send-file.py \ jingle-share/test-send-file-send-before-accept.py \ jingle-share/test-send-file-wait-to-provide.py \ $(NULL) # other files used by the twisted tests, but are not tests and are not built # source TWISTED_OTHER_FILES = \ bytestream.py \ connect/torture.py \ constants.py \ file-transfer/file_transfer_helper.py \ gabbletest.py \ httptest.py \ jingle/call_helper.py \ jingle/callutils.py \ jingle/__init__.py \ jingle/jingletest2.py \ jingle-share/file_transfer_helper.py \ jingle-share/jingleshareutils.py \ mucutil.py \ ns.py \ olpc/util.py \ presence/__init__.py \ presence/invisible_helper.py \ rostertest.py \ sasl/saslutil.py \ search/search_helper.py \ test-helper.py \ tls-cert.pem \ tls-key.pem \ tubes/tubetestutil.py \ $(NULL) if ENABLE_INSTALLED_TESTS # Install files in each directory. They could be tests, pristine data files, # scripts or built source twistedtestsdir = @gabbletestsdir@/twisted nobase_nodist_twistedtests_SCRIPTS = \ run-test.sh \ tools/exec-with-log.sh \ tools/run-gabble.sh \ $(NULL) nobase_dist_twistedtests_SCRIPTS = \ tools/with-session-bus.sh \ $(NULL) nobase_dist_twistedtests_DATA = \ $(TWISTED_TESTS) \ $(TWISTED_OTHER_FILES) \ $(NULL) nobase_nodist_twistedtests_DATA = \ config.py \ gabble-twisted-tests.list \ $(installed_conf_files) \ $(service_files) $(NULL) endif check-local: check-coding-style check-twisted # set to 6 when using refdbg, to give Gabble time to exit CHECK_TWISTED_SLEEP=0 check-twisted: $(BUILT_SOURCES) if WANT_TWISTED_TESTS rm -f tools/core rm -f tools/vgcore.* rm -f tools/gabble-testing.log rm -f tools/strace.log if test -n "$$GABBLE_TEST_REFDBG"; then \ sleep=6; \ else \ sleep=$(CHECK_TWISTED_SLEEP); \ fi; \ failed=0; \ GABBLE_TEST_UNINSTALLED=1 \ GABBLE_TEST_SLEEP="--sleep=$$sleep" \ GABBLE_ABS_TOP_SRCDIR=@abs_top_srcdir@ \ GABBLE_ABS_TOP_BUILDDIR=@abs_top_builddir@ \ sh run-test.sh "$(TWISTED_TESTS)" || failed=1; \ if test -e tools/core; then\ echo -e "\033[0;31;1mCore dump exists: tools/core\033[0m";\ exit 1;\ fi; \ if test $$failed = 1; then\ exit 1;\ fi; else @echo "Configured without Twisted test support. To enable them," @echo "ensure that these Python modules are available:" @echo " • twisted.words.xish.domish" @echo " • twisted.words.protocols.jabber" @echo " • twisted.internet.reactor" @echo "and then re-run configure." endif if ENABLE_DEBUG DEBUGGING_PYBOOL = True else DEBUGGING_PYBOOL = False endif if ENABLE_PLUGINS PLUGINS_ENABLED_PYBOOL = True else PLUGINS_ENABLED_PYBOOL = False endif if ENABLE_CHANNEL_TYPE_CALL CHANNEL_TYPE_CALL_ENABLED_PYBOOL = True else CHANNEL_TYPE_CALL_ENABLED_PYBOOL = False endif if ENABLE_GOOGLE_RELAY GOOGLE_RELAY_ENABLED_PYBOOL = True else GOOGLE_RELAY_ENABLED_PYBOOL = False endif if ENABLE_FILE_TRANSFER FILE_TRANSFER_ENABLED_PYBOOL = True else FILE_TRANSFER_ENABLED_PYBOOL = False endif if ENABLE_VOIP VOIP_ENABLED_PYBOOL = True else VOIP_ENABLED_PYBOOL = False endif if ENABLE_JINGLE_FILE_TRANSFER JINGLE_FILE_TRANSFER_ENABLED_PYBOOL = True else JINGLE_FILE_TRANSFER_ENABLED_PYBOOL = False endif config.py: Makefile $(AM_V_GEN) { \ echo "PACKAGE_STRING = \"$(PACKAGE_STRING)\""; \ echo "CLIENT_TYPE = '$(CLIENT_TYPE)'"; \ echo "DEBUGGING = $(DEBUGGING_PYBOOL)"; \ echo "PLUGINS_ENABLED = $(PLUGINS_ENABLED_PYBOOL)"; \ echo "CHANNEL_TYPE_CALL_ENABLED = $(CHANNEL_TYPE_CALL_ENABLED_PYBOOL)"; \ echo "GOOGLE_RELAY_ENABLED = $(GOOGLE_RELAY_ENABLED_PYBOOL)"; \ echo "FILE_TRANSFER_ENABLED = $(FILE_TRANSFER_ENABLED_PYBOOL)"; \ echo "VOIP_ENABLED = $(VOIP_ENABLED_PYBOOL)"; \ echo "JINGLE_FILE_TRANSFER_ENABLED = $(JINGLE_FILE_TRANSFER_ENABLED_PYBOOL)"; \ } > $@ BUILT_SOURCES = config.py TWISTED_TESTS += $(TWISTED_FT_TESTS) $(TWISTED_TUBE_TESTS) TWISTED_TESTS += $(TWISTED_JINGLE_TESTS) $(TWISTED_VCARD_TESTS) if ENABLE_INSTALLED_TESTS gabbledebugdir = @gabbletestsdir@/twisted gabbledebug_PROGRAMS = \ telepathy-gabble-debug else noinst_PROGRAMS = \ telepathy-gabble-debug endif telepathy_gabble_debug_SOURCES = \ main-debug.c \ test-resolver.c \ test-resolver.h telepathy_gabble_debug_LDADD = \ $(top_builddir)/src/libgabble-convenience.la \ $(ALL_LIBS) telepathy_gabble_debug_LDFLAGS = -export-dynamic AM_CFLAGS = $(ERROR_CFLAGS) @DBUS_CFLAGS@ @GLIB_CFLAGS@ @WOCKY_CFLAGS@ \ @TP_GLIB_CFLAGS@ \ -I $(top_srcdir)/src -I $(top_builddir)/src \ -I $(top_srcdir)/lib -I $(top_builddir)/lib \ -I $(top_srcdir) -I $(top_builddir) ALL_LIBS = @DBUS_LIBS@ @GLIB_LIBS@ @WOCKY_LIBS@ @TP_GLIB_LIBS@ CLEANFILES = gabble-[1-9]*.log *.pyc */*.pyc config.py check_misc_sources = $(TESTS) # the following used to be in tools/ include $(top_srcdir)/tools/check-coding-style.mk gabble-twisted-tests.list: Makefile $(AM_V_GEN)echo $(TWISTED_TESTS) > $@ run-test.sh: run-test.sh.in Makefile $(AM_V_GEN)sed -e "s|[@]gabbletestsdir[@]|@gabbletestsdir@|g" \ -e "s|[@]PYTHON[@]|$(PYTHON)|g" \ -e "s|[@]TEST_PYTHON[@]|$(TEST_PYTHON)|g" \ $< > $@ @chmod +x $@ tools/run-gabble.sh: tools/run-gabble.sh.in Makefile @mkdir -p tools $(AM_V_GEN)sed \ -e "s|[@]gabbletestsdir[@]|@gabbletestsdir@|g" \ -e "s|[@]pluginexecdir[@]|@pluginexecdir@|g" \ -e "s|[@]libdir[@]|$(libdir)|g" \ $< > $@ @chmod +x $@ tools/exec-with-log.sh: tools/exec-with-log.sh.in $(MKDIR_P) tools $(AM_V_GEN)sed -e "s|[@]abs_top_builddir[@]|@abs_top_builddir@|g" \ -e "s|[@]abs_top_srcdir[@]|@abs_top_srcdir@|g" $< > $@ @chmod +x $@ # The wildcard % matches both config files! tools/%.conf: tools/%.conf.in Makefile $(MKDIR_P) tools/servicedir $(MKDIR_P) tools/servicedir-uninstalled $(AM_V_GEN)sed -e "s|[@]gabbletestsdir[@]|@gabbletestsdir@|g" \ -e "s|[@]abs_top_builddir[@]|@abs_top_builddir@|g" $< > $@ # We don't use the full filename for the .in because > 99 character filenames # in tarballs are non-portable (and automake 1.8 doesn't let us build # non-archaic tarballs) tools/servicedir/org.freedesktop.Telepathy.ConnectionManager.%.service: tools/servicedir/%.service.in Makefile $(MKDIR_P) tools/servicedir $(AM_V_GEN)sed -e "s|[@]gabbletestsdir[@]|@gabbletestsdir@|g" $< > $@ tools/servicedir-uninstalled/org.freedesktop.Telepathy.ConnectionManager.%.service: tools/servicedir-uninstalled/%.service.in $(MKDIR_P) tools/servicedir-uninstalled $(AM_V_GEN)sed -e "s|[@]abs_top_builddir[@]|@abs_top_builddir@|g" $< > $@ # D-Bus service file for testing installed_service_in_files = tools/servicedir/gabble.service.in service_files = tools/servicedir/org.freedesktop.Telepathy.ConnectionManager.gabble.service uninstalled_service_in_files = tools/servicedir-uninstalled/gabble.service.in uninstalled_service_files = tools/servicedir-uninstalled/org.freedesktop.Telepathy.ConnectionManager.gabble.service # D-Bus config file for testing installed_conf_in_files = tools/servicedir/tmp-session-bus.conf.in installed_conf_files = $(installed_conf_in_files:.conf.in=.conf) uninstalled_conf_in_files = tools/servicedir-uninstalled/tmp-session-bus.conf.in uninstalled_conf_files = $(uninstalled_conf_in_files:.conf.in=.conf) BUILT_SOURCES += \ $(service_files) \ $(installed_conf_files) \ $(uninstalled_service_files) \ $(uninstalled_conf_files) \ gabble-twisted-tests.list \ run-test.sh \ tools/exec-with-log.sh \ tools/run-gabble.sh \ $(NULL) EXTRA_DIST = \ $(installed_service_in_files) \ $(uninstalled_service_in_files) \ $(installed_conf_in_files) \ $(uninstalled_conf_in_files) \ tools/exec-with-log.sh.in \ tools/run-gabble.sh.in \ run-test.sh.in \ $(NULL) CLEANFILES += \ $(BUILT_SOURCES) \ tools/gabble-testing.log �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/client-types.py�����������������������������������������������0000664�0001750�0001750�00000023464�12332441362�024026� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test Conn.I.ClientTypes """ import random from functools import partial from servicetest import EventPattern, assertEquals, assertLength, assertContains, assertSameSets from gabbletest import exec_test, make_presence, sync_stream import constants as cs import ns from caps_helper import ( presence_and_disco, send_presence, expect_disco, send_disco_reply, compute_caps_hash, ) client_base = 'http://telepathy.freedesktop.org/fake-client/client-types-' caps_base = { 'ver': '0.1' } features = [ ns.JINGLE_015, ns.JINGLE_015_AUDIO, ns.JINGLE_015_VIDEO, ns.GOOGLE_P2P, ] # our identities BOT = ['client/bot/en/doesnotcompute'] CONSOLE = ['client/console/en/dumb'] GAME = ['client/game/en/wiibox3'] HANDHELD = ['client/handheld/en/lolpaq'] PC = ['client/pc/en/Lolclient 0.L0L'] PHONE = ['client/phone/en/gr8phone 101'] WEB = ['client/web/en/webcat'] SMS = ['client/phone/en/tlk 2 u l8r'] TRANSIENT_PHONE = ['client/phone/en/fleeting visit'] BANANAPHONE = ['client/phone/en/banana milk is pretty disgusting'] def build_stuff(identities): types = map(lambda x: x.split('/')[1], identities) # add something to the end of the client string so that the caps # hashes aren't all the same and so stop discoing client = client_base + ''.join(types) caps = caps_base caps['node'] = client return (caps, client, types) def contact_online(q, conn, stream, contact, identities, disco=True, dataforms={}, initial=True, show=None): (caps, client, types) = build_stuff(identities) handle = conn.RequestHandles(cs.HT_CONTACT, [contact])[0] # make contact come online presence_and_disco (q, conn, stream, contact, disco, client, caps, features, identities, dataforms=dataforms, initial = initial, show = show) if initial: event = q.expect('dbus-signal', signal='ClientTypesUpdated') assertEquals([handle, types], event.args) def test(q, bus, conn, stream): # check all these types appear as they should contact_online(q, conn, stream, 'bot@bot.com/lol', BOT) contact_online(q, conn, stream, 'console@console.com/lol', CONSOLE) contact_online(q, conn, stream, 'game@game.com/lol', GAME) contact_online(q, conn, stream, 'handheld@handheld.com/lol', HANDHELD) contact_online(q, conn, stream, 'pc@pc.com/lol', PC) contact_online(q, conn, stream, 'phone@phone.com/lol', PHONE) contact_online(q, conn, stream, 'web@web.com/lol', WEB) contact_online(q, conn, stream, 'sms@sms.com/lol', SMS) meredith_one = 'meredith@foo.com/One' meredith_two = 'meredith@foo.com/Two' meredith_three = 'meredith@foo.com/Three' meredith_handle = conn.RequestHandles(cs.HT_CONTACT, [meredith_one])[0] # Meredith signs in from one resource contact_online(q, conn, stream, meredith_one, PC, show='chat') # * One: chat: pc # ClientTypes should be: ['pc'] # Meredith signs in from another resource contact_online(q, conn, stream, meredith_two, PHONE, show='dnd', initial=False) # * One: chat: pc # * Two: dnd: phone # ClientTypes should be: ['pc'] # check we're still a PC types = conn.GetClientTypes([meredith_handle], dbus_interface=cs.CONN_IFACE_CLIENT_TYPES) assertLength(1, types) assertLength(1, types[meredith_handle]) assertEquals('pc', types[meredith_handle][0]) # Two now becomes more available stream.send(make_presence(meredith_two, show='chat')) # * One: chat: pc # * Two: chat: phone # ClientTypes should be: ['pc'] types = conn.GetClientTypes([meredith_handle], dbus_interface=cs.CONN_IFACE_CLIENT_TYPES) assertEquals('pc', types[meredith_handle][0]) # One now becomes less available stream.send(make_presence(meredith_one, show='away')) # * One: away: pc # * Two: chat: phone # ClientTypes should be: ['phone'] # wait for the presence change q.expect('dbus-signal', signal='PresencesChanged', args=[{meredith_handle: (cs.PRESENCE_AVAILABLE, 'chat', '')}]) # now wait for the change in client type event = q.expect('dbus-signal', signal='ClientTypesUpdated') assertEquals([meredith_handle, ['phone']], event.args) # make One more available again stream.send(make_presence(meredith_one, show='chat', status='lawl')) # * One: chat: pc # * Two: chat: phone # ClientTypes should be: ['pc'] # wait for the presence change q.expect('dbus-signal', signal='PresencesChanged', args=[{meredith_handle: (cs.PRESENCE_AVAILABLE, 'chat', 'lawl')}]) # now wait for the change in client type event = q.expect('dbus-signal', signal='ClientTypesUpdated') assertEquals([meredith_handle, ['pc']], event.args) # both One and Two go away stream.send(make_presence(meredith_one, show='away')) # * One: away: pc # * Two: chat: phone # ClientTypes should be: ['phone'] stream.send(make_presence(meredith_two, show='away')) # * One: away: pc # * Two: away: phone # ClientTypes should be: ['pc'] # wait for the presence change q.expect('dbus-signal', signal='PresencesChanged', args=[{meredith_handle: (cs.PRESENCE_AWAY, 'away', '')}]) # check it still thinks we're a PC types = conn.GetClientTypes([meredith_handle], dbus_interface=cs.CONN_IFACE_CLIENT_TYPES) assertEquals('pc', types[meredith_handle][0]) # Three, with multiple identities, signs in identities = [PHONE[0], CONSOLE[0], HANDHELD[0], BOT[0]] contact_online(q, conn, stream, meredith_three, identities, show='chat', initial=False) # * One: away: pc # * Two: away: phone # * Three: chat: phone, console, handheld, bot # ClientTypes should be: ['phone', 'console', 'handheld', 'bot'] in some order # wait for the presence change q.expect('dbus-signal', signal='PresencesChanged', args=[{meredith_handle: (cs.PRESENCE_AVAILABLE, 'chat', 'hello')}]) # now wait for the change in client type event = q.expect('dbus-signal', signal='ClientTypesUpdated') assertEquals(meredith_handle, event.args[0]) assertEquals(['bot', 'console', 'handheld', 'phone'], sorted(event.args[1])) # that'll do # # ... # # wait wait! no it won't! Here's a regression test for # <https://bugs.freedesktop.org/show_bug.cgi?id=31772>. (caps, client, types) = build_stuff(TRANSIENT_PHONE) contact = 'mini9@meegoconf.ie/hai' send_presence(q, conn, stream, contact, caps) stanza = expect_disco(q, contact, client, caps) stream.send(make_presence(contact, type='unavailable')) send_disco_reply(stream, stanza, TRANSIENT_PHONE, []) # Gabble used to crash upon receiving a disco reply from a contact who's no # longer in the presence cache. So we sync here to check if it's died. sync_stream(q, stream) def test2(q, bus, conn, stream): marco_pidgin = 'marco@fancy.italian.restaurant/Pidgin' marco_phone = 'marco@fancy.italian.restaurant/N900' handle = conn.RequestHandles(cs.HT_CONTACT, [marco_pidgin])[0] # pidgin comes online contact_online(q, conn, stream, marco_pidgin, PC) types = conn.GetClientTypes([handle], dbus_interface=cs.CONN_IFACE_CLIENT_TYPES) assertSameSets(['pc'], types[handle]) # phone comes online contact_online(q, conn, stream, marco_phone, PHONE, initial=False) types = conn.GetClientTypes([handle], dbus_interface=cs.CONN_IFACE_CLIENT_TYPES) assertSameSets(['pc'], types[handle]) sync_stream(q, stream) # pidgin goes offline stream.send(make_presence(marco_pidgin, type='unavailable')) # no presence signal q.expect('dbus-signal', signal='ClientTypesUpdated', args=[handle, ['phone']]) # pidgin comes back online caps, _, _ = build_stuff(PC) stream.send(make_presence(marco_pidgin, status='hello', caps=caps)) q.expect('dbus-signal', signal='ClientTypesUpdated', args=[handle, ['pc']]) attrs = conn.Contacts.GetContactAttributes([handle], [cs.CONN_IFACE_CLIENT_TYPES], False) assertContains(handle, attrs) attr = cs.CONN_IFACE_CLIENT_TYPES + '/client-types' assertContains(attr, attrs[handle]) assertEquals(['pc'], attrs[handle][attr]) def two_contacts_with_the_same_hash(q, bus, conn, stream, bare_jids): contact1 = 'bowyer.place@tfl.gov.uk' contact2 = 'albany.road@tfl.gov.uk' if not bare_jids: contact1 += '/lol' contact2 += '/whut' h1, h2 = conn.RequestHandles(cs.HT_CONTACT, [contact1, contact2]) ver = compute_caps_hash(BANANAPHONE, features, {}) caps = { # Uniquify slightly with a stringified boolean ;-) 'node': '%s%s' % (client_base, bare_jids), 'ver': ver, 'hash': 'sha-1', } send_presence(q, conn, stream, contact1, caps) stanza = expect_disco(q, contact1, caps['node'], caps) send_presence(q, conn, stream, contact2, caps) q.forbid_events([ EventPattern('stream-iq', to=contact2, query_ns=ns.DISCO_INFO), ]) sync_stream(q, stream) send_disco_reply(stream, stanza, BANANAPHONE, features, {}) q.expect_many( EventPattern('dbus-signal', signal='ClientTypesUpdated', args=[h1, ['phone']]), # Gabble previously did not emit ClientTypesUpdated for anyone beside # the contact we sent the disco request to; so this second event would # never arrive. EventPattern('dbus-signal', signal='ClientTypesUpdated', args=[h2, ['phone']]), ) if __name__ == '__main__': exec_test(test) exec_test(test2) exec_test(partial(two_contacts_with_the_same_hash, bare_jids=False)) exec_test(partial(two_contacts_with_the_same_hash, bare_jids=True)) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/rostertest.py�������������������������������������������������0000664�0001750�0001750�00000013347�12332441362�023623� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from twisted.words.protocols.jabber.client import IQ from gabbletest import (wrap_channel,) from servicetest import (assertEquals, assertLength, EventPattern, assertContains) import constants as cs import ns def make_roster_push(stream, jid, subscription, ask_subscribe=False, name=None): iq = IQ(stream, "set") iq['id'] = 'push' query = iq.addElement('query') query['xmlns'] = ns.ROSTER item = query.addElement('item') item['jid'] = jid item['subscription'] = subscription if name is not None: item['name'] = name if ask_subscribe: item['ask'] = 'subscribe' return iq def send_roster_push(stream, jid, subscription, ask_subscribe=False, name=None): iq = make_roster_push(stream, jid, subscription, ask_subscribe=ask_subscribe, name=name) stream.send(iq) def get_contact_list_event_patterns(q, bus, conn, expected_handle_type, name): expected_handle = conn.RequestHandles(expected_handle_type, [name])[0] def new_channel_predicate(e): path, type, handle_type, handle, suppress_handler = e.args if type != cs.CHANNEL_TYPE_CONTACT_LIST: return False if handle_type != expected_handle_type: return False if handle != expected_handle: return False return True new_channel_repr = ('NewChannel(., ContactList, %u, "%s", .)' % (expected_handle_type, name)) new_channel_predicate.__repr__ = lambda: new_channel_repr def new_channels_predicate(e): info, = e.args if len(info) != 1: return False path, props = info[0] if props.get(cs.CHANNEL_TYPE) != cs.CHANNEL_TYPE_CONTACT_LIST: return False if props.get(cs.TARGET_HANDLE_TYPE) != expected_handle_type: return False if props.get(cs.TARGET_HANDLE) != expected_handle: return False return True new_channels_repr = ('NewChannels(... ct=ContactList, ht=%u, name="%s"... )' % (expected_handle_type, name)) new_channels_predicate.__repr__ = lambda: new_channels_repr return ( EventPattern('dbus-signal', signal='NewChannel', predicate=new_channel_predicate), EventPattern('dbus-signal', signal='NewChannels', predicate=new_channels_predicate) ) def expect_contact_list_signals(q, bus, conn, lists, groups=[], expect_more=None): assert lists or groups if expect_more is None: eps = [] else: eps = expect_more[:] for name in lists: eps.extend(get_contact_list_event_patterns(q, bus, conn, cs.HT_LIST, name)) for name in groups: eps.extend(get_contact_list_event_patterns(q, bus, conn, cs.HT_GROUP, name)) events = q.expect_many(*eps) ret = [] more = [] if expect_more is not None: for ep in expect_more: more.append(events.pop(0)) for name in lists: old_signal = events.pop(0) new_signal = events.pop(0) ret.append((old_signal, new_signal)) for name in groups: old_signal = events.pop(0) new_signal = events.pop(0) ret.append((old_signal, new_signal)) assert len(events) == 0 if expect_more is not None: return ret, more return ret def check_contact_list_signals(q, bus, conn, signals, ht, name, contacts, lp_contacts=[], rp_contacts=[]): """ Looks at NewChannel and NewChannels signals for the contact list with ID 'name' and checks that its members, lp members and rp members are exactly 'contacts', 'lp_contacts' and 'rp_contacts'. Returns a proxy for the channel. """ old_signal, new_signal = signals path, type, handle_type, handle, suppress_handler = old_signal.args assertEquals(cs.CHANNEL_TYPE_CONTACT_LIST, type) assertEquals(name, conn.InspectHandles(handle_type, [handle])[0]) chan = wrap_channel(bus.get_object(conn.bus_name, path), cs.CHANNEL_TYPE_CONTACT_LIST) members = chan.Group.GetMembers() assertEquals(sorted(contacts), sorted(conn.InspectHandles(cs.HT_CONTACT, members))) lp_handles = conn.RequestHandles(cs.HT_CONTACT, lp_contacts) rp_handles = conn.RequestHandles(cs.HT_CONTACT, rp_contacts) # NB. comma: we're unpacking args. Thython! info, = new_signal.args assertLength(1, info) # one channel path_, emitted_props = info[0] assertEquals(path_, path) assertEquals(cs.CHANNEL_TYPE_CONTACT_LIST, emitted_props[cs.CHANNEL_TYPE]) assertEquals(ht, emitted_props[cs.TARGET_HANDLE_TYPE]) assertEquals(handle, emitted_props[cs.TARGET_HANDLE]) channel_props = chan.Properties.GetAll(cs.CHANNEL) assertEquals(handle, channel_props.get('TargetHandle')) assertEquals(ht, channel_props.get('TargetHandleType')) assertEquals(cs.CHANNEL_TYPE_CONTACT_LIST, channel_props.get('ChannelType')) assertContains(cs.CHANNEL_IFACE_GROUP, channel_props.get('Interfaces')) assertEquals(name, channel_props['TargetID']) assertEquals(False, channel_props['Requested']) assertEquals('', channel_props['InitiatorID']) assertEquals(0, channel_props['InitiatorHandle']) group_props = chan.Properties.GetAll(cs.CHANNEL_IFACE_GROUP) assertContains('HandleOwners', group_props) assertContains('Members', group_props) assertEquals(members, group_props['Members']) assertContains('LocalPendingMembers', group_props) actual_lp_handles = [x[0] for x in group_props['LocalPendingMembers']] assertEquals(sorted(lp_handles), sorted(actual_lp_handles)) assertContains('RemotePendingMembers', group_props) assertEquals(sorted(rp_handles), sorted(group_props['RemotePendingMembers'])) assertContains('GroupFlags', group_props) return chan �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/roster/�������������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�022350� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/roster/push-from-contact.py�����������������������������������0000664�0001750�0001750�00000002342�12332441362�026265� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Ensure that Gabble correctly ignores roster pushes from contacts. """ from servicetest import EventPattern from gabbletest import exec_test, acknowledge_iq from rostertest import ( make_roster_push, expect_contact_list_signals, check_contact_list_signals, ) import ns import constants as cs jid = 'moonboots@xsf.lit' def test(q, bus, conn, stream): # Gabble asks for the roster; the server sends back an empty roster. event = q.expect('stream-iq', query_ns=ns.ROSTER) acknowledge_iq(stream, event.stanza) pairs = expect_contact_list_signals(q, bus, conn, ['stored']) stored = check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'stored', []) # Some malicious peer sends us a roster push to try to trick us into # showing them on our roster. Gabble should know better than to trust it. iq = make_roster_push(stream, jid, 'both') iq['from'] = jid stream.send(iq) q.forbid_events( [ EventPattern('dbus-signal', signal='MembersChanged', path=stored.object_path), EventPattern('dbus-signal', signal='ContactsChanged'), ]) e = q.expect('stream-iq', iq_type='error') if __name__ == '__main__': exec_test(test) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/roster/removed-from-rp-subscribe.py���������������������������0000664�0001750�0001750�00000020762�12332441362�027722� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Regression tests for rescinding outstanding subscription requests. """ from twisted.words.protocols.jabber.client import IQ from servicetest import EventPattern, assertEquals, assertLength, call_async from gabbletest import exec_test, acknowledge_iq from rostertest import expect_contact_list_signals, check_contact_list_signals import constants as cs import ns jid = 'marco@barisione.lit' def test(q, bus, conn, stream, remove, local, modern): # Gabble asks for the roster; the server sends back an empty roster. event = q.expect('stream-iq', query_ns=ns.ROSTER) event.stanza['type'] = 'result' stream.send(event.stanza) pairs = expect_contact_list_signals(q, bus, conn, ['publish', 'subscribe', 'stored']) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'publish', []) subscribe = check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'subscribe', []) stored = check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'stored', []) assertLength(0, pairs) # i.e. we've checked all of them self_handle = conn.GetSelfHandle() h = conn.RequestHandles(cs.HT_CONTACT, [jid])[0] # Another client logged into our account (Gajim, say) wants to subscribe to # Marco's presence. First, per RFC 3921 it 'SHOULD perform a "roster set" # for the new roster item': # # <iq type='set'> # <query xmlns='jabber:iq:roster'> # <item jid='marco@barisione.lit'/> # </query> # </iq> # # 'As a result, the user's server (1) MUST initiate a roster push for the # new roster item to all available resources associated with this user that # have requested the roster, setting the 'subscription' attribute to a # value of "none"': iq = IQ(stream, "set") item = iq.addElement((ns.ROSTER, 'query')).addElement('item') item['jid'] = jid item['subscription'] = 'none' stream.send(iq) # In response, Gabble should add Marco to stored: q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=['', [h], [], [], [], 0, 0], path=stored.object_path), EventPattern('dbus-signal', signal='ContactsChanged', args=[{ h: (cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_NO, ''), }, []], ), ) # Gajim sends a <presence type='subscribe'/> to Marco. 'As a result, the # user's server MUST initiate a second roster push to all of the user's # available resources that have requested the roster, setting [...] # ask='subscribe' attribute in the roster item [for Marco]: iq = IQ(stream, "set") item = iq.addElement((ns.ROSTER, 'query')).addElement('item') item['jid'] = jid item['subscription'] = 'none' item['ask'] = 'subscribe' stream.send(iq) # In response, Gabble should add Marco to subscribe:remote-pending: q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=['', [], [], [], [h], self_handle, 0], path=subscribe.object_path), EventPattern('dbus-signal', signal='ContactsChanged', args=[{ h: (cs.SUBSCRIPTION_STATE_ASK, cs.SUBSCRIPTION_STATE_NO, ''), }, []], ), ) # The user decides that they don't care what Marco's baking after all # (maybe they read his blog instead?) and: if remove: # ...removes him from the roster... if local: # ...by telling Gabble to remove him from stored. if modern: call_async(q, conn.ContactList, 'RemoveContacts', [h]) else: call_async(q, stored.Group, 'RemoveMembers', [h], '') event = q.expect('stream-iq', iq_type='set', query_ns=ns.ROSTER) item = event.query.firstChildElement() assertEquals(jid, item['jid']) assertEquals('remove', item['subscription']) else: # ...using the other client. pass # The server must 'inform all of the user's available resources that # have requested the roster of the roster item removal': iq = IQ(stream, "set") item = iq.addElement((ns.ROSTER, 'query')).addElement('item') item['jid'] = jid item['subscription'] = 'remove' # When Marco found this bug, this roster update included: item['ask'] = 'subscribe' # which is a bit weird: I don't think the server should send that when # the contact's being removed. I think Gabble should ignore it, so I'm # including it in the test. stream.send(iq) # In response, Gabble should announce that Marco has been removed from # subscribe:remote-pending and stored:members: q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=['', [], [h], [], [], 0, 0], path=subscribe.object_path), EventPattern('dbus-signal', signal='MembersChanged', args=['', [], [h], [], [], 0, 0], path=stored.object_path), EventPattern('dbus-signal', signal='ContactsChanged', args=[{}, [h]], ), ) if local and modern: acknowledge_iq(stream, event.stanza) q.expect('dbus-return', method='RemoveContacts') # FIXME: when we depend on a new enough tp-glib we can expect # RemoveMembers to return here in the local case, too else: # ...rescinds the subscription request... if local: # ...by telling Gabble to remove him from 'subscribe'. if modern: call_async(q, conn.ContactList, 'Unsubscribe', [h]) else: subscribe.Group.RemoveMembers([h], '') events = [EventPattern('stream-presence', to=jid, presence_type='unsubscribe')] if modern: events.append(EventPattern('dbus-return', method='Unsubscribe')) event = q.expect_many(*events)[0] else: # ...in the other client. pass # In response, the server sends a roster update: iq = IQ(stream, "set") item = iq.addElement((ns.ROSTER, 'query')).addElement('item') item['jid'] = jid item['subscription'] = 'none' # no ask='subscribe' any more. stream.send(iq) # In response, Gabble should announce that Marco has been removed from # subscribe:remote-pending. It shouldn't wait for the <presence # type='unsubscribed'/> ack before doing so: empirical tests reveal # that it's never delivered. q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=['', [], [h], [], [], 0, 0], path=subscribe.object_path), EventPattern('dbus-signal', signal='ContactsChanged', args=[{ h: (cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_NO, ''), }, []], ), ) def test_remove_local(q, bus, conn, stream): test(q, bus, conn, stream, remove=True, local=True, modern=True) def test_unsubscribe_local(q, bus, conn, stream): test(q, bus, conn, stream, remove=False, local=True, modern=True) def test_remove_remote(q, bus, conn, stream): test(q, bus, conn, stream, remove=True, local=False, modern=True) def test_unsubscribe_remote(q, bus, conn, stream): test(q, bus, conn, stream, remove=False, local=False, modern=True) def test_remove_local_old(q, bus, conn, stream): test(q, bus, conn, stream, remove=True, local=True, modern=False) def test_unsubscribe_local_old(q, bus, conn, stream): test(q, bus, conn, stream, remove=False, local=True, modern=False) def test_remove_remote_old(q, bus, conn, stream): test(q, bus, conn, stream, remove=True, local=False, modern=False) def test_unsubscribe_remote_old(q, bus, conn, stream): test(q, bus, conn, stream, remove=False, local=False, modern=False) if __name__ == '__main__': exec_test(test_remove_local) exec_test(test_unsubscribe_local) exec_test(test_remove_remote) exec_test(test_unsubscribe_remote) exec_test(test_remove_local_old) exec_test(test_unsubscribe_local_old) exec_test(test_remove_remote_old) exec_test(test_unsubscribe_remote_old) ��������������telepathy-gabble-0.18.3/tests/twisted/roster/push-without-id.py�������������������������������������0000664�0001750�0001750�00000004364�12332441362�025774� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Ensure that Gabble correctly handles broken roster pushes from servers that omit id='', in flagrant violation of XMPP Core. (Sadly these servers exist, so we should interop with them. Think of it of like No_Reply in D-Bus... """ from servicetest import EventPattern, sync_dbus from gabbletest import exec_test, acknowledge_iq, sync_stream from rostertest import ( make_roster_push, expect_contact_list_signals, check_contact_list_signals, ) import ns import constants as cs jid = 'moonboots@xsf.lit' def test(q, bus, conn, stream): # Gabble asks for the roster; the server sends back an empty roster. event = q.expect('stream-iq', query_ns=ns.ROSTER) acknowledge_iq(stream, event.stanza) pairs = expect_contact_list_signals(q, bus, conn, ['stored']) stored = check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'stored', []) # The server sends us a roster push without an id=''. WTF! iq = make_roster_push(stream, jid, 'both') del iq['id'] stream.send(iq) h = conn.RequestHandles(cs.HT_CONTACT, [jid])[0] q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=['', [h], [], [], [], 0, 0], path=stored.object_path), EventPattern('dbus-signal', signal='ContactsChanged', args=[{ h: (cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_YES, ''), }, []], ), ) # Verify that Gabble didn't crash while trying to ack the push. sync_stream(q, stream) # Just for completeness, let's repeat this test with a malicious roster # push from a contact (rather than from our server). Our server's *really* # broken if it allows this. Nonetheless... iq = make_roster_push(stream, 'silvio@gov.it', 'both') del iq['id'] iq['from'] = 'silvio@gov.it' stream.send(iq) q.forbid_events( [ EventPattern('dbus-signal', signal='MembersChanged', path=stored.object_path), EventPattern('dbus-signal', signal='ContactsChanged'), ]) # Make sure Gabble's got the evil push... sync_stream(q, stream) # ...and make sure it's not emitted anything. sync_dbus(bus, q, conn) if __name__ == '__main__': exec_test(test) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/roster/groups.py����������������������������������������������0000664�0001750�0001750�00000021003�12332441362�024226� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test basic roster group functionality. """ from gabbletest import exec_test, acknowledge_iq, sync_stream from rostertest import expect_contact_list_signals, check_contact_list_signals from servicetest import (assertLength, EventPattern, assertEquals, call_async, sync_dbus, assertContains, assertDoesNotContain) import constants as cs import ns from twisted.words.protocols.jabber.client import IQ from twisted.words.xish import xpath def parse_roster_change_request(query, iq): item = query.firstChildElement() groups = set() for gn in xpath.queryForNodes('/iq/query/item/group', iq): groups.add(str(gn)) return item['jid'], groups def send_roster_push(stream, jid, groups): iq = IQ(stream, 'set') query = iq.addElement((ns.ROSTER, 'query')) item = query.addElement('item') item['jid'] = jid item['subscription'] = 'both' for group in groups: item.addElement('group', content=group) stream.send(iq) def test(q, bus, conn, stream): event = q.expect('stream-iq', query_ns=ns.ROSTER) event.stanza['type'] = 'result' item = event.query.addElement('item') item['jid'] = 'amy@foo.com' item['subscription'] = 'both' item.addElement('group', content='women') item = event.query.addElement('item') item['jid'] = 'bob@foo.com' item['subscription'] = 'from' item.addElement('group', content='men') item = event.query.addElement('item') item['jid'] = 'che@foo.com' item['subscription'] = 'to' item.addElement('group', content='men') stream.send(event.stanza) # Avoid relying on the implementation detail of exactly when # TpBaseContactList emits ContactsChanged, relative to when it # announces its channels. Prior to 0.20.3, 0.21.1 it would # announce the channels, emit GroupsChanged, then announce the channels # again... which was a bug, but it turned out this test relied on it. # # We do still rely on the implementation detail that we emit GroupsChanged # once per group with all of its members, not once per contact with all # of their groups. On a typical contact list, there are more contacts # than groups, so that'll work out smaller. pairs, groups_changed = expect_contact_list_signals(q, bus, conn, [], ['men', 'women'], [ EventPattern('dbus-signal', signal='GroupsChanged', interface=cs.CONN_IFACE_CONTACT_GROUPS, path=conn.object_path, predicate=lambda e: 'women' in e.args[1]), EventPattern('dbus-signal', signal='GroupsChanged', interface=cs.CONN_IFACE_CONTACT_GROUPS, path=conn.object_path, predicate=lambda e: 'men' in e.args[1]), ]) amy, bob, che = conn.RequestHandles(cs.HT_CONTACT, ['amy@foo.com', 'bob@foo.com', 'che@foo.com']) assertEquals([[amy], ['women'], []], groups_changed[0].args) assertEquals([[bob, che], ['men'], []], groups_changed[1].args) q.expect('dbus-signal', signal='ContactListStateChanged', args=[cs.CONTACT_LIST_STATE_SUCCESS]) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_GROUP, 'men', ['bob@foo.com', 'che@foo.com']) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_GROUP, 'women', ['amy@foo.com']) assertLength(0, pairs) # i.e. we've checked all of them # change Amy's groups call_async(q, conn.ContactGroups, 'SetContactGroups', amy, ['ladies', 'people starting with A']) s, iq = q.expect_many( EventPattern('dbus-signal', signal='GroupsCreated'), EventPattern('stream-iq', iq_type='set', query_name='query', query_ns=ns.ROSTER), ) assertEquals(set(('ladies', 'people starting with A')), set(s.args[0])) jid, groups = parse_roster_change_request(iq.query, iq.stanza) assertEquals('amy@foo.com', jid) assertEquals(set(('ladies', 'people starting with A')), groups) acknowledge_iq(stream, iq.stanza) q.expect('dbus-return', method='SetContactGroups') # Now the server sends us a roster push. send_roster_push(stream, 'amy@foo.com', ['people starting with A', 'ladies']) # We get a single signal corresponding to that roster push e = q.expect('dbus-signal', signal='GroupsChanged', predicate=lambda e: e.args[0] == [amy]) assertEquals(set(['ladies', 'people starting with A']), set(e.args[1])) assertEquals(['women'], e.args[2]) # check that Amy's state is what we expected attrs = conn.Contacts.GetContactAttributes([amy], [cs.CONN_IFACE_CONTACT_GROUPS], False)[amy] # make the group list order-independent attrs[cs.CONN_IFACE_CONTACT_GROUPS + '/groups'] = \ set(attrs[cs.CONN_IFACE_CONTACT_GROUPS + '/groups']) assertEquals({ cs.CONN_IFACE_CONTACT_GROUPS + '/groups': set(['ladies', 'people starting with A']), cs.CONN + '/contact-id': 'amy@foo.com' }, attrs) for it_worked in (False, True): # remove a group with a member (the old API couldn't do this) call_async(q, conn.ContactGroups, 'RemoveGroup', 'people starting with A') iq = q.expect('stream-iq', iq_type='set', query_name='query', query_ns=ns.ROSTER) jid, groups = parse_roster_change_request(iq.query, iq.stanza) assertEquals('amy@foo.com', jid) assertEquals(set(('ladies',)), groups) acknowledge_iq(stream, iq.stanza) # we emit these as soon as the IQ is ack'd, so that we can indicate # group removal... q.expect('dbus-signal', signal='GroupsRemoved', args=[['people starting with A']]) q.expect('dbus-signal', signal='GroupsChanged', args=[[amy], [], ['people starting with A']]) q.expect('dbus-return', method='RemoveGroup') if it_worked: # ... although in fact this is what *actually* removes Amy from the # group send_roster_push(stream, 'amy@foo.com', ['ladies']) else: # if the change didn't "stick", this message will revert it send_roster_push(stream, 'amy@foo.com', ['ladies', 'people starting with A']) q.expect('dbus-signal', signal='GroupsCreated', args=[['people starting with A']]) q.expect('dbus-signal', signal='GroupsChanged', args=[[amy], ['people starting with A'], []]) sync_dbus(bus, q, conn) sync_stream(q, stream) assertEquals({ cs.CONN_IFACE_CONTACT_GROUPS + '/groups': ['ladies', 'people starting with A'], cs.CONN + '/contact-id': 'amy@foo.com' }, conn.Contacts.GetContactAttributes([amy], [cs.CONN_IFACE_CONTACT_GROUPS], False)[amy]) # sanity check: after all that, we expect Amy to be in group 'ladies' only sync_dbus(bus, q, conn) sync_stream(q, stream) assertEquals({ cs.CONN_IFACE_CONTACT_GROUPS + '/groups': ['ladies'], cs.CONN + '/contact-id': 'amy@foo.com' }, conn.Contacts.GetContactAttributes([amy], [cs.CONN_IFACE_CONTACT_GROUPS], False)[amy]) # Rename group 'ladies' to 'girls' call_async(q, conn.ContactGroups, 'RenameGroup', 'ladies', 'girls') # Amy is added to 'girls' e = q.expect('stream-iq', iq_type='set', query_name='query', query_ns=ns.ROSTER) jid, groups = parse_roster_change_request(e.query, e.stanza) assertEquals('amy@foo.com', jid) assertEquals(set(['girls', 'ladies']), groups) send_roster_push(stream, 'amy@foo.com', ['girls', 'ladies']) acknowledge_iq(stream, e.stanza) # Amy is removed from 'ladies' e = q.expect('stream-iq', iq_type='set', query_name='query', query_ns=ns.ROSTER) jid, groups = parse_roster_change_request(e.query, e.stanza) assertEquals('amy@foo.com', jid) assertEquals(set(['girls']), groups) send_roster_push(stream, 'amy@foo.com', ['girls']) acknowledge_iq(stream, e.stanza) q.expect('dbus-return', method='RenameGroup') # check everything has been updated groups = conn.Properties.Get(cs.CONN_IFACE_CONTACT_GROUPS, 'Groups') assertContains('girls', groups) assertDoesNotContain('ladies', groups) contacts = conn.ContactList.GetContactListAttributes([cs.CONN_IFACE_CONTACT_GROUPS], False) assertEquals(['girls'], contacts[amy][cs.CONN_IFACE_CONTACT_GROUPS + '/groups']) if __name__ == '__main__': exec_test(test) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/roster/initial-aliases.py�������������������������������������0000664�0001750�0001750�00000002771�12332441362�025772� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test retrieving the aliases after connection. """ from servicetest import ( assertContains, assertLength ) from gabbletest import ( exec_test, make_result_iq ) import constants as cs import ns def add_contact(iq, jid, alias): query = iq.firstChildElement() item = query.addElement('item') item['jid'] = jid item['name'] = alias item['subscription'] = 'both' def test(q, bus, conn, stream): """ Check that when we receive a roster update we emit a single AliasesChanged for all the contacts. """ conn.Connect() # Gabble asks the server for the initial roster event = q.expect('stream-iq', iq_type='get', query_ns=ns.ROSTER) result = make_result_iq(stream, event.stanza) # We reply with a roster with two contacts bob_jid = 'bob.smith@example.com' bob_alias = 'Bob Smith' add_contact(result, bob_jid, bob_alias) alice_jid = 'alice@example.com' alice_alias = 'Alice' add_contact(result, alice_jid, alice_alias) stream.send(result) # Check we get a single AliasesChanged for both contacts event = q.expect('dbus-signal', signal='AliasesChanged') added = event.args[0] bob_handle, alice_handle = conn.RequestHandles(cs.HT_CONTACT, [bob_jid, alice_jid]) assertLength(2, added) assertContains((bob_handle, bob_alias), added) assertContains((alice_handle, alice_alias), added) if __name__ == '__main__': exec_test(test, do_connect=False) �������telepathy-gabble-0.18.3/tests/twisted/roster/request-group-before-roster.py�������������������������0000664�0001750�0001750�00000003415�12332441362�030314� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Regression test for a bug where RequestChannel times out when requesting a group channel if the roster hasn't been received at the time of the call. """ from gabbletest import exec_test, sync_stream from servicetest import sync_dbus, call_async import constants as cs import ns def test(q, bus, conn, stream): roster_event = q.expect('stream-iq', query_ns=ns.ROSTER) roster_event.stanza['type'] = 'result' call_async(q, conn, "RequestHandles", cs.HT_GROUP, ['test']) event = q.expect('dbus-return', method='RequestHandles') test_handle = event.value[0][0] call_async(q, conn, 'RequestChannel', cs.CHANNEL_TYPE_CONTACT_LIST, cs.HT_GROUP, test_handle, True) # A previous incarnation of this test --- written with the intention that # RequestChannel would be called before the roster was received, to expose # a bug in Gabble triggered by that ordering --- was racy: if the D-Bus # daemon happened to be particularly busy, the call to RequestChannel # reached Gabble after the roster stanza. (The race was discovered when # that reversed order triggered a newly-introduced instance of the # opposite bug to the one the test was targetting!) So we sync the XMPP # stream and D-Bus queue here. sync_stream(q, stream) sync_dbus(bus, q, conn) # send an empty roster stream.send(roster_event.stanza) event = q.expect('dbus-return', method='RequestChannel') path = event.value[0] while True: event = q.expect('dbus-signal', signal='NewChannel') assert event.args[0] == path, (event.args, path) _, type, handle_type, handle, suppress_handler = event.args if handle_type == cs.HT_GROUP and handle == test_handle: break if __name__ == '__main__': exec_test(test) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/roster/ensure.py����������������������������������������������0000664�0001750�0001750�00000003304�12332441362�024214� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test ensuring roster channels """ from gabbletest import exec_test from servicetest import call_async import constants as cs import ns def test(q, bus, conn, stream): roster_event = q.expect('stream-iq', query_ns=ns.ROSTER) roster_event.stanza['type'] = 'result' call_async(q, conn, "RequestHandles", cs.HT_GROUP, ['test']) event = q.expect('dbus-return', method='RequestHandles') test_handle = event.value[0][0] # send an empty roster stream.send(roster_event.stanza) call_async(q, conn.Requests, 'EnsureChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CONTACT_LIST, cs.TARGET_HANDLE_TYPE: cs.HT_GROUP, cs.TARGET_HANDLE: test_handle, }) call_async(q, conn.Requests, 'EnsureChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CONTACT_LIST, cs.TARGET_HANDLE_TYPE: cs.HT_GROUP, cs.TARGET_HANDLE: test_handle, }) ret = q.expect('dbus-return', method='EnsureChannel') ret2 = q.expect('dbus-return', method='EnsureChannel') # We don't test the NewChannels signal here - depending on exact timing, # it might happen between the two EnsureChannel calls, or after the second # one. yours, path, props = ret.value yours2, path2, props2 = ret2.value assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_CONTACT_LIST, props assert props[cs.TARGET_HANDLE_TYPE] == cs.HT_GROUP, props assert props[cs.TARGET_HANDLE] == test_handle, props assert props[cs.TARGET_ID] == 'test', props assert yours != yours2, (yours, yours2) assert path == path2, (path, path2) assert props == props2, (props, props2) if __name__ == '__main__': exec_test(test) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/roster/test-google-roster.py����������������������������������0000664�0001750�0001750�00000055777�12332441362�026505� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# vim: set fileencoding=utf-8 : """ Test workarounds for gtalk """ from gabbletest import ( acknowledge_iq, exec_test, sync_stream, make_result_iq, GoogleXmlStream, ) from rostertest import ( expect_contact_list_signals, check_contact_list_signals, ) from servicetest import ( call_async, sync_dbus, EventPattern, assertLength, assertEquals, assertContains, assertDoesNotContain, ) import constants as cs import ns from twisted.words.protocols.jabber.client import IQ from twisted.words.xish import domish def make_set_roster_iq(stream, user, contact, state, ask, attrs={}): iq = IQ(stream, 'set') query = iq.addElement((ns.ROSTER, 'query')) add_gr_attributes(query) add_roster_item(query, contact, state, ask, attrs=attrs) return iq def add_gr_attributes(query): query['xmlns:gr'] = ns.GOOGLE_ROSTER query['gr:ext'] = '2' def add_roster_item(query, contact, state, ask, attrs={}): item = query.addElement('item') item['jid'] = contact item['subscription'] = state if ask: item['ask'] = 'subscribe' for k, v in attrs.iteritems(): item[k] = v return item def is_stored(event): return event.path.endswith('/stored') def is_subscribe(event): return event.path.endswith('/subscribe') def is_publish(event): return event.path.endswith('/publish') def is_deny(event): return event.path.endswith('/deny') def test_inital_roster(q, bus, conn, stream): """ This part of the test checks that Gabble correctly alters on which lists contacts appear based on the google:roster attributes and special-cases. """ event = q.expect('stream-iq', query_ns=ns.ROSTER) query = event.query assertContains('gr', query.localPrefixes) assertEquals(ns.GOOGLE_ROSTER, query.localPrefixes['gr']) # We support version 2 of Google's extensions. assertEquals('2', query[(ns.GOOGLE_ROSTER, 'ext')]) result = make_result_iq(stream, event.stanza) query = result.firstChildElement() add_gr_attributes(query) # Gabble suppresses contacts labelled as "hidden" from all roster channels. add_roster_item(query, 'should-be-hidden@example.com', 'both', False, {'gr:t': 'H'}) # Gabble should hide contacts on the Google roster with subscription="none" # and ask!="subscribe", to hide contacts which are actually just email # addresses. (This is in line with Pidgin; the code there was added by Sean # Egan, who worked on Google Talk for Google at the time.) add_roster_item(query, 'probably-an-email-address@badger.com', 'none', False) # This contact is remote pending, so we shouldn't suppress it. add_roster_item(query, 'this-is-a-jid@badger.com', 'none', True) add_roster_item(query, 'lp-bug-398293@gmail.com', 'both', False, {'gr:autosub': 'true'}) # These contacts are blocked but we're subscribed to them, so they should # show up in all of the lists. add_roster_item(query, 'blocked-but-subscribed@boards.ca', 'both', False, {'gr:t': 'B'}) add_roster_item(query, 'music-is-math@boards.ca', 'both', False, {'gr:t': 'B'}) # This contact is blocked, and we have no other subscription to them; so, # they should not show up in 'stored'. add_roster_item(query, 'blocked-and-no-sub@boards.ca', 'none', False, {'gr:t': 'B'}) # Send back the roster stream.send(result) # Since s-b-h had the "hidden" flag set, we don't expect them to be on any # lists. But we do want the "autosub" contact to be visible; see # <https://bugs.launchpad.net/ubuntu/+source/telepathy-gabble/+bug/398293>, # where Gabble was incorrectly hiding valid contacts. mutually_subscribed_contacts = ['lp-bug-398293@gmail.com', 'blocked-but-subscribed@boards.ca', 'music-is-math@boards.ca'] rp_contacts = ['this-is-a-jid@badger.com'] blocked_contacts = ['blocked-but-subscribed@boards.ca', 'blocked-and-no-sub@boards.ca', 'music-is-math@boards.ca'] pairs = expect_contact_list_signals(q, bus, conn, ['publish', 'subscribe', 'stored', 'deny']) publish = check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'publish', mutually_subscribed_contacts) subscribe = check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'subscribe', mutually_subscribed_contacts, rp_contacts=rp_contacts) stored = check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'stored', mutually_subscribed_contacts + rp_contacts) deny = check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'deny', blocked_contacts) assertLength(0, pairs) # i.e. we've checked all of them return (publish, subscribe, stored, deny) def test_flickering(q, bus, conn, stream, subscribe): """ Google's server is buggy; when asking to subscribe to somebody, the subscription state transitions "flicker" sometimes. Here, we test that Gabble is suppressing the flickers. """ self_handle = conn.GetSelfHandle() contact = 'bob@foo.com' handle = conn.RequestHandles(cs.HT_CONTACT, ['bob@foo.com'])[0] # request subscription call_async(q, subscribe.Group, 'AddMembers', [handle], "") event = q.expect('stream-iq', iq_type='set', query_ns=ns.ROSTER) item = event.query.firstChildElement() assertEquals(contact, item['jid']) acknowledge_iq(stream, event.stanza) # FIXME: when we depend on a new enough tp-glib we could expect # AddMembers to return at this point # send empty roster item iq = make_set_roster_iq(stream, 'test@localhost/Resource', contact, "none", False) stream.send(iq) # We don't expect the stored list to be updated here, because Gabble # ignores Google Talk roster items with subscription="none" and # ask!="subscribe" as described above. event = q.expect('stream-presence', presence_type='subscribe') # Google's server appears to be buggy. If you send # <presence type='subscribe'/> # it sends: # 1. A roster update with ask="subscribe"; # 2. Another roster update, without ask="subscribe"; # 3. A third roster update, with ask="subscribe". # Gabble should work around this, to avoid spuriously informing the UI that # the subscription request was declined. # Send roster update 1: none, ask=subscribe iq = make_set_roster_iq(stream, 'test@localhost/Resource', contact, "none", True) stream.send(iq) # Gabble should report this update to the UI. q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=['', [handle], [], [], [], 0, cs.GC_REASON_NONE], predicate=is_stored), EventPattern('dbus-signal', signal='MembersChanged', args=['', [], [], [], [handle], self_handle, cs.GC_REASON_NONE], predicate=is_subscribe), EventPattern('dbus-signal', signal='ContactsChanged', args=[{handle: (cs.SUBSCRIPTION_STATE_ASK, cs.SUBSCRIPTION_STATE_NO, ''), }, []]), ) # Gabble shouldn't report any changes to subscribe or stored's members in # response to the next two roster updates. change_events = [ EventPattern('dbus-signal', signal='MembersChanged', predicate=is_subscribe), EventPattern('dbus-signal', signal='MembersChanged', predicate=is_stored), EventPattern('dbus-signal', signal='ContactsChanged'), ] q.forbid_events(change_events) # Send roster update 2: none iq = make_set_roster_iq(stream, 'test@localhost/Resource', contact, "none", False) stream.send(iq) # Send roster update 3: none, ask=subscribe iq = make_set_roster_iq(stream, 'test@localhost/Resource', contact, "none", True) stream.send(iq) # Neither of those should have been signalled as a change to the subscribe # list sync_stream(q, stream) sync_dbus(bus, q, conn) q.unforbid_events(change_events) # Also, when the contact accepts the subscription request, they flicker # similarly: # 1. subscription='to' # 2. subscription='none' ask='subscribe' # 3. subscription='to' # Again, Gabble should work around this rather than informing the UI that a # subscription request was accepted twice. # Send roster update 1: subscription=to (accepted) iq = make_set_roster_iq(stream, 'test@localhost/Resource', contact, "to", False) stream.send(iq) presence = domish.Element(('jabber:client', 'presence')) presence['from'] = 'bob@foo.com' presence['type'] = 'subscribed' stream.send(presence) # Gabble should report this update to the UI. q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=['', [handle], [], [], [], handle, cs.GC_REASON_NONE], predicate=is_subscribe), EventPattern('dbus-signal', signal='ContactsChanged', args=[{handle: (cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_NO, ''), }, []]), ) # Gabble shouldn't report any changes to subscribe or stored's members in # response to the next two roster updates. q.forbid_events(change_events) # Send roster update 2: subscription=none, ask=subscribe (pending again) iq = make_set_roster_iq(stream, 'test@localhost/Resource', contact, "none", True) stream.send(iq) # Send roster update 3: subscript=to (accepted again) iq = make_set_roster_iq(stream, 'test@localhost/Resource', contact, "to", False) stream.send(iq) # Neither of those should have been signalled as a change to the subscribe # list sync_stream(q, stream) sync_dbus(bus, q, conn) q.unforbid_events(change_events) def test_local_pending(q, bus, conn, stream, subscribe): """ When somebody asks to subscribe to us, Google sends the subscription request and then a roster update saying there is no subscription. This causes the contact to appear in local pending and then disappear. Here, we test that Gabble is suppressing the flickers. """ contact = 'alice@foo.com' handle = conn.RequestHandles(cs.HT_CONTACT, [contact])[0] # Alice asks to subscribes to us presence = domish.Element(('jabber:client', 'presence')) presence['from'] = contact presence['type'] = 'subscribe' stream.send(presence) q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=['', [], [], [handle], [], handle, cs.GC_REASON_NONE], predicate=is_publish), EventPattern('dbus-signal', signal='ContactsChanged', args=[{handle: (cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_ASK, '')}, []]), ) # Now we send the spurious roster update with subscribe="none" and verify # that nothing happens to her publish state in reaction to that change_event = EventPattern('dbus-signal', signal='MembersChanged', predicate=is_publish) q.forbid_events([change_event]) iq = make_set_roster_iq(stream, 'test@localhost/Resource', contact, "none", False) stream.send(iq) sync_stream(q, stream) sync_dbus(bus, q, conn) q.unforbid_events([change_event]) # Now we cancel alice's subscription request and verify that if the # redundant IQ is sent again, it's safely handled presence = domish.Element(('jabber:client', 'presence')) presence['from'] = contact presence['type'] = 'unsubscribe' stream.send(presence) q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=['', [], [handle], [], [], handle, cs.GC_REASON_NONE], predicate=is_publish), EventPattern('dbus-signal', signal='ContactsChanged', args=[{handle: (cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_REMOVED_REMOTELY, '')}, []]), ) # Now we send a roster roster update with subscribe="none" again (which # doesn't change anything, it just confirms what we already knew) and # verify that nothing happens to her publish state in reaction to that. q.forbid_events([change_event]) iq = make_set_roster_iq(stream, 'test@localhost/Resource', contact, "none", False) stream.send(iq) sync_stream(q, stream) sync_dbus(bus, q, conn) q.unforbid_events([change_event]) # This event is forbidden in all of the deny tests! remove_events = [ EventPattern('stream-iq', query_ns=ns.ROSTER, predicate=(lambda event: event.query.firstChildElement()['subscription'] == 'remove'), ) ] def test_deny_simple(q, bus, conn, stream, stored, deny): """ If we remove a blocked contact from 'stored', they shouldn't actually be removed from the roster: rather, we should cancel both subscription directions, at which point they will vanish from 'stored', while remaining on 'deny'. """ contact = 'blocked-but-subscribed@boards.ca' handle = conn.RequestHandles(cs.HT_CONTACT, [contact])[0] assertContains(handle, stored.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) call_async(q, stored.Group, 'RemoveMembers', [handle], "") q.forbid_events(remove_events) q.expect_many( EventPattern('stream-presence', to=contact, presence_type='unsubscribe'), EventPattern('stream-presence', to=contact, presence_type='unsubscribed'), EventPattern('dbus-return', method='RemoveMembers'), ) # Our server sends roster pushes in response to our unsubscribe and # unsubscribed commands. stream.send(make_set_roster_iq(stream, 'test@localhost/Resource', contact, "from", False, attrs={'gr:t': 'B'})) stream.send(make_set_roster_iq(stream, 'test@localhost/Resource', contact, "none", False, attrs={'gr:t': 'B'})) # As a result they should drop off all three non-deny lists, but not fall # off deny: q.expect_many( EventPattern('dbus-signal', signal='ContactsChanged', args=[{}, [handle]]), *[ EventPattern('dbus-signal', signal='MembersChanged', args=['', [], [handle], [], [], 0, cs.GC_REASON_NONE], predicate=p) for p in [is_stored, is_subscribe, is_publish] ]) assertContains(handle, deny.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) q.unforbid_events(remove_events) def test_deny_overlap_one(q, bus, conn, stream, subscribe, stored, deny): """ Here's a tricker case: blocking a contact, and then removing them before the server's responded to the block request. """ self_handle = conn.GetSelfHandle() # As we saw in test_flickering(), we have a subscription to Bob, # everything's peachy. contact = 'bob@foo.com' handle = conn.RequestHandles(cs.HT_CONTACT, ['bob@foo.com'])[0] assertContains(handle, stored.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) assertContains(handle, subscribe.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) q.forbid_events(remove_events) # But then we have a falling out. In a blind rage, I block Bob: call_async(q, deny.Group, 'AddMembers', [handle], "") event = q.expect('stream-iq', query_ns=ns.ROSTER) item = event.query.firstChildElement() assertEquals(contact, item['jid']) assertEquals('B', item[(ns.GOOGLE_ROSTER, 't')]) # Then — *before the server has replied* — I remove him from stored. call_async(q, stored.Group, 'RemoveMembers', [handle], "") # subscription='remove' is still forbidden from above. So we sync to ensure # that Gabble's received RemoveMembers, and if it's going to send us a # remove (or premature <presence type='unsubscribe'/>) we catch it. sync_dbus(bus, q, conn) sync_stream(q, stream) # So now we send a roster push and reply for the block request. stream.send(make_set_roster_iq(stream, 'test@localhost/Resource', contact, 'to', False, attrs={ 'gr:t': 'B' })) acknowledge_iq(stream, event.stanza) # At which point, Bob should appear on 'deny', and Gabble should send an # unsubscribe, but *not* an unsubscribe*d* because Bob wasn't subscribed to # us! unsubscribed_events = [ EventPattern('stream-presence', presence_type='unsubscribed') ] q.forbid_events(unsubscribed_events) q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', predicate=is_deny, args=["", [handle], [], [], [], self_handle, 0]), EventPattern('stream-presence', to=contact, presence_type='unsubscribe'), ) # And our server sends us a roster push in response to unsubscribe: stream.send(make_set_roster_iq(stream, 'test@localhost/Resource', contact, "none", False, attrs={'gr:t': 'B'})) # As a result, Gabble makes Bob fall off subscribe and stored. q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', predicate=is_subscribe, args=["", [], [handle], [], [], 0, 0]), EventPattern('dbus-signal', signal='MembersChanged', predicate=is_stored, args=["", [], [handle], [], [], 0, 0]), EventPattern('dbus-signal', signal='ContactsChanged', args=[{}, [handle]]), ) # And he should definitely still be on deny. That rascal. assertContains(handle, deny.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) q.unforbid_events(unsubscribed_events) q.unforbid_events(remove_events) def test_deny_overlap_two(q, bus, conn, stream, subscribe, publish, stored, deny): """ Here's another tricky case: editing a contact (setting an alias, say), and then while that edit's in flight, blocking and remove the contact. """ # This contact was on our roster when we started. contact = 'lp-bug-398293@gmail.com' handle = conn.RequestHandles(cs.HT_CONTACT, [contact])[0] assertContains(handle, stored.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) assertContains(handle, subscribe.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) assertContains(handle, publish.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) # Once again, at no point in this test should anyone be removed outright. q.forbid_events(remove_events) # First up, we edit the contact's alias, triggering a roster update from # the client. conn.Aliasing.SetAliases({handle: 'oh! the huge manatee!'}) event = q.expect('stream-iq', query_ns=ns.ROSTER) item = event.query.firstChildElement() assertEquals(contact, item['jid']) assertEquals('oh! the huge manatee!', item['name']) # Before the server responds, we block and remove the contact. The edits # should be queued... patterns = [ EventPattern('stream-iq', query_ns=ns.ROSTER), EventPattern('stream-presence', presence_type='unsubscribed'), EventPattern('stream-presence', presence_type='unsubscribe'), ] q.forbid_events(patterns) call_async(q, deny.Group, 'AddMembers', [handle], "") call_async(q, stored.Group, 'RemoveMembers', [handle], "") # Make sure if the edits are sent prematurely, we've got them. sync_stream(q, stream) q.unforbid_events(patterns) # Okay, now we respond to the alias update. At this point we expect an # update to gr:t=B, leaving subscription=both intact, and subscription # cancellations. acknowledge_iq(stream, event.stanza) roster_event, _, _ = q.expect_many(*patterns) item = roster_event.query.firstChildElement() assertEquals(contact, item['jid']) assertEquals('B', item[(ns.GOOGLE_ROSTER, 't')]) # And we're done. Clean up. q.unforbid_events(remove_events) def test_deny_unblock_remove(q, bus, conn, stream, stored, deny): """ Test unblocking a contact, and, while that request is pending, deleting them. """ self_handle = conn.GetSelfHandle() # This contact was on our roster, blocked and subscribed, when we started. contact = 'music-is-math@boards.ca' handle = conn.RequestHandles(cs.HT_CONTACT, [contact])[0] # They're blocked, and we have a bidi subscription, so they should be on # deny and stored. (We already checked this earlier, but we've been messing # with the roster so let's be sure the preconditions are okay...) assertContains(handle, deny.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) assertContains(handle, stored.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) # Unblock them. call_async(q, deny.Group, 'RemoveMembers', [handle], "") roster_event = q.expect('stream-iq', query_ns=ns.ROSTER) item = roster_event.query.firstChildElement() assertEquals(contact, item['jid']) assertDoesNotContain((ns.GOOGLE_ROSTER, 't'), item.attributes) # If we now remove them from stored, the edit shouldn't be sent until the # unblock event has had a reply. q.forbid_events(remove_events) call_async(q, stored.Group, 'RemoveMembers', [handle], "") # Make sure if the remove is sent prematurely, we catch it. sync_stream(q, stream) q.unforbid_events(remove_events) # So now we send a roster push and reply for the unblock request. stream.send(make_set_roster_iq(stream, 'test@localhost/Resource', contact, 'both', False, attrs={})) acknowledge_iq(stream, roster_event.stanza) # And on receiving the push and reply, Gabble should show them being # removed from deny, and send a remove. _, roster_event = q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=['', [], [handle], [], [], self_handle, cs.GC_REASON_NONE], predicate=is_deny), remove_events[0], ) item = roster_event.query.firstChildElement() assertEquals(contact, item['jid']) stream.send(make_set_roster_iq(stream, 'test@localhost/Resource', contact, 'remove', False, attrs={})) acknowledge_iq(stream, roster_event.stanza) q.expect('dbus-signal', signal='MembersChanged', args=['', [], [handle], [], [], 0, cs.GC_REASON_NONE], predicate=is_stored) def test_contact_blocking(q, bus, conn, stream, stored, deny): """test ContactBlocking API""" assertContains(cs.CONN_IFACE_CONTACT_BLOCKING, conn.Properties.Get(cs.CONN, "Interfaces")) # 3 contacts are blocked blocked = conn.RequestBlockedContacts(dbus_interface=cs.CONN_IFACE_CONTACT_BLOCKING) assertLength(3, blocked) def test(q, bus, conn, stream): publish, subscribe, stored, deny = test_inital_roster(q, bus, conn, stream) test_flickering(q, bus, conn, stream, subscribe) test_local_pending(q, bus, conn, stream, subscribe) test_deny_simple(q, bus, conn, stream, stored, deny) test_deny_overlap_one(q, bus, conn, stream, subscribe, stored, deny) test_deny_overlap_two(q, bus, conn, stream, subscribe, publish, stored, deny) test_deny_unblock_remove(q, bus, conn, stream, stored, deny) test_contact_blocking(q, bus, conn, stream, stored, deny) if __name__ == '__main__': exec_test(test, protocol=GoogleXmlStream) �telepathy-gabble-0.18.3/tests/twisted/roster/edit-before-roster.py����������������������������������0000664�0001750�0001750�00000010433�12332441362�026415� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test editing the roster before we've received it. """ from gabbletest import exec_test, acknowledge_iq, sync_stream from servicetest import (EventPattern, assertEquals, call_async, sync_dbus) import constants as cs import ns from twisted.words.protocols.jabber.client import IQ from twisted.words.xish import xpath def test(q, bus, conn, stream): event = q.expect('stream-iq', query_ns=ns.ROSTER) event.stanza['type'] = 'result' item = event.query.addElement('item') item['jid'] = 'amy@foo.com' item['subscription'] = 'both' item.addElement('group', content='women') item = event.query.addElement('item') item['jid'] = 'bob@foo.com' item['subscription'] = 'from' item.addElement('group', content='men') item = event.query.addElement('item') item['jid'] = 'che@foo.com' item['subscription'] = 'to' item.addElement('group', content='men') # Before we get the roster, try to change something. It won't work. amy, bob, che = conn.RequestHandles(cs.HT_CONTACT, ['amy@foo.com', 'bob@foo.com', 'che@foo.com']) call_async(q, conn.ContactGroups, 'AddToGroup', 'Amy & Bob', [amy, bob]) q.expect('dbus-error', method='AddToGroup', name=cs.NOT_YET) # Now send the roster, and things will happen. stream.send(event.stanza) def mentions_amy(e): return bool(xpath.queryForNodes('/iq/query/item[@jid = "amy@foo.com"]', e.stanza)) def mentions_bob(e): return bool(xpath.queryForNodes('/iq/query/item[@jid = "bob@foo.com"]', e.stanza)) s1, s2, _ = q.expect_many( EventPattern('dbus-signal', signal='GroupsChanged', interface=cs.CONN_IFACE_CONTACT_GROUPS, path=conn.object_path, predicate=lambda e: 'women' in e.args[1]), EventPattern('dbus-signal', signal='GroupsChanged', interface=cs.CONN_IFACE_CONTACT_GROUPS, path=conn.object_path, predicate=lambda e: 'men' in e.args[1]), EventPattern('dbus-signal', signal='ContactListStateChanged', args=[cs.CONTACT_LIST_STATE_SUCCESS]), ) call_async(q, conn.ContactGroups, 'AddToGroup', 'Amy & Bob', [amy, bob]) set1, set2 = q.expect_many( EventPattern('stream-iq', query_ns=ns.ROSTER, query_name='query', iq_type='set', predicate=mentions_amy), EventPattern('stream-iq', query_ns=ns.ROSTER, query_name='query', iq_type='set', predicate=mentions_bob), ) assertEquals([[amy], ['women'], []], s1.args) assertEquals([[bob, che], ['men'], []], s2.args) item = set1.query.firstChildElement() assertEquals('amy@foo.com', item['jid']) groups = set() for gn in xpath.queryForNodes('/iq/query/item/group', set1.stanza): groups.add(str(gn)) assertEquals(set(('Amy & Bob', 'women')), groups) item = set2.query.firstChildElement() assertEquals('bob@foo.com', item['jid']) groups = set() for gn in xpath.queryForNodes('/iq/query/item/group', set2.stanza): groups.add(str(gn)) assertEquals(set(('Amy & Bob', 'men')), groups) # Send a couple of roster pushes to reflect Amy and Bob's new states. iq = IQ(stream, 'set') query = iq.addElement((ns.ROSTER, 'query')) item = query.addElement('item') item['jid'] = 'amy@foo.com' item['subscription'] = 'both' item.addElement('group', content='women') item.addElement('group', content='Amy & Bob') stream.send(iq) q.expect('dbus-signal', signal='GroupsChanged', args=[[amy], ['Amy & Bob'], []]) iq = IQ(stream, 'set') query = iq.addElement((ns.ROSTER, 'query')) item = query.addElement('item') item['jid'] = 'bob@foo.com' item['subscription'] = 'both' item.addElement('group', content='men') item.addElement('group', content='Amy & Bob') stream.send(iq) q.expect('dbus-signal', signal='GroupsChanged', args=[[bob], ['Amy & Bob'], []]) # Acknowledge Amy's IQ, but make sure we don't see the acknowledgement # until Bob's IQ has replied too acknowledge_iq(stream, set1.stanza) sync_dbus(bus, q, conn) sync_stream(q, stream) # When we get the reply for Bob, it actually happens. acknowledge_iq(stream, set2.stanza) q.expect('dbus-return', method='AddToGroup') if __name__ == '__main__': exec_test(test) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/roster/test-roster-subscribe.py�������������������������������0000664�0001750�0001750�00000024034�12332441362�027170� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- encoding:utf-8 -*- """ Test subscribing to a contact's presence. """ from twisted.words.xish import domish from servicetest import (EventPattern, assertLength, assertEquals, call_async, wrap_channel, sync_dbus) from gabbletest import (acknowledge_iq, exec_test, sync_stream) from rostertest import send_roster_push import constants as cs import ns def test_ancient(q, bus, conn, stream): test(q, bus, conn, stream, False) def test_modern(q, bus, conn, stream): test(q, bus, conn, stream, True) def test_ancient_remove(q, bus, conn, stream): test(q, bus, conn, stream, False, True) def test_modern_remove(q, bus, conn, stream): test(q, bus, conn, stream, True, True) def test_ancient_reject(q, bus, conn, stream): test(q, bus, conn, stream, False, 'reject') def test_modern_reject(q, bus, conn, stream): test(q, bus, conn, stream, True, 'reject') def test_ancient_reject_remove(q, bus, conn, stream): test(q, bus, conn, stream, False, True, 'reject') def test_modern_reject_remove(q, bus, conn, stream): test(q, bus, conn, stream, True, True, 'reject') def test_ancient_revoke(q, bus, conn, stream): test(q, bus, conn, stream, False, 'revoke') def test_modern_revoke(q, bus, conn, stream): test(q, bus, conn, stream, True, 'revoke') def test_ancient_revoke_remove(q, bus, conn, stream): test(q, bus, conn, stream, False, True, 'revoke') def test_modern_revoke_remove(q, bus, conn, stream): test(q, bus, conn, stream, True, True, 'revoke') def test(q, bus, conn, stream, modern=True, remove=False, remote='accept'): event = q.expect('stream-iq', query_ns=ns.ROSTER) # send back empty roster event.stanza['type'] = 'result' stream.send(event.stanza) while True: event = q.expect('dbus-signal', signal='NewChannel') path, type, handle_type, handle, suppress_handler = event.args if type != cs.CHANNEL_TYPE_CONTACT_LIST: continue chan_name = conn.InspectHandles(handle_type, [handle])[0] if chan_name == 'subscribe': break chan = wrap_channel(bus.get_object(conn.bus_name, path), 'ContactList') assertLength(0, chan.Group.GetMembers()) stored_path = conn.Requests.EnsureChannel({ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CONTACT_LIST, cs.TARGET_HANDLE_TYPE: cs.HT_LIST, cs.TARGET_ID: 'stored', })[1] stored = wrap_channel(bus.get_object(conn.bus_name, stored_path), 'ContactList') # request subscription alice, bob = conn.RequestHandles(cs.HT_CONTACT, ['alice@foo.com', 'bob@foo.com']) # Repeated subscription requests are *not* idempotent: the second request # should nag the contact again. for first_time in True, False, False: if modern: call_async(q, conn.ContactList, 'RequestSubscription', [bob], 'plz add kthx') else: call_async(q, chan.Group, 'AddMembers', [bob], 'plz add kthx') if first_time: event = q.expect('stream-iq', iq_type='set', query_ns=ns.ROSTER) item = event.query.firstChildElement() assertEquals('bob@foo.com', item["jid"]) acknowledge_iq(stream, event.stanza) expectations = [ EventPattern('stream-presence', presence_type='subscribe'), ] if modern: expectations.append(EventPattern('dbus-return', method='RequestSubscription')) event = q.expect_many(*expectations)[0] assertEquals('plz add kthx', event.presence_status) if first_time: # Our server sends a roster push indicating that yes, we added him send_roster_push(stream, 'bob@foo.com', 'none') q.expect('stream-iq', iq_type='result', iq_id='push') # Our server will also send a roster push with the ask=subscribe # sub-state, in response to our <presence type=subscribe>. # (RFC 3921 §8.2.4) send_roster_push(stream, 'bob@foo.com', 'none', True) q.expect('stream-iq', iq_type='result', iq_id='push') if remote == 'reject': # Bob rejects our request. presence = domish.Element(('jabber:client', 'presence')) presence['from'] = 'bob@foo.com' presence['type'] = 'unsubscribed' stream.send(presence) q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=['', [], [bob], [], [], bob, cs.GC_REASON_PERMISSION_DENIED]), #EventPattern('stream-presence'), EventPattern('dbus-signal', signal='ContactsChanged', args=[{bob: (cs.SUBSCRIPTION_STATE_REMOVED_REMOTELY, cs.SUBSCRIPTION_STATE_NO, ''), }, []]), ) send_roster_push(stream, 'bob@foo.com', 'to') q.expect('stream-iq', iq_type='result', iq_id='push') else: # Bob accepts presence = domish.Element(('jabber:client', 'presence')) presence['from'] = 'bob@foo.com' presence['type'] = 'subscribed' stream.send(presence) q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=['', [bob], [], [], [], bob, 0]), EventPattern('stream-presence'), EventPattern('dbus-signal', signal='ContactsChanged', args=[{bob: (cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_NO, ''), }, []]), ) send_roster_push(stream, 'bob@foo.com', 'to') q.expect('stream-iq', iq_type='result', iq_id='push') # Doing the same again is a successful no-op forbidden = [EventPattern('stream-iq', query_ns=ns.ROSTER), EventPattern('stream-presence')] sync_stream(q, stream) sync_dbus(bus, q, conn) q.forbid_events(forbidden) call_async(q, conn.ContactList, 'RequestSubscription', [bob], 'moo') q.expect('dbus-return', method='RequestSubscription') # Alice is not on the list call_async(q, conn.ContactList, 'Unsubscribe', [alice]) q.expect('dbus-return', method='Unsubscribe') call_async(q, conn.ContactList, 'RemoveContacts', [alice]) q.expect('dbus-return', method='RemoveContacts') sync_stream(q, stream) sync_dbus(bus, q, conn) q.unforbid_events(forbidden) if remote == 'revoke': # After accepting us, Bob then removes us. presence = domish.Element(('jabber:client', 'presence')) presence['from'] = 'bob@foo.com' presence['type'] = 'unsubscribed' stream.send(presence) q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=['', [], [bob], [], [], bob, cs.GC_REASON_PERMISSION_DENIED]), EventPattern('stream-presence'), EventPattern('dbus-signal', signal='ContactsChanged', args=[{bob: (cs.SUBSCRIPTION_STATE_REMOVED_REMOTELY, cs.SUBSCRIPTION_STATE_NO, ''), }, []]), ) # Else, Bob isn't actually as interesting as we thought. Never mind, # we can unsubscribe or remove him (below), with the same APIs we'd # use to acknowledge remote removal. # (Unsubscribing from pending-subscribe is tested in # roster/removed-from-rp-subscribe.py so we don't test it here.) # If Bob removed us, we have to use modern APIs from now on, because from # the point of view of the old Group interface, removed remotely and # removed locally are synonymous. if remote in ('reject', 'revoke'): modern = True if modern: if remove: returning_method = 'RemoveContacts' call_async(q, conn.ContactList, 'RemoveContacts', [bob]) else: returning_method = 'Unsubscribe' call_async(q, conn.ContactList, 'Unsubscribe', [bob]) else: returning_method = 'RemoveMembers' if remove: call_async(q, stored.Group, 'RemoveMembers', [bob], '') else: call_async(q, chan.Group, 'RemoveMembers', [bob], '') if remove: iq = q.expect('stream-iq', iq_type='set', query_ns=ns.ROSTER, query_name='query') acknowledge_iq(stream, iq.stanza) if modern: q.expect('dbus-return', method='RemoveContacts') # FIXME: when we depend on a new enough tp-glib, expect RemoveMembers # to return here too send_roster_push(stream, 'bob@foo.com', 'remove') q.expect_many( EventPattern('stream-iq', iq_type='result', iq_id='push'), EventPattern('dbus-signal', signal='ContactsChanged', args=[{}, [bob]]), ) else: q.expect_many( EventPattern('dbus-return', method=returning_method), EventPattern('stream-presence', presence_type='unsubscribe', to='bob@foo.com'), ) send_roster_push(stream, 'bob@foo.com', 'none') q.expect_many( EventPattern('stream-iq', iq_type='result', iq_id='push'), EventPattern('dbus-signal', signal='ContactsChanged', args=[{bob: (cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_NO, ''), }, []]), ) if __name__ == '__main__': exec_test(test_ancient) exec_test(test_modern) exec_test(test_ancient_remove) exec_test(test_modern_remove) exec_test(test_ancient_revoke) exec_test(test_modern_revoke) exec_test(test_ancient_revoke_remove) exec_test(test_modern_revoke_remove) exec_test(test_ancient_reject) exec_test(test_modern_reject) exec_test(test_ancient_reject_remove) exec_test(test_modern_reject_remove) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/roster/test-roster-item-deletion.py���������������������������0000664�0001750�0001750�00000007205�12332441362�027747� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Regression test for http://bugs.freedesktop.org/show_bug.cgi?id=19524 """ from gabbletest import exec_test, acknowledge_iq from rostertest import (expect_contact_list_signals, check_contact_list_signals, send_roster_push) from servicetest import (assertLength, assertEquals, EventPattern, call_async) import constants as cs import ns def test_ancient(q, bus, conn, stream): test(q, bus, conn, stream, False) def test_modern(q, bus, conn, stream): test(q, bus, conn, stream, True) def test_ancient_queued(q, bus, conn, stream): test(q, bus, conn, stream, False, True) def test_modern_queued(q, bus, conn, stream): test(q, bus, conn, stream, True, True) def test(q, bus, conn, stream, modern=True, queued=False): event = q.expect('stream-iq', query_ns=ns.ROSTER) event.stanza['type'] = 'result' item = event.query.addElement('item') item['jid'] = 'quux@foo.com' item['subscription'] = 'none' quux_handle = conn.RequestHandles(cs.HT_CONTACT, ['quux@foo.com'])[0] stream.send(event.stanza) # slight implementation detail: TpBaseContactList emits ContactsChanged # before it announces its channels q.expect('dbus-signal', signal='ContactsChanged', interface=cs.CONN_IFACE_CONTACT_LIST, path=conn.object_path, args=[{quux_handle: (cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_NO, '')}, []]) pairs = expect_contact_list_signals(q, bus, conn, ['publish', 'subscribe', 'stored']) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'publish', []) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'subscribe', []) stored = check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'stored', ['quux@foo.com']) assertLength(0, pairs) # i.e. we've checked all of them if queued: conn.Aliasing.SetAliases({quux_handle: 'Quux'}) set_aliases = q.expect('stream-iq', query_ns=ns.ROSTER) item = set_aliases.query.firstChildElement() assertEquals('quux@foo.com', item['jid']) assertEquals('Quux', item['name']) expectations = [ EventPattern('stream-iq', iq_type='set', query_ns=ns.ROSTER), ] if modern: call_async(q, conn.ContactList, 'RemoveContacts', [quux_handle]) else: call_async(q, stored.Group, 'RemoveMembers', [quux_handle], '') if queued: # finish off the previous thing we were doing, so removal can proceed acknowledge_iq(stream, set_aliases.stanza) event = q.expect_many(*expectations)[0] item = event.query.firstChildElement() assertEquals('quux@foo.com', item['jid']) assertEquals('remove', item['subscription']) send_roster_push(stream, 'quux@foo.com', 'remove') q.expect_many( EventPattern('dbus-signal', interface=cs.CHANNEL_IFACE_GROUP, path=stored.object_path, signal='MembersChanged', args=['', [], [quux_handle], [], [], 0, 0]), EventPattern('dbus-signal', interface=cs.CONN_IFACE_CONTACT_LIST, path=conn.object_path, signal='ContactsChanged', args=[{}, [quux_handle]]), EventPattern('stream-iq', iq_id='push', iq_type='result'), ) acknowledge_iq(stream, event.stanza) if modern: q.expect('dbus-return', method='RemoveContacts') # FIXME: when we depend on a new enough tp-glib, RemoveMembers should # return at this point too if __name__ == '__main__': exec_test(test_ancient) exec_test(test_modern) exec_test(test_ancient_queued) exec_test(test_modern_queued) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/roster/request-group-after-roster.py��������������������������0000664�0001750�0001750�00000002712�12332441362�030152� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Regression test for a bug where CreateChannel times out when requesting a group channel after the roster has been received. """ from gabbletest import exec_test, sync_stream from servicetest import sync_dbus, call_async import constants as cs import ns def test(q, bus, conn, stream): roster_event = q.expect('stream-iq', query_ns=ns.ROSTER) roster_event.stanza['type'] = 'result' call_async(q, conn, "RequestHandles", cs.HT_GROUP, ['test']) event = q.expect('dbus-return', method='RequestHandles') test_handle = event.value[0][0] # send an empty roster stream.send(roster_event.stanza) sync_stream(q, stream) sync_dbus(bus, q, conn) call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CONTACT_LIST, cs.TARGET_HANDLE_TYPE: cs.HT_GROUP, cs.TARGET_HANDLE: test_handle, }) event = q.expect('dbus-return', method='CreateChannel') ret_path, ret_props = event.value event = q.expect('dbus-signal', signal='NewChannels') path, props = event.args[0][0] assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_CONTACT_LIST, props assert props[cs.TARGET_HANDLE_TYPE] == cs.HT_GROUP, props assert props[cs.TARGET_HANDLE] == test_handle, props assert props[cs.TARGET_ID] == 'test', props assert ret_path == path, (ret_path, path) assert ret_props == props, (ret_props, props) if __name__ == '__main__': exec_test(test) ������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/roster/test-save-alias-to-roster.py���������������������������0000664�0001750�0001750�00000015765�12332441362�027667� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test that updating an alias saves it to the roster. """ import dbus from servicetest import EventPattern, call_async, assertEquals from gabbletest import ( acknowledge_iq, exec_test, make_result_iq, sync_stream, elem ) import constants as cs import ns from rostertest import expect_contact_list_signals, send_roster_push from pubsub import make_pubsub_event def send_pep_nick_reply(stream, stanza, nickname): result = make_result_iq(stream, stanza) pubsub = result.firstChildElement() items = pubsub.addElement('items') items['node'] = ns.NICK item = items.addElement('item') item.addElement('nick', ns.NICK, content=nickname) stream.send(result) def check_roster_write(stream, event, jid, name): item = event.query.firstChildElement() assertEquals(jid, item['jid']) # This copes with name=None assertEquals(name, item.getAttribute('name')) acknowledge_iq(stream, event.stanza) # RFC 3921 requires the server to send a roster push to all connected # resources whenever a resource updates the roster. Gabble depends on this # and pays no attention to its own nick update until the server sends a # push. send_roster_push(stream, jid, 'none', name=name) def expect_AliasesChanged_and_roster_write(q, stream, handle, jid, nick): roster_write = q.expect('stream-iq', iq_type='set', query_ns=ns.ROSTER) check_roster_write(stream, roster_write, jid, nick) q.expect('dbus-signal', signal='AliasesChanged', args=[[(handle, nick if nick else jid)]]) def test(q, bus, conn, stream): event, event2 = q.expect_many( EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', query_ns=ns.ROSTER)) acknowledge_iq(stream, event.stanza) acknowledge_iq(stream, event2.stanza) signals = expect_contact_list_signals(q, bus, conn, lists=['subscribe']) old_signal, new_signal = signals[0] path = old_signal.args[0] # request subscription chan = bus.get_object(conn.bus_name, path) group_iface = dbus.Interface(chan, cs.CHANNEL_IFACE_GROUP) assert group_iface.GetMembers() == [] handle = conn.RequestHandles(1, ['bob@foo.com'])[0] call_async(q, group_iface, 'AddMembers', [handle], '') event = q.expect('stream-iq', iq_type='set', query_ns=ns.ROSTER) item = event.query.firstChildElement() acknowledge_iq(stream, event.stanza) q.expect('dbus-return', method='AddMembers') call_async(q, conn.Aliasing, 'RequestAliases', [handle]) event = q.expect('stream-iq', iq_type='get', query_ns='http://jabber.org/protocol/pubsub', to='bob@foo.com') send_pep_nick_reply(stream, event.stanza, 'Bobby') event, _ = q.expect_many( EventPattern('stream-iq', iq_type='set', query_ns=ns.ROSTER), EventPattern('dbus-return', method='RequestAliases', value=(['Bobby'],))) check_roster_write(stream, event, 'bob@foo.com', 'Bobby') # We get a roster push for a contact who for some reason has their alias # set on our roster to the empty string (maybe a buggy client?). It's never # useful for Gabble to say that someone's alias is the empty string (given # the current semantics where the alias is always meant to be something you # could show, even if it's just their JID), so let's forbid that. jid = 'parts@labor.lit' handle = conn.RequestHandles(cs.HT_CONTACT, [jid])[0] q.forbid_events([EventPattern('dbus-signal', signal='AliasesChanged', args=[[(handle, '')]])]) send_roster_push(stream, jid, 'both', name='') # I don't really have very strong opinions on whether Gabble should be # signalling that this contact's alias has *changed* per se, so am not # explicitly expecting that. q.expect('dbus-signal', signal='MembersChanged') # But if we ask for it, Gabble should probably send a PEP query. assertEquals(jid, conn.Aliasing.GetAliases([handle])[handle]) event = q.expect('stream-iq', iq_type='get', query_ns=ns.PUBSUB, to=jid) nick = 'Constant Future' send_pep_nick_reply(stream, event.stanza, nick) expect_AliasesChanged_and_roster_write(q, stream, handle, jid, nick) # Here's another contact, whose alias is set on our roster to their JID: # because we've cached that they have no alias. Gabble shouldn't make # unsolicited PEP or vCard queries to them. jid = 'friendly@faith.plate' handle = conn.RequestHandles(cs.HT_CONTACT, [jid])[0] q.forbid_events([ EventPattern('stream-iq', query_ns=ns.PUBSUB, to=jid), EventPattern('stream-iq', query_ns=ns.VCARD_TEMP, to=jid), ]) send_roster_push(stream, jid, 'both', name=jid) q.expect('dbus-signal', signal='AliasesChanged', args=[[(handle, jid)]]) sync_stream(q, stream) # But if we get a PEP nickname update for this contact, Gabble should use # the new nickname, and write it back to the roster. nick = u'The Friendly Faith Plate' stream.send(make_pubsub_event(jid, ns.NICK, elem(ns.NICK, 'nick')(nick))) expect_AliasesChanged_and_roster_write(q, stream, handle, jid, nick) # As an undocumented extension, we treat setting the alias to the empty # string to mean "whatever the contact says their nickname is". (The rest # of this test is a regression test for # <https://bugs.freedesktop.org/show_bug.cgi?id=11321>.) # # So first up, let's change the Friendly Faith Plate's nickname to # something else. custom_nick = u'I saw a deer today' conn.Aliasing.SetAliases({handle: custom_nick}) expect_AliasesChanged_and_roster_write(q, stream, handle, jid, custom_nick) assertEquals([custom_nick], conn.Aliasing.RequestAliases([handle])) # And now set it to the empty string. Since Gabble happens to have a # nickname this contact specified cached, it should switch over to that one. conn.Aliasing.SetAliases({handle: ''}) expect_AliasesChanged_and_roster_write(q, stream, handle, jid, nick) assertEquals([nick], conn.Aliasing.RequestAliases([handle])) # Here's a contact we haven't seen before, pushed to our roster with a # nickname already there. jid = 'glados@aperture.lit' handle = conn.RequestHandles(cs.HT_CONTACT, [jid])[0] nick = 'Potato' send_roster_push(stream, jid, 'both', name=nick) q.expect('dbus-signal', signal='AliasesChanged', args=[[(handle, nick)]]) # If the user clears their alias, we should expect Gabble to say over D-Bus # that their nickname is their jid, and send a roster push removing the # name='' attribute... conn.Aliasing.SetAliases({handle: ''}) expect_AliasesChanged_and_roster_write(q, stream, handle, jid, None) # ...and also send a PEP query to find a better nickname; when the contact # replies, Gabble should update the roster accordingly. event = q.expect('stream-iq', iq_type='get', query_ns=ns.PUBSUB, to=jid) send_pep_nick_reply(stream, event.stanza, 'GLaDOS') expect_AliasesChanged_and_roster_write(q, stream, handle, jid, 'GLaDOS') if __name__ == '__main__': exec_test(test) �����������telepathy-gabble-0.18.3/tests/twisted/roster/authorize.py�������������������������������������������0000664�0001750�0001750�00000026644�12332441362�024741� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test receiving and authorizing publish requests, including "pre-authorization" (authorizing publication before someone asks for it). """ from gabbletest import (exec_test, sync_stream, acknowledge_iq) from rostertest import (expect_contact_list_signals, check_contact_list_signals, send_roster_push) from servicetest import (assertEquals, assertLength, call_async, EventPattern, sync_dbus) import constants as cs import ns from twisted.words.xish import domish def test(q, bus, conn, stream, modern=True, remove=False): call_async(q, conn.ContactList, 'GetContactListAttributes', [], False) q.expect('dbus-error', method='GetContactListAttributes', name=cs.NOT_YET) event = q.expect('stream-iq', query_ns=ns.ROSTER) item = event.query.addElement('item') item['jid'] = 'holly@example.com' item['subscription'] = 'both' event.stanza['type'] = 'result' stream.send(event.stanza) holly, dave, arnold, kristine, cat = conn.RequestHandles(cs.HT_CONTACT, ['holly@example.com', 'dave@example.com', 'arnold@example.com', 'kristine@example.com', 'cat@example.com']) # slight implementation detail: TpBaseContactList emits ContactsChanged # before it announces its channels s = q.expect('dbus-signal', signal='ContactsChanged', interface=cs.CONN_IFACE_CONTACT_LIST, path=conn.object_path) assertEquals([{ holly: (cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_YES, ''), }, []], s.args) pairs = expect_contact_list_signals(q, bus, conn, ['publish', 'subscribe', 'stored']) # this is emitted last, so clients can tell when the initial state dump # has finished q.expect('dbus-signal', signal='ContactListStateChanged', args=[cs.CONTACT_LIST_STATE_SUCCESS]) call_async(q, conn.ContactList, 'GetContactListAttributes', [], False) r = q.expect('dbus-return', method='GetContactListAttributes') assertEquals(({ holly: { cs.CONN_IFACE_CONTACT_LIST + '/publish': cs.SUBSCRIPTION_STATE_YES, cs.CONN_IFACE_CONTACT_LIST + '/subscribe': cs.SUBSCRIPTION_STATE_YES, cs.CONN + '/contact-id': 'holly@example.com', } },), r.value) # check that the channels were as we expected too publish = check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'publish', ['holly@example.com']) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'subscribe', ['holly@example.com']) stored = check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'stored', ['holly@example.com']) assertLength(0, pairs) # i.e. we've checked all of them # publication authorized for Dave, Holly (the former is pre-authorization, # the latter is a no-op) if modern: call_async(q, conn.ContactList, 'AuthorizePublication', [dave, holly]) event = q.expect('dbus-return', method='AuthorizePublication') else: call_async(q, publish.Group, 'AddMembers', [dave, holly], '') event = q.expect('dbus-return', method='AddMembers') # Receive authorization requests from the contacts # We pre-authorized Dave, so this is automatically approved presence = domish.Element(('jabber:client', 'presence')) presence['type'] = 'subscribe' presence['from'] = 'dave@example.com' stream.send(presence) q.expect_many( EventPattern('dbus-signal', signal='ContactsChanged', args=[{dave: (cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_ASK, '')}, []]), EventPattern('stream-presence', presence_type='subscribed', to='dave@example.com'), ) # Our server responds to Dave being authorized send_roster_push(stream, 'dave@example.com', 'from') q.expect_many( EventPattern('stream-iq', iq_type='result', iq_id='push'), EventPattern('dbus-signal', signal='ContactsChanged', args=[{dave: (cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_YES, '')}, []]), ) # The request from Kristine needs authorization (below) presence['from'] = 'kristine@example.com' stream.send(presence) q.expect('dbus-signal', signal='ContactsChanged', args=[{kristine: (cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_ASK, '')}, []]) # This request from Arnold is dealt with below presence['from'] = 'arnold@example.com' stream.send(presence) q.expect('dbus-signal', signal='ContactsChanged', args=[{arnold: (cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_ASK, '')}, []]) if modern: returning_method = 'AuthorizePublication' call_async(q, conn.ContactList, 'AuthorizePublication', [kristine, holly]) else: returning_method = 'AddMembers' call_async(q, publish.Group, 'AddMembers', [kristine, holly], '') q.expect_many( EventPattern('dbus-return', method=returning_method), EventPattern('stream-presence', presence_type='subscribed', to='kristine@example.com'), ) # Our server acknowledges that we authorized Kristine. Holly's state # does not change. send_roster_push(stream, 'kristine@example.com', 'from') q.expect_many( EventPattern('dbus-signal', signal='ContactsChanged', args=[{kristine: (cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_YES, '')}, []]), EventPattern('stream-iq', iq_type='result', iq_id='push'), ) # Arnold gives up waiting for us, and cancels his request presence['from'] = 'arnold@example.com' presence['type'] = 'unsubscribe' stream.send(presence) q.expect_many( EventPattern('dbus-signal', signal='ContactsChanged', args=[{arnold: (cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_REMOVED_REMOTELY, '')}, []]), EventPattern('stream-presence', presence_type='unsubscribed', to='arnold@example.com'), ) # We can acknowledge that with RemoveContacts or with Unpublish. # The old Chan.T.ContactList API can't acknowledge RemovedRemotely, # because it sees it as "not there at all" and the group logic drops # the "redundant" request. if remove: returning_method = 'RemoveContacts' call_async(q, conn.ContactList, 'RemoveContacts', [arnold]) else: returning_method = 'Unpublish' call_async(q, conn.ContactList, 'Unpublish', [arnold]) # Even if we Unpublish() here, Arnold was never on our XMPP roster, # so setting his publish state to SUBSCRIPTION_STATE_NO should result # in his removal. q.expect_many( EventPattern('dbus-return', method=returning_method), EventPattern('dbus-signal', signal='ContactsChanged', args=[{}, [arnold]]), ) # Rejecting an authorization request also works presence = domish.Element(('jabber:client', 'presence')) presence['type'] = 'subscribe' presence['from'] = 'cat@example.com' stream.send(presence) q.expect('dbus-signal', signal='ContactsChanged', args=[{cat: (cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_ASK, '')}, []]) if modern: if remove: returning_method = 'RemoveContacts' call_async(q, conn.ContactList, 'RemoveContacts', [cat]) else: returning_method = 'Unpublish' call_async(q, conn.ContactList, 'Unpublish', [cat]) else: returning_method = 'RemoveMembers' if remove: call_async(q, stored.Group, 'RemoveMembers', [cat], '') else: call_async(q, publish.Group, 'RemoveMembers', [cat], '') # As above, the only reason the Cat is on our contact list is the pending # publish request, so Unpublish really results in removal. q.expect_many( EventPattern('dbus-return', method=returning_method), EventPattern('dbus-signal', signal='ContactsChanged', args=[{}, [cat]]), ) # Redundant API calls (removing an absent contact, etc.) cause no network # traffic, and succeed. forbidden = [EventPattern('stream-iq', query_ns=ns.ROSTER), EventPattern('stream-presence')] sync_stream(q, stream) sync_dbus(bus, q, conn) q.forbid_events(forbidden) call_async(q, conn.ContactList, 'AuthorizePublication', [kristine, holly, dave]) call_async(q, conn.ContactList, 'Unpublish', [arnold, cat]) call_async(q, conn.ContactList, 'RemoveContacts', [arnold, cat]) q.expect_many( EventPattern('dbus-return', method='AuthorizePublication'), EventPattern('dbus-return', method='Unpublish'), EventPattern('dbus-return', method='RemoveContacts'), ) sync_stream(q, stream) sync_dbus(bus, q, conn) q.unforbid_events(forbidden) # There's one more case: revoking the publish permission of someone who is # genuinely on the roster. if modern: if remove: returning_method = 'RemoveContacts' call_async(q, conn.ContactList, 'RemoveContacts', [holly]) else: returning_method = 'Unpublish' call_async(q, conn.ContactList, 'Unpublish', [holly]) else: returning_method = 'RemoveMembers' if remove: call_async(q, stored.Group, 'RemoveMembers', [holly], '') else: call_async(q, publish.Group, 'RemoveMembers', [holly], '') if remove: iq = q.expect('stream-iq', iq_type='set', query_ns=ns.ROSTER, query_name='query') acknowledge_iq(stream, iq.stanza) if modern: q.expect('dbus-return', method='RemoveContacts') # FIXME: when we depend on a new enough tp-glib, expect RemoveMembers # to return here too send_roster_push(stream, 'holly@example.com', 'remove') q.expect_many( EventPattern('stream-iq', iq_type='result', iq_id='push'), EventPattern('dbus-signal', signal='ContactsChanged', args=[{}, [holly]]), ) else: q.expect_many( EventPattern('dbus-return', method=returning_method), EventPattern('stream-presence', presence_type='unsubscribed', to='holly@example.com'), ) send_roster_push(stream, 'holly@example.com', 'to') q.expect_many( EventPattern('stream-iq', iq_type='result', iq_id='push'), EventPattern('dbus-signal', signal='ContactsChanged', args=[{holly: (cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_NO, ''), }, []]), ) def test_ancient(q, bus, conn, stream): test(q, bus, conn, stream, modern=False) def test_ancient_remove(q, bus, conn, stream): test(q, bus, conn, stream, modern=False, remove=True) def test_modern(q, bus, conn, stream): test(q, bus, conn, stream, modern=True) def test_modern_remove(q, bus, conn, stream): test(q, bus, conn, stream, modern=True, remove=True) if __name__ == '__main__': exec_test(test_ancient) exec_test(test_ancient_remove) exec_test(test_modern) exec_test(test_modern_remove) ��������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/roster/test-roster.py�����������������������������������������0000664�0001750�0001750�00000006733�12332441362�025217� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test basic roster functionality. """ from gabbletest import exec_test from rostertest import expect_contact_list_signals, check_contact_list_signals from servicetest import (assertEquals, assertLength, call_async) import constants as cs import ns def test(q, bus, conn, stream): call_async(q, conn.ContactList, 'GetContactListAttributes', [], False) q.expect('dbus-error', method='GetContactListAttributes', name=cs.NOT_YET) event = q.expect('stream-iq', query_ns=ns.ROSTER) event.stanza['type'] = 'result' item = event.query.addElement('item') item['jid'] = 'amy@foo.com' item['subscription'] = 'both' item = event.query.addElement('item') item['jid'] = 'bob@foo.com' item['subscription'] = 'from' item = event.query.addElement('item') item['jid'] = 'che@foo.com' item['subscription'] = 'to' stream.send(event.stanza) # Regression test for <https://bugs.freedesktop.org/show_bug.cgi?id=42186>: # some super-buggy XMPP server running on vk.com sends its reply to our # roster query twice. This used to crash Gabble. stream.send(event.stanza) # slight implementation detail: TpBaseContactList emits ContactsChanged # before it announces its channels s = q.expect('dbus-signal', signal='ContactsChanged', interface=cs.CONN_IFACE_CONTACT_LIST, path=conn.object_path) amy, bob, che = conn.RequestHandles(cs.HT_CONTACT, ['amy@foo.com', 'bob@foo.com', 'che@foo.com']) assertEquals([{ amy: (cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_YES, ''), bob: (cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_YES, ''), che: (cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_NO, ''), }, []], s.args) pairs = expect_contact_list_signals(q, bus, conn, ['publish', 'subscribe', 'stored']) # this is emitted last, so clients can tell when the initial state dump # has finished q.expect('dbus-signal', signal='ContactListStateChanged', args=[cs.CONTACT_LIST_STATE_SUCCESS]) call_async(q, conn.ContactList, 'GetContactListAttributes', [], False) r = q.expect('dbus-return', method='GetContactListAttributes') assertEquals(({ amy: { cs.CONN_IFACE_CONTACT_LIST + '/subscribe': cs.SUBSCRIPTION_STATE_YES, cs.CONN_IFACE_CONTACT_LIST + '/publish': cs.SUBSCRIPTION_STATE_YES, cs.CONN + '/contact-id': 'amy@foo.com', }, bob: { cs.CONN_IFACE_CONTACT_LIST + '/subscribe': cs.SUBSCRIPTION_STATE_NO, cs.CONN_IFACE_CONTACT_LIST + '/publish': cs.SUBSCRIPTION_STATE_YES, cs.CONN + '/contact-id': 'bob@foo.com', }, che: { cs.CONN_IFACE_CONTACT_LIST + '/subscribe': cs.SUBSCRIPTION_STATE_YES, cs.CONN_IFACE_CONTACT_LIST + '/publish': cs.SUBSCRIPTION_STATE_NO, cs.CONN + '/contact-id': 'che@foo.com', }, },), r.value) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'publish', ['amy@foo.com', 'bob@foo.com']) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'subscribe', ['amy@foo.com', 'che@foo.com']) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'stored', ['amy@foo.com', 'bob@foo.com', 'che@foo.com']) assertLength(0, pairs) # i.e. we've checked all of them if __name__ == '__main__': exec_test(test) �������������������������������������telepathy-gabble-0.18.3/tests/twisted/roster/groups-12791.py����������������������������������������0000664�0001750�0001750�00000006473�12332441362�024725� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test broken groups on the roster (regression test for fd.o #12791) """ import dbus from gabbletest import exec_test from rostertest import expect_contact_list_signals, check_contact_list_signals from servicetest import assertLength import constants as cs import ns def _expect_group_channel(q, bus, conn, name, contacts): event = q.expect('dbus-signal', signal='NewChannel') path, type, handle_type, handle, suppress_handler = event.args assert type == cs.CHANNEL_TYPE_CONTACT_LIST, type assert handle_type == cs.HT_GROUP, handle_type inspected = conn.InspectHandles(handle_type, [handle])[0] assert inspected == name, (inspected, name) chan = bus.get_object(conn.bus_name, path) group_iface = dbus.Interface(chan, cs.CHANNEL_IFACE_GROUP) inspected = conn.InspectHandles(cs.HT_CONTACT, group_iface.GetMembers()) assert inspected == contacts, (inspected, contacts) def test(q, bus, conn, stream): event = q.expect('stream-iq', query_ns=ns.ROSTER) event.stanza['type'] = 'result' item = event.query.addElement('item') item['jid'] = 'amy@foo.com' item['subscription'] = 'both' item.addElement('group', content='women') item.addElement('group', content='affected-by-fdo-12791') # This is a broken roster - Amy appears twice. This should only happen # if the server is somehow buggy. This was my initial attempt at # reproducing fd.o #12791 - I doubt it's very realistic, but we shouldn't # assert, regardless of what input we get! item = event.query.addElement('item') item['jid'] = 'amy@foo.com' item['subscription'] = 'both' item.addElement('group', content='women') item = event.query.addElement('item') item['jid'] = 'bob@foo.com' item['subscription'] = 'from' item.addElement('group', content='men') # This is what was *actually* strange about the #12791 submitter's roster - # Bob appears, fully subscribed, but also there's an attempt to subscribe # to one of Bob's resources. We now ignore such items item = event.query.addElement('item') item['jid'] = 'bob@foo.com/Resource' item['subscription'] = 'none' item['ask'] = 'subscribe' item = event.query.addElement('item') item['jid'] = 'che@foo.com' item['subscription'] = 'to' item.addElement('group', content='men') stream.send(event.stanza) pairs = expect_contact_list_signals(q, bus, conn, ['publish', 'subscribe', 'stored'], ['men', 'women', 'affected-by-fdo-12791']) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'publish', ['amy@foo.com', 'bob@foo.com']) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'subscribe', ['amy@foo.com', 'che@foo.com']) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, 'stored', ['amy@foo.com', 'bob@foo.com', 'che@foo.com']) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_GROUP, 'men', ['bob@foo.com', 'che@foo.com']) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_GROUP, 'women', ['amy@foo.com']) check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_GROUP, 'affected-by-fdo-12791', []) assertLength(0, pairs) # i.e. we've checked all of them if __name__ == '__main__': exec_test(test) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/version.py����������������������������������������������������0000664�0001750�0001750�00000002367�12332441362�023072� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# vim: set encoding=utf-8 : """ Tests Gabble's implementation of XEP-0092. """ from twisted.words.xish import xpath from servicetest import assertLength, assertEquals from gabbletest import exec_test, elem_iq, elem import ns def test(q, bus, conn, stream): request = elem_iq(stream, 'get')( elem(ns.VERSION, 'query') ) stream.send(request) reply = q.expect('stream-iq', iq_id=request['id'], query_ns=ns.VERSION, query_name='query') # Both <name/> and <version/> are REQUIRED. What they actually contain is # someone else's problem™. names = xpath.queryForNodes('/query/name', reply.query) assertLength(1, names) versions = xpath.queryForNodes('/query/version', reply.query) assertLength(1, versions) # <os/> is OPTIONAL. “Revealing the application's underlying operating # system may open the user or system to attacks directed against that # operating system; therefore, an application MUST provide a way for a # human user or administrator to disable sharing of information about the # operating system.” The “way” that we provide is never to send it. oss = xpath.queryForNodes('/query/os', reply.query) assert oss is None if __name__ == '__main__': exec_test(test) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/servicetest.py������������������������������������������������0000664�0001750�0001750�00000051361�12332441362�023743� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Infrastructure code for testing connection managers. """ from twisted.internet import glib2reactor from twisted.internet.protocol import Protocol, Factory, ClientFactory glib2reactor.install() import sys import time import os import pprint import unittest import dbus.glib from twisted.internet import reactor import constants as cs tp_name_prefix = 'org.freedesktop.Telepathy' tp_path_prefix = '/org/freedesktop/Telepathy' class DictionarySupersetOf (object): """Utility class for expecting "a dictionary with at least these keys".""" def __init__(self, dictionary): self._dictionary = dictionary def __repr__(self): return "DictionarySupersetOf(%s)" % self._dictionary def __eq__(self, other): """would like to just do: return set(other.items()).issuperset(self._dictionary.items()) but it turns out that this doesn't work if you have another dict nested in the values of your dicts""" try: for k,v in self._dictionary.items(): if k not in other or other[k] != v: return False return True except TypeError: # other is not iterable return False class Event(object): def __init__(self, type, **kw): self.__dict__.update(kw) self.type = type (self.subqueue, self.subtype) = type.split ("-", 1) def __str__(self): return '\n'.join([ str(type(self)) ] + format_event(self)) def format_event(event): ret = ['- type %s' % event.type] for key in sorted(dir(event)): if key != 'type' and not key.startswith('_'): ret.append('- %s: %s' % ( key, pprint.pformat(getattr(event, key)))) if key == 'error': ret.append('%s' % getattr(event, key)) return ret class EventPattern: def __init__(self, type, **properties): self.type = type self.predicate = None if 'predicate' in properties: self.predicate = properties['predicate'] del properties['predicate'] self.properties = properties (self.subqueue, self.subtype) = type.split ("-", 1) def __repr__(self): properties = dict(self.properties) if self.predicate is not None: properties['predicate'] = self.predicate return '%s(%r, **%r)' % ( self.__class__.__name__, self.type, properties) def match(self, event): if event.type != self.type: return False for key, value in self.properties.iteritems(): try: if getattr(event, key) != value: return False except AttributeError: return False if self.predicate is None or self.predicate(event): return True return False class TimeoutError(Exception): pass class ForbiddenEventOccurred(Exception): def __init__(self, event): Exception.__init__(self) self.event = event def __str__(self): return '\n' + '\n'.join(format_event(self.event)) class BaseEventQueue: """Abstract event queue base class. Implement the wait() method to have something that works. """ def __init__(self, timeout=None): self.verbose = False self.forbidden_events = set() self.event_queues = {} if timeout is None: self.timeout = 5 else: self.timeout = timeout def log(self, s): if self.verbose: print s def log_queues(self, queues): self.log ("Waiting for event on: %s" % ", ".join(queues)) def log_event(self, event): self.log('got event:') if self.verbose: map(self.log, format_event(event)) def forbid_events(self, patterns): """ Add patterns (an iterable of EventPattern) to the set of forbidden events. If a forbidden event occurs during an expect or expect_many, the test will fail. """ self.forbidden_events.update(set(patterns)) def unforbid_events(self, patterns): """ Remove 'patterns' (an iterable of EventPattern) from the set of forbidden events. These must be the same EventPattern pointers that were passed to forbid_events. """ self.forbidden_events.difference_update(set(patterns)) def unforbid_all(self): """ Remove all patterns from the set of forbidden events. """ self.forbidden_events.clear() def _check_forbidden(self, event): for e in self.forbidden_events: if e.match(event): raise ForbiddenEventOccurred(event) def expect(self, type, **kw): """ Waits for an event matching the supplied pattern to occur, and returns it. For example, to await a D-Bus signal with particular arguments: e = q.expect('dbus-signal', signal='Badgers', args=["foo", 42]) """ pattern = EventPattern(type, **kw) t = time.time() while True: event = self.wait([pattern.subqueue]) self._check_forbidden(event) if pattern.match(event): self.log('handled, took %0.3f ms' % ((time.time() - t) * 1000.0) ) self.log('') return event self.log('not handled') self.log('') def expect_many(self, *patterns): """ Waits for events matching all of the supplied EventPattern instances to return, and returns a list of events in the same order as the patterns they matched. After a pattern is successfully matched, it is not considered for future events; if more than one unsatisfied pattern matches an event, the first "wins". Note that the expected events may occur in any order. If you're expecting a series of events in a particular order, use repeated calls to expect() instead. This method is useful when you're awaiting a number of events which may happen in any order. For instance, in telepathy-gabble, calling a D-Bus method often causes a value to be returned immediately, as well as a query to be sent to the server. Since these events may reach the test in either order, the following is incorrect and will fail if the IQ happens to reach the test first: ret = q.expect('dbus-return', method='Foo') query = q.expect('stream-iq', query_ns=ns.FOO) The following would be correct: ret, query = q.expect_many( EventPattern('dbus-return', method='Foo'), EventPattern('stream-iq', query_ns=ns.FOO), ) """ ret = [None] * len(patterns) t = time.time() while None in ret: try: queues = set() for i, pattern in enumerate(patterns): if ret[i] is None: queues.add(pattern.subqueue) event = self.wait(queues) except TimeoutError: self.log('timeout') self.log('still expecting:') for i, pattern in enumerate(patterns): if ret[i] is None: self.log(' - %r' % pattern) raise self._check_forbidden(event) for i, pattern in enumerate(patterns): if ret[i] is None and pattern.match(event): self.log('handled, took %0.3f ms' % ((time.time() - t) * 1000.0) ) self.log('') ret[i] = event break else: self.log('not handled') self.log('') return ret def demand(self, type, **kw): pattern = EventPattern(type, **kw) event = self.wait([pattern.subqueue]) if pattern.match(event): self.log('handled') self.log('') return event self.log('not handled') raise RuntimeError('expected %r, got %r' % (pattern, event)) def queues_available(self, queues): if queues == None: return self.event_queues.keys() else: available = self.event_queues.keys() return filter(lambda x: x in available, queues) def pop_next(self, queue): events = self.event_queues[queue] e = events.pop(0) if not events: self.event_queues.pop (queue) return e def append(self, event): self.log ("Adding to queue") self.log_event (event) self.event_queues[event.subqueue] = \ self.event_queues.get(event.subqueue, []) + [event] class IteratingEventQueue(BaseEventQueue): """Event queue that works by iterating the Twisted reactor.""" def __init__(self, timeout=None): BaseEventQueue.__init__(self, timeout) def wait(self, queues=None): stop = [False] def later(): stop[0] = True delayed_call = reactor.callLater(self.timeout, later) self.log_queues(queues) qa = self.queues_available(queues) while not qa and (not stop[0]): reactor.iterate(0.01) qa = self.queues_available(queues) if qa: delayed_call.cancel() e = self.pop_next (qa[0]) self.log_event (e) return e else: raise TimeoutError class TestEventQueue(BaseEventQueue): def __init__(self, events): BaseEventQueue.__init__(self) for e in events: self.append (e) def wait(self, queues = None): qa = self.queues_available(queues) if qa: return self.pop_next (qa[0]) else: raise TimeoutError class EventQueueTest(unittest.TestCase): def test_expect(self): queue = TestEventQueue([Event('test-foo'), Event('test-bar')]) assert queue.expect('test-foo').type == 'test-foo' assert queue.expect('test-bar').type == 'test-bar' def test_expect_many(self): queue = TestEventQueue([Event('test-foo'), Event('test-bar')]) bar, foo = queue.expect_many( EventPattern('test-bar'), EventPattern('test-foo')) assert bar.type == 'test-bar' assert foo.type == 'test-foo' def test_expect_many2(self): # Test that events are only matched against patterns that haven't yet # been matched. This tests a regression. queue = TestEventQueue([Event('test-foo', x=1), Event('test-foo', x=2)]) foo1, foo2 = queue.expect_many( EventPattern('test-foo'), EventPattern('test-foo')) assert foo1.type == 'test-foo' and foo1.x == 1 assert foo2.type == 'test-foo' and foo2.x == 2 def test_expect_queueing(self): queue = TestEventQueue([Event('foo-test', x=1), Event('foo-test', x=2)]) queue.append(Event('bar-test', x=1)) queue.append(Event('bar-test', x=2)) queue.append(Event('baz-test', x=1)) queue.append(Event('baz-test', x=2)) for x in xrange(1,2): e = queue.expect ('baz-test') assertEquals (x, e.x) e = queue.expect ('bar-test') assertEquals (x, e.x) e = queue.expect ('foo-test') assertEquals (x, e.x) def test_timeout(self): queue = TestEventQueue([]) self.assertRaises(TimeoutError, queue.expect, 'test-foo') def test_demand(self): queue = TestEventQueue([Event('test-foo'), Event('test-bar')]) foo = queue.demand('test-foo') assert foo.type == 'test-foo' def test_demand_fail(self): queue = TestEventQueue([Event('test-foo'), Event('test-bar')]) self.assertRaises(RuntimeError, queue.demand, 'test-bar') def unwrap(x): """Hack to unwrap D-Bus values, so that they're easier to read when printed.""" if isinstance(x, list): return map(unwrap, x) if isinstance(x, tuple): return tuple(map(unwrap, x)) if isinstance(x, dict): return dict([(unwrap(k), unwrap(v)) for k, v in x.iteritems()]) if isinstance(x, dbus.Boolean): return bool(x) for t in [unicode, str, long, int, float]: if isinstance(x, t): return t(x) return x def call_async(test, proxy, method, *args, **kw): """Call a D-Bus method asynchronously and generate an event for the resulting method return/error.""" def reply_func(*ret): test.append(Event('dbus-return', method=method, value=unwrap(ret))) def error_func(err): test.append(Event('dbus-error', method=method, error=err, name=err.get_dbus_name(), message=str(err))) method_proxy = getattr(proxy, method) kw.update({'reply_handler': reply_func, 'error_handler': error_func}) method_proxy(*args, **kw) def sync_dbus(bus, q, conn): # Dummy D-Bus method call. We can't use DBus.Peer.Ping() because libdbus # replies to that message immediately, rather than handing it up to # dbus-glib and thence Gabble, which means that Ping()ing Gabble doesn't # ensure that it's processed all D-Bus messages prior to our ping. # # This won't do the right thing unless the proxy has a unique name. assert conn.object.bus_name.startswith(':') root_object = bus.get_object(conn.object.bus_name, '/', introspect=False) call_async(q, dbus.Interface(root_object, 'org.freedesktop.Telepathy.Tests'), 'DummySyncDBus') q.expect('dbus-error', method='DummySyncDBus') class ProxyWrapper: def __init__(self, object, default, others={}): self.object = object self.default_interface = dbus.Interface(object, default) self.Properties = dbus.Interface(object, dbus.PROPERTIES_IFACE) self.TpProperties = \ dbus.Interface(object, tp_name_prefix + '.Properties') self.interfaces = dict([ (name, dbus.Interface(object, iface)) for name, iface in others.iteritems()]) def __getattr__(self, name): if name in self.interfaces: return self.interfaces[name] if name in self.object.__dict__: return getattr(self.object, name) return getattr(self.default_interface, name) def wrap_connection(conn): return ProxyWrapper(conn, tp_name_prefix + '.Connection', dict([ (name, tp_name_prefix + '.Connection.Interface.' + name) for name in ['Aliasing', 'Avatars', 'Capabilities', 'Contacts', 'SimplePresence', 'Requests']] + [('Peer', 'org.freedesktop.DBus.Peer'), ('ContactCapabilities', cs.CONN_IFACE_CONTACT_CAPS), ('ContactInfo', cs.CONN_IFACE_CONTACT_INFO), ('Location', cs.CONN_IFACE_LOCATION), ('Future', tp_name_prefix + '.Connection.FUTURE'), ('MailNotification', cs.CONN_IFACE_MAIL_NOTIFICATION), ('ContactList', cs.CONN_IFACE_CONTACT_LIST), ('ContactGroups', cs.CONN_IFACE_CONTACT_GROUPS), ('PowerSaving', cs.CONN_IFACE_POWER_SAVING), ('Addressing', cs.CONN_IFACE_ADDRESSING), ])) def wrap_channel(chan, type_, extra=None): interfaces = { type_: tp_name_prefix + '.Channel.Type.' + type_, 'Group': tp_name_prefix + '.Channel.Interface.Group', } if extra: interfaces.update(dict([ (name, tp_name_prefix + '.Channel.Interface.' + name) for name in extra])) return ProxyWrapper(chan, tp_name_prefix + '.Channel', interfaces) def wrap_content(chan, extra=None): interfaces = { } if extra: interfaces.update(dict([ (name, tp_name_prefix + '.Call1.Content.Interface.' + name) for name in extra])) return ProxyWrapper(chan, tp_name_prefix + '.Call1.Content', interfaces) def make_connection(bus, event_func, name, proto, params): cm = bus.get_object( tp_name_prefix + '.ConnectionManager.%s' % name, tp_path_prefix + '/ConnectionManager/%s' % name, introspect=False) cm_iface = dbus.Interface(cm, tp_name_prefix + '.ConnectionManager') connection_name, connection_path = cm_iface.RequestConnection( proto, dbus.Dictionary(params, signature='sv')) conn = wrap_connection(bus.get_object(connection_name, connection_path)) return conn def make_channel_proxy(conn, path, iface): bus = dbus.SessionBus() chan = bus.get_object(conn.object.bus_name, path) chan = dbus.Interface(chan, tp_name_prefix + '.' + iface) return chan # block_reading can be used if the test want to choose when we start to read # data from the socket. class EventProtocol(Protocol): def __init__(self, queue=None, block_reading=False): self.queue = queue self.block_reading = block_reading def dataReceived(self, data): if self.queue is not None: self.queue.append(Event('socket-data', protocol=self, data=data)) def sendData(self, data): self.transport.write(data) def connectionMade(self): if self.block_reading: self.transport.stopReading() def connectionLost(self, reason=None): if self.queue is not None: self.queue.append(Event('socket-disconnected', protocol=self)) class EventProtocolFactory(Factory): def __init__(self, queue, block_reading=False): self.queue = queue self.block_reading = block_reading def _create_protocol(self): return EventProtocol(self.queue, self.block_reading) def buildProtocol(self, addr): proto = self._create_protocol() self.queue.append(Event('socket-connected', protocol=proto)) return proto class EventProtocolClientFactory(EventProtocolFactory, ClientFactory): pass def watch_tube_signals(q, tube): def got_signal_cb(*args, **kwargs): q.append(Event('tube-signal', path=kwargs['path'], signal=kwargs['member'], args=map(unwrap, args), tube=tube)) tube.add_signal_receiver(got_signal_cb, path_keyword='path', member_keyword='member', byte_arrays=True) def pretty(x): return pprint.pformat(unwrap(x)) def assertEquals(expected, value): if expected != value: raise AssertionError( "expected:\n%s\ngot:\n%s" % (pretty(expected), pretty(value))) def assertSameSets(expected, value): exp_set = set(expected) val_set = set(value) if exp_set != val_set: raise AssertionError( "expected contents:\n%s\ngot:\n%s" % ( pretty(exp_set), pretty(val_set))) def assertNotEquals(expected, value): if expected == value: raise AssertionError( "expected something other than:\n%s" % pretty(value)) def assertContains(element, value): if element not in value: raise AssertionError( "expected:\n%s\nin:\n%s" % (pretty(element), pretty(value))) def assertDoesNotContain(element, value): if element in value: raise AssertionError( "expected:\n%s\nnot in:\n%s" % (pretty(element), pretty(value))) def assertLength(length, value): if len(value) != length: raise AssertionError("expected: length %d, got length %d:\n%s" % ( length, len(value), pretty(value))) def assertFlagsSet(flags, value): masked = value & flags if masked != flags: raise AssertionError( "expected flags %u, of which only %u are set in %u" % ( flags, masked, value)) def assertFlagsUnset(flags, value): masked = value & flags if masked != 0: raise AssertionError( "expected none of flags %u, but %u are set in %u" % ( flags, masked, value)) def assertDBusError(name, error): if error.get_dbus_name() != name: raise AssertionError( "expected DBus error named:\n %s\ngot:\n %s\n(with message: %s)" % (name, error.get_dbus_name(), error.message)) def install_colourer(): def red(s): return '\x1b[31m%s\x1b[0m' % s def green(s): return '\x1b[32m%s\x1b[0m' % s patterns = { 'handled': green, 'not handled': red, } class Colourer: def __init__(self, fh, patterns): self.fh = fh self.patterns = patterns def write(self, s): for p, f in self.patterns.items(): if s.startswith(p): self.fh.write(f(p) + s[len(p):]) return self.fh.write(s) sys.stdout = Colourer(sys.stdout, patterns) return sys.stdout # this is just to shut up unittest. class DummyStream(object): def write(self, s): if 'CHECK_TWISTED_VERBOSE' in os.environ: print s, def flush(self): pass if __name__ == '__main__': stream = DummyStream() runner = unittest.TextTestRunner(stream=stream) unittest.main(testRunner=runner) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/test-location.py����������������������������������������������0000664�0001750�0001750�00000026655�12332441362�024200� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import dbus import time import datetime from gabbletest import ( exec_test, elem, acknowledge_iq, send_error_reply, sync_stream, make_result_iq, disconnect_conn, ) from servicetest import ( call_async, EventPattern, assertEquals, assertLength, assertContains, ) from twisted.words.xish import xpath import constants as cs import ns Rich_Presence_Access_Control_Type_Publish_List = 1 def test(q, bus, conn, stream): # we don't yet know we have PEP assertEquals(0, conn.Get(cs.CONN_IFACE_LOCATION, "SupportedLocationFeatures", dbus_interface=cs.PROPERTIES_IFACE)) conn.Connect() # discard activities request and status change q.expect_many( EventPattern('stream-iq', iq_type='set', query_ns=ns.PUBSUB), EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]), ) # we now know we have PEP assertEquals(cs.LOCATION_FEATURE_CAN_SET, conn.Get(cs.CONN_IFACE_LOCATION, "SupportedLocationFeatures", dbus_interface=cs.PROPERTIES_IFACE)) # check location properties access_control_types = conn.Get( cs.CONN_IFACE_LOCATION, "LocationAccessControlTypes", dbus_interface=cs.PROPERTIES_IFACE) # only one access control is implemented in Gabble at the moment: assert len(access_control_types) == 1, access_control_types assert access_control_types[0] == \ Rich_Presence_Access_Control_Type_Publish_List access_control = conn.Get( cs.CONN_IFACE_LOCATION, "LocationAccessControl", dbus_interface=cs.PROPERTIES_IFACE) assert len(access_control) == 2, access_control assert access_control[0] == \ Rich_Presence_Access_Control_Type_Publish_List properties = conn.GetAll( cs.CONN_IFACE_LOCATION, dbus_interface=cs.PROPERTIES_IFACE) assert properties.get('LocationAccessControlTypes') == access_control_types assert properties.get('LocationAccessControl') == access_control # Test setting the properties # Enum out of range bad_access_control = dbus.Struct([dbus.UInt32(99), dbus.UInt32(0, variant_level=1)], signature=dbus.Signature('uv')) try: conn.Set (cs.CONN_IFACE_LOCATION, 'LocationAccessControl', bad_access_control, dbus_interface =cs.PROPERTIES_IFACE) except dbus.DBusException, e: pass else: assert False, "Should have had an error!" # Bad type bad_access_control = dbus.String("This should not be a string") try: conn.Set (cs.CONN_IFACE_LOCATION, 'LocationAccessControl', bad_access_control, dbus_interface =cs.PROPERTIES_IFACE) except dbus.DBusException, e: assert e.get_dbus_name() == cs.INVALID_ARGUMENT, e.get_dbus_name() else: assert False, "Should have had an error!" # Bad type bad_access_control = dbus.Struct([dbus.String("bad"), dbus.String("!"), dbus.UInt32(0, variant_level=1)], signature=dbus.Signature('ssv')) try: conn.Set (cs.CONN_IFACE_LOCATION, 'LocationAccessControl', bad_access_control, dbus_interface =cs.PROPERTIES_IFACE) except dbus.DBusException, e: assert e.get_dbus_name() == cs.INVALID_ARGUMENT, e.get_dbus_name() else: assert False, "Should have had an error!" # Correct conn.Set (cs.CONN_IFACE_LOCATION, 'LocationAccessControl', access_control, dbus_interface =cs.PROPERTIES_IFACE) # LocationAccessControlTypes is read-only, check Gabble return the # PermissionDenied error try: conn.Set (cs.CONN_IFACE_LOCATION, 'LocationAccessControlTypes', access_control_types, dbus_interface =cs.PROPERTIES_IFACE) except dbus.DBusException, e: assert e.get_dbus_name() == cs.PERMISSION_DENIED, e.get_dbus_name() else: assert False, "Should have had an error!" date = dbus.Int64(time.time()) date_str = datetime.datetime.utcfromtimestamp(date).strftime('%FT%H:%M:%SZ') # set a Location call_async(q, conn.Location, 'SetLocation', { 'lat': dbus.Double(0.0, variant_level=1), 'lon': 0.0, 'language': 'en', 'timestamp': date, 'country': 'Congo', 'accuracy': 1.4, # Gabble silently ignores unknown keys 'badger': 'mushroom'}) geoloc_iq_set_event = EventPattern('stream-iq', predicate=lambda x: xpath.queryForNodes("/iq/pubsub/publish/item/geoloc", x.stanza)) event = q.expect_many(geoloc_iq_set_event)[0] geoloc = xpath.queryForNodes("/iq/pubsub/publish/item/geoloc", event.stanza)[0] assertEquals(geoloc.getAttribute((ns.XML, 'lang')), 'en') lon = xpath.queryForNodes('/geoloc/lon', geoloc)[0] assertEquals(float(str(lon)), 0.0) lat = xpath.queryForNodes('/geoloc/lat', geoloc)[0] assertEquals(float(str(lat)), 0.0) timestamp = xpath.queryForNodes('/geoloc/timestamp', geoloc)[0] assertEquals(str(timestamp), date_str) country = xpath.queryForNodes('/geoloc/country', geoloc)[0] assertEquals(str(country), 'Congo') lat = xpath.queryForNodes('/geoloc/accuracy', geoloc)[0] assertEquals(float(str(lat)), 1.4) acknowledge_iq(stream, event.stanza) q.expect('dbus-return', method='SetLocation') # Server refuses to set Location call_async(q, conn.Location, 'SetLocation', { 'lat': 0.0, 'lon': 0.0}) geoloc_iq_set_event = EventPattern('stream-iq', predicate=lambda x: xpath.queryForNodes("/iq/pubsub/publish/item/geoloc", x.stanza)) event = q.expect_many(geoloc_iq_set_event)[0] send_error_reply(stream, event.stanza) q.expect('dbus-error', method='SetLocation') # Request Bob's location bob_handle = conn.RequestHandles(1, ['bob@foo.com'])[0] call_async(q, conn.Location, 'GetLocations', [bob_handle]) # Gabble should not send a pubsub query. The point of PEP is that we don't # have to do this. pubsub_get_pattern = EventPattern('stream-iq', iq_type='get', query_ns=ns.PUBSUB) q.forbid_events([ pubsub_get_pattern ]) # GetLocations returns immediately. get_locations = q.expect('dbus-return', method='GetLocations') locations = get_locations.value[0] # Location isn't known yet assertLength(0, locations) # Sync the XMPP stream to ensure Gabble hasn't sent a query. sync_stream(q, stream) # Bob updates his location message = elem('message', from_='bob@foo.com')( elem((ns.PUBSUB_EVENT), 'event')( elem('items', node=ns.GEOLOC)( elem('item', id='12345')( elem(ns.GEOLOC, 'geoloc', attrs={'xml:lang': 'en'})( elem('lat')(u'1.25'), elem('lon')(u'5.5'), elem('country')(u'Belgium'), elem('accuracy')(u'2.3'), elem('timestamp')(unicode(date_str)), # invalid element, will be ignored by Gabble elem('badger')(u'mushroom'), ) ) ) ) ) stream.send(message) update_event = q.expect('dbus-signal', signal='LocationUpdated') handle, location = update_event.args assertEquals(bob_handle, handle) assertLength(6, location) assertEquals(location['language'], 'en') assertEquals(location['lat'], 1.25) assertEquals(location['lon'], 5.5) assertEquals(location['country'], 'Belgium') assertEquals(location['accuracy'], 2.3) assertEquals(location['timestamp'], date) # Get location again; Gabble should return the cached location locations = conn.Location.GetLocations([bob_handle]) assertLength(1, locations) assertEquals(locations[bob_handle], location) charles_handle = conn.RequestHandles(cs.HT_CONTACT, ['charles@foo.com'])[0] # check that Contacts interface supports location attributes = conn.Contacts.GetContactAttributes( [bob_handle, charles_handle], [cs.CONN_IFACE_LOCATION], False) assertLength(2, attributes) assertContains(bob_handle, attributes) assertContains(charles_handle, attributes) assertEquals( { cs.CONN_IFACE_LOCATION + '/location': location, cs.CONN + '/contact-id': 'bob@foo.com'}, attributes[bob_handle]) assertEquals( { cs.CONN + '/contact-id': 'charles@foo.com'}, attributes[charles_handle]) # Try to set our location by passing a valid with an invalid type (lat is # supposed to be a double) q.forbid_events([geoloc_iq_set_event]) try: conn.Location.SetLocation({'lat': 'pony'}) except dbus.DBusException, e: assertEquals(e.get_dbus_name(), cs.INVALID_ARGUMENT) else: assert False # Bob updates his location again message = elem('message', from_='bob@foo.com')( elem((ns.PUBSUB_EVENT), 'event')( elem('items', node=ns.GEOLOC)( elem('item', id='12345')( elem(ns.GEOLOC, 'geoloc')( elem ('country') (u'France') ) ) ) ) ) stream.send(message) update_event = q.expect('dbus-signal', signal='LocationUpdated') handle, location = update_event.args assertEquals(handle, bob_handle) assertLength(1, location) assertEquals(location['country'], 'France') # Now we test explicitly retrieving Bob's location, so we should not forbid # such queries. :) q.unforbid_events([ pubsub_get_pattern ]) call_async(q, conn.Location, 'RequestLocation', bob_handle) e = q.expect('stream-iq', iq_type='get', query_ns=ns.PUBSUB, to='bob@foo.com') # Hey, while we weren't looking Bob moved abroad! result = make_result_iq(stream, e.stanza) result['from'] = 'bob@foo.com' pubsub_node = result.firstChildElement() pubsub_node.addChild( elem('items', node=ns.GEOLOC)( elem('item', id='12345')( elem(ns.GEOLOC, 'geoloc')( elem ('country') (u'Chad') ) ) ) ) stream.send(result) ret = q.expect('dbus-return', method='RequestLocation') location, = ret.value assertLength(1, location) assertEquals(location['country'], 'Chad') # Let's ask again; this time Bob's server hates us for some reason. call_async(q, conn.Location, 'RequestLocation', bob_handle) e = q.expect('stream-iq', iq_type='get', query_ns=ns.PUBSUB, to='bob@foo.com') send_error_reply(stream, e.stanza, elem('error', type='auth')( elem(ns.STANZA, 'forbidden') )) e = q.expect('dbus-error', method='RequestLocation') assertEquals(cs.PERMISSION_DENIED, e.name) # FIXME: maybe we should check that the cache gets invalidated in this # case? We should also test whether or not the cache is invalidated # properly if the contact clears their PEP node. # Let's ask a final time, and disconnect while we're doing so, to make sure # this doesn't break Gabble or Wocky. call_async(q, conn.Location, 'RequestLocation', bob_handle) e = q.expect('stream-iq', iq_type='get', query_ns=ns.PUBSUB, to='bob@foo.com') # Tasty argument unpacking. disconnect_conn returns two lists, one for # expeced_before=[] and one for expected_after=[...] _, (e, ) = disconnect_conn(q, conn, stream, expected_after=[EventPattern('dbus-error', method='RequestLocation')]) assertEquals(cs.CANCELLED, e.name) if __name__ == '__main__': exec_test(test, do_connect=False) �����������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/sasl/���������������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�021774� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/sasl/complex.py�����������������������������������������������0000664�0001750�0001750�00000012773�12332441362�024020� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test the server sasl channel with the PLAIN mechanism """ import dbus from servicetest import EventPattern, assertEquals, assertSameSets, call_async from gabbletest import exec_test import constants as cs from saslutil import SaslEventAuthenticator, connect_and_get_sasl_channel JID = "test@example.org" INITIAL_RESPONSE = 'Thunder and lightning. Enter three Witches.' CR_PAIRS = [ ('When shall we three meet again?', 'Ere the set of sun.'), ('Where the place?', 'Upon the heath.'), ] SUCCESS_DATA = 'Exeunt.' MECHANISMS = ["PLAIN", "DIGEST-MD5", "SCOTTISH-PLAY"] def test_complex_success(q, bus, conn, stream, with_extra_data=True, accept_early=False): chan, props = connect_and_get_sasl_channel(q, bus, conn) assertSameSets(MECHANISMS + ['X-TELEPATHY-PASSWORD'], props.get(cs.SASL_AVAILABLE_MECHANISMS)) call_async(q, chan.SASLAuthentication, 'StartMechanismWithData', "FOO", "") q.expect('dbus-error', method='StartMechanismWithData', name=cs.NOT_IMPLEMENTED) if with_extra_data: chan.SASLAuthentication.StartMechanismWithData("SCOTTISH-PLAY", INITIAL_RESPONSE) e = q.expect('sasl-auth', initial_response=INITIAL_RESPONSE) else: chan.SASLAuthentication.StartMechanism("SCOTTISH-PLAY") e = q.expect('sasl-auth', has_initial_response=False) authenticator = e.authenticator q.expect('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_IN_PROGRESS, '', {}]) if not with_extra_data: # send the stage directions in-band instead authenticator.challenge('') e = q.expect('dbus-signal', signal='NewChallenge', interface=cs.CHANNEL_IFACE_SASL_AUTH) # this ought to be '' but dbus-python has fd.o #28131 assert e.args in ([''], ['None']) chan.SASLAuthentication.Respond(INITIAL_RESPONSE) q.expect('sasl-response', response=INITIAL_RESPONSE) for challenge, response in CR_PAIRS: authenticator.challenge(challenge) q.expect('dbus-signal', signal='NewChallenge', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[challenge]) chan.SASLAuthentication.Respond(response) q.expect('sasl-response', response=response) if with_extra_data: authenticator.success(SUCCESS_DATA) else: # The success data is sent in-band as a challenge authenticator.challenge(SUCCESS_DATA) q.expect('dbus-signal', signal='NewChallenge', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[SUCCESS_DATA]) if accept_early: # the UI can tell that this challenge isn't actually a challenge, # it's a success in disguise chan.SASLAuthentication.AcceptSASL() q.expect('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_CLIENT_ACCEPTED, '', {}]) else: chan.SASLAuthentication.Respond(dbus.ByteArray('')) if with_extra_data: # Wocky removes the distinction between a challenge containing # success data followed by a plain success, and a success # containing initial data, so we won't get to Server_Succeeded # til we "respond" to the "challenge". However, at the XMPP level, # we shouldn't get a response to a success. q.forbid_events([EventPattern('sasl-response')]) else: q.expect('sasl-response', response='') authenticator.success(None) if not accept_early: # *now* we accept q.expect('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_SERVER_SUCCEEDED, '', {}]) # We're willing to accept this SASL transaction chan.SASLAuthentication.AcceptSASL() q.expect('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_SUCCEEDED, '', {}]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) chan.Close() # ... and check that the Connection is still OK conn.GetSelfHandle() def test_complex_success_data(q, bus, conn, stream): test_complex_success(q, bus, conn, stream, True) def test_complex_success_no_data(q, bus, conn, stream): test_complex_success(q, bus, conn, stream, False) def test_complex_success_data_accept(q, bus, conn, stream): test_complex_success(q, bus, conn, stream, True, True) def test_complex_success_no_data_accept(q, bus, conn, stream): test_complex_success(q, bus, conn, stream, False, True) if __name__ == '__main__': exec_test( test_complex_success_data, {'password': None, 'account' : JID}, authenticator=SaslEventAuthenticator(JID.split('@')[0], MECHANISMS), do_connect=False) exec_test( test_complex_success_no_data, {'password': None, 'account' : JID}, authenticator=SaslEventAuthenticator(JID.split('@')[0], MECHANISMS), do_connect=False) exec_test( test_complex_success_data_accept, {'password': None, 'account' : JID}, authenticator=SaslEventAuthenticator(JID.split('@')[0], MECHANISMS), do_connect=False) exec_test( test_complex_success_no_data_accept, {'password': None, 'account' : JID}, authenticator=SaslEventAuthenticator(JID.split('@')[0], MECHANISMS), do_connect=False) �����telepathy-gabble-0.18.3/tests/twisted/sasl/saslutil.py����������������������������������������������0000664�0001750�0001750�00000011473�12332441362�024205� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# hey, Python: encoding: utf-8 from gabbletest import XmppAuthenticator from base64 import b64decode, b64encode from twisted.words.xish import domish import constants as cs import ns from servicetest import (ProxyWrapper, EventPattern, assertEquals, assertLength, Event) class SaslChannelWrapper(ProxyWrapper): def __init__(self, object, default=cs.CHANNEL, interfaces={ "ServerAuthentication" : cs.CHANNEL_TYPE_SERVER_AUTHENTICATION, "SASLAuthentication" : cs.CHANNEL_IFACE_SASL_AUTH}): ProxyWrapper.__init__(self, object, default, interfaces) class SaslEventAuthenticator(XmppAuthenticator): def __init__(self, jid, mechanisms): XmppAuthenticator.__init__(self, jid, '') self._mechanisms = mechanisms def streamSASL(self): XmppAuthenticator.streamSASL(self) self.xmlstream.addObserver("/response", self._response) self.xmlstream.addObserver("/abort", self._abort) def failure(self, fail_str): reply = domish.Element((ns.NS_XMPP_SASL, 'failure')) reply.addElement(fail_str) self.xmlstream.send(reply) self.xmlstream.reset() def abort(self): self.failure('abort') def not_authorized(self): self.failure('not-authorized') def success(self, data=None): reply = domish.Element((ns.NS_XMPP_SASL, 'success')) if data is not None: reply.addContent(b64encode(data)) self.xmlstream.send(reply) self.authenticated=True self.xmlstream.reset() def challenge(self, data): reply = domish.Element((ns.NS_XMPP_SASL, 'challenge')) reply.addContent(b64encode(data)) self.xmlstream.send(reply) def auth(self, auth): # Special case in XMPP: '=' means a zero-byte blob, whereas an empty # or self-terminating XML element means no initial response. # (RFC 3920 §6.2 (3)) if str(auth) == '': self._event_func(Event('sasl-auth', authenticator=self, has_initial_response=False, initial_response=None, xml=auth)) elif str(auth) == '=': self._event_func(Event('sasl-auth', authenticator=self, has_initial_response=False, initial_response=None, xml=auth)) else: self._event_func(Event('sasl-auth', authenticator=self, has_initial_response=True, initial_response=b64decode(str(auth)), xml=auth)) def _response(self, response): self._event_func(Event('sasl-response', authenticator=self, response=b64decode(str(response)), xml=response)) def _abort(self, abort): self._event_func(Event('sasl-abort', authenticator=self, xml=abort)) def connect_and_get_sasl_channel(q, bus, conn): conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) return expect_sasl_channel(q, bus, conn) def expect_sasl_channel(q, bus, conn): old_signal, new_signal = q.expect_many( EventPattern('dbus-signal', signal='NewChannel', predicate=lambda e: e.args[1] == cs.CHANNEL_TYPE_SERVER_AUTHENTICATION), EventPattern('dbus-signal', signal='NewChannels', predicate=lambda e: e.args[0][0][1].get(cs.CHANNEL_TYPE) == cs.CHANNEL_TYPE_SERVER_AUTHENTICATION), ) path, type, handle_type, handle, suppress_handler = old_signal.args chan = SaslChannelWrapper(bus.get_object(conn.bus_name, path)) assertLength(1, new_signal.args[0]) assertEquals(path, new_signal.args[0][0][0]) props = new_signal.args[0][0][1] assertEquals(cs.CHANNEL_IFACE_SASL_AUTH, props.get(cs.AUTH_METHOD)) return chan, props def abort_auth(q, chan, reason, message): reason_err_map = { cs.SASL_ABORT_REASON_USER_ABORT : cs.CANCELLED, cs.SASL_ABORT_REASON_INVALID_CHALLENGE : cs.SERVICE_CONFUSED } mapped_error = reason_err_map.get(reason, cs.CANCELLED) chan.SASLAuthentication.AbortSASL(reason, message) ssc, ce, _ = q.expect_many( EventPattern( 'dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, predicate=lambda e: e.args[0] == cs.SASL_STATUS_CLIENT_FAILED), EventPattern('dbus-signal', signal='ConnectionError'), EventPattern( 'dbus-signal', signal="StatusChanged", args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_AUTHENTICATION_FAILED])) assertEquals(cs.SASL_STATUS_CLIENT_FAILED, ssc.args[0]) assertEquals(mapped_error, ssc.args[1]) assertEquals(message, ssc.args[2].get('debug-message')), assertEquals(mapped_error, ce.args[0]) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/sasl/jabber_auth.py�������������������������������������������0000664�0001750�0001750�00000010453�12332441362�024610� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test the server sasl channel with Jabber auth pseudomechanisms """ from twisted.words.xish import domish from twisted.words.protocols.jabber import xmlstream from twisted.words.protocols.jabber.client import IQ import hashlib import dbus from servicetest import (EventPattern, assertEquals, assertSameSets, assertContains) from gabbletest import exec_test, JabberXmlStream, JabberAuthenticator import constants as cs import ns from saslutil import expect_sasl_channel, abort_auth JID = "test@localhost" PASSWORD = "pass" def test_jabber_pass_success(q, bus, conn, stream): conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) e = q.expect('auth-initial-iq') authenticator = e.authenticator authenticator.respondToInitialIq(e.iq) chan, props = expect_sasl_channel(q, bus, conn) assertSameSets(['X-TELEPATHY-PASSWORD'], props.get(cs.SASL_AVAILABLE_MECHANISMS)) chan.SASLAuthentication.StartMechanismWithData('X-TELEPATHY-PASSWORD', PASSWORD) e = q.expect('auth-second-iq') authenticator.respondToSecondIq(e.iq) q.expect('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_SERVER_SUCCEEDED, '', {}]) chan.SASLAuthentication.AcceptSASL() q.expect('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_SUCCEEDED, '', {}]) e = q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) CODES = { 'not-authorized': 401, 'conflict': 409, 'not-acceptable': 406 } TYPES = { 'not-authorized': 'auth', 'conflict': 'cancel', 'not-acceptable': 'modify' } CSRS = { 'not-authorized': cs.CSR_AUTHENTICATION_FAILED, 'conflict': cs.CSR_NAME_IN_USE, 'not-acceptable': cs.CSR_AUTHENTICATION_FAILED } ERRORS = { 'not-authorized': cs.AUTHENTICATION_FAILED, 'conflict': cs.ALREADY_CONNECTED, 'not-acceptable': cs.AUTHENTICATION_FAILED } def test_jabber_pass_fail(q, bus, conn, stream, which): conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) e = q.expect('auth-initial-iq') authenticator = e.authenticator authenticator.respondToInitialIq(e.iq) chan, props = expect_sasl_channel(q, bus, conn) assertSameSets(['X-TELEPATHY-PASSWORD'], props.get(cs.SASL_AVAILABLE_MECHANISMS)) chan.SASLAuthentication.StartMechanismWithData('X-TELEPATHY-PASSWORD', PASSWORD) e = q.expect('auth-second-iq') result = IQ(stream, 'error') result['id'] = e.id error = result.addElement('error') error['code'] = str(CODES[which]) error['type'] = TYPES[which] error.addElement((ns.STANZA, which)) stream.send(result) e = q.expect('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, predicate=lambda e: e.args[0] == cs.SASL_STATUS_SERVER_FAILED) assertEquals(ERRORS[which], e.args[1]) assertContains('debug-message', e.args[2]) e = q.expect('dbus-signal', signal='ConnectionError') assertEquals(ERRORS[which], e.args[0]) assertContains('debug-message', e.args[1]) e = q.expect('dbus-signal', signal='StatusChanged') assertEquals(cs.CONN_STATUS_DISCONNECTED, e.args[0]) assertEquals(CSRS[which], e.args[1]) def test_jabber_pass_not_authorized(q, bus, conn, stream): test_jabber_pass_fail(q, bus, conn, stream, 'not-authorized') def test_jabber_pass_conflict(q, bus, conn, stream): test_jabber_pass_fail(q, bus, conn, stream, 'conflict') def test_jabber_pass_not_acceptable(q, bus, conn, stream): test_jabber_pass_fail(q, bus, conn, stream, 'not-acceptable') if __name__ == '__main__': for test in ( # these are Examples 5 to 8 of XEP-0078 test_jabber_pass_success, test_jabber_pass_not_authorized, test_jabber_pass_conflict, test_jabber_pass_not_acceptable): exec_test( test, {'password': None, 'account' : JID}, protocol=JabberXmlStream, authenticator=JabberAuthenticator(JID.split('@')[0], PASSWORD, emit_events=True), do_connect=False) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/sasl/abort.py�������������������������������������������������0000664�0001750�0001750�00000017265�12332441362�023461� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test the server sasl aborting at different stages """ import dbus from servicetest import EventPattern, assertEquals from gabbletest import exec_test, call_async import constants as cs from saslutil import SaslEventAuthenticator, connect_and_get_sasl_channel, \ abort_auth JID = "test@example.org" PASSWORD = "pass" EXCHANGE = [("", "remote challenge"), ("Another step", "Here we go"), ("local response", "")] MECHANISMS = ["PLAIN", "DIGEST-MD5", "ABORT-TEST"] def test_abort_early(q, bus, conn, stream): chan, props = connect_and_get_sasl_channel(q, bus, conn) abort_auth(q, chan, 31337, "maybe if I use an undefined code you'll crash") def start_mechanism(q, bus, conn, mechanism="ABORT-TEST", initial_response=EXCHANGE[0][1]): chan, props = connect_and_get_sasl_channel(q, bus, conn) chan.SASLAuthentication.StartMechanismWithData(mechanism, initial_response) q.expect('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_IN_PROGRESS, '', {}]) e = q.expect('sasl-auth', initial_response=initial_response) return chan, e.authenticator def test_abort_mid(q, bus, conn, stream): chan, authenticator = start_mechanism(q, bus, conn) authenticator.challenge(EXCHANGE[1][0]) q.expect('dbus-signal', signal='NewChallenge', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[EXCHANGE[1][0]]) abort_auth(q, chan, cs.SASL_ABORT_REASON_INVALID_CHALLENGE, "wrong data from server") def test_disconnect_mid(q, bus, conn, stream): chan, authenticator = start_mechanism(q, bus, conn) authenticator.challenge(EXCHANGE[1][0]) q.expect('dbus-signal', signal='NewChallenge', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[EXCHANGE[1][0]]) call_async(q, conn, 'Disconnect') q.expect_many(EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_REQUESTED]), EventPattern('dbus-return', method='Disconnect')) def test_abort_connected(q, bus, conn, stream): initial_response = '\0' + JID.split('@')[0] + '\0' + PASSWORD chan, authenticator = start_mechanism(q, bus, conn, mechanism='PLAIN', initial_response=initial_response) authenticator.success(None) q.expect('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_SERVER_SUCCEEDED, '', {}]) chan.SASLAuthentication.AcceptSASL() q.expect('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_SUCCEEDED, '', {}]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) call_async(q, chan.SASLAuthentication, 'AbortSASL', cs.SASL_ABORT_REASON_USER_ABORT, "aborting too late") q.expect('dbus-error', method='AbortSASL', name=cs.NOT_AVAILABLE) chan.Close() def test_give_up_while_waiting(q, bus, conn, stream, channel_method, authenticator_method): """Regression test for https://bugs.freedesktop.org/show_bug.cgi?id=52146 where closing the auth channel while waiting for a challenge from the server would not abort the SASL exchange, and the challenge subsequently arriving would make Gabble assert. """ chan, authenticator = start_mechanism(q, bus, conn) # While Gabble is waiting for waiting for the server to make the next move, # a Telepathy client does something to try to end the authentication # process. channel_method(chan) # And then we hear something back from the server. authenticator_method(authenticator) # FIXME: Gabble should probably send <abort/> and wait for the server to # say <failure><aborted/> rather than unceremoniously closing the # connection. # # In the bug we're testing for, the stream connection would indeed be lost, # but Gabble would also crash and leave a core dump behind. So this test # would appear to pass, but 'make check' would fail as we want. q.expect_many( EventPattern('stream-connection-lost'), EventPattern('dbus-signal', signal='ConnectionError'), EventPattern( 'dbus-signal', signal="StatusChanged", args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_AUTHENTICATION_FAILED]), ) def test_close_then_challenge(q, bus, conn, stream): """This is the specific scenario for which 52146 was reported. The channel was being closed because its handler crashed. """ test_give_up_while_waiting(q, bus, conn, stream, lambda chan: chan.Close(), lambda authenticator: authenticator.challenge(EXCHANGE[1][0])) def test_close_then_success(q, bus, conn, stream): test_give_up_while_waiting(q, bus, conn, stream, lambda chan: chan.Close(), lambda authenticator: authenticator.success()) def test_close_then_failure(q, bus, conn, stream): test_give_up_while_waiting(q, bus, conn, stream, lambda chan: chan.Close(), lambda authenticator: authenticator.not_authorized()) def test_abort_then_challenge(q, bus, conn, stream): test_give_up_while_waiting(q, bus, conn, stream, lambda chan: chan.SASLAuthentication.AbortSASL( cs.SASL_ABORT_REASON_USER_ABORT, "bored now"), lambda authenticator: authenticator.challenge(EXCHANGE[1][0])) def test_abort_then_success(q, bus, conn, stream): """FIXME: this test fails because the channel changes its state from TP_SASL_STATUS_CLIENT_FAILED to TP_SASL_STATUS_SERVER_SUCCEEDED and waits for the client to ack it when <success> arrives, which is dumb. """ test_give_up_while_waiting(q, bus, conn, stream, lambda chan: chan.SASLAuthentication.AbortSASL( cs.SASL_ABORT_REASON_USER_ABORT, "bored now"), lambda authenticator: authenticator.success()) def test_abort_then_failure(q, bus, conn, stream): test_give_up_while_waiting(q, bus, conn, stream, lambda chan: chan.SASLAuthentication.AbortSASL( cs.SASL_ABORT_REASON_USER_ABORT, "bored now"), lambda authenticator: authenticator.not_authorized()) def abort_and_close(chan): chan.SASLAuthentication.AbortSASL( cs.SASL_ABORT_REASON_USER_ABORT, "bored now") chan.Close() def test_abort_and_close_then_challenge(q, bus, conn, stream): test_give_up_while_waiting(q, bus, conn, stream, abort_and_close, lambda authenticator: authenticator.challenge(EXCHANGE[1][0])) def test_abort_and_close_then_failure(q, bus, conn, stream): test_give_up_while_waiting(q, bus, conn, stream, abort_and_close, lambda authenticator: authenticator.not_authorized()) def exec_test_(func): # Can't use functools.partial, because the authenticator is stateful. authenticator = SaslEventAuthenticator(JID.split('@')[0], MECHANISMS) exec_test(func, do_connect=False, authenticator=authenticator, params={'password': None, 'account' : JID, }) if __name__ == '__main__': exec_test_(test_abort_early) exec_test_(test_abort_mid) exec_test_(test_disconnect_mid) exec_test_(test_abort_connected) exec_test_(test_close_then_challenge) exec_test_(test_close_then_success) exec_test_(test_close_then_failure) exec_test_(test_abort_then_challenge) # exec_test_(test_abort_then_success) exec_test_(test_abort_then_failure) exec_test_(test_abort_and_close_then_challenge) exec_test_(test_abort_and_close_then_failure) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/sasl/close.py�������������������������������������������������0000664�0001750�0001750�00000002121�12332441362�023440� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""Test the SASL channel being undispatchable.""" import dbus from servicetest import EventPattern from gabbletest import exec_test import constants as cs from saslutil import connect_and_get_sasl_channel JID = 'weaver@crobuzon.fic' def test_no_password(q, bus, conn, stream): chan, props = connect_and_get_sasl_channel(q, bus, conn) chan.Close() q.expect_many( EventPattern('dbus-signal', path=chan.object_path, signal='Closed'), EventPattern('dbus-signal', path=conn.object_path, signal='ChannelClosed', args=[chan.object_path]), EventPattern('dbus-signal', path=conn.object_path, signal='ConnectionError', predicate=lambda e: e.args[0] == cs.AUTHENTICATION_FAILED), EventPattern('dbus-signal', path=conn.object_path, signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_AUTHENTICATION_FAILED]), ) if __name__ == '__main__': exec_test(test_no_password, {'password': None,'account' : JID}, do_connect=False) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/sasl/plain.py�������������������������������������������������0000664�0001750�0001750�00000021507�12332441362�023447� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test the server sasl channel with the PLAIN mechanism """ from twisted.words.xish import domish from twisted.words.protocols.jabber import xmlstream from base64 import b64decode import dbus from servicetest import EventPattern, assertEquals, assertContains, call_async from gabbletest import exec_test import constants as cs from saslutil import SaslEventAuthenticator, connect_and_get_sasl_channel, \ abort_auth JID = "test@example.org" PASSWORD = "pass" INITIAL_RESPONSE = '\0' + JID.split('@')[0] + '\0' + PASSWORD def test_plain_success(q, bus, conn, stream): chan, props = connect_and_get_sasl_channel(q, bus, conn) assertEquals(JID, props.get(cs.SASL_AUTHORIZATION_IDENTITY)) # On some servers we can't do DIGEST auth without this information. assertEquals('example.org', props.get(cs.SASL_DEFAULT_REALM)) # We can't necessarily do PLAIN auth without this information. assertEquals('test', props.get(cs.SASL_DEFAULT_USERNAME)) chan.SASLAuthentication.StartMechanismWithData('PLAIN', INITIAL_RESPONSE) e, _ = q.expect_many( EventPattern('sasl-auth', initial_response=INITIAL_RESPONSE), EventPattern('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_IN_PROGRESS, '', {}]), ) authenticator = e.authenticator authenticator.success(None) q.expect('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_SERVER_SUCCEEDED, '', {}]) chan.SASLAuthentication.AcceptSASL() q.expect('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_SUCCEEDED, '', {}]) e = q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) def test_plain_no_account(q, bus, conn, stream): chan, props = connect_and_get_sasl_channel(q, bus, conn) assertEquals('example.com', props.get(cs.SASL_DEFAULT_REALM)) assertEquals('', props.get(cs.SASL_DEFAULT_USERNAME)) chan.SASLAuthentication.StartMechanismWithData('PLAIN', INITIAL_RESPONSE) e, _ = q.expect_many( EventPattern('sasl-auth', initial_response=INITIAL_RESPONSE), EventPattern('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_IN_PROGRESS, '', {}]), ) authenticator = e.authenticator authenticator.success(None) q.expect('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_SERVER_SUCCEEDED, '', {}]) chan.SASLAuthentication.AcceptSASL() q.expect('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_SUCCEEDED, '', {}]) e = q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) def test_plain_fail_helper(q, bus, conn, stream, element, error, csr): chan, props = connect_and_get_sasl_channel(q, bus, conn) chan.SASLAuthentication.StartMechanismWithData('PLAIN', INITIAL_RESPONSE) e, _ = q.expect_many( EventPattern('sasl-auth', initial_response=INITIAL_RESPONSE), EventPattern('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_IN_PROGRESS, '', {}]), ) authenticator = e.authenticator authenticator.failure(element) e = q.expect('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH) assertEquals([cs.SASL_STATUS_SERVER_FAILED, error], e.args[:2]) assertContains('debug-message', e.args[2]) e = q.expect('dbus-signal', signal='ConnectionError') assertEquals(error, e.args[0]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, csr]) def test_plain_fail(q, bus, conn, stream): test_plain_fail_helper(q, bus, conn, stream, 'not-authorized', cs.AUTHENTICATION_FAILED, cs.CSR_AUTHENTICATION_FAILED) def test_plain_bad_encoding(q, bus, conn, stream): test_plain_fail_helper(q, bus, conn, stream, 'incorrect-encoding', cs.AUTHENTICATION_FAILED, cs.CSR_AUTHENTICATION_FAILED) def test_plain_weak(q, bus, conn, stream): test_plain_fail_helper(q, bus, conn, stream, 'mechanism-too-weak', cs.AUTHENTICATION_FAILED, cs.CSR_AUTHENTICATION_FAILED) def test_plain_bad_authzid(q, bus, conn, stream): test_plain_fail_helper(q, bus, conn, stream, 'invalid-authzid', cs.AUTHENTICATION_FAILED, cs.CSR_AUTHENTICATION_FAILED) def test_plain_bad_mech(q, bus, conn, stream): test_plain_fail_helper(q, bus, conn, stream, 'invalid-mechanism', cs.AUTHENTICATION_FAILED, cs.CSR_AUTHENTICATION_FAILED) def test_plain_tempfail(q, bus, conn, stream): test_plain_fail_helper(q, bus, conn, stream, 'temporary-failure', cs.AUTHENTICATION_FAILED, cs.CSR_AUTHENTICATION_FAILED) def test_plain_abort(q, bus, conn, stream): chan, props = connect_and_get_sasl_channel(q, bus, conn) chan.SASLAuthentication.StartMechanismWithData('PLAIN', INITIAL_RESPONSE) e, _ = q.expect_many( EventPattern('sasl-auth', initial_response=INITIAL_RESPONSE), EventPattern('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_IN_PROGRESS, '', {}]), ) authenticator = e.authenticator authenticator.success(None) q.expect('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_SERVER_SUCCEEDED, '', {}]) abort_auth(q, chan, cs.SASL_ABORT_REASON_INVALID_CHALLENGE, "Something is fishy") def test_bad_usage(q, bus, conn, stream): chan, props = connect_and_get_sasl_channel(q, bus, conn) call_async(q, chan.SASLAuthentication, 'Respond', 'This is uncalled for') q.expect('dbus-error', method='Respond', name=cs.NOT_AVAILABLE) chan.SASLAuthentication.StartMechanismWithData('PLAIN', INITIAL_RESPONSE) e, _ = q.expect_many( EventPattern('sasl-auth', initial_response=INITIAL_RESPONSE), EventPattern('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_IN_PROGRESS, '', {}]), ) authenticator = e.authenticator call_async(q, chan.SASLAuthentication, 'StartMechanismWithData', 'PLAIN', 'foo') q.expect('dbus-error', method='StartMechanismWithData', name=cs.NOT_AVAILABLE) authenticator.success(None) q.expect('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_SERVER_SUCCEEDED, '', {}]) call_async(q, chan.SASLAuthentication, 'Respond', 'Responding after success') q.expect('dbus-error', method='Respond', name=cs.NOT_AVAILABLE) if __name__ == '__main__': exec_test( test_plain_success, {'password': None, 'account' : JID}, authenticator=SaslEventAuthenticator('test', ['PLAIN']), do_connect=False) exec_test( test_plain_no_account, {'password': None, 'account' : 'example.com'}, authenticator=SaslEventAuthenticator('test', ['PLAIN']), do_connect=False) exec_test( test_plain_fail, {'password': None, 'account' : JID}, authenticator=SaslEventAuthenticator('test', ['PLAIN']), do_connect=False) exec_test( test_plain_bad_encoding, {'password': None, 'account' : JID}, authenticator=SaslEventAuthenticator('test', ['PLAIN']), do_connect=False) exec_test( test_plain_weak, {'password': None, 'account' : JID}, authenticator=SaslEventAuthenticator('test', ['PLAIN']), do_connect=False) exec_test( test_plain_bad_authzid, {'password': None, 'account' : JID}, authenticator=SaslEventAuthenticator('test', ['PLAIN']), do_connect=False) exec_test( test_plain_bad_mech, {'password': None, 'account' : JID}, authenticator=SaslEventAuthenticator('test', ['PLAIN']), do_connect=False) exec_test( test_plain_tempfail, {'password': None, 'account' : JID}, authenticator=SaslEventAuthenticator('test', ['PLAIN']), do_connect=False) exec_test( test_plain_abort, {'password': None, 'account' : JID}, authenticator=SaslEventAuthenticator('test', ['PLAIN']), do_connect=False) exec_test( test_bad_usage, {'password': None, 'account' : JID}, authenticator=SaslEventAuthenticator('test', ['PLAIN']), do_connect=False) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/sasl/telepathy-password.py������������������������������������0000664�0001750�0001750�00000003761�12332441362�026205� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test the server sasl channel with the X-TELEPATHY-PASSWORD mechanism. """ from servicetest import call_async from gabbletest import exec_test import constants as cs from saslutil import connect_and_get_sasl_channel PASSWORD = "pass" def test_close_straight_after_accept(q, bus, conn, stream): chan, props = connect_and_get_sasl_channel(q, bus, conn) call_async(q, chan.SASLAuthentication, 'StartMechanismWithData', 'X-TELEPATHY-PASSWORD', PASSWORD) # In_Progress appears before StartMechanismWithData returns q.expect('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_IN_PROGRESS, '', {}]) q.expect('dbus-return', method='StartMechanismWithData') q.expect('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_SERVER_SUCCEEDED, '', {}]) # fd.o#32278: # When this was breaking, gabble received AcceptSASL and told the # success_async GAsyncResult to complete in an idle. But, before # the result got its callback called, Close was also received and # the auth manager cleared its channel. When the idle function was # finally reached it saw it no longer had a channel (it had been # cleared in the closed callback) and thought it should be # chaining up to the wocky auth registry but of course it should # be calling the channel finish function. call_async(q, chan.SASLAuthentication, 'AcceptSASL') call_async(q, chan, 'Close') q.expect('dbus-signal', signal='SASLStatusChanged', interface=cs.CHANNEL_IFACE_SASL_AUTH, args=[cs.SASL_STATUS_SUCCEEDED, '', {}]) e = q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) if __name__ == '__main__': exec_test(test_close_straight_after_accept, {'password': None, 'account' : "test@example.org"}, do_connect=False) ���������������telepathy-gabble-0.18.3/tests/twisted/run-test.sh.in������������������������������������������������0000664�0001750�0001750�00000003163�12332441362�023550� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/bin/sh if test "x$GABBLE_TEST_UNINSTALLED" = x; then script_fullname=`readlink -e "@gabbletestsdir@/twisted/run-test.sh"` if [ `readlink -e "$0"` != "$script_fullname" ] ; then echo "This script is meant to be installed at $script_fullname" >&2 exit 1 fi test_src="@gabbletestsdir@" test_build="@gabbletestsdir@" config_file="@gabbletestsdir@/twisted/tools/servicedir/tmp-session-bus.conf" PYTHONPATH="@gabbletestsdir@/twisted" export PYTHONPATH GABBLE_TWISTED_PATH="@gabbletestsdir@/twisted" export GABBLE_TWISTED_PATH else if test -z "$GABBLE_ABS_TOP_SRCDIR"; then echo "GABBLE_ABS_TOP_SRCDIR must be set" >&2 exit 1 fi if test -z "$GABBLE_ABS_TOP_BUILDDIR"; then echo "GABBLE_ABS_TOP_BUILDDIR must be set" >&2 exit 1 fi test_src="${GABBLE_ABS_TOP_SRCDIR}/tests" test_build="${GABBLE_ABS_TOP_BUILDDIR}/tests" config_file="${test_build}/twisted/tools/servicedir-uninstalled/tmp-session-bus.conf" PYTHONPATH="${test_src}/twisted:${test_build}/twisted" export PYTHONPATH GABBLE_TWISTED_PATH="${test_src}/twisted" export GABBLE_TWISTED_PATH fi if [ -n "$1" ] ; then list="$1" else list=$(cat "${test_build}"/twisted/gabble-twisted-tests.list) fi any_failed=0 for i in $list ; do echo "Testing $i ..." sh "${test_src}/twisted/tools/with-session-bus.sh" \ ${GABBLE_TEST_SLEEP} \ --config-file="${config_file}" \ -- \ @TEST_PYTHON@ -u "${test_src}/twisted/$i" e=$? case "$e" in (0) echo "PASS: $i" ;; (77) echo "SKIP: $i" ;; (*) any_failed=1 echo "FAIL: $i ($e)" ;; esac done exit $any_failed �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/plugin-channel-managers.py������������������������������������0000664�0001750�0001750�00000001727�12332441362�026103� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test Gabble's implementation of channel managers from plugins. """ from servicetest import ( sync_dbus, call_async, EventPattern, assertEquals, assertContains, ) from gabbletest import exec_test, send_error_reply, acknowledge_iq, sync_stream import constants as cs from config import PLUGINS_ENABLED TEST_PLUGIN_IFACE = "org.freedesktop.Telepathy.Gabble.Plugin.Test" if not PLUGINS_ENABLED: print "NOTE: built without --enable-plugins, not testing plugins" raise SystemExit(77) # which makes the test show up as skipped def test(q, bus, conn, stream): rccs = conn.Properties.Get(cs.CONN_IFACE_REQUESTS, 'RequestableChannelClasses') # These values are from plugins/test.c fixed = { cs.CHANNEL_TYPE: "com.jonnylamb.lolbags", cs.TARGET_HANDLE_TYPE: cs.HT_NONE, } allowed = ["com.jonnylamb.omg", "com.jonnylamb.brokethebuild"] assertContains((fixed, allowed), rccs) if __name__ == '__main__': exec_test(test) �����������������������������������������telepathy-gabble-0.18.3/tests/twisted/cm/�����������������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�021431� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/cm/protocol.py������������������������������������������������0000664�0001750�0001750�00000006705�12332441362�023645� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test Gabble's o.T.Protocol implementation """ import dbus from servicetest import unwrap, tp_path_prefix, assertEquals from gabbletest import exec_test, call_async import constants as cs import time def test(q, bus, conn, stream): cm = bus.get_object(cs.CM + '.gabble', tp_path_prefix + '/ConnectionManager/gabble') cm_iface = dbus.Interface(cm, cs.CM) cm_prop_iface = dbus.Interface(cm, cs.PROPERTIES_IFACE) protocols = unwrap(cm_prop_iface.Get(cs.CM, 'Protocols')) assertEquals(set(['jabber']), set(protocols.keys())) protocol_names = unwrap(cm_iface.ListProtocols()) assertEquals(set(['jabber']), set(protocol_names)) cm_params = cm_iface.GetParameters('jabber') jabber_props = protocols['jabber'] jabber_params = jabber_props[cs.PROTOCOL + '.Parameters'] assertEquals(cm_params, jabber_params) proto = bus.get_object(cm.bus_name, cm.object_path + '/jabber') proto_iface = dbus.Interface(proto, cs.PROTOCOL) proto_prop_iface = dbus.Interface(proto, cs.PROPERTIES_IFACE) proto_props = unwrap(proto_prop_iface.GetAll(cs.PROTOCOL)) for key in ['Parameters', 'Interfaces', 'ConnectionInterfaces', 'RequestableChannelClasses', u'VCardField', u'EnglishName', u'Icon']: a = jabber_props[cs.PROTOCOL + '.' + key] b = proto_props[key] assertEquals(a, b) assertEquals('foo@mit.edu', unwrap(proto_iface.NormalizeContact('foo@MIT.Edu/Telepathy'))) # org.freedesktop.Telepathy.Protocol.Interface.Presence expected_status = {'available': (cs.PRESENCE_AVAILABLE, True, True), 'dnd' : (cs.PRESENCE_BUSY, True, True), 'unknown' : (cs.PRESENCE_UNKNOWN, False, False), 'away' : (cs.PRESENCE_AWAY, True, True), 'xa' : (cs.PRESENCE_EXTENDED_AWAY, True, True), 'chat' : (cs.PRESENCE_AVAILABLE, True, True), 'error' : (cs.PRESENCE_ERROR, False, False), 'offline' : (cs.PRESENCE_OFFLINE, False, False), 'testaway' : (cs.PRESENCE_AWAY, False, False), 'testbusy' : (cs.PRESENCE_BUSY, True, False), 'hidden' : (cs.PRESENCE_HIDDEN, True, True)} presences = proto_prop_iface.Get(cs.PROTOCOL_IFACE_PRESENCES, 'Statuses'); # Plugins could add additional statuses, so we check if expected_status is # included in presences rather than equality. for k, v in expected_status.iteritems(): assertEquals(expected_status[k], unwrap(presences[k])) # (Only) 'account' is mandatory for IdentifyAccount() call_async(q, proto_iface, 'IdentifyAccount', {}) q.expect('dbus-error', method='IdentifyAccount', name=cs.INVALID_ARGUMENT) test_params = { 'account': 'test@localhost' } acc_name = unwrap(proto_iface.IdentifyAccount(test_params)) assertEquals(test_params['account'], acc_name) conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) q.expect('stream-authenticated') q.expect('dbus-signal', signal='PresencesChanged', args=[{1L: (cs.PRESENCE_AVAILABLE, 'available', '')}]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) return if __name__ == '__main__': exec_test(test, do_connect=False) �����������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/mucutil.py����������������������������������������������������0000664�0001750�0001750�00000006716�12332441362�023071� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# vim: set fileencoding=utf-8 : Python sucks! """ Utility functions for tests that need to interact with MUCs. """ import dbus from twisted.words.xish import domish, xpath from servicetest import call_async, wrap_channel, EventPattern, assertLength from gabbletest import make_muc_presence, request_muc_handle import constants as cs import ns def echo_muc_presence (q, stream, stanza, affiliation, role): x = stanza.addElement((ns.MUC_USER, 'x')) stanza['from'] = stanza['to'] del stanza['to'] item = x.addElement('item') item['affiliation'] = affiliation item['role'] = role stream.send (stanza) def try_to_join_muc(q, bus, conn, stream, muc, request=None): """ Ask Gabble to join a MUC, and expect it to send <presence/> Returns: the stream-presence Event object. """ if request is None: request = { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: muc, } call_async(q, conn.Requests, 'CreateChannel', dbus.Dictionary(request, signature='sv')) join_event = q.expect('stream-presence', to='%s/test' % muc) # XEP-0045 §7.1.2 sez: # “MUC clients SHOULD signal their ability to speak the MUC protocol by # including in the initial presence stanza an empty <x/> element # qualified by the 'http://jabber.org/protocol/muc' namespace.” x_muc_nodes = xpath.queryForNodes('/presence/x[@xmlns="%s"]' % ns.MUC, join_event.stanza) assertLength(1, x_muc_nodes) return join_event def join_muc(q, bus, conn, stream, muc, request=None, also_capture=[], role='participant', affiliation='none'): """ Joins 'muc', returning the muc's handle, a proxy object for the channel, its path and its immutable properties just after the CreateChannel event has fired. The room contains one other member. """ muc_handle = request_muc_handle(q, conn, stream, muc) try_to_join_muc(q, bus, conn, stream, muc, request=request) # Send presence for other member of room. stream.send(make_muc_presence('owner', 'moderator', muc, 'bob')) # Send presence for own membership of room. stream.send(make_muc_presence(affiliation, role, muc, 'test')) captured = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), *also_capture) path, props = captured[0].value chan = wrap_channel(bus.get_object(conn.bus_name, path), 'Text', ['Messages', 'Subject.DRAFT', 'RoomConfig1', 'ChatState']) return (muc_handle, chan, path, props) + tuple(captured[1:]) def join_muc_and_check(q, bus, conn, stream, muc, request=None): """ Like join_muc(), but also checks the NewChannels and NewChannel signals and the Members property, and returns both members' handles. """ muc_handle, chan, path, props = \ join_muc(q, bus, conn, stream, muc, request=request) q.expect('dbus-signal', signal='NewChannels', args=[[(path, props)]]) q.expect('dbus-signal', signal='NewChannel', args=[path, cs.CHANNEL_TYPE_TEXT, cs.HT_ROOM, muc_handle, True]) test_handle, bob_handle = conn.RequestHandles(cs.HT_CONTACT, ['%s/test' % muc, '%s/bob' % muc]) members = chan.Get(cs.CHANNEL_IFACE_GROUP, 'Members', dbus_interface=cs.PROPERTIES_IFACE) assert set(members) == set([test_handle, bob_handle]), \ (members, (test_handle, bob_handle)) return (muc_handle, chan, test_handle, bob_handle) ��������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle-share/�������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�023402� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle-share/test-receive-file-decline.py���������������������0000664�0001750�0001750�00000006141�12225363340�030664� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import dbus import constants as cs from servicetest import EventPattern from file_transfer_helper import SendFileTest, ReceiveFileTest, \ FileTransferTest, exec_file_transfer_test from config import JINGLE_FILE_TRANSFER_ENABLED if not JINGLE_FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer or --disable-voip" raise SystemExit(77) class ReceiveFileDecline(ReceiveFileTest): def __init__(self, file, address_type, access_control, access_control_param): FileTransferTest.__init__(self, file, address_type, access_control, access_control_param) self._actions = [self.connect, self.set_ft_caps, None, self.wait_for_ft_caps, None, self.check_new_channel, self.close_and_check, self.done] def close_and_check(self): self.channel.Close() state_event, event, _ = self.q.expect_many( EventPattern('dbus-signal', signal='FileTransferStateChanged', path=self.channel.object_path), EventPattern('stream-iq', stream=self.stream, iq_type='set', query_name='session'), EventPattern('dbus-signal', signal='Closed', path=self.channel.object_path)) state, reason = state_event.args assert state == cs.FT_STATE_CANCELLED assert reason == cs.FT_STATE_CHANGE_REASON_LOCAL_STOPPED while event.query.getAttribute('type') != 'terminate': event = self.q.expect('stream-iq', stream=self.stream, iq_type='set', query_name='session') class SendFileDeclined (SendFileTest): def __init__(self, file, address_type, access_control, acces_control_param): FileTransferTest.__init__(self, file, address_type, access_control, acces_control_param) self._actions = [self.connect, self.set_ft_caps, self.check_ft_available, None, self.wait_for_ft_caps, None, self.request_ft_channel, self.provide_file, None, self.check_declined, self.close_channel, self.done] def check_declined(self): state_event = self.q.expect('dbus-signal', signal='FileTransferStateChanged', path=self.channel.object_path) state, reason = state_event.args assert state == cs.FT_STATE_CANCELLED assert reason == cs.FT_STATE_CHANGE_REASON_REMOTE_STOPPED transferred = self.ft_props.Get(cs.CHANNEL_TYPE_FILE_TRANSFER, 'TransferredBytes') # no byte has been transferred as the file was declined assert transferred == 0 # try to provide the file try: self.provide_file() except dbus.DBusException, e: assert e.get_dbus_name() == cs.NOT_AVAILABLE else: assert False if __name__ == '__main__': exec_file_transfer_test(SendFileDeclined, ReceiveFileDecline) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle-share/jingleshareutils.py������������������������������0000664�0001750�0001750�00000007646�12332441362�027336� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import dbus from twisted.words.xish import xpath from servicetest import (assertEquals, EventPattern) from gabbletest import exec_test, make_result_iq, sync_stream, make_presence import constants as cs from caps_helper import compute_caps_hash, \ text_fixed_properties, text_allowed_properties, \ ft_fixed_properties, ft_allowed_properties import ns run = 0 def test_ft_caps_from_contact(q, bus, conn, stream, contact, contact_handle, client): global run run += 1 conn_caps_iface = dbus.Interface(conn, cs.CONN_IFACE_CONTACT_CAPS) conn_contacts_iface = dbus.Interface(conn, cs.CONN_IFACE_CONTACTS) # send presence with no FT cap presence = make_presence(contact, status='hello') c = presence.addElement((ns.CAPS, 'c')) c['node'] = client c['ver'] = compute_caps_hash(['client/pc//jingleshareutils-%d' % run], [], {}) c['ext'] = "" stream.send(presence) # Gabble looks up our capabilities event = q.expect('stream-iq', to=contact, query_ns=ns.DISCO_INFO) query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assert query_node.attributes['node'] == \ client + '#' + c['ver'] # send good reply result = make_result_iq(stream, event.stanza) query = result.firstChildElement() query['node'] = client + '#' + c['ver'] stream.send(result) # no change in ContactCapabilities, so no signal ContactCapabilitiesChanged sync_stream(q, stream) # no special capabilities basic_caps = dbus.Dictionary({contact_handle: [(text_fixed_properties, text_allowed_properties)]}) caps = conn_caps_iface.GetContactCapabilities([contact_handle]) assert caps == basic_caps, caps # test again, to check GetContactCapabilities does not have side effect caps = conn_caps_iface.GetContactCapabilities([contact_handle]) assert caps == basic_caps, caps # check the Contacts interface give the same caps caps_via_contacts_iface = conn_contacts_iface.GetContactAttributes( [contact_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [contact_handle][cs.ATTR_CONTACT_CAPABILITIES] assert caps_via_contacts_iface == caps[contact_handle], \ caps_via_contacts_iface # send presence with ft capa presence = make_presence(contact, status='hello') c = presence.addElement((ns.CAPS, 'c')) c['node'] = client c['ext'] = "share-v1" c['ver'] = '1.1' stream.send(presence) # Gabble looks up our capabilities event = q.expect('stream-iq', to=contact, query_ns=ns.DISCO_INFO) query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assertEquals(client + '#' + c['ver'], query_node.attributes['node']) # send good reply result = make_result_iq(stream, event.stanza) query = result.firstChildElement() query['node'] = client + '#' + c['ver'] feature = query.addElement('feature') feature['var'] = ns.GOOGLE_FEAT_SHARE stream.send(result) generic_ft_caps = dbus.Dictionary({contact_handle: [(text_fixed_properties, text_allowed_properties), (ft_fixed_properties, ft_allowed_properties)]}) event = q.expect('dbus-signal', signal='ContactCapabilitiesChanged') assert len(event.args) == 1 assert event.args[0] == generic_ft_caps caps = conn_caps_iface.GetContactCapabilities([contact_handle]) assert caps == generic_ft_caps, caps # test again, to check GetContactCapabilities does not have side effect caps = conn_caps_iface.GetContactCapabilities([contact_handle]) assert caps == generic_ft_caps, caps # check the Contacts interface give the same caps caps_via_contacts_iface = conn_contacts_iface.GetContactAttributes( [contact_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [contact_handle][cs.ATTR_CONTACT_CAPABILITIES] assert caps_via_contacts_iface == caps[contact_handle], \ caps_via_contacts_iface ������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle-share/test-receive-file-and-disconnect.py��������������0000664�0001750�0001750�00000001176�12225363340�032155� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ from file_transfer_helper import SendFileTest, ReceiveFileTest, \ exec_file_transfer_test from config import JINGLE_FILE_TRANSFER_ENABLED if not JINGLE_FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer or --disable-voip" raise SystemExit(77) class ReceiveFileAndDisconnectTest(ReceiveFileTest): def receive_file(self): s = self.create_socket() s.connect(self.address) # return True so the test will be ended and the connection # disconnected return True if __name__ == '__main__': exec_file_transfer_test(SendFileTest, ReceiveFileAndDisconnectTest) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle-share/file_transfer_helper.py��������������������������0000664�0001750�0001750�00000057546�12332441362�030150� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import dbus import socket import hashlib import time import datetime from servicetest import EventPattern, assertEquals, assertLength, assertSameSets from gabbletest import exec_test, sync_stream, make_result_iq, elem_iq, elem import ns from caps_helper import text_fixed_properties, text_allowed_properties, \ stream_tube_fixed_properties, stream_tube_allowed_properties, \ dbus_tube_fixed_properties, dbus_tube_allowed_properties, \ ft_fixed_properties, ft_allowed_properties, compute_caps_hash, \ extract_disco_parts from twisted.words.xish import domish, xpath import constants as cs import sys class File(object): DEFAULT_DATA = "What a nice file" DEFAULT_NAME = "The foo.txt" DEFAULT_CONTENT_TYPE = 'text/plain' DEFAULT_DESCRIPTION = "A nice file to test" def __init__(self, data=DEFAULT_DATA, name=DEFAULT_NAME, content_type=DEFAULT_CONTENT_TYPE, description=DEFAULT_DESCRIPTION, hash_type=cs.FILE_HASH_TYPE_MD5): self.data = data self.size = len(self.data) self.name = name self.content_type = content_type self.description = description self.date = int(time.time()) self.compute_hash(hash_type) self.offset = 0 def compute_hash(self, hash_type): assert hash_type == cs.FILE_HASH_TYPE_MD5 self.hash_type = hash_type self.hash = hashlib.md5(self.data).hexdigest() generic_ft_caps = [(text_fixed_properties, text_allowed_properties), (stream_tube_fixed_properties, \ stream_tube_allowed_properties), (dbus_tube_fixed_properties, dbus_tube_allowed_properties), (ft_fixed_properties, ft_allowed_properties)] generic_caps = [(text_fixed_properties, text_allowed_properties), (stream_tube_fixed_properties, \ stream_tube_allowed_properties), (dbus_tube_fixed_properties, dbus_tube_allowed_properties)] class FileTransferTest(object): caps_identities = None caps_features = None caps_dataforms = None caps_ft = None def __init__(self, file, address_type, access_control, access_control_param): self.file = file self.address_type = address_type self.access_control = access_control self.access_control_param = access_control_param self.closed = True def connect(self): self.conn.Connect() self.q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED], path=self.conn.object.object_path) self.self_handle = self.conn.GetSelfHandle() self.self_handle_name = self.conn.InspectHandles(cs.HT_CONTACT, [self.self_handle])[0] def set_target(self, jid): self.target = jid self.handle = self.conn.RequestHandles(cs.HT_CONTACT, [jid])[0] def set_ft_caps(self): caps_iface = dbus.Interface(self.conn, cs.CONN_IFACE_CONTACT_CAPS) caps_iface.UpdateCapabilities([("self", [ft_fixed_properties], dbus.Array([], signature="s"))]) self.q.expect('dbus-signal', signal='ContactCapabilitiesChanged', path=self.conn.object.object_path, args=[{self.self_handle:generic_ft_caps}]) def wait_for_ft_caps(self): conn_caps_iface = dbus.Interface(self.conn, cs.CONN_IFACE_CONTACT_CAPS) caps = conn_caps_iface.GetContactCapabilities([self.handle]) if caps != dbus.Dictionary({self.handle:generic_ft_caps}): self.q.expect('dbus-signal', signal='ContactCapabilitiesChanged', path=self.conn.object.object_path, args=[{self.handle:generic_ft_caps}]) caps = conn_caps_iface.GetContactCapabilities([self.handle]) assert caps == dbus.Dictionary({self.handle:generic_ft_caps}), caps def create_ft_channel(self): ft_chan = self.bus.get_object(self.conn.object.bus_name, self.ft_path) self.channel = dbus.Interface(ft_chan, cs.CHANNEL) self.ft_channel = dbus.Interface(ft_chan, cs.CHANNEL_TYPE_FILE_TRANSFER) self.ft_props = dbus.Interface(ft_chan, cs.PROPERTIES_IFACE) self.closed = False def channel_closed_cb(): self.closed = True self.channel.connect_to_signal('Closed', channel_closed_cb) def close_channel(self): if self.closed is False: self.channel.Close() self.q.expect('dbus-signal', signal='Closed', path=self.channel.object_path) def done(self): pass def test(self, q, bus, conn, stream): self.q = q self.bus = bus self.conn = conn self.stream = stream self.stream.addObserver( "//presence", self._cb_presence_iq, priority=1) self.stream.addObserver( "/iq/query[@xmlns='http://jabber.org/protocol/disco#info']", self._cb_disco_iq, priority=1) def _cb_presence_iq(self, stanza): nodes = xpath.queryForNodes("/presence/c", stanza) c = nodes[0] if 'share-v1' in c.getAttribute('ext'): assert FileTransferTest.caps_identities is not None and \ FileTransferTest.caps_features is not None and \ FileTransferTest.caps_dataforms is not None new_hash = compute_caps_hash(FileTransferTest.caps_identities, FileTransferTest.caps_features + \ [ns.GOOGLE_FEAT_SHARE], FileTransferTest.caps_dataforms) # Replace ver hash from one with file-transfer ns to one without FileTransferTest.caps_ft = c.attributes['ver'] c.attributes['ver'] = new_hash else: node = c.attributes['node'] ver = c.attributes['ver'] # ask for raw caps request = elem_iq(self.stream, 'get', from_='fake_contact@jabber.org/resource')( elem(ns.DISCO_INFO, 'query', node=(node + '#' + ver))) self.stream.send(request) def _cb_disco_iq(self, iq): nodes = xpath.queryForNodes("/iq/query", iq) query = nodes[0] if query.getAttribute('node') is None: return node = query.attributes['node'] ver = node.replace("http://telepathy.freedesktop.org/caps#", "") if iq.getAttribute('type') == 'result': if FileTransferTest.caps_identities is None or \ FileTransferTest.caps_features is None or \ FileTransferTest.caps_dataforms is None: # create our own identity identity_nodes = xpath.queryForNodes('/iq/query/identity', iq) assertLength(1, identity_nodes) identity_node = identity_nodes[0] identity_category = identity_node['category'] identity_type = identity_node['type'] identity_name = identity_node['name'] identity = '%s/%s//%s' % (identity_category, identity_type, identity_name) _, features, dataforms = extract_disco_parts(iq) FileTransferTest.caps_identities = [identity] FileTransferTest.caps_features = features FileTransferTest.caps_dataforms = dataforms # Check if the hash matches the announced capabilities assertEquals(compute_caps_hash(FileTransferTest.caps_identities, FileTransferTest.caps_features, FileTransferTest.caps_dataforms), ver) if ver == FileTransferTest.caps_ft: caps_share = compute_caps_hash(FileTransferTest.caps_identities, FileTransferTest.caps_features + \ [ns.GOOGLE_FEAT_SHARE], FileTransferTest.caps_dataforms) n = query.attributes['node'].replace(ver, caps_share) query.attributes['node'] = n for feature in xpath.queryForNodes('/iq/query/feature', iq): query.children.remove(feature) for f in FileTransferTest.caps_features + [ns.GOOGLE_FEAT_SHARE]: el = domish.Element((None, 'feature')) el['var'] = f query.addChild(el) elif iq.getAttribute('type') == 'get': caps_share = compute_caps_hash(FileTransferTest.caps_identities, FileTransferTest.caps_features + \ [ns.GOOGLE_FEAT_SHARE], FileTransferTest.caps_dataforms) if ver == caps_share: n = query.attributes['node'].replace(ver, FileTransferTest.caps_ft) query.attributes['node'] = n def create_socket(self): if self.address_type == cs.SOCKET_ADDRESS_TYPE_UNIX: return socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) elif self.address_type == cs.SOCKET_ADDRESS_TYPE_IPV4: return socket.socket(socket.AF_INET, socket.SOCK_STREAM) elif self.address_type == cs.SOCKET_ADDRESS_TYPE_IPV6: return socket.socket(socket.AF_INET6, socket.SOCK_STREAM) else: assert False class ReceiveFileTest(FileTransferTest): def __init__(self, file, address_type, access_control, access_control_param): FileTransferTest.__init__(self, file, address_type, access_control, access_control_param) self._actions = [self.connect, self.set_ft_caps, None, self.wait_for_ft_caps, None, self.check_new_channel, self.accept_file, None, self.receive_file, None, self.close_channel, self.done] def check_new_channel(self): def is_ft_channel_event(event): channels, = event.args if len(channels) > 1: return False path, props = channels[0] return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_FILE_TRANSFER e = self.q.expect('dbus-signal', signal='NewChannels', path=self.conn.object.object_path, predicate=is_ft_channel_event) channels, = e.args path, props = channels[0] # check channel properties # org.freedesktop.Telepathy.Channel D-Bus properties assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_FILE_TRANSFER, props assertSameSets( [ cs.CHANNEL_IFACE_FILE_TRANSFER_METADATA, cs.CHANNEL_TYPE_FILE_TRANSFER + '.FUTURE', ], props[cs.INTERFACES]) assert props[cs.TARGET_HANDLE] == self.handle, props assert props[cs.TARGET_ID] == self.target, props assert props[cs.TARGET_HANDLE_TYPE] == cs.HT_CONTACT, props assert props[cs.REQUESTED] == False, props assert props[cs.INITIATOR_HANDLE] == self.handle, props assert props[cs.INITIATOR_ID] == self.target, props # org.freedesktop.Telepathy.Channel.Type.FileTransfer D-Bus properties assert props[cs.FT_STATE] == cs.FT_STATE_PENDING, props assert props[cs.FT_CONTENT_TYPE] == '', props assert props[cs.FT_FILENAME].encode('utf-8') == self.file.name, props assert props[cs.FT_SIZE] == self.file.size, props # FT's protocol doesn't allow us the send the hash info assert props[cs.FT_CONTENT_HASH_TYPE] == cs.FILE_HASH_TYPE_NONE, props assert props[cs.FT_CONTENT_HASH] == '', props assert props[cs.FT_DESCRIPTION] == '', props assert props[cs.FT_DATE] == 0, props assert props[cs.FT_AVAILABLE_SOCKET_TYPES] == \ {cs.SOCKET_ADDRESS_TYPE_UNIX: [cs.SOCKET_ACCESS_CONTROL_LOCALHOST], cs.SOCKET_ADDRESS_TYPE_IPV4: [cs.SOCKET_ACCESS_CONTROL_LOCALHOST], cs.SOCKET_ADDRESS_TYPE_IPV6: [cs.SOCKET_ACCESS_CONTROL_LOCALHOST]}, \ props[cs.FT_AVAILABLE_SOCKET_TYPES] assert props[cs.FT_TRANSFERRED_BYTES] == 0, props assert props[cs.FT_INITIAL_OFFSET] == 0, props self.ft_path = path self.create_ft_channel() def accept_file(self): self.address = self.ft_channel.AcceptFile(self.address_type, self.access_control, self.access_control_param, self.file.offset, byte_arrays=True) state_event = self.q.expect('dbus-signal', signal='FileTransferStateChanged', path=self.channel.object_path) state, reason = state_event.args assert state == cs.FT_STATE_ACCEPTED assert reason == cs.FT_STATE_CHANGE_REASON_REQUESTED state_event, offset_event = self.q.expect_many( EventPattern ('dbus-signal', signal='FileTransferStateChanged', path=self.channel.object_path), EventPattern ('dbus-signal', signal='InitialOffsetDefined', path=self.channel.object_path)) offset = offset_event.args[0] assert offset == 0 state, reason = state_event.args assert state == cs.FT_STATE_OPEN assert reason == cs.FT_STATE_CHANGE_REASON_NONE def receive_file(self): # Connect to Gabble's socket s = self.create_socket() s.connect(self.address) self._read_file_from_socket(s) def _read_file_from_socket(self, s): # Read the file from Gabble's socket data = '' read = 0 to_receive = self.file.size e = self.q.expect('dbus-signal', signal='TransferredBytesChanged', path=self.channel.object_path) count = e.args[0] while True: received = s.recv(1024) if len(received) == 0: break data += received assert data == self.file.data while count < to_receive: # Catch TransferredBytesChanged until we transfered all the data e = self.q.expect('dbus-signal', signal='TransferredBytesChanged', path=self.channel.object_path) count = e.args[0] e = self.q.expect('dbus-signal', signal='FileTransferStateChanged', path=self.channel.object_path) state, reason = e.args assert state == cs.FT_STATE_COMPLETED assert reason == cs.FT_STATE_CHANGE_REASON_NONE class SendFileTest(FileTransferTest): def __init__(self, file, address_type, access_control, acces_control_param): FileTransferTest.__init__(self, file, address_type, access_control, acces_control_param) self._actions = [self.connect, self.set_ft_caps, self.check_ft_available, None, self.wait_for_ft_caps, None, self.request_ft_channel, self.provide_file, None, self.send_file, self.wait_for_completion, None, self.close_channel, self.done] def check_ft_available(self): properties = self.conn.GetAll(cs.CONN_IFACE_REQUESTS, dbus_interface=cs.PROPERTIES_IFACE) # general FT class assert ({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_FILE_TRANSFER, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT}, [cs.FT_CONTENT_HASH_TYPE, cs.TARGET_HANDLE, cs.TARGET_ID, cs.FT_CONTENT_TYPE, cs.FT_FILENAME, cs.FT_SIZE, cs.FT_CONTENT_HASH, cs.FT_DESCRIPTION, cs.FT_DATE, cs.FT_URI, cs.FT_SERVICE_NAME, cs.FT_METADATA] ) in properties.get('RequestableChannelClasses'),\ properties['RequestableChannelClasses'] # FT class with MD5 as HashType assert ({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_FILE_TRANSFER, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.FT_CONTENT_HASH_TYPE: cs.FILE_HASH_TYPE_MD5}, [cs.TARGET_HANDLE, cs.TARGET_ID, cs.FT_CONTENT_TYPE, cs.FT_FILENAME, cs.FT_SIZE, cs.FT_CONTENT_HASH, cs.FT_DESCRIPTION, cs.FT_DATE, cs.FT_URI, cs.FT_SERVICE_NAME, cs.FT_METADATA] ) in properties.get('RequestableChannelClasses'),\ properties['RequestableChannelClasses'] def request_ft_channel(self): self.ft_path, props = self.conn.Requests.CreateChannel({ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_FILE_TRANSFER, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: self.handle, cs.FT_CONTENT_TYPE: self.file.content_type, cs.FT_FILENAME: self.file.name, cs.FT_SIZE: self.file.size, cs.FT_CONTENT_HASH_TYPE: self.file.hash_type, cs.FT_CONTENT_HASH: self.file.hash, cs.FT_DESCRIPTION: self.file.description, cs.FT_DATE: self.file.date, cs.FT_INITIAL_OFFSET: 0, }) # org.freedesktop.Telepathy.Channel D-Bus properties assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_FILE_TRANSFER assertSameSets( [ cs.CHANNEL_IFACE_FILE_TRANSFER_METADATA, cs.CHANNEL_TYPE_FILE_TRANSFER + '.FUTURE', ], props[cs.INTERFACES]) assert props[cs.TARGET_HANDLE] == self.handle assert props[cs.TARGET_ID] == self.target assert props[cs.TARGET_HANDLE_TYPE] == cs.HT_CONTACT assert props[cs.REQUESTED] == True assert props[cs.INITIATOR_HANDLE] == self.self_handle assert props[cs.INITIATOR_ID] == self.self_handle_name # org.freedesktop.Telepathy.Channel.Type.FileTransfer D-Bus properties assert props[cs.FT_STATE] == cs.FT_STATE_PENDING assert props[cs.FT_CONTENT_TYPE] == self.file.content_type assert props[cs.FT_FILENAME].encode('utf-8') == self.file.name, props assert props[cs.FT_SIZE] == self.file.size assert props[cs.FT_CONTENT_HASH_TYPE] == self.file.hash_type assert props[cs.FT_CONTENT_HASH] == self.file.hash assert props[cs.FT_DESCRIPTION] == self.file.description assert props[cs.FT_DATE] == self.file.date assert props[cs.FT_AVAILABLE_SOCKET_TYPES] == \ {cs.SOCKET_ADDRESS_TYPE_UNIX: [cs.SOCKET_ACCESS_CONTROL_LOCALHOST], cs.SOCKET_ADDRESS_TYPE_IPV4: [cs.SOCKET_ACCESS_CONTROL_LOCALHOST], cs.SOCKET_ADDRESS_TYPE_IPV6: [cs.SOCKET_ACCESS_CONTROL_LOCALHOST]}, \ props[cs.FT_AVAILABLE_SOCKET_TYPES] assert props[cs.FT_TRANSFERRED_BYTES] == 0 assert props[cs.FT_INITIAL_OFFSET] == 0 self.create_ft_channel() self.open = False self.offset_defined = False def initial_offset_defined_cb(offset): self.offset_defined = True assert offset == 0, offset self.ft_channel.connect_to_signal('InitialOffsetDefined', initial_offset_defined_cb) # Make sure the file transfer is of type jingle-share event = self.q.expect('stream-iq', stream=self.stream, query_name = 'session', query_ns = ns.GOOGLE_SESSION) description_node = xpath.queryForNodes('/iq/session/description', event.stanza)[0] assert description_node.uri == ns.GOOGLE_SESSION_SHARE, \ description_node.uri def provide_file(self): # try to accept our outgoing file transfer try: self.ft_channel.AcceptFile(self.address_type, self.access_control, self.access_control_param, self.file.offset, byte_arrays=True) except dbus.DBusException, e: assert e.get_dbus_name() == cs.NOT_AVAILABLE else: assert False # In case a unit test accepts the FT before we ProvideFile # then the ProvideFile will result in an OPEN state with reason state = self.ft_props.Get(cs.CHANNEL_TYPE_FILE_TRANSFER, 'State') if state == cs.FT_STATE_ACCEPTED: self.open_reason = cs.FT_STATE_CHANGE_REASON_REQUESTED else: self.open_reason = cs.FT_STATE_CHANGE_REASON_NONE self.address = self.ft_channel.ProvideFile(self.address_type, self.access_control, self.access_control_param, byte_arrays=True) def send_file(self): if self.open is False: self.q.expect('dbus-signal', signal='FileTransferStateChanged', path=self.channel.object_path, args=[cs.FT_STATE_OPEN, self.open_reason]) assert self.offset_defined == True s = self.create_socket() s.connect(self.address) s.send(self.file.data) def wait_for_completion(self): to_send = self.file.size self.count = 0 def bytes_changed_cb(bytes): self.count = bytes self.ft_channel.connect_to_signal('TransferredBytesChanged', bytes_changed_cb) # FileTransferStateChanged can be fired while we are receiving data self.completed = False def ft_state_changed_cb(state, reason): if state == cs.FT_STATE_COMPLETED: self.completed = True self.ft_channel.connect_to_signal('FileTransferStateChanged', ft_state_changed_cb) # If not all the bytes transferred have been announced using # TransferredBytesChanged, wait for them while self.count < to_send: self.q.expect('dbus-signal', signal='TransferredBytesChanged', path=self.channel.object_path) assert self.count == to_send def exec_file_transfer_test(send_cls, recv_cls, file = None): addr_type = cs.SOCKET_ADDRESS_TYPE_IPV4 access_control = cs.SOCKET_ACCESS_CONTROL_LOCALHOST access_control_param = "" if file is None: file = File() def test(q, bus, conns, streams): q.timeout = 15 conn1, conn2 = conns stream1, stream2 = streams send = send_cls(file, addr_type, access_control, access_control_param) recv = recv_cls(file, addr_type, access_control, access_control_param) send.test(q, bus, conn1, stream1) recv.test(q, bus, conn2, stream2) send_action = 0 recv_action = 0 target_set = False done = False while send_action < len(send._actions) or \ recv_action < len(recv._actions): for i in range(send_action, len(send._actions)): action = send._actions[i] if action is None: break done = action() if done is True: break send_action = i + 1 if done is True: break for i in range(recv_action, len(recv._actions)): action = recv._actions[i] if action is None: break done = action() if done is True: break recv_action = i + 1 if done is True: break if target_set == False: send.set_target(recv.self_handle_name) recv.set_target(send.self_handle_name) target_set = True exec_test(test, num_instances=2, do_connect=False) ����������������������������������������������������������������������������������������������������������������������������������������������������������test-receive-file-and-close-socket-while-receiving.py�����������������������������������������������0000664�0001750�0001750�00000001462�12225363340�035415� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000�telepathy-gabble-0.18.3/tests/twisted/jingle-share��������������������������������������������������������������������������������������������������������������������� import constants as cs from file_transfer_helper import SendFileTest, ReceiveFileTest, \ exec_file_transfer_test from config import JINGLE_FILE_TRANSFER_ENABLED if not JINGLE_FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer or --disable-voip" raise SystemExit(77) class ReceiveFileAndCancelWhileReceiving(ReceiveFileTest): def receive_file(self): # Connect to Gabble's socket s = self.create_socket() s.connect(self.address) # for some reason the socket is closed s.close() self.q.expect('dbus-signal', signal='FileTransferStateChanged', args=[cs.FT_STATE_CANCELLED, cs.FT_STATE_CHANGE_REASON_LOCAL_ERROR]) if __name__ == '__main__': exec_file_transfer_test(SendFileTest, ReceiveFileAndCancelWhileReceiving) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle-share/test-caps-file-transfer.py�����������������������0000664�0001750�0001750�00000014373�12332441362�030417� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import dbus from twisted.words.xish import xpath from servicetest import (assertEquals, EventPattern) from gabbletest import exec_test, make_result_iq, sync_stream, make_presence import constants as cs from caps_helper import compute_caps_hash, \ text_fixed_properties, text_allowed_properties, \ stream_tube_fixed_properties, stream_tube_allowed_properties, \ dbus_tube_fixed_properties, dbus_tube_allowed_properties, \ ft_fixed_properties, ft_allowed_properties_with_metadata import ns from jingleshareutils import test_ft_caps_from_contact from config import FILE_TRANSFER_ENABLED if not FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer" raise SystemExit(77) def test(q, bus, conn, stream): client = 'http://telepathy.freedesktop.org/fake-client' test_ft_caps_from_contact(q, bus, conn, stream, 'bilbo1@foo.com/Foo', 2L, client) # our own capabilities, formerly tested here, are now in # tests/twisted/caps/advertise-contact-capabilities.py generic_ft_caps = [(text_fixed_properties, text_allowed_properties), (stream_tube_fixed_properties, \ stream_tube_allowed_properties), (dbus_tube_fixed_properties, dbus_tube_allowed_properties), (ft_fixed_properties, ft_allowed_properties_with_metadata)] generic_caps = [(text_fixed_properties, text_allowed_properties), (stream_tube_fixed_properties, \ stream_tube_allowed_properties), (dbus_tube_fixed_properties, dbus_tube_allowed_properties)] def check_contact_caps(conn, handle, with_ft): conn_caps_iface = dbus.Interface(conn, cs.CONN_IFACE_CONTACT_CAPS) conn_contacts_iface = dbus.Interface(conn, cs.CONN_IFACE_CONTACTS) if with_ft: expected_caps = dbus.Dictionary({handle: generic_ft_caps}) else: expected_caps = dbus.Dictionary({handle: generic_caps}) caps = conn_caps_iface.GetContactCapabilities([handle]) assert caps == expected_caps, caps # check the Contacts interface give the same caps caps_via_contacts_iface = conn_contacts_iface.GetContactAttributes( [handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [handle][cs.ATTR_CONTACT_CAPABILITIES] assert caps_via_contacts_iface == caps[handle], \ caps_via_contacts_iface def test2(q, bus, connections, streams): conn1, conn2 = connections stream1, stream2 = streams conn1_handle = conn1.Properties.Get(cs.CONN, 'SelfHandle') conn1_jid = conn1.InspectHandles(cs.HT_CONTACT, [conn1_handle])[0] conn2_handle = conn2.Properties.Get(cs.CONN, 'SelfHandle') conn2_jid = conn2.InspectHandles(cs.HT_CONTACT, [conn2_handle])[0] handle1 = conn2.RequestHandles(cs.HT_CONTACT, [conn1_jid])[0] handle2 = conn1.RequestHandles(cs.HT_CONTACT, [conn2_jid])[0] q.expect_many(EventPattern('dbus-signal', signal='ContactCapabilitiesChanged', path=conn1.object.object_path), EventPattern('dbus-signal', signal='ContactCapabilitiesChanged', path=conn2.object.object_path)) check_contact_caps (conn1, handle2, False) check_contact_caps (conn2, handle1, False) caps_iface = dbus.Interface(conn1, cs.CONN_IFACE_CONTACT_CAPS) caps_iface.UpdateCapabilities([("self", [ft_fixed_properties], dbus.Array([], signature="s"))]) _, presence, disco, _ = \ q.expect_many(EventPattern('dbus-signal', signal='ContactCapabilitiesChanged', path=conn1.object.object_path, args=[{conn1_handle:generic_ft_caps}]), EventPattern('stream-presence', stream=stream1), EventPattern('stream-iq', stream=stream1, query_ns=ns.DISCO_INFO, iq_type = 'result'), EventPattern('dbus-signal', signal='ContactCapabilitiesChanged', path=conn2.object.object_path, args=[{handle1:generic_ft_caps}])) presence_c = xpath.queryForNodes('/presence/c', presence.stanza)[0] assert "share-v1" in presence_c.attributes['ext'] conn1_ver = presence_c.attributes['ver'] found_share = False for feature in xpath.queryForNodes('/iq/query/feature', disco.stanza): if feature.attributes['var'] == ns.GOOGLE_FEAT_SHARE: found_share = True assert found_share check_contact_caps (conn2, handle1, True) caps_iface = dbus.Interface(conn2, cs.CONN_IFACE_CONTACT_CAPS) caps_iface.UpdateCapabilities([("self", [ft_fixed_properties], dbus.Array([], signature="s"))]) _, presence, _ = \ q.expect_many(EventPattern('dbus-signal', signal='ContactCapabilitiesChanged', path=conn2.object.object_path, args=[{conn2_handle:generic_ft_caps}]), EventPattern('stream-presence', stream=stream2), EventPattern('dbus-signal', signal='ContactCapabilitiesChanged', path=conn1.object.object_path, args=[{handle2:generic_ft_caps}])) presence_c = xpath.queryForNodes('/presence/c', presence.stanza)[0] assert "share-v1" in presence_c.attributes['ext'] # We will have the same capabilities on both sides, so we can't check for # a cap disco since the hash will be the same, so we need to make sure the # hash is indeed the same assert presence_c.attributes['ver'] == conn1_ver found_share = False for feature in xpath.queryForNodes('/iq/query/feature', disco.stanza): if feature.attributes['var'] == ns.GOOGLE_FEAT_SHARE: found_share = True assert found_share check_contact_caps (conn1, handle2, True) if __name__ == '__main__': exec_test(test) exec_test(test2, num_instances=2) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle-share/test-send-file-send-before-accept.py�������������0000664�0001750�0001750�00000002417�12225363340�032220� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from file_transfer_helper import SendFileTest, FileTransferTest, \ ReceiveFileTest, exec_file_transfer_test from config import JINGLE_FILE_TRANSFER_ENABLED if not JINGLE_FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer or --disable-voip" raise SystemExit(77) print("FIXME: test is not stable enough.\n" + " https://bugs.freedesktop.org/show_bug.cgi?id=49595") raise SystemExit(77) class SendFileBeforeAccept(SendFileTest): def __init__(self, file, address_type, access_control, acces_control_param): FileTransferTest.__init__(self, file, address_type, access_control, acces_control_param) self._actions = [self.connect, self.set_ft_caps, self.check_ft_available, None, self.wait_for_ft_caps, None, self.request_ft_channel, self.provide_file, self.set_open, self.send_file, None, self.wait_for_completion, None, self.close_channel, self.done] def set_open(self): self.open = True self.offset_defined = True if __name__ == '__main__': exec_file_transfer_test(SendFileBeforeAccept, ReceiveFileTest) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������test-receive-file-and-sender-disconnect-while-pending.py��������������������������������������������0000664�0001750�0001750�00000003616�12225363340�036105� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000�telepathy-gabble-0.18.3/tests/twisted/jingle-share���������������������������������������������������������������������������������������������������������������������import dbus import constants as cs from file_transfer_helper import SendFileTest, ReceiveFileTest, \ FileTransferTest, exec_file_transfer_test from config import JINGLE_FILE_TRANSFER_ENABLED if not JINGLE_FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer or --disable-voip" raise SystemExit(77) class ReceiveFileAndSenderDisconnectWhilePendingTest(ReceiveFileTest): def accept_file(self): e = self.q.expect('dbus-signal', signal='FileTransferStateChanged', path = self.channel.object_path, args=[cs.FT_STATE_CANCELLED, \ cs.FT_STATE_CHANGE_REASON_REMOTE_STOPPED]) # We can't accept the transfer now try: self.ft_channel.AcceptFile(cs.SOCKET_ADDRESS_TYPE_UNIX, cs.SOCKET_ACCESS_CONTROL_LOCALHOST, "", 0) except dbus.DBusException, e: assert e.get_dbus_name() == cs.NOT_AVAILABLE else: assert False self.close_channel() # stop the test return True class SendFileAndDisconnect (SendFileTest): def __init__(self, file, address_type, access_control, acces_control_param): FileTransferTest.__init__(self, file, address_type, access_control, acces_control_param) self._actions = [self.connect, self.set_ft_caps, self.check_ft_available, None, self.wait_for_ft_caps, None, self.request_ft_channel, self.provide_file, self.disconnect, None, self.close_channel, self.done] def disconnect(self): self.conn.Disconnect() if __name__ == '__main__': exec_file_transfer_test(SendFileAndDisconnect, \ ReceiveFileAndSenderDisconnectWhilePendingTest) ������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle-share/test-multift.py����������������������������������0000664�0001750�0001750�00000013475�12332441362�026420� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import dbus from twisted.words.protocols.jabber.client import IQ from servicetest import assertEquals, assertSameSets, EventPattern from gabbletest import exec_test, sync_stream import constants as cs from jingleshareutils import test_ft_caps_from_contact from config import JINGLE_FILE_TRANSFER_ENABLED if not JINGLE_FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer or --disable-voip" raise SystemExit(77) def test(q, bus, conn, stream): client = 'http://telepathy.freedesktop.org/fake-client' contact = 'bilbo1@foo.com/Resource' files = [("file", "File.txt", 12345, False), ("file", "Image.txt", 54321, True), ("folder", "Folder", 123, False), ("folder", "Folder no size", None, True)] test_ft_caps_from_contact(q, bus, conn, stream, contact, 2L, client) self_handle = conn.GetSelfHandle() jid = conn.InspectHandles(cs.HT_CONTACT, [self_handle])[0] iq = IQ(stream, "set") iq['to'] = jid iq['from'] = contact session = iq.addElement("session", "http://www.google.com/session") session['type'] = "initiate" session['id'] = "2156517633" session['initiator'] = contact session.addElement("transport", "http://www.google.com/transport/p2p") description = session.addElement("description", "http://www.google.com/session/share") manifest = description.addElement("manifest") for f in files: type, name, size, image = f file = manifest.addElement(type) if size is not None: file['size'] = str(size) file.addElement("name", None, name) if image: image = file.addElement("image") image['width'] = '1200' image['height'] = '1024' protocol = description.addElement("protocol") http = protocol.addElement("http") url = http.addElement("url", None, "/temporary/ade15194140cf7b7bceafe/") url['name'] = 'source-path' url = http.addElement("url", None, "/temporary/578d715be25ddc28870d3f/") url['name'] = 'preview-path' stream.send(iq) event = q.expect('dbus-signal', signal="NewChannels") channels = event.args[0] # Make sure we get the right amout of channels assert len(channels) == len(files) # Make sure every file transfer has a channel associated with it found = [False for i in files] file_collection = None for channel in channels: path, props = channel # Get the FileCollection and make sure it exists if file_collection is None: file_collection = props[cs.FT_FILE_COLLECTION] assert file_collection != '' assert file_collection is not None # FileCollection must be the same for every channel assert props[cs.FT_FILE_COLLECTION] == file_collection, props for i, f in enumerate(files): type, name, size, image = f if type == "folder": name = "%s.tar" % name if size is None: size = 0 if props[cs.FT_FILENAME].encode('utf=8') == name: assert found[i] == False found[i] = True assert props[cs.FT_SIZE] == size, props assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_FILE_TRANSFER, props assertSameSets( [ cs.CHANNEL_IFACE_FILE_TRANSFER_METADATA, cs.CHANNEL_TYPE_FILE_TRANSFER + '.FUTURE', ], props[cs.INTERFACES]) assert props[cs.TARGET_HANDLE] == 2L, props assert props[cs.TARGET_ID] == contact.replace("/Resource", ""), props assert props[cs.TARGET_HANDLE_TYPE] == cs.HT_CONTACT, props assert props[cs.REQUESTED] == False, props assert props[cs.INITIATOR_HANDLE] == 2L, props assert props[cs.INITIATOR_ID] == contact.replace("/Resource", ""), props assert props[cs.FT_STATE] == cs.FT_STATE_PENDING, props assert props[cs.FT_CONTENT_TYPE] == '', props # FT's protocol doesn't allow us the send the hash info assert props[cs.FT_CONTENT_HASH_TYPE] == cs.FILE_HASH_TYPE_NONE, props assert props[cs.FT_CONTENT_HASH] == '', props assert props[cs.FT_DESCRIPTION] == '', props assert props[cs.FT_DATE] == 0, props assert props[cs.FT_AVAILABLE_SOCKET_TYPES] == \ {cs.SOCKET_ADDRESS_TYPE_UNIX: [cs.SOCKET_ACCESS_CONTROL_LOCALHOST], cs.SOCKET_ADDRESS_TYPE_IPV4: [cs.SOCKET_ACCESS_CONTROL_LOCALHOST], cs.SOCKET_ADDRESS_TYPE_IPV6: [cs.SOCKET_ACCESS_CONTROL_LOCALHOST]}, \ props[cs.FT_AVAILABLE_SOCKET_TYPES] assert props[cs.FT_TRANSFERRED_BYTES] == 0, props assert props[cs.FT_INITIAL_OFFSET] == 0, props assert False not in found event = q.expect('stream-iq', to=contact, iq_type='set', query_name='session') session_node = event.query assert session_node.attributes['type'] == 'transport-accept' # Close all but one of the channels, and make sure Gabble doesn't cancel # the multi-FT yet. terminate_pattern = EventPattern('stream-iq', to=contact, iq_type='set', query_name='session', predicate=lambda event: event.query['type'] == 'terminate') q.forbid_events([terminate_pattern]) for path, props in channels[:-1]: ft_chan = bus.get_object(conn.object.bus_name, path) channel = dbus.Interface(ft_chan, cs.CHANNEL) channel.Close() q.expect('dbus-signal', signal='Closed', path=path) sync_stream(q, stream) q.unforbid_all() # Now close the final channel, and make sure Gabble terminates the session. last_path, props = channels[-1] ft_chan = bus.get_object(conn.object.bus_name, last_path) channel = dbus.Interface(ft_chan, cs.CHANNEL) channel.Close() q.expect_many(terminate_pattern) if __name__ == '__main__': exec_test(test) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle-share/test-send-file-and-cancel-immediately.py���������0000664�0001750�0001750�00000005255�12225363340�033063� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import dbus import constants as cs from servicetest import EventPattern from file_transfer_helper import SendFileTest, ReceiveFileTest, \ FileTransferTest, exec_file_transfer_test from config import JINGLE_FILE_TRANSFER_ENABLED if not JINGLE_FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer or --disable-voip" raise SystemExit(77) class ReceiveFileStopped(ReceiveFileTest): def __init__(self, file, address_type, access_control, access_control_param): FileTransferTest.__init__(self, file, address_type, access_control, access_control_param) self._actions = [self.connect, self.set_ft_caps, None, self.wait_for_ft_caps, None, self.check_new_channel, None, self.check_stopped, None, self.close_channel, self.done] def check_stopped(self): state_event = self.q.expect ('dbus-signal', signal='FileTransferStateChanged', path=self.channel.object_path) state, reason = state_event.args assert state == cs.FT_STATE_CANCELLED assert reason == cs.FT_STATE_CHANGE_REASON_REMOTE_STOPPED # try to provide the file try: self.accept_file() except dbus.DBusException, e: assert e.get_dbus_name() == cs.NOT_AVAILABLE else: assert False class SendFileAndClose (SendFileTest): def __init__(self, file, address_type, access_control, acces_control_param): FileTransferTest.__init__(self, file, address_type, access_control, acces_control_param) self._actions = [self.connect, self.set_ft_caps, self.check_ft_available, None, self.wait_for_ft_caps, None, self.request_ft_channel, self.provide_file, None, self.close_and_check, None, self.close_channel, self.done] def close_and_check(self): self.channel.Close() state_event, _ = self.q.expect_many( EventPattern('dbus-signal', signal='FileTransferStateChanged', path=self.channel.object_path), EventPattern('dbus-signal', signal='Closed', path=self.channel.object_path)) state, reason = state_event.args assert state == cs.FT_STATE_CANCELLED assert reason == cs.FT_STATE_CHANGE_REASON_LOCAL_STOPPED if __name__ == '__main__': exec_file_transfer_test(SendFileAndClose, ReceiveFileStopped) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle-share/test-send-file-wait-to-provide.py����������������0000664�0001750�0001750�00000003134�12225363340�031621� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import dbus import constants as cs from servicetest import EventPattern from file_transfer_helper import SendFileTest, ReceiveFileTest, \ FileTransferTest, exec_file_transfer_test from config import JINGLE_FILE_TRANSFER_ENABLED if not JINGLE_FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer or --disable-voip" raise SystemExit(77) class SendFileAndWaitToProvide (SendFileTest): def __init__(self, file, address_type, access_control, acces_control_param): FileTransferTest.__init__(self, file, address_type, access_control, acces_control_param) self._actions = [self.connect, self.set_ft_caps, self.check_ft_available, None, self.wait_for_ft_caps, None, self.request_ft_channel, self.check_pending_state, None, self.check_accepted_state, self.provide_file, self.send_file, self.wait_for_completion, None, self.close_channel, self.done] def check_pending_state(self): # state is still Pending as remote didn't accept the transfer yet state = self.ft_props.Get(cs.CHANNEL_TYPE_FILE_TRANSFER, 'State') assert state == cs.FT_STATE_PENDING def check_accepted_state(self): # Remote accepted the transfer state = self.ft_props.Get(cs.CHANNEL_TYPE_FILE_TRANSFER, 'State') assert state == cs.FT_STATE_ACCEPTED, state if __name__ == '__main__': exec_file_transfer_test(SendFileAndWaitToProvide, ReceiveFileTest) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������test-receive-file-and-sender-disconnect-while-transfering.py����������������������������������������0000664�0001750�0001750�00000003213�12225363340�036774� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000�telepathy-gabble-0.18.3/tests/twisted/jingle-share���������������������������������������������������������������������������������������������������������������������import dbus import constants as cs from file_transfer_helper import SendFileTest, ReceiveFileTest, \ FileTransferTest, exec_file_transfer_test from config import JINGLE_FILE_TRANSFER_ENABLED if not JINGLE_FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer or --disable-voip" raise SystemExit(77) class ReceiveFileAndSenderDisconnectWhileTransfering(ReceiveFileTest): def receive_file(self): self.q.expect('dbus-signal', signal='FileTransferStateChanged', path = self.channel.object_path, args=[cs.FT_STATE_CANCELLED, \ cs.FT_STATE_CHANGE_REASON_REMOTE_STOPPED]) self.close_channel() # stop the test return True class SendFileAndDisconnect (SendFileTest): def __init__(self, file, address_type, access_control, acces_control_param): FileTransferTest.__init__(self, file, address_type, access_control, acces_control_param) self._actions = [self.connect, self.set_ft_caps, self.check_ft_available, None, self.wait_for_ft_caps, None, self.request_ft_channel, self.provide_file, None, self.send_file, self.wait_for_completion, self.disconnect, None, self.close_channel, self.done] def disconnect(self): self.conn.Disconnect() if __name__ == '__main__': exec_file_transfer_test(SendFileAndDisconnect, \ ReceiveFileAndSenderDisconnectWhileTransfering) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle-share/test-send-file.py��������������������������������0000664�0001750�0001750�00000000747�12225363340�026600� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- coding: utf-8 -*- from file_transfer_helper import SendFileTest, ReceiveFileTest, \ exec_file_transfer_test, File from config import JINGLE_FILE_TRANSFER_ENABLED if not JINGLE_FILE_TRANSFER_ENABLED: print "NOTE: built with --disable-file-transfer or --disable-voip" raise SystemExit(77) if __name__ == '__main__': file = File() file.offset = 5 file.name = "The greek foo δοκιμή.txt" exec_file_transfer_test(SendFileTest, ReceiveFileTest, file) �������������������������telepathy-gabble-0.18.3/tests/twisted/tls-key.pem���������������������������������������������������0000644�0001750�0001750�00000003213�11444674763�023133� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAwt9AF1py3GpF66t6xyH8vtLu8zQJnUWMPPDCAO8KWWeC8TBz KruGJ58srKETSPcG5Qj5CdvV8gZoXy3PRpp55eqYc39OJ/cfd2fLfSR558Kqic3b cX7h7AFmv/th3t7jcVjC/nVMvzgeYmsz3gsCrasJoee6CxSx5Bfg4Ya8HlJKEAw5 yf9cU9Gx5nbJUPapzCMYYw1KGfU5AJPvD6bKB2z3JX6+srZwoxnyzqAPb1noT6JE w70D0Jl3OdryBTafAN4dOY3qdwwWM5BvliXCUTYcsQtHcxasqxSVtlzLQrNKdXD2 h4F1TwnuInFy2OPHoVWhbwUdNit41UO1pHrc8QIDAQABAoIBAC0rgHipT4yF2bU5 51i3KRW2YQrgmgXpdAtAJ0f+IKD+nFx5xYg3NW6Dt+A/6e90yxVV0hwV5+6Uy6ac QLp13iGMElBbRut+nb2YwpM8XEF7XvpYTDBvn8CLxpxjkZkOgxvn3jMLT4HXaTuY 68nhNXq59Z6gzv/4iQ989XRxPbOtKWI1m96ZTFstkG8TJjaO9AnDxR2sEGHQ+rhP IRMbHLagY1qA0OxMhHCHMTwq/oVBR7xtgraLzeHnSg+Q4Z+hY+TSNmlmJxZINHTK c4kxVhAv2iGJaLDC7XviyKs/AMmoVfcSuG+BGDDOxhpOjx/G4ZzKmp2VVwNOEYk1 E2z7JH0CgYEAy+zMzpdgNIYIcKRAYqQITInsNnfGY+y2tOhUeNA558ZVoqt7Gf1Z TWegqyxtP71ZYkLqidNlJasgX2cU6aAkAHfO1EnpZiaX6WKSXGIfukLhH9Jwc6MW Xnnv0dZ9i83IL5sLIkAVb0TqqIIBvbxZjEYFSQVwpfG8BCvxNwQJ2U8CgYEA9KKh /DkoULrC8SIQ1TroOFcqLZPUFcCPHEfxHC+urWkYpRCrQ43jiZMCegPnKuUEQ9Nu 7UZqOrP0WYyEqQ3P+jC4I4xBozJigGttMTBnC2rm40PCPZcUz28Ja/Tos4oiEN6q qVG5/IlfcjuZZGsFIKbTCxM2uXwykmJDeAC91b8CgYAvbIWAsfF8pYMG9xvGFNGd QyH81MP9bwpabgFfC0W8IgK+TtTVCXcgKi5SQIWzogxMbrVukgvew7pGlYlmf4h/ 11zxP7MYv3bqnrLc6zDnty/1n5HpQo8sL31XNmOCBLw+Xfcr4u1ZMBTGVV2kS04j 8hC+l5ZH8TzBV5rEKZtEvwKBgQCtltmqyEQ7RMsfoDShmfM+R1u+i69q4ACs6L/G aG9izbiXKITeoshazt5rBmn6nhewqU+FPvoSPa+d+4AHFa4Gspt3XgcVbqNGzPPm e5ojF/BOQ76JRbOWngvpdxfIjrQtlFM1YrC+6hu4S2JFR0uUJ8yJh1DFvcOE7AVE GgKasQKBgET77FdaEiiajroe0CE8Ulmge4mpok7QQ81ag6gV6X3R7Ru20pg9iqGo U9OS2VgpqhoWz9PSoI/ZZghRYq0oQz9XDNLtZeGswFJgl4A/TrVs6gWcRxbVfAtg 9EmaJucDIxXNHqoD2yXj7XJPqDkNuD7rV7IOnrsg4La1N7SQpQk2 -----END RSA PRIVATE KEY----- �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tls-cert.pem��������������������������������������������������0000644�0001750�0001750�00000002714�11444674763�023305� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIIEHDCCAwagAwIBAgIBAjALBgkqhkiG9w0BAQUwbDELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTERMA8G A1UECBMIQ29uZnVzZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTAeFw0w OTA5MTgxMjU0MDdaFw0zNzA5MTExMjU0MDdaMGkxCzAJBgNVBAYTAlVLMRIwEAYD VQQKEwlDb2xsYWJvcmExGTAXBgNVBAsTEFdvY2t5IFRlc3QgU3VpdGUxDjAMBgNV BAgTBURhemVkMRswGQYDVQQDExJXb2NreSBYTVBQIExpYnJhcnkwggEfMAsGCSqG SIb3DQEBAQOCAQ4AMIIBCQKCAQDC30AXWnLcakXrq3rHIfy+0u7zNAmdRYw88MIA 7wpZZ4LxMHMqu4YnnyysoRNI9wblCPkJ29XyBmhfLc9Gmnnl6phzf04n9x93Z8t9 JHnnwqqJzdtxfuHsAWa/+2He3uNxWML+dUy/OB5iazPeCwKtqwmh57oLFLHkF+Dh hrweUkoQDDnJ/1xT0bHmdslQ9qnMIxhjDUoZ9TkAk+8PpsoHbPclfr6ytnCjGfLO oA9vWehPokTDvQPQmXc52vIFNp8A3h05jep3DBYzkG+WJcJRNhyxC0dzFqyrFJW2 XMtCs0p1cPaHgXVPCe4icXLY48ehVaFvBR02K3jVQ7WketzxAgMBAAGjgdIwgc8w DAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwIQYD VR0RBBowGIIQd2Vhc2VsLWp1aWNlLm9yZ4cEfwAAATAPBgNVHQ8BAf8EBQMDByAA MB0GA1UdDgQWBBRDAfw/7QRZO5a0qmJ75Oeo3hA01zAfBgNVHSMEGDAWgBRJMCYI jJrWac2LwMwOXAKOSh+mjDAsBgNVHR8EJTAjMCGgH6AdhhtmaWxlOi8vL3RtcC93 b2NreS10ZXN0cy9jcmwwCwYJKoZIhvcNAQEFA4IBAQAIcwQ8FN7lnnQPm4al6y5v zrGzVSxkUuN+I8457E9ZAoFpItMGqWWKjjbOgjS3d95yJWmEW2eBVC3/LMEAvv4z Q6HkTRhafkiLWmXNa8DtbUq1cZ2hNrR1lNTOL4zXwg9JQbtFw0EAM7LfSgqHhTzs xO0AbXaO0TlbYkn9/amPCNQcFjg6Dgdm3x0T3g/tLQjtzjro/hdgYZqPng0MYBpG AUj99FwahI5D8cAPoUjtpxZOlsexz4r8UVGNRvL0Wqg57w8KKF7GVr15b2ZAeQwo pNJkMSXAyPpKW24Q06zwYFnC+Cp32udf2wIB9FEC3zNQugUbtFitHzPjzhum13iR -----END CERTIFICATE----- ����������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/avatar-requirements.py����������������������������������������0000664�0001750�0001750�00000003024�12332441362�025373� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from servicetest import call_async, EventPattern from gabbletest import exec_test, acknowledge_iq, make_result_iq import constants as cs def test_get_all(conn): props = conn.GetAll(cs.CONN_IFACE_AVATARS, dbus_interface=cs.PROPERTIES_IFACE) types = props['SupportedAvatarMIMETypes'] minw = props['MinimumAvatarWidth'] minh = props['MinimumAvatarHeight'] maxw = props['MaximumAvatarWidth'] maxh = props['MaximumAvatarHeight'] maxb = props['MaximumAvatarBytes'] rech = props['RecommendedAvatarHeight'] recw = props['RecommendedAvatarWidth'] assert types[0] == 'image/png', types assert 'image/jpeg' in types, types assert 'image/gif' in types, types assert minw == 32, minw assert minh == 32, minh assert maxw == 96, maxw assert maxh == 96, maxh assert maxb == 8192, maxb assert recw == 64, recw assert rech == 64, rech def test(q, bus, conn, stream): test_get_all(conn) conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) test_get_all(conn) # deprecated version types, minw, minh, maxw, maxh, maxb = conn.Avatars.GetAvatarRequirements() assert types[0] == 'image/png', types assert 'image/jpeg' in types, types assert 'image/gif' in types, types assert minw == 32, minw assert minh == 32, minh assert maxw == 96, maxw assert maxh == 96, maxh assert maxb == 8192, maxb if __name__ == '__main__': exec_test(test, do_connect=False) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/last-activity.py����������������������������������������������0000664�0001750�0001750�00000002621�12332441362�024173� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Trivial smoke-test for XEP-0012 support. """ from servicetest import assertEquals, assertContains from gabbletest import exec_test, elem, elem_iq import ns def test(q, bus, conn, stream): e = q.expect('stream-iq', iq_type='get', query_ns=ns.ROSTER) e.stanza['type'] = 'result' e.query.addChild( elem('item', jid='romeo@montague.lit', subscription='both')) stream.send(e.stanza) # Romeo's on the roster. stream.send( elem_iq(stream, 'get', from_='romeo@montague.lit')( elem(ns.LAST, 'query') ) ) e = q.expect('stream-iq', iq_type='result', query_ns=ns.LAST, query_name='query') # No real assertions about the number of seconds; this is just a smoke # test. seconds = e.query['seconds'] assert seconds >= 0 # Juliet is not. stream.send( elem_iq(stream, 'get', from_='juliet@capulet.lit')( elem(ns.LAST, 'query') ) ) e = q.expect('stream-iq', iq_type='error', query_ns=ns.LAST, query_name='query') # Yuck. assertEquals('forbidden', e.stanza.children[1].children[0].name) # If the server asks, Gabble had better not crash. stream.send( elem_iq(stream, 'get')( elem(ns.LAST, 'query') ) ) e = q.expect('stream-iq', iq_type='result', query_ns=ns.LAST, query_name='query') if __name__ == '__main__': exec_test(test) ���������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/caps/���������������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�021760� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/caps/broken-reply.py������������������������������������������0000664�0001750�0001750�00000001142�12225363340�024732� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Tests that disco replies whose <query/> node is missing don't crash Gabble. """ from gabbletest import exec_test, sync_stream, make_result_iq import caps_helper def test(q, bus, conn, stream): jid = 'crashy@cra.shy/hi' caps = { 'node': 'oh:hi', 'ver': "dere", } h = caps_helper.send_presence(q, conn, stream, jid, caps, initial=False) request = caps_helper.expect_disco(q, jid, caps['node'], caps) result = make_result_iq(stream, request, add_query_node=False) stream.send(result) sync_stream(q, stream) if __name__ == '__main__': exec_test(test) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/caps/from-bare-jid.py�����������������������������������������0000664�0001750�0001750�00000007753�12332441362�024755� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Tests receiving capabilities from bare JIDs. """ from twisted.words.xish import xpath from servicetest import ( assertEquals, assertContains, assertDoesNotContain, EventPattern, ) from gabbletest import make_presence, exec_test from caps_helper import compute_caps_hash, send_disco_reply import constants as cs import ns from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test(q, bus, conn, stream): client = 'http://example.com/perverse-client' contact_bare_jid = 'edgecase@example.com' contact_with_resource = 'edgecase@example.com/hi' contact_handle = conn.RequestHandles(cs.HT_CONTACT, [contact_bare_jid])[0] # Gabble gets a presence stanza from a bare JID, which is a tad surprising. features = [ ns.JINGLE_015, ns.JINGLE_015_AUDIO, ns.JINGLE_015_VIDEO, ns.GOOGLE_P2P, ] caps = {'node': client, 'hash': 'sha-1', 'ver': compute_caps_hash([], features, {}), } p = make_presence(contact_bare_jid, status='Hello', caps=caps) stream.send(p) # Gabble looks up the hash event = q.expect('stream-iq', to=contact_bare_jid, query_ns='http://jabber.org/protocol/disco#info') query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assertEquals(client + '#' + caps['ver'], query_node.attributes['node']) # The bare jid replies send_disco_reply(stream, event.stanza, [], features) # Gabble lets us know their caps have changed. (Gabble used to ignore the # reply.) streamed_media_caps = (contact_handle, cs.CHANNEL_TYPE_STREAMED_MEDIA, 0, 3, 0, cs.MEDIA_CAP_AUDIO | cs.MEDIA_CAP_VIDEO) e = q.expect('dbus-signal', signal='CapabilitiesChanged') assertContains(streamed_media_caps, e.args[0]) # Gabble gets another presence stanza from the bare JID, with different # caps. features.append(ns.TUBES) caps = {'node': client, 'hash': 'sha-1', 'ver': compute_caps_hash([], features, {}), } p = make_presence(contact_bare_jid, status='Get out the abacus', caps=caps) stream.send(p) # Gabble looks up the new hash disco2 = q.expect('stream-iq', to=contact_bare_jid, query_ns='http://jabber.org/protocol/disco#info') query_node = xpath.queryForNodes('/iq/query', disco2.stanza)[0] assertEquals(client + '#' + caps['ver'], query_node.attributes['node']) # This time, before the bare JID replies, Gabble gets a presence from the # resourceful jid. features_ = features + [ns.CHAT_STATES] caps = {'node': client, 'hash': 'sha-1', 'ver': compute_caps_hash([], features_, {}), } p = make_presence(contact_with_resource, status='Count this', caps=caps) stream.send(p) # Gabble throws away presence from the bare JID when it gets presence from # a resource (and vice versa), so it should now say the contact is # incapable. Gabble also looks up the resourceful JID's hash. cc, disco3 = q.expect_many( EventPattern('dbus-signal', signal='CapabilitiesChanged'), EventPattern('stream-iq', to=contact_with_resource, query_ns='http://jabber.org/protocol/disco#info'), ) assertDoesNotContain(streamed_media_caps, cc.args[0]) query_node = xpath.queryForNodes('/iq/query', disco3.stanza)[0] assertEquals(client + '#' + caps['ver'], query_node.attributes['node']) # The bare jid replies! Getting a disco reply from a bare JID when we've # got presence from resources used to crash Gabble, but now it just ignores # it. send_disco_reply(stream, disco2.stanza, [], features) # Now the resourceful JID replies: send_disco_reply(stream, disco3.stanza, [], features_) # Gabble should announce that the contact has acquired some caps. e = q.expect('dbus-signal', signal='CapabilitiesChanged') assertContains(streamed_media_caps, e.args[0]) if __name__ == '__main__': exec_test(test) ���������������������telepathy-gabble-0.18.3/tests/twisted/caps/advertise-contact-caps.py��������������������������������0000664�0001750�0001750�00000023406�12332441362�026673� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test UpdateCapabilities. """ from functools import partial import dbus from twisted.words.xish import xpath, domish from servicetest import EventPattern from gabbletest import exec_test, sync_stream from caps_helper import caps_contain, receive_presence_and_ask_caps, \ FIXED_CAPS, JINGLE_CAPS, VARIABLE_CAPS, check_caps, disco_caps import constants as cs import ns from config import FILE_TRANSFER_ENABLED, VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def noop_presence_update(q, stream): # At the moment Gabble does not optimize away presence updates that # have no effect. When it does, we can forbid those events here. #events = [EventPattern('stream-presence')] #q.forbid_events(events) sync_stream(q, stream) #q.unforbid_events(events) JINGLE_CAPS_EXCEPT_GVIDEO = [n for n in JINGLE_CAPS if n != ns.GOOGLE_FEAT_VIDEO] def run_test(q, bus, conn, stream, media_channel_type, media_interface, initial_audio, initial_video): conn.ContactCapabilities.UpdateCapabilities([ (cs.CLIENT + '.AbiWord', [ { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.STREAM_TUBE_SERVICE: 'x-abiword' }, { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.STREAM_TUBE_SERVICE: 'x-abiword' }, ], []), ]) conn.Connect() _, initial_presence = q.expect_many( EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]), EventPattern('stream-presence'), ) (disco_response, namespaces, _) = disco_caps(q, stream, initial_presence) check_caps(namespaces, [ns.TUBES + '/stream#x-abiword']) conn.ContactCapabilities.UpdateCapabilities([ (cs.CLIENT + '.AbiWord', [ { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.STREAM_TUBE_SERVICE: 'x-abiword' }, { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.STREAM_TUBE_SERVICE: 'x-abiword' }, ], []), (cs.CLIENT + '.KCall', [ { cs.CHANNEL_TYPE: media_channel_type }, { cs.CHANNEL_TYPE: media_channel_type, initial_audio: True}, { cs.CHANNEL_TYPE: media_channel_type, initial_video: True}, ], [ media_interface + '/gtalk-p2p', media_interface + '/ice-udp', media_interface + '/video/h264', ]), ]) (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream, False) check_caps(namespaces, JINGLE_CAPS + [ns.TUBES + '/stream#x-abiword']) # Removing our H264 codec removes our ability to do Google Video conn.ContactCapabilities.UpdateCapabilities([ (cs.CLIENT + '.KCall', [ { cs.CHANNEL_TYPE: media_channel_type }, { cs.CHANNEL_TYPE: media_channel_type, initial_audio: True}, { cs.CHANNEL_TYPE: media_channel_type, initial_video: True}, ], [ media_interface + '/gtalk-p2p', media_interface + '/ice-udp', ]), ]) (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream, False) check_caps(namespaces, JINGLE_CAPS_EXCEPT_GVIDEO + [ns.TUBES + '/stream#x-abiword']) # Remove AbiWord's caps conn.ContactCapabilities.UpdateCapabilities([ (cs.CLIENT + '.AbiWord', [], []), ]) (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream, False) check_caps(namespaces, JINGLE_CAPS_EXCEPT_GVIDEO) # Remove KCall's caps too conn.ContactCapabilities.UpdateCapabilities([ (cs.CLIENT + '.KCall', [], []), ]) (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream, False) check_caps(namespaces, []) # If AbiWord claims that it can do MediaSignalling things on its Tubes # channels, then it's wrong, and that still doesn't make us callable. conn.ContactCapabilities.UpdateCapabilities([ (cs.CLIENT + '.AbiWord', [ { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.STREAM_TUBE_SERVICE: 'x-abiword' }, { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.STREAM_TUBE_SERVICE: 'x-abiword' }, ], [ media_interface + '/gtalk-p2p', media_interface + '/ice-udp', media_interface + '/video/h264', ]), ]) (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream, False) check_caps(namespaces, [ns.TUBES + '/stream#x-abiword']) # Remove the broken version of AbiWord's caps conn.ContactCapabilities.UpdateCapabilities([ (cs.CLIENT + '.AbiWord', [], []), ]) (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream, False) check_caps(namespaces, []) # Add caps selectively. Here we're callable, but not via ICE-UDP, and not # with video. # # (Jingle and raw UDP need no special client support, so are automatically # enabled whenever we can do audio or video.) conn.ContactCapabilities.UpdateCapabilities([ (cs.CLIENT + '.KCall', [ { cs.CHANNEL_TYPE: media_channel_type }, { cs.CHANNEL_TYPE: media_channel_type, initial_audio: True}, ], [media_interface + '/gtalk-p2p']), ]) (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream, False) check_caps(namespaces, [ns.GOOGLE_P2P, ns.JINGLE_TRANSPORT_RAWUDP, ns.JINGLE, ns.JINGLE_015, ns.GOOGLE_FEAT_VOICE, ns.JINGLE_RTP_AUDIO, ns.JINGLE_RTP, ns.JINGLE_015_AUDIO]) # With AUDIO but no transport, we are only callable via raw UDP, which # Google clients cannot do. conn.ContactCapabilities.UpdateCapabilities([ (cs.CLIENT + '.KCall', [ { cs.CHANNEL_TYPE: media_channel_type }, { cs.CHANNEL_TYPE: media_channel_type, initial_audio: True}, ], []) ]) (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream, False) check_caps(namespaces, [ns.JINGLE_TRANSPORT_RAWUDP, ns.JINGLE, ns.JINGLE_015, ns.JINGLE_RTP_AUDIO, ns.JINGLE_RTP, ns.JINGLE_015_AUDIO]) # With VIDEO and ICE-UDP only, we are very futuristic indeed. # Google clients cannot interop with us. conn.ContactCapabilities.UpdateCapabilities([ (cs.CLIENT + '.KCall', [ { cs.CHANNEL_TYPE: media_channel_type }, { cs.CHANNEL_TYPE: media_channel_type, initial_video: True}, ], [ media_interface + '/ice-udp', media_interface + '/video/theora', ]), ]) (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream, False) check_caps(namespaces, [ns.JINGLE_TRANSPORT_ICEUDP, ns.JINGLE_TRANSPORT_RAWUDP, ns.JINGLE, ns.JINGLE_015, ns.JINGLE_RTP_VIDEO, ns.JINGLE_RTP, ns.JINGLE_015_VIDEO]) # Remove KCall to simplify subsequent checks conn.ContactCapabilities.UpdateCapabilities([ (cs.CLIENT + '.KCall', [], []), ]) (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream, False) check_caps(namespaces, []) # Support file transfer if FILE_TRANSFER_ENABLED: conn.ContactCapabilities.UpdateCapabilities([ (cs.CLIENT + '.FileReceiver', [{ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_FILE_TRANSFER, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, }], []), ]) (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream, False) check_caps(namespaces, [ns.FILE_TRANSFER]) def run_mixed_test (q, bus, conn, stream): conn.Connect() conn.ContactCapabilities.UpdateCapabilities([ (cs.CLIENT + '.SquareWheel', [ { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.INITIAL_AUDIO: True}, { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.INITIAL_VIDEO: True}, ], [ cs.CHANNEL_IFACE_MEDIA_SIGNALLING + '/gtalk-p2p', cs.CHANNEL_IFACE_MEDIA_SIGNALLING + '/ice-udp', cs.CHANNEL_IFACE_MEDIA_SIGNALLING + '/video/h264', ]), (cs.CLIENT + '.FlyingCar', [ { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL, cs.CALL_INITIAL_AUDIO: True}, { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL, cs.CALL_INITIAL_VIDEO: True}, ], [ cs.CHANNEL_TYPE_CALL + '/gtalk-p2p', cs.CHANNEL_TYPE_CALL + '/ice', cs.CHANNEL_TYPE_CALL + '/video/h264', ]), ]) (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream, False) check_caps(namespaces, JINGLE_CAPS) if __name__ == '__main__': exec_test( partial(run_test, media_channel_type=cs.CHANNEL_TYPE_STREAMED_MEDIA, media_interface=cs.CHANNEL_IFACE_MEDIA_SIGNALLING, initial_audio=cs.INITIAL_AUDIO, initial_video=cs.INITIAL_VIDEO), do_connect=False) exec_test( partial(run_test, media_channel_type=cs.CHANNEL_TYPE_CALL, media_interface=cs.CHANNEL_TYPE_CALL, initial_audio=cs.CALL_INITIAL_AUDIO, initial_video=cs.CALL_INITIAL_VIDEO), do_connect=False) exec_test(run_mixed_test, do_connect=False) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/caps/trust-thyself.py�����������������������������������������0000664�0001750�0001750�00000005332�12332441362�025163� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test that we cache our own capabilities, so that we don't disco other people with the same caps hash or ext='' bundles. """ from twisted.words.xish import xpath from twisted.words.protocols.jabber.client import IQ from gabbletest import exec_test, make_presence, sync_stream from servicetest import EventPattern, assertEquals, assertNotEquals import ns import constants as cs from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test(q, bus, conn, stream): self_presence = q.expect('stream-presence') c = xpath.queryForNodes('/presence/c', self_presence.stanza)[0] jid = 'lol@great.big/omg' # Gabble shouldn't send any disco requests to our contact during this test. q.forbid_events([ EventPattern('stream-iq', to=jid, iq_type='get', query_ns=ns.DISCO_INFO), ]) # Check that Gabble doesn't disco other clients with the same caps hash. p = make_presence(jid, caps={'node': c['node'], 'hash': c['hash'], 'ver': c['ver'], }) stream.send(p) sync_stream(q, stream) # Check that Gabble doesn't disco its own ext='' bundles (well, its own # bundles as advertised by Gabbles that don't do hashed caps) p = make_presence(jid, caps={'node': c['node'], 'ver': c['ver'], # omitting hash='' so Gabble doesn't ignore ext='' 'ext': 'voice-v1 video-v1', }) stream.send(p) sync_stream(q, stream) # Advertise some different capabilities, to change our own caps hash. add = [(cs.CHANNEL_TYPE_STREAMED_MEDIA, 2L**32-1), (cs.CHANNEL_TYPE_STREAM_TUBE, 2L**32-1), (cs.CHANNEL_TYPE_STREAM_TUBE, 2L**32-1)] remove = [] caps = conn.Capabilities.AdvertiseCapabilities(add, remove) self_presence = q.expect('stream-presence') c_ = xpath.queryForNodes('/presence/c', self_presence.stanza)[0] assertNotEquals(c['ver'], c_['ver']) for suffix in [c['ver'], 'voice-v1', 'video-v1', 'camera-v1', 'share-v1', 'pmuc-v1'] + list(c_['ext'].split()): # But then someone asks us for our old caps iq = IQ(stream, 'get') iq['from'] = jid query = iq.addElement((ns.DISCO_INFO, 'query')) query['node'] = c['node'] + '#' + suffix stream.send(iq) # Gabble should still know what they are, and reply. This is # actually quite important: there's a bug in iChat where if you # return an error to a disco query, it just asks again, and again, # and again... reply = q.expect('stream-iq', to=jid) assertEquals('result', reply.iq_type) if __name__ == '__main__': exec_test(test) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/caps/offline.py�����������������������������������������������0000664�0001750�0001750�00000002547�12332441362�023755� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test for fd.o#32874 -- Offline contacts do not have capabilities. """ from gabbletest import exec_test from servicetest import assertEquals, assertSameSets, assertLength import constants as cs import ns def test(q, bus, conn, stream): conn.Connect() # bob is offline jid = 'bob@foo.com' event = q.expect('stream-iq', query_ns=ns.ROSTER) event.stanza['type'] = 'result' item = event.query.addElement('item') item['jid'] = jid item['subscription'] = 'from' stream.send(event.stanza) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]), bob_handle = conn.RequestHandles(cs.HT_CONTACT, [jid])[0] # new ContactCapabilities ccaps_map = conn.ContactCapabilities.GetContactCapabilities([bob_handle]) assertLength(1, ccaps_map) assertLength(1, ccaps_map[bob_handle]) fixed, allowed = ccaps_map[bob_handle][0] assertEquals({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT}, fixed) assertSameSets([cs.TARGET_HANDLE], allowed) # old Capabilities all_caps = conn.Capabilities.GetCapabilities([bob_handle]) assertLength(1, all_caps) caps = all_caps[0] assertEquals((bob_handle, cs.CHANNEL_TYPE_TEXT, 3, 0), caps) if __name__ == '__main__': exec_test(test, do_connect=False) ���������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/caps/receive-jingle.py����������������������������������������0000664�0001750�0001750�00000013415�12332441362�025217� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test receiving another contact's capabilities. """ import dbus from servicetest import EventPattern, assertEquals, sync_dbus from gabbletest import exec_test, make_result_iq, make_presence, sync_stream import constants as cs from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) icaps_attr = cs.CONN_IFACE_CAPS + "/caps" basic_caps = [(2, cs.CHANNEL_TYPE_TEXT, 3, 0)] def test(q, bus, conn, stream): presence = make_presence('bob@foo.com/Foo', status='hello') stream.send(presence) q.expect('dbus-signal', signal='PresencesChanged', args=[{2L: (2, u'available', 'hello')}]) # FIXME: throughout this test, Bob's handle is assumed to be 2. # no special capabilities assert conn.Capabilities.GetCapabilities([2]) == basic_caps # holding the handle here: see below assert conn.Contacts.GetContactAttributes( [2], [cs.CONN_IFACE_CAPS], True) == \ { 2L: { icaps_attr: basic_caps, cs.CONN + '/contact-id': 'bob@foo.com'}} # send updated presence with Jingle audio/video caps info. we turn on both # audio and video at the same time to test that all of the capabilities are # discovered before any capabilities change signal is emitted presence = make_presence('bob@foo.com/Foo', status='hello', caps={ 'node': 'http://telepathy.freedesktop.org/fake-client', 'ver' : '0.1', 'ext' : 'video', }) stream.send(presence) # Gabble looks up both the version and the video bundles, in any order (version_event, video_event) = q.expect_many( EventPattern('stream-iq', to='bob@foo.com/Foo', query_ns='http://jabber.org/protocol/disco#info', query_node='http://telepathy.freedesktop.org/fake-client#0.1'), EventPattern('stream-iq', to='bob@foo.com/Foo', query_ns='http://jabber.org/protocol/disco#info', query_node='http://telepathy.freedesktop.org/fake-client#video')) # reply to the video bundle query first - this capability alone is not # sufficient to make us callable result = make_result_iq(stream, video_event.stanza) query = result.firstChildElement() feature = query.addElement('feature') feature['var'] = 'http://jabber.org/protocol/jingle/description/video' stream.send(result) # reply to the version bundle query, which should make us audio and # video callable result = make_result_iq(stream, version_event.stanza) query = result.firstChildElement() feature = query.addElement('feature') feature['var'] = 'http://jabber.org/protocol/jingle' feature = query.addElement('feature') feature['var'] = 'http://jabber.org/protocol/jingle/description/audio' feature = query.addElement('feature') feature['var'] = 'http://www.google.com/transport/p2p' stream.send(result) # we can now do audio and video calls event = q.expect('dbus-signal', signal='CapabilitiesChanged', args=[[(2, cs.CHANNEL_TYPE_STREAMED_MEDIA, 0, 3, 0, cs.MEDIA_CAP_AUDIO | cs.MEDIA_CAP_VIDEO)]]) caps = conn.Contacts.GetContactAttributes([2], [cs.CONN_IFACE_CAPS], False) assert caps.keys() == [2L] assert icaps_attr in caps[2L] assert len(caps[2L][icaps_attr]) == 2 assert basic_caps[0] in caps[2L][icaps_attr] assert (2, cs.CHANNEL_TYPE_STREAMED_MEDIA, 3, 3) in caps[2L][icaps_attr] # send updated presence without video support presence = make_presence('bob@foo.com/Foo', status='hello', caps={ 'node': 'http://telepathy.freedesktop.org/fake-client', 'ver' : '0.1', }) stream.send(presence) # we can now do only audio calls (and as a result have the ImmutableStreams # cap) event = q.expect('dbus-signal', signal='CapabilitiesChanged', args=[[(2, cs.CHANNEL_TYPE_STREAMED_MEDIA, 3, 3, cs.MEDIA_CAP_AUDIO | cs.MEDIA_CAP_VIDEO, cs.MEDIA_CAP_AUDIO | cs.MEDIA_CAP_IMMUTABLE_STREAMS)]]) caps = conn.Contacts.GetContactAttributes([2], [cs.CONN_IFACE_CAPS], False) assert caps.keys() == [2L] assert icaps_attr in caps[2L] assert len(caps[2L][icaps_attr]) == 2 assert basic_caps[0] in caps[2L][icaps_attr] assert (2, cs.CHANNEL_TYPE_STREAMED_MEDIA, 3, cs.MEDIA_CAP_AUDIO | cs.MEDIA_CAP_IMMUTABLE_STREAMS) \ in caps[2L][icaps_attr] # go offline presence = make_presence('bob@foo.com/Foo', type='unavailable') stream.send(presence) # can't do audio calls any more q.expect_many( EventPattern('dbus-signal', signal='CapabilitiesChanged', args=[[(2, cs.CHANNEL_TYPE_STREAMED_MEDIA, 3, 0, cs.MEDIA_CAP_AUDIO | cs.MEDIA_CAP_IMMUTABLE_STREAMS, 0)]], ), EventPattern('dbus-signal', signal='PresencesChanged', args=[{2: (cs.PRESENCE_OFFLINE, 'offline', '')}]), ) # Contact went offline. Previously, this test asserted that the handle # became invalid, but that's not guaranteed to happen immediately; so we # now hold the handle (above), to guarantee that it does *not* become # invalid. assert conn.Contacts.GetContactAttributes( [2], [cs.CONN_IFACE_CAPS], False) == \ { 2L: { icaps_attr: basic_caps, cs.CONN + '/contact-id': 'bob@foo.com'}} # What about a handle that's not valid? assertEquals({}, conn.Contacts.GetContactAttributes( [31337], [cs.CONN_IFACE_CAPS], False)) # regression test for fd.o #15198: getting caps of invalid handle crashed try: conn.Capabilities.GetCapabilities([31337]) except dbus.DBusException, e: pass else: assert False, "Should have had an error!" if __name__ == '__main__': exec_test(test) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/caps/tube-caps.py���������������������������������������������0000664�0001750�0001750�00000037415�12332441362�024220� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test tubes capabilities with Connection.Interface.ContactCapabilities 1. Receive presence and caps from contacts and check that GetContactCapabilities works correctly and that ContactCapabilitiesChanged is correctly received. Also check that GetContactAttributes gives the same results. - no tube cap at all - 1 stream tube cap - 1 D-Bus tube cap - 1 stream tube + 1 D-Bus tube caps - 2 stream tube + 2 D-Bus tube caps - 1 stream tube + 1 D-Bus tube caps, again, to test whether the caps cache works with tubes 2. Test UpdateCapabilities and test that a presence stanza is sent to the contacts, test that the D-Bus signal ContactCapabilitiesChanged is fired for the self handle, ask Gabble for its caps with an iq request, check the reply is correct, and ask Gabble for its caps using D-Bus method GetContactCapabilities. Also check that GetContactAttributes gives the same results. Ensure that just a Requested=True channel class in a client filter doesn't make a tube service advertised as a cap. - no tube cap at all - 1 Requested=True stream tube cap - 1 stream tube cap - 1 D-Bus tube cap + 1 Requested=True cap - 1 stream tube + 1 D-Bus tube caps + 1 Requested=True cap - 2 stream tube + 2 D-Bus tube caps - 1 stream tube + 1 D-Bus tube caps, again, just for the fun """ import dbus from twisted.words.xish import xpath from servicetest import assertEquals, assertLength, assertContains,\ assertDoesNotContain from gabbletest import exec_test, make_result_iq, sync_stream, make_presence import constants as cs from caps_helper import compute_caps_hash, text_fixed_properties,\ text_allowed_properties, stream_tube_fixed_properties, stream_tube_allowed_properties,\ dbus_tube_fixed_properties, dbus_tube_allowed_properties, receive_presence_and_ask_caps,\ caps_contain, ft_fixed_properties, ft_allowed_properties import ns specialized_tube_allowed_properties = dbus.Array([cs.TARGET_HANDLE, cs.TARGET_ID]) bidir_daap_fixed_properties = dbus.Dictionary({ cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.STREAM_TUBE_SERVICE: 'daap' }) outgoing_daap_fixed_properties = dbus.Dictionary({ cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.REQUESTED : True, cs.STREAM_TUBE_SERVICE: 'daap' }) incoming_daap_fixed_properties = dbus.Dictionary({ cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.REQUESTED : False, cs.STREAM_TUBE_SERVICE: 'daap' }) http_fixed_properties = dbus.Dictionary({ cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.STREAM_TUBE_SERVICE: 'http' }) xiangqi_fixed_properties = dbus.Dictionary({ cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE, cs.DBUS_TUBE_SERVICE_NAME: 'com.example.Xiangqi' }) go_fixed_properties = dbus.Dictionary({ cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE, cs.DBUS_TUBE_SERVICE_NAME: 'com.example.Go' }) client = 'http://telepathy.freedesktop.org/fake-client' def assertSameElements(a, b): assertEquals(sorted(a), sorted(b)) def receive_caps(q, conn, stream, contact, contact_handle, features, expected_caps, expect_disco=True, expect_ccc=True): presence = make_presence(contact, status='hello') c = presence.addElement((ns.CAPS, 'c')) c['node'] = client c['ver'] = compute_caps_hash([], features if features is not None else [], {}) c['hash'] = 'sha-1' stream.send(presence) if expect_disco: # Gabble looks up our capabilities event = q.expect('stream-iq', to=contact, query_ns=ns.DISCO_INFO) query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assert query_node.attributes['node'] == \ client + '#' + c['ver'] # send good reply result = make_result_iq(stream, event.stanza) query = result.firstChildElement() query['node'] = client + '#' + c['ver'] for f in features: feature = query.addElement('feature') feature['var'] = f stream.send(result) if expect_ccc: event = q.expect('dbus-signal', signal='ContactCapabilitiesChanged') announced_ccs, = event.args assertSameElements(expected_caps, announced_ccs) else: # Make sure Gabble's got the caps sync_stream(q, stream) caps = conn.ContactCapabilities.GetContactCapabilities([contact_handle]) assertSameElements(expected_caps, caps) # test again, to check GetContactCapabilities does not have side effect caps = conn.ContactCapabilities.GetContactCapabilities([contact_handle]) assertSameElements(expected_caps, caps) # check the Contacts interface give the same caps caps_via_contacts_iface = conn.Contacts.GetContactAttributes( [contact_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [contact_handle][cs.ATTR_CONTACT_CAPABILITIES] assertSameElements(caps[contact_handle], caps_via_contacts_iface) def test_tube_caps_from_contact(q, bus, conn, stream, contact): contact_handle = conn.RequestHandles(cs.HT_CONTACT, [contact])[0] # Check that we don't crash if we haven't seen any caps/presence for this # contact yet. caps = conn.ContactCapabilities.GetContactCapabilities([contact_handle]) basic_caps = dbus.Dictionary({contact_handle: [(text_fixed_properties, text_allowed_properties)]}) # Since we don't know their caps, they should be omitted from the dict, # rather than present with no caps, but all contacts have text chat caps. assertEquals(basic_caps, caps) # send presence with no tube cap # We don't expect ContactCapabilitiesChanged to be emitted here: we always # assume people can do text channels. receive_caps(q, conn, stream, contact, contact_handle, [], basic_caps, expect_ccc=False) # send presence with generic tubes caps generic_tubes_caps = dbus.Dictionary({contact_handle: [(text_fixed_properties, text_allowed_properties), (stream_tube_fixed_properties, stream_tube_allowed_properties), (dbus_tube_fixed_properties, dbus_tube_allowed_properties)]}) receive_caps(q, conn, stream, contact, contact_handle, [ns.TUBES], generic_tubes_caps) # send presence with 1 stream tube cap daap_caps = dbus.Dictionary({contact_handle: [(text_fixed_properties, text_allowed_properties), (stream_tube_fixed_properties, stream_tube_allowed_properties), (dbus_tube_fixed_properties, dbus_tube_allowed_properties), (incoming_daap_fixed_properties, specialized_tube_allowed_properties)]}) receive_caps(q, conn, stream, contact, contact_handle, [ns.TUBES + '/stream#daap'], daap_caps) # send presence with 1 D-Bus tube cap xiangqi_caps = dbus.Dictionary({contact_handle: [(text_fixed_properties, text_allowed_properties), (stream_tube_fixed_properties, stream_tube_allowed_properties), (dbus_tube_fixed_properties, dbus_tube_allowed_properties), (xiangqi_fixed_properties, specialized_tube_allowed_properties)]}) receive_caps(q, conn, stream, contact, contact_handle, [ns.TUBES + '/dbus#com.example.Xiangqi'], xiangqi_caps) # send presence with both D-Bus and stream tube caps daap_xiangqi_caps = dbus.Dictionary({contact_handle: [(text_fixed_properties, text_allowed_properties), (stream_tube_fixed_properties, stream_tube_allowed_properties), (dbus_tube_fixed_properties, dbus_tube_allowed_properties), (incoming_daap_fixed_properties, specialized_tube_allowed_properties), (xiangqi_fixed_properties, specialized_tube_allowed_properties)]}) receive_caps(q, conn, stream, contact, contact_handle, [ns.TUBES + '/dbus#com.example.Xiangqi', ns.TUBES + '/stream#daap', ], daap_xiangqi_caps) # send presence with 4 tube caps all_tubes_caps = dbus.Dictionary({contact_handle: [(text_fixed_properties, text_allowed_properties), (stream_tube_fixed_properties, stream_tube_allowed_properties), (dbus_tube_fixed_properties, dbus_tube_allowed_properties), (incoming_daap_fixed_properties, specialized_tube_allowed_properties), (http_fixed_properties, specialized_tube_allowed_properties), (xiangqi_fixed_properties, specialized_tube_allowed_properties), (go_fixed_properties, specialized_tube_allowed_properties)]}) receive_caps(q, conn, stream, contact, contact_handle, [ns.TUBES + '/dbus#com.example.Xiangqi', ns.TUBES + '/dbus#com.example.Go', ns.TUBES + '/stream#daap', ns.TUBES + '/stream#http', ], all_tubes_caps) # send presence with both D-Bus and stream tube caps # Gabble does not look up our capabilities because of the cache receive_caps(q, conn, stream, contact, contact_handle, [ns.TUBES + '/dbus#com.example.Xiangqi', ns.TUBES + '/stream#daap', ], daap_xiangqi_caps, expect_disco=False) def advertise_caps(q, conn, stream, filters, expected_features, unexpected_features, expected_caps): self_handle = conn.GetSelfHandle() ret_caps = conn.ContactCapabilities.UpdateCapabilities( [(cs.CLIENT + '.Foo', filters, [])]) # Expect Gabble to reply with the correct caps event, namespaces, _, signaled_caps = receive_presence_and_ask_caps(q, stream) assertSameElements(expected_caps, signaled_caps) assertContains(ns.TUBES, namespaces) for var in expected_features: assertContains(var, namespaces) for var in unexpected_features: assertDoesNotContain(var, namespaces) # Check our own caps caps = conn.ContactCapabilities.GetContactCapabilities([self_handle]) assertSameElements(expected_caps, caps) # check the Contacts interface give the same caps caps_via_contacts_iface = conn.Contacts.GetContactAttributes( [self_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [self_handle][cs.ATTR_CONTACT_CAPABILITIES] assertSameElements(caps[self_handle], caps_via_contacts_iface) def test_tube_caps_to_contact(q, bus, conn, stream): self_handle = conn.GetSelfHandle() basic_caps = dbus.Dictionary({self_handle: [(text_fixed_properties, text_allowed_properties), (stream_tube_fixed_properties, stream_tube_allowed_properties), (dbus_tube_fixed_properties, dbus_tube_allowed_properties), ]}) daap_caps = dbus.Dictionary({self_handle: [(text_fixed_properties, text_allowed_properties), (stream_tube_fixed_properties, stream_tube_allowed_properties), (dbus_tube_fixed_properties, dbus_tube_allowed_properties), (incoming_daap_fixed_properties, specialized_tube_allowed_properties), (ft_fixed_properties, ft_allowed_properties)]}) xiangqi_caps = dbus.Dictionary({self_handle: [(text_fixed_properties, text_allowed_properties), (stream_tube_fixed_properties, stream_tube_allowed_properties), (dbus_tube_fixed_properties, dbus_tube_allowed_properties), (xiangqi_fixed_properties, specialized_tube_allowed_properties), (ft_fixed_properties, ft_allowed_properties)]}) daap_xiangqi_caps = dbus.Dictionary({self_handle: [(text_fixed_properties, text_allowed_properties), (stream_tube_fixed_properties, stream_tube_allowed_properties), (dbus_tube_fixed_properties, dbus_tube_allowed_properties), (incoming_daap_fixed_properties, specialized_tube_allowed_properties), (xiangqi_fixed_properties, specialized_tube_allowed_properties), (ft_fixed_properties, ft_allowed_properties)]}) all_tubes_caps = dbus.Dictionary({self_handle: [(text_fixed_properties, text_allowed_properties), (stream_tube_fixed_properties, stream_tube_allowed_properties), (dbus_tube_fixed_properties, dbus_tube_allowed_properties), (incoming_daap_fixed_properties, specialized_tube_allowed_properties), (http_fixed_properties, specialized_tube_allowed_properties), (xiangqi_fixed_properties, specialized_tube_allowed_properties), (go_fixed_properties, specialized_tube_allowed_properties), (ft_fixed_properties, ft_allowed_properties)]}) # Check our own caps caps = conn.ContactCapabilities.GetContactCapabilities([self_handle]) assertEquals(basic_caps, caps) # check the Contacts interface give the same caps caps_via_contacts_iface = conn.Contacts.GetContactAttributes( [self_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [self_handle][cs.ATTR_CONTACT_CAPABILITIES] assertEquals(caps[self_handle], caps_via_contacts_iface) # Advertise nothing conn.ContactCapabilities.UpdateCapabilities( [(cs.CLIENT + '.Foo', {}, [])]) # Check our own caps caps = conn.ContactCapabilities.GetContactCapabilities([self_handle]) assertLength(1, caps) assertEquals(basic_caps, caps) # check the Contacts interface give the same caps caps_via_contacts_iface = conn.Contacts.GetContactAttributes( [self_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [self_handle][cs.ATTR_CONTACT_CAPABILITIES] assertEquals(caps[self_handle], caps_via_contacts_iface) sync_stream(q, stream) # Advertise a Requested=True tube cap conn.ContactCapabilities.UpdateCapabilities( [(cs.CLIENT + '.Foo', [outgoing_daap_fixed_properties], [])]) # Check our own caps caps = conn.ContactCapabilities.GetContactCapabilities([self_handle]) assertLength(1, caps) assertEquals(basic_caps, caps) # check the Contacts interface give the same caps caps_via_contacts_iface = conn.Contacts.GetContactAttributes( [self_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [self_handle][cs.ATTR_CONTACT_CAPABILITIES] assertEquals(caps[self_handle], caps_via_contacts_iface) sync_stream(q, stream) advertise_caps(q, conn, stream, [bidir_daap_fixed_properties], [ns.TUBES + '/stream#daap'], [ns.TUBES + '/stream#http', ns.TUBES + '/dbus#com.example.Go', ns.TUBES + '/dbus#com.example.Xiangqi', ], daap_caps) advertise_caps(q, conn, stream, [outgoing_daap_fixed_properties, xiangqi_fixed_properties], [ns.TUBES + '/dbus#com.example.Xiangqi'], [ns.TUBES + '/stream#daap', ns.TUBES + '/stream#http', ns.TUBES + '/dbus#com.example.Go', ], xiangqi_caps) advertise_caps(q, conn, stream, [incoming_daap_fixed_properties, outgoing_daap_fixed_properties, xiangqi_fixed_properties], [ns.TUBES + '/dbus#com.example.Xiangqi', ns.TUBES + '/stream#daap', ], [ns.TUBES + '/stream#http', ns.TUBES + '/dbus#com.example.Go', ], daap_xiangqi_caps) advertise_caps(q, conn, stream, [incoming_daap_fixed_properties, http_fixed_properties, go_fixed_properties, xiangqi_fixed_properties], [ns.TUBES + '/dbus#com.example.Xiangqi', ns.TUBES + '/stream#daap', ns.TUBES + '/stream#http', ns.TUBES + '/dbus#com.example.Go', ], [], all_tubes_caps) # test daap + xiangqi again for some reason advertise_caps(q, conn, stream, [incoming_daap_fixed_properties, xiangqi_fixed_properties], [ns.TUBES + '/dbus#com.example.Xiangqi', ns.TUBES + '/stream#daap', ], [ns.TUBES + '/stream#http', ns.TUBES + '/dbus#com.example.Go', ], daap_xiangqi_caps) def test(q, bus, conn, stream): test_tube_caps_from_contact(q, bus, conn, stream, 'bilbo1@foo.com/Foo') test_tube_caps_to_contact(q, bus, conn, stream) if __name__ == '__main__': exec_test(test) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/caps/advertise-legacy.py��������������������������������������0000664�0001750�0001750�00000010221�12332441362�025547� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test AdvertiseCapabilities. """ import dbus from twisted.words.xish import xpath, domish from servicetest import EventPattern from gabbletest import exec_test from caps_helper import caps_contain, receive_presence_and_ask_caps,\ check_caps, JINGLE_CAPS import constants as cs import ns from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def run_test(q, bus, conn, stream): initial_presence = q.expect('stream-presence') # This method call looks wrong, but it's "the other side" of # test/twisted/capabilities/legacy-caps.py in MC 5.1 - MC doesn't know # how to map Client capabilities into the old Capabilities interface. # # Also, MC sometimes puts the same channel type in the list twice, so # make sure Gabble copes. add = [(cs.CHANNEL_TYPE_STREAMED_MEDIA, 2L**32-1), (cs.CHANNEL_TYPE_STREAM_TUBE, 2L**32-1), (cs.CHANNEL_TYPE_STREAM_TUBE, 2L**32-1)] remove = [] caps = conn.Capabilities.AdvertiseCapabilities(add, remove) (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream, False) check_caps(namespaces, JINGLE_CAPS) # Remove all our caps again add = [] remove = [cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.CHANNEL_TYPE_STREAM_TUBE] caps = conn.Capabilities.AdvertiseCapabilities(add, remove) (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream, False) check_caps(namespaces, []) # Add caps selectively (i.e. what a client that actually understood the # old Capabilities interface would do). With AUDIO and GTALK_P2P, we're # callable, but not via ICE-UDP, and not with video. # # (Jingle and raw UDP need no special client support, so are automatically # enabled whenever we can do audio or video.) add = [(cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.MEDIA_CAP_AUDIO | cs.MEDIA_CAP_GTALKP2P)] remove = [] caps = conn.Capabilities.AdvertiseCapabilities(add, remove) (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream, False) check_caps(namespaces, [ns.GOOGLE_P2P, ns.JINGLE_TRANSPORT_RAWUDP, ns.JINGLE, ns.JINGLE_015, ns.GOOGLE_FEAT_VOICE, ns.JINGLE_RTP_AUDIO, ns.JINGLE_RTP, ns.JINGLE_015_AUDIO]) # Remove all our caps again add = [] remove = [cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.CHANNEL_TYPE_STREAM_TUBE] caps = conn.Capabilities.AdvertiseCapabilities(add, remove) (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream, False) check_caps(namespaces, []) # With AUDIO but no transport, we are only callable via raw UDP, which # Google clients cannot do. add = [(cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.MEDIA_CAP_AUDIO)] remove = [] caps = conn.Capabilities.AdvertiseCapabilities(add, remove) (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream, False) check_caps(namespaces, [ns.JINGLE_TRANSPORT_RAWUDP, ns.JINGLE, ns.JINGLE_015, ns.JINGLE_RTP_AUDIO, ns.JINGLE_RTP, ns.JINGLE_015_AUDIO]) # Remove all our caps again add = [] remove = [cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.CHANNEL_TYPE_STREAM_TUBE] caps = conn.Capabilities.AdvertiseCapabilities(add, remove) (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream, False) check_caps(namespaces, []) # With VIDEO and ICE-UDP only, we are very futuristic indeed. # Google clients cannot interop with us. add = [(cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.MEDIA_CAP_VIDEO | cs.MEDIA_CAP_ICEUDP)] remove = [] caps = conn.Capabilities.AdvertiseCapabilities(add, remove) (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream, False) check_caps(namespaces, [ns.JINGLE_TRANSPORT_ICEUDP, ns.JINGLE_TRANSPORT_RAWUDP, ns.JINGLE, ns.JINGLE_015, ns.JINGLE_RTP_VIDEO, ns.JINGLE_RTP, ns.JINGLE_015_VIDEO]) if __name__ == '__main__': exec_test(run_test) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/caps/disco-without-node.py������������������������������������0000644�0001750�0001750�00000001011�12225363340�026037� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test that Gabble responds to disco#info queries without a node='' attribute. """ from servicetest import assertEquals from gabbletest import exec_test, elem_iq, elem import constants as cs import ns def test(q, bus, conn, stream): jid = 'foo@bar.com' iq = elem_iq(stream, 'get', from_=jid)(elem(ns.DISCO_INFO, 'query')) stream.send(iq) event = q.expect('stream-iq', iq_type='result', to='foo@bar.com') assertEquals(iq['id'], event.stanza['id']) if __name__ == '__main__': exec_test(test) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/caps/compat-bundles.py����������������������������������������0000664�0001750�0001750�00000003204�12225363340�025237� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Check that Gabble always responds to disco for voice-v1 and video-v1. They have hard-coded contents, because they only exist for compatibility with Google Talk, Google Video Chat, and old versions of Gabble. In particular, if the appropriate capabilities are not enabled (as in this test), doing disco on the bundles still gives their contents. """ import dbus from twisted.words.xish import xpath, domish from servicetest import EventPattern, assertEquals from gabbletest import exec_test, elem, elem_iq import constants as cs import ns from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def disco_bundle(q, bus, conn, stream, node, features): request = \ elem_iq(stream, 'get', from_='fake_contact@jabber.org/resource')( elem(ns.DISCO_INFO, 'query', node=node) ) stream.send(request) disco_response = q.expect('stream-iq', query_ns=ns.DISCO_INFO, iq_id=request['id']) nodes = xpath.queryForNodes('/iq/query/feature', disco_response.stanza) vars = [n["var"] for n in nodes] assertEquals(set(features), set(vars)) def run_test(q, bus, conn, stream): event_stream = q.expect('stream-presence') c_nodes = xpath.queryForNodes('/presence/c', event_stream.stanza) assert c_nodes is not None assert len(c_nodes) == 1 node = c_nodes[0].attributes['node'] disco_bundle(q, bus, conn, stream, node + '#voice-v1', set([ns.GOOGLE_FEAT_VOICE])) disco_bundle(q, bus, conn, stream, node + '#video-v1', set([ns.GOOGLE_FEAT_VIDEO])) if __name__ == '__main__': exec_test(run_test) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/caps/caps-persistent-cache.py���������������������������������0000664�0001750�0001750�00000007672�12332441362�026524� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ from twisted.words.xish import xpath from servicetest import ( assertEquals, assertContains, assertDoesNotContain, EventPattern, ) from gabbletest import make_presence, exec_test from caps_helper import compute_caps_hash, send_disco_reply import constants as cs import ns from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) contact_bare_jid = 'macbeth@glamis' contact_jid = 'macbeth@glamis/hall' client = 'http://telepathy.freedesktop.org/zomg-ponies' features = [ ns.JINGLE_015, ns.JINGLE_015_AUDIO, ns.JINGLE_015_VIDEO, ns.GOOGLE_P2P, ns.TUBES + '/dbus#com.example.Xiangqi', ] xiangqi_tube_cap = ( {cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.DBUS_TUBE_SERVICE_NAME: u'com.example.Xiangqi'}, [cs.TARGET_HANDLE, cs.TARGET_ID]) def send_presence(q, stream, contact_jid, identity): ver = compute_caps_hash([identity], features, {}) stream.send(make_presence(contact_jid, status='Hello', caps={'node': client, 'hash': 'sha-1', 'ver': ver})) def handle_disco(q, stream, contact_jid, identity): # Gabble tries to resolve a caps hash. ver = compute_caps_hash([identity], features, {}) event = q.expect('stream-iq', to=contact_jid, query_ns=ns.DISCO_INFO) assertEquals(client + '#' + ver, event.query.attributes['node']) # The bare jid replies. send_disco_reply(stream, event.stanza, [identity], features) def capabilities_changed(q, contact_handle): streamed_media_caps = (contact_handle, cs.CHANNEL_TYPE_STREAMED_MEDIA, 0, 3, 0, cs.MEDIA_CAP_AUDIO | cs.MEDIA_CAP_VIDEO) e = q.expect('dbus-signal', signal='CapabilitiesChanged') assertContains(streamed_media_caps, e.args[0]) e = q.expect('dbus-signal', signal='ContactCapabilitiesChanged') assertContains(contact_handle, e.args[0]) assertContains(xiangqi_tube_cap, e.args[0][contact_handle]) def test1(q, bus, conn, stream): contact_handle = conn.RequestHandles(cs.HT_CONTACT, [contact_bare_jid])[0] send_presence(q, stream, contact_jid, 'client/pc//thane') handle_disco(q, stream, contact_jid, 'client/pc//thane') capabilities_changed(q, contact_handle) def test2(q, bus, conn, stream): # The second time around, the capabilities are retrieved from the cache, # so no disco request is sent. contact_handle = conn.RequestHandles(cs.HT_CONTACT, [contact_bare_jid])[0] send_presence(q, stream, contact_jid, 'client/pc//thane') capabilities_changed(q, contact_handle) # Overflow the cache. GC is considered every 50 inserts, and then only # performed if the cache has more entries than a threshold which is set to # 50 in the test suite, reducing the cache to 0.95 * that threshold, which # is 47 in the test suite. # # We want to ensure that Macbeth is removed from the cache. In the worst # case, GC is considered and performed when we insert the 46th witch, which # will leave Macbeth in the cache. Inserting a further 50 witches will # ensure that Macbeth is flushed even in this worst case. Let's round up to # 100 witches. for i in range(100): overflow_contact_jid = 'witch%d@forest/cauldron' % i overflow_identity = 'client/pc//prophecy%d' % i send_presence(q, stream, overflow_contact_jid, overflow_identity) handle_disco(q, stream, overflow_contact_jid, overflow_identity) if __name__ == '__main__': # We run test1. The capabilities for macbeth@glamis's client # need to be fetched via disco and are then stored in the cache. exec_test(test1) # We run test2 again. The capabilities are retrieved from the cache, so no # disco request is sent. Then, a bunch of other clients turn up and force # the entry for Macbeth's client out of the cache. exec_test(test2) # We run test1 again. The caps are no longer in the cache, so a disco # request is sent again. exec_test(test1) ����������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/caps/initial-caps.py������������������������������������������0000664�0001750�0001750�00000001542�12225363340�024702� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test initial capabilities """ import dbus from twisted.words.xish import xpath, domish from servicetest import EventPattern from gabbletest import exec_test, sync_stream from caps_helper import check_caps, disco_caps import constants as cs import ns from config import VOIP_ENABLED def run_test(q, bus, conn, stream): initial_presence = q.expect('stream-presence') _, namespaces, _ = disco_caps(q, stream, initial_presence) # For some reason, until we advertise any capabilities, these caps turn # up in our presence if VOIP_ENABLED: caps = [ ns.JINGLE, ns.JINGLE_015, ns.JINGLE_TRANSPORT_ICEUDP, ns.JINGLE_TRANSPORT_RAWUDP, ns.GOOGLE_P2P ] else: caps = [] check_caps(namespaces, caps) if __name__ == '__main__': exec_test(run_test) ��������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/caps/hashed-caps.py�������������������������������������������0000664�0001750�0001750�00000027226�12332441362�024514� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# coding=utf-8 """ Test the verification string introduced in version 1.5 of XEP-0115 This test changes the caps several times: - Initial presence to be online - Change presence to handle audio calls, using XEP-0115-v1.3. Check that 'CapabilitiesChanged' *is* fired - Change presence *not* to handle audio calls, using XEP-0115-v1.5, but with a *bogus* hash. Check that 'CapabilitiesChanged' is *not* fired - Change presence *not* to handle audio calls, using XEP-0115-v1.5, with a *good* hash. Check that 'CapabilitiesChanged' *is* fired - Change presence to handle audio calls, using XEP-0115-v1.5, with a XEP-0128 dataform. Check that 'CapabilitiesChanged' is fired This is done for 2 contacts Then, this test announce 2 contacts with the same hash. - Gabble must ask only once for the hash and update the caps for both contacts - When the caps advertised by the first contact does not match, Gabble asks the second and update only the caps of the second contact """ import dbus from twisted.words.xish import xpath from gabbletest import ( exec_test, make_result_iq, make_presence, sync_stream, elem, ) from servicetest import sync_dbus, EventPattern, assertLength import constants as cs import ns from caps_helper import ( compute_caps_hash, make_caps_disco_reply, send_disco_reply, fake_client_dataforms) from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) caps_changed_flag = False some_identities = [ 'client/pc/fr/le gabble', 'client/pc/en/gabble', ] jingle_av_features = [ ns.JINGLE_015, ns.JINGLE_015_AUDIO, ns.JINGLE_015_VIDEO, ns.GOOGLE_P2P, ] def caps_changed_cb(dummy): # Workaround to bug 9980: do not raise an error but use a flag # https://bugs.freedesktop.org/show_bug.cgi?id=9980 global caps_changed_flag caps_changed_flag = True def test_hash(q, bus, conn, stream, contact, contact_handle, client): global caps_changed_flag presence = make_presence(contact, status='hello') stream.send(presence) q.expect('dbus-signal', signal='PresencesChanged', args=[{contact_handle: (2, u'available', 'hello')}]) # no special capabilities basic_caps = [(contact_handle, cs.CHANNEL_TYPE_TEXT, 3, 0)] assert conn.Capabilities.GetCapabilities([contact_handle]) == basic_caps # send updated presence with Jingle caps info presence = make_presence(contact, status='hello', caps={'node': client, 'ver': '0.1', }) stream.send(presence) # Gabble looks up our capabilities event = q.expect('stream-iq', to=contact, query_ns='http://jabber.org/protocol/disco#info') query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assert query_node.attributes['node'] == \ client + '#' + '0.1' # send good reply send_disco_reply(stream, event.stanza, [], jingle_av_features) # we can now do audio calls event = q.expect('dbus-signal', signal='CapabilitiesChanged') caps_diff = event.args[0] media_diff = [c for c in caps_diff if c[1] == cs.CHANNEL_TYPE_STREAMED_MEDIA][0] assert media_diff[5] & cs.MEDIA_CAP_AUDIO, media_diff[5] caps_changed_flag = False # Send presence without any capabilities. XEP-0115 §8.4 Caps Optimization # says “receivers of presence notifications MUST NOT expect an annotation # on every presence notification they receive”, so the contact should still # be media-capable afterwards. stream.send(make_presence(contact, status='very capable')) q.expect('dbus-signal', signal='PresencesChanged', args=[{contact_handle: (2, u'available', 'very capable')}]) ye_olde_caps = conn.Capabilities.GetCapabilities([contact_handle]) assertLength(1, [c for c in ye_olde_caps if c[1] == cs.CHANNEL_TYPE_STREAMED_MEDIA and c[3] & cs.MEDIA_CAP_AUDIO]) # send bogus presence caps = { 'node': client, 'ver': 'ceci=nest=pas=un=hash', 'hash': 'sha-1', } presence = make_presence(contact, status='hello', caps=caps) stream.send(presence) # Gabble looks up our capabilities event = q.expect('stream-iq', to=contact, query_ns='http://jabber.org/protocol/disco#info') query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assert query_node.attributes['node'] == \ client + '#' + caps['ver'] # send bogus reply send_disco_reply(stream, event.stanza, [], ['http://jabber.org/protocol/bogus-feature']) # don't receive any D-Bus signal sync_dbus(bus, q, conn) sync_stream(q, stream) assert caps_changed_flag == False # send presence with empty caps presence = make_presence(contact, status='hello', caps={'node': client, 'ver': '0.0', }) stream.send(presence) # Gabble looks up our capabilities event = q.expect('stream-iq', to=contact, query_ns='http://jabber.org/protocol/disco#info') query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assert query_node.attributes['node'] == \ client + '#' + '0.0' # still don't receive any D-Bus signal sync_dbus(bus, q, conn) assert caps_changed_flag == False # send good reply result = make_result_iq(stream, event.stanza) query = result.firstChildElement() stream.send(result) # we can now do nothing event = q.expect('dbus-signal', signal='CapabilitiesChanged') assert caps_changed_flag == True caps_changed_flag = False # send correct presence ver = compute_caps_hash(some_identities, jingle_av_features, fake_client_dataforms) caps = { 'node': client, 'ver': ver, 'hash': 'sha-1', } presence = make_presence(contact, status='hello', caps=caps) stream.send(presence) # Gabble looks up our capabilities event = q.expect('stream-iq', to=contact, query_ns='http://jabber.org/protocol/disco#info') query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assert query_node.attributes['node'] == \ client + '#' + caps['ver'] # don't receive any D-Bus signal sync_dbus(bus, q, conn) assert caps_changed_flag == False # send good reply send_disco_reply( stream, event.stanza, some_identities, jingle_av_features, fake_client_dataforms) # we can now do audio calls event = q.expect('dbus-signal', signal='CapabilitiesChanged', ) assert caps_changed_flag == True caps_changed_flag = False def test_two_clients(q, bus, conn, stream, contact1, contact2, contact_handle1, contact_handle2, client, broken_hash): global caps_changed_flag presence = make_presence(contact1, status='hello') stream.send(presence) q.expect('dbus-signal', signal='PresencesChanged', args=[{contact_handle1: (2, u'available', 'hello')}]) presence = make_presence(contact2, status='hello') stream.send(presence) q.expect('dbus-signal', signal='PresencesChanged', args=[{contact_handle2: (2, u'available', 'hello')}]) # no special capabilities basic_caps = [(contact_handle1, cs.CHANNEL_TYPE_TEXT, 3, 0)] assert conn.Capabilities.GetCapabilities([contact_handle1]) == basic_caps basic_caps = [(contact_handle2, cs.CHANNEL_TYPE_TEXT, 3, 0)] assert conn.Capabilities.GetCapabilities([contact_handle2]) == basic_caps # send updated presence with Jingle caps info ver = compute_caps_hash(some_identities, jingle_av_features, {}) caps = { 'node': client, 'ver': ver, 'hash': 'sha-1', } presence = make_presence(contact1, status='hello', caps=caps) stream.send(presence) presence = make_presence(contact2, status='hello', caps=caps) stream.send(presence) # Gabble looks up our capabilities event = q.expect('stream-iq', to=contact1, query_ns='http://jabber.org/protocol/disco#info') query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assert query_node.attributes['node'] == \ client + '#' + ver # don't receive any D-Bus signal sync_dbus(bus, q, conn) assert caps_changed_flag == False result = make_caps_disco_reply( stream, event.stanza, some_identities, jingle_av_features) if broken_hash: # make the hash break! query = result.firstChildElement() query.addElement('feature')['var'] = 'http://example.com/another-feature' stream.send(result) if broken_hash: # Gabble looks up our capabilities again because the first contact # failed to provide a valid hash event = q.expect('stream-iq', to=contact2, query_ns='http://jabber.org/protocol/disco#info') query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assert query_node.attributes['node'] == \ client + '#' + ver # don't receive any D-Bus signal sync_dbus(bus, q, conn) assert caps_changed_flag == False # send good reply send_disco_reply(stream, event.stanza, some_identities, jingle_av_features) # we can now do audio calls with both contacts event = q.expect('dbus-signal', signal='CapabilitiesChanged', args=[[(contact_handle2, cs.CHANNEL_TYPE_STREAMED_MEDIA, 0, 3, 0, cs.MEDIA_CAP_AUDIO | cs.MEDIA_CAP_VIDEO)]]) if not broken_hash: # if the first contact failed to provide a good hash, it does not # deserve its capabilities to be understood by Gabble! event = q.expect('dbus-signal', signal='CapabilitiesChanged', args=[[(contact_handle1, cs.CHANNEL_TYPE_STREAMED_MEDIA, 0, 3, 0, cs.MEDIA_CAP_AUDIO | cs.MEDIA_CAP_VIDEO)]]) caps_changed_flag = False # don't receive any D-Bus signal sync_dbus(bus, q, conn) assert caps_changed_flag == False def test_39464(q, bus, conn, stream): """ Regression test for an issue where a form with no type='' attribute on the <x/> node would crash Gabble. """ client = 'fake:qutim' hash = 'blahblah' contact = 'bug-39464@example.com/foo' caps = { 'node': client, 'ver': hash, 'hash': 'sha-1', } presence = make_presence(contact, status='hello', caps=caps) stream.send(presence) # Gabble looks up our capabilities event = q.expect('stream-iq', to=contact, query_ns=ns.DISCO_INFO) # Send a reply with a form without a type='' result = make_result_iq(stream, event.stanza, add_query_node=False) result.addChild( elem(ns.DISCO_INFO, 'query', node='%s#%s' % (client, hash))( # NB. no type='' attribute elem(ns.X_DATA, 'x') ) ) stream.send(result) # We don't really care what Gabble does, as long as it doesn't crash. sync_stream(q, stream) def test(q, bus, conn, stream): # be notified when the signal CapabilitiesChanged is fired conn_caps_iface = dbus.Interface(conn, cs.CONN_IFACE_CAPS) conn_caps_iface.connect_to_signal('CapabilitiesChanged', caps_changed_cb) test_hash(q, bus, conn, stream, 'bob@foo.com/Foo', 2L, 'http://telepathy.freedesktop.org/fake-client') test_hash(q, bus, conn, stream, 'bob2@foo.com/Foo', 3L, 'http://telepathy.freedesktop.org/fake-client2') test_two_clients(q, bus, conn, stream, 'user1@example.com/Res', 'user2@example.com/Res', 4L, 5L, 'http://telepathy.freedesktop.org/fake-client3', 0) test_two_clients(q, bus, conn, stream, 'user3@example.com/Res', 'user4@example.com/Res', 6L, 7L, 'http://telepathy.freedesktop.org/fake-client4', 1) test_39464(q, bus, conn, stream) if __name__ == '__main__': exec_test(test) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/caps/jingle-caps.py�������������������������������������������0000664�0001750�0001750�00000022226�12332441362�024523� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test several different permutations of features that should a client audio and/or video capable """ from functools import partial from itertools import permutations from gabbletest import exec_test, make_presence, sync_stream from servicetest import ( assertContains, assertDoesNotContain, assertEquals, EventPattern, make_channel_proxy ) import constants as cs import ns from caps_helper import presence_and_disco, compute_caps_hash, send_presence from jingle.jingletest2 import JingleTest2, JingleProtocol031 from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) client = 'http://telepathy.freedesktop.org/fake-client' caps = { 'node': client, 'ver': "dummy", 'hash': 'sha-1' } all_transports = [ ns.JINGLE_TRANSPORT_ICEUDP, ns.JINGLE_TRANSPORT_RAWUDP, ns.GOOGLE_P2P ] def check_contact_caps (caps, channel_type, expected_media_caps): [media_caps] = [ c for c in caps if c[0][cs.CHANNEL_TYPE] == channel_type ] assertEquals (expected_media_caps, media_caps[1]) def test_caps(q, conn, stream, contact, features, audio, video, google=False): caps['ver'] = compute_caps_hash ([], features, {}) h = presence_and_disco(q, conn, stream, contact, True, client, caps, features) cflags = 0 stream_expected_media_caps = [] call_expected_media_caps = [] if audio: cflags |= cs.MEDIA_CAP_AUDIO stream_expected_media_caps.append (cs.INITIAL_AUDIO) call_expected_media_caps.append (cs.CALL_INITIAL_AUDIO) call_expected_media_caps.append (cs.CALL_INITIAL_AUDIO_NAME) if video: cflags |= cs.MEDIA_CAP_VIDEO stream_expected_media_caps.append (cs.INITIAL_VIDEO) call_expected_media_caps.append (cs.CALL_INITIAL_VIDEO) call_expected_media_caps.append (cs.CALL_INITIAL_VIDEO_NAME) # If the contact can only do one of audio or video, or uses a Google # client, they'll have the ImmutableStreams cap. if cflags < (cs.MEDIA_CAP_AUDIO | cs.MEDIA_CAP_VIDEO) or google: cflags |= cs.MEDIA_CAP_IMMUTABLE_STREAMS stream_expected_media_caps.append(cs.IMMUTABLE_STREAMS) else: call_expected_media_caps.append(cs.CALL_MUTABLE_CONTENTS) _, event = q.expect_many( EventPattern('dbus-signal', signal='CapabilitiesChanged', args = [[ ( h, cs.CHANNEL_TYPE_STREAMED_MEDIA, 0, # old generic 3, # new generic (can create and receive these) 0, # old specific cflags ) ]] # new specific ), EventPattern('dbus-signal', signal='ContactCapabilitiesChanged') ) assertContains((h, cs.CHANNEL_TYPE_STREAMED_MEDIA, 3, cflags), conn.Capabilities.GetCapabilities([h])) # Check Contact capabilities for streamed media assertEquals(len(event.args), 1) assertEquals (event.args[0], conn.ContactCapabilities.GetContactCapabilities([h])) check_contact_caps (event.args[0][h], cs.CHANNEL_TYPE_STREAMED_MEDIA, stream_expected_media_caps) check_contact_caps (event.args[0][h], cs.CHANNEL_TYPE_CALL, call_expected_media_caps) def test_all_transports(q, conn, stream, contact, features, audio, video): for t in all_transports: test_caps(q, conn, stream, contact, features + [t] , audio, video) contact += "a" def test(q, bus, conn, stream): # Fully capable jingle clients with one transport each features = [ ns.JINGLE_RTP, ns.JINGLE_RTP_AUDIO, ns.JINGLE_RTP_VIDEO ] test_all_transports(q, conn, stream, "full@a", features, True, True) # video capable jingle clients with one transport each features = [ ns.JINGLE_RTP, ns.JINGLE_RTP_VIDEO ] test_all_transports (q, conn, stream, "video@a", features, False, True) # audio capable jingle clients with one transport each features = [ ns.JINGLE_RTP, ns.JINGLE_RTP_AUDIO ] test_all_transports(q, conn, stream, "audio@a", features, True, False) # old jingle client fully capable features = [ ns.JINGLE_015, ns.JINGLE_015_AUDIO, ns.JINGLE_015_VIDEO ] test_all_transports(q, conn, stream, "oldfull@a", features, True, True) # old jingle client video capable features = [ ns.JINGLE_015, ns.JINGLE_015_VIDEO ] test_all_transports(q, conn, stream, "oldvideo@a", features, False, True) # old jingle client audio capable features = [ ns.JINGLE_015, ns.JINGLE_015_AUDIO ] test_all_transports(q, conn, stream, "oldaudio@a", features, True, False) # Google media doesn't need a transport at all features = [ ns.GOOGLE_FEAT_VOICE, ns.GOOGLE_FEAT_VIDEO ] test_caps(q, conn, stream, "full@google", features, True, True, google=True) # Google video only features = [ ns.GOOGLE_FEAT_VIDEO ] test_caps(q, conn, stream, "video@google", features, False, True, google=True) # Google audio only features = [ ns.GOOGLE_FEAT_VOICE ] test_caps(q, conn, stream, "audio@google", features, True, False, google=True) def test_prefer_phones(q, bus, conn, stream, expect_disco): cat = 'cat@windowsill' def sign_in_a_cat(jid, identities, show=None): caps['ver'] = compute_caps_hash(identities, features, {}) presence_and_disco(q, conn, stream, jid, expect_disco, client, caps, features, identities=identities, initial=False, show=show) # Make sure Gabble's got the caps sync_stream(q, stream) def make_call(expected_recipient): jp = JingleProtocol031() jt = JingleTest2(jp, conn, q, stream, 'test@localhost', 'dummy') conn.Requests.CreateChannel({ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: cat, cs.INITIAL_AUDIO: True, }) e = q.expect('dbus-signal', signal='NewSessionHandler') session = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session.Ready() e = q.expect('dbus-signal', signal='NewStreamHandler') stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) stream_handler.Ready(jt.get_audio_codecs_dbus()) stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) e = q.expect('stream-iq', predicate=jp.action_predicate('session-initiate')) assertEquals(expected_recipient, e.to) features = [ ns.JINGLE_RTP, ns.JINGLE_RTP_AUDIO, ns.JINGLE_RTP_VIDEO ] + all_transports # My cat is signed in with their laptop (which is available)... laptop_jid = 'cat@windowsill/Laptop' sign_in_a_cat(laptop_jid, ['client/pc//clocks']) # ...and a web client, which is away. cloud_jid = 'cat@windowsill/Cloud' sign_in_a_cat(cloud_jid, ['client/web//zomg'], show='away') # The laptop is more available, so the call should go there. make_call(expected_recipient=laptop_jid) # But if my cat signs in with a phone, also set to away... phone_jid = 'cat@windowsill/Fido' sign_in_a_cat(phone_jid, ['client/phone//mars rover'], show='away') # ...then calls should go there, even though the laptop is more available. make_call(expected_recipient=phone_jid) def test_google_caps(q, bus, conn, stream): i = 1 # we want to make sure all permutations of voice-v1 and video-v1 # result in the correct caps, so let's do exactly that. for j in (1, 2): for ext_set in permutations(['voice-v1', 'video-v1'], j): jid = 'larry%s@page/mountainview' % i i += 1 # order of these ext values shouldn't matter gcaps = { 'node': 'blahblahthiskeepsonchanging', 'ver': '1.1', 'ext': ' '.join(ext_set) } handle = conn.RequestHandles(cs.HT_CONTACT, [jid])[0] send_presence(q, conn, stream, jid, gcaps, initial=True) e = q.expect('dbus-signal', signal='ContactCapabilitiesChanged', predicate=lambda e: handle in e.args[0]) assertEquals(1, len(e.args[0])) rccs = e.args[0][handle] found = False for fixed, allowed in rccs: if fixed[cs.CHANNEL_TYPE] != cs.CHANNEL_TYPE_CALL: continue # we should only have InitialAudio or InitialVideo if # voice-v1 or video-v1 is present respectively for a, b in [('voice-v1' in ext_set, cs.CALL_INITIAL_AUDIO), ('video-v1' in ext_set, cs.CALL_INITIAL_VIDEO)]: if a: assertContains(b, allowed) else: assertDoesNotContain(b, allowed) found = True assert found if __name__ == '__main__': exec_test(test) exec_test(partial(test_prefer_phones, expect_disco=True)) # And again, this time pulling the caps from the cache. This tests that the # quirk is cached! exec_test(partial(test_prefer_phones, expect_disco=False)) exec_test(test_google_caps) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/caps/caps-cache.py��������������������������������������������0000664�0001750�0001750�00000007630�12332441362�024320� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test that requesting a caps set 1 time is enough with hash and that we need 5 confirmation without hash. """ from twisted.words.xish import xpath from servicetest import EventPattern, assertEquals, assertContains from gabbletest import exec_test, make_presence, sync_stream import constants as cs import ns from caps_helper import ( compute_caps_hash, fake_client_dataforms, presence_and_disco, send_presence, expect_disco, send_disco_reply) from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) client = 'http://telepathy.freedesktop.org/fake-client/caps-cache' features = [ ns.JINGLE_015, ns.JINGLE_015_AUDIO, ns.JINGLE_015_VIDEO, ns.GOOGLE_P2P, ] def expect_caps(q, conn, h): # we can now do audio and video calls event = q.expect('dbus-signal', signal='CapabilitiesChanged') check_caps(conn, h) def check_caps(conn, h): assertContains((h, cs.CHANNEL_TYPE_STREAMED_MEDIA, 3, cs.MEDIA_CAP_AUDIO | cs.MEDIA_CAP_VIDEO), conn.Capabilities.GetCapabilities([h])) def update_contact_caps(q, conn, stream, contact, caps, disco = True, dataforms = {}, initial = True): h = presence_and_disco (q, conn, stream, contact, disco, client, caps, features, dataforms=dataforms, initial = initial) expect_caps (q, conn, h) def test(q, bus, conn, stream): caps = { 'node': client, 'ver': '0.1', } update_contact_caps(q, conn, stream, 'bob1@foo.com/Foo', caps) update_contact_caps(q, conn, stream, 'bob2@foo.com/Foo', caps) # Meredith signs in from one resource. update_contact_caps(q, conn, stream, 'meredith@foo.com/One', caps) # Meredith signs in from another resource with the same client. We don't # need to disco her, even though we don't trust this caps node in general # yet, because she's already told us what it means. meredith_two = 'meredith@foo.com/Two' q.forbid_events([ EventPattern('stream-iq', to=meredith_two, query_ns=ns.DISCO_INFO) ]) stream.send(make_presence(meredith_two, 'hello', caps=caps)) sync_stream(q, stream) # Jens signs in from one resource, which is slow to answer the disco query. jens_one = 'jens@foo.com/One' j = send_presence(q, conn, stream, jens_one, caps) j_stanza = expect_disco(q, jens_one, client, caps) # Jens now signs in elsewhere with the same client; we disco it (maybe # it'll reply sooner? Maybe his first client's network connection went away # and the server hasn't noticed yet?) and it replies immediately. update_contact_caps (q, conn, stream, 'jens@foo.com/Two', caps, initial=False) # Jens' first client replies. We don't expect any caps changes here, and # this shouldn't count as a second point towards the five we need to trust # this caps node. send_disco_reply(stream, j_stanza, [], features) check_caps (conn, j) update_contact_caps (q, conn, stream, 'bob5@foo.com/Foo', caps) # Now five distinct contacts have told us what this caps node means, we # trust it. update_contact_caps (q, conn, stream, 'bob6@foo.com/Foo', caps, disco = False) update_contact_caps (q, conn, stream, 'bob7@foo.com/Foo', caps, disco = False) caps = { 'node': client, 'ver': compute_caps_hash([], features, fake_client_dataforms), 'hash': 'sha-1', } update_contact_caps(q, conn, stream, 'bilbo1@foo.com/Foo', caps, dataforms = fake_client_dataforms) # We can verify the reply for these caps against the hash, and thus never # need to disco it again. update_contact_caps(q, conn, stream, 'bilbo2@foo.com/Foo', caps, disco = False, dataforms = fake_client_dataforms) update_contact_caps(q, conn, stream, 'bilbo3@foo.com/Foo', caps, disco = False, dataforms = fake_client_dataforms) if __name__ == '__main__': exec_test(test) ��������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/caps/double-disco.py������������������������������������������0000644�0001750�0001750�00000003224�12225363340�024673� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ from twisted.words.xish import xpath from servicetest import EventPattern from gabbletest import exec_test, make_presence, sync_stream import constants as cs import ns def test(q, bus, conn, stream): contact = 'grapes@graze.box/delicious' presence = make_presence(contact, status='eat me!', caps={ 'node': 'oh:hai', 'ver': 'thar', }) thar_disco = EventPattern('stream-iq', to=contact, query_ns=ns.DISCO_INFO, query_node='oh:hai#thar') stream.send(presence) q.expect_many(thar_disco) # Okay, all good so far. But if we get the same caps node again from the # same contact, we shouldn't disco it again: we won't get any more trust # that way. This matters in practice, because Google's clients send a whole # bunch of presence stanzas in quick succession when they sign on. q.forbid_events([thar_disco]) stream.send(presence) sync_stream(q, stream) # If we get a presence update from this contact with some new ext='' # bundles, we should disco those, but not the nodes we're already querying. presence = make_presence(contact, status='eat me!', caps={ 'node': 'oh:hai', 'ver': 'thar', 'ext': 'good-sir', }) good_sir_disco = EventPattern('stream-iq', to=contact, query_ns=ns.DISCO_INFO, query_node='oh:hai#good-sir') stream.send(presence) q.expect_many(good_sir_disco) sync_stream(q, stream) # We should only disco ext='' attributes once per jid, too. q.forbid_events([good_sir_disco]) stream.send(presence) sync_stream(q, stream) if __name__ == '__main__': exec_test(test) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tubes/��������������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�022154� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tubes/test-socks5-muc.py��������������������������������������0000664�0001750�0001750�00000005640�12332441362�025472� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""Check if SOCKS5 relays are disabled in muc""" import os if os.name != 'posix': # skipped on non-Unix for now, because it uses a Unix socket raise SystemExit(77) import dbus from servicetest import call_async, EventPattern, EventProtocolClientFactory from gabbletest import acknowledge_iq, make_muc_presence, exec_test import constants as cs import ns from mucutil import join_muc from bytestream import BytestreamS5BRelay, create_from_si_offer, announce_socks5_proxy from twisted.internet import reactor def test(q, bus, conn, stream): iq_event, disco_event = q.expect_many( EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS)) acknowledge_iq(stream, iq_event.stanza) announce_socks5_proxy(q, stream, disco_event.stanza) text_chan = join_muc(q, bus, conn, stream, 'chat@conf.localhost') # bob offers a stream tube stream_tube_id = 1 presence = make_muc_presence('owner', 'moderator', 'chat@conf.localhost', 'bob') tubes = presence.addElement((ns.TUBES, 'tubes')) tube = tubes.addElement((None, 'tube')) tube['type'] = 'stream' tube['service'] = 'echo' tube['id'] = str(stream_tube_id) parameters = tube.addElement((None, 'parameters')) stream.send(presence) def new_chan_predicate(e): path, props = e.args[0][0] return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE e = q.expect('dbus-signal', signal='NewChannels', predicate=new_chan_predicate) channels = e.args[0] assert len(channels) == 1 path, props = channels[0] assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE tube_chan = bus.get_object(conn.bus_name, path) tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE) call_async(q, tube_iface, 'Accept', 0, 0, '', byte_arrays=True) accept_return_event, _ = q.expect_many( EventPattern('dbus-return', method='Accept'), EventPattern('dbus-signal', signal='TubeChannelStateChanged', args=[cs.TUBE_CHANNEL_STATE_OPEN])) unix_socket_adr = accept_return_event.value[0] factory = EventProtocolClientFactory(q) reactor.connectUNIX(unix_socket_adr, factory) # expect SI request e = q.expect('stream-iq', to='chat@conf.localhost/bob', query_ns=ns.SI, query_name='si') bytestream, profile = create_from_si_offer(stream, q, BytestreamS5BRelay, e.stanza, 'chat@conf.localhost/bob') result, si = bytestream.create_si_reply(e.stanza, 'test@localhost/Resource') si.addElement((ns.TUBES, 'tube')) stream.send(result) # wait SOCKS5 init iq id, mode, si, hosts = bytestream._expect_socks5_init() for jid, host, port in hosts: # the proxy is not announced because we are in a muc assert jid != 'proxy.localhost' if __name__ == '__main__': exec_test(test) ������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tubes/test-get-available-tubes.py�����������������������������0000664�0001750�0001750�00000004776�12332441362�027327� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""Test GetAvailableStreamTubeTypes and GetAvailableTubeTypes""" import os import sys import dbus from servicetest import call_async, EventPattern, tp_name_prefix,\ assertContains, assertEquals, assertLength from gabbletest import ( exec_test, make_result_iq, acknowledge_iq, make_muc_presence) import constants as cs sample_parameters = dbus.Dictionary({ 's': 'hello', 'ay': dbus.ByteArray('hello'), 'u': dbus.UInt32(123), 'i': dbus.Int32(-123), }, signature='sv') def test(q, bus, conn, stream): iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, iq_event.stanza) # muc stream tube call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: 'chat@conf.localhost', cs.STREAM_TUBE_SERVICE: 'test'}) q.expect('stream-presence', to='chat@conf.localhost/test') # Send presence for other member of room. stream.send(make_muc_presence('owner', 'moderator', 'chat@conf.localhost', 'bob')) # Send presence for own membership of room. stream.send(make_muc_presence('owner', 'moderator', 'chat@conf.localhost', 'test')) members, event = q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=[u'', [2, 3], [], [], [], 0, 0]), EventPattern('dbus-return', method='CreateChannel')) path = event.value[0] props = event.value[1] tube = bus.get_object(conn.bus_name, path) stream_tubes_types = tube.Get(cs.CHANNEL_TYPE_STREAM_TUBE, 'SupportedSocketTypes', dbus_interface=cs.PROPERTIES_IFACE) if os.name == 'posix': assert cs.SOCKET_ACCESS_CONTROL_LOCALHOST in \ stream_tubes_types[cs.SOCKET_ADDRESS_TYPE_UNIX], \ stream_tubes_types[cs.SOCKET_ADDRESS_TYPE_UNIX] # so far we only guarantee to support credentials-passing on Linux if sys.platform == 'linux2': assert cs.SOCKET_ACCESS_CONTROL_CREDENTIALS in \ stream_tubes_types[cs.SOCKET_ADDRESS_TYPE_UNIX], \ stream_tubes_types[cs.SOCKET_ADDRESS_TYPE_UNIX] assertEquals([cs.SOCKET_ACCESS_CONTROL_LOCALHOST, cs.SOCKET_ACCESS_CONTROL_PORT], stream_tubes_types[cs.SOCKET_ADDRESS_TYPE_IPV4]) assertEquals([cs.SOCKET_ACCESS_CONTROL_LOCALHOST, cs.SOCKET_ACCESS_CONTROL_PORT], stream_tubes_types[cs.SOCKET_ADDRESS_TYPE_IPV6]) if __name__ == '__main__': exec_test(test) ��telepathy-gabble-0.18.3/tests/twisted/tubes/offer-muc-stream-tube.py��������������������������������0000664�0001750�0001750�00000015752�12332441362�026642� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""Test stream tube support in the context of a MUC.""" import errno import os import dbus from servicetest import call_async, EventPattern, unwrap, assertContains, assertEquals from gabbletest import acknowledge_iq, make_muc_presence import constants as cs import ns import tubetestutil as t from mucutil import join_muc from bytestream import BytestreamS5BRelay, BytestreamS5BRelayBugged from twisted.words.xish import xpath from twisted.internet import reactor sample_parameters = dbus.Dictionary({ 's': 'hello', 'ay': dbus.ByteArray('hello'), 'u': dbus.UInt32(123), 'i': dbus.Int32(-123), }, signature='sv') def connect_to_tube(stream, q, bytestream_cls, muc, stream_tube_id): # The CM is the server, so fake a client wanting to talk to it bytestream = bytestream_cls(stream, q, 'alpha', '%s/bob' % muc, '%s/test' % muc, True) # set the real jid of the target as 'to' because the XMPP server changes # it when delivering the IQ iq, si = bytestream.create_si_offer(ns.TUBES, 'test@localhost/Resource') stream_node = si.addElement((ns.TUBES, 'muc-stream')) stream_node['tube'] = str(stream_tube_id) stream.send(iq) return bytestream def use_tube(q, bytestream, protocol, conn_id): # have the fake client open the stream bytestream.open_bytestream() # have the fake client send us some data bytestream.send_data('hello initiator') # the server reply event = q.expect('socket-data', data='hello initiator', protocol=protocol) data = 'hello joiner' protocol.sendData(data) # we receive server's data binary = bytestream.get_data(len(data)) assert binary == data, binary # peer closes the bytestream bytestream.close() e = q.expect('dbus-signal', signal='ConnectionClosed') assertEquals(conn_id, e.args[0]) assertEquals(cs.CONNECTION_LOST, e.args[1]) def test(q, bus, conn, stream, bytestream_cls, address_type, access_control, access_control_param): if bytestream_cls in [BytestreamS5BRelay, BytestreamS5BRelayBugged]: # disable SOCKS5 relay tests because proxy can't be used with muc # contacts atm return iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, iq_event.stanza) t.check_conn_properties(q, conn) bob_handle = conn.RequestHandles(cs.HT_CONTACT, ['chat@conf.localhost/bob'])[0] address = t.create_server(q, address_type) def new_chan_predicate(e): types = [] for _, props in e.args[0]: types.append(props[cs.CHANNEL_TYPE]) return cs.CHANNEL_TYPE_STREAM_TUBE in types def find_stream_tube(channels): for path, props in channels: if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE: return path, props return None, None # offer a stream tube to another room (new API) address = t.create_server(q, address_type, block_reading=True) request = { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: 'chat@conf.localhost', cs.STREAM_TUBE_SERVICE: 'newecho', } _, _, new_tube_path, new_tube_props = \ join_muc(q, bus, conn, stream, 'chat@conf.localhost', request) e = q.expect('dbus-signal', signal='NewChannels', predicate=new_chan_predicate) path, prop = find_stream_tube(e.args[0]) assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE assert prop[cs.INITIATOR_ID] == 'chat@conf.localhost/test' assert prop[cs.REQUESTED] == True assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM assert prop[cs.TARGET_ID] == 'chat@conf.localhost' assert prop[cs.STREAM_TUBE_SERVICE] == 'newecho' # check that the tube channel is in the channels list all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, 'Channels', dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assertContains((path, prop), all_channels) tube_chan = bus.get_object(conn.bus_name, path) stream_tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE) chan_iface = dbus.Interface(tube_chan, cs.CHANNEL) tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE) assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED # offer the tube call_async(q, stream_tube_iface, 'Offer', address_type, address, access_control, {'foo': 'bar'}) stream_event, _, status_event = q.expect_many( EventPattern('stream-presence', to='chat@conf.localhost/test'), EventPattern('dbus-return', method='Offer'), EventPattern('dbus-signal', signal='TubeChannelStateChanged', args=[cs.TUBE_CHANNEL_STATE_OPEN])) tube_self_handle = tube_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP) assert conn.InspectHandles(cs.HT_CONTACT, [tube_self_handle]) == ['chat@conf.localhost/test'] presence = stream_event.stanza tubes_nodes = xpath.queryForNodes('/presence/tubes[@xmlns="%s"]' % ns.TUBES, presence) assert tubes_nodes is not None assert len(tubes_nodes) == 1 stream_tube_id = 666 tube_nodes = xpath.queryForNodes('/tubes/tube', tubes_nodes[0]) assert tube_nodes is not None assert len(tube_nodes) == 1 for tube in tube_nodes: assert tube['type'] == 'stream' assert not tube.hasAttribute('initiator') assert tube['service'] == 'newecho' assert not tube.hasAttribute('stream-id') assert not tube.hasAttribute('dbus-name') stream_tube_id = int(tube['id']) params = {} parameter_nodes = xpath.queryForNodes('/tube/parameters/parameter', tube) for node in parameter_nodes: assert node['name'] not in params params[node['name']] = (node['type'], str(node)) assert params == {'foo': ('str', 'bar')} bob_handle = conn.RequestHandles(cs.HT_CONTACT, ['chat@conf.localhost/bob'])[0] bytestream = connect_to_tube(stream, q, bytestream_cls, 'chat@conf.localhost', stream_tube_id) iq_event, socket_event, conn_event = q.expect_many( EventPattern('stream-iq', iq_type='result'), EventPattern('socket-connected'), EventPattern('dbus-signal', signal='NewRemoteConnection', interface=cs.CHANNEL_TYPE_STREAM_TUBE)) handle, access, conn_id = conn_event.args assert handle == bob_handle protocol = socket_event.protocol # start to read from the transport so we can read the control byte protocol.transport.startReading() t.check_new_connection_access(q, access_control, access, protocol) # handle iq_event bytestream.check_si_reply(iq_event.stanza) tube = xpath.queryForNodes('/iq//si/tube[@xmlns="%s"]' % ns.TUBES, iq_event.stanza) assert len(tube) == 1 use_tube(q, bytestream, protocol, conn_id) chan_iface.Close() q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed')) t.cleanup() if __name__ == '__main__': t.exec_stream_tube_test(test) ����������������������telepathy-gabble-0.18.3/tests/twisted/tubes/tubetestutil.py�����������������������������������������0000664�0001750�0001750�00000034255�12332441362�025265� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Helper functions for writing tubes tests """ import errno import os import socket import sys import tempfile import dbus from servicetest import unwrap, assertContains, EventProtocolClientFactory,\ EventProtocolFactory, assertEquals, EventProtocol, EventPattern from gabbletest import exec_test import constants as cs import bytestream import ns from twisted.internet import reactor from twisted.internet.protocol import Factory, Protocol from twisted.internet.error import CannotListenError from twisted.internet import tcp _to_cleanup = [] def cleanup(): for f in _to_cleanup: try: os.remove(f) except OSError: pass # worse things have happened del _to_cleanup[:] def check_tube_in_tubes(tube, tubes): """ Check that 'tube' is in 'tubes', which should be the return value of ListTubes(). tube[0] may be None to check that a new-style tube is represented on the old interface (because you don't know what its id is in those cases) """ utube = unwrap(tube) if tube[0] is None: for t in tubes: if tube[1:] == t[1:]: return else: for t in tubes: if tube[0] != t[0]: continue pair = "\n %s,\n %s" % (utube, unwrap(t)) assert tube[1] == t[1], "self handles don't match: %s" % pair assert tube[2] == t[2], "tube types don't match: %s" % pair assert tube[3] == t[3], "services don't match: %s " % pair assert tube[4] == t[4], "parameters don't match: %s" % pair assert tube[5] == t[5], "states don't match: %s" % pair return assert False, "tube %s not in %s" % (unwrap (tube), unwrap (tubes)) def check_conn_properties(q, conn, channel_list=None): """ Check that Connection.Interface.Requests.Channels matches channel_list, and that RequestableChannelClasses contains the expected tube types. """ properties = conn.GetAll( cs.CONN_IFACE_REQUESTS, dbus_interface=cs.PROPERTIES_IFACE) if channel_list == None: assert properties.get('Channels') == [], properties['Channels'] else: for i in channel_list: assert i in properties['Channels'], \ (i, properties['Channels']) # 1-1 StreamTube channel assert ({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT }, [cs.TARGET_HANDLE, cs.TARGET_ID, cs.STREAM_TUBE_SERVICE] ) in properties.get('RequestableChannelClasses'),\ properties['RequestableChannelClasses'] # muc StreamTube channel assert ({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM }, [cs.TARGET_HANDLE, cs.TARGET_ID, cs.STREAM_TUBE_SERVICE] ) in properties.get('RequestableChannelClasses'),\ properties['RequestableChannelClasses'] # 1-1 D-Bus tube channel assert ({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT}, [cs.TARGET_HANDLE, cs.TARGET_ID, cs.DBUS_TUBE_SERVICE_NAME] ) in properties.get('RequestableChannelClasses'),\ properties['RequestableChannelClasses'] # muc D-Bus tube channel assert ({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM}, [cs.TARGET_HANDLE, cs.TARGET_ID, cs.DBUS_TUBE_SERVICE_NAME] ) in properties.get('RequestableChannelClasses'),\ properties['RequestableChannelClasses'] def check_NewChannel_signal(args, channel_type, chan_path, contact_handle, suppress_handler): """ Checks the first argument, a tuple of arguments from NewChannel, matches the other arguments. """ if chan_path is not None: assert args[0] == chan_path, (args, chan_path) assert args[1] == channel_type, (args, channel_type) assert args[2] == cs.HT_CONTACT, (args, cs.HT_CONTACT) assert args[3] == contact_handle, (args, contact_handle) assert args[4] == suppress_handler, (args, suppress_handler) def check_NewChannels_signal(conn, args, channel_type, chan_path, contact_handle, contact_id, initiator_handle): """ Checks the first argument, a one-tuple of arguments from NewChannels, matches the other arguments. """ assert len(args) == 1, args assert len(args[0]) == 1 # one channel path, props = args[0][0] assert path == chan_path, (emitted_path, chan_path) assert props[cs.CHANNEL_TYPE] == channel_type, (props, channel_type) assert props[cs.TARGET_HANDLE_TYPE] == cs.HT_CONTACT, props assert props[cs.TARGET_HANDLE] == contact_handle, (props, contact_handle) assert props[cs.TARGET_ID] == contact_id, (props, contact_id) assert props[cs.REQUESTED] == True, props assert props[cs.INITIATOR_HANDLE] == initiator_handle, \ (props, initiator_handle) assert props[cs.INITIATOR_ID] == 'test@localhost', props # check that the newly announced channel is in the channels list all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, 'Channels', dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assertContains((path, props), all_channels) def check_platform_socket_types(sock_types): assertContains(cs.SOCKET_ADDRESS_TYPE_IPV4, sock_types) assertContains(cs.SOCKET_ADDRESS_TYPE_IPV6, sock_types) if os.name == 'posix': # true on at least Linux assertContains(cs.SOCKET_ADDRESS_TYPE_UNIX, sock_types) def check_channel_properties(q, bus, conn, channel, channel_type, contact_handle, contact_id, state=None): """ Checks the D-Bus properties of a 1-1 Tubes, StreamTube or DBusTube channel, initiated by the test user """ # Check o.fd.T.Channel properties. channel_props = channel.GetAll(cs.CHANNEL, dbus_interface=cs.PROPERTIES_IFACE) assert channel_props.get('TargetHandle') == contact_handle, \ (channel_props.get('TargetHandle'), contact_handle) assert channel_props.get('TargetHandleType') == cs.HT_CONTACT, \ channel_props.get('TargetHandleType') assert channel_props.get('ChannelType') == channel_type, \ channel_props.get('ChannelType') assert 'Interfaces' in channel_props, channel_props assert cs.CHANNEL_IFACE_GROUP not in \ channel_props['Interfaces'], \ channel_props['Interfaces'] assert channel_props['TargetID'] == contact_id assert channel_props['Requested'] == True assert channel_props['InitiatorID'] == 'test@localhost' assert channel_props['InitiatorHandle'] == conn.GetSelfHandle() if channel_type == cs.CHANNEL_TYPE_TUBES: assert state is None assert len(channel_props['Interfaces']) == 0, channel_props['Interfaces'] supported_socket_types = channel.GetAvailableStreamTubeTypes() else: assert state is not None tube_props = channel.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE) assert tube_props['State'] == state # no strict check but at least check the properties exist assert tube_props['Parameters'] is not None assert channel_props['Interfaces'] == \ dbus.Array([cs.CHANNEL_IFACE_TUBE], signature='s'), \ channel_props['Interfaces'] if channel_type == cs.CHANNEL_TYPE_STREAM_TUBE: supported_socket_types = channel.Get(cs.CHANNEL_TYPE_STREAM_TUBE, 'SupportedSocketTypes', dbus_interface=cs.PROPERTIES_IFACE) else: supported_socket_types = None if supported_socket_types is not None: check_platform_socket_types(supported_socket_types) class Echo(EventProtocol): """ A trivial protocol that just echoes back whatever you send it, in lowercase. """ def __init__(self, queue=None, block_reading=False): EventProtocol.__init__(self, queue, block_reading) self.echoed = True def dataReceived(self, data): EventProtocol.dataReceived(self, data) if self.echoed: self.transport.write(data.lower()) class EchoFactory(EventProtocolFactory): def _create_protocol(self): return Echo(self.queue, self.block_reading) def set_up_echo(q, address_type, block_reading=False, streamfile='stream'): """ Sets up an instance of Echo listening on a socket of type @address_type """ factory = EchoFactory(q, block_reading) return create_server(q, address_type, factory, streamfile=streamfile) # Twisted doesn't set the REUSEADDR option on client sockets. # As we need this option to be able to bind successively on the same port # during the tests, we define our own client and connector to be able to set # this option. class MyTCPClient(tcp.Client): def createInternetSocket(self): s = tcp.Client.createInternetSocket(self) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) return s class MyTCPConnector(tcp.Connector): def _makeTransport(self): return MyTCPClient(self.host, self.port, self.bindAddress, self, self.reactor) def connect_socket(q, address_type, address, access_control, access_control_param): factory = EventProtocolClientFactory(q) if address_type == cs.SOCKET_ADDRESS_TYPE_UNIX: reactor.connectUNIX(address, factory) elif address_type == cs.SOCKET_ADDRESS_TYPE_IPV4: ip, port = address assert port > 0 if access_control == cs.SOCKET_ACCESS_CONTROL_PORT: # connect from the ip/port specified # This means the test will fail if the port is already binded. It # would be better to bind the port before connecting but that's # not easily doable with twisted... c = MyTCPConnector(ip, port, factory, 30, access_control_param, reactor) c.connect() else: reactor.connectTCP(ip, port, factory) else: assert False def create_server(q, address_type, factory=None, block_reading=False, streamfile='stream'): if factory is None: factory = EventProtocolFactory(q, block_reading) if address_type == cs.SOCKET_ADDRESS_TYPE_UNIX: # don't use os.getcwd() here because it can be quite long and # can easily hit the AF_UNIX max path length. path = tempfile.mkstemp(suffix=streamfile)[1] try: os.remove(path) except OSError, e: if e.errno != errno.ENOENT: raise reactor.listenUNIX(path, factory) _to_cleanup.append(path) return dbus.ByteArray(path) elif address_type == cs.SOCKET_ADDRESS_TYPE_IPV4: for port in range(5000,6000): try: reactor.listenTCP(port, factory, interface='localhost') except CannotListenError: continue else: return ('127.0.0.1', dbus.UInt16(port)) else: assert False def check_new_connection_access(q, access_control, access_control_param, protocol): if access_control == cs.SOCKET_ACCESS_CONTROL_LOCALHOST: # nothing to check return elif access_control == cs.SOCKET_ACCESS_CONTROL_PORT: ip, port = access_control_param address = protocol.transport.getPeer() assertEquals(ip, address.host) assertEquals(port, address.port) elif access_control == cs.SOCKET_ACCESS_CONTROL_CREDENTIALS: byte = access_control_param e = q.expect('socket-data', protocol=protocol) assert ord(e.data) == byte # FIXME: check if credentials are actually passed. This is actually # really hard to test because Python doesn't implement recvmsg(). # Twisted's transport abstraction doesn't help either. # Credentials passing is tested in Gibber's tests so not testing it # here is actually not that bad. else: assert False def connect_to_cm_socket(q, to, address_type, address, access_control, access_control_param): connect_socket(q, address_type, address, access_control, access_control_param) if access_control == cs.SOCKET_ACCESS_CONTROL_CREDENTIALS: socket_event = q.expect('socket-connected') # socket is connected. Let's send our credentials (the byte is # meaningless) socket_event.protocol.sendData('a') # once credentials have been sent, Gabble sends SI request si_event, sig = q.expect_many( EventPattern('stream-iq', to=to, query_ns=ns.SI, query_name='si'), EventPattern('dbus-signal', signal='NewLocalConnection')) else: socket_event, si_event, sig = q.expect_many( EventPattern('socket-connected'), # expect SI request EventPattern('stream-iq', to=to, query_ns=ns.SI, query_name='si'), EventPattern('dbus-signal', signal='NewLocalConnection')) connection_id = sig.args[0] assert connection_id != 0 return socket_event, si_event, connection_id def exec_tube_test(test, *args): for bytestream_cls in [ bytestream.BytestreamIBBMsg, bytestream.BytestreamIBBIQ, bytestream.BytestreamS5B, bytestream.BytestreamSIFallbackS5CannotConnect, bytestream.BytestreamSIFallbackS5WrongHash, bytestream.BytestreamS5BRelay, bytestream.BytestreamS5BRelayBugged]: exec_test(lambda q, bus, conn, stream: test(q, bus, conn, stream, bytestream_cls, *args)) def exec_stream_tube_test(test): if os.name == 'posix': exec_tube_test(test, cs.SOCKET_ADDRESS_TYPE_UNIX, cs.SOCKET_ACCESS_CONTROL_LOCALHOST, "") exec_tube_test(test, cs.SOCKET_ADDRESS_TYPE_IPV4, cs.SOCKET_ACCESS_CONTROL_LOCALHOST, "") exec_tube_test(test, cs.SOCKET_ADDRESS_TYPE_IPV4, cs.SOCKET_ACCESS_CONTROL_PORT, ('127.0.0.1', dbus.UInt16(8631))) # we only guarantee to support credentials-passing on Linux if sys.platform == 'linux2': exec_tube_test(test, cs.SOCKET_ADDRESS_TYPE_UNIX, cs.SOCKET_ACCESS_CONTROL_CREDENTIALS, dbus.Byte(77)) def exec_dbus_tube_test(test): exec_tube_test(test, cs.SOCKET_ACCESS_CONTROL_CREDENTIALS) exec_tube_test(test, cs.SOCKET_ACCESS_CONTROL_LOCALHOST) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tubes/check-create-tube-return.py�����������������������������0000664�0001750�0001750�00000005114�12332441362�027310� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" fd.o#25533 demonstrated that if you requested a {dbus,stream} tube channel to a room before you had actually joined the room (i.e. GabbleMucChannel was not ready yet) then the {Create,Request,Ensure}Channel return would be the Tubes channel (there for compatibility reasons), not the Tube channel you requested. """ import dbus from servicetest import call_async, EventPattern, assertContains, assertEquals from gabbletest import exec_test, acknowledge_iq, elem, make_muc_presence import constants as cs import tubetestutil as t from mucutil import join_muc from twisted.words.xish import xpath def test(q, bus, conn, stream): iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, iq_event.stanza) t.check_conn_properties(q, conn) # Create new style tube channel and make sure that is indeed # returned. muc = 'chat@conf.localhost' call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: muc, cs.DBUS_TUBE_SERVICE_NAME: 'com.example.LolDongs'}) q.expect('stream-presence', to='%s/test' % muc) stream.send(make_muc_presence('owner', 'moderator', muc, 'bob')) stream.send(make_muc_presence('none', 'participant', muc, 'test')) ret, _, _ = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('dbus-signal', signal='NewChannel'), EventPattern('dbus-signal', signal='NewChannels'), ) _, props = ret.value assertEquals(props[cs.CHANNEL_TYPE], cs.CHANNEL_TYPE_DBUS_TUBE) assertEquals(props[cs.TARGET_HANDLE_TYPE], cs.HT_ROOM) assertEquals(props[cs.TARGET_ID], muc) # Now try joining the text muc before asking for the tube channel. muc = 'chat2@conf.localhost' join_muc(q, bus, conn, stream, muc) call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: muc, cs.DBUS_TUBE_SERVICE_NAME: 'com.example.LolDongs'}) ret, _, _ = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('dbus-signal', signal='NewChannel'), EventPattern('dbus-signal', signal='NewChannels'), ) _, props = ret.value assertEquals(props[cs.CHANNEL_TYPE], cs.CHANNEL_TYPE_DBUS_TUBE) assertEquals(props[cs.TARGET_HANDLE_TYPE], cs.HT_ROOM) assertEquals(props[cs.TARGET_ID], muc) if __name__ == '__main__': exec_test(test) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tubes/offer-private-dbus-tube.py������������������������������0000664�0001750�0001750�00000020541�12332441362�027162� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""Test D-Bus private tube support""" import dbus from dbus.connection import Connection from dbus.lowlevel import SignalMessage from servicetest import call_async, EventPattern, unwrap, watch_tube_signals,\ assertContains, assertEquals from gabbletest import sync_stream, make_presence import constants as cs import tubetestutil as t from twisted.words.xish import xpath import ns from bytestream import create_from_si_offer, announce_socks5_proxy from caps_helper import send_disco_reply sample_parameters = dbus.Dictionary({ 's': 'hello', 'ay': dbus.ByteArray('hello'), 'u': dbus.UInt32(123), 'i': dbus.Int32(-123), }, signature='sv') def alice_accepts_tube(q, stream, iq_event, dbus_tube_id, bytestream_cls): iq = iq_event.stanza bytestream, profile = create_from_si_offer(stream, q, bytestream_cls, iq, 'test@localhost/Resource') assert profile == ns.TUBES tube_nodes = xpath.queryForNodes('/iq/si/tube[@xmlns="%s"]' % ns.TUBES, iq) assert len(tube_nodes) == 1 tube = tube_nodes[0] tube['type'] = 'dbus' assert tube['initiator'] == 'test@localhost' assert tube['service'] == 'com.example.TestCase' assert tube['id'] == str(dbus_tube_id) params = {} parameter_nodes = xpath.queryForNodes('/tube/parameters/parameter', tube) for node in parameter_nodes: assert node['name'] not in params params[node['name']] = (node['type'], str(node)) assert params == {'ay': ('bytes', 'aGVsbG8='), 's': ('str', 'hello'), 'i': ('int', '-123'), 'u': ('uint', '123'), } # Alice accepts the tube result, si = bytestream.create_si_reply(iq) si.addElement((ns.TUBES, 'tube')) stream.send(result) bytestream.wait_bytestream_open() q.expect('dbus-signal', signal='TubeChannelStateChanged', args=[cs.TUBE_STATE_OPEN]) return bytestream def send_dbus_message_to_alice(q, stream, dbus_tube_adr, bytestream): tube = Connection(dbus_tube_adr) signal = SignalMessage('/', 'foo.bar', 'baz') signal.append(42, signature='u') tube.send_message(signal) binary = bytestream.get_data() # little and big endian versions of: SIGNAL, NO_REPLY, protocol v1, # 4-byte payload assert binary.startswith('l\x04\x01\x01' '\x04\x00\x00\x00') or \ binary.startswith('B\x04\x01\x01' '\x00\x00\x00\x04') # little and big endian versions of the 4-byte payload, UInt32(42) assert (binary[0] == 'l' and binary.endswith('\x2a\x00\x00\x00')) or \ (binary[0] == 'B' and binary.endswith('\x00\x00\x00\x2a')) # XXX: verify that it's actually in the "sender" slot, rather than just # being in the message somewhere watch_tube_signals(q, tube) dbus_message = binary # Have the fake client send us a message all in one go... bytestream.send_data(dbus_message) q.expect('tube-signal', signal='baz', args=[42], tube=tube) # ... and a message one byte at a time ... for byte in dbus_message: bytestream.send_data(byte) q.expect('tube-signal', signal='baz', args=[42], tube=tube) # ... and two messages in one go bytestream.send_data(dbus_message + dbus_message) q.expect('tube-signal', signal='baz', args=[42], tube=tube) q.expect('tube-signal', signal='baz', args=[42], tube=tube) def offer_new_dbus_tube(q, bus, conn, stream, self_handle, alice_handle, bytestream_cls, access_control): # Offer a tube to Alice (new API) def new_chan_predicate(e): types = [] for _, props in e.args[0]: types.append(props[cs.CHANNEL_TYPE]) return cs.CHANNEL_TYPE_DBUS_TUBE in types def find_dbus_tube(channels): for path, props in channels: if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE: return path, props return None, None call_async(q, conn.Requests, 'CreateChannel', {cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: 'alice@localhost', cs.DBUS_TUBE_SERVICE_NAME: 'com.example.TestCase' }, byte_arrays=True) cc_ret, nc = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('dbus-signal', signal='NewChannels', predicate=new_chan_predicate), ) tube_path, tube_props = cc_ret.value _, new_channel_props = find_dbus_tube(nc.args[0]) # check tube channel properties assert tube_props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE assert tube_props[cs.INTERFACES] == [cs.CHANNEL_IFACE_TUBE] assert tube_props[cs.TARGET_HANDLE_TYPE] == cs.HT_CONTACT assert tube_props[cs.TARGET_HANDLE] == alice_handle assert tube_props[cs.TARGET_ID] == 'alice@localhost' assert tube_props[cs.REQUESTED] == True assert tube_props[cs.INITIATOR_HANDLE] == self_handle assert tube_props[cs.INITIATOR_ID] == "test@localhost" assert tube_props[cs.DBUS_TUBE_SERVICE_NAME] == 'com.example.TestCase' assert tube_props[cs.DBUS_TUBE_SUPPORTED_ACCESS_CONTROLS] == [cs.SOCKET_ACCESS_CONTROL_CREDENTIALS, cs.SOCKET_ACCESS_CONTROL_LOCALHOST] assert cs.DBUS_TUBE_DBUS_NAMES not in tube_props assert cs.TUBE_PARAMETERS not in tube_props assert cs.TUBE_STATE not in tube_props # get the list of all channels to check that newly announced ones are in it all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, 'Channels', dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) for path, props in nc.args[0]: assertContains((path, props), all_channels) assertEquals(tube_props, new_channel_props) tube_chan = bus.get_object(conn.bus_name, tube_path) tube_chan_iface = dbus.Interface(tube_chan, cs.CHANNEL) dbus_tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_DBUS_TUBE) # check State and Parameters props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assert props['State'] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED # check ServiceName and DBusNames props = tube_chan.GetAll(cs.CHANNEL_TYPE_DBUS_TUBE, dbus_interface=cs.PROPERTIES_IFACE) assert props['ServiceName'] == 'com.example.TestCase' assert props['DBusNames'] == {} # Only when we offer the tube should it appear on the Tubes channel and an # IQ be sent to Alice. We sync the stream to ensure the IQ would have # arrived if it had been sent. sync_stream(q, stream) call_async(q, dbus_tube_iface, 'Offer', sample_parameters, access_control) offer_return_event, iq_event, state_event = q.expect_many( EventPattern('dbus-return', method='Offer'), EventPattern('stream-iq', to='alice@localhost/Test'), EventPattern('dbus-signal', signal='TubeChannelStateChanged'), ) tube_address = offer_return_event.value[0] assert len(tube_address) > 0 assert state_event.args[0] == cs.TUBE_CHANNEL_STATE_REMOTE_PENDING status = tube_chan.Get(cs.CHANNEL_IFACE_TUBE, 'State', dbus_interface=cs.PROPERTIES_IFACE) assert status == cs.TUBE_STATE_REMOTE_PENDING tube_chan_iface.Close() q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed')) def test(q, bus, conn, stream, bytestream_cls, access_control): disco_event = q.expect('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS) announce_socks5_proxy(q, stream, disco_event.stanza) t.check_conn_properties(q, conn) self_handle = conn.GetSelfHandle() alice_handle = conn.RequestHandles(cs.HT_CONTACT, ["alice@localhost"])[0] # send Alice's presence caps = { 'ext': '', 'ver': '0.0.0', 'node': 'http://example.com/fake-client0' } presence = make_presence('alice@localhost/Test', caps=caps) stream.send(presence) _, disco_event = q.expect_many( EventPattern('dbus-signal', signal='PresencesChanged', args = [{alice_handle: (2L, u'available', u'')}]), EventPattern('stream-iq', to='alice@localhost/Test', query_ns=ns.DISCO_INFO), ) # reply to disco query send_disco_reply(stream, disco_event.stanza, [], [ns.TUBES]) sync_stream(q, stream) offer_new_dbus_tube(q, bus, conn, stream, self_handle, alice_handle, bytestream_cls, access_control) if __name__ == '__main__': t.exec_dbus_tube_test(test) ���������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tubes/accept-private-stream-tube.py���������������������������0000664�0001750�0001750�00000015335�12332440117�027660� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Receives several tube offers: - Test to accept a 1-1 stream tube - using UNIX sockets and IPv4 sockets - using the old tube iface and the new tube iface - Test to accept with bad parameters - Test to refuse the tube offer - using the old tube iface and the new tube iface """ import dbus from servicetest import call_async, EventPattern, sync_dbus, assertEquals from gabbletest import acknowledge_iq, send_error_reply, make_result_iq from twisted.words.xish import domish, xpath from twisted.internet import reactor import ns import constants as cs from bytestream import create_from_si_offer, announce_socks5_proxy import tubetestutil as t bob_jid = 'bob@localhost/Bob' stream_tube_id = 49 def receive_tube_offer(q, bus, conn, stream): global stream_tube_id message = domish.Element(('jabber:client', 'message')) message['to'] = 'test@localhost/Resource' message['from'] = bob_jid tube_node = message.addElement((ns.TUBES, 'tube')) tube_node['type'] = 'stream' tube_node['service'] = 'http' stream_tube_id += 1 tube_node['id'] = str(stream_tube_id) stream.send(message) def new_chan_predicate(e): path, props = e.args[0][0] return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE new_sig = q.expect('dbus-signal', signal='NewChannels', predicate=new_chan_predicate) assert len(new_sig.args) == 1 assert len(new_sig.args[0]) == 1 path, props = new_sig.args[0][0] assertEquals(cs.CHANNEL_TYPE_STREAM_TUBE, props[cs.CHANNEL_TYPE]) assertEquals(cs.HT_CONTACT, props[cs.TARGET_HANDLE_TYPE]) assertEquals(False, props[cs.REQUESTED]) # create channel proxies new_tube_chan = bus.get_object(conn.bus_name, path) new_tube_iface = dbus.Interface(new_tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE) return (new_tube_chan, new_tube_iface) def expect_tube_activity(q, bus, conn, stream, bytestream_cls, address_type, address, access_control, access_control_param): event_socket, event_iq, conn_id = t.connect_to_cm_socket(q, bob_jid, address_type, address, access_control, access_control_param) protocol = event_socket.protocol data = "hello initiator" protocol.sendData(data) bytestream, profile = create_from_si_offer(stream, q, bytestream_cls, event_iq.stanza, 'test@localhost/Resource') assert profile == ns.TUBES stream_node = xpath.queryForNodes('/iq/si/stream[@xmlns="%s"]' % ns.TUBES, event_iq.stanza)[0] assert stream_node is not None assert stream_node['tube'] == str(stream_tube_id) result, si = bytestream.create_si_reply(event_iq.stanza) si.addElement((ns.TUBES, 'tube')) stream.send(result) bytestream.wait_bytestream_open() binary = bytestream.get_data(len(data)) assert data == binary, binary # reply to the initiator bytestream.send_data('hello joiner') e = q.expect('socket-data') assert e.data == 'hello joiner' return bytestream, conn_id def test(q, bus, conn, stream, bytestream_cls, address_type, access_control, access_control_param): if access_control == cs.SOCKET_ACCESS_CONTROL_CREDENTIALS: print "Skip Socket_Access_Control_Credentials (fdo #45445)" return vcard_event, roster_event, disco_event = q.expect_many( EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', query_ns=ns.ROSTER), EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS)) acknowledge_iq(stream, vcard_event.stanza) announce_socks5_proxy(q, stream, disco_event.stanza) roster = roster_event.stanza roster['type'] = 'result' item = roster_event.query.addElement('item') item['jid'] = 'bob@localhost' # Bob can do tubes item['subscription'] = 'both' stream.send(roster) # Send Bob presence and his caps presence = domish.Element(('jabber:client', 'presence')) presence['from'] = 'bob@localhost/Bob' presence['to'] = 'test@localhost/Resource' c = presence.addElement('c') c['xmlns'] = 'http://jabber.org/protocol/caps' c['node'] = 'http://example.com/ICantBelieveItsNotTelepathy' c['ver'] = '1.2.3' stream.send(presence) event = q.expect('stream-iq', iq_type='get', query_ns='http://jabber.org/protocol/disco#info', to='bob@localhost/Bob') assert event.query['node'] == \ 'http://example.com/ICantBelieveItsNotTelepathy#1.2.3' result = make_result_iq(stream, event.stanza) query = result.firstChildElement() feature = query.addElement('feature') feature['var'] = ns.TUBES stream.send(result) sync_dbus(bus, q, conn) # Receive a tube offer from Bob (new_tube_chan, new_tube_iface) = \ receive_tube_offer(q, bus, conn, stream) # Try bad parameters on the new iface call_async(q, new_tube_iface, 'Accept', 20, 0, '', byte_arrays=True) q.expect('dbus-error', method='Accept') call_async(q, new_tube_iface, 'Accept', 0, 1, '', byte_arrays=True) q.expect('dbus-error', method='Accept') # Receive a tube offer from Bob (new_tube_chan, new_tube_iface) = \ receive_tube_offer(q, bus, conn, stream) # Accept the tube with new iface, and use UNIX sockets call_async(q, new_tube_iface, 'Accept', address_type, access_control, access_control_param, byte_arrays=True) accept_return_event, _ = q.expect_many( EventPattern('dbus-return', method='Accept'), EventPattern('dbus-signal', signal='TubeChannelStateChanged', args=[2])) socket_address = accept_return_event.value[0] bytestream, conn_id = expect_tube_activity(q, bus, conn, stream, bytestream_cls, address_type, socket_address, access_control, access_control_param) # peer closes the bytestream bytestream.close() e = q.expect('dbus-signal', signal='ConnectionClosed') assertEquals(conn_id, e.args[0]) assertEquals(cs.CONNECTION_LOST, e.args[1]) # establish another tube connection event_socket, si_event, conn_id = t.connect_to_cm_socket(q, bob_jid, address_type, socket_address, access_control, access_control_param) # bytestream is refused send_error_reply(stream, si_event.stanza) e = q.expect('dbus-signal', signal='ConnectionClosed') assertEquals(conn_id, e.args[0]) assertEquals(cs.CONNECTION_REFUSED, e.args[1]) new_tube_chan.Close() # Receive a tube offer from Bob (new_tube_chan, new_tube_iface) = \ receive_tube_offer(q, bus, conn, stream) # Just close the tube new_tube_chan.Close() q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed')) if __name__ == '__main__': t.exec_stream_tube_test(test) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tubes/create-invalid-tube-channels.py�������������������������0000644�0001750�0001750�00000002763�12225363340�030142� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Check that Gabble rejects invalid requests for tubes channels. """ import dbus from servicetest import call_async from gabbletest import exec_test import constants as cs def is_tube(path, props): ct = props[cs.CHANNEL_TYPE] return ct in [cs.CHANNEL_TYPE_STREAM_TUBE, cs.CHANNEL_TYPE_DBUS_TUBE] def check_no_tubes(conn_props): channels = conn_props.Get(cs.CONN_IFACE_REQUESTS, 'Channels') tube_channels = filter(is_tube, channels) assert len(tube_channels) == 0, tube_channels def test(q, bus, conn, stream): conn_props = dbus.Interface(conn, cs.PROPERTIES_IFACE) # Try to CreateChannel with unknown properties # Gabble must return an error call_async(q, conn.Requests, 'CreateChannel', {cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: "foo@example.com", 'this.property.does.not.exist': 'this.value.should.not.exist' }) ret = q.expect('dbus-error', method='CreateChannel') check_no_tubes(conn_props) # Try to CreateChannel with missing properties ("Service") # Gabble must return an error call_async(q, conn.Requests, 'CreateChannel', {cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: "foo@example.com", }) ret = q.expect('dbus-error', method='CreateChannel') check_no_tubes(conn_props) if __name__ == '__main__': exec_test(test) �������������telepathy-gabble-0.18.3/tests/twisted/tubes/accept-muc-dbus-tube.py���������������������������������0000664�0001750�0001750�00000011363�12332441362�026434� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import dbus from servicetest import ( assertEquals, assertNotEquals, assertSameSets, call_async, EventPattern, ) from gabbletest import exec_test, acknowledge_iq, make_muc_presence import constants as cs from twisted.words.xish import xpath import ns from mucutil import join_muc_and_check def test(q, bus, conn, stream, access_control): iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, iq_event.stanza) muc = 'chat@conf.localhost' _, _, test_handle, bob_handle = \ join_muc_and_check(q, bus, conn, stream, muc) # Bob offers a stream tube bob_bus_name = ':2.Ym9i' presence = make_muc_presence('owner', 'moderator', 'chat@conf.localhost', 'bob') tubes = presence.addElement((ns.TUBES, 'tubes')) tube = tubes.addElement((None, 'tube')) tube['type'] = 'dbus' tube['initiator'] = 'chat@conf.localhost/bob' tube['stream-id'] = '10' tube['id'] = '1' tube['service'] = 'com.example.Test' tube['dbus-name'] = bob_bus_name parameters = tube.addElement((None, 'parameters')) parameter = parameters.addElement((None, 'parameter')) parameter['type'] = 'str' parameter['name'] = 'foo' parameter.addContent('bar') stream.send(presence) # tube channel is created def new_chan_predicate(e): path, props = e.args[0][0] return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE event = q.expect('dbus-signal', signal='NewChannels', predicate=new_chan_predicate) channels = event.args[0] path, props = channels[0] assertEquals(cs.CHANNEL_TYPE_DBUS_TUBE, props[cs.CHANNEL_TYPE]) assertEquals('chat@conf.localhost/bob', props[cs.INITIATOR_ID]) bob_handle = props[cs.INITIATOR_HANDLE] assertSameSets([cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE], props[cs.INTERFACES]) assertEquals(False, props[cs.REQUESTED]) assertEquals('chat@conf.localhost', props[cs.TARGET_ID]) assertEquals('com.example.Test', props[cs.DBUS_TUBE_SERVICE_NAME]) assertEquals({'foo': 'bar'}, props[cs.TUBE_PARAMETERS]) assertEquals([cs.SOCKET_ACCESS_CONTROL_CREDENTIALS, cs.SOCKET_ACCESS_CONTROL_LOCALHOST], props[cs.DBUS_TUBE_SUPPORTED_ACCESS_CONTROLS]) tube_chan = bus.get_object(conn.bus_name, path) tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_IFACE_TUBE) dbus_tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_DBUS_TUBE) tube_chan_iface = dbus.Interface(tube_chan, cs.CHANNEL) # only Bob is in DBusNames dbus_names = tube_chan.Get(cs.CHANNEL_TYPE_DBUS_TUBE, 'DBusNames', dbus_interface=cs.PROPERTIES_IFACE) assertEquals({bob_handle: bob_bus_name}, dbus_names) call_async(q, dbus_tube_iface, 'Accept', access_control) return_event, names_changed1, names_changed2, presence_event = q.expect_many( EventPattern('dbus-return', method='Accept'), EventPattern('dbus-signal', signal='DBusNamesChanged', interface=cs.CHANNEL_TYPE_DBUS_TUBE), EventPattern('dbus-signal', signal='DBusNamesChanged', interface=cs.CHANNEL_TYPE_DBUS_TUBE), EventPattern('stream-presence', to='chat@conf.localhost/test')) tube_addr = return_event.value[0] assert len(tube_addr) > 0 # check presence stanza tube_node = xpath.queryForNodes('/presence/tubes/tube', presence_event.stanza)[0] assertEquals('chat@conf.localhost/bob', tube_node['initiator']) assertEquals('com.example.Test', tube_node['service']) assertEquals('10', tube_node['stream-id']) assertEquals('dbus', tube_node['type']) assertEquals('1', tube_node['id']) self_bus_name = tube_node['dbus-name'] tubes_self_handle = tube_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP) assertNotEquals(0, tubes_self_handle) # both of us are in DBusNames now dbus_names = tube_chan.Get(cs.CHANNEL_TYPE_DBUS_TUBE, 'DBusNames', dbus_interface=cs.PROPERTIES_IFACE) assertEquals({bob_handle: bob_bus_name, tubes_self_handle: self_bus_name}, dbus_names) added, removed = names_changed1.args assertEquals({bob_handle: bob_bus_name}, added) assertEquals([], removed) added, removed = names_changed2.args assertEquals({tubes_self_handle: self_bus_name}, added) assertEquals([], removed) tube_chan_iface.Close() q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed')) if __name__ == '__main__': # We can't use t.exec_dbus_tube_test() as we can use only the muc bytestream exec_test(lambda q, bus, conn, stream: test(q, bus, conn, stream, cs.SOCKET_ACCESS_CONTROL_CREDENTIALS)) exec_test(lambda q, bus, conn, stream: test(q, bus, conn, stream, cs.SOCKET_ACCESS_CONTROL_LOCALHOST)) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tubes/ensure-si-tube.py���������������������������������������0000664�0001750�0001750�00000010715�12332441362�025372� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test support for creating and retrieving 1-1 tubes with EnsureChannel """ import dbus from servicetest import call_async, EventPattern, tp_name_prefix, unwrap from gabbletest import exec_test, acknowledge_iq import constants as cs import ns from twisted.words.xish import domish import tubetestutil as t sample_parameters = dbus.Dictionary({ 's': 'hello', 'ay': dbus.ByteArray('hello'), 'u': dbus.UInt32(123), 'i': dbus.Int32(-123), }, signature='sv') def test(q, bus, conn, stream): conn.Connect() properties = conn.GetAll( cs.CONN_IFACE_REQUESTS, dbus_interface=cs.PROPERTIES_IFACE) assert properties.get('Channels') == [], properties['Channels'] assert ({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, }, [cs.TARGET_HANDLE, cs.TARGET_ID, cs.STREAM_TUBE_SERVICE] ) in properties.get('RequestableChannelClasses'),\ unwrap(properties['RequestableChannelClasses']) _, vcard_event, roster_event = q.expect_many( EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]), EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', query_ns=ns.ROSTER)) acknowledge_iq(stream, vcard_event.stanza) roster = roster_event.stanza roster['type'] = 'result' item = roster_event.query.addElement('item') item['jid'] = 'bob@localhost' item['subscription'] = 'both' stream.send(roster) presence = domish.Element(('jabber:client', 'presence')) presence['from'] = 'bob@localhost/Bob' presence['to'] = 'test@localhost/Resource' c = presence.addElement('c') c['xmlns'] = 'http://jabber.org/protocol/caps' c['node'] = 'http://example.com/ICantBelieveItsNotTelepathy' c['ver'] = '1.2.3' stream.send(presence) event = q.expect('stream-iq', iq_type='get', query_ns='http://jabber.org/protocol/disco#info', to='bob@localhost/Bob') result = event.stanza result['type'] = 'result' assert event.query['node'] == \ 'http://example.com/ICantBelieveItsNotTelepathy#1.2.3' feature = event.query.addElement('feature') feature['var'] = ns.TUBES stream.send(result) bob_handle = conn.RequestHandles(1, ['bob@localhost'])[0] def new_chan_predicate(e): types = [] for _, props in e.args[0]: types.append(props[cs.CHANNEL_TYPE]) return cs.CHANNEL_TYPE_STREAM_TUBE in types call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: bob_handle, cs.STREAM_TUBE_SERVICE: 'the.service', }) ret, _ = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('dbus-signal', signal='NewChannels', predicate=new_chan_predicate), ) chan_path, props = ret.value # Ensure a tube to the same person; check it's the same one. # call_async(q, conn.Requests, 'EnsureChannel', # { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, # cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, # cs.TARGET_HANDLE: bob_handle, # cs.STREAM_TUBE_SERVICE: 'the.service', # }) # ret = q.expect('dbus-return', method='EnsureChannel') # yours, ensured_path, _ = ret.value # assert ensured_path == chan_path, (ensured_path, chan_path) # assert not yours chan = bus.get_object(conn.bus_name, chan_path) chan.Close() # Now let's try ensuring a new tube. call_async(q, conn.Requests, 'EnsureChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: bob_handle, cs.STREAM_TUBE_SERVICE: 'the.service', }) ret, new_sig = q.expect_many( EventPattern('dbus-return', method='EnsureChannel'), EventPattern('dbus-signal', signal='NewChannels', predicate=new_chan_predicate), ) yours, path, props = ret.value assert yours emitted_props = new_sig.args[0][0][1] assert props == emitted_props, (props, emitted_props) chan = bus.get_object(conn.bus_name, path) chan.Close() if __name__ == '__main__': exec_test(test, do_connect=False) ���������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tubes/offer-muc-dbus-tube.py����������������������������������0000664�0001750�0001750�00000027571�12332441362�026306� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""Test IBB tube support in the context of a MUC.""" import base64 import dbus from dbus.connection import Connection from dbus.lowlevel import SignalMessage from servicetest import call_async, EventPattern, assertContains, assertEquals from gabbletest import exec_test, acknowledge_iq, elem, make_muc_presence, sync_stream import ns import constants as cs import tubetestutil as t from twisted.words.xish import xpath from mucutil import join_muc, echo_muc_presence sample_parameters = dbus.Dictionary({ 's': 'hello', 'ay': dbus.ByteArray('hello'), 'u': dbus.UInt32(123), 'i': dbus.Int32(-123), }, signature='sv') def check_tube_in_presence(presence, initiator): tubes_nodes = xpath.queryForNodes('/presence/tubes[@xmlns="%s"]' % ns.TUBES, presence) assert tubes_nodes is not None assert len(tubes_nodes) == 1 tube_nodes = xpath.queryForNodes('/tubes/tube', tubes_nodes[0]) assert tube_nodes is not None assert len(tube_nodes) == 1 for tube in tube_nodes: tube['type'] = 'dbus' assert tube['initiator'] == initiator assert tube['service'] == 'com.example.TestCase' dbus_stream_id = tube['stream-id'] my_bus_name = tube['dbus-name'] dbus_tube_id = tube['id'] params = {} parameter_nodes = xpath.queryForNodes('/tube/parameters/parameter', tube) for node in parameter_nodes: assert node['name'] not in params params[node['name']] = (node['type'], str(node)) assert params == {'ay': ('bytes', 'aGVsbG8='), 's': ('str', 'hello'), 'i': ('int', '-123'), 'u': ('uint', '123'), } return dbus_stream_id, my_bus_name, dbus_tube_id def fire_signal_on_tube(q, tube, chatroom, dbus_stream_id, my_bus_name): signal = SignalMessage('/', 'foo.bar', 'baz') signal.append(42, signature='u') tube.send_message(signal) event = q.expect('stream-message', to=chatroom, message_type='groupchat') message = event.stanza data_nodes = xpath.queryForNodes('/message/data[@xmlns="%s"]' % ns.MUC_BYTESTREAM, message) assert data_nodes is not None assert len(data_nodes) == 1 ibb_data = data_nodes[0] assert ibb_data['sid'] == dbus_stream_id binary = base64.b64decode(str(ibb_data)) # little and big endian versions of: SIGNAL, NO_REPLY, protocol v1, # 4-byte payload assert binary.startswith('l\x04\x01\x01' '\x04\x00\x00\x00') or \ binary.startswith('B\x04\x01\x01' '\x00\x00\x00\x04') # little and big endian versions of the 4-byte payload, UInt32(42) assert (binary[0] == 'l' and binary.endswith('\x2a\x00\x00\x00')) or \ (binary[0] == 'B' and binary.endswith('\x00\x00\x00\x2a')) # XXX: verify that it's actually in the "sender" slot, rather than just # being in the message somewhere assert my_bus_name in binary # Send another big signal which has to be split on 3 stanzas signal = SignalMessage('/', 'foo.bar', 'baz') signal.append('a' * 100000, signature='s') tube.send_message(signal) def wait_for_data(q): event = q.expect('stream-message', to=chatroom, message_type='groupchat') data_nodes = xpath.queryForNodes('/message/data[@xmlns="%s"]' % ns.MUC_BYTESTREAM, event.stanza) ibb_data = data_nodes[0] return ibb_data['frag'] frag = wait_for_data(q) assertEquals(frag, 'first') frag = wait_for_data(q) assertEquals(frag, 'middle') frag = wait_for_data(q) assertEquals(frag, 'last') def test(q, bus, conn, stream, access_control): iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, iq_event.stanza) # check if we can request muc D-Bus tube t.check_conn_properties(q, conn) self_handle = conn.GetSelfHandle() self_name = conn.InspectHandles(1, [self_handle])[0] # offer a D-Bus tube to another room using new API muc = 'chat2@conf.localhost' request = { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: 'chat2@conf.localhost', cs.DBUS_TUBE_SERVICE_NAME: 'com.example.TestCase', } join_muc(q, bus, conn, stream, muc, request=request) e = q.expect('dbus-signal', signal='NewChannels') channels = e.args[0] assert len(channels) == 1 path, prop = channels[0] assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE assert prop[cs.INITIATOR_ID] == 'chat2@conf.localhost/test' assert prop[cs.REQUESTED] == True assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM assert prop[cs.TARGET_ID] == 'chat2@conf.localhost' assert prop[cs.DBUS_TUBE_SERVICE_NAME] == 'com.example.TestCase' assert prop[cs.DBUS_TUBE_SUPPORTED_ACCESS_CONTROLS] == [cs.SOCKET_ACCESS_CONTROL_CREDENTIALS, cs.SOCKET_ACCESS_CONTROL_LOCALHOST] # check that the tube channel is in the channels list all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, 'Channels', dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assertContains((path, prop), all_channels) tube_chan = bus.get_object(conn.bus_name, path) dbus_tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_DBUS_TUBE) chan_iface = dbus.Interface(tube_chan, cs.CHANNEL) tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED # try to offer using a wrong access control try: dbus_tube_iface.Offer(sample_parameters, cs.SOCKET_ACCESS_CONTROL_PORT) except dbus.DBusException, e: assertEquals(e.get_dbus_name(), cs.INVALID_ARGUMENT) else: assert False # offer the tube call_async(q, dbus_tube_iface, 'Offer', sample_parameters, access_control) presence_event, return_event, status_event, dbus_changed_event = q.expect_many( EventPattern('stream-presence', to='chat2@conf.localhost/test'), EventPattern('dbus-return', method='Offer'), EventPattern('dbus-signal', signal='TubeChannelStateChanged', args=[cs.TUBE_CHANNEL_STATE_OPEN]), EventPattern('dbus-signal', signal='DBusNamesChanged', interface=cs.CHANNEL_TYPE_DBUS_TUBE)) tube_self_handle = tube_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP) assert tube_self_handle != 0 # handle presence_event # We announce our newly created tube in our muc presence presence = presence_event.stanza dbus_stream_id, my_bus_name, dbus_tube_id = check_tube_in_presence(presence, 'chat2@conf.localhost/test') # handle dbus_changed_event added, removed = dbus_changed_event.args assert added == {tube_self_handle: my_bus_name} assert removed == [] dbus_tube_adr = return_event.value[0] bob_bus_name = ':2.Ym9i' bob_handle = conn.RequestHandles(cs.HT_CONTACT, ['chat2@conf.localhost/bob'])[0] def bob_in_tube(): presence = elem('presence', from_='chat2@conf.localhost/bob', to='chat2@conf.localhost')( elem('x', xmlns=ns.MUC_USER), elem('tubes', xmlns=ns.TUBES)( elem('tube', type='dbus', initiator='chat2@conf.localhost/test', service='com.example.TestCase', id=str(dbus_tube_id))( elem('parameters')( elem('parameter', name='ay', type='bytes')(u'aGVsbG8='), elem('parameter', name='s', type='str')(u'hello'), elem('parameter', name='i', type='int')(u'-123'), elem('parameter', name='u', type='uint')(u'123') )))) # have to add stream-id and dbus-name attributes manually as we can't use # keyword with '-'... tube_node = xpath.queryForNodes('/presence/tubes/tube', presence)[0] tube_node['stream-id'] = dbus_stream_id tube_node['dbus-name'] = bob_bus_name stream.send(presence) # Bob joins the tube bob_in_tube() dbus_changed_event = q.expect('dbus-signal', signal='DBusNamesChanged', interface=cs.CHANNEL_TYPE_DBUS_TUBE) added, removed = dbus_changed_event.args assert added == {bob_handle: bob_bus_name} assert removed == [] tube = Connection(dbus_tube_adr) fire_signal_on_tube(q, tube, 'chat2@conf.localhost', dbus_stream_id, my_bus_name) names = tube_chan.Get(cs.CHANNEL_TYPE_DBUS_TUBE, 'DBusNames', dbus_interface=cs.PROPERTIES_IFACE) assert names == {tube_self_handle: my_bus_name, bob_handle: bob_bus_name} # Bob leave the tube presence = elem('presence', from_='chat2@conf.localhost/bob', to='chat2@conf.localhost')( elem('x', xmlns=ns.MUC_USER), elem('tubes', xmlns=ns.TUBES)) stream.send(presence) dbus_changed_event = q.expect('dbus-signal', signal='DBusNamesChanged', interface=cs.CHANNEL_TYPE_DBUS_TUBE) added, removed = dbus_changed_event.args assert added == {} assert removed == [bob_handle] names = tube_chan.Get(cs.CHANNEL_TYPE_DBUS_TUBE, 'DBusNames', dbus_interface=cs.PROPERTIES_IFACE) assert names == {tube_self_handle: my_bus_name} chan_iface.Close() _, _, event = q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed'), EventPattern('stream-presence', to='chat2@conf.localhost/test', presence_type='unavailable')) # we must echo the MUC presence so the room will actually close # and we should wait to make sure gabble has actually parsed our # echo before trying to rejoin echo_muc_presence(q, stream, event.stanza, 'none', 'participant') sync_stream(q, stream) # rejoin the room call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: 'chat2@conf.localhost' }) q.expect('stream-presence', to='chat2@conf.localhost/test') # Bob is in the room and in the tube bob_in_tube() # Send presence for own membership of room. stream.send(make_muc_presence('none', 'participant', muc, 'test')) def new_tube(e): path, props = e.args[0][0] return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE def new_text(e): path, props = e.args[0][0] return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT # tube and text is created text_event, tube_event = q.expect_many(EventPattern('dbus-signal', signal='NewChannels', predicate=new_text), EventPattern('dbus-signal', signal='NewChannels', predicate=new_tube)) channels = e.args[0] tube_path, props = tube_event.args[0][0] assertEquals(cs.CHANNEL_TYPE_DBUS_TUBE, props[cs.CHANNEL_TYPE]) assertEquals('chat2@conf.localhost/test', props[cs.INITIATOR_ID]) assertEquals(False, props[cs.REQUESTED]) assertEquals(cs.HT_ROOM, props[cs.TARGET_HANDLE_TYPE]) assertEquals('com.example.TestCase', props[cs.DBUS_TUBE_SERVICE_NAME]) _, props = text_event.args[0][0] assertEquals(cs.CHANNEL_TYPE_TEXT, props[cs.CHANNEL_TYPE]) assertEquals(True, props[cs.REQUESTED]) # tube is local-pending tube_chan = bus.get_object(conn.bus_name, tube_path) state = tube_chan.Get(cs.CHANNEL_IFACE_TUBE, 'State', dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(cs.TUBE_STATE_LOCAL_PENDING, state) if __name__ == '__main__': # We can't use t.exec_dbus_tube_test() as we can use only the muc bytestream exec_test(lambda q, bus, conn, stream: test(q, bus, conn, stream, cs.SOCKET_ACCESS_CONTROL_CREDENTIALS)) exec_test(lambda q, bus, conn, stream: test(q, bus, conn, stream, cs.SOCKET_ACCESS_CONTROL_LOCALHOST)) ���������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tubes/accept-private-dbus-tube.py�����������������������������0000664�0001750�0001750�00000012677�12332441362�027333� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""Test 1-1 tubes support.""" import dbus from servicetest import call_async, EventPattern, sync_dbus, assertEquals from gabbletest import acknowledge_iq, sync_stream import constants as cs import ns import tubetestutil as t from twisted.words.xish import domish, xpath last_tube_id = 69 def contact_offer_dbus_tube(bytestream, tube_id): iq, si = bytestream.create_si_offer(ns.TUBES) tube = si.addElement((ns.TUBES, 'tube')) tube['type'] = 'dbus' tube['service'] = 'com.example.TestCase2' tube['id'] = str(tube_id) parameters = tube.addElement((None, 'parameters')) parameter = parameters.addElement((None, 'parameter')) parameter['type'] = 'str' parameter['name'] = 'login' parameter.addContent('TEST') bytestream.stream.send(iq) def test(q, bus, conn, stream, bytestream_cls, access_control): global last_tube_id t.check_conn_properties(q, conn) vcard_event, roster_event = q.expect_many( EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', query_ns=ns.ROSTER)) self_handle = conn.GetSelfHandle() acknowledge_iq(stream, vcard_event.stanza) roster = roster_event.stanza roster['type'] = 'result' item = roster_event.query.addElement('item') item['jid'] = 'bob@localhost' # Bob can do tubes item['subscription'] = 'both' stream.send(roster) bob_full_jid = 'bob@localhost/Bob' self_full_jid = 'test@localhost/Resource' # Send Bob presence and his tube caps presence = domish.Element(('jabber:client', 'presence')) presence['from'] = bob_full_jid presence['to'] = self_full_jid c = presence.addElement('c') c['xmlns'] = 'http://jabber.org/protocol/caps' c['node'] = 'http://example.com/ICantBelieveItsNotTelepathy' c['ver'] = '1.2.3' stream.send(presence) event = q.expect('stream-iq', iq_type='get', query_ns='http://jabber.org/protocol/disco#info', to=bob_full_jid) result = event.stanza result['type'] = 'result' assert event.query['node'] == \ 'http://example.com/ICantBelieveItsNotTelepathy#1.2.3' feature = event.query.addElement('feature') feature['var'] = ns.TUBES stream.send(result) # A tube request can be done only if the contact has tube capabilities # Ensure that Bob's caps have been received sync_stream(q, stream) # Also ensure that all the new contact list channels have been announced, # so that the NewChannel(s) signals we look for after calling # RequestChannel are the ones we wanted. sync_dbus(bus, q, conn) bob_handle = conn.RequestHandles(cs.HT_CONTACT, ['bob@localhost'])[0] # let's try to accept a D-Bus tube using the new API bytestream = bytestream_cls(stream, q, 'gamma', bob_full_jid, self_full_jid, True) last_tube_id += 1 contact_offer_dbus_tube(bytestream, last_tube_id) def new_chan_predicate(e): path, props = e.args[0][0] return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE e = q.expect('dbus-signal', signal='NewChannels', predicate=new_chan_predicate) channels = e.args[0] assert len(channels) == 1 path, props = channels[0] assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE assert props[cs.INITIATOR_HANDLE] == bob_handle assert props[cs.INITIATOR_ID] == 'bob@localhost' assert props[cs.INTERFACES] == [cs.CHANNEL_IFACE_TUBE] assert props[cs.REQUESTED] == False assert props[cs.TARGET_HANDLE] == bob_handle assert props[cs.TARGET_ID] == 'bob@localhost' assert props[cs.DBUS_TUBE_SERVICE_NAME] == 'com.example.TestCase2' assert props[cs.TUBE_PARAMETERS] == {'login': 'TEST'} assert props[cs.DBUS_TUBE_SUPPORTED_ACCESS_CONTROLS] == [cs.SOCKET_ACCESS_CONTROL_CREDENTIALS, cs.SOCKET_ACCESS_CONTROL_LOCALHOST] assert cs.TUBE_STATE not in props tube_chan = bus.get_object(conn.bus_name, path) tube_chan_iface = dbus.Interface(tube_chan, cs.CHANNEL) dbus_tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_DBUS_TUBE) status = tube_chan.Get(cs.CHANNEL_IFACE_TUBE, 'State', dbus_interface=cs.PROPERTIES_IFACE) assert status == cs.TUBE_STATE_LOCAL_PENDING # try to accept using a wrong access control try: dbus_tube_iface.Accept(cs.SOCKET_ACCESS_CONTROL_PORT) except dbus.DBusException, e: assertEquals(e.get_dbus_name(), cs.INVALID_ARGUMENT) else: assert False # accept the tube (new API) call_async(q, dbus_tube_iface, 'Accept', access_control) events = q.expect_many (EventPattern('stream-iq', iq_type='result', query_ns=ns.SI), EventPattern('dbus-return', method='Accept')) iq_event = events[0] bytestream.check_si_reply(iq_event.stanza) tube = xpath.queryForNodes('/iq/si/tube[@xmlns="%s"]' % ns.TUBES, iq_event.stanza) assert len(tube) == 1 return_event = events[1] addr = return_event.value[0] assert len(addr) > 0 # Open the bytestream _, state_event = bytestream.open_bytestream([], [EventPattern('dbus-signal', signal='TubeChannelStateChanged', path=path)]) state_event = state_event[0] assert state_event.args[0] == cs.TUBE_STATE_OPEN # close the tube tube_chan_iface.Close() q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed')) if __name__ == '__main__': t.exec_dbus_tube_test(test) �����������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tubes/offer-no-caps.py����������������������������������������0000664�0001750�0001750�00000006433�12225363340�025164� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test that offering a tube to a contact without tube capabilities fails appropriately. """ import dbus from twisted.words.xish import domish from servicetest import EventPattern, make_channel_proxy, call_async from gabbletest import exec_test, acknowledge_iq, sync_stream import constants as cs import tubetestutil as t import ns def props(ct, extra=None): ret = { cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: 'joe@localhost', cs.CHANNEL_TYPE: ct, } if extra is not None: ret.update(extra) return ret def test(q, bus, conn, stream): vcard_event, roster_event = q.expect_many( EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', query_ns=ns.ROSTER)) acknowledge_iq(stream, vcard_event.stanza) # Send a roster with one member, Joe. roster = roster_event.stanza roster['type'] = 'result' item = roster_event.query.addElement('item') item['jid'] = 'joe@localhost' item['subscription'] = 'both' stream.send(roster) # Send Joe's presence. presence = domish.Element(('jabber:client', 'presence')) presence['from'] = 'joe@localhost/Joe' presence['to'] = 'test@localhost/Resource' c = presence.addElement('c') c['xmlns'] = 'http://jabber.org/protocol/caps' c['node'] = 'http://example.com/IDontSupportTubes' c['ver'] = '1.0' stream.send(presence) # Gabble discoes Joe, because it doesn't know his client's caps event = q.expect('stream-iq', iq_type='get', query_ns='http://jabber.org/protocol/disco#info', to='joe@localhost/Joe') assert event.query['node'] == 'http://example.com/IDontSupportTubes#1.0' # Send a "Joe doesn't have any caps" response. result = event.stanza result['type'] = 'result' stream.send(result) # Ensure Joe's caps have been received. # FIXME: we shouldn't need to do this, the tubes code should wait for the # caps to appear, just like the StreamedMedia channel does. sync_stream(q, stream) address = t.create_server(q, cs.SOCKET_ADDRESS_TYPE_IPV4) # Now we try making new-style DBusTube and StreamTube channels, and calling # the relevant Offer method on them; this should fail with NotAvailable. # FIXME: I think this should be NotCapable st_path, _ = conn.Requests.CreateChannel(props(cs.CHANNEL_TYPE_STREAM_TUBE, {cs.STREAM_TUBE_SERVICE: "newecho"})) st_chan = bus.get_object(conn.bus_name, st_path) st = dbus.Interface(st_chan, cs.CHANNEL_TYPE_STREAM_TUBE) call_async(q, st, 'Offer', cs.SOCKET_ADDRESS_TYPE_IPV4, address, cs.SOCKET_ACCESS_CONTROL_LOCALHOST, {}) e = q.expect('dbus-error', method='Offer').error assert e.get_dbus_name() == cs.NOT_AVAILABLE, e.get_dbus_name() dt_path, _ = conn.Requests.CreateChannel(props(cs.CHANNEL_TYPE_DBUS_TUBE, { cs.DBUS_TUBE_SERVICE_NAME: "com.newecho" })) dt_chan = bus.get_object(conn.bus_name, dt_path) dt = dbus.Interface(dt_chan, cs.CHANNEL_TYPE_DBUS_TUBE) call_async(q, dt, 'Offer', {}, cs.SOCKET_ACCESS_CONTROL_CREDENTIALS) e = q.expect('dbus-error', method='Offer').error assert e.get_dbus_name() == cs.NOT_AVAILABLE, e.get_dbus_name() t.cleanup() if __name__ == '__main__': exec_test(test) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tubes/request-invalid-dbus-tube.py����������������������������0000644�0001750�0001750�00000002017�12225363340�027521� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import dbus from gabbletest import exec_test import constants as cs invalid_service_names = [ 'invalidServiceName' , 'one ten hundred thousand million' , 'me.is.it.you?.hello.you.sexy.sons.o.@#$%.heh' , ':1.1' , '' ] def test(q, bus, conn, stream): for invalid_service_name in invalid_service_names: try: conn.Requests.CreateChannel( {cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: 'alice@localhost', cs.DBUS_TUBE_SERVICE_NAME: invalid_service_name }) except dbus.DBusException, e: assert e.get_dbus_name() == cs.INVALID_ARGUMENT, \ (e.get_dbus_name(), invalid_service_name) else: assert False # TODO: do the same with muc D-Bus tubes if __name__ == '__main__': exec_test(test) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tubes/accept-muc-stream-tube.py�������������������������������0000664�0001750�0001750�00000020503�12332441362�026766� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""Test IBB stream tube support in the context of a MUC.""" import sys import dbus from servicetest import call_async, EventPattern, assertEquals, assertSameSets from gabbletest import acknowledge_iq, make_muc_presence, send_error_reply, disconnect_conn import constants as cs import ns import tubetestutil as t from bytestream import create_from_si_offer, announce_socks5_proxy, BytestreamS5BRelay, BytestreamS5BRelayBugged from twisted.words.xish import xpath sample_parameters = dbus.Dictionary({ 's': 'hello', 'ay': dbus.ByteArray('hello'), 'u': dbus.UInt32(123), 'i': dbus.Int32(-123), }, signature='sv') def test(q, bus, conn, stream, bytestream_cls, address_type, access_control, access_control_param): if bytestream_cls in [BytestreamS5BRelay, BytestreamS5BRelayBugged]: # disable SOCKS5 relay tests because proxy can't be used with muc # contacts atm return if access_control == cs.SOCKET_ACCESS_CONTROL_CREDENTIALS: print "Skip Socket_Access_Control_Credentials (fdo #45445)" return iq_event, disco_event = q.expect_many( EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS)) acknowledge_iq(stream, iq_event.stanza) announce_socks5_proxy(q, stream, disco_event.stanza) call_async(q, conn, 'RequestHandles', 2, ['chat@conf.localhost']) event = q.expect('dbus-return', method='RequestHandles') handles = event.value[0] room_handle = handles[0] # join the muc call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_HANDLE: room_handle}) _, stream_event = q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=[u'', [], [], [], [2], 0, 0]), EventPattern('stream-presence', to='chat@conf.localhost/test')) # Send presence for other member of room. stream.send(make_muc_presence('owner', 'moderator', 'chat@conf.localhost', 'bob')) # Send presence for own membership of room. stream.send(make_muc_presence('none', 'participant', 'chat@conf.localhost', 'test')) q.expect('dbus-signal', signal='MembersChanged', args=[u'', [2, 3], [], [], [], 0, 0]) assert conn.InspectHandles(1, [2]) == ['chat@conf.localhost/test'] assert conn.InspectHandles(1, [3]) == ['chat@conf.localhost/bob'] bob_handle = 3 event = q.expect('dbus-return', method='CreateChannel') # Bob offers a stream tube stream_tube_id = 666 presence = make_muc_presence('owner', 'moderator', 'chat@conf.localhost', 'bob') tubes = presence.addElement((ns.TUBES, 'tubes')) tube = tubes.addElement((None, 'tube')) tube['type'] = 'stream' tube['service'] = 'echo' tube['id'] = str(stream_tube_id) parameters = tube.addElement((None, 'parameters')) parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 's' parameter['type'] = 'str' parameter.addContent('hello') parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 'ay' parameter['type'] = 'bytes' parameter.addContent('aGVsbG8=') parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 'u' parameter['type'] = 'uint' parameter.addContent('123') parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 'i' parameter['type'] = 'int' parameter.addContent('-123') stream.send(presence) # text channel event, new_event = q.expect_many( EventPattern('dbus-signal', signal='NewChannel'), EventPattern('dbus-signal', signal='NewChannels')) assert event.args[1] == cs.CHANNEL_TYPE_TEXT, event.args channels = new_event.args[0] assert len(channels) == 1 path, props = channels[0] assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT def new_chan_predicate(e): path, props = e.args[0][0] return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE # tube channel is announced new_event = q.expect('dbus-signal', signal='NewChannels', predicate=new_chan_predicate) channels = new_event.args[0] assert len(channels) == 1 path, props = channels[0] assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE assert props[cs.INITIATOR_HANDLE] == bob_handle assert props[cs.INITIATOR_ID] == 'chat@conf.localhost/bob' assertSameSets([cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE], props[cs.INTERFACES]) assert props[cs.REQUESTED] == False assert props[cs.TARGET_HANDLE] == room_handle assert props[cs.TARGET_ID] == 'chat@conf.localhost' assert props[cs.STREAM_TUBE_SERVICE] == 'echo' assert props[cs.TUBE_PARAMETERS] == {'s': 'hello', 'ay': 'hello', 'u': 123, 'i': -123} assert access_control in \ props[cs.STREAM_TUBE_SUPPORTED_SOCKET_TYPES][address_type] tube_chan = bus.get_object(conn.bus_name, path) tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE) assert tube_props['Parameters'] == sample_parameters assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_LOCAL_PENDING # Accept the tube call_async(q, tube_iface, 'Accept', address_type, access_control, access_control_param, byte_arrays=True) accept_return_event, _ = q.expect_many( EventPattern('dbus-return', method='Accept'), EventPattern('dbus-signal', signal='TubeChannelStateChanged', args=[2])) address = accept_return_event.value[0] socket_event, si_event, conn_id = t.connect_to_cm_socket(q, 'chat@conf.localhost/bob', address_type, address, access_control, access_control_param) protocol = socket_event.protocol protocol.sendData("hello initiator") def accept_tube_si_connection(): bytestream, profile = create_from_si_offer(stream, q, bytestream_cls, si_event.stanza, 'chat@conf.localhost/test') assert profile == ns.TUBES muc_stream_node = xpath.queryForNodes('/iq/si/muc-stream[@xmlns="%s"]' % ns.TUBES, si_event.stanza)[0] assert muc_stream_node is not None assert muc_stream_node['tube'] == str(stream_tube_id) # set the real jid of the target as 'to' because the XMPP server changes # it when delivering the IQ result, si = bytestream.create_si_reply(si_event.stanza, 'test@localhost/Resource') si.addElement((ns.TUBES, 'tube')) stream.send(result) bytestream.wait_bytestream_open() return bytestream bytestream = accept_tube_si_connection() binary = bytestream.get_data() assert binary == 'hello initiator' # reply on the socket bytestream.send_data('hi joiner!') q.expect('socket-data', protocol=protocol, data="hi joiner!") # peer closes the bytestream bytestream.close() e = q.expect('dbus-signal', signal='ConnectionClosed') assertEquals(conn_id, e.args[0]) assertEquals(cs.CONNECTION_LOST, e.args[1]) # establish another tube connection socket_event, si_event, conn_id = t.connect_to_cm_socket(q, 'chat@conf.localhost/bob', address_type, address, access_control, access_control_param) # bytestream is refused send_error_reply(stream, si_event.stanza) e, _ = q.expect_many( EventPattern('dbus-signal', signal='ConnectionClosed'), EventPattern('socket-disconnected')) assertEquals(conn_id, e.args[0]) assertEquals(cs.CONNECTION_REFUSED, e.args[1]) # establish another tube connection socket_event, si_event, conn_id = t.connect_to_cm_socket(q, 'chat@conf.localhost/bob', address_type, address, access_control, access_control_param) protocol = socket_event.protocol bytestream = accept_tube_si_connection() # disconnect local socket protocol.transport.loseConnection() e, _ = q.expect_many( EventPattern('dbus-signal', signal='ConnectionClosed'), EventPattern('socket-disconnected')) assertEquals(conn_id, e.args[0]) assertEquals(cs.CANCELLED, e.args[1]) # OK, we're done disconnect_conn(q, conn, stream) if __name__ == '__main__': t.exec_stream_tube_test(test) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tubes/close-muc-with-closed-tube.py���������������������������0000664�0001750�0001750�00000007601�12332441362�027567� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""Test IBB stream tube support in the context of a MUC.""" import dbus from servicetest import call_async, EventPattern, unwrap, assertEquals from gabbletest import exec_test, make_result_iq, acknowledge_iq, make_muc_presence import constants as cs import ns import tubetestutil as t sample_parameters = dbus.Dictionary({ 's': 'hello', 'ay': dbus.ByteArray('hello'), 'u': dbus.UInt32(123), 'i': dbus.Int32(-123), }, signature='sv') def test(q, bus, conn, stream): iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, iq_event.stanza) call_async(q, conn, 'RequestHandles', cs.HT_ROOM, ['chat@conf.localhost']) event = q.expect('dbus-return', method='RequestHandles') handles = event.value[0] room_handle = handles[0] # join the muc call_async(q, conn, 'RequestChannel', cs.CHANNEL_TYPE_TEXT, cs.HT_ROOM, room_handle, True) _, stream_event = q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=[u'', [], [], [], [2], 0, 0]), EventPattern('stream-presence', to='chat@conf.localhost/test')) # Send presence for other member of room. stream.send(make_muc_presence('owner', 'moderator', 'chat@conf.localhost', 'bob')) # Send presence for own membership of room. stream.send(make_muc_presence('none', 'participant', 'chat@conf.localhost', 'test')) q.expect('dbus-signal', signal='MembersChanged', args=[u'', [2, 3], [], [], [], 0, 0]) assert conn.InspectHandles(cs.HT_CONTACT, [2, 3]) == \ ['chat@conf.localhost/test', 'chat@conf.localhost/bob'] bob_handle = 3 event = q.expect('dbus-return', method='RequestChannel') text_chan = bus.get_object(conn.bus_name, event.value[0]) # Bob offers a muc tube tube_id = 666 stream_id = 1234 presence = make_muc_presence('owner', 'moderator', 'chat@conf.localhost', 'bob') tubes = presence.addElement((ns.TUBES, 'tubes')) tube = tubes.addElement((None, 'tube')) tube['type'] = 'dbus' tube['service'] = 'org.telepathy.freedesktop.test' tube['id'] = str(tube_id) tube['stream-id'] = str(stream_id) tube['dbus-name'] = ':2.Y2Fzc2lkeS10ZXN0MgAA' tube['initiator'] = 'chat@conf.localhost/bob' parameters = tube.addElement((None, 'parameters')) parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 's' parameter['type'] = 'str' parameter.addContent('hello') parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 'ay' parameter['type'] = 'bytes' parameter.addContent('aGVsbG8=') parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 'u' parameter['type'] = 'uint' parameter.addContent('123') parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 'i' parameter['type'] = 'int' parameter.addContent('-123') stream.send(presence) def new_chan_predicate(e): path, props = e.args[0][0] return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE # tube channel is automatically created event = q.expect('dbus-signal', signal='NewChannels', predicate=new_chan_predicate) path, props = event.args[0][0] assertEquals(cs.CHANNEL_TYPE_DBUS_TUBE, props[cs.CHANNEL_TYPE]) assertEquals(cs.HT_ROOM, props[cs.TARGET_HANDLE_TYPE]) assertEquals(room_handle, props[cs.TARGET_HANDLE]) assertEquals('chat@conf.localhost', props[cs.TARGET_ID]) assertEquals(False, props[cs.REQUESTED]) tube_chan = bus.get_object(conn.bus_name, path) tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_DBUS_TUBE) # reject the tube tube_iface.Close(dbus_interface=cs.CHANNEL) q.expect('dbus-signal', signal='ChannelClosed') # close the text channel text_chan.Close() if __name__ == '__main__': exec_test(test) �������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tubes/offer-private-stream-tube.py����������������������������0000664�0001750�0001750�00000024375�12332441362�027531� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""Test 1-1 tubes support.""" import dbus from servicetest import call_async, EventPattern, sync_dbus, assertEquals from gabbletest import acknowledge_iq, sync_stream, make_result_iq import constants as cs import ns import tubetestutil as t from twisted.words.xish import domish, xpath sample_parameters = dbus.Dictionary({ 's': 'hello', 'ay': dbus.ByteArray('hello'), 'u': dbus.UInt32(123), 'i': dbus.Int32(-123), }, signature='sv') new_sample_parameters = dbus.Dictionary({ 's': 'newhello', 'ay': dbus.ByteArray('newhello'), 'u': dbus.UInt32(123), 'i': dbus.Int32(-123), }, signature='sv') def contact_offer_dbus_tube(bytestream, tube_id): iq, si = bytestream.create_si_offer(ns.TUBES) tube = si.addElement((ns.TUBES, 'tube')) tube['type'] = 'dbus' tube['service'] = 'com.example.TestCase2' tube['id'] = tube_id parameters = tube.addElement((None, 'parameters')) parameter = parameters.addElement((None, 'parameter')) parameter['type'] = 'str' parameter['name'] = 'login' parameter.addContent('TEST') bytestream.stream.send(iq) def test(q, bus, conn, stream, bytestream_cls, address_type, access_control, access_control_param): address1 = t.set_up_echo(q, address_type, True, streamfile='stream') address2 = t.set_up_echo(q, address_type, True, streamfile='stream2') t.check_conn_properties(q, conn) vcard_event, roster_event = q.expect_many( EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', query_ns=ns.ROSTER)) self_handle = conn.GetSelfHandle() acknowledge_iq(stream, vcard_event.stanza) roster = roster_event.stanza roster['type'] = 'result' item = roster_event.query.addElement('item') item['jid'] = 'bob@localhost' # Bob can do tubes item['subscription'] = 'both' stream.send(roster) bob_full_jid = 'bob@localhost/Bob' self_full_jid = 'test@localhost/Resource' # Send Bob presence and his tube caps presence = domish.Element(('jabber:client', 'presence')) presence['from'] = bob_full_jid presence['to'] = self_full_jid c = presence.addElement('c') c['xmlns'] = 'http://jabber.org/protocol/caps' c['node'] = 'http://example.com/ICantBelieveItsNotTelepathy' c['ver'] = '1.2.3' stream.send(presence) event = q.expect('stream-iq', iq_type='get', query_ns='http://jabber.org/protocol/disco#info', to=bob_full_jid) assert event.query['node'] == \ 'http://example.com/ICantBelieveItsNotTelepathy#1.2.3' result = make_result_iq(stream, event.stanza) query = result.firstChildElement() feature = query.addElement('feature') feature['var'] = ns.TUBES stream.send(result) # A tube request can be done only if the contact has tube capabilities # Ensure that Bob's caps have been received sync_stream(q, stream) # Also ensure that all the new contact list channels have been announced, # so that the NewChannel(s) signals we look for after calling # RequestChannel are the ones we wanted. sync_dbus(bus, q, conn) # Test tubes with Bob. Bob has tube capabilities. bob_handle = conn.RequestHandles(1, ['bob@localhost'])[0] # Try CreateChannel with correct properties # Gabble must succeed call_async(q, conn.Requests, 'CreateChannel', {cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: bob_handle, cs.STREAM_TUBE_SERVICE: "newecho", }) def find_stream_tube(channels): for path, props in channels: if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE: return path, props return None, None def new_chan_predicate(e): path, _ = find_stream_tube(e.args[0]) return path is not None ret, new_sig = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('dbus-signal', signal='NewChannels', predicate=new_chan_predicate), ) new_chan_path = ret.value[0] new_chan_prop_asv = ret.value[1] # State and Parameters are mutables so not announced assert cs.TUBE_STATE not in new_chan_prop_asv assert cs.TUBE_PARAMETERS not in new_chan_prop_asv assert new_chan_path.find("StreamTube") != -1, new_chan_path assert new_chan_path.find("SITubesChannel") == -1, new_chan_path new_tube_chan = bus.get_object(conn.bus_name, new_chan_path) new_tube_iface = dbus.Interface(new_tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE) # check State and Parameters new_tube_props = new_tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE) # the tube created using the new API is in the "not offered" state assert new_tube_props['State'] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED _, stream_tube_channel_properties = find_stream_tube(new_sig.args[0]) assert cs.TUBE_STATE not in stream_tube_channel_properties assert cs.TUBE_PARAMETERS not in stream_tube_channel_properties # Offer the first tube created call_async(q, new_tube_iface, 'Offer', address_type, address2, access_control, new_sample_parameters) msg_event, state_event = q.expect_many( EventPattern('stream-message'), EventPattern('dbus-signal', signal='TubeChannelStateChanged')) assert state_event.args[0] == cs.TUBE_CHANNEL_STATE_REMOTE_PENDING message = msg_event.stanza assert message['to'] == bob_full_jid tube_nodes = xpath.queryForNodes('/message/tube[@xmlns="%s"]' % ns.TUBES, message) assert tube_nodes is not None assert len(tube_nodes) == 1 tube = tube_nodes[0] assert tube['service'] == 'newecho' assert tube['type'] == 'stream' assert not tube.hasAttribute('initiator') stream_tube_id = long(tube['id']) params = {} parameter_nodes = xpath.queryForNodes('/tube/parameters/parameter', tube) for node in parameter_nodes: assert node['name'] not in params params[node['name']] = (node['type'], str(node)) assert params == {'ay': ('bytes', 'bmV3aGVsbG8='), 's': ('str', 'newhello'), 'i': ('int', '-123'), 'u': ('uint', '123'), } # The new tube has been offered, the parameters cannot be changed anymore # We need to use call_async to check the error tube_prop_iface = dbus.Interface(new_tube_chan, cs.PROPERTIES_IFACE) call_async(q, tube_prop_iface, 'Set', cs.CHANNEL_IFACE_TUBE, 'Parameters', dbus.Dictionary( {dbus.String(u'foo2'): dbus.String(u'bar2')}, signature=dbus.Signature('sv')), dbus_interface=cs.PROPERTIES_IFACE) set_error = q.expect('dbus-error') # check it is *not* correctly changed new_tube_props = new_tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assert new_tube_props.get("Parameters") == new_sample_parameters, \ new_tube_props.get("Parameters") # The CM is the server, so fake a client wanting to talk to it # Old API tube bytestream1 = bytestream_cls(stream, q, 'alpha', bob_full_jid, self_full_jid, True) iq, si = bytestream1.create_si_offer(ns.TUBES) stream_node = si.addElement((ns.TUBES, 'stream')) stream_node['tube'] = str(stream_tube_id) stream.send(iq) si_reply_event, _, new_conn_event, socket_event = q.expect_many( EventPattern('stream-iq', iq_type='result'), EventPattern('dbus-signal', signal='TubeChannelStateChanged', args=[cs.TUBE_STATE_OPEN]), EventPattern('dbus-signal', signal='NewRemoteConnection'), EventPattern('socket-connected')) bytestream1.check_si_reply(si_reply_event.stanza) tube = xpath.queryForNodes('/iq/si/tube[@xmlns="%s"]' % ns.TUBES, si_reply_event.stanza) assert len(tube) == 1 handle, access, id = new_conn_event.args assert handle == bob_handle protocol = socket_event.protocol # we don't want to echo the access control byte protocol.echoed = False # start to read from the transport so we can read the control byte protocol.transport.startReading() t.check_new_connection_access(q, access_control, access, protocol) protocol.echoed = True # The CM is the server, so fake a client wanting to talk to it # New API tube bytestream2 = bytestream_cls(stream, q, 'beta', bob_full_jid, self_full_jid, True) iq, si = bytestream2.create_si_offer(ns.TUBES) stream_node = si.addElement((ns.TUBES, 'stream')) stream_node['tube'] = str(stream_tube_id) stream.send(iq) si_reply_event, new_conn_event, socket_event = q.expect_many( EventPattern('stream-iq', iq_type='result'), EventPattern('dbus-signal', signal='NewRemoteConnection'), EventPattern('socket-connected')) bytestream2.check_si_reply(si_reply_event.stanza) tube = xpath.queryForNodes('/iq/si/tube[@xmlns="%s"]' % ns.TUBES, si_reply_event.stanza) assert len(tube) == 1 handle, access, conn_id = new_conn_event.args assert handle == bob_handle protocol = socket_event.protocol # we don't want to echo the access control byte protocol.echoed = False # start to read from the transport so we can read the control byte protocol.transport.startReading() t.check_new_connection_access(q, access_control, access, protocol) protocol.echoed = True # have the fake client open the stream bytestream1.open_bytestream() # have the fake client send us some data data = 'hello, world' bytestream1.send_data(data) binary = bytestream1.get_data(len(data)) assert binary == data, binary # have the fake client open the stream bytestream2.open_bytestream() # have the fake client send us some data data = 'hello, new world' bytestream2.send_data(data) binary = bytestream2.get_data(len(data)) assert binary == data, binary # peer closes the bytestream bytestream2.close() e = q.expect('dbus-signal', signal='ConnectionClosed') assertEquals(conn_id, e.args[0]) assertEquals(cs.CONNECTION_LOST, e.args[1]) t.cleanup() if __name__ == '__main__': t.exec_stream_tube_test(test) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/bytestream.py�������������������������������������������������0000664�0001750�0001750�00000072533�12225363340�023566� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import base64 import hashlib import sys import random import socket from twisted.internet.protocol import Factory, Protocol from twisted.internet import reactor from twisted.words.protocols.jabber.client import IQ from twisted.words.xish import xpath, domish from twisted.internet.error import CannotListenError from servicetest import Event, EventPattern from gabbletest import acknowledge_iq, make_result_iq, elem_iq, elem import ns def wait_events(q, expected, my_event): tmp = expected + [my_event] events = q.expect_many(*tmp) return events[:-1], events[-1] def create_from_si_offer(stream, q, bytestream_cls, iq, initiator): si_nodes = xpath.queryForNodes('/iq/si', iq) assert si_nodes is not None assert len(si_nodes) == 1 si = si_nodes[0] feature = xpath.queryForNodes('/si/feature', si)[0] x = xpath.queryForNodes('/feature/x', feature)[0] assert x['type'] == 'form' field = xpath.queryForNodes('/x/field', x)[0] assert field['var'] == 'stream-method' assert field['type'] == 'list-single' bytestreams = [] for value in xpath.queryForNodes('/field/option/value', field): bytestreams.append(str(value)) bytestream = bytestream_cls(stream, q, si['id'], initiator, iq['to'], False) bytestream.check_si_offer(iq, bytestreams) return bytestream, si['profile'] def is_ipv4(address): try: socket.inet_pton(socket.AF_INET, address) except (ValueError, socket.error): return False return True class Bytestream(object): def __init__(self, stream, q, sid, initiator, target, initiated): self.stream = stream self.q = q self.stream_id = sid self.initiator = initiator self.target = target self.initiated = initiated def open_bytestream(self, expected_before=[], expected_after=[]): raise NotImplemented def send_data(self, data): raise NotImplemented def get_ns(self): raise NotImplemented def wait_bytestream_open(self): raise NotImplemented def get_data(self, size=0): raise NotImplemented def wait_bytestream_closed(self, expected=[]): raise NotImplemented def check_si_offer(self, iq, bytestreams): assert self.get_ns() in bytestreams def close(self): raise NotImplemented ##### XEP-0095: Stream Initiation ##### def _create_si_offer(self, profile, to=None): assert self.initiated iq = IQ(self.stream, 'set') iq['from'] = self.initiator if to is None: iq['to'] = self.target else: iq['to'] = to si = iq.addElement((ns.SI, 'si')) si['id'] = self.stream_id si['profile'] = profile feature = si.addElement((ns.FEATURE_NEG, 'feature')) x = feature.addElement((ns.X_DATA, 'x')) x['type'] = 'form' field = x.addElement((None, 'field')) field['var'] = 'stream-method' field['type'] = 'list-single' return iq, si, field def create_si_offer(self, profile, to=None): iq, si, field = self._create_si_offer(profile, to) option = field.addElement((None, 'option')) value = option.addElement((None, 'value')) value.addContent(self.get_ns()) return iq, si def create_si_reply(self, iq, to=None): result = make_result_iq(self.stream, iq) result['from'] = iq['to'] if to is None: result['to'] = self.initiator else: result['to'] = to res_si = result.firstChildElement() res_feature = res_si.addElement((ns.FEATURE_NEG, 'feature')) res_x = res_feature.addElement((ns.X_DATA, 'x')) res_x['type'] = 'submit' res_field = res_x.addElement((None, 'field')) res_field['var'] = 'stream-method' res_value = res_field.addElement((None, 'value')) res_value.addContent(self.get_ns()) return result, res_si def check_si_reply(self, iq): si = xpath.queryForNodes('/iq/si[@xmlns="%s"]' % ns.SI, iq)[0] value = xpath.queryForNodes('/si/feature/x/field/value', si) assert len(value) == 1 proto = value[0] assert str(proto) == self.get_ns() ##### XEP-0065: SOCKS5 Bytestreams ##### def listen_socks5(q): for port in range(5000, 5100): try: reactor.listenTCP(port, S5BFactory(q.append), interface='localhost') except CannotListenError: continue else: return port assert False, "Can't find a free port" def announce_socks5_proxy(q, stream, disco_stanza): reply = make_result_iq(stream, disco_stanza) query = xpath.queryForNodes('/iq/query', reply)[0] item = query.addElement((None, 'item')) item['jid'] = 'proxy.localhost' stream.send(reply) # wait for proxy disco#info query event = q.expect('stream-iq', to='proxy.localhost', query_ns=ns.DISCO_INFO, iq_type='get') reply = elem_iq(stream, 'result', from_='proxy.localhost', id=event.stanza['id'])( elem(ns.DISCO_INFO, 'query')( elem('identity', category='proxy', type='bytestreams', name='SOCKS5 Bytestreams')(), elem('feature', var=ns.BYTESTREAMS)())) stream.send(reply) # Gabble asks for SOCKS5 info event = q.expect('stream-iq', to='proxy.localhost', query_ns=ns.BYTESTREAMS, iq_type='get') port = listen_socks5(q) reply = elem_iq(stream, 'result', id=event.stanza['id'], from_='proxy.localhost')( elem(ns.BYTESTREAMS, 'query')( elem('streamhost', jid='proxy.localhost', host='127.0.0.1', port=str(port))())) stream.send(reply) class BytestreamS5B(Bytestream): def __init__(self, stream, q, sid, initiator, target, initiated): Bytestream.__init__(self, stream, q, sid, initiator, target, initiated) # hosts that will be announced when sending S5B open IQ self.hosts = [ # Not working streamhost ('invalid.invalid', 'invalid.invalid'), # Working streamhost (self.initiator, '127.0.0.1'), # This works too but should not be tried as Gabble should just # connect to the previous one ('Not me', '127.0.0.1')] def get_ns(self): return ns.BYTESTREAMS def _send_socks5_init(self, port): iq = IQ(self.stream, 'set') iq['to'] = self.target iq['from'] = self.initiator query = iq.addElement((ns.BYTESTREAMS, 'query')) query['sid'] = self.stream_id query['mode'] = 'tcp' for jid, host in self.hosts: streamhost = query.addElement('streamhost') streamhost['jid'] = jid streamhost['host'] = host streamhost['port'] = str(port) self.stream.send(iq) def _wait_auth_request(self): event = self.q.expect('s5b-data-received') assert event.data == '\x05\x01\x00' # version 5, 1 auth method, no auth self.transport = event.transport def _send_auth_reply(self): self.transport.write('\x05\x00') # version 5, no auth def _compute_hash_domain(self): # sha-1(sid + initiator + target) unhashed_domain = self.stream_id + self.initiator + self.target return hashlib.sha1(unhashed_domain).hexdigest() def _wait_connect_cmd(self): event = self.q.expect('s5b-data-received', transport=self.transport) # version 5, connect, reserved, domain type expected_connect = '\x05\x01\x00\x03' expected_connect += chr(40) # len (SHA-1) expected_connect += self._compute_hash_domain() expected_connect += '\x00\x00' # port assert event.data == expected_connect def _send_connect_reply(self): connect_reply = '\x05\x00\x00\x03' connect_reply += chr(40) # len (SHA-1) connect_reply += self._compute_hash_domain() connect_reply += '\x00\x00' # port self.transport.write(connect_reply) def _check_s5b_reply(self, iq): streamhost = xpath.queryForNodes('/iq/query/streamhost-used', iq)[0] assert streamhost['jid'] == self.initiator def _socks5_expect_connection(self, expected_before, expected_after): events_before, _ = wait_events(self.q, expected_before, EventPattern('s5b-connected')) self._wait_auth_request() self._send_auth_reply() self._wait_connect_cmd() self._send_connect_reply() # wait for S5B IQ reply events_after, e = wait_events(self.q, expected_after, EventPattern('stream-iq', iq_type='result', to=self.initiator)) self._check_s5b_reply(e.stanza) return events_before, events_after def open_bytestream(self, expected_before=[], expected_after=[]): port = listen_socks5(self.q) self._send_socks5_init(port) return self._socks5_expect_connection(expected_before, expected_after) def send_data(self, data): self.transport.write(data) def _expect_socks5_init(self): event = self.q.expect('stream-iq', iq_type='set') iq = event.stanza query = xpath.queryForNodes('/iq/query', iq)[0] assert query.uri == ns.BYTESTREAMS mode = query['mode'] sid = query['sid'] hosts = [] for streamhost in xpath.queryForNodes('/query/streamhost', query): hosts.append((streamhost['jid'], streamhost['host'], int(streamhost['port']))) return iq['id'], mode, sid, hosts def _send_auth_cmd(self): #version 5, 1 auth method, no auth self.transport.write('\x05\x01\x00') def _wait_auth_reply(self): event = self.q.expect('s5b-data-received') assert event.data == '\x05\x00' # version 5, no auth def _send_connect_cmd(self): # version 5, connect, reserved, domain type connect = '\x05\x01\x00\x03' connect += chr(40) # len (SHA-1) connect += self._compute_hash_domain() connect += '\x00\x00' # port self.transport.write(connect) def _wait_connect_reply(self): event = self.q.expect('s5b-data-received') # version 5, succeed, reserved, domain type expected_reply = '\x05\x00\x00\x03' expected_reply += chr(40) # len (SHA-1) expected_reply += self._compute_hash_domain() expected_reply += '\x00\x00' # port assert event.data == expected_reply def _socks5_connect(self, host, port): reactor.connectTCP(host, port, S5BFactory(self.q.append)) event = self.q.expect('s5b-connected') self.transport = event.transport self._send_auth_cmd() self._wait_auth_reply() self._send_connect_cmd() self._wait_connect_reply() return True def _send_socks5_reply(self, id, stream_used): result = IQ(self.stream, 'result') result['id'] = id result['from'] = self.target result['to'] = self.initiator query = result.addElement((ns.BYTESTREAMS, 'query')) streamhost_used = query.addElement((None, 'streamhost-used')) streamhost_used['jid'] = stream_used result.send() def wait_bytestream_open(self): id, mode, sid, hosts = self._expect_socks5_init() assert mode == 'tcp' assert sid == self.stream_id stream_host_found = False for jid, host, port in hosts: if not is_ipv4(host): continue if jid == self.initiator: stream_host_found = True if self._socks5_connect(host, port): self._send_socks5_reply(id, jid) else: # Connection failed self.send_not_found(id) break assert stream_host_found def get_data(self, size=0): binary = '' received = False while not received: e = self.q.expect('s5b-data-received', transport=self.transport) binary += e.data if len(binary) >= size or size == 0: received = True return binary def wait_bytestream_closed(self, expected=[]): events, _ = wait_events(self.q, expected, EventPattern('s5b-connection-lost')) return events def check_error_stanza(self, iq): error = xpath.queryForNodes('/iq/error', iq)[0] assert error['code'] == '404' assert error['type'] == 'cancel' def send_not_found(self, id): iq = IQ(self.stream, 'error') iq['to'] = self.initiator iq['from'] = self.target iq['id'] = id error = iq.addElement(('', 'error')) error['type'] = 'cancel' error['code'] = '404' self.stream.send(iq) def close(self): self.transport.loseConnection() class BytestreamS5BPidgin(BytestreamS5B): """Simulate buggy S5B implementation (as Pidgin's one)""" def _send_connect_reply(self): # version 5, ok, reserved, domain type connect_reply = '\x05\x00\x00\x03' # I'm Pidgin, why should I respect SOCKS5 XEP? domain = '127.0.0.1' connect_reply += chr(len(domain)) connect_reply += domain connect_reply += '\x00\x00' # port self.transport.write(connect_reply) class BytestreamS5BCannotConnect(BytestreamS5B): """SOCKS5 bytestream not working because target can't connect to initiator.""" def __init__(self, stream, q, sid, initiator, target, initiated): BytestreamS5B.__init__(self, stream, q, sid, initiator, target, initiated) self.hosts = [('invalid.invalid', 'invalid.invalid')] def open_bytestream(self, expected_before=[], expected_after=[]): self._send_socks5_init(12345) events_before, iq_event = wait_events(self.q, expected_before, EventPattern('stream-iq', iq_type='error', to=self.initiator)) self.check_error_stanza(iq_event.stanza) return events_before, [] def _socks5_connect(self, host, port): # Pretend we can't connect to it return False class BytestreamS5BWrongHash(BytestreamS5B): """Connection is closed because target sends the wrong hash""" def __init__(self, stream, q, sid, initiator, target, initiated): BytestreamS5B.__init__(self, stream, q, sid, initiator, target, initiated) self.hosts = [(self.initiator, '127.0.0.1')] def _send_connect_cmd(self): # version 5, connect, reserved, domain type connect = '\x05\x01\x00\x03' # send wrong hash as domain domain = 'this is wrong' connect += chr(len(domain)) connect += domain connect += '\x00\x00' # port self.transport.write(connect) def _socks5_connect(self, host, port): reactor.connectTCP(host, port, S5BFactory(self.q.append)) event = self.q.expect('s5b-connected') self.transport = event.transport self._send_auth_cmd() self._wait_auth_reply() self._send_connect_cmd() # Gabble disconnects the connection because we sent a wrong hash self.q.expect('s5b-connection-lost') return False def _socks5_expect_connection(self, expected_before, expected_after): events_before, _ = wait_events(self.q, expected_before, EventPattern('s5b-connected')) self._wait_auth_request() self._send_auth_reply() self._wait_connect_cmd() # pretend the hash was wrong and close the transport self.transport.loseConnection() iq_event = self.q.expect('stream-iq', iq_type='error', to=self.initiator) self.check_error_stanza(iq_event.stanza) return events_before, [] class BytestreamS5BRelay(BytestreamS5B): """Direct connection doesn't work so we use a relay""" def __init__(self, stream, q, sid, initiator, target, initiated): BytestreamS5B.__init__(self, stream, q, sid, initiator, target, initiated) self.hosts = [(self.initiator, 'invalid.invalid'), ('proxy.localhost', '127.0.0.1')] # This is the only thing we need to check to test the Target side as the # protocol is similar from this side. def _check_s5b_reply(self, iq): streamhost = xpath.queryForNodes('/iq/query/streamhost-used', iq)[0] assert streamhost['jid'] == 'proxy.localhost' def wait_bytestream_open(self): # The only difference of using a relay on the Target side is to # connect to another streamhost. id, mode, sid, hosts = self._expect_socks5_init() assert mode == 'tcp' assert sid == self.stream_id proxy_found = False for jid, host, port in hosts: if jid != self.initiator: proxy_found = True # connect to the (fake) relay if self._socks5_connect(host, port): self._send_socks5_reply(id, jid) else: assert False break assert proxy_found # The initiator (Gabble) is now supposed to connect to the proxy too self._wait_connect_to_proxy() def _wait_connect_to_proxy(self): e = self.q.expect('s5b-connected') self.transport = e.transport self._wait_auth_request() self._send_auth_reply() self._wait_connect_cmd() self._send_connect_reply() self._wait_activation_iq() def _wait_activation_iq(self): e = self.q.expect('stream-iq', iq_type='set', to='proxy.localhost', query_ns=ns.BYTESTREAMS) query = xpath.queryForNodes('/iq/query', e.stanza)[0] assert query['sid'] == self.stream_id activate = xpath.queryForNodes('/iq/query/activate', e.stanza)[0] assert str(activate) == self.target self._reply_activation_iq(e.stanza) def _reply_activation_iq(self, iq): reply = make_result_iq(self.stream, iq) reply.send() def _socks5_connect(self, host, port): # No point to emulate the proxy. Just pretend the Target properly # connects, auth and requests connection return True def wait_bytestream_closed(self, expected=[]): if expected == []: return [] return self.q.expect_many(*expected) class BytestreamS5BRelayBugged(BytestreamS5BRelay): """Simulate bugged ejabberd (< 2.0.2) proxy sending wrong CONNECT reply""" def _send_connect_reply(self): # send a 6 bytes wrong reply connect_reply = '\x05\x00\x00\x00\x00\x00' self.transport.write(connect_reply) class S5BProtocol(Protocol): def connectionMade(self): self.factory.event_func(Event('s5b-connected', transport=self.transport)) def dataReceived(self, data): self.factory.event_func(Event('s5b-data-received', data=data, transport=self.transport)) class S5BFactory(Factory): protocol = S5BProtocol def __init__(self, event_func): self.event_func = event_func def buildProtocol(self, addr): protocol = Factory.buildProtocol(self, addr) return protocol def startedConnecting(self, connector): self.event_func(Event('s5b-started-connecting', connector=connector)) def clientConnectionLost(self, connector, reason): self.event_func(Event('s5b-connection-lost', connector=connector, reason=reason)) def clientConnectionFailed(self, connector, reason): self.event_func(Event('s5b-connection-failed', reason=reason)) def expect_socks5_reply(q): event = q.expect('stream-iq', iq_type='result') iq = event.stanza query = xpath.queryForNodes('/iq/query', iq)[0] assert query.uri == ns.BYTESTREAMS streamhost_used = xpath.queryForNodes('/query/streamhost-used', query)[0] return streamhost_used ##### XEP-0047: In-Band Bytestreams (IBB) ##### class BytestreamIBB(Bytestream): def __init__(self, stream, q, sid, initiator, target, initiated): Bytestream.__init__(self, stream, q, sid, initiator, target, initiated) self.seq = 0 self.checked = False def get_ns(self): return ns.IBB def check_si_reply(self, iq): self.checked = True def open_bytestream(self, expected_before=[], expected_after=[]): # open IBB bytestream iq = IQ(self.stream, 'set') iq['to'] = self.target iq['from'] = self.initiator open = iq.addElement((ns.IBB, 'open')) open['sid'] = self.stream_id # set a ridiculously small block size to stress test IBB buffering open['block-size'] = '1' assert self.checked events_before = self.q.expect_many(*expected_before) self.stream.send(iq) events_after = self.q.expect_many(*expected_after) return events_before, events_after def _send(self, from_, to, data): raise NotImplemented def send_data(self, data): if self.initiated: from_ = self.initiator to = self.target else: from_ = self.target to = self.initiator self._send(from_, to, data) self.seq += 1 def wait_bytestream_open(self): # Wait IBB open iq event = self.q.expect('stream-iq', iq_type='set') open = xpath.queryForNodes('/iq/open', event.stanza)[0] assert open.uri == ns.IBB assert open['sid'] == self.stream_id # open IBB bytestream acknowledge_iq(self.stream, event.stanza) def get_data(self, size=0): # wait for IBB stanza. Gabble always uses IQ binary = '' received = False while not received: ibb_event = self.q.expect('stream-iq', query_ns=ns.IBB) data_nodes = xpath.queryForNodes('/iq/data[@xmlns="%s"]' % ns.IBB, ibb_event.stanza) assert data_nodes is not None assert len(data_nodes) == 1 ibb_data = data_nodes[0] binary += base64.b64decode(str(ibb_data)) assert ibb_data['sid'] == self.stream_id # ack the IQ result = make_result_iq(self.stream, ibb_event.stanza) result.send() if len(binary) >= size or size == 0: received = True return binary def wait_bytestream_closed(self, expected=[]): events, close_event = wait_events(self.q, expected, EventPattern('stream-iq', iq_type='set', query_name='close', query_ns=ns.IBB)) # sender finish to send the file and so close the bytestream acknowledge_iq(self.stream, close_event.stanza) return events def close(self): if self.initiated: from_ = self.initiator to = self.target else: from_ = self.target to = self.initiator iq = elem_iq(self.stream, 'set', from_=from_, to=to, id=str(id))( elem('close', xmlns=ns.IBB, sid=self.stream_id)()) self.stream.send(iq) class BytestreamIBBMsg(BytestreamIBB): def _send(self, from_, to, data): message = domish.Element(('jabber:client', 'message')) message['to'] = to message['from'] = from_ data_node = message.addElement((ns.IBB, 'data')) data_node['sid'] = self.stream_id data_node['seq'] = str(self.seq) data_node.addContent(base64.b64encode(data)) self.stream.send(message) def _wait_data_event(self): ibb_event = self.q.expect('stream-message') data_nodes = xpath.queryForNodes('/message/data[@xmlns="%s"]' % ns.IBB, ibb_event.stanza) assert data_nodes is not None assert len(data_nodes) == 1 ibb_data = data_nodes[0] assert ibb_data['sid'] == self.stream_id return str(ibb_data), ibb_data['sid'] class BytestreamIBBIQ(BytestreamIBB): def _send(self, from_, to, data): id = random.randint(0, sys.maxint) iq = elem_iq(self.stream, 'set', from_=from_, to=to, id=str(id))( elem('data', xmlns=ns.IBB, sid=self.stream_id, seq=str(self.seq))( (unicode(base64.b64encode(data))))) self.stream.send(iq) ##### SI Fallback (Gabble specific extension) ##### class BytestreamSIFallback(Bytestream): """Abstract class used for all the SI fallback scenarios""" def __init__(self, stream, q, sid, initiator, target, initiated): Bytestream.__init__(self, stream, q, sid, initiator, target, initiated) self.socks5 = BytestreamS5B(stream, q, sid, initiator, target, initiated) self.ibb = BytestreamIBBMsg(stream, q, sid, initiator, target, initiated) def create_si_offer(self, profile, to=None): iq, si, field = self._create_si_offer(profile, to) # add SOCKS5 option = field.addElement((None, 'option')) value = option.addElement((None, 'value')) value.addContent(self.socks5.get_ns()) # add IBB option = field.addElement((None, 'option')) value = option.addElement((None, 'value')) value.addContent(self.ibb.get_ns()) si_multiple = si.addElement((ns.SI_MULTIPLE, 'si-multiple')) return iq, si def check_si_reply(self, iq): value = xpath.queryForNodes( '/iq/si[@xmlns="%s"]/si-multiple[@xmlns="%s"]/value' % (ns.SI, ns.SI_MULTIPLE), iq) assert len(value) == 2 assert str(value[0]) == self.socks5.get_ns() assert str(value[1]) == self.ibb.get_ns() def create_si_reply(self, iq, to=None): result = make_result_iq(self.stream, iq) result['from'] = iq['to'] if to is None: result['to'] = self.initiator else: result['to'] = to res_si = result.firstChildElement() si_multiple = res_si.addElement((ns.SI_MULTIPLE, 'si-multiple')) # add SOCKS5 res_value = si_multiple.addElement((None, 'value')) res_value.addContent(self.socks5.get_ns()) # add IBB res_value = si_multiple.addElement((None, 'value')) res_value.addContent(self.ibb.get_ns()) return result, res_si def open_bytestream(self, expected_before=[], expected_after=[]): # first propose to peer to connect using SOCKS5 # We set an invalid IP so that won't work self.socks5._send_socks5_init([ # Not working streamhost (self.initiator, 'invalid.invalid', 12345), ]) events_before, iq_event = wait_events(self.q, expected_before, EventPattern('stream-iq', iq_type='error', to=self.initiator)) self.socks5.check_error_stanza(iq_event.stanza) # socks5 failed, let's try IBB _, events_after = self.ibb.open_bytestream([], expected_after) return events_before, events_after def send_data(self, data): self.used.send_data(data) def get_data(self, size=0): return self.used.get_data(size) def wait_bytestream_closed(self, expected=[]): return self.used.wait_bytestream_closed(expected) def check_si_offer(self, iq, bytestreams): assert self.socks5.get_ns() in bytestreams assert self.ibb.get_ns() in bytestreams # check if si-multiple is supported si_multiple = xpath.queryForNodes( '/iq/si[@xmlns="%s"]/si-multiple[@xmlns="%s"]' % (ns.SI, ns.SI_MULTIPLE), iq) assert si_multiple is not None def close(self): return self.used.close() class BytestreamSIFallbackS5CannotConnect(BytestreamSIFallback): """Try to use SOCKS5 and fallback to IBB because the target can't connect to the receiver.""" def __init__(self, stream, q, sid, initiator, target, initiated): BytestreamSIFallback.__init__(self, stream, q, sid, initiator, target, initiated) self.socks5 = BytestreamS5BCannotConnect(stream, q, sid, initiator, target, initiated) self.used = self.ibb def open_bytestream(self, expected_before=[], expected_after=[]): # First propose to peer to connect using SOCKS5 # That won't work as target can't connect events_before, _ = self.socks5.open_bytestream(expected_before) # socks5 failed, let's try IBB _, events_after = self.ibb.open_bytestream([], expected_after) return events_before, events_after def wait_bytestream_open(self): # Gabble tries SOCKS5 first self.socks5.wait_bytestream_open() # Gabble now tries IBB self.ibb.wait_bytestream_open() def check_si_reply (self, iq): self.ibb.check_si_reply (iq) class BytestreamSIFallbackS5WrongHash(BytestreamSIFallback): """Try to use SOCKS5 and fallback to IBB because target sent the wrong hash as domain in the CONNECT command.""" def __init__(self, stream, q, sid, initiator, target, initiated): BytestreamSIFallback.__init__(self, stream, q, sid, initiator, target, initiated) self.socks5 = BytestreamS5BWrongHash(stream, q, sid, initiator, target, initiated) self.used = self.ibb def open_bytestream(self, expected_before=[], expected_after=[]): # SOCKS5 won't work because we'll pretend the hash was wrong and # close the connection events_before, _ = self.socks5.open_bytestream(expected_before) # socks5 failed, let's try IBB _, events_after = self.ibb.open_bytestream([], expected_after) return events_before, events_after def wait_bytestream_open(self): # BytestreamS5BWrongHash will send a wrong hash so Gabble will # disconnect the connection self.socks5.wait_bytestream_open() # Gabble now tries IBB self.ibb.wait_bytestream_open() def check_si_reply (self, iq): self.ibb.check_si_reply (iq) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/sidecars.py���������������������������������������������������0000664�0001750�0001750�00000010565�12332441362�023201� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test Gabble's implementation of sidecars, using the test plugin. """ from servicetest import ( sync_dbus, call_async, EventPattern, assertEquals, assertContains, ) from gabbletest import exec_test, send_error_reply, acknowledge_iq, sync_stream import constants as cs from config import PLUGINS_ENABLED TEST_PLUGIN_IFACE = "org.freedesktop.Telepathy.Gabble.Plugin.Test" if not PLUGINS_ENABLED: print "NOTE: built without --enable-plugins, not testing plugins" print " (but still testing failing calls to EnsureSidecar)" def test(q, bus, conn, stream): # Request a sidecar thate we support before we're connected; it should just # wait around until we're connected. call_async(q, conn.Future, 'EnsureSidecar', TEST_PLUGIN_IFACE) if PLUGINS_ENABLED: # Now we're connected, the call we made earlier should return. path, props = q.expect('dbus-return', method='EnsureSidecar').value # This sidecar doesn't even implement get_immutable_properties; it # should just get the empty dict filled in for it. assertEquals({}, props) # We should get the same sidecar if we request it again path2, props2 = conn.Future.EnsureSidecar(TEST_PLUGIN_IFACE) assertEquals((path, props), (path2, props2)) else: # Only now does it fail. q.expect('dbus-error', method='EnsureSidecar') # This is not a valid interface name call_async(q, conn.Future, 'EnsureSidecar', 'not an interface') q.expect('dbus-error', name=cs.INVALID_ARGUMENT) # The test plugin makes no reference to this interface. call_async(q, conn.Future, 'EnsureSidecar', 'unsupported.sidecar') q.expect('dbus-error', name=cs.NOT_IMPLEMENTED) if PLUGINS_ENABLED: # This sidecar does have some properties: path, props = conn.Future.EnsureSidecar(TEST_PLUGIN_IFACE + ".Props") assertContains(TEST_PLUGIN_IFACE + ".Props.Greeting", props) # The plugin claims it implements this sidecar, but actually doesn't. # Check that we don't blow up (although this is no different from # Gabble's perspective to creating a sidecar failing because a network # service wasn't there, for instance). call_async(q, conn.Future, 'EnsureSidecar', TEST_PLUGIN_IFACE + ".Buggy") q.expect('dbus-error', name=cs.NOT_IMPLEMENTED) # This sidecar sends a stanza, and waits for a reply, before being # created. pattern = EventPattern('stream-iq', to='sidecar.example.com', query_ns='http://example.com/sidecar') call_async(q, conn.Future, 'EnsureSidecar', TEST_PLUGIN_IFACE + ".IQ") e = q.expect_many(pattern)[0] sync_dbus(bus, q, conn) # If the server says no, EnsureSidecar should fail. send_error_reply(stream, e.stanza) q.expect('dbus-error', method='EnsureSidecar', name=cs.NOT_AVAILABLE) # Let's try again. The plugin should get a chance to ping the server # again. call_async(q, conn.Future, 'EnsureSidecar', TEST_PLUGIN_IFACE + ".IQ") e = q.expect_many(pattern)[0] # The server said yes, so we should get a sidecar back! acknowledge_iq(stream, e.stanza) q.expect('dbus-return', method='EnsureSidecar') # If we ask again once the plugin has been created, it should return at # once without any more network traffic. q.forbid_events([pattern]) conn.Future.EnsureSidecar(TEST_PLUGIN_IFACE + ".IQ") sync_stream(q, stream) # TODO: test ensuring a sidecar that waits for something from the # network, disconnecting while it's waiting, and ensuring that nothing # breaks regardless of whether the network replies before # </stream:stream> or not. call_async(q, conn, 'Disconnect') q.expect_many( EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_REQUESTED]), EventPattern('stream-closed'), ) call_async(q, conn.Future, 'EnsureSidecar', 'zomg.what') # With older telepathy-glib this would be DISCONNECTED; # with newer telepathy-glib the Connection disappears from the bus # sooner, and you get UnknownMethod or something from dbus-glib. q.expect('dbus-error') stream.sendFooter() q.expect('dbus-return', method='Disconnect') if __name__ == '__main__': exec_test(test) �������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/pep-support.py������������������������������������������������0000664�0001750�0001750�00000005221�12332441362�023673� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import dbus from gabbletest import exec_test, GoogleXmlStream, acknowledge_iq, BaseXmlStream,\ sync_stream from servicetest import call_async, EventPattern from twisted.words.protocols.jabber.client import IQ from twisted.words.xish import xpath import constants as cs import ns # PEP supports is advertised in Server's disco which is wrong but that's what # old ejabberd used to do. class PepInServerDiscoXmlStream(BaseXmlStream): version = (1, 0) def _cb_disco_iq(self, iq): # Advertise PEP support in server disco rather than when discoing our # bare JID nodes = xpath.queryForNodes( "/iq/query[@xmlns='http://jabber.org/protocol/disco#info']", iq) query = nodes[0] identity = query.addElement('identity') identity['category'] = 'pubsub' identity['type'] = 'pep' iq['type'] = 'result' iq['from'] = 'localhost' self.send(iq) def _cb_bare_jid_disco_iq(self, iq): # Additionally, Prosody 0.6.1 doesn't like us discoing our own bare # JID, and responds with an error which doesn't have the 'from' # attribute. Wocky used to discard this, but now tolerates it. result = IQ(self, 'error') result['id'] = iq['id'] error = result.addElement((None, 'error')) error['type'] = 'cancel' error.addElement((ns.STANZA, 'service-unavailable')) self.send(result) def test_legacy(q, bus, conn, stream): call_async(q, conn.Location, 'SetLocation', { 'lat': 0.0, 'lon': 0.0}) geoloc_iq_set_event = EventPattern('stream-iq', predicate=lambda x: xpath.queryForNodes("/iq/pubsub/publish/item/geoloc", x.stanza)) event = q.expect_many(geoloc_iq_set_event)[0] acknowledge_iq(stream, event.stanza) q.expect('dbus-return', method='SetLocation') # PEP is not supported. def test_no_pep(q, bus, conn, stream): call_async(q, conn.Location, 'SetLocation', { 'lat': 0.0, 'lon': 0.0}) q.expect('dbus-error', name=cs.NOT_IMPLEMENTED) #PEP is advertised using the right protocol def test_pep(q, bus, conn, stream): call_async(q, conn.Location, 'SetLocation', { 'lat': 0.0, 'lon': 0.0}) geoloc_iq_set_event = EventPattern('stream-iq', predicate=lambda x: xpath.queryForNodes("/iq/pubsub/publish/item/geoloc", x.stanza)) event = q.expect_many(geoloc_iq_set_event)[0] acknowledge_iq(stream, event.stanza) q.expect('dbus-return', method='SetLocation') if __name__ == '__main__': exec_test(test_legacy, protocol=PepInServerDiscoXmlStream) exec_test(test_no_pep, protocol=GoogleXmlStream) exec_test(test_pep) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/pubsub.py�����������������������������������������������������0000664�0001750�0001750�00000006163�12332441362�022703� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""Send malformed pubsub notifications to be sure that Gabble isn't confused about those""" from gabbletest import exec_test, elem, sync_stream import constants as cs import ns def make_pubsub_event(from_, node, *contents): return elem('message', from_=from_)( elem((ns.PUBSUB_EVENT), 'event')( elem('items', node=node)( elem('item')( *contents ) ) ) ) def test(q, bus, conn, stream): # event node without NS message = elem('message', from_='bob@foo.com')( elem('event')( elem('items', node=ns.GEOLOC)( elem('item', id='12345')( elem(ns.GEOLOC, 'geoloc')( elem ('country') (u'France')))))) stream.send(message) # event node with a wrong NS message = elem('message', from_='bob@foo.com')( elem('badger', 'event')( elem('items', node=ns.GEOLOC)( elem('item', id='12345')( elem(ns.GEOLOC, 'geoloc')( elem ('country') (u'France')))))) stream.send(message) # event node without 'from' message = elem('message')( elem((ns.PUBSUB_EVENT), 'event')( elem('items', node=ns.GEOLOC)( elem('item', id='12345')( elem(ns.GEOLOC, 'geoloc')( elem ('country') (u'France')))))) stream.send(message) # event node with an invalid 'from' message = elem('message', from_='aaaa')( elem((ns.PUBSUB_EVENT), 'event')( elem('items', node=ns.GEOLOC)( elem('item', id='12345')( elem(ns.GEOLOC, 'geoloc')( elem ('country') (u'France')))))) stream.send(message) # no items node message = elem('message', from_='bob@foo.com')( elem((ns.PUBSUB_EVENT), 'event')()) stream.send(message) # no item node message = elem('message', from_='bob@foo.com')( elem((ns.PUBSUB_EVENT), 'event')( elem('items', node=ns.GEOLOC)())) stream.send(message) # item node doesn't have any child message = elem('message', from_='bob@foo.com')( elem((ns.PUBSUB_EVENT), 'event')( elem('items', node=ns.GEOLOC)( elem('item', id='12345')()))) stream.send(message) # the child of the item node doesn't have a NS message = elem('message', from_='bob@foo.com')( elem((ns.PUBSUB_EVENT), 'event')( elem('items', node=ns.GEOLOC)( elem('item', id='12345')( elem('geoloc')( elem ('country') (u'France')))))) stream.send(message) # valid but unknown pubsub notification message = elem('message', from_='bob@foo.com')( elem((ns.PUBSUB_EVENT), 'event')( elem('items', node='http://www.badger.com')( elem('item', id='12345')( elem('http://www.badger.com', 'badger')( elem ('mushroom') (u'snake')))))) stream.send(message) sync_stream(q, stream) if __name__ == '__main__': exec_test(test) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/test-resolver.c�����������������������������������������������0000664�0001750�0001750�00000016250�12223562023�024006� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * test-resolver.c - Source for TestResolver * Copyright © 2009 Collabora Ltd. * @author Vivek Dasmohapatra <vivek@collabora.co.uk> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* this code largely culled from gunixresolver.c in glib and modified to * make a dummy resolver we can insert duff records in on the fly */ /* examples: * GResolver *kludged; * kludged = g_object_new (TEST_TYPE_RESOLVER, NULL); * g_resolver_set_default (kludged); * test_resolver_add_SRV (TEST_RESOLVER (kludged), * "xmpp-client", "tcp", "jabber.earth.li", "localhost", 1337); * test_resolver_add_A (TEST_RESOLVER (kludged), "localhost", "127.0.1.1"); */ #include "config.h" #include <stdio.h> #include <glib.h> #ifdef G_OS_WIN32 #include <windows.h> #else #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #endif #include "test-resolver.h" typedef struct _fake_host { char *key; char *addr; } fake_host; typedef struct _fake_serv { char *key; GSrvTarget *srv; } fake_serv; G_DEFINE_TYPE (TestResolver, test_resolver, G_TYPE_RESOLVER); /* ************************************************************************* */ static gchar * _service_rrname (const char *service, const char *protocol, const char *domain) { gchar *rrname, *ascii_domain; ascii_domain = g_hostname_to_ascii (domain); rrname = g_strdup_printf ("_%s._%s.%s", service, protocol, ascii_domain); g_free (ascii_domain); return rrname; } static GList * find_fake_services (TestResolver *tr, const char *name) { GList *fake = NULL; GList *rval = NULL; for (fake = tr->fake_SRV; fake != NULL; fake = g_list_next (fake)) { fake_serv *entry = fake->data; if (entry != NULL && !g_strcmp0 (entry->key, name)) rval = g_list_append (rval, g_srv_target_copy (entry->srv)); } return rval; } static GList * find_fake_hosts (TestResolver *tr, const char *name) { GList *fake = NULL; GList *rval = NULL; for (fake = tr->fake_A; fake != NULL; fake = g_list_next (fake)) { fake_host *entry = fake->data; if (entry != NULL && !g_strcmp0 (entry->key, name)) rval = g_list_append (rval, g_inet_address_new_from_string (entry->addr)); } return rval; } static void lookup_service_async (GResolver *resolver, const char *rr, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer data) { TestResolver *tr = TEST_RESOLVER (resolver); GList *addr = find_fake_services (tr, rr); GObject *source = G_OBJECT (resolver); GSimpleAsyncResult *res = g_simple_async_result_new (source, cb, data, lookup_service_async); if (addr != NULL) g_simple_async_result_set_op_res_gpointer (res, addr, NULL); else g_simple_async_result_set_error (res, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND, "No fake SRV record registered"); g_simple_async_result_complete_in_idle (res); g_object_unref (res); } static GList * lookup_service_finish (GResolver *resolver, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); if (g_simple_async_result_propagate_error (simple, error)) return NULL; return g_simple_async_result_get_op_res_gpointer (simple); } static GList * lookup_by_name (GResolver *resolver, const gchar *hostname, GCancellable *cancellable, GError **error) { GList *result; result = find_fake_hosts (TEST_RESOLVER (resolver), hostname); if (result == NULL) g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND, "No fake hostname record registered"); return result; } static void lookup_by_name_async (GResolver *resolver, const gchar *hostname, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer data) { GObject *source = G_OBJECT (resolver); GSimpleAsyncResult *res = g_simple_async_result_new (source, cb, data, NULL); GList *addr; GError *error = NULL; addr = lookup_by_name (resolver, hostname, NULL, &error); if (addr != NULL) { g_simple_async_result_set_op_res_gpointer (res, addr, NULL); } else { g_simple_async_result_set_from_error (res, error); g_error_free (error); } g_simple_async_result_complete_in_idle (res); g_object_unref (res); } static GList * lookup_by_name_finish (GResolver *resolver, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); if (g_simple_async_result_propagate_error (simple, error)) return NULL; return g_simple_async_result_get_op_res_gpointer (simple); } /* ************************************************************************* */ static void test_resolver_init (TestResolver *tr) { } static void test_resolver_class_init (TestResolverClass *klass) { GResolverClass *resolver_class = G_RESOLVER_CLASS (klass); resolver_class->lookup_by_name_async = lookup_by_name_async; resolver_class->lookup_by_name_finish = lookup_by_name_finish; resolver_class->lookup_service_async = lookup_service_async; resolver_class->lookup_service_finish = lookup_service_finish; resolver_class->lookup_by_name = lookup_by_name; } void test_resolver_reset (TestResolver *tr) { GList *fake = NULL; for (fake = tr->fake_A; fake != NULL; fake = g_list_next (fake)) { fake_host *entry = fake->data; g_free (entry->key); g_free (entry->addr); g_free (entry); } g_list_free (tr->fake_A); tr->fake_A = NULL; for (fake = tr->fake_SRV; fake != NULL; fake = g_list_next (fake)) { fake_serv *entry = fake->data; g_free (entry->key); g_srv_target_free (entry->srv); g_free (entry); } g_list_free (tr->fake_SRV); tr->fake_SRV = NULL; } gboolean test_resolver_add_A (TestResolver *tr, const char *hostname, const char *addr) { fake_host *entry = g_new0( fake_host, 1 ); entry->key = g_strdup (hostname); entry->addr = g_strdup (addr); tr->fake_A = g_list_append (tr->fake_A, entry); return TRUE; } gboolean test_resolver_add_SRV (TestResolver *tr, const char *service, const char *protocol, const char *domain, const char *addr, guint16 port) { char *key = _service_rrname (service, protocol, domain); fake_serv *entry = g_new0 (fake_serv, 1); GSrvTarget *serv = g_srv_target_new (addr, port, 0, 0); entry->key = key; entry->srv = serv; tr->fake_SRV = g_list_append (tr->fake_SRV, entry); return TRUE; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/ns.py���������������������������������������������������������0000664�0001750�0001750�00000007744�12332440117�022026� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������AMP = "http://jabber.org/protocol/amp" BYTESTREAMS = 'http://jabber.org/protocol/bytestreams' CHAT_STATES = 'http://jabber.org/protocol/chatstates' CAPS = "http://jabber.org/protocol/caps" CLIENT = "jabber:client" DISCO_INFO = "http://jabber.org/protocol/disco#info" DISCO_ITEMS = "http://jabber.org/protocol/disco#items" FEATURE_NEG = 'http://jabber.org/protocol/feature-neg' FILE_TRANSFER = 'http://jabber.org/protocol/si/profile/file-transfer' GEOLOC = 'http://jabber.org/protocol/geoloc' GOOGLE_FEAT_SESSION = 'http://www.google.com/xmpp/protocol/session' GOOGLE_FEAT_SHARE = 'http://google.com/xmpp/protocol/share/v1' GOOGLE_FEAT_VOICE = 'http://www.google.com/xmpp/protocol/voice/v1' GOOGLE_FEAT_VIDEO = 'http://www.google.com/xmpp/protocol/video/v1' GOOGLE_JINGLE_INFO = 'google:jingleinfo' GOOGLE_P2P = "http://www.google.com/transport/p2p" GOOGLE_QUEUE = 'google:queue' GOOGLE_ROSTER = 'google:roster' GOOGLE_SESSION = "http://www.google.com/session" GOOGLE_SESSION_SHARE = "http://www.google.com/session/share" GOOGLE_SESSION_PHONE = "http://www.google.com/session/phone" GOOGLE_SESSION_VIDEO = "http://www.google.com/session/video" GOOGLE_MAIL_NOTIFY = "google:mail:notify" IBB = 'http://jabber.org/protocol/ibb' JINGLE_015 = "http://jabber.org/protocol/jingle" JINGLE_015_AUDIO = "http://jabber.org/protocol/jingle/description/audio" JINGLE_015_VIDEO = "http://jabber.org/protocol/jingle/description/video" JINGLE = "urn:xmpp:jingle:1" JINGLE_ERRORS = "urn:xmpp:jingle:errors:1" JINGLE_RTP = "urn:xmpp:jingle:apps:rtp:1" JINGLE_RTP_AUDIO = "urn:xmpp:jingle:apps:rtp:audio" JINGLE_RTP_VIDEO = "urn:xmpp:jingle:apps:rtp:video" JINGLE_RTP_ERRORS = "urn:xmpp:jingle:apps:rtp:errors:1" JINGLE_RTP_INFO_1 = "urn:xmpp:jingle:apps:rtp:info:1" JINGLE_TRANSPORT_ICEUDP = "urn:xmpp:jingle:transports:ice-udp:1" JINGLE_TRANSPORT_RAWUDP = "urn:xmpp:jingle:transports:raw-udp:1" LAST = "jabber:iq:last" MUC = 'http://jabber.org/protocol/muc' MUC_BYTESTREAM = 'http://telepathy.freedesktop.org/xmpp/protocol/muc-bytestream' MUC_OWNER = '%s#owner' % MUC MUC_ROOMINFO = '%s#roominfo' % MUC MUC_USER = '%s#user' % MUC NICK = "http://jabber.org/protocol/nick" NS_XMPP_SASL = 'urn:ietf:params:xml:ns:xmpp-sasl' NS_XMPP_BIND = 'urn:ietf:params:xml:ns:xmpp-bind' NS_XMPP_TLS = 'urn:ietf:params:xml:ns:xmpp-tls' NS_XMPP_SESSION = 'urn:ietf:params:xml:ns:xmpp-session' OLPC_ACTIVITIES = "http://laptop.org/xmpp/activities" OLPC_ACTIVITIES_NOTIFY = "%s+notify" % OLPC_ACTIVITIES OLPC_ACTIVITY = "http://laptop.org/xmpp/activity" OLPC_ACTIVITY_PROPS = "http://laptop.org/xmpp/activity-properties" OLPC_ACTIVITY_PROPS_NOTIFY = "%s+notify" % OLPC_ACTIVITY_PROPS OLPC_BUDDY = "http://laptop.org/xmpp/buddy" OLPC_BUDDY_PROPS = "http://laptop.org/xmpp/buddy-properties" OLPC_BUDDY_PROPS_NOTIFY = "%s+notify" % OLPC_BUDDY_PROPS OLPC_CURRENT_ACTIVITY = "http://laptop.org/xmpp/current-activity" OLPC_CURRENT_ACTIVITY_NOTIFY = "%s+notify" % OLPC_CURRENT_ACTIVITY PUBSUB = "http://jabber.org/protocol/pubsub" PUBSUB_EVENT = "%s#event" % PUBSUB RECEIPTS = "urn:xmpp:receipts" REGISTER = "jabber:iq:register" ROSTER = "jabber:iq:roster" SEARCH = 'jabber:iq:search' SI = 'http://jabber.org/protocol/si' SI_MULTIPLE = 'http://telepathy.freedesktop.org/xmpp/si-multiple' STANZA = "urn:ietf:params:xml:ns:xmpp-stanzas" STREAMS = "urn:ietf:params:xml:ns:xmpp-streams" TEMPPRES = "urn:xmpp:temppres:0" TUBES = 'http://telepathy.freedesktop.org/xmpp/tubes' MUJI = 'http://telepathy.freedesktop.org/xmpp/muji' VCARD_TEMP = 'vcard-temp' VCARD_TEMP_UPDATE = 'vcard-temp:x:update' X_DATA = 'jabber:x:data' X_DELAY = 'jabber:x:delay' XML = 'http://www.w3.org/XML/1998/namespace' X_OOB = 'jabber:x:oob' GABBLE_CAPS="http://telepathy.freedesktop.org/caps" PRESENCE_INVISIBLE = 'presence-invisible' PRIVACY = 'jabber:iq:privacy' INVISIBLE = 'urn:xmpp:invisible:0' GOOGLE_SHARED_STATUS = 'google:shared-status' VERSION = 'jabber:iq:version' TP_FT_METADATA_SERVICE = 'http://telepathy.freedesktop.org/xmpp/file-transfer-service' TP_FT_METADATA = 'http://telepathy.freedesktop.org/xmpp/file-transfer-metadata' ����������������������������telepathy-gabble-0.18.3/tests/twisted/test-debug.py�������������������������������������������������0000664�0001750�0001750�00000003642�12332441362�023445� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test the debug message interface. """ import dbus from servicetest import assertEquals, sync_dbus, call_async, ProxyWrapper from servicetest import EventPattern from gabbletest import exec_test import constants as cs from config import DEBUGGING path = '/org/freedesktop/Telepathy/debug' iface = 'org.freedesktop.Telepathy.Debug' def test(q, bus, conn, stream): messages = [] def new_message(timestamp, domain, level, string): messages.append((timestamp, domain, level, string)) debug = ProxyWrapper(bus.get_object(conn.bus_name, path), iface) debug.connect_to_signal('NewDebugMessage', new_message) if not DEBUGGING: # If we're built with --disable-debug, check that the Debug object # isn't present. call_async(q, debug, 'GetMessages') q.expect('dbus-error', method='GetMessages') return assert len(debug.GetMessages()) > 0 # Turn signalling on and generate some messages. assert len(messages) == 0 assert debug.Properties.Get(iface, 'Enabled') == False debug.Properties.Set(iface, 'Enabled', True) channel_path = conn.RequestChannel( cs.CHANNEL_TYPE_TEXT, cs.HT_CONTACT, conn.GetSelfHandle(), True) q.expect_many( EventPattern ('dbus-signal', signal='NewChannel'), EventPattern ('dbus-signal', signal = 'NewDebugMessage')) assert len(messages) > 0 # Turn signalling off and check we don't get any more messages. debug.Properties.Set(iface, 'Enabled', False) sync_dbus(bus, q, conn) snapshot = list(messages) channel = bus.get_object(conn.bus_name, channel_path) channel.Close(dbus_interface=cs.CHANNEL) q.expect('dbus-signal', signal='Closed') conn.RequestChannel( cs.CHANNEL_TYPE_TEXT, cs.HT_CONTACT, conn.GetSelfHandle(), True) q.expect('dbus-signal', signal='NewChannel') assertEquals (snapshot, messages) if __name__ == '__main__': exec_test(test) ����������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/connect/������������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�022463� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/connect/disco-facebook.py�������������������������������������0000664�0001750�0001750�00000003026�12225363340�025677� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test that Gabble is tolerant of non-RFC-compliance from Facebook. https://bugs.freedesktop.org/show_bug.cgi?id=68829 """ from gabbletest import exec_test, XmppXmlStream import constants as cs import ns from twisted.words.xish import xpath def test(q, bus, conn, stream): conn.Connect() # everything is fine and actually very boring q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]), q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) class XmppXmlStreamFacebook201309(XmppXmlStream): """As of 2013-09, a new version of Facebook's XMPP server (used consistently for beta.chat.facebook.com, and gradually being rolled out for chat.facebook.com users) omits the 'from' attribute in its disco reply. The disco reply is otherwise correct. """ def _cb_disco_iq(self, iq): nodes = xpath.queryForNodes( "/iq/query[@xmlns='" + ns.DISCO_INFO + "']", iq) query = nodes[0] for feature in self.disco_features: query.addChild(elem('feature', var=feature)) iq['type'] = 'result' # The Facebook server's IQ responses have neither 'from' nor 'to' try: del iq['from'] except KeyError: pass try: del iq['to'] except KeyError: pass self.send(iq) if __name__ == '__main__': exec_test(test, protocol=XmppXmlStreamFacebook201309, do_connect=False) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/connect/disconnect-timeout.py���������������������������������0000644�0001750�0001750�00000001250�12225363340�026637� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Disconnect the connection but the server doesn't send its stream close stanza. After a while Gabble gives up, force the closing and the Disconnect D-Bus call returns. """ from gabbletest import exec_test from servicetest import call_async, EventPattern import constants as cs def test(q, bus, conn, stream): call_async(q, conn, 'Disconnect') q.expect_many( EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_REQUESTED]), EventPattern('stream-closed')) q.expect('dbus-return', method='Disconnect') if __name__ == '__main__': # Gabble will time out after 5 seconds exec_test(test, timeout=10) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/connect/disco-error-from-bare-jid.py��������������������������0000644�0001750�0001750�00000002575�12225363340�027701� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" When we connect, Gabble sends a disco request both to the server, and to our own bare JID (to find out whether we support PEP). Some servers return errors from the latter; Gabble should ignore the error, and connect anyway. This tests <https://bugs.freedesktop.org/show_bug.cgi?id=28599> """ from gabbletest import exec_test, XmppXmlStream, elem, send_error_reply import constants as cs import ns def test(q, bus, conn, stream): conn.Connect() # We start connecting... q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]), # ...and then we finish connecting, despite the server having got upset # when we auto-discoed. Party on! q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) class BareJidDiscoErrorXmlStream(XmppXmlStream): def _cb_bare_jid_disco_iq(self, iq): """ \o\ /o/ <o/ \o> /o> ... "Crap! It's the cops! Turn the music off!" """ send_error_reply(self, iq, error_stanza=elem('error')( elem(ns.STANZA, 'feature-not-implemented'), elem(ns.STANZA, 'text')( u'No, officer! This is certainly not an illegal party.') )) if __name__ == '__main__': exec_test(test, protocol=BareJidDiscoErrorXmlStream, do_connect=False) �����������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/connect/torture.py��������������������������������������������0000664�0001750�0001750�00000001304�12225363340�024530� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" This test does nothing besides connect, and then disconnect as soon as the session is established, two thousand times. It was used to smoke out a bug where connections were leaked (which ultimately meant that new connections could not be established, since the file descriptors were leaked too); it may also be useful for profiling the connection process (and test framework). """ from gabbletest import exec_test import os if os.environ.get('REALLY_TORTURE', '') != 'yes': raise SystemExit(77) def test(q, bus, conn, stream): pass def main(): for i in xrange(0, 2000): print i exec_test(test) print "we partied like it's %i" % i if __name__ == '__main__': main() ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/connect/test-connection-params.py�����������������������������0000664�0001750�0001750�00000003272�12225363340�027427� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test connecting with different ContactList.DownloadAtConnection values """ import dbus from servicetest import EventPattern from gabbletest import exec_test, sync_stream, call_async import constants as cs import ns forbidden = [EventPattern('stream-iq', query_ns=ns.ROSTER)] def test_get_roster(q, bus, conn, stream): # DownloadAtConnection = True, so gabble should get the roster # automatically q.expect('stream-iq', query_ns=ns.ROSTER) # but calling ContactList.Download should not try and get the # roster again q.forbid_events(forbidden) conn.ContactList.Download() sync_stream(q, stream) q.unforbid_events(forbidden) def test_dont_get_roster(q, bus, conn, stream): # DownloadAtConnection = False, so let's make sure the roster # isn't fetched automatically q.forbid_events(forbidden) conn.Connect() q.expect_many(EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])) sync_stream(q, stream) q.unforbid_events(forbidden) # seems fine, now calling Download should try and get the roster # successfully. call_async(q, conn.ContactList, 'Download') q.expect_many(EventPattern('stream-iq', query_ns=ns.ROSTER), EventPattern('dbus-return', method='Download')) if __name__ == '__main__': # Parameter DownloadAtConnection = True exec_test(test_get_roster, params={cs.CONN_IFACE_CONTACT_LIST + '.DownloadAtConnection': True}) # Parameter DownloadAtConnection = False exec_test(test_dont_get_roster, params={cs.CONN_IFACE_CONTACT_LIST + '.DownloadAtConnection': False}, do_connect=False) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/connect/test-nonblocking-tls.py�������������������������������0000644�0001750�0001750�00000011330�12225363340�027102� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test connecting to a server with 2 accounts. Check one account does not block the second account. """ import os import sys import dbus import servicetest from twisted.words.xish import domish from twisted.words.protocols.jabber import xmlstream import twisted.internet.protocol from twisted.internet import reactor from servicetest import (Event, unwrap) from gabbletest import ( make_connection, make_stream, XmppAuthenticator, XmppXmlStream, disconnect_conn, GabbleAuthenticator) import constants as cs NS_XMPP_TLS = 'urn:ietf:params:xml:ns:xmpp-tls' NS_XMPP_SASL = 'urn:ietf:params:xml:ns:xmpp-sasl' class BlockForeverTlsAuthenticator(GabbleAuthenticator): """A TLS stream authenticator that is deliberately broken. It sends <proceed/> to the client but then do nothing, so the TLS handshake will not work. Useful for testing regression of bug #14341.""" def __init__(self, username, password): GabbleAuthenticator.__init__(self, username, password) self.username = username self.password = password self.authenticated = False def streamStarted(self, root=None): if root: self.xmlstream.sid = root.getAttribute('id') self.xmlstream.sendHeader() features = domish.Element((xmlstream.NS_STREAMS, 'features')) mechanisms = features.addElement((NS_XMPP_SASL, 'mechanisms')) mechanism = mechanisms.addElement('mechanism', content='DIGEST-MD5') starttls = features.addElement((NS_XMPP_TLS, 'starttls')) starttls.addElement('required') self.xmlstream.send(features) self.xmlstream.addOnetimeObserver("/starttls", self.auth) def auth(self, auth): proceed = domish.Element((NS_XMPP_TLS, 'proceed')) self.xmlstream.send(proceed) return; # auth blocks self.xmlstream.reset() self.authenticated = True def test(q, bus, conn1, conn2, stream1, stream2): # Connection 1 conn1.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) # Connection 1 blocks because the fake jabber server behind conn1 does not # proceed to the tls handshake. The second connection is independant and # should work. # Connection 2 conn2.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) q.expect('stream-authenticated') q.expect('dbus-signal', signal='PresencesChanged', args=[{1L: (cs.PRESENCE_AVAILABLE, 'available', '')}]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) # Disconnection 2 disconnect_conn(q, conn2, stream2) if __name__ == '__main__': queue = servicetest.IteratingEventQueue(None) queue.verbose = ( os.environ.get('CHECK_TWISTED_VERBOSE', '') != '' or '-v' in sys.argv) bus = dbus.SessionBus() params = { 'account': 'test1@localhost/Resource', 'password': 'pass', 'resource': 'Resource', 'server': 'localhost', 'port': dbus.UInt32(4242), } conn1, jid1 = make_connection(bus, queue.append, params) authenticator = BlockForeverTlsAuthenticator('test1', 'pass') stream1 = make_stream(queue.append, authenticator, protocol=XmppXmlStream) factory = twisted.internet.protocol.Factory() factory.protocol = lambda:stream1 port1 = reactor.listenTCP(4242, factory, interface='localhost') params = { 'account': 'test2@localhost/Resource', 'password': 'pass', 'resource': 'Resource', 'server': 'localhost', 'port': dbus.UInt32(4343), } conn2, jid2 = make_connection(bus, queue.append, params) authenticator = XmppAuthenticator('test2', 'pass') stream2 = make_stream(queue.append, authenticator, protocol=XmppXmlStream) factory = twisted.internet.protocol.Factory() factory.protocol = lambda:stream2 port1 = reactor.listenTCP(4343, factory, interface='localhost') bus.add_signal_receiver( lambda *args, **kw: queue.append(Event('dbus-signal', path=unwrap(kw['path']), signal=kw['member'], args=map(unwrap, args), interface=kw['interface'])), None, # signal name None, # interface None, path_keyword='path', member_keyword='member', interface_keyword='interface', byte_arrays=True ) try: test(queue, bus, conn1, conn2, stream1, stream2) finally: try: conn1.Disconnect() conn2.Disconnect() except dbus.DBusException, e: pass ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/connect/network-error.py��������������������������������������0000644�0001750�0001750�00000001411�12225363340�025641� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Connection is disconnected because server closes its TCP stream abruptly. """ from gabbletest import exec_test from servicetest import EventPattern import constants as cs import sys def test(q, bus, conn, stream): # server closes its stream stream.transport.loseConnection() # Gabble disconnect and close its connection q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_NONE_SPECIFIED]) q.expect('dbus-signal', signal='NameOwnerChanged', predicate=lambda e: cs.CONN + '.gabble.jabber' in str(e.args[0]) and str(e.args[1]) != '' and str(e.args[2]) == '') if __name__ == '__main__': exec_test(test) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/connect/test-fail.py������������������������������������������0000644�0001750�0001750�00000006404�12225363340�024720� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test various ways in which connections can fail. """ from twisted.words.xish import domish from twisted.words.protocols.jabber import xmlstream import dbus from servicetest import assertEquals from gabbletest import exec_test, GabbleAuthenticator import constants as cs import ns def test_network_error(q, bus, conn, stream): conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) # FIXME: this is G_IO_ERROR_FAILED, which we can't really map to anything # better than NetworkError. The debug message says "Connection refused", # so something, somewhere, ought to be able to do better, and give us # enough information to produce cs.CONNECTION_REFUSED. new = q.expect('dbus-signal', signal='ConnectionError') assertEquals(cs.NETWORK_ERROR, new.args[0]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_NETWORK_ERROR]) def test_conflict_after_connect(q, bus, conn, stream): stream.send_stream_error('conflict') new = q.expect('dbus-signal', signal='ConnectionError') assertEquals(cs.CONNECTION_REPLACED, new.args[0]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_NAME_IN_USE]) class StreamErrorAuthenticator(GabbleAuthenticator): def __init__(self, stream_error): GabbleAuthenticator.__init__(self, username='n/a', password='n/a') self.__stream_error = stream_error def streamStarted(self, root=None): if root: self.xmlstream.sid = root.getAttribute('id') self.xmlstream.sendHeader() no = domish.Element((xmlstream.NS_STREAMS, 'error')) no.addElement((ns.STREAMS, self.__stream_error)) self.xmlstream.send(no) def test_stream_conflict_during_connect(q, bus, conn, stream): conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) new = q.expect('dbus-signal', signal='ConnectionError') assertEquals(cs.ALREADY_CONNECTED, new.args[0]) old = q.expect('dbus-signal', signal='StatusChanged') status, reason = old.args assertEquals(cs.CONN_STATUS_DISCONNECTED, status) assertEquals(cs.CSR_NAME_IN_USE, reason) def test_host_unknown(q, bus, conn, stream): conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) new = q.expect('dbus-signal', signal='ConnectionError') assertEquals(cs.AUTHENTICATION_FAILED, new.args[0]) old = q.expect('dbus-signal', signal='StatusChanged') status, reason = old.args assertEquals(cs.CONN_STATUS_DISCONNECTED, status) assertEquals(cs.CSR_AUTHENTICATION_FAILED, reason) if __name__ == '__main__': exec_test(test_network_error, {'port': dbus.UInt32(4243)}, do_connect=False) exec_test(test_conflict_after_connect) exec_test(test_stream_conflict_during_connect, authenticator=StreamErrorAuthenticator('conflict'), do_connect=False) exec_test(test_host_unknown, {'server': 'localhost', 'account': 'test@example.org', }, authenticator=StreamErrorAuthenticator('host-unknown'), do_connect=False) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/connect/test-twice.py�����������������������������������������0000664�0001750�0001750�00000005007�12332441362�025120� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test connecting to a server with 2 accounts, testing XmppAuthenticator and JabberAuthenticator """ import os import sys import dbus import constants as cs from gabbletest import exec_test from rostertest import expect_contact_list_signals, check_contact_list_signals from servicetest import assertLength def test(q, bus, conns, streams): conn1, conn2 = conns stream1, stream2 = streams # Connection 1 conn1.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED], path=conn1.object.object_path) q.expect('stream-authenticated') q.expect('dbus-signal', signal='PresencesChanged', args=[{1L: (cs.PRESENCE_AVAILABLE, 'available', '')}], path=conn1.object.object_path) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED], path=conn1.object.object_path) pairs = expect_contact_list_signals(q, bus, conn1, ['publish', 'subscribe', 'stored']) check_contact_list_signals(q, bus, conn1, pairs.pop(0), cs.HT_LIST, 'publish', []) check_contact_list_signals(q, bus, conn1, pairs.pop(0), cs.HT_LIST, 'subscribe', []) check_contact_list_signals(q, bus, conn1, pairs.pop(0), cs.HT_LIST, 'stored', []) assertLength(0, pairs) # i.e. we popped and checked all of them # Connection 2 conn2.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED], path=conn2.object.object_path) q.expect('stream-authenticated') q.expect('dbus-signal', signal='PresencesChanged', args=[{1L: (cs.PRESENCE_AVAILABLE, 'available', '')}], path=conn2.object.object_path) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED], path=conn2.object.object_path) pairs = expect_contact_list_signals(q, bus, conn2, ['publish', 'subscribe', 'stored']) check_contact_list_signals(q, bus, conn2, pairs.pop(0), cs.HT_LIST, 'publish', []) check_contact_list_signals(q, bus, conn2, pairs.pop(0), cs.HT_LIST, 'subscribe', []) check_contact_list_signals(q, bus, conn2, pairs.pop(0), cs.HT_LIST, 'stored', []) assertLength(0, pairs) # i.e. we popped and checked all of them if __name__ == '__main__': exec_test(test, num_instances=2, do_connect=False) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/connect/disco-no-reply.py�������������������������������������0000644�0001750�0001750�00000001725�12225363340�025675� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test that Gabble disconnects connection if it doesn't receive a response to its initial service discovery request to the server """ from gabbletest import exec_test, XmppXmlStream import constants as cs def test(q, bus, conn, stream): conn.Connect() # connecting q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]), # We are disconnected with Connection_Status_Reason_Network_Error as the # disco request timed out q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_NETWORK_ERROR]), class JabberXmlStreamNoDiscoReply(XmppXmlStream): """Subclass XmppXmlStream not to respond to disco requests to the server.""" def _cb_disco_iq (self, iq): pass if __name__ == '__main__': # telepathy-gabble-debug has been tweaked to time out after 3 seconds exec_test(test, protocol=JabberXmlStreamNoDiscoReply, do_connect=False) �������������������������������������������telepathy-gabble-0.18.3/tests/twisted/connect/test-success.py���������������������������������������0000644�0001750�0001750�00000001100�12225363340�025441� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test connecting to a server. """ from gabbletest import exec_test import constants as cs def test(q, bus, conn, stream): conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) q.expect('stream-authenticated') q.expect('dbus-signal', signal='PresencesChanged', args=[{1L: (cs.PRESENCE_AVAILABLE, 'available', '')}]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) if __name__ == '__main__': exec_test(test, do_connect=False) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/connect/stream-closed.py��������������������������������������0000644�0001750�0001750�00000001042�12225363340�025563� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Connection is disconnected because server closes its XMPP stream. """ from gabbletest import exec_test from servicetest import EventPattern import constants as cs def test(q, bus, conn, stream): # server closes its stream stream.sendFooter() # Gabble disconnect and close its connection q.expect_many( EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_NETWORK_ERROR]), EventPattern('stream-closed')) if __name__ == '__main__': exec_test(test) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/constants.py��������������������������������������������������0000664�0001750�0001750�00000041743�12332441362�023422� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Some handy constants for other tests to share and enjoy. """ from dbus import PROPERTIES_IFACE CM = "org.freedesktop.Telepathy.ConnectionManager" HT_NONE = 0 HT_CONTACT = 1 HT_ROOM = 2 HT_LIST = 3 HT_GROUP = 4 CHANNEL = "org.freedesktop.Telepathy.Channel" CHANNEL_IFACE_CALL_STATE = CHANNEL + ".Interface.CallState" CHANNEL_IFACE_CHAT_STATE = CHANNEL + '.Interface.ChatState' CHANNEL_IFACE_DESTROYABLE = CHANNEL + ".Interface.Destroyable" CHANNEL_IFACE_DTMF = CHANNEL + ".Interface.DTMF" CHANNEL_IFACE_GROUP = CHANNEL + ".Interface.Group" CHANNEL_IFACE_HOLD = CHANNEL + ".Interface.Hold" CHANNEL_IFACE_MEDIA_SIGNALLING = CHANNEL + ".Interface.MediaSignalling" CHANNEL_IFACE_MESSAGES = CHANNEL + ".Interface.Messages" CHANNEL_IFACE_PASSWORD = CHANNEL + ".Interface.Password" CHANNEL_IFACE_TUBE = CHANNEL + ".Interface.Tube" CHANNEL_IFACE_SASL_AUTH = CHANNEL + ".Interface.SASLAuthentication" CHANNEL_IFACE_CONFERENCE = CHANNEL + '.Interface.Conference' CHANNEL_IFACE_ROOM = CHANNEL + '.Interface.Room2' CHANNEL_IFACE_ROOM_CONFIG = CHANNEL + '.Interface.RoomConfig1' CHANNEL_IFACE_SUBJECT = CHANNEL + '.Interface.Subject2' CHANNEL_IFACE_FILE_TRANSFER_METADATA = CHANNEL + '.Interface.FileTransfer.Metadata' CHANNEL_TYPE_CALL = CHANNEL + ".Type.Call1" CHANNEL_TYPE_CONTACT_LIST = CHANNEL + ".Type.ContactList" CHANNEL_TYPE_CONTACT_SEARCH = CHANNEL + ".Type.ContactSearch" CHANNEL_TYPE_TEXT = CHANNEL + ".Type.Text" CHANNEL_TYPE_TUBES = CHANNEL + ".Type.Tubes" CHANNEL_TYPE_STREAM_TUBE = CHANNEL + ".Type.StreamTube" CHANNEL_TYPE_DBUS_TUBE = CHANNEL + ".Type.DBusTube" CHANNEL_TYPE_STREAMED_MEDIA = CHANNEL + ".Type.StreamedMedia" CHANNEL_TYPE_TEXT = CHANNEL + ".Type.Text" CHANNEL_TYPE_FILE_TRANSFER = CHANNEL + ".Type.FileTransfer" CHANNEL_TYPE_SERVER_AUTHENTICATION = \ CHANNEL + ".Type.ServerAuthentication" CHANNEL_TYPE_SERVER_TLS_CONNECTION = \ CHANNEL + ".Type.ServerTLSConnection" TP_AWKWARD_PROPERTIES = "org.freedesktop.Telepathy.Properties" PROPERTY_FLAG_READ = 1 PROPERTY_FLAG_WRITE = 2 PROPERTY_FLAGS_RW = PROPERTY_FLAG_READ | PROPERTY_FLAG_WRITE CHANNEL_TYPE = CHANNEL + '.ChannelType' TARGET_HANDLE_TYPE = CHANNEL + '.TargetHandleType' TARGET_HANDLE = CHANNEL + '.TargetHandle' TARGET_ID = CHANNEL + '.TargetID' REQUESTED = CHANNEL + '.Requested' INITIATOR_HANDLE = CHANNEL + '.InitiatorHandle' INITIATOR_ID = CHANNEL + '.InitiatorID' INTERFACES = CHANNEL + '.Interfaces' INITIAL_AUDIO = CHANNEL_TYPE_STREAMED_MEDIA + '.InitialAudio' INITIAL_VIDEO = CHANNEL_TYPE_STREAMED_MEDIA + '.InitialVideo' IMMUTABLE_STREAMS = CHANNEL_TYPE_STREAMED_MEDIA + '.ImmutableStreams' CALL_INITIAL_AUDIO = CHANNEL_TYPE_CALL + '.InitialAudio' CALL_INITIAL_AUDIO_NAME = CHANNEL_TYPE_CALL + '.InitialAudioName' CALL_INITIAL_VIDEO = CHANNEL_TYPE_CALL + '.InitialVideo' CALL_INITIAL_VIDEO_NAME = CHANNEL_TYPE_CALL + '.InitialVideoName' CALL_MUTABLE_CONTENTS = CHANNEL_TYPE_CALL + '.MutableContents' CALL_CONTENT = 'org.freedesktop.Telepathy.Call1.Content' CALL_CONTENT_IFACE_MEDIA = \ 'org.freedesktop.Telepathy.Call1.Content.Interface.Media' CALL_CONTENT_IFACE_DTMF = \ 'org.freedesktop.Telepathy.Call1.Content.Interface.DTMF' CALL_CONTENT_MEDIADESCRIPTION = \ 'org.freedesktop.Telepathy.Call1.Content.MediaDescription' CALL_STREAM = 'org.freedesktop.Telepathy.Call1.Stream' CALL_STREAM_IFACE_MEDIA = \ 'org.freedesktop.Telepathy.Call1.Stream.Interface.Media' CALL_STREAM_ENDPOINT = 'org.freedesktop.Telepathy.Call1.Stream.Endpoint' CALL_MEDIA_TYPE_AUDIO = 0 CALL_MEDIA_TYPE_VIDEO = 1 CALL_CONTENT_PACKETIZATION_RTP = 0 CALL_CONTENT_PACKETIZATION_RAW = 1 CALL_CONTENT_PACKETIZATION_MSN_WEBCAM = 2 CALL_STREAM_TRANSPORT_UNKNOWN = 0 CALL_STREAM_TRANSPORT_RAW_UDP = 1 CALL_STREAM_TRANSPORT_ICE = 2 CALL_STREAM_TRANSPORT_GTALK_P2P = 3 CALL_STREAM_TRANSPORT_WLM_2009 = 4 CALL_STREAM_TRANSPORT_SHM = 5 CALL_STREAM_TRANSPORT_MULTICAST = 6 #for streamed media CALL_STATE_RINGING = 1 CALL_STATE_HELD = 4 CALL_STATE_UNKNOWN = 0, CALL_STATE_PENDING_INITIATOR = 1 CALL_STATE_INITIALISING = 2 CALL_STATE_INITIALISED = 3 CALL_STATE_ACCEPTED = 4 CALL_STATE_ACTIVE = 5 CALL_STATE_ENDED = 6 CALL_FLAG_LOCALLY_HELD = 1 CALL_FLAG_LOCALLY_RINGING = 2 CALL_FLAG_LOCALLY_QUEUED = 4 CALL_FLAG_FORWARDED = 8 CALL_FLAG_CLEARING = 16 CALL_MEMBER_FLAG_RINGING = 1 CALL_MEMBER_FLAG_HELD = 2 CALL_DISPOSITION_NONE = 0 CALL_DISPOSITION_INITIAL = 1 CALL_SENDING_STATE_NONE = 0 CALL_SENDING_STATE_PENDING_SEND = 1 CALL_SENDING_STATE_SENDING = 2 CALL_SENDING_STATE_PENDING_STOP_SENDING = 3 CALL_STREAM_FLOW_STATE_STOPPED = 0 CALL_STREAM_FLOW_STATE_PENDING_START = 1 CALL_STREAM_FLOW_STATE_PENDING_STOP = 2 CALL_STREAM_FLOW_STATE_STARTED = 3 CALL_STREAM_ENDPOINT_STATE_CONNECTING = 0 CALL_STREAM_ENDPOINT_STATE_PROVISIONALLY_CONNECTED = 1 CALL_STREAM_ENDPOINT_STATE_FULLY_CONNECTED = 2 CALL_STREAM_ENDPOINT_STATE_EXHAUSTED_CANDIDATES = 3 CALL_STREAM_ENDPOINT_STATE_FAILED = 4 CALL_STREAM_CANDIDATE_TYPE_HOST = 1 CALL_STREAM_CANDIDATE_TYPE_SERVER_REFLEXIVE = 2 CALL_STREAM_CANDIDATE_TYPE_RELAY = 4 CALL_STATE_CHANGE_REASON_UNKNOWN = 0 CALL_STATE_CHANGE_REASON_PROGRESS_MADE = 1 CALL_STATE_CHANGE_REASON_USER_REQUESTED = 2 CALL_STATE_CHANGE_REASON_FORWARDED = 3 CALL_STATE_CHANGE_REASON_REJECTED = 4 CALL_STATE_CHANGE_REASON_NO_ANSWER = 5 CALL_STATE_CHANGE_REASON_INVALID_CONTACT = 6 CALL_STATE_CHANGE_REASON_PERMISSION_DENIED = 7 CALL_STATE_CHANGE_REASON_BUSY = 8 CALL_STATE_CHANGE_REASON_INTERNAL_ERROR = 9 CALL_STATE_CHANGE_REASON_SERVICE_ERROR = 10 CALL_STATE_CHANGE_REASON_NETWORK_ERROR = 11 CALL_STATE_CHANGE_REASON_MEDIA_ERROR = 12 CALL_STATE_CHANGE_REASON_CONNECTIVITY_ERROR = 13 CALL_STREAM_COMPONENT_UNKNOWN = 0 CALL_STREAM_COMPONENT_DATA = 1 CALL_STREAM_COMPONENT_CONTROL = 2 SUBSCRIPTION_STATE_UNKNOWN = 0 SUBSCRIPTION_STATE_NO = 1 SUBSCRIPTION_STATE_REMOVED_REMOTELY = 2 SUBSCRIPTION_STATE_ASK = 3 SUBSCRIPTION_STATE_YES = 4 CONTACT_LIST_STATE_NONE = 0 CONTACT_LIST_STATE_WAITING = 1 CONTACT_LIST_STATE_FAILURE = 2 CONTACT_LIST_STATE_SUCCESS = 3 CONN = "org.freedesktop.Telepathy.Connection" CONN_IFACE_AVATARS = CONN + '.Interface.Avatars' CONN_IFACE_ALIASING = CONN + '.Interface.Aliasing' CONN_IFACE_CAPS = CONN + '.Interface.Capabilities' CONN_IFACE_CONTACTS = CONN + '.Interface.Contacts' CONN_IFACE_CONTACT_CAPS = CONN + '.Interface.ContactCapabilities' CONN_IFACE_CONTACT_INFO = CONN + ".Interface.ContactInfo" CONN_IFACE_PRESENCE = CONN + '.Interface.Presence' CONN_IFACE_SIMPLE_PRESENCE = CONN + '.Interface.SimplePresence' CONN_IFACE_REQUESTS = CONN + '.Interface.Requests' CONN_IFACE_LOCATION = CONN + '.Interface.Location' CONN_IFACE_GABBLE_DECLOAK = CONN + '.Interface.Gabble.Decloak' CONN_IFACE_MAIL_NOTIFICATION = CONN + '.Interface.MailNotification' CONN_IFACE_CONTACT_LIST = CONN + '.Interface.ContactList' CONN_IFACE_CONTACT_GROUPS = CONN + '.Interface.ContactGroups' CONN_IFACE_CLIENT_TYPES = CONN + '.Interface.ClientTypes' CONN_IFACE_POWER_SAVING = CONN + '.Interface.PowerSaving' CONN_IFACE_CONTACT_BLOCKING = CONN + '.Interface.ContactBlocking' CONN_IFACE_ADDRESSING = CONN + '.Interface.Addressing1' ATTR_CONTACT_CAPABILITIES = CONN_IFACE_CONTACT_CAPS + '/capabilities' STREAM_HANDLER = 'org.freedesktop.Telepathy.Media.StreamHandler' ERROR = 'org.freedesktop.Telepathy.Error' INVALID_ARGUMENT = ERROR + '.InvalidArgument' NOT_IMPLEMENTED = ERROR + '.NotImplemented' NOT_AVAILABLE = ERROR + '.NotAvailable' PERMISSION_DENIED = ERROR + '.PermissionDenied' OFFLINE = ERROR + '.Offline' NOT_CAPABLE = ERROR + '.NotCapable' CONNECTION_REFUSED = ERROR + '.ConnectionRefused' CONNECTION_FAILED = ERROR + '.ConnectionFailed' CONNECTION_LOST = ERROR + '.ConnectionLost' CANCELLED = ERROR + '.Cancelled' DISCONNECTED = ERROR + '.Disconnected' REGISTRATION_EXISTS = ERROR + '.RegistrationExists' AUTHENTICATION_FAILED = ERROR + '.AuthenticationFailed' CONNECTION_REPLACED = ERROR + '.ConnectionReplaced' ALREADY_CONNECTED = ERROR + '.AlreadyConnected' NETWORK_ERROR = ERROR + '.NetworkError' NOT_YET = ERROR + '.NotYet' INVALID_HANDLE = ERROR + '.InvalidHandle' CERT_UNTRUSTED = ERROR + '.Cert.Untrusted' SERVICE_BUSY = ERROR + '.ServiceBusy' SERVICE_CONFUSED = ERROR + '.ServiceConfused' BANNED = ERROR + '.Channel.Banned' UNKNOWN_METHOD = 'org.freedesktop.DBus.Error.UnknownMethod' TUBE_PARAMETERS = CHANNEL_IFACE_TUBE + '.Parameters' TUBE_STATE = CHANNEL_IFACE_TUBE + '.State' STREAM_TUBE_SERVICE = CHANNEL_TYPE_STREAM_TUBE + '.Service' DBUS_TUBE_SERVICE_NAME = CHANNEL_TYPE_DBUS_TUBE + '.ServiceName' DBUS_TUBE_DBUS_NAMES = CHANNEL_TYPE_DBUS_TUBE + '.DBusNames' DBUS_TUBE_SUPPORTED_ACCESS_CONTROLS = CHANNEL_TYPE_DBUS_TUBE + '.SupportedAccessControls' STREAM_TUBE_SUPPORTED_SOCKET_TYPES = CHANNEL_TYPE_STREAM_TUBE + '.SupportedSocketTypes' CONFERENCE_INITIAL_CHANNELS = CHANNEL_IFACE_CONFERENCE + '.InitialChannels' CONFERENCE_INITIAL_INVITEE_HANDLES = CHANNEL_IFACE_CONFERENCE + '.InitialInviteeHandles' CONFERENCE_INITIAL_INVITEE_IDS = CHANNEL_IFACE_CONFERENCE + '.InitialInviteeIDs' CONTACT_SEARCH_ASK = CHANNEL_TYPE_CONTACT_SEARCH + '.AvailableSearchKeys' CONTACT_SEARCH_SERVER = CHANNEL_TYPE_CONTACT_SEARCH + '.Server' CONTACT_SEARCH_STATE = CHANNEL_TYPE_CONTACT_SEARCH + '.SearchState' SEARCH_NOT_STARTED = 0 SEARCH_IN_PROGRESS = 1 SEARCH_MORE_AVAILABLE = 2 SEARCH_COMPLETED = 3 SEARCH_FAILED = 4 TUBE_CHANNEL_STATE_LOCAL_PENDING = 0 TUBE_CHANNEL_STATE_REMOTE_PENDING = 1 TUBE_CHANNEL_STATE_OPEN = 2 TUBE_CHANNEL_STATE_NOT_OFFERED = 3 MEDIA_STREAM_TYPE_AUDIO = 0 MEDIA_STREAM_TYPE_VIDEO = 1 MEDIA_STREAM_BASE_PROTO_UDP = 0 MEDIA_STREAM_BASE_PROTO_TCP = 1 MEDIA_STREAM_TRANSPORT_TYPE_LOCAL = 0 MEDIA_STREAM_TRANSPORT_TYPE_DERIVED = 1 MEDIA_STREAM_TRANSPORT_TYPE_RELAY = 2 SOCKET_ADDRESS_TYPE_UNIX = 0 SOCKET_ADDRESS_TYPE_ABSTRACT_UNIX = 1 SOCKET_ADDRESS_TYPE_IPV4 = 2 SOCKET_ADDRESS_TYPE_IPV6 = 3 SOCKET_ACCESS_CONTROL_LOCALHOST = 0 SOCKET_ACCESS_CONTROL_PORT = 1 SOCKET_ACCESS_CONTROL_NETMASK = 2 SOCKET_ACCESS_CONTROL_CREDENTIALS = 3 TUBE_STATE_LOCAL_PENDING = 0 TUBE_STATE_REMOTE_PENDING = 1 TUBE_STATE_OPEN = 2 TUBE_STATE_NOT_OFFERED = 3 TUBE_TYPE_DBUS = 0 TUBE_TYPE_STREAM = 1 MEDIA_STREAM_DIRECTION_NONE = 0 MEDIA_STREAM_DIRECTION_SEND = 1 MEDIA_STREAM_DIRECTION_RECEIVE = 2 MEDIA_STREAM_DIRECTION_BIDIRECTIONAL = 3 MEDIA_STREAM_PENDING_LOCAL_SEND = 1 MEDIA_STREAM_PENDING_REMOTE_SEND = 2 MEDIA_STREAM_TYPE_AUDIO = 0 MEDIA_STREAM_TYPE_VIDEO = 1 MEDIA_STREAM_STATE_DISCONNECTED = 0 MEDIA_STREAM_STATE_CONNECTING = 1 MEDIA_STREAM_STATE_CONNECTED = 2 MEDIA_STREAM_DIRECTION_NONE = 0 MEDIA_STREAM_DIRECTION_SEND = 1 MEDIA_STREAM_DIRECTION_RECEIVE = 2 MEDIA_STREAM_DIRECTION_BIDIRECTIONAL = 3 FT_STATE_NONE = 0 FT_STATE_PENDING = 1 FT_STATE_ACCEPTED = 2 FT_STATE_OPEN = 3 FT_STATE_COMPLETED = 4 FT_STATE_CANCELLED = 5 FT_STATE_CHANGE_REASON_NONE = 0 FT_STATE_CHANGE_REASON_REQUESTED = 1 FT_STATE_CHANGE_REASON_LOCAL_STOPPED = 2 FT_STATE_CHANGE_REASON_REMOTE_STOPPED = 3 FT_STATE_CHANGE_REASON_LOCAL_ERROR = 4 FT_STATE_CHANGE_REASON_REMOTE_ERROR = 5 FILE_HASH_TYPE_NONE = 0 FILE_HASH_TYPE_MD5 = 1 FILE_HASH_TYPE_SHA1 = 2 FILE_HASH_TYPE_SHA256 = 3 FT_STATE = CHANNEL_TYPE_FILE_TRANSFER + '.State' FT_CONTENT_TYPE = CHANNEL_TYPE_FILE_TRANSFER + '.ContentType' FT_FILENAME = CHANNEL_TYPE_FILE_TRANSFER + '.Filename' FT_SIZE = CHANNEL_TYPE_FILE_TRANSFER + '.Size' FT_CONTENT_HASH_TYPE = CHANNEL_TYPE_FILE_TRANSFER + '.ContentHashType' FT_CONTENT_HASH = CHANNEL_TYPE_FILE_TRANSFER + '.ContentHash' FT_DESCRIPTION = CHANNEL_TYPE_FILE_TRANSFER + '.Description' FT_DATE = CHANNEL_TYPE_FILE_TRANSFER + '.Date' FT_AVAILABLE_SOCKET_TYPES = CHANNEL_TYPE_FILE_TRANSFER + '.AvailableSocketTypes' FT_TRANSFERRED_BYTES = CHANNEL_TYPE_FILE_TRANSFER + '.TransferredBytes' FT_INITIAL_OFFSET = CHANNEL_TYPE_FILE_TRANSFER + '.InitialOffset' FT_FILE_COLLECTION = CHANNEL_TYPE_FILE_TRANSFER + '.FUTURE.FileCollection' FT_URI = CHANNEL_TYPE_FILE_TRANSFER + '.URI' FT_SERVICE_NAME = CHANNEL_IFACE_FILE_TRANSFER_METADATA + '.ServiceName' FT_METADATA = CHANNEL_IFACE_FILE_TRANSFER_METADATA + '.Metadata' GF_CAN_ADD = 1 GF_CAN_REMOVE = 2 GF_CAN_RESCIND = 4 GF_MESSAGE_ADD = 8 GF_MESSAGE_REMOVE = 16 GF_MESSAGE_ACCEPT = 32 GF_MESSAGE_REJECT = 64 GF_MESSAGE_RESCIND = 128 GF_CHANNEL_SPECIFIC_HANDLES = 256 GF_ONLY_ONE_GROUP = 512 GF_HANDLE_OWNERS_NOT_AVAILABLE = 1024 GF_PROPERTIES = 2048 GF_MEMBERS_CHANGED_DETAILED = 4096 GC_REASON_NONE = 0 GC_REASON_OFFLINE = 1 GC_REASON_KICKED = 2 GC_REASON_BUSY = 3 GC_REASON_INVITED = 4 GC_REASON_BANNED = 5 GC_REASON_ERROR = 6 GC_REASON_INVALID_CONTACT = 7 GC_REASON_NO_ANSWER = 8 GC_REASON_RENAMED = 9 GC_REASON_PERMISSION_DENIED = 10 GC_REASON_SEPARATED = 11 HS_UNHELD = 0 HS_HELD = 1 HS_PENDING_HOLD = 2 HS_PENDING_UNHOLD = 3 HSR_NONE = 0 HSR_REQUESTED = 1 HSR_RESOURCE_NOT_AVAILABLE = 2 CONN_STATUS_CONNECTED = 0 CONN_STATUS_CONNECTING = 1 CONN_STATUS_DISCONNECTED = 2 CSR_NONE_SPECIFIED = 0 CSR_REQUESTED = 1 CSR_NETWORK_ERROR = 2 CSR_AUTHENTICATION_FAILED = 3 CSR_ENCRYPTION_ERROR = 4 CSR_NAME_IN_USE = 5 CSR_CERT_NOT_PROVIDED = 6 CSR_CERT_UNTRUSTED = 7 CSR_CERT_EXPIRED = 8 CSR_CERT_NOT_ACTIVATED = 9 CSR_CERT_HOSTNAME_MISMATCH = 10 CSR_CERT_FINGERPRINT_MISMATCH = 11 CSR_CERT_SELF_SIGNED = 12 CSR_CERT_OTHER_ERROR = 13 BUDDY_INFO = 'org.laptop.Telepathy.BuddyInfo' ACTIVITY_PROPERTIES = 'org.laptop.Telepathy.ActivityProperties' CHAT_STATE_GONE = 0 CHAT_STATE_INACTIVE = 1 CHAT_STATE_ACTIVE = 2 CHAT_STATE_PAUSED = 3 CHAT_STATE_COMPOSING = 4 # Channel_Media_Capabilities MEDIA_CAP_AUDIO = 1 MEDIA_CAP_VIDEO = 2 MEDIA_CAP_STUN = 4 MEDIA_CAP_GTALKP2P = 8 MEDIA_CAP_ICEUDP = 16 MEDIA_CAP_IMMUTABLE_STREAMS = 32 CLIENT = 'org.freedesktop.Telepathy.Client' PRESENCE_OFFLINE = 1 PRESENCE_AVAILABLE = 2 PRESENCE_AWAY = 3 PRESENCE_EXTENDED_AWAY = 4 PRESENCE_HIDDEN = 5 PRESENCE_BUSY = 6 PRESENCE_UNKNOWN = 7 PRESENCE_ERROR = 8 CONTACT_INFO_FLAG_CAN_SET = 1 CONTACT_INFO_FLAG_PUSH = 2 CONTACT_INFO_FIELD_FLAG_PARAMETERS_EXACT = 1 CONTACT_INFO_FIELD_FLAG_OVERWRITTEN_BY_NICKNAME = 2 # Channel_Interface_SaslAuthentication SASL_STATUS_NOT_STARTED = 0 SASL_STATUS_IN_PROGRESS = 1 SASL_STATUS_SERVER_SUCCEEDED = 2 SASL_STATUS_CLIENT_ACCEPTED = 3 SASL_STATUS_SUCCEEDED = 4 SASL_STATUS_SERVER_FAILED = 5 SASL_STATUS_CLIENT_FAILED = 6 SASL_ABORT_REASON_INVALID_CHALLENGE = 0 SASL_ABORT_REASON_USER_ABORT = 1 AUTH_METHOD = CHANNEL_TYPE_SERVER_AUTHENTICATION + ".AuthenticationMethod" SASL_AVAILABLE_MECHANISMS = CHANNEL_IFACE_SASL_AUTH + ".AvailableMechanisms" SASL_STATUS = CHANNEL_IFACE_SASL_AUTH + ".SASLStatus" SASL_ERROR = CHANNEL_IFACE_SASL_AUTH + ".SASLError" SASL_ERROR_DETAILS = CHANNEL_IFACE_SASL_AUTH + ".SASLErrorDetails" SASL_CONTEXT = CHANNEL_IFACE_SASL_AUTH + ".SASLContext" SASL_AUTHORIZATION_IDENTITY = CHANNEL_IFACE_SASL_AUTH + ".AuthorizationIdentity" SASL_DEFAULT_REALM = CHANNEL_IFACE_SASL_AUTH + ".DefaultRealm" SASL_DEFAULT_USERNAME = CHANNEL_IFACE_SASL_AUTH + ".DefaultUsername" # Channel_Type_ServerTLSConnection TLS_CERT_PATH = CHANNEL_TYPE_SERVER_TLS_CONNECTION + ".ServerCertificate" TLS_HOSTNAME = CHANNEL_TYPE_SERVER_TLS_CONNECTION + ".Hostname" TLS_REFERENCE_IDENTITIES = \ CHANNEL_TYPE_SERVER_TLS_CONNECTION + ".ReferenceIdentities" # Connection.Interface.Location LOCATION_FEATURE_CAN_SET = 1 # Channel.Type.Text MT_NORMAL = 0 MT_ACTION = 1 MT_NOTICE = 2 MT_AUTO_REPLY = 3 MT_DELIVERY_REPORT = 4 class MessageFlag(object): TRUNCATED = 1 NON_TEXT_CONTENT = 2 SCROLLBACK = 4 RESCUED = 8 class SendError(object): UNKNOWN = 0 OFFLINE = 1 INVALID_CONTACT = 2 PERMISSION_DENIED = 3 TOO_LONG = 4 NOT_IMPLEMENTED = 5 PROTOCOL = 'org.freedesktop.Telepathy.Protocol' PROTOCOL_IFACE_PRESENCES = PROTOCOL + '.Interface.Presence' PROTOCOL_IFACE_ADDRESSING = PROTOCOL + '.Interface.Addressing' PARAM_REQUIRED = 1 PARAM_REGISTER = 2 PARAM_HAS_DEFAULT = 4 PARAM_SECRET = 8 PARAM_DBUS_PROPERTY = 16 AUTHENTICATION = 'org.freedesktop.Telepathy.Authentication' AUTH_TLS_CERT = AUTHENTICATION + ".TLSCertificate" TLS_CERT_STATE_PENDING = 0 TLS_CERT_STATE_ACCEPTED = 1 TLS_CERT_STATE_REJECTED = 2 TLS_REJECT_REASON_UNKNOWN = 0 TLS_REJECT_REASON_UNTRUSTED = 1 # Channel.Interface.Messages MESSAGE_PART_SUPPORT_FLAGS = CHANNEL_IFACE_MESSAGES + '.MessagePartSupportFlags' DELIVERY_REPORTING_SUPPORT = CHANNEL_IFACE_MESSAGES + '.DeliveryReportingSupport' SUPPORTED_CONTENT_TYPES = CHANNEL_IFACE_MESSAGES + '.SupportedContentTypes' MSG_SENDING_FLAGS_REPORT_DELIVERY = 1 MSG_SENDING_FLAGS_REPORT_READ = 2 MSG_SENDING_FLAGS_REPORT_DELETED = 4 DELIVERY_REPORTING_SUPPORT_FLAGS_RECEIVE_FAILURES = 1 DELIVERY_REPORTING_SUPPORT_FLAGS_RECEIVE_SUCCESSES = 2 DELIVERY_REPORTING_SUPPORT_FLAGS_RECEIVE_READ = 4 DELIVERY_REPORTING_SUPPORT_FLAGS_RECEIVE_DELETED = 8 DELIVERY_STATUS_UNKNOWN = 0 DELIVERY_STATUS_DELIVERED = 1 DELIVERY_STATUS_TEMPORARILY_FAILED = 2 DELIVERY_STATUS_PERMANENTLY_FAILED = 3 DELIVERY_STATUS_ACCEPTED = 4 DELIVERY_STATUS_READ = 5 DELIVERY_STATUS_DELETED = 6 MEDIA_STREAM_ERROR_UNKNOWN = 0 MEDIA_STREAM_ERROR_EOS = 1 MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED = 2 MEDIA_STREAM_ERROR_CONNECTION_FAILED = 3 MEDIA_STREAM_ERROR_NETWORK_ERROR = 4 MEDIA_STREAM_ERROR_NO_CODECS = 5 MEDIA_STREAM_ERROR_INVALID_CM_BEHAVIOR = 6 MEDIA_STREAM_ERROR_MEDIA_ERROR = 7 PASSWORD_FLAG_PROVIDE = 8 # Channel.Interface.Room ROOM_NAME = CHANNEL_IFACE_ROOM + '.RoomName' ROOM_SERVER = CHANNEL_IFACE_ROOM + '.Server' # Channel.Interface.Subject SUBJECT = CHANNEL_IFACE_ROOM + '.Subject' SUBJECT_PRESENT = 1 SUBJECT_CAN_SET = 2 �����������������������������telepathy-gabble-0.18.3/tests/twisted/tls/����������������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�021634� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tls/server-tls-channel.py�������������������������������������0000664�0001750�0001750�00000034022�12332440117�025711� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# coding=utf-8 """ Copyright © 2010 Collabora Ltd. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. """ """ Test the server TLS channel """ import base64 import dbus import os from OpenSSL import crypto from twisted.words.protocols.jabber import xmlstream from twisted.words.protocols.jabber.client import IQ from twisted.words.xish import domish, xpath from twisted.internet import ssl import ns from gabbletest import exec_test, XmppAuthenticator from servicetest import ProxyWrapper, EventPattern from servicetest import assertEquals, assertLength, assertSameSets import constants as cs JID = "test@example.org" # the certificate is for the domain name 'weasel-juice.org'. # the files are copied from wocky/tests/certs/tls-[cert,key].pem CA_CERT_HOSTNAME = 'weasel-juice.org' CA_CERT = os.environ.get('GABBLE_TWISTED_PATH', '.') + '/tls-cert.pem' CA_KEY = os.environ.get('GABBLE_TWISTED_PATH', '.') + '/tls-key.pem' class TlsAuthenticator(XmppAuthenticator): def __init__(self, username, password, resource=None): XmppAuthenticator.__init__(self, username, password, resource) self.tls_encrypted = False def streamTLS(self): features = domish.Element((xmlstream.NS_STREAMS, 'features')) starttls = features.addElement((ns.NS_XMPP_TLS, 'starttls')) starttls.addElement('required') self.xmlstream.send(features) self.xmlstream.addOnetimeObserver("/starttls", self.tlsAuth) def streamStarted(self, root=None): self.streamInitialize(root) if self.authenticated and self.tls_encrypted: self.streamIQ() elif self.tls_encrypted: self.streamSASL() else: self.streamTLS() def tlsAuth(self, auth): with open(CA_KEY, 'rb') as f: pem_key = f.read() pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, pem_key, "") with open(CA_CERT, 'rb') as f: pem_cert = f.read() cert = crypto.load_certificate(crypto.FILETYPE_PEM, pem_cert) tls_ctx = ssl.CertificateOptions(privateKey=pkey, certificate=cert) self.xmlstream.send(domish.Element((ns.NS_XMPP_TLS, 'proceed'))) self.xmlstream.transport.startTLS(tls_ctx) self.xmlstream.reset() self.tls_encrypted = True class ServerTlsChanWrapper(ProxyWrapper): def __init__(self, object, default=cs.CHANNEL, interfaces={ "ServerTLSConnection" : cs.CHANNEL_TYPE_SERVER_TLS_CONNECTION}): ProxyWrapper.__init__(self, object, default, interfaces) class TlsCertificateWrapper(ProxyWrapper): def __init__(self, object, default=cs.AUTH_TLS_CERT, interfaces={ "TLSCertificate" : cs.AUTH_TLS_CERT}): ProxyWrapper.__init__(self, object, default, interfaces) def test_disconnect_inbetween(q, bus, conn, stream): # we don't expect a channel at all in this case, # as we lose the connection before the TLS channel is created conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) conn.Disconnect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_REQUESTED]) def is_server_tls_chan_event(event): channels = event.args[0]; if len(channels) > 1: return False path, props = channels[0] return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_SERVER_TLS_CONNECTION def connect_and_get_tls_objects(q, bus, conn, expect_example_jid=True): conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) ev, = q.expect_many( EventPattern('dbus-signal', signal='NewChannels', predicate=is_server_tls_chan_event)) channels = ev.args[0] path, props = channels[0] chan = ServerTlsChanWrapper(bus.get_object(conn.bus_name, path)) hostname = props[cs.TLS_HOSTNAME] certificate_path = props[cs.TLS_CERT_PATH] if expect_example_jid: assertEquals(hostname, 'example.org') return chan, hostname, certificate_path def test_connect_early_close_success(q, bus, conn, stream): chan, hostname, certificate_path = connect_and_get_tls_objects(q, bus, conn) # close the channel early chan.Close() # we expect the fallback verification process to connect successfully, # even if the certificate doesn't match the hostname, as encryption-required is not set q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed'), EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) ) def test_connect_early_close_fail(q, bus, conn, stream): chan, hostname, certificate_path = connect_and_get_tls_objects(q, bus, conn) # close the channel early chan.Close() # we expect the fallback verification process to fail, as there's a hostname mismatch, # encryption-required is set and ignore-ssl-errors is not q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed'), EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_CERT_HOSTNAME_MISMATCH]) ) def rejection_list_match(event): rejections = event.args[0]; if len(rejections) != 1: return False return rejections == [(cs.TLS_REJECT_REASON_UNTRUSTED, cs.CERT_UNTRUSTED, {})] def test_connect_fail(q, bus, conn, stream): chan, hostname, certificate_path = connect_and_get_tls_objects(q, bus, conn) certificate = TlsCertificateWrapper(bus.get_object(conn.bus_name, certificate_path)) certificate.TLSCertificate.Reject([(cs.TLS_REJECT_REASON_UNTRUSTED, cs.CERT_UNTRUSTED, {})]) # we first expect the certificate to be rejected q.expect('dbus-signal', signal='Rejected', predicate=rejection_list_match) # this should trigger a ConnectionError q.expect('dbus-signal', signal='ConnectionError', args=[cs.CERT_UNTRUSTED, {}]) # at this point the channel should be closed q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed') ) # finally, we should receive a StatusChanged signal on the connection q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_CERT_UNTRUSTED]) def test_connect_success(q, bus, conn, stream): chan, hostname, certificate_path = connect_and_get_tls_objects(q, bus, conn) certificate = TlsCertificateWrapper(bus.get_object(conn.bus_name, certificate_path)) certificate.TLSCertificate.Accept() q.expect('dbus-signal', signal='Accepted') cert_props = dbus.Interface(certificate, cs.PROPERTIES_IFACE) state = cert_props.Get(cs.AUTH_TLS_CERT, 'State') rejections = cert_props.Get(cs.AUTH_TLS_CERT, 'Rejections') assertLength(0, rejections) chan.Close() q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed'), EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) ) def connect_and_get_tls_properties(q, bus, conn): chan, hostname, certificate_path = connect_and_get_tls_objects(q, bus, conn) chan_props = dbus.Interface(chan, cs.PROPERTIES_IFACE) return chan_props.GetAll(cs.CHANNEL_TYPE_SERVER_TLS_CONNECTION) def test_channel_reference_identity(q, bus, conn, stream): props = connect_and_get_tls_properties (q, bus, conn) reference_identities = props["ReferenceIdentities"] assertSameSets(reference_identities, [ "example.org", "localhost"]) assertEquals(props["Hostname"], "example.org") def test_channel_reference_identity_with_extra(q, bus, conn, stream): props = connect_and_get_tls_properties (q, bus, conn) reference_identities = props["ReferenceIdentities"] assertSameSets(reference_identities, [ "example.org", "hypnotoad.example.org", "localhost" ]) assertEquals(props["Hostname"], "example.org") def test_channel_reference_identity_with_extra_multiple(q, bus, conn, stream): props = connect_and_get_tls_properties (q, bus, conn) reference_identities = props["ReferenceIdentities"] assertSameSets(reference_identities, [ "example.org", "hypnotoad.example.org", "localhost", "other.local" ]) assertEquals(props["Hostname"], "example.org") def test_channel_accept_hostname(q, bus, conn, stream): chan, hostname, certificate_path = connect_and_get_tls_objects(q, bus, conn, False) # close the channel early chan.Close() # we expect the fallback verification process to accept the hostname (because # it matches the JID's hostname or because it's in extra-certificate-identities), # but the certificate verification will fail anyway as we don't trust the CA q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed'), EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_CERT_UNTRUSTED]) ) def test_channel_reject_hostname(q, bus, conn, stream): chan, hostname, certificate_path = connect_and_get_tls_objects(q, bus, conn, False) # close the channel early chan.Close() # we expect the fallback verification process to not accept the hostname; # it doesn't match the JID's hostname nor the hostnames in the # extra-certificate-identities parameter q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed'), EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_CERT_HOSTNAME_MISMATCH]) ) if __name__ == '__main__': exec_test(test_connect_success, { 'account' : JID }, authenticator=TlsAuthenticator(username='test', password='pass'), do_connect=False) exec_test(test_connect_fail, { 'account' : JID }, authenticator=TlsAuthenticator(username='test', password='pass'), do_connect=False) exec_test(test_connect_early_close_success, { 'account' : JID, 'ignore-ssl-errors' : False, 'require-encryption' : False }, authenticator=TlsAuthenticator(username='test', password='pass'), do_connect=False) exec_test(test_connect_early_close_fail, { 'account' : JID, 'ignore-ssl-errors' : False, 'require-encryption' : True }, authenticator=TlsAuthenticator(username='test', password='pass'), do_connect=False) exec_test(test_disconnect_inbetween, { 'account' : JID }, authenticator=TlsAuthenticator(username='test', password='pass'), do_connect=False) # Certificate verification reference identity checks exec_test(test_channel_reference_identity, { 'account' : JID }, authenticator=TlsAuthenticator(username='test', password='pass'), do_connect=False) exec_test(test_channel_reference_identity_with_extra, { 'account' : JID, 'extra-certificate-identities' : [ 'hypnotoad.example.org' ] }, authenticator=TlsAuthenticator(username='test', password='pass'), do_connect=False) exec_test(test_channel_reference_identity_with_extra_multiple, { 'account' : JID, 'extra-certificate-identities' : [ 'hypnotoad.example.org', 'other.local', '' ] }, authenticator=TlsAuthenticator(username='test', password='pass'), do_connect=False) # Hostname verification exec_test(test_channel_accept_hostname, { 'account' : 'test@' + CA_CERT_HOSTNAME, 'ignore-ssl-errors' : False, 'require-encryption' : True }, authenticator=TlsAuthenticator(username='test', password='pass'), do_connect=False) exec_test(test_channel_accept_hostname, { 'account' : 'test@' + CA_CERT_HOSTNAME, 'ignore-ssl-errors' : False, 'require-encryption' : True, 'extra-certificate-identities' : [ 'other.local', CA_CERT_HOSTNAME ] }, authenticator=TlsAuthenticator(username='test', password='pass'), do_connect=False) exec_test(test_channel_accept_hostname, { 'account' : JID, 'ignore-ssl-errors' : False, 'require-encryption' : True, 'extra-certificate-identities' : [ 'other.local', CA_CERT_HOSTNAME ] }, authenticator=TlsAuthenticator(username='test', password='pass'), do_connect=False) exec_test(test_channel_reject_hostname, { 'account' : 'test@alternative.' + CA_CERT_HOSTNAME, 'ignore-ssl-errors' : False, 'require-encryption' : True }, authenticator=TlsAuthenticator(username='test', password='pass'), do_connect=False) exec_test(test_channel_reject_hostname, { 'account' : JID, 'ignore-ssl-errors' : False, 'require-encryption' : True, 'extra-certificate-identities' : [ 'other.local', 'hypnotoad.example.org' ] }, authenticator=TlsAuthenticator(username='test', password='pass'), do_connect=False) exec_test(test_channel_reject_hostname, { 'account' : JID, 'ignore-ssl-errors' : False, 'require-encryption' : True }, authenticator=TlsAuthenticator(username='test', password='pass'), do_connect=False) exec_test(test_channel_reject_hostname, { 'account' : JID, 'ignore-ssl-errors' : False, 'require-encryption' : True, 'extra-certificate-identities' : [ 'alternative.' + CA_CERT_HOSTNAME ] }, authenticator=TlsAuthenticator(username='test', password='pass'), do_connect=False) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tls/legacy-jabber.py������������������������������������������0000664�0001750�0001750�00000002211�12225363340�024662� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" fd.o #65036: connecting to legacy Jabber servers should respect require-encryption """ from servicetest import assertEquals from gabbletest import exec_test, JabberXmlStream, JabberAuthenticator import constants as cs JID = 'alice@example.com' PASSWORD = 's3kr1t' def test_require_encryption(q, bus, conn, stream): conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) # FIXME: arrange to get a better error new = q.expect('dbus-signal', signal='ConnectionError') assertEquals(cs.NETWORK_ERROR, new.args[0]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_NETWORK_ERROR]) if __name__ == '__main__': exec_test(test_require_encryption, { 'password': PASSWORD, 'account': JID, 'require-encryption': True, 'old-ssl': False, 'resource': 'legacy-require-encryption', }, protocol=JabberXmlStream, authenticator=JabberAuthenticator(JID.split('@')[0], PASSWORD), do_connect=False) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/gabbletest.py�������������������������������������������������0000664�0001750�0001750�00000067521�12332441362�023524� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Infrastructure code for testing Gabble by pretending to be a Jabber server. """ import base64 import os import hashlib import sys import random import re import traceback import ns import constants as cs import servicetest from servicetest import ( assertEquals, assertLength, assertContains, wrap_channel, EventPattern, call_async, unwrap, Event) import twisted from twisted.words.xish import domish, xpath from twisted.words.protocols.jabber.client import IQ from twisted.words.protocols.jabber import xmlstream from twisted.internet import reactor, ssl import dbus def make_result_iq(stream, iq, add_query_node=True): result = IQ(stream, "result") result["id"] = iq["id"] to = iq.getAttribute('to') if to is not None: result["from"] = to query = iq.firstChildElement() if query and add_query_node: result.addElement((query.uri, query.name)) return result def acknowledge_iq(stream, iq): stream.send(make_result_iq(stream, iq)) def send_error_reply(stream, iq, error_stanza=None): result = IQ(stream, "error") result["id"] = iq["id"] query = iq.firstChildElement() to = iq.getAttribute('to') if to is not None: result["from"] = to if query: result.addElement((query.uri, query.name)) if error_stanza: result.addChild(error_stanza) stream.send(result) def request_muc_handle(q, conn, stream, muc_jid): servicetest.call_async(q, conn, 'RequestHandles', 2, [muc_jid]) event = q.expect('dbus-return', method='RequestHandles') return event.value[0][0] def make_muc_presence(affiliation, role, muc_jid, alias, jid=None, photo=None): presence = domish.Element((None, 'presence')) presence['from'] = '%s/%s' % (muc_jid, alias) x = presence.addElement((ns.MUC_USER, 'x')) item = x.addElement('item') item['affiliation'] = affiliation item['role'] = role if jid is not None: item['jid'] = jid if photo is not None: presence.addChild( elem(ns.VCARD_TEMP_UPDATE, 'x')( elem('photo')(unicode(photo)) )) return presence def sync_stream(q, stream): """Used to ensure that Gabble has processed all stanzas sent to it.""" iq = IQ(stream, "get") id = iq['id'] iq.addElement(('http://jabber.org/protocol/disco#info', 'query')) stream.send(iq) q.expect('stream-iq', query_ns='http://jabber.org/protocol/disco#info', predicate=(lambda event: event.stanza['id'] == id and event.iq_type == 'result')) class GabbleAuthenticator(xmlstream.Authenticator): def __init__(self, username, password, resource=None): self.username = username self.password = password self.resource = resource self.bare_jid = None self.full_jid = None self._event_func = lambda e: None xmlstream.Authenticator.__init__(self) def set_event_func(self, event_func): self._event_func = event_func class JabberAuthenticator(GabbleAuthenticator): "Trivial XML stream authenticator that accepts one username/digest pair." # Patch in fix from http://twistedmatrix.com/trac/changeset/23418. # This monkeypatch taken from Gadget source code from twisted.words.xish.utility import EventDispatcher def _addObserver(self, onetime, event, observerfn, priority, *args, **kwargs): if self._dispatchDepth > 0: self._updateQueue.append(lambda: self._addObserver(onetime, event, observerfn, priority, *args, **kwargs)) return self._oldAddObserver(onetime, event, observerfn, priority, *args, **kwargs) EventDispatcher._oldAddObserver = EventDispatcher._addObserver EventDispatcher._addObserver = _addObserver def __init__(self, username, password, resource=None, emit_events=False): GabbleAuthenticator.__init__(self, username, password, resource) self.emit_events = emit_events def streamStarted(self, root=None): if root: self.xmlstream.sid = '%x' % random.randint(1, sys.maxint) self.xmlstream.domain = root.getAttribute('to') self.xmlstream.sendHeader() self.xmlstream.addOnetimeObserver( "/iq/query[@xmlns='jabber:iq:auth']", self.initialIq) def initialIq(self, iq): if self.emit_events: self._event_func(Event('auth-initial-iq', authenticator=self, iq=iq, id=iq["id"])) else: self.respondToInitialIq(iq) self.xmlstream.addOnetimeObserver('/iq/query/username', self.secondIq) def respondToInitialIq(self, iq): result = IQ(self.xmlstream, "result") result["id"] = iq["id"] query = result.addElement('query') query["xmlns"] = "jabber:iq:auth" query.addElement('username', content='test') query.addElement('password') query.addElement('digest') query.addElement('resource') self.xmlstream.send(result) def secondIq(self, iq): if self.emit_events: self._event_func(Event('auth-second-iq', authenticator=self, iq=iq, id=iq["id"])) else: self.respondToSecondIq(iq) def respondToSecondIq(self, iq): username = xpath.queryForNodes('/iq/query/username', iq) assert map(str, username) == [self.username] digest = xpath.queryForNodes('/iq/query/digest', iq) expect = hashlib.sha1(self.xmlstream.sid + self.password).hexdigest() assert map(str, digest) == [expect] resource = xpath.queryForNodes('/iq/query/resource', iq) assertLength(1, resource) if self.resource is not None: assertEquals(self.resource, str(resource[0])) self.bare_jid = '%s@%s' % (self.username, self.xmlstream.domain) self.full_jid = '%s/%s' % (self.bare_jid, resource) result = IQ(self.xmlstream, "result") result["id"] = iq["id"] self.xmlstream.send(result) self.xmlstream.dispatch(self.xmlstream, xmlstream.STREAM_AUTHD_EVENT) class XmppAuthenticator(GabbleAuthenticator): def __init__(self, username, password, resource=None): GabbleAuthenticator.__init__(self, username, password, resource) self.authenticated = False self._mechanisms = ['PLAIN'] def streamInitialize(self, root): if root: self.xmlstream.sid = root.getAttribute('id') self.xmlstream.domain = root.getAttribute('to') if self.xmlstream.sid is None: self.xmlstream.sid = '%x' % random.randint(1, sys.maxint) self.xmlstream.sendHeader() def streamIQ(self): features = elem(xmlstream.NS_STREAMS, 'features')( elem(ns.NS_XMPP_BIND, 'bind'), elem(ns.NS_XMPP_SESSION, 'session'), ) self.xmlstream.send(features) self.xmlstream.addOnetimeObserver( "/iq/bind[@xmlns='%s']" % ns.NS_XMPP_BIND, self.bindIq) self.xmlstream.addOnetimeObserver( "/iq/session[@xmlns='%s']" % ns.NS_XMPP_SESSION, self.sessionIq) def streamSASL(self): features = domish.Element((xmlstream.NS_STREAMS, 'features')) mechanisms = features.addElement((ns.NS_XMPP_SASL, 'mechanisms')) for mechanism in self._mechanisms: mechanisms.addElement('mechanism', content=mechanism) self.xmlstream.send(features) self.xmlstream.addOnetimeObserver("/auth", self.auth) def streamStarted(self, root=None): self.streamInitialize(root) if self.authenticated: # Initiator authenticated itself, and has started a new stream. self.streamIQ() else: self.streamSASL() def auth(self, auth): assert (base64.b64decode(str(auth)) == '\x00%s\x00%s' % (self.username, self.password)) success = domish.Element((ns.NS_XMPP_SASL, 'success')) self.xmlstream.send(success) self.xmlstream.reset() self.authenticated = True def bindIq(self, iq): resource = xpath.queryForString('/iq/bind/resource', iq) if self.resource is not None: assertEquals(self.resource, resource) else: assert resource is not None result = IQ(self.xmlstream, "result") result["id"] = iq["id"] bind = result.addElement((ns.NS_XMPP_BIND, 'bind')) self.bare_jid = '%s@%s' % (self.username, self.xmlstream.domain) self.full_jid = '%s/%s' % (self.bare_jid, resource) jid = bind.addElement('jid', content=self.full_jid) self.xmlstream.send(result) self.xmlstream.dispatch(self.xmlstream, xmlstream.STREAM_AUTHD_EVENT) def sessionIq(self, iq): self.xmlstream.send(make_result_iq(self.xmlstream, iq)) class StreamEvent(servicetest.Event): def __init__(self, type_, stanza, stream): servicetest.Event.__init__(self, type_, stanza=stanza) self.stream = stream self.to = stanza.getAttribute("to") class IQEvent(StreamEvent): def __init__(self, stream, iq): StreamEvent.__init__(self, 'stream-iq', iq, stream) self.iq_type = iq.getAttribute("type") self.iq_id = iq.getAttribute("id") query = iq.firstChildElement() if query: self.query = query self.query_ns = query.uri self.query_name = query.name if query.getAttribute("node"): self.query_node = query.getAttribute("node") else: self.query = None class PresenceEvent(StreamEvent): def __init__(self, stream, stanza): StreamEvent.__init__(self, 'stream-presence', stanza, stream) self.presence_type = stanza.getAttribute('type') statuses = xpath.queryForNodes('/presence/status', stanza) if statuses: self.presence_status = str(statuses[0]) class MessageEvent(StreamEvent): def __init__(self, stream, stanza): StreamEvent.__init__(self, 'stream-message', stanza, stream) self.message_type = stanza.getAttribute('type') class StreamFactory(twisted.internet.protocol.Factory): def __init__(self, streams, jids): self.streams = streams self.jids = jids self.presences = {} self.mappings = dict(map (lambda jid, stream: (jid, stream), jids, streams)) # Make a copy of the streams self.factory_streams = list(streams) self.factory_streams.reverse() # Do not add observers for single instances because it's unnecessary and # some unit tests need to respond to the roster request, and we shouldn't # answer it for them otherwise we break compatibility if len(streams) > 1: # We need to have a function here because lambda keeps a reference on # the stream and jid and in the for loop, there is no context def addObservers(stream, jid): stream.addObserver('/iq', lambda x: \ self.forward_iq(stream, jid, x)) stream.addObserver('/presence', lambda x: \ self.got_presence(stream, jid, x)) for (jid, stream) in self.mappings.items(): addObservers(stream, jid) def protocol(self, *args): return self.factory_streams.pop() def got_presence (self, stream, jid, stanza): stanza.attributes['from'] = jid self.presences[jid] = stanza for dest_jid in self.presences.keys(): # Dispatch the new presence to other clients stanza.attributes['to'] = dest_jid self.mappings[dest_jid].send(stanza) # Don't echo the presence twice if dest_jid != jid: # Dispatch other client's presence to this stream presence = self.presences[dest_jid] presence.attributes['to'] = jid stream.send(presence) def lost_presence(self, stream, jid): if self.presences.has_key(jid): del self.presences[jid] for dest_jid in self.presences.keys(): presence = domish.Element(('jabber:client', 'presence')) presence['from'] = jid presence['to'] = dest_jid presence['type'] = 'unavailable' self.mappings[dest_jid].send(presence) def forward_iq(self, stream, jid, stanza): stanza.attributes['from'] = jid query = stanza.firstChildElement() # Fake other accounts as being part of our roster if query and query.uri == ns.ROSTER: roster = make_result_iq(stream, stanza) query = roster.firstChildElement() for roster_jid in self.mappings.keys(): if jid != roster_jid: item = query.addElement('item') item['jid'] = roster_jid item['subscription'] = 'both' stream.send(roster) return to = stanza.getAttribute('to') dest = None if to is not None: dest = self.mappings.get(to) if dest is not None: dest.send(stanza) class BaseXmlStream(xmlstream.XmlStream): initiating = False namespace = 'jabber:client' pep_support = True disco_features = [] handle_privacy_lists = True def __init__(self, event_func, authenticator): xmlstream.XmlStream.__init__(self, authenticator) self.event_func = event_func self.addObserver('//iq', lambda x: event_func( IQEvent(self, x))) self.addObserver('//message', lambda x: event_func( MessageEvent(self, x))) self.addObserver('//presence', lambda x: event_func( PresenceEvent(self, x))) self.addObserver('//event/stream/authd', self._cb_authd) if self.handle_privacy_lists: self.addObserver("/iq/query[@xmlns='%s']" % ns.PRIVACY, self._cb_priv_list) def connectionMade(self): xmlstream.XmlStream.connectionMade(self) if 'GABBLE_NODELAY' in os.environ: self.transport.setTcpNoDelay(True) def _cb_priv_list(self, iq): send_error_reply(self, iq) def _cb_authd(self, _): # called when stream is authenticated assert self.authenticator.full_jid is not None assert self.authenticator.bare_jid is not None self.addObserver( "/iq[@to='%s']/query[@xmlns='http://jabber.org/protocol/disco#info']" % self.domain, self._cb_disco_iq) self.addObserver( "/iq[@to='%s']/query[@xmlns='http://jabber.org/protocol/disco#info']" % self.authenticator.bare_jid, self._cb_bare_jid_disco_iq) self.event_func(servicetest.Event('stream-authenticated')) def _cb_disco_iq(self, iq): nodes = xpath.queryForNodes( "/iq/query[@xmlns='http://jabber.org/protocol/disco#info']", iq) query = nodes[0] for feature in self.disco_features: query.addChild(elem('feature', var=feature)) iq['type'] = 'result' iq['from'] = iq['to'] self.send(iq) def _cb_bare_jid_disco_iq(self, iq): # advertise PEP support nodes = xpath.queryForNodes( "/iq/query[@xmlns='http://jabber.org/protocol/disco#info']", iq) query = nodes[0] identity = query.addElement('identity') identity['category'] = 'pubsub' identity['type'] = 'pep' iq['type'] = 'result' iq['from'] = iq['to'] self.send(iq) def onDocumentEnd(self): self.event_func(servicetest.Event('stream-closed')) # We don't chain up XmlStream.onDocumentEnd() because it will # disconnect the TCP connection making tests as # connect/disconnect-timeout.py not working def connectionLost(self, reason): self.event_func(servicetest.Event('stream-connection-lost')) xmlstream.XmlStream.connectionLost(self, reason) def send_stream_error(self, error='system-shutdown'): # Yes, there are meant to be two different STREAMS namespaces. go_away = \ elem(xmlstream.NS_STREAMS, 'error')( elem(ns.STREAMS, error) ) self.send(go_away) class JabberXmlStream(BaseXmlStream): version = (0, 9) class XmppXmlStream(BaseXmlStream): version = (1, 0) class GoogleXmlStream(BaseXmlStream): version = (1, 0) pep_support = False disco_features = [ns.GOOGLE_ROSTER, ns.GOOGLE_JINGLE_INFO, ns.GOOGLE_MAIL_NOTIFY, ns.GOOGLE_QUEUE, ] def _cb_bare_jid_disco_iq(self, iq): # Google talk doesn't support PEP :( iq['type'] = 'result' iq['from'] = iq['to'] self.send(iq) def make_connection(bus, event_func, params=None, suffix=''): # Gabble accepts a resource in 'account', but the value of 'resource' # overrides it if there is one. test_name = re.sub('(.*tests/twisted/|\./)', '', sys.argv[0]) account = 'test%s@localhost/%s' % (suffix, test_name) default_params = { 'account': account, 'password': 'pass', 'resource': 'Resource', 'server': 'localhost', 'port': dbus.UInt32(4242), 'fallback-socks5-proxies': dbus.Array([], signature='s'), 'require-encryption': False, } if params: default_params.update(params) # Allow omitting the 'password' param if default_params['password'] is None: del default_params['password'] # Allow omitting the 'account' param if default_params['account'] is None: del default_params['account'] jid = default_params.get('account', None) conn = servicetest.make_connection(bus, event_func, 'gabble', 'jabber', default_params) return (conn, jid) def make_stream(event_func, authenticator=None, protocol=None, resource=None, suffix=''): # set up Jabber server if authenticator is None: authenticator = XmppAuthenticator('test%s' % suffix, 'pass', resource=resource) authenticator.set_event_func(event_func) if protocol is None: protocol = XmppXmlStream stream = protocol(event_func, authenticator) return stream def disconnect_conn(q, conn, stream, expected_before=[], expected_after=[]): call_async(q, conn, 'Disconnect') tmp = expected_before + [ EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_REQUESTED]), EventPattern('stream-closed')] before_events = q.expect_many(*tmp) stream.sendFooter() tmp = expected_after + [EventPattern('dbus-return', method='Disconnect')] after_events = q.expect_many(*tmp) return before_events[:-2], after_events[:-1] def element_repr(element): """__repr__ cannot safely return non-ASCII: see <http://bugs.python.org/issue5876>. So we print non-ASCII characters as \uXXXX escapes in debug output """ return element.toXml().encode('unicode-escape') def expect_connected(queue): queue.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) queue.expect('stream-authenticated') queue.expect('dbus-signal', signal='PresencesChanged', args=[{1L: (cs.PRESENCE_AVAILABLE, u'available', '')}]) queue.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) def exec_test_deferred(fun, params, protocol=None, timeout=None, authenticator=None, num_instances=1, do_connect=True, make_connection_func=make_connection, expect_connected_func=expect_connected): # hack to ease debugging domish.Element.__repr__ = element_repr colourer = None if sys.stdout.isatty() or 'CHECK_FORCE_COLOR' in os.environ: colourer = servicetest.install_colourer() try: bus = dbus.SessionBus() except dbus.exceptions.DBusException as e: print e os._exit(1) queue = servicetest.IteratingEventQueue(timeout) queue.verbose = ( os.environ.get('CHECK_TWISTED_VERBOSE', '') != '' or '-v' in sys.argv) conns = [] jids = [] streams = [] resource = params.get('resource') if params is not None else None for i in range(0, num_instances): if i == 0: suffix = '' else: suffix = str(i) try: (conn, jid) = make_connection_func(bus, queue.append, params, suffix) except Exception, e: # Crap. This is normally because the connection's still kicking # around on the bus. Let's bin any connections we *did* manage to # get going and then bail out unceremoniously. print e for conn in conns: conn.Disconnect() os._exit(1) conns.append(conn) jids.append(jid) streams.append(make_stream(queue.append, protocol=protocol, authenticator=authenticator, resource=resource, suffix=suffix)) factory = StreamFactory(streams, jids) port = reactor.listenTCP(4242, factory, interface='localhost') def signal_receiver(*args, **kw): if kw['path'] == '/org/freedesktop/DBus' and \ kw['member'] == 'NameOwnerChanged': bus_name, old_name, new_name = args if new_name == '': for i, conn in enumerate(conns): stream = streams[i] jid = jids[i] if conn._requested_bus_name == bus_name: factory.lost_presence(stream, jid) break queue.append(Event('dbus-signal', path=unwrap(kw['path']), signal=kw['member'], args=map(unwrap, args), interface=kw['interface'])) match_all_signals = bus.add_signal_receiver( signal_receiver, None, # signal name None, # interface None, path_keyword='path', member_keyword='member', interface_keyword='interface', byte_arrays=True ) error = None try: if do_connect: for conn in conns: conn.Connect() expect_connected_func(queue) if len(conns) == 1: fun(queue, bus, conns[0], streams[0]) else: fun(queue, bus, conns, streams) except Exception, e: traceback.print_exc() error = e queue.verbose = False if colourer: sys.stdout = colourer.fh d = port.stopListening() # Does the Connection object still exist? for i, conn in enumerate(conns): if not bus.name_has_owner(conn.object.bus_name): # Connection has already been disconnected and destroyed continue try: if conn.GetStatus() == cs.CONN_STATUS_CONNECTED: # Connection is connected, properly disconnect it disconnect_conn(queue, conn, streams[i]) else: # Connection is not connected, call Disconnect() to destroy it conn.Disconnect() except dbus.DBusException, e: pass except Exception, e: traceback.print_exc() error = e try: conn.Disconnect() raise AssertionError("Connection didn't disappear; " "all subsequent tests will probably fail") except dbus.DBusException, e: pass except Exception, e: traceback.print_exc() error = e match_all_signals.remove() if error is None: d.addBoth((lambda *args: reactor.crash())) else: # please ignore the POSIX behind the curtain d.addBoth((lambda *args: os._exit(1))) def exec_test(fun, params=None, protocol=None, timeout=None, authenticator=None, num_instances=1, do_connect=True): reactor.callWhenRunning( exec_test_deferred, fun, params, protocol, timeout, authenticator, num_instances, do_connect) reactor.run() # Useful routines for server-side vCard handling current_vcard = domish.Element(('vcard-temp', 'vCard')) def expect_and_handle_get_vcard(q, stream): get_vcard_event = q.expect('stream-iq', query_ns=ns.VCARD_TEMP, query_name='vCard', iq_type='get') iq = get_vcard_event.stanza vcard = iq.firstChildElement() assert vcard.name == 'vCard', vcard.toXml() # Send back current vCard result = make_result_iq(stream, iq, add_query_node=False) result.addChild(current_vcard) stream.send(result) def expect_and_handle_set_vcard(q, stream, check=None): global current_vcard set_vcard_event = q.expect('stream-iq', query_ns=ns.VCARD_TEMP, query_name='vCard', iq_type='set') iq = set_vcard_event.stanza vcard = iq.firstChildElement() assert vcard.name == 'vCard', vcard.toXml() if check is not None: check(vcard) # Update current vCard current_vcard = vcard stream.send(make_result_iq(stream, iq)) def _elem_add(elem, *children): for child in children: if isinstance(child, domish.Element): elem.addChild(child) elif isinstance(child, unicode): elem.addContent(child) else: raise ValueError( 'invalid child object %r (must be element or unicode)', child) def elem(a, b=None, attrs={}, **kw): r""" >>> elem('foo')().toXml() u'<foo/>' >>> elem('foo', x='1')().toXml() u"<foo x='1'/>" >>> elem('foo', x='1')(u'hello').toXml() u"<foo x='1'>hello</foo>" >>> elem('foo', x='1')(u'hello', ... elem('http://foo.org', 'bar', y='2')(u'bye')).toXml() u"<foo x='1'>hello<bar xmlns='http://foo.org' y='2'>bye</bar></foo>" >>> elem('foo', attrs={'xmlns:bar': 'urn:bar', 'bar:cake': 'yum'})( ... elem('bar:e')(u'i') ... ).toXml() u"<foo xmlns:bar='urn:bar' bar:cake='yum'><bar:e>i</bar:e></foo>" """ class _elem(domish.Element): def __call__(self, *children): _elem_add(self, *children) return self if b is not None: elem = _elem((a, b)) else: elem = _elem((None, a)) # Can't just update kw into attrs, because that *modifies the parameter's # default*. Thanks python. allattrs = {} allattrs.update(kw) allattrs.update(attrs) # First, let's pull namespaces out realattrs = {} for k, v in allattrs.iteritems(): if k.startswith('xmlns:'): abbr = k[len('xmlns:'):] elem.localPrefixes[abbr] = v else: realattrs[k] = v for k, v in realattrs.iteritems(): if k == 'from_': elem['from'] = v else: elem[k] = v return elem def elem_iq(server, type, **kw): class _iq(IQ): def __call__(self, *children): _elem_add(self, *children) return self iq = _iq(server, type) for k, v in kw.iteritems(): if k == 'from_': iq['from'] = v else: iq[k] = v return iq def make_presence(_from, to='test@localhost', type=None, show=None, status=None, caps=None, photo=None): presence = domish.Element((None, 'presence')) presence['from'] = _from presence['to'] = to if type is not None: presence['type'] = type if show is not None: presence.addElement('show', content=show) if status is not None: presence.addElement('status', content=status) if caps is not None: cel = presence.addElement(('http://jabber.org/protocol/caps', 'c')) for key,value in caps.items(): cel[key] = value # <x xmlns="vcard-temp:x:update"><photo>4a1...</photo></x> if photo is not None: x = presence.addElement((ns.VCARD_TEMP_UPDATE, 'x')) x.addElement('photo').addContent(photo) return presence �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/test-helper.py������������������������������������������������0000644�0001750�0001750�00000004210�12225363340�023624� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Helper script for writing tests. How it works: - Each event that occurs generates a Python function that expects exactly that event. - Each time an event occurs, you're dropped into a Python debugger. The commands you type will be inserted into the function that expects that event. - Executing "!return False" in the debugger will stop the script, as will SIGINT (Control-C). Once your'e done, the test code is written to a file called test.dump. """ import pdb import pprint from twisted.internet import glib2reactor glib2reactor.install() from gabbletest import EventTest, run class LoggingPdb(pdb.Pdb): def __init__(self): pdb.Pdb.__init__(self) self.log = [] def default(self, line): self.log.append(line) return pdb.Pdb.default(self, line) def expect(event, data): return True class TestShell: def __init__(self): self.events = [] def expect(self, event, data): print 'event:' for item in event: print '-', pprint.pformat(item) db = LoggingPdb() ret = db.runcall(expect, event, data) print (ret, db.log) self.events.append((event, db.log, ret)) return False def make_expect_func(self, suffix, event, log, ret): lines = [] lines.append('def expect_%s(event, data):\n' % suffix) lines.extend([ ' if event[%d] != %r:\n return False\n\n' % (i, item) for i, item in enumerate(event)]) lines.extend([' %s\n' % line for line in log]) lines.append(' return %r\n' % ret) return ''.join(lines) def make_script(self): return '\n'.join([ self.make_expect_func(i, event, log, ret) for i, (event, log, ret) in enumerate(self.events)]) class NoTimeoutEventTest(EventTest): def timeout_cb(self): pass if __name__ == '__main__': test = NoTimeoutEventTest() shell = TestShell() test.expect(shell.expect) try: run(test) except KeyboardInterrupt: pass print 'writing test to test.dump' fh = file('test.dump', 'w') fh.write(shell.make_script()) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/presence/�����������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�022636� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/presence/plugins.py�������������������������������������������0000664�0001750�0001750�00000010535�12332440117�024663� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test Gabble support for plugins adding presence statuses. """ from gabbletest import ( XmppXmlStream, exec_test, make_presence, elem, elem_iq, acknowledge_iq, send_error_reply ) from servicetest import ( EventPattern, assertEquals, assertNotEquals, assertContains, assertDoesNotContain, call_async ) import ns import constants as cs from twisted.words.xish import xpath, domish from invisible_helper import Xep0186AndManualPrivacyListStream, \ ManualPrivacyListStream def test(q, bus, conn, stream): statuses = conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, 'Statuses') # testbusy and testaway are provided by test plugin assertContains('testbusy', statuses) assertContains('testaway', statuses) assertEquals(statuses['testbusy'][0], cs.PRESENCE_BUSY) assertEquals(statuses['testaway'][0], cs.PRESENCE_AWAY) conn.SimplePresence.SetPresence('testbusy', '') conn.Connect() # ... gabble asks for all the available lists on the server ... stream.handle_get_all_privacy_lists(q, bus, conn, lists=["foo-list", "test-busy-list", "bar-list"]) # ... gabble checks whether there's usable invisible list on the server ... get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='get') list_node = xpath.queryForNodes('//list', get_list.query)[0] assertEquals('invisible', list_node['name']) error = domish.Element((None, 'error')) error['type'] = 'cancel' error.addElement((ns.STANZA, 'item-not-found')) send_error_reply (stream, get_list.stanza, error) # ... since there is none, Gabble creates it ... create_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') list_node = xpath.queryForNodes('//list', create_list.query)[0] assertEquals('invisible', list_node['name']) assertNotEquals([], xpath.queryForNodes('/query/list/item/presence-out', create_list.query)) acknowledge_iq(stream, create_list.stanza) get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') list_node = xpath.queryForNodes('//active', get_list.query)[0] # ... and then activates the one linked with the requested status # Note: testbusy status is linked to test-busy-list by test plugin assertEquals('test-busy-list', list_node['name']) acknowledge_iq(stream, get_list.stanza) q.expect('dbus-signal', signal='PresencesChanged', args=[{1L: (cs.PRESENCE_BUSY, u'testbusy', '')}]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) # ... testaway is not supposed to be settable on us call_async(q, conn.SimplePresence, 'SetPresence', 'testaway', '') q.expect('dbus-error', method='SetPresence', name=cs.INVALID_ARGUMENT) def test_with_xep0186(q, bus, conn, stream): statuses = conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, 'Statuses') # testbusy and testaway are provided by test plugin assertContains('testbusy', statuses) assertContains('testaway', statuses) assertEquals(statuses['testbusy'][0], cs.PRESENCE_BUSY) assertEquals(statuses['testaway'][0], cs.PRESENCE_AWAY) conn.SimplePresence.SetPresence('testbusy', '') conn.Connect() # ... gabble asks for all the available lists on the server ... stream.handle_get_all_privacy_lists(q, bus, conn, lists=["foo-list", "test-busy-list", "bar-list"]) get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') list_node = xpath.queryForNodes('//active', get_list.query)[0] # ... and then activates the one linked with the requested status # Note: testbusy status is linked to test-busy-list by test plugin assertEquals('test-busy-list', list_node['name']) acknowledge_iq(stream, get_list.stanza) q.expect('dbus-signal', signal='PresencesChanged', args=[{1L: (cs.PRESENCE_BUSY, u'testbusy', '')}]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) # ... testaway is not supposed to be settable on us call_async(q, conn.SimplePresence, 'SetPresence', 'testaway', '') q.expect('dbus-error', method='SetPresence', name=cs.INVALID_ARGUMENT) if __name__ == '__main__': exec_test(test, protocol=ManualPrivacyListStream, do_connect=False) exec_test(test_with_xep0186, protocol=Xep0186AndManualPrivacyListStream, do_connect=False) �������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/presence/set-idempotence.py�����������������������������������0000664�0001750�0001750�00000007330�12332441362�026271� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test that redundant calls to SetPresence don't cause anything to happen. """ import dbus from servicetest import EventPattern from gabbletest import exec_test import constants as cs from invisible_helper import Xep0186Stream, ValidInvisibleListStream, \ Xep0186AndValidInvisibleListStream def run_test(q, bus, conn, stream): # Expect an initial presence push from the client. q.expect('stream-presence') # Set presence to away. This should cause PresencesChanged to be emitted, # and a new <presence> stanza to be sent to the server. conn.SimplePresence.SetPresence('away', 'gone') simple_signal, presence = q.expect_many ( EventPattern('dbus-signal', signal='PresencesChanged'), EventPattern('stream-presence')) assert simple_signal.args == [{1L: (3L, u'away', u'gone')}] assert conn.Contacts.GetContactAttributes([1], [cs.CONN_IFACE_SIMPLE_PRESENCE], False) == { 1L: { cs.CONN_IFACE_SIMPLE_PRESENCE + "/presence": (3L, u'away', u'gone'), 'org.freedesktop.Telepathy.Connection/contact-id': 'test@localhost'}} children = list(presence.stanza.elements()) assert children[0].name == 'show' assert str(children[0]) == 'away' assert children[1].name == 'status' assert str(children[1]) == 'gone' # Set presence a second time. Since this call is redundant, there should # be no PresencesChanged or <presence> sent to the server. conn.SimplePresence.SetPresence('away', 'gone') assert conn.Contacts.GetContactAttributes([1], [cs.CONN_IFACE_SIMPLE_PRESENCE], False) == { 1L: { cs.CONN_IFACE_SIMPLE_PRESENCE + "/presence": (3L, u'away', u'gone'), 'org.freedesktop.Telepathy.Connection/contact-id': 'test@localhost'}} # Set presence a third time. This call is not redundant, and should # generate a signal/message. conn.SimplePresence.SetPresence('available', 'yo') simple_signal, presence = q.expect_many ( EventPattern('dbus-signal', signal='PresencesChanged'), EventPattern('stream-presence')) assert simple_signal.args == [{1L: (2L, u'available', u'yo')}] children = list(presence.stanza.elements()) assert children[0].name == 'status' assert str(children[0]) == 'yo' assert conn.Contacts.GetContactAttributes([1], [cs.CONN_IFACE_SIMPLE_PRESENCE], False) == { 1L: { cs.CONN_IFACE_SIMPLE_PRESENCE + "/presence": (2L, u'available', u'yo'), 'org.freedesktop.Telepathy.Connection/contact-id': 'test@localhost'}} # call SetPresence with an empty message, as this used to cause a # crash in tp-glib conn.SimplePresence.SetPresence('available', '') simple_signal, presence = q.expect_many ( EventPattern('dbus-signal', signal='PresencesChanged'), EventPattern('stream-presence')) assert simple_signal.args == [{1L: (2L, u'available', u'')}] assert conn.Contacts.GetContactAttributes([1], [cs.CONN_IFACE_SIMPLE_PRESENCE], False) == { 1L: { cs.CONN_IFACE_SIMPLE_PRESENCE + "/presence": (2L, u'available', u''), 'org.freedesktop.Telepathy.Connection/contact-id': 'test@localhost'}} if __name__ == '__main__': exec_test(run_test) # Run this test against some invisibility-capable servers, even though we # don't use invisibility, to check that invisibility support doesn't break # us. This is a regression test for # <https://bugs.freedesktop.org/show_bug.cgi?id=30117>. It turned out that # XEP-0126 support meant that our own presence changes were never # signalled. for protocol in [Xep0186AndValidInvisibleListStream, Xep0186Stream, ValidInvisibleListStream]: exec_test(run_test, protocol=protocol) exec_test(run_test, protocol=protocol) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/presence/decloak.py�������������������������������������������0000664�0001750�0001750�00000005110�12332441362�024600� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from twisted.words.xish import domish from gabbletest import exec_test, make_presence from servicetest import EventPattern, assertEquals import ns import constants as cs def test(q, bus, conn, stream, should_decloak=False): event = q.expect('stream-iq', query_ns=ns.ROSTER) event.stanza['type'] = 'result' stream.send(event.stanza) # First test is to use the CM param's value worker(q, bus, conn, stream, should_decloak) # We can change it at runtime, so flip it to the other value and retry should_decloak = not should_decloak conn.Set(cs.CONN_IFACE_GABBLE_DECLOAK, 'DecloakAutomatically', should_decloak, dbus_interface=cs.PROPERTIES_IFACE) worker(q, bus, conn, stream, should_decloak) # Trivial test for SendDirectedPresence() bob_handle = conn.RequestHandles(1, ['bob@foo.com'])[0] conn.SendDirectedPresence(bob_handle, False, dbus_interface=cs.CONN_IFACE_GABBLE_DECLOAK) q.expect('stream-presence', to='bob@foo.com') def worker(q, bus, conn, stream, should_decloak): decloak_automatically = conn.Get(cs.CONN_IFACE_GABBLE_DECLOAK, 'DecloakAutomatically', dbus_interface=cs.PROPERTIES_IFACE) assertEquals(should_decloak, decloak_automatically) amy_handle = conn.RequestHandles(1, ['amy@foo.com'])[0] # Amy directs presence to us presence = make_presence('amy@foo.com/panopticon') decloak = presence.addElement((ns.TEMPPRES, 'temppres')) decloak['reason'] = 'media' stream.send(presence) events = [ EventPattern('dbus-signal', signal='PresencesChanged', args=[{amy_handle: (cs.PRESENCE_AVAILABLE, 'available', '')}]), EventPattern('dbus-signal', signal='DecloakRequested', args=[amy_handle, 'media', should_decloak]), ] forbidden = [] if should_decloak: events.append(EventPattern('stream-presence', to='amy@foo.com/panopticon')) else: forbidden = [EventPattern('stream-presence')] q.forbid_events(forbidden) q.expect_many(*events) presence = make_presence('amy@foo.com/panopticon', type='unavailable') stream.send(presence) q.expect('dbus-signal', signal='PresencesChanged', args=[{amy_handle: (cs.PRESENCE_OFFLINE, 'offline', '')}]) q.unforbid_events(forbidden) if __name__ == '__main__': exec_test(test, params={cs.CONN_IFACE_GABBLE_DECLOAK + '.DecloakAutomatically': False}) exec_test(lambda q, b, c, s: test(q, b, c, s, should_decloak=True), params={cs.CONN_IFACE_GABBLE_DECLOAK + '.DecloakAutomatically': True}) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/presence/error.py���������������������������������������������0000664�0001750�0001750�00000004453�12332441362�024340� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Tests that Gabble provides at least some useful information from error presences. """ from gabbletest import exec_test, make_presence, elem from servicetest import assertEquals import ns import constants as cs def test(q, bus, conn, stream): jids = ['gregory@unreachable.example.com', 'thehawk@unreachable.example.net', ] gregory, hawk = jids gregory_handle, hawk_handle = conn.RequestHandles(cs.HT_CONTACT, jids) event = q.expect('stream-iq', query_ns=ns.ROSTER) event.stanza['type'] = 'result' for jid in jids: item = event.query.addElement('item') item['jid'] = jid item['subscription'] = 'both' stream.send(event.stanza) q.expect('dbus-signal', signal='PresencesChanged', args=[{gregory_handle: (cs.PRESENCE_OFFLINE, 'offline', ''), hawk_handle: (cs.PRESENCE_OFFLINE, 'offline', ''), } ]) # Our server can't resolve unreachable.example.com so it sends us an error # presence for Gregory. (This is what Prosody actually does.) presence = make_presence(gregory, type='error') error_text = u'Connection failed: DNS resolution failed' presence.addChild( elem('error', type='cancel')( elem(ns.STANZA, 'remote-server-not-found'), elem(ns.STANZA, 'text')( error_text ) )) stream.send(presence) e = q.expect('dbus-signal', signal='PresencesChanged') presences, = e.args type_, status, message = presences[gregory_handle] assertEquals(cs.PRESENCE_ERROR, type_) assertEquals('error', status) assertEquals(error_text, message) # How about maybe the hawk's server is busted? presence = make_presence(hawk, type='error') presence.addChild( elem('error', type='cancel')( elem(ns.STANZA, 'internal-server-error'), )) stream.send(presence) e = q.expect('dbus-signal', signal='PresencesChanged') presences, = e.args type_, status, message = presences[hawk_handle] assertEquals(cs.PRESENCE_ERROR, type_) assertEquals('error', status) # FIXME: It might be less user-hostile to give some kind of readable # description of the error in future. assertEquals('internal-server-error', message) if __name__ == '__main__': exec_test(test) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/presence/initial-contact-presence.py��������������������������0000664�0001750�0001750�00000007632�12332441362�030075� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test that contacts we're subscribed to have their presence go from unknown to offline when we get the roster, even if we've got (unavailable) presence for them before we receive the roster; and that receiving available presence from a contact before we get the roster also works. This serves as a regression test for <https://bugs.freedesktop.org/show_bug.cgi?id=38603>, among other bugs. """ from gabbletest import exec_test, make_presence, sync_stream, elem from servicetest import assertEquals, EventPattern, sync_dbus import constants as cs import ns from twisted.words.xish import domish AVAILABLE = (cs.PRESENCE_AVAILABLE, u'available', u'') OFFLINE = (cs.PRESENCE_OFFLINE, u'offline', u'') UNKNOWN = (cs.PRESENCE_UNKNOWN, u'unknown', u'') def make_roster_item(jid, subscription): item = domish.Element((None, 'item')) item['jid'] = jid item['subscription'] = subscription return item def test(q, bus, conn, stream): event = q.expect('stream-iq', query_ns=ns.ROSTER) amy, bob, che, dre, eve = conn.RequestHandles(cs.HT_CONTACT, ['amy@foo.com', 'bob@foo.com', 'che@foo.com', 'dre@foo.com', 'eve@foo.com']) assertEquals({amy: UNKNOWN, bob: UNKNOWN, che: UNKNOWN, dre: UNKNOWN, eve: UNKNOWN, }, conn.SimplePresence.GetPresences([amy, bob, che, dre, eve])) # Before the server sends Gabble the roster, it relays an 'unavailable' # presence for one of the contacts we're subscribed to. This seems to # happen in practice when using Prosody with a shared roster: the presence # probes start coming back negatively before the shared roster is retrieved # and returned to the client. stream.send(make_presence('dre@foo.com', type='unavailable')) # Dre's presence is still unknown, since we don't have the roster. This # isn't a change per se---we checked above, and Dre's presence was # unknown---so it shouldn't be signalled. q.forbid_events([EventPattern('dbus-signal', signal='PresencesChanged', args=[{dre: UNKNOWN}])]) # We also receive an available presence from Eve before the roster arrives: # this presence should behave normally. stream.send(make_presence('eve@foo.com')) q.expect('dbus-signal', signal='PresencesChanged', args=[{eve: AVAILABLE}]) # We also get a message from a contact before we get the roster (presumably # they sent this while we were offline?). This shouldn't affect the contact # being reported as offline when we finally do get the roster, but it used # to: <https://bugs.freedesktop.org/show_bug.cgi?id=41743>. stream.send( elem('message', from_='amy@foo.com', type='chat')( elem('body')(u'why are you never online?') )) q.expect('dbus-signal', signal='MessageReceived') event.stanza['type'] = 'result' event.query.addChild(make_roster_item('amy@foo.com', 'both')) event.query.addChild(make_roster_item('bob@foo.com', 'from')) event.query.addChild(make_roster_item('che@foo.com', 'to')) event.query.addChild(make_roster_item('dre@foo.com', 'both')) event.query.addChild(make_roster_item('eve@foo.com', 'both')) stream.send(event.stanza) # The presence for contacts on the roster whose subscription is 'to' or # 'both' but for whom we haven't already received presence should change # from 'unknown' (as checked above) to 'offline'. e = q.expect('dbus-signal', signal='PresencesChanged') changed_presences, = e.args assertEquals( {amy: OFFLINE, che: OFFLINE, dre: OFFLINE, }, changed_presences) assertEquals({amy: OFFLINE, bob: UNKNOWN, che: OFFLINE, dre: OFFLINE, eve: AVAILABLE, }, conn.SimplePresence.GetPresences([amy, bob, che, dre, eve])) if __name__ == '__main__': exec_test(test) ������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/presence/__init__.py������������������������������������������0000664�0001750�0001750�00000000000�12225363340�024726� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/presence/invisible_xep_0186.py��������������������������������0000664�0001750�0001750�00000007263�12332440117�026524� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" A simple smoke-test for XEP-0186 invisibility """ from gabbletest import exec_test, acknowledge_iq, send_error_reply from servicetest import ( EventPattern, assertEquals, assertNotEquals, assertContains, ) import ns import constants as cs from invisible_helper import Xep0186AndValidInvisibleListStream, Xep0186Stream def test_invisible_on_connect(q, bus, conn, stream): props = conn.Properties.GetAll(cs.CONN_IFACE_SIMPLE_PRESENCE) assertNotEquals({}, props['Statuses']) presence_event_pattern = EventPattern('stream-presence') q.forbid_events([presence_event_pattern]) conn.SimplePresence.SetPresence("hidden", "") conn.Connect() event = q.expect('stream-iq', query_name='invisible') acknowledge_iq(stream, event.stanza) q.unforbid_events([presence_event_pattern]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) def test_invisible_on_connect_fails(q, bus, conn, stream): conn.SimplePresence.SetPresence("hidden", "") conn.Connect() event = q.expect('stream-iq', query_name='invisible') send_error_reply(stream, event.stanza) # Darn! At least we should have our presence set to DND. q.expect_many( EventPattern('dbus-signal', signal='PresencesChanged', interface=cs.CONN_IFACE_SIMPLE_PRESENCE, args=[{1: (6, 'dnd', '')}]), EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])) def test_invisible(q, bus, conn, stream): assertContains("hidden", conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, "Statuses")) conn.SimplePresence.SetPresence("hidden", "") # First we send an <invisible/> command. event = q.expect('stream-iq', query_name='invisible') acknowledge_iq(stream, event.stanza) # When that's returned successfully, we can signal the change on D-Bus. q.expect('dbus-signal', signal='PresencesChanged', interface=cs.CONN_IFACE_SIMPLE_PRESENCE, args=[{1: (5, 'hidden', '')}]) conn.SimplePresence.SetPresence("away", "gone") # First Gabble sends a <visible/> command. event = q.expect('stream-iq', query_name='visible') acknowledge_iq(stream, event.stanza) # Then: "It is the responsibility of the client to send an undirected # presence notification to the server". Plus, we should signal the change # on D-Bus. q.expect_many( EventPattern('stream-presence', to=None), EventPattern('dbus-signal', signal='PresencesChanged', interface=cs.CONN_IFACE_SIMPLE_PRESENCE, args=[{1: (3, 'away', 'gone')}])) def test_invisible_fails(q, bus, conn, stream): assertContains("hidden", conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, "Statuses")) conn.SimplePresence.SetPresence("hidden", "") # First we send an <invisible/> command. event = q.expect('stream-iq', query_name='invisible') send_error_reply(stream, event.stanza) # When that fails, we should expect our status to change to dnd. q.expect('dbus-signal', signal='PresencesChanged', interface=cs.CONN_IFACE_SIMPLE_PRESENCE, args=[{1: (6, 'dnd', '')}]) if __name__ == '__main__': for protocol in [Xep0186Stream, Xep0186AndValidInvisibleListStream]: exec_test(test_invisible_on_connect, protocol=protocol, do_connect=False) exec_test(test_invisible_on_connect_fails, protocol=protocol, do_connect=False) exec_test(test_invisible, protocol=protocol) exec_test(test_invisible_fails, protocol=protocol) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/presence/presence.py������������������������������������������0000664�0001750�0001750�00000002071�12332441362�025005� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" A simple smoke-test for C.I.SimplePresence FIXME: test C.I.Presence too """ from twisted.words.xish import domish from gabbletest import exec_test, make_presence from servicetest import EventPattern import ns import constants as cs def test(q, bus, conn, stream): event = q.expect('stream-iq', query_ns=ns.ROSTER) amy_handle = conn.RequestHandles(1, ['amy@foo.com'])[0] event.stanza['type'] = 'result' item = event.query.addElement('item') item['jid'] = 'amy@foo.com' item['subscription'] = 'both' stream.send(event.stanza) stream.send(make_presence('amy@foo.com', show='away', status='At the pub')) q.expect('dbus-signal', signal='PresencesChanged', args=[{amy_handle: (cs.PRESENCE_AWAY, 'away', 'At the pub')}]) stream.send(make_presence( 'amy@foo.com', show='chat', status='I may have been drinking')) q.expect('dbus-signal', signal='PresencesChanged', args=[{amy_handle: (cs.PRESENCE_AVAILABLE, 'chat', 'I may have been drinking')}]) if __name__ == '__main__': exec_test(test) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/presence/initial-presence.py����������������������������������0000664�0001750�0001750�00000002512�12332440117�026431� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Tests setting your own presence before calling Connect(), allowing the user to sign in as Busy/Invisible/whatever rather than available. """ from twisted.words.xish import domish from gabbletest import exec_test from servicetest import EventPattern, assertEquals, assertNotEquals import ns import constants as cs from invisible_helper import ValidInvisibleListStream, Xep0186Stream, \ Xep0186AndValidInvisibleListStream def test(q, bus, conn, stream): props = conn.Properties.GetAll(cs.CONN_IFACE_SIMPLE_PRESENCE) assertNotEquals({}, props['Statuses']) conn.SimplePresence.SetPresence("away", "watching bees") conn.Connect() _, presence = q.expect_many( EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]), EventPattern('stream-presence'), ) children = list(presence.stanza.elements()) assertEquals('show', children[0].name) assertEquals('away', children[0].children[0]) assertEquals('status', children[1].name) assertEquals('watching bees', children[1].children[0]) if __name__ == '__main__': exec_test(test, do_connect=False) for protocol in [ValidInvisibleListStream, Xep0186Stream, Xep0186AndValidInvisibleListStream]: exec_test(test, protocol=protocol, do_connect=False) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/presence/invisible_xep_0126.py��������������������������������0000664�0001750�0001750�00000034637�12332440117�026523� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# coding=utf-8 """ A simple smoke-test for XEP-0126 invisibility We are deliberately not advertising support for privacy lists on connection disco, this is because it is not explicitly required by XEP-0016 or XEP-0126. Some servers silently support it, like certain version of Ejabberd and all released versions of Prosody (as of 7.0). """ from gabbletest import ( exec_test, acknowledge_iq, send_error_reply, elem, elem_iq ) from servicetest import ( EventPattern, assertEquals, assertNotEquals, assertContains, assertDoesNotContain ) import ns import constants as cs from twisted.words.xish import xpath, domish from invisible_helper import ManualPrivacyListStream from functools import partial def test_create_invisible_list(q, bus, conn, stream): conn.SimplePresence.SetPresence("away", "") conn.Connect() stream.handle_get_all_privacy_lists(q, bus, conn) get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='get') list_node = xpath.queryForNodes('//list', get_list.query)[0] assertEquals('invisible', list_node['name']) error = domish.Element((None, 'error')) error['type'] = 'cancel' error.addElement((ns.STANZA, 'item-not-found')) send_error_reply (stream, get_list.stanza, error) create_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') list_node = xpath.queryForNodes('//list', create_list.query)[0] assertEquals('invisible', list_node['name']) assertNotEquals([], xpath.queryForNodes('/query/list/item/presence-out', create_list.query)) acknowledge_iq(stream, create_list.stanza) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) assertContains("hidden", conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, "Statuses")) def test_create_invisible_list_failed(q, bus, conn, stream): conn.SimplePresence.SetPresence("away", "") conn.Connect() stream.handle_get_all_privacy_lists(q, bus, conn) get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='get') list_node = xpath.queryForNodes('//list', get_list.query)[0] assertEquals('invisible', list_node['name']) error = domish.Element((None, 'error')) error['type'] = 'cancel' error.addElement((ns.STANZA, 'item-not-found')) send_error_reply (stream, get_list.stanza, error) create_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') list_node = xpath.queryForNodes('//list', create_list.query)[0] assertEquals('invisible', list_node['name']) assertNotEquals([], xpath.queryForNodes('/query/list/item/presence-out', create_list.query)) send_error_reply(stream, create_list.stanza) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) assertDoesNotContain("hidden", conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, "Statuses")) def test_invisible_on_connect_fail_no_list(q, bus, conn, stream): props = conn.Properties.GetAll(cs.CONN_IFACE_SIMPLE_PRESENCE) assertNotEquals({}, props['Statuses']) presence_event_pattern = EventPattern('stream-presence') q.forbid_events([presence_event_pattern]) conn.SimplePresence.SetPresence("hidden", "") conn.Connect() stream.handle_get_all_privacy_lists(q, bus, conn) get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='get') list_node = xpath.queryForNodes('//list', get_list.query)[0] assertEquals('invisible', list_node['name']) send_error_reply(stream, get_list.stanza) q.unforbid_events([presence_event_pattern]) # Darn! At least we should have our presence set to DND. q.expect_many( EventPattern('dbus-signal', signal='PresencesChanged', interface=cs.CONN_IFACE_SIMPLE_PRESENCE, args=[{1: (6, 'dnd', '')}]), EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])) # 'hidden' should not be an available status. assertDoesNotContain("hidden", conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, "Statuses")) def test_invisible_on_connect_fail_invalid_list(q, bus, conn, stream, really_invalid=False): props = conn.Properties.GetAll(cs.CONN_IFACE_SIMPLE_PRESENCE) assertNotEquals({}, props['Statuses']) presence_event_pattern = EventPattern('stream-presence') q.forbid_events([presence_event_pattern]) conn.SimplePresence.SetPresence("hidden", "") conn.Connect() stream.handle_get_all_privacy_lists(q, bus, conn, ['invisible']) get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='get') list_node = xpath.queryForNodes('//list', get_list.query)[0] assertEquals('invisible', list_node['name']) if really_invalid: # At one point Gabble would crash if the reply was of type 'result' but # wasn't well-formed. acknowledge_iq(stream, get_list.stanza) else: stream.send_privacy_list(get_list.stanza, [elem('item', type='jid', value='tybalt@example.com', action='allow', order='1')(elem('presence-out')), elem('item', action='deny', order='2')(elem('presence-out'))]) create_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') created = xpath.queryForNodes('//list', create_list.stanza)[0] assertEquals(created["name"], 'invisible-gabble') acknowledge_iq (stream, create_list.stanza) q.unforbid_events([presence_event_pattern]) activate_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') active = xpath.queryForNodes('//active', activate_list.stanza)[0] assertEquals(active["name"], 'invisible-gabble') acknowledge_iq (stream, activate_list.stanza) q.expect_many( EventPattern('dbus-signal', signal='PresencesChanged', interface=cs.CONN_IFACE_SIMPLE_PRESENCE, args=[{1: (5, 'hidden', '')}]), EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])) # 'hidden' should not be an available status. assertContains("hidden", conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, "Statuses")) def test_invisible_on_connect_fail(q, bus, conn, stream): props = conn.Properties.GetAll(cs.CONN_IFACE_SIMPLE_PRESENCE) assertNotEquals({}, props['Statuses']) presence_event_pattern = EventPattern('stream-presence') q.forbid_events([presence_event_pattern]) conn.SimplePresence.SetPresence("hidden", "") conn.Connect() stream.handle_get_all_privacy_lists(q, bus, conn) create_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') # Check its name assertNotEquals([], xpath.queryForNodes('/query/list/item/presence-out', create_list.query)) acknowledge_iq(stream, create_list.stanza) set_active = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') active = xpath.queryForNodes('//active', set_active.query)[0] assertEquals('invisible', active['name']) send_error_reply(stream, set_active.stanza) q.unforbid_events([presence_event_pattern]) # Darn! At least we should have our presence set to DND. q.expect_many( EventPattern('dbus-signal', signal='PresencesChanged', interface=cs.CONN_IFACE_SIMPLE_PRESENCE, args=[{1: (6, 'dnd', '')}]), EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])) def test_invisible_on_connect(q, bus, conn, stream): props = conn.Properties.GetAll(cs.CONN_IFACE_SIMPLE_PRESENCE) assertNotEquals({}, props['Statuses']) presence_event_pattern = EventPattern('stream-presence') q.forbid_events([presence_event_pattern]) conn.SimplePresence.SetPresence("hidden", "") conn.Connect() stream.handle_get_all_privacy_lists(q, bus, conn, ['invisible']) get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='get') list_node = xpath.queryForNodes('//list', get_list.query)[0] assertEquals('invisible', list_node['name']) stream.send_privacy_list(get_list.stanza, [elem('item', action='deny', order='1')(elem('presence-out'))]) set_active = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') active = xpath.queryForNodes('//active', set_active.query)[0] assertEquals('invisible', active['name']) acknowledge_iq(stream, set_active.stanza) q.unforbid_events([presence_event_pattern]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) def test_invisible(q, bus, conn, stream): conn.Connect() stream.handle_get_all_privacy_lists(q, bus, conn, ['invisible']) get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='get') stream.send_privacy_list(get_list.stanza, [elem('item', action='deny', order='1')(elem('presence-out'))]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) assertContains("hidden", conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, "Statuses")) conn.SimplePresence.SetPresence("hidden", "") # §3.5 Become Globally Invisible # <http://xmpp.org/extensions/xep-0126.html#invis-global> # # First, the user sends unavailable presence for broadcasting to all # contacts: q.expect('stream-presence', to=None, presence_type='unavailable') # Second, the user sets as active the global invisibility list previously # defined: event = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') active = xpath.queryForNodes('//active', event.query)[0] assertEquals('invisible', active['name']) acknowledge_iq(stream, event.stanza) # In order to appear globally invisible, the client MUST now re-send the # user's presence for broadcasting to all contacts, which the active rule # will block to all contacts: q.expect_many( EventPattern('stream-presence', to=None, presence_type=None), EventPattern('dbus-signal', signal='PresencesChanged', interface=cs.CONN_IFACE_SIMPLE_PRESENCE, args=[{1: (5, 'hidden', '')}])) conn.SimplePresence.SetPresence("away", "gone") # §3.3 Become Globally Visible # <http://xmpp.org/extensions/xep-0126.html#vis-global> # # Because globally allowing outbound presence notifications is most likely # the default behavior of any server, a more straightforward way to become # globally visible is to decline the use of any active rule (the # equivalent, as it were, of taking off a magic invisibility ring): event = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') active = xpath.queryForNodes('//active', event.query)[0] assert (not active.compareAttribute('name', 'invisible')) acknowledge_iq(stream, event.stanza) # In order to ensure synchronization of presence notifications, the client # SHOULD now re-send the user's presence for broadcasting to all contacts. # # At this point, we also signal our presence change on D-Bus: q.expect_many( EventPattern('stream-presence', to=None, presence_type=None), EventPattern('dbus-signal', signal='PresencesChanged', interface=cs.CONN_IFACE_SIMPLE_PRESENCE, args=[{1: (3, 'away', 'gone')}])) def test_privacy_list_push_conflict(q, bus, conn, stream): test_invisible_on_connect(q, bus, conn, stream) set_id = stream.send_privacy_list_push_iq("invisible") _, req_list = q.expect_many( EventPattern('stream-iq', iq_type='result', iq_id=set_id), EventPattern('stream-iq', query_ns=ns.PRIVACY, iq_type="get")) stream.send_privacy_list(req_list.stanza, [elem('item', type='jid', value='tybalt@example.com', action='allow', order='1')(elem('presence-out')), elem('item', action='deny', order='2')(elem('presence-out'))]) create_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') created = xpath.queryForNodes('//list', create_list.stanza)[0] assertEquals(created["name"], 'invisible-gabble') acknowledge_iq(stream, create_list.stanza) set_active = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') active = xpath.queryForNodes('//active', set_active.query)[0] assertEquals('invisible-gabble', active['name']) acknowledge_iq(stream, set_active.stanza) def test_privacy_list_push_valid(q, bus, conn, stream): test_invisible_on_connect(q, bus, conn, stream) set_id = stream.send_privacy_list_push_iq("invisible") _, req_list = q.expect_many( EventPattern('stream-iq', iq_type='result', iq_id=set_id), EventPattern('stream-iq', query_ns=ns.PRIVACY, iq_type="get")) stream.send_privacy_list(req_list.stanza, [elem('item', action='deny', order='1')(elem(u'presence-out')), elem('item', type='jid', value='tybalt@example.com', action='deny', order='2')(elem(u'message'))]) # We redundantly re-activate the 'invisible' list. These lines also # check to see that we didn't switch over to 'invisible-gabble' activate_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') active = xpath.queryForNodes('//active', activate_list.stanza)[0] assertEquals(active["name"], 'invisible') acknowledge_iq (stream, activate_list.stanza) if __name__ == '__main__': exec_test(test_invisible, protocol=ManualPrivacyListStream, do_connect=False) exec_test(test_invisible_on_connect, protocol=ManualPrivacyListStream, do_connect=False) exec_test(test_create_invisible_list, protocol=ManualPrivacyListStream, do_connect=False) exec_test(test_create_invisible_list_failed, protocol=ManualPrivacyListStream, do_connect=False) exec_test(test_invisible_on_connect_fail_no_list, protocol=ManualPrivacyListStream, do_connect=False) exec_test(test_invisible_on_connect_fail_invalid_list, protocol=ManualPrivacyListStream, do_connect=False) exec_test(partial(test_invisible_on_connect_fail_invalid_list, really_invalid=True), protocol=ManualPrivacyListStream, do_connect=False) exec_test(test_privacy_list_push_valid, protocol=ManualPrivacyListStream, do_connect=False) exec_test(test_privacy_list_push_conflict, protocol=ManualPrivacyListStream, do_connect=False) �������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/presence/invisible_helper.py����������������������������������0000644�0001750�0001750�00000015560�12225363340�026531� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from gabbletest import ( XmppXmlStream, elem, elem_iq, send_error_reply, acknowledge_iq ) import ns from twisted.words.xish import xpath from time import time class ManualPrivacyListStream(XmppXmlStream): """Unlike the base class, which automatically responds to privacy list requests in the negative, this stream class does not automatically respond. Instead it provides helper methods to let your test expect requests and respond to them manually.""" handle_privacy_lists = False def send_privacy_list_list(self, iq_id, lists=[]): list_elements = [elem('list', name=l) for l in lists] iq = elem_iq(self, "result", id=iq_id)( elem(ns.PRIVACY, 'query')(*list_elements)) self.send(iq) def handle_get_all_privacy_lists(self, q, bus, conn, lists=[]): e = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='get') self.send_privacy_list_list(e.iq_id, lists) def send_privacy_list_push_iq(self, list_name): iq = elem_iq(self, 'set')( elem(ns.PRIVACY, 'query')( elem('list', name=list_name) ) ) self.send(iq) return iq["id"] def send_privacy_list(self, req_iq, list_items): req_list = xpath.queryForNodes('//list', req_iq)[0] iq = elem_iq(self, "result", id=req_iq["id"])( elem(ns.PRIVACY, 'query')( elem('list', name=req_list["name"])(*list_items) ) ) self.send(iq) class ValidInvisibleListStream(ManualPrivacyListStream): """This stream class pretends to be a server which supports privacy lists. It has exactly one stored list, named 'invisible', which satisfies Gabble's idea of what an invisible list should look like. Activating that list, or disabling the active list, will succeed; any attempts to activate or modify other lists will fail. The intention is that this class could be used to run presence tests unrelated to invisibility against a server which supports invisibility.""" def __init__(self, event_func, authenticator): ManualPrivacyListStream.__init__(self, event_func, authenticator) self.addObserver("/iq/query[@xmlns='%s']" % ns.PRIVACY, self.privacy_list_iq_cb) def privacy_list_iq_cb(self, iq): if iq.getAttribute("type") == 'set': active = xpath.queryForNodes("//active", iq) if active and ('name' not in active[0].attributes or active[0]['name'] == 'invisible'): acknowledge_iq(self, iq) else: # Don't allow other lists to be activated; and don't allow # modifications. send_error_reply(self, iq) else: requested_lists = xpath.queryForNodes('//list', iq) if not requested_lists: self.send_privacy_list_list(iq['id'], ['invisible']) elif requested_lists[0]['name'] == 'invisible': self.send_privacy_list(iq, [elem('item', action='deny', order='1')( elem('presence-out') ) ]) else: send_error_reply(self, iq, elem(ns.STANZA, 'item-not-found')) class Xep0186Stream(XmppXmlStream): disco_features = [ns.INVISIBLE] class Xep0186AndValidInvisibleListStream(ValidInvisibleListStream): disco_features = [ns.INVISIBLE] class Xep0186AndManualPrivacyListStream(ManualPrivacyListStream): disco_features = [ns.INVISIBLE] class SharedStatusStream(XmppXmlStream): disco_features = [ns.GOOGLE_SHARED_STATUS] handle_privacy_lists = False def __init__(self, event_func, authenticator): XmppXmlStream.__init__(self, event_func, authenticator) self.addObserver("/iq/query[@xmlns='%s']" % ns.GOOGLE_SHARED_STATUS, self.shared_status_iq_cb) self.shared_status_lists = {u'default' : [u'Pining away', u'Wherefore indeed', u'Thinking about the sun'], u'dnd' : [u'Chilling with Mercutio', u'Visiting the monk']} self.shared_status = (u'Pining away', u'default', u'false') self.min_version = '2' self.max_status_message_length = '512' self.max_statuses = '5' def set_shared_status_lists(self, shared_status_lists=None, status=None, show=None, invisible=None, min_version=None): self.shared_status_lists = shared_status_lists or \ self.shared_status_lists _status, _show, _invisible = self.shared_status self.shared_status = (status or _status, show or _show, invisible or _invisible) self.min_version = min_version or self.min_version self._send_status_list() def _send_status_list(self, iq_id=None): if iq_id is None: iq_id = str(int(time())) iq_type = "set" else: iq_type = "result" status, show, invisible = self.shared_status elems = [] elems.append(elem('status')(unicode(status))) elems.append(elem('show')(unicode(show))) for show, statuses in self.shared_status_lists.items(): lst = [] for _status in statuses: lst.append(elem('status')(unicode(_status))) elems.append(elem('status-list', show=show)(*lst)) elems.append(elem('invisible', value=invisible)()) attribs = {'status-max' : self.max_status_message_length, 'status-list-max' : '3', 'status-list-contents-max' : self.max_statuses, 'status-min-ver' : self.min_version} iq = elem_iq(self, iq_type, id=iq_id)( elem(ns.GOOGLE_SHARED_STATUS, 'query', **attribs)(*elems)) self.send(iq) def _store_shared_statuses(self, iq): _status = xpath.queryForNodes('//status', iq)[0] _show = xpath.queryForNodes('//show', iq)[0] _invisible = xpath.queryForNodes('//invisible', iq)[0] self.shared_status = (str(_status), str(_show), _invisible.getAttribute('value')) _status_lists = xpath.queryForNodes('//status-list', iq) self.shared_status_lists = {} for s in _status_lists: self.shared_status_lists[s.getAttribute('show')] = \ [str(e) for e in xpath.queryForNodes('//status', s)] def shared_status_iq_cb(self, req_iq): if req_iq.getAttribute("type") == 'get': self._send_status_list(req_iq['id']) if req_iq.getAttribute("type") == 'set': self._store_shared_statuses(req_iq) self.send(elem_iq(self, "result", id=req_iq['id'])()) ������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/presence/shared-status.py�������������������������������������0000664�0001750�0001750�00000040652�12332441362�025777� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# coding=utf-8 """ A simple smoke-test for Google Shared Status. See: http://code.google.com/apis/talk/jep_extensions/shared_status.html """ from gabbletest import ( exec_test, XmppXmlStream, acknowledge_iq, send_error_reply, disconnect_conn, elem, elem_iq ) from servicetest import ( EventPattern, assertEquals, assertNotEquals, assertContains, assertDoesNotContain, sync_dbus ) import ns import copy import constants as cs import dbus from twisted.words.xish import xpath, domish from invisible_helper import SharedStatusStream presence_types = {'available' : cs.PRESENCE_AVAILABLE, 'away' : cs.PRESENCE_AWAY, 'xa' : cs.PRESENCE_EXTENDED_AWAY, 'hidden' : cs.PRESENCE_HIDDEN, 'dnd' : cs.PRESENCE_BUSY} def _show_to_shared_status_show(show): # Away and extended away don't use shared status. shared_show = 'default' if show == 'dnd': shared_show = 'dnd' shared_invisible = 'false' if show == 'hidden': shared_invisible = 'true' return shared_show, shared_invisible def _test_remote_status(q, bus, conn, stream, msg, show, list_attrs): self = conn.GetSelfHandle() presence = conn.SimplePresence.GetPresences([self])[self] is_away = presence[0] in (cs.PRESENCE_AWAY, cs.PRESENCE_EXTENDED_AWAY) if is_away: # Away is per connection. If we remotely change the shared status, # we have to stay away. _test_remote_status_away(q, bus, conn, stream, msg, show, list_attrs) else: # If we are not away and the remote status changes, we have to change # also our local presence to reflect that. _test_remote_status_not_away(q, stream, msg, show, list_attrs) def _test_remote_status_away(q, bus, conn, stream, msg, show, list_attrs): events = [EventPattern('dbus-signal', signal='PresencesChanged', interface=cs.CONN_IFACE_SIMPLE_PRESENCE, args=[{1: (presence_types[show], show, msg)}])] q.forbid_events(events) list_attrs['status'] = list_attrs.get('status', msg) stream.set_shared_status_lists(**list_attrs) q.expect('stream-iq', iq_type='result') sync_dbus(bus, q, conn) q.unforbid_events(events) def _test_remote_status_not_away(q, stream, msg, show, list_attrs): list_attrs['status'] = list_attrs.get('status', msg) stream.set_shared_status_lists(**list_attrs) q.expect('stream-iq', iq_type='result') q.expect('dbus-signal', signal='PresencesChanged', interface=cs.CONN_IFACE_SIMPLE_PRESENCE, args=[{1: (presence_types[show], show, msg)}]) def _test_local_status(q, conn, stream, msg, show, expected_show=None): expected_show = expected_show or show away = expected_show in ('away', 'xa') self = conn.GetSelfHandle() prev_presence = conn.SimplePresence.GetPresences([self])[self] was_away = prev_presence[0] in (cs.PRESENCE_AWAY, cs.PRESENCE_EXTENDED_AWAY) was_invisible = (prev_presence[0] == cs.PRESENCE_HIDDEN) if away: # Away and extended away are mapped to idle, that is per connection. # This means we use <presence/> instead of shared presence... if not was_invisible: # ... so in normal cases we don't expect the shared presence # stuff, but ... wrong_presence_pattern = EventPattern('stream-iq', query_ns=ns.GOOGLE_SHARED_STATUS, iq_type='set') else: # ... when switching from invisible we have to leave invisible # first and then go away. wrong_presence_pattern = None elif was_away: # Non-away status, but we were away previously. Considering that we # went away using <presence/>, we need to also leave it using # <presence/> plus the shared status. wrong_presence_pattern = None else: # Normal case without away involvement; we just expect the use of # shared status. wrong_presence_pattern = EventPattern('stream-presence') if wrong_presence_pattern: q.forbid_events([wrong_presence_pattern]) conn.SimplePresence.SetPresence(show, msg) max_status_message_length = int(stream.max_status_message_length) if not away or (away and was_invisible): event = q.expect('stream-iq', query_ns=ns.GOOGLE_SHARED_STATUS, iq_type='set') shared_show, shared_invisible = _show_to_shared_status_show(expected_show) _status = xpath.queryForNodes('//status', event.query)[0] assertEquals(msg[:max_status_message_length], _status.children[0]) _show = xpath.queryForNodes('//show', event.query)[0] assertEquals(shared_show, _show.children[0]) _invisible = xpath.queryForNodes('//invisible', event.query)[0] assertEquals(shared_invisible, _invisible.getAttribute('value')) if was_away or (away and was_invisible): q.expect('stream-presence') else: q.expect('stream-presence') q.expect('dbus-signal', signal='PresencesChanged', interface=cs.CONN_IFACE_SIMPLE_PRESENCE, args=[{1: (presence_types[expected_show], expected_show, msg[:max_status_message_length])}]) if wrong_presence_pattern: q.unforbid_events([wrong_presence_pattern]) def test(q, bus, conn, stream): q.expect_many(EventPattern('stream-iq', query_ns=ns.GOOGLE_SHARED_STATUS, iq_type='get'), EventPattern('stream-iq', query_ns=ns.GOOGLE_SHARED_STATUS, iq_type='set'), EventPattern('stream-presence')) # Set shared status to dnd. _test_local_status(q, conn, stream, "Don't disturb, buddy.", "dnd") # Test maximum status message length max_status_message_length = int(stream.max_status_message_length) _test_local_status(q, conn, stream, "ab" * max_status_message_length, "dnd") # Test invisibility _test_local_status(q, conn, stream, "Peekabo", "hidden") _test_local_status(q, conn, stream, "Here!", "available") # Set shared status to default, local status to away. _test_local_status(q, conn, stream, "I'm away right now", "away") _test_local_status(q, conn, stream, "cd" * max_status_message_length, "away") # Test the transition from away to non-away as GTalk treats it in a # different way. _test_local_status(q, conn, stream, "Here!", "available") _test_local_status(q, conn, stream, "I'm away right now", "away") _test_local_status(q, conn, stream, "I'm away right now", "xa") _test_local_status(q, conn, stream, "Here!", "available") # Test the transition from hidden to away. _test_local_status(q, conn, stream, "Peekabo", "hidden") _test_local_status(q, conn, stream, "I'm away right now", "away") # Test if the status is changed correctly from another client. _test_local_status(q, conn, stream, "Don't disturb, buddy.", "dnd") _test_remote_status(q, bus, conn, stream, "This is me busy, set from another client.", "dnd", {"show" : "dnd"}) _test_remote_status(q, bus, conn, stream, "This is me available, set from another client.", "available", {"show" : "default"}) # Test that our own status as exposed over D-Bus doesn't change when # when we are away and other clients change the shared status. _test_local_status(q, conn, stream, "Lunch!", "away") _test_remote_status(q, bus, conn, stream, "This is me busy, set from another client.", "dnd", {"show" : "dnd"}) _test_remote_status(q, bus, conn, stream, "This is me available, set from another client.", "available", {"show" : "default"}) # Change min version stream.set_shared_status_lists(min_version="1") q.expect('stream-iq', iq_type='result') # Going invisible now should fail, we should just be dnd. _test_local_status(q, conn, stream, "Peekabo", "hidden", "dnd") # Let's go back to version 2 stream.set_shared_status_lists(min_version="2") q.expect('stream-iq', iq_type='result') # "hidden" should work again. _test_local_status(q, conn, stream, "Peekabo", "hidden") # Changing min version mid-flight should make us 'dnd' stream.set_shared_status_lists(min_version="1") q.expect('stream-iq', iq_type='result') q.expect('dbus-signal', signal='PresencesChanged', interface=cs.CONN_IFACE_SIMPLE_PRESENCE, args=[{1: (cs.PRESENCE_BUSY, 'dnd', "Peekabo")}]) def _test_on_connect(q, bus, conn, stream, shared_status, show, msg, expected_show=None, min_version=None): expected_show = expected_show or show _status, _show, _invisible = shared_status stream.shared_status = shared_status if min_version is not None: stream.min_version = min_version forbidden_event_patterns = [EventPattern('stream-presence'), EventPattern('stream-iq', query_ns=ns.PRIVACY, iq_type='get')] q.forbid_events(forbidden_event_patterns) conn.SimplePresence.SetPresence(show, msg) conn.Connect() _, event = q.expect_many(EventPattern('stream-iq', query_ns=ns.GOOGLE_SHARED_STATUS, iq_type='get'), EventPattern('stream-iq', query_ns=ns.GOOGLE_SHARED_STATUS, iq_type='set')) shared_show, shared_invisible = _show_to_shared_status_show(show) _status = xpath.queryForNodes('//status', event.query)[0] assertEquals(msg, _status.children[0]) _show = xpath.queryForNodes('//show', event.query)[0] assertEquals(shared_show, _show.children[0]) _invisible = xpath.queryForNodes('//invisible', event.query)[0] assertEquals(shared_invisible, _invisible.getAttribute('value')) q.expect_many( EventPattern('dbus-signal', signal='PresencesChanged', interface=cs.CONN_IFACE_SIMPLE_PRESENCE, args=[{1: (presence_types[expected_show], expected_show, msg)}]), EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])) q.unforbid_events(forbidden_event_patterns) def test_connect_available(q, bus, conn, stream): _test_on_connect(q, bus, conn, stream, ("I'm busy, buddy.", 'dnd', 'false'), 'available', "I'm here, baby.") def test_connect_chat(q, bus, conn, stream): _test_on_connect(q, bus, conn, stream, ("I'm busy, buddy.", 'dnd', 'false'), 'chat', "Do you want to chat?", 'available') def test_connect_dnd(q, bus, conn, stream): _test_on_connect(q, bus, conn, stream, ("Chat with me.", 'default', 'false'), 'dnd', "I'm busy, buddy.") def test_connect_hidden(q, bus, conn, stream): _test_on_connect(q, bus, conn, stream, ("Chat with me.", 'default', 'false'), 'hidden', "I see, but I can't be seen") def test_connect_hidden_future_version(q, bus, conn, stream): _test_on_connect(q, bus, conn, stream, ("Chat with me.", 'default', 'false'), 'hidden', "I see, but I can't be seen", min_version='42') def test_connect_hidden_not_available(q, bus, conn, stream): """Fall back to DND if you try to connect while invisible, but shared status is not completely supported.""" _status, _show, _invisible = "Chat with me.", 'default', 'false' msg = "I see, but I don't think I can be seen" show = "hidden" stream.shared_status = (_status, _show, _invisible) stream.min_version = "1" presence_event_pattern = EventPattern('stream-presence') q.forbid_events([presence_event_pattern]) conn.SimplePresence.SetPresence(show, msg) conn.Connect() _, event = q.expect_many(EventPattern('stream-iq', query_ns=ns.GOOGLE_SHARED_STATUS, iq_type='get'), EventPattern('stream-iq', query_ns=ns.GOOGLE_SHARED_STATUS, iq_type='set')) _status = xpath.queryForNodes('//status', event.query)[0] assertEquals(msg, _status.children[0]) _show = xpath.queryForNodes('//show', event.query)[0] assertEquals("dnd", _show.children[0]) _invisible = xpath.queryForNodes('//invisible', event.query)[0] assertEquals("false", _invisible.getAttribute('value')) q.expect_many( EventPattern('dbus-signal', signal='PresencesChanged', interface=cs.CONN_IFACE_SIMPLE_PRESENCE, args=[{1: (cs.PRESENCE_BUSY, "dnd", msg)}]), EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])) q.unforbid_events([presence_event_pattern]) def test_shared_status_list(q, bus, conn, stream): '''Test the shared status list usage''' test_statuses = {"dnd" : ['I am not available now', 'I am busy with real work', 'I have a life, you know...', 'I am actually playing Duke Nukem', 'It is important to me'], "available" : ['I am twiddling my thumbs', 'Please chat me up', 'I am here for you', 'Message me already!']} max_statuses = int(stream.max_statuses) q.expect_many(EventPattern('stream-iq', query_ns=ns.GOOGLE_SHARED_STATUS, iq_type='get'), EventPattern('stream-iq', query_ns=ns.GOOGLE_SHARED_STATUS, iq_type='set'), EventPattern('stream-presence')) for show, statuses in test_statuses.items(): shared_show, _ = _show_to_shared_status_show(show) expected_list = stream.shared_status_lists[shared_show] for status in statuses: _test_local_status(q, conn, stream, status, show) expected_list = [status] + expected_list[:max_statuses - 1] assertEquals(expected_list, stream.shared_status_lists[shared_show]) def test_shared_status_away(q, bus, conn, stream): '''Test the shared status lists with away statuses''' q.expect_many(EventPattern('stream-iq', query_ns=ns.GOOGLE_SHARED_STATUS, iq_type='get'), EventPattern('stream-iq', query_ns=ns.GOOGLE_SHARED_STATUS, iq_type='set'), EventPattern('stream-presence')) expected_list = copy.deepcopy(stream.shared_status_lists) for show in ('away', 'xa'): for status in ('not going to', 'be actually set'): _test_local_status(q, conn, stream, status, show) assertEquals(expected_list, stream.shared_status_lists) def test_shared_status_chat(q, bus, conn, stream): '''Test that 'chat' is not supported with shared status''' q.expect_many(EventPattern('stream-iq', query_ns=ns.GOOGLE_SHARED_STATUS, iq_type='get'), EventPattern('stream-iq', query_ns=ns.GOOGLE_SHARED_STATUS, iq_type='set'), EventPattern('stream-presence')) try: conn.SimplePresence.SetPresence('chat', 'This is not going to work') except dbus.DBusException, e: assert e.get_dbus_name() == cs.NOT_AVAILABLE else: assert False if __name__ == '__main__': exec_test(test, protocol=SharedStatusStream) exec_test(test_connect_available, protocol=SharedStatusStream, do_connect=False) exec_test(test_connect_chat, protocol=SharedStatusStream, do_connect=False) exec_test(test_connect_dnd, protocol=SharedStatusStream, do_connect=False) exec_test(test_connect_hidden, protocol=SharedStatusStream, do_connect=False) exec_test(test_connect_hidden_future_version, protocol=SharedStatusStream, do_connect=False) exec_test(test_connect_hidden_not_available, protocol=SharedStatusStream, do_connect=False) exec_test(test_shared_status_list, protocol=SharedStatusStream) exec_test(test_shared_status_away, protocol=SharedStatusStream) exec_test(test_shared_status_chat, protocol=SharedStatusStream) ��������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/caps_helper.py������������������������������������������������0000664�0001750�0001750�00000026744�12332441362�023677� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# vim: set fileencoding=utf-8 : import hashlib import base64 import dbus from twisted.words.xish import domish, xpath from gabbletest import make_result_iq, make_presence, elem_iq, elem from servicetest import ( EventPattern, assertEquals, assertContains, assertDoesNotContain, assertLength, ) import config import ns import constants as cs if config.VOIP_ENABLED: FIXED_JINGLE_CAPS = [ ns.JINGLE, ns.JINGLE_015, ns.JINGLE_TRANSPORT_RAWUDP, ] else: FIXED_JINGLE_CAPS = [] # The caps we have regardless of any clients' caps FIXED_CAPS = FIXED_JINGLE_CAPS + [ ns.GOOGLE_FEAT_SESSION, ns.NICK, ns.NICK + '+notify', ns.CHAT_STATES, ns.SI, ns.IBB, ns.BYTESTREAMS, ] JINGLE_CAPS = [ # Additional Jingle transports ns.JINGLE_TRANSPORT_ICEUDP, ns.GOOGLE_P2P, # Jingle content types ns.GOOGLE_FEAT_VOICE, ns.GOOGLE_FEAT_VIDEO, ns.JINGLE_015_AUDIO, ns.JINGLE_015_VIDEO, ns.JINGLE_RTP, ns.JINGLE_RTP_AUDIO, ns.JINGLE_RTP_VIDEO, ] VARIABLE_CAPS = ( JINGLE_CAPS + [ ns.FILE_TRANSFER, # FIXME: currently we always advertise these, but in future we should # only advertise them if >= 1 client supports them: # ns.TUBES, # there is an unlimited set of these; only the ones actually relevant to # the tests so far are shown here ns.TUBES + '/stream#x-abiword', ns.TUBES + '/stream#daap', ns.TUBES + '/stream#http', ns.TUBES + '/dbus#com.example.Go', ns.TUBES + '/dbus#com.example.Xiangqi', ]) def check_caps(namespaces, desired): """Assert that all the FIXED_CAPS are supported, and of the VARIABLE_CAPS, every capability in desired is supported, and every other capability is not. """ for c in FIXED_CAPS: assertContains(c, namespaces) for c in VARIABLE_CAPS: if c in desired: assertContains(c, namespaces) else: assertDoesNotContain(c, namespaces) text_fixed_properties = dbus.Dictionary({ cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT }) text_allowed_properties = dbus.Array([cs.TARGET_HANDLE]) stream_tube_fixed_properties = dbus.Dictionary({ cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE }) stream_tube_allowed_properties = dbus.Array([cs.TARGET_HANDLE, cs.TARGET_ID, cs.STREAM_TUBE_SERVICE]) dbus_tube_fixed_properties = dbus.Dictionary({ cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE }) dbus_tube_allowed_properties = dbus.Array([cs.TARGET_HANDLE, cs.TARGET_ID, cs.DBUS_TUBE_SERVICE_NAME]) ft_fixed_properties = dbus.Dictionary({ cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_FILE_TRANSFER, }) ft_allowed_properties = dbus.Array([ cs.CHANNEL_TYPE_FILE_TRANSFER + '.ContentHashType', cs.TARGET_HANDLE, cs.TARGET_ID, cs.CHANNEL_TYPE_FILE_TRANSFER + '.ContentType', cs.CHANNEL_TYPE_FILE_TRANSFER + '.Filename', cs.CHANNEL_TYPE_FILE_TRANSFER + '.Size', cs.CHANNEL_TYPE_FILE_TRANSFER + '.ContentHash', cs.CHANNEL_TYPE_FILE_TRANSFER + '.Description', cs.CHANNEL_TYPE_FILE_TRANSFER + '.Date', cs.FT_URI]) ft_allowed_properties_with_metadata = dbus.Array( ft_allowed_properties + [cs.FT_SERVICE_NAME, cs.FT_METADATA]) fake_client_dataforms = { 'urn:xmpp:dataforms:softwareinfo': {'software': ['A Fake Client with Twisted'], 'software_version': ['5.11.2-svn-20080512'], 'os': ['Debian GNU/Linux unstable (sid) unstable sid'], 'os_version': ['2.6.24-1-amd64'], }, } def compute_caps_hash(identities, features, dataforms): """ Accepts a list of slash-separated identities, a list of feature namespaces, and a map from FORM_TYPE to (map from field name to values), returns the verification string as defined by <http://xmpp.org/extensions/xep-0115.html#ver>. """ components = [] for identity in sorted(identities): if len(identity.split('/')) != 4: raise ValueError( "expecting identities of the form " + "'category/type/lang/client': got " + repr(identity)) components.append(identity) for feature in sorted(features): components.append(feature) for form_type in sorted(dataforms.keys()): components.append(form_type) for var in sorted(dataforms[form_type].keys()): components.append(var) for value in sorted(dataforms[form_type][var]): components.append(value) components.append('') m = hashlib.sha1() S = u'<'.join(components) m.update(S.encode('utf-8')) return base64.b64encode(m.digest()) def add_data_forms(root, dataforms): for type, fields in dataforms.iteritems(): x = root.addElement((ns.X_DATA, 'x')) x['type'] = 'result' field = x.addElement('field') field['var'] = 'FORM_TYPE' field['type'] = 'hidden' field.addElement('value', content=type) for var, values in fields.iteritems(): field = x.addElement('field') field['var'] = var for value in values: field.addElement('value', content=value) def make_caps_disco_reply(stream, req, identities, features, dataforms={}): iq = make_result_iq(stream, req) query = iq.firstChildElement() for identity in identities: category, type_, lang, name = identity.split('/') el = query.addElement('identity') el['category'] = category el['type'] = type_ el['name'] = name el['xml:lang'] = lang for f in features: el = domish.Element((None, 'feature')) el['var'] = f query.addChild(el) add_data_forms(query, dataforms) return iq def receive_presence_and_ask_caps(q, stream, expect_dbus=True): # receive presence stanza if expect_dbus: presence, event_dbus = q.expect_many( EventPattern('stream-presence'), EventPattern('dbus-signal', signal='ContactCapabilitiesChanged') ) assertLength(1, event_dbus.args) signaled_caps = event_dbus.args[0] else: presence = q.expect('stream-presence') signaled_caps = None return disco_caps(q, stream, presence) + (signaled_caps,) def extract_data_forms(x_nodes): dataforms = {} if not x_nodes: return dataforms for form in x_nodes: name = None fields = {} for field in xpath.queryForNodes('/x/field', form): if field['var'] == 'FORM_TYPE': name = str(field.firstChildElement()) else: value_nodes = xpath.queryForNodes('/field/value', field) or [] values = [str(x) for x in value_nodes] fields[field['var']] = values if name is not None: dataforms[name] = fields return dataforms def extract_disco_parts(stanza): identity_nodes = xpath.queryForNodes('/iq/query/identity', stanza) assertLength(1, identity_nodes) identity_node = identity_nodes[0] assertEquals('client', identity_node['category']) assertEquals(config.CLIENT_TYPE, identity_node['type']) assertEquals(config.PACKAGE_STRING, identity_node['name']) assertDoesNotContain('xml:lang', identity_node.attributes) identity = 'client/%s//%s' % (config.CLIENT_TYPE, config.PACKAGE_STRING) features = [] for feature in xpath.queryForNodes('/iq/query/feature', stanza): features.append(feature['var']) # a quick and ugly data form extractor x_nodes = xpath.queryForNodes('/iq/query/x', stanza) or [] dataforms = extract_data_forms(x_nodes) return ([identity], features, dataforms) def disco_caps(q, stream, presence): c_nodes = xpath.queryForNodes('/presence/c', presence.stanza) assert c_nodes is not None assertLength(1, c_nodes) hash = c_nodes[0].attributes['hash'] ver = c_nodes[0].attributes['ver'] node = c_nodes[0].attributes['node'] assertEquals('sha-1', hash) # ask caps request = \ elem_iq(stream, 'get', from_='fake_contact@jabber.org/resource')( elem(ns.DISCO_INFO, 'query', node=(node + '#' + ver)) ) stream.send(request) # receive caps event = q.expect('stream-iq', query_ns=ns.DISCO_INFO, iq_id=request['id']) # Check that Gabble's announcing the identity we think it should be. (identities, features, dataforms) = extract_disco_parts(event.stanza) # Check if the hash matches the announced capabilities assertEquals(compute_caps_hash(identities, features, dataforms), ver) return (event, features, dataforms) def caps_contain(event, cap): node = xpath.queryForNodes('/iq/query/feature[@var="%s"]' % cap, event.stanza) if node is None: return False if len(node) != 1: return False var = node[0].attributes['var'] if var is None: return False return var == cap def presence_and_disco(q, conn, stream, contact, disco, client, caps, features, identities=[], dataforms={}, initial=True, show=None): h = send_presence(q, conn, stream, contact, caps, initial=initial, show=show) if disco: stanza = expect_disco(q, contact, client, caps) send_disco_reply(stream, stanza, identities, features, dataforms) return h def send_presence(q, conn, stream, contact, caps, initial=True, show=None): h = conn.RequestHandles(cs.HT_CONTACT, [contact])[0] if initial: stream.send(make_presence(contact, status='hello')) q.expect('dbus-signal', signal='PresencesChanged', args=[{h: (2, u'available', 'hello')}]) # no special capabilities assertEquals([(h, cs.CHANNEL_TYPE_TEXT, 3, 0)], conn.Capabilities.GetCapabilities([h])) # send updated presence with caps info stream.send(make_presence(contact, show=show, status='hello', caps=caps)) return h def expect_disco(q, contact, client, caps): # Gabble looks up our capabilities event = q.expect('stream-iq', to=contact, query_ns=ns.DISCO_INFO) assertEquals(client + '#' + caps['ver'], event.query['node']) return event.stanza def send_disco_reply(stream, stanza, identities, features, dataforms={}): stream.send( make_caps_disco_reply(stream, stanza, identities, features, dataforms)) if __name__ == '__main__': # example from XEP-0115 assertEquals('QgayPKawpkPSDYmwT/WM94uAlu0=', compute_caps_hash(['client/pc//Exodus 0.9.1'], ["http://jabber.org/protocol/disco#info", "http://jabber.org/protocol/disco#items", "http://jabber.org/protocol/muc", "http://jabber.org/protocol/caps"], {})) # another example from XEP-0115 identities = [u'client/pc/en/Psi 0.11', u'client/pc/el/Ψ 0.11'] features = [ u'http://jabber.org/protocol/caps', u'http://jabber.org/protocol/disco#info', u'http://jabber.org/protocol/disco#items', u'http://jabber.org/protocol/muc', ] dataforms = { u'urn:xmpp:dataforms:softwareinfo': { u'ip_version': [u'ipv4', u'ipv6'], u'os': [u'Mac'], u'os_version': [u'10.5.1'], u'software': [u'Psi'], u'software_version': [u'0.11'], }, } assertEquals('q07IKJEyjvHSyhy//CH0CxmKi8w=', compute_caps_hash(identities, features, dataforms)) ����������������������������telepathy-gabble-0.18.3/tests/twisted/test-fallback-socks5-proxy.py���������������������������������0000664�0001750�0001750�00000032213�12332441362�026476� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ import socket from gabbletest import ( exec_test, elem, elem_iq, sync_stream, make_presence, send_error_reply, make_result_iq, sync_stream) from servicetest import ( EventPattern, call_async, assertEquals, assertLength, assertDoesNotContain) from caps_helper import send_disco_reply from bytestream import create_from_si_offer, BytestreamS5B import ns import constants as cs from twisted.words.xish import xpath import dbus from config import FILE_TRANSFER_ENABLED proxy_query_events = [ EventPattern('stream-iq', to='fallback1-proxy.localhost', iq_type='get', query_ns=ns.BYTESTREAMS), EventPattern('stream-iq', to='fallback2-proxy.localhost', iq_type='get', query_ns=ns.BYTESTREAMS)] proxy_port = {'fallback1-proxy.localhost': '12345', 'fallback2-proxy.localhost': '6789', 'fallback3-proxy.localhost': '3333', 'fallback4-proxy.localhost': '4444', 'fallback5-proxy.localhost': '5555', 'fallback6-proxy.localhost': '6666',} def connect_and_announce_alice(q, bus, conn, stream): q.forbid_events(proxy_query_events) # Send Alice's presence caps = { 'ext': '', 'ver': '0.0.0', 'node': 'http://example.com/fake-client0' } presence = make_presence('alice@localhost/Test', caps=caps) stream.send(presence) disco_event = q.expect('stream-iq', to='alice@localhost/Test', query_ns=ns.DISCO_INFO) send_disco_reply( stream, disco_event.stanza, [], [ns.TUBES, ns.FILE_TRANSFER]) sync_stream(q, stream) q.unforbid_events(proxy_query_events) def send_socks5_reply(stream, iq, jid=None, host=None, port=None): if jid is None: jid = iq['to'] if port is None: port = proxy_port[jid] if host is None: host = '127.0.0.1' reply = elem_iq(stream, 'result', id=iq['id'], from_=iq['to'])( elem(ns.BYTESTREAMS, 'query')( elem('streamhost', jid=jid, host=host, port=port)())) stream.send(reply) def wait_si_and_return_proxies(q, stream): e = q.expect('stream-iq', to='alice@localhost/Test') bytestream, profile = create_from_si_offer(stream, q, BytestreamS5B, e.stanza, 'test@localhost/Resource') # Alice accepts the SI result, si = bytestream.create_si_reply(e.stanza) stream.send(result) e = q.expect('stream-iq', to='alice@localhost/Test') proxies = [] for node in xpath.queryForNodes('/iq/query/streamhost', e.stanza): if node['jid'] == 'test@localhost/Resource': # skip our own stream hosts continue proxies.append((node['jid'], node['host'], node['port'])) return proxies def check_proxies(expected, proxies): assertEquals(set(expected), set(proxies)) def offer_dbus_tube(q, bus, conn, stream): connect_and_announce_alice(q, bus, conn, stream) # Offer a private D-Bus tube just to check if the proxy is present in the # SOCKS5 offer call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: 'alice@localhost', cs.DBUS_TUBE_SERVICE_NAME: 'com.example.TestCase'}) # Proxy queries are send when creating the channel return_event, e1, e2 = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), proxy_query_events[0], proxy_query_events[1]) send_socks5_reply(stream, e1.stanza) send_socks5_reply(stream, e2.stanza) path, props = return_event.value tube_chan = bus.get_object(conn.bus_name, path) dbus_tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_DBUS_TUBE) dbus_tube_iface.Offer({}, cs.SOCKET_ACCESS_CONTROL_CREDENTIALS) proxies = wait_si_and_return_proxies(q, stream) check_proxies([('fallback2-proxy.localhost', '127.0.0.1', '6789'), ('fallback1-proxy.localhost', '127.0.0.1', '12345')], proxies) def accept_stream_tube(q, bus, conn, stream): connect_and_announce_alice(q, bus, conn, stream) # Accept a stream tube, we'll need SOCKS5 proxies each time we'll connect # on the tube socket # Alice offers us a stream tube message = elem('message', to='test@localhost/Resource', from_='alice@localhost/Test')( elem(ns.TUBES, 'tube', type='stream', service='http', id='10')) stream.send(message) # we are interested in the 'NewChannels' announcing the tube channel def new_chan_predicate(e): path, props = e.args[0][0] return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE # Proxy queries are send when receiving an incoming stream tube new_chan, e1, e2 = q.expect_many( EventPattern('dbus-signal', signal='NewChannels', predicate=new_chan_predicate), proxy_query_events[0], proxy_query_events[1]) send_socks5_reply(stream, e1.stanza) send_socks5_reply(stream, e2.stanza) path, props = new_chan.args[0][0] assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE tube_chan = bus.get_object(conn.bus_name, path) tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE) # connect to the socket so a SOCKS5 bytestream will be created address = tube_iface.Accept(cs.SOCKET_ADDRESS_TYPE_IPV4, cs.SOCKET_ACCESS_CONTROL_LOCALHOST, 0, byte_arrays=True) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(address) proxies = wait_si_and_return_proxies(q, stream) check_proxies([('fallback2-proxy.localhost', '127.0.0.1', '6789'), ('fallback1-proxy.localhost', '127.0.0.1', '12345')], proxies) def send_file_to_alice(q, conn): call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_FILE_TRANSFER, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: 'alice@localhost', cs.FT_FILENAME: 'test.txt', cs.FT_CONTENT_TYPE: 'text/plain', cs.FT_SIZE: 10}) def send_file(q, bus, conn, stream): connect_and_announce_alice(q, bus, conn, stream) # Send a file; proxy queries are send when creating the FT channel send_file_to_alice(q, conn) return_event, e1, e2 = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), proxy_query_events[0], proxy_query_events[1]) send_socks5_reply(stream, e1.stanza) send_socks5_reply(stream, e2.stanza) # ensure that the same proxy is not queried more than once q.forbid_events(proxy_query_events) proxies = wait_si_and_return_proxies(q, stream) check_proxies([('fallback2-proxy.localhost', '127.0.0.1', '6789'), ('fallback1-proxy.localhost', '127.0.0.1', '12345')], proxies) def double_server(q, bus, conn, stream): # For some reason the 2 proxies are actually the same. Check that we don't # set them twice in the SOCKS5 init stanza connect_and_announce_alice(q, bus, conn, stream) send_file_to_alice(q, conn) return_event, e1, e2 = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), proxy_query_events[0], proxy_query_events[1]) send_socks5_reply(stream, e1.stanza) # send the same reply for the second stanza with with a different port send_socks5_reply(stream, e2.stanza, 'fallback1-proxy.localhost', '127.0.0.1', '6789') proxies = wait_si_and_return_proxies(q, stream) # check that the proxy has been set only once check_proxies([('fallback1-proxy.localhost', '127.0.0.1', '6789')], proxies) def cache_full(q, bus, conn, stream): # Test how Gabble manages the proxy cache once it's full connect_and_announce_alice(q, bus, conn, stream) send_file_to_alice(q, conn) # 3 proxies are queried (NB_MIN_SOCKS5_PROXIES) return_event, e1, e2, e3 = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('stream-iq', iq_type='get', query_ns=ns.BYTESTREAMS), EventPattern('stream-iq', iq_type='get', query_ns=ns.BYTESTREAMS), EventPattern('stream-iq', iq_type='get', query_ns=ns.BYTESTREAMS)) send_socks5_reply(stream, e1.stanza) send_socks5_reply(stream, e2.stanza) send_socks5_reply(stream, e3.stanza) proxies = wait_si_and_return_proxies(q, stream) assertLength(3, set(proxies)) oldest_proxy = proxies[2] # send another file, one more proxy is queried send_file_to_alice(q, conn) return_event, e1, = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('stream-iq', iq_type='get', query_ns=ns.BYTESTREAMS)) send_socks5_reply(stream, e1.stanza) proxies = wait_si_and_return_proxies(q, stream) assertLength(4, set(proxies)) # the new proxy is the head of the list assertEquals(e1.stanza['to'], proxies[0][0]) # send another file, one more proxy is queried send_file_to_alice(q, conn) return_event, e1, = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('stream-iq', iq_type='get', query_ns=ns.BYTESTREAMS)) send_socks5_reply(stream, e1.stanza) proxies = wait_si_and_return_proxies(q, stream) assertLength(5, set(proxies)) # the new proxy is the head of the list assertEquals(e1.stanza['to'], proxies[0][0]) # send another file, one more proxy is queried send_file_to_alice(q, conn) return_event, e1, = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('stream-iq', iq_type='get', query_ns=ns.BYTESTREAMS)) send_socks5_reply(stream, e1.stanza) proxies = wait_si_and_return_proxies(q, stream) # we reached the max size of the cache (FALLBACK_PROXY_CACHE_SIZE) so the # oldest proxy has been removed assertLength(5, set(proxies)) # the new proxy is the head of the list assertEquals(e1.stanza['to'], proxies[0][0]) # the oldest proxy has been removed assertDoesNotContain(oldest_proxy, proxies) #send another file. We already queried all the proxies so the list is recycled send_file_to_alice(q, conn) # the oldest proxy is re-requested first return_event, e1, = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('stream-iq', to=oldest_proxy[0], iq_type='get', query_ns=ns.BYTESTREAMS)) def proxy_error(q, bus, conn, stream): # Test if another proxy is queried if a query failed connect_and_announce_alice(q, bus, conn, stream) send_file_to_alice(q, conn) return_event, e1, e2, e3 = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('stream-iq', iq_type='get', query_ns=ns.BYTESTREAMS), EventPattern('stream-iq', iq_type='get', query_ns=ns.BYTESTREAMS), EventPattern('stream-iq', iq_type='get', query_ns=ns.BYTESTREAMS)) # Return errors for all the requests; the bugged proxies shouldn't be queried again q.forbid_events([EventPattern('stream-iq', to=e1.stanza['to'], iq_type='get', query_ns=ns.BYTESTREAMS)]) send_error_reply(stream, e1.stanza) # the fourth proxy is queried q.expect('stream-iq', iq_type='get', query_ns=ns.BYTESTREAMS) q.forbid_events([EventPattern('stream-iq', to=e2.stanza['to'], iq_type='get', query_ns=ns.BYTESTREAMS)]) send_error_reply(stream, e2.stanza) sync_stream(q, stream) q.forbid_events([EventPattern('stream-iq', to=e3.stanza['to'], iq_type='get', query_ns=ns.BYTESTREAMS)]) send_error_reply(stream, e3.stanza) sync_stream(q, stream) def proxies_telepathy_im(q, bus, conn, stream): # Test if proxies.telepathy.im is properly used when no fallback proxies # are passed to Gabble connect_and_announce_alice(q, bus, conn, stream) send_file_to_alice(q, conn) # Gabble asks for a proxy list to our server return_event, e, = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('stream-iq', to='proxies.telepathy.im', iq_type='get', query_ns=ns.DISCO_ITEMS)) # reply with 2 servers reply = make_result_iq(stream, e.stanza) query = xpath.queryForNodes('/iq/query', reply)[0] item = query.addElement((None, 'item')) item['jid'] = 'proxy1.localhost' item = query.addElement((None, 'item')) item['jid'] = 'proxy2.localhost' stream.send(reply) # These servers are queried e1, e2 = q.expect_many( EventPattern('stream-iq', to='proxy1.localhost', iq_type='get', query_ns=ns.BYTESTREAMS), EventPattern('stream-iq', to='proxy2.localhost', iq_type='get', query_ns=ns.BYTESTREAMS)) if __name__ == '__main__': params = {'fallback-socks5-proxies': ['fallback1-proxy.localhost', 'fallback2-proxy.localhost']} exec_test(offer_dbus_tube, params=params) exec_test(accept_stream_tube, params=params) if FILE_TRANSFER_ENABLED: exec_test(send_file, params=params) exec_test(double_server, params=params) params6 = {'fallback-socks5-proxies': ['fallback1-proxy.localhost', 'fallback2-proxy.localhost', 'fallback3-proxy.localhost', 'fallback4-proxy.localhost', 'fallback5-proxy.localhost', 'fallback6-proxy.localhost']} exec_test(cache_full, params=params6) params4 = {'fallback-socks5-proxies': ['fallback1-proxy.localhost', 'fallback2-proxy.localhost', 'fallback3-proxy.localhost', 'fallback4-proxy.localhost']} exec_test(proxy_error, params=params4) exec_test(proxies_telepathy_im, params={}) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/�������������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�022302� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/test-outgoing-call-rejected.py�������������������������0000664�0001750�0001750�00000006000�12332441362�030145� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test outgoing call handling. This tests the case when the remote party rejects our call because they're busy. """ from gabbletest import make_result_iq from servicetest import make_channel_proxy, assertEquals import constants as cs from jingletest2 import JingleTest2, test_all_dialects from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def _test(jp, q, bus, conn, stream, jingle_reason, group_change_reason, stream_error): remote_jid = 'foo@bar.com/Foo' jt = JingleTest2(jp, conn, q, stream, 'test@localhost', remote_jid) jt.prepare() self_handle = conn.GetSelfHandle() remote_handle = conn.RequestHandles(cs.HT_CONTACT, [remote_jid])[0] path = conn.RequestChannel(cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.HT_CONTACT, remote_handle, True) signalling_iface = make_channel_proxy(conn, path, 'Channel.Interface.MediaSignalling') media_iface = make_channel_proxy(conn, path, 'Channel.Type.StreamedMedia') media_iface.RequestStreams(remote_handle, [cs.MEDIA_STREAM_TYPE_AUDIO]) # S-E gets notified about new session handler, and calls Ready on it e = q.expect('dbus-signal', signal='NewSessionHandler') assert e.args[1] == 'rtp' session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() e = q.expect('dbus-signal', signal='NewStreamHandler') stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) stream_handler.Ready(jt.get_audio_codecs_dbus()) stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) e = q.expect('stream-iq', predicate=jp.action_predicate('session-initiate')) stream.send(make_result_iq(stream, e.stanza)) text = u"begone!" jt.parse_session_initiate(e.query) jt.terminate(reason=jingle_reason, text=text) mc = q.expect('dbus-signal', signal='MembersChanged') message, added, removed, lp, rp, actor, reason = mc.args assert added == [], added assert set(removed) == set([self_handle, remote_handle]), \ (removed, self_handle, remote_handle) assert lp == [], lp assert rp == [], rp assert actor == remote_handle, (actor, remote_handle) if jp.is_modern_jingle(): assertEquals(text, message) assertEquals(group_change_reason, reason) if jp.is_modern_jingle() and stream_error: se = q.expect('dbus-signal', signal='StreamError') assertEquals(stream_error, se.args[1]) q.expect('dbus-signal', signal='Close') #XXX - match against the path def test_busy(jp, q, bus, conn, stream): _test(jp, q, bus, conn, stream, "busy", cs.GC_REASON_BUSY, None) def test_codec_fail(jp, q, bus, conn, stream): _test(jp, q, bus, conn, stream, "failed-application", cs.GC_REASON_ERROR, cs.MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED) if __name__ == '__main__': test_all_dialects(test_busy) test_all_dialects(test_codec_fail) telepathy-gabble-0.18.3/tests/twisted/jingle/initial-audio-video.py���������������������������������0000664�0001750�0001750�00000016251�12332441362�026506� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Tests outgoing calls created with InitialAudio and/or InitialVideo, and exposing the initial contents of incoming calls as values of InitialAudio and InitialVideo """ import operator from servicetest import ( assertContains, assertEquals, assertLength, wrap_channel, EventPattern, call_async, make_channel_proxy) from jingletest2 import JingleTest2, test_all_dialects import constants as cs from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def outgoing(jp, q, bus, conn, stream): remote_jid = 'flames@cold.mountain/beyond' jt = JingleTest2(jp, conn, q, stream, 'test@localhost', remote_jid) jt.prepare() self_handle = conn.GetSelfHandle() remote_handle = conn.RequestHandles(cs.HT_CONTACT, [remote_jid])[0] rccs = conn.Properties.Get(cs.CONN_IFACE_REQUESTS, 'RequestableChannelClasses') media_classes = [ rcc for rcc in rccs if rcc[0][cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAMED_MEDIA ] assertLength(1, media_classes) fixed, allowed = media_classes[0] assertContains(cs.INITIAL_AUDIO, allowed) assertContains(cs.INITIAL_VIDEO, allowed) check_neither(q, conn, bus, stream, remote_handle) check_iav(jt, q, conn, bus, stream, remote_handle, True, False) check_iav(jt, q, conn, bus, stream, remote_handle, False, True) check_iav(jt, q, conn, bus, stream, remote_handle, True, True) def check_neither(q, conn, bus, stream, remote_handle): """ Make a channel without specifying InitialAudio or InitialVideo; check that it's announced with both False, and that they're both present and false in GetAll(). """ path, props = conn.Requests.CreateChannel({ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: remote_handle}) assertContains((cs.INITIAL_AUDIO, False), props.items()) assertContains((cs.INITIAL_VIDEO, False), props.items()) chan = wrap_channel(bus.get_object(conn.bus_name, path), cs.CHANNEL_TYPE_STREAMED_MEDIA, ['MediaSignalling']) props = chan.Properties.GetAll(cs.CHANNEL_TYPE_STREAMED_MEDIA) assertContains(('InitialAudio', False), props.items()) assertContains(('InitialVideo', False), props.items()) # We shouldn't have started a session yet, so there shouldn't be any # session handlers. Strictly speaking, there could be a session handler # with no stream handlers, but... session_handlers = chan.MediaSignalling.GetSessionHandlers() assertLength(0, session_handlers) def check_iav(jt, q, conn, bus, stream, remote_handle, initial_audio, initial_video): """ Make a channel and check that its InitialAudio and InitialVideo properties come out correctly. """ call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: remote_handle, cs.INITIAL_AUDIO: initial_audio, cs.INITIAL_VIDEO: initial_video, }) if initial_video and (not jt.jp.can_do_video() or (not initial_audio and not jt.jp.can_do_video_only ())): # Some protocols can't do video event = q.expect('dbus-error', method='CreateChannel') assertEquals(cs.NOT_CAPABLE, event.error.get_dbus_name()) else: path, props = q.expect('dbus-return', method='CreateChannel').value assertContains((cs.INITIAL_AUDIO, initial_audio), props.items()) assertContains((cs.INITIAL_VIDEO, initial_video), props.items()) chan = wrap_channel(bus.get_object(conn.bus_name, path), cs.CHANNEL_TYPE_STREAMED_MEDIA, ['MediaSignalling']) props = chan.Properties.GetAll(cs.CHANNEL_TYPE_STREAMED_MEDIA) assertContains(('InitialAudio', initial_audio), props.items()) assertContains(('InitialVideo', initial_video), props.items()) session_handlers = chan.MediaSignalling.GetSessionHandlers() assertLength(1, session_handlers) path, type = session_handlers[0] assertEquals('rtp', type) session_handler = make_channel_proxy(conn, path, 'Media.SessionHandler') session_handler.Ready() stream_handler_paths = [] stream_handler_types = [] for x in [initial_audio, initial_video]: if x: e = q.expect('dbus-signal', signal='NewStreamHandler') stream_handler_paths.append(e.args[0]) stream_handler_types.append(e.args[2]) if initial_audio: assertContains(cs.MEDIA_STREAM_TYPE_AUDIO, stream_handler_types) if initial_video: assertContains(cs.MEDIA_STREAM_TYPE_VIDEO, stream_handler_types) for x in xrange (0, len(stream_handler_paths)): p = stream_handler_paths[x] t = stream_handler_types[x] sh = make_channel_proxy(conn, p, 'Media.StreamHandler') sh.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) if t == cs.MEDIA_STREAM_TYPE_AUDIO: sh.Ready(jt.get_audio_codecs_dbus()) else: sh.Ready(jt.get_video_codecs_dbus()) sh.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) e = q.expect('stream-iq', predicate=jt.jp.action_predicate('session-initiate')) jt.parse_session_initiate (e.query) jt.accept() events = reduce(operator.concat, [ [ EventPattern('dbus-signal', signal='SetRemoteCodecs', path=p), EventPattern('dbus-signal', signal='SetStreamPlaying', path=p), ] for p in stream_handler_paths ], []) q.expect_many(*events) chan.Close() def incoming(jp, q, bus, conn, stream): remote_jid = 'skinny.fists@heaven/antennas' jt = JingleTest2(jp, conn, q, stream, 'test@localhost', remote_jid) jt.prepare() self_handle = conn.GetSelfHandle() remote_handle = conn.RequestHandles(cs.HT_CONTACT, [remote_jid])[0] for a, v in [("audio1", None), (None, "video1"), ("audio1", "video1")]: if v!= None and not jp.can_do_video(): continue if a == None and v != None and not jp.can_do_video_only(): continue jt.incoming_call(audio=a, video=v) e = q.expect('dbus-signal', signal='NewChannels', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args[0][0][1].values()) chans = e.args[0] assertLength(1, chans) path, props = chans[0] assertEquals(cs.CHANNEL_TYPE_STREAMED_MEDIA, props[cs.CHANNEL_TYPE]) assertEquals(a != None, props[cs.INITIAL_AUDIO]) assertEquals(v != None, props[cs.INITIAL_VIDEO]) # FIXME: This doesn't check non-Google contacts that can only do one # media type, as such contacts as simulated by JingleTest2 can always # do both. assertEquals(not jp.can_do_video() or not jp.can_do_video_only(), props[cs.IMMUTABLE_STREAMS]) chan = wrap_channel(bus.get_object(conn.bus_name, path), cs.CHANNEL_TYPE_STREAMED_MEDIA) chan.Close() if __name__ == '__main__': test_all_dialects(outgoing) test_all_dialects(incoming) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/stream-errors-on-content-reject.py���������������������0000664�0001750�0001750�00000022630�12332441362�031011� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test StreamError events when new content is rejected in-call. """ import dbus from gabbletest import make_result_iq, sync_stream, exec_test from servicetest import ( make_channel_proxy, unwrap, EventPattern, assertEquals, assertLength) from jingletest2 import JingleTest2, JingleProtocol031 import constants as cs from twisted.words.xish import xpath from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def _content_reject_predicate(event): reason = xpath.queryForNodes("/iq" "/jingle[@action='content-reject']" "/reason/failed-application", event.stanza) return bool(reason) def _start_audio_session(jp, q, bus, conn, stream, incoming): jt = JingleTest2(jp, conn, q, stream, 'test@localhost', 'foo@bar.com/Foo') jt.prepare() self_handle = conn.GetSelfHandle() remote_handle = conn.RequestHandles(cs.HT_CONTACT, [jt.peer])[0] if incoming: jt.incoming_call() else: ret = conn.Requests.CreateChannel( { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: remote_handle, cs.INITIAL_AUDIO: True }) nc, e = q.expect_many( EventPattern('dbus-signal', signal='NewChannel', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args), EventPattern('dbus-signal', signal='NewSessionHandler')) path = nc.args[0] media_chan = make_channel_proxy(conn, path, 'Channel.Interface.Group') media_iface = make_channel_proxy(conn, path, 'Channel.Type.StreamedMedia') # S-E was notified about new session handler, and calls Ready on it session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() nsh_event = q.expect('dbus-signal', signal='NewStreamHandler') # S-E gets notified about a newly-created stream stream_handler = make_channel_proxy(conn, nsh_event.args[0], 'Media.StreamHandler') group_props = media_chan.GetAll( cs.CHANNEL_IFACE_GROUP, dbus_interface=dbus.PROPERTIES_IFACE) if incoming: assertEquals([remote_handle], group_props['Members']) assertEquals(unwrap(group_props['LocalPendingMembers']), [(self_handle, remote_handle, cs.GC_REASON_INVITED, '')]) else: assertEquals([self_handle], group_props['Members']) streams = media_chan.ListStreams( dbus_interface=cs.CHANNEL_TYPE_STREAMED_MEDIA) stream_id = streams[0][0] stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) stream_handler.Ready(jt.dbusify_codecs([("FOO", 5, 8000, {})])) msg = u"None of the codecs are good for us, damn!" expected_events = [] if incoming: stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) stream_handler.SupportedCodecs(jt.get_audio_codecs_dbus()) e = q.expect('stream-iq', predicate=jp.action_predicate('transport-info')) assertEquals(jt.peer, e.query['initiator']) content = xpath.queryForNodes('/iq/jingle/content', e.stanza)[0] assertEquals('initiator', content['creator']) stream.send(make_result_iq(stream, e.stanza)) media_chan.AddMembers([self_handle], 'accepted') memb, acc, _, _, _ = q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=[u'', [self_handle], [], [], [], self_handle, cs.GC_REASON_NONE]), EventPattern('stream-iq', predicate=jp.action_predicate('session-accept')), EventPattern('dbus-signal', signal='SetStreamSending', args=[True]), EventPattern('dbus-signal', signal='SetStreamPlaying', args=[True]), EventPattern('dbus-signal', signal='StreamDirectionChanged', args=[stream_id, cs.MEDIA_STREAM_DIRECTION_BIDIRECTIONAL, 0])) stream.send(make_result_iq(stream, acc.stanza)) active_event = jp.rtp_info_event("active") if active_event is not None: q.expect_many(active_event) members = media_chan.GetMembers() assert set(members) == set([self_handle, remote_handle]), members else: stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) session_initiate = q.expect( 'stream-iq', predicate=jp.action_predicate('session-initiate')) q.expect('dbus-signal', signal='MembersChanged', path=path, args=['', [], [], [], [remote_handle], self_handle, cs.GC_REASON_INVITED]) jt.parse_session_initiate(session_initiate.query) stream.send(jp.xml(jp.ResultIq('test@localhost', session_initiate.stanza, []))) jt.accept() q.expect_many( EventPattern('stream-iq', iq_type='result'), # Call accepted EventPattern('dbus-signal', signal='MembersChanged', args=['', [remote_handle], [], [], [], remote_handle, cs.GC_REASON_NONE]), ) return jt, media_iface def _start_audio_session_outgoing(jp, q, bus, conn, stream): return _start_audio_session(jp, q, bus, conn, stream, False) def _start_audio_session_incoming(jp, q, bus, conn, stream): return _start_audio_session(jp, q, bus, conn, stream, True) def _remote_content_add(jp, q, bus, conn, stream, initiate_call_func): jt, chan = initiate_call_func(jp, q, bus, conn, stream) video_codecs = [ jp.PayloadType(name, str(rate), str(id), parameters) \ for (name, id, rate, parameters) in jt.video_codecs] node = jp.SetIq(jt.peer, jt.jid, [ jp.Jingle(jt.sid, jt.peer, 'content-add', [ jp.Content( 'videostream', 'initiator', 'both', jp.Description('video', video_codecs), jp.TransportGoogleP2P()) ]) ]) stream.send(jp.xml(node)) _, nsh = q.expect_many( EventPattern('dbus-signal', signal='StreamAdded'), EventPattern('dbus-signal', signal='NewStreamHandler')) stream_handler_path, stream_id, media_type, direction = nsh.args video_handler = make_channel_proxy(conn, stream_handler_path, 'Media.StreamHandler') video_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) video_handler.Ready(jt.dbusify_codecs([("FOO", 5, 8000, {})])) msg = u"None of the codecs are good for us, damn!" video_handler.Error(cs.MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED, msg) q.expect_many( EventPattern('dbus-signal', signal='StreamError', args=[stream_id, cs.MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED, msg]), EventPattern('stream-iq', predicate=_content_reject_predicate)) def _local_content_add(jp, q, bus, conn, stream, initiate_call_func): jt, chan = initiate_call_func(jp, q, bus, conn, stream) remote_handle = conn.RequestHandles(cs.HT_CONTACT, [jt.peer])[0] chan.RequestStreams(remote_handle, [cs.MEDIA_STREAM_TYPE_VIDEO]) nsh = q.expect('dbus-signal', signal='NewStreamHandler') stream_handler_path, stream_id, media_type, direction = nsh.args video_handler = make_channel_proxy(conn, stream_handler_path, 'Media.StreamHandler') video_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) video_handler.Ready(jt.get_audio_codecs_dbus()) video_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) e = q.expect('stream-iq', predicate=jp.action_predicate('content-add')) c = e.query.firstChildElement() stream.send(make_result_iq(stream, e.stanza)) node = jp.SetIq(jt.peer, jt.jid, [ jp.Jingle(jt.sid, jt.peer, 'content-reject', [ ('reason', None, {}, [ ('failed-application', None, {}, [])]), jp.Content(c['name'], c['creator'], c['senders']) ]) ]) stream.send(jp.xml(node)) q.expect('dbus-signal', signal='StreamError', args=[stream_id, cs.MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED, ""]), def test_remote_content_add_incoming(jp, q, bus, conn, stream): _remote_content_add(jp, q, bus, conn, stream, _start_audio_session_incoming) def test_remote_content_add_outgoing(jp, q, bus, conn, stream): _remote_content_add(jp, q, bus, conn, stream, _start_audio_session_outgoing) def test_local_content_add_incoming(jp, q, bus, conn, stream): _local_content_add(jp, q, bus, conn, stream, _start_audio_session_incoming) def test_local_content_add_outgoing(jp, q, bus, conn, stream): _local_content_add(jp, q, bus, conn, stream, _start_audio_session_outgoing) if __name__ == '__main__': for f in (test_local_content_add_incoming, test_local_content_add_outgoing, test_remote_content_add_incoming, test_remote_content_add_outgoing): exec_test( lambda q, b, c, s: f(JingleProtocol031(), q, b, c, s)) ��������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/outgoing-ensure.py�������������������������������������0000664�0001750�0001750�00000017465�12332441362�026014� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test making outgoing calls using EnsureChannel, and retrieving existing calls using EnsureChannel. This also exercises calls to a contact on a SIP gateway, who has no resource, only a bare JID. """ from functools import partial from gabbletest import exec_test from servicetest import ( wrap_channel, call_async, EventPattern, assertEquals, assertLength, ) import constants as cs from jingletest2 import JingleProtocol031, JingleTest2 from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test(q, bus, conn, stream, channel_type): jt = JingleTest2(JingleProtocol031(), conn, q, stream, 'test@localhost', 'foo@sip.bar.com') jt.prepare() self_handle = conn.GetSelfHandle() handle = conn.RequestHandles(cs.HT_CONTACT, [jt.peer])[0] request = { cs.CHANNEL_TYPE: channel_type, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: handle} if channel_type == cs.CHANNEL_TYPE_CALL: request[cs.CALL_INITIAL_AUDIO] = True # Ensure a channel that doesn't exist yet. call_async(q, conn.Requests, 'EnsureChannel', request) ret, old_sig, new_sig = q.expect_many( EventPattern('dbus-return', method='EnsureChannel'), EventPattern('dbus-signal', signal='NewChannel', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args), EventPattern('dbus-signal', signal='NewChannels', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args[0][0][1].values()), ) yours, path, props = ret.value # this channel was created in response to our EnsureChannel call, so it # should be ours. assert yours, ret.value sig_path, sig_ct, sig_ht, sig_h, sig_sh = old_sig.args assertEquals(sig_path, path) assertEquals(channel_type, sig_ct) assertEquals(cs.HT_CONTACT, sig_ht) assertEquals(handle, sig_h) assert sig_sh # suppress handler assertLength(1, new_sig.args) assertLength(1, new_sig.args[0]) # one channel assertLength(2, new_sig.args[0][0]) # two struct members assertEquals(path, new_sig.args[0][0][0]) emitted_props = new_sig.args[0][0][1] assertEquals(channel_type, emitted_props[cs.CHANNEL_TYPE]) assertEquals(cs.HT_CONTACT, emitted_props[cs.TARGET_HANDLE_TYPE]) assertEquals(handle, emitted_props[cs.TARGET_HANDLE]) assertEquals(jt.peer_bare_jid, emitted_props[cs.TARGET_ID]) assert emitted_props[cs.REQUESTED] assertEquals(self_handle, emitted_props[cs.INITIATOR_HANDLE]) assertEquals('test@localhost', emitted_props[cs.INITIATOR_ID]) # Now ensure a media channel with the same contact, and check it's the # same. call_async(q, conn.Requests, 'EnsureChannel', request) event = q.expect('dbus-return', method='EnsureChannel') yours2, path2, props2 = event.value # We should have got back the same channel we created a page or so ago. assertEquals(path2, path) # It's not been created for this call, so Yours should be False. assert not yours2 # Time passes ... afterwards we close the chan chan = wrap_channel(bus.get_object(conn.bus_name, path), 'StreamedMedia') chan.Close() # Ensure a channel that doesn't exist yet. call_async(q, conn.Requests, 'EnsureChannel', request) # Re-ensure a channel that is hopefully still pending creation. call_async(q, conn.Requests, 'EnsureChannel', request) ret, ret2, old_sig, new_sig = q.expect_many( EventPattern('dbus-return', method='EnsureChannel'), EventPattern('dbus-return', method='EnsureChannel'), EventPattern('dbus-signal', signal='NewChannel', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args), EventPattern('dbus-signal', signal='NewChannels', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args[0][0][1].values()), ) yours, path, props = ret.value # this channel was created in response to our EnsureChannel call, so it # should be ours. assert yours, ret.value sig_path, sig_ct, sig_ht, sig_h, sig_sh = old_sig.args assertEquals(sig_path, path) assertEquals(channel_type, sig_ct) assertEquals(cs.HT_CONTACT, sig_ht) assertEquals(handle, sig_h) assert sig_sh # suppress handler assertLength(1, new_sig.args) assertLength(1, new_sig.args[0]) # one channel assertLength(2, new_sig.args[0][0]) # two struct members assertEquals(path, new_sig.args[0][0][0]) emitted_props = new_sig.args[0][0][1] assertEquals(channel_type, emitted_props[cs.CHANNEL_TYPE]) assertEquals(cs.HT_CONTACT, emitted_props[cs.TARGET_HANDLE_TYPE]) assertEquals(handle, emitted_props[cs.TARGET_HANDLE]) assertEquals(jt.peer_bare_jid, emitted_props[cs.TARGET_ID]) assert emitted_props[cs.REQUESTED] assertEquals(self_handle, emitted_props[cs.INITIATOR_HANDLE]) assertEquals('test@localhost', emitted_props[cs.INITIATOR_ID]) yours2, path2, props2 = ret2.value # We should have got back the same channel we created a page or so ago. assertEquals(path2, path) # It's not been created for this call, so Yours should be False. assert not yours2 # Time passes ... afterwards we close the chan chan = wrap_channel(bus.get_object(conn.bus_name, path), 'StreamedMedia') chan.Close() # The remaining checks don't apply to calls if channel_type == cs.CHANNEL_TYPE_CALL: return # Now, create an anonymous channel with RequestChannel, add the other # person to it with RequestStreams, then Ensure a media channel with that # person. We should get the anonymous channel back. call_async( q, conn, 'RequestChannel', channel_type, 0, 0, True) ret, old_sig, new_sig = q.expect_many( EventPattern('dbus-return', method='RequestChannel'), EventPattern('dbus-signal', signal='NewChannel', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args), EventPattern('dbus-signal', signal='NewChannels', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args[0][0][1].values()), ) path = ret.value[0] assertEquals( [path, channel_type, cs.HT_NONE, 0, True], old_sig.args) assertLength(1, new_sig.args) assertLength(1, new_sig.args[0]) # one channel assertLength(2, new_sig.args[0][0]) # two struct members assertEquals(path, new_sig.args[0][0][0]) emitted_props = new_sig.args[0][0][1] assertEquals(channel_type, emitted_props[cs.CHANNEL_TYPE]) assertEquals(cs.HT_NONE, emitted_props[cs.TARGET_HANDLE_TYPE]) assertEquals(0, emitted_props[cs.TARGET_HANDLE]) assertEquals('', emitted_props[cs.TARGET_ID]) assert emitted_props[cs.REQUESTED] assertEquals(self_handle, emitted_props[cs.INITIATOR_HANDLE]) assertEquals('test@localhost', emitted_props[cs.INITIATOR_ID]) chan = wrap_channel(bus.get_object(conn.bus_name, path), 'StreamedMedia') # Request streams with the other person. This should make them the # channel's "peer" property. chan.StreamedMedia.RequestStreams(handle, [cs.MEDIA_STREAM_TYPE_AUDIO]) # Now, Ensuring a media channel with handle should yield the channel just # created. call_async(q, conn.Requests, 'EnsureChannel', request) event = q.expect('dbus-return', method='EnsureChannel') yours, path2, _ = event.value # we should have got back the anonymous channel we got with requestchannel # and called RequestStreams(handle) on. assertEquals(path2, path) # It's not been created for this call, so Yours should be False. assert not yours chan.Close() if __name__ == '__main__': exec_test(partial(test, channel_type=cs.CHANNEL_TYPE_STREAMED_MEDIA)) exec_test(partial(test, channel_type=cs.CHANNEL_TYPE_CALL)) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/call-muc.py��������������������������������������������0000664�0001750�0001750�00000031006�12332441362�024342� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test basic outgoing and incoming call handling """ import dbus from dbus.exceptions import DBusException from twisted.words.xish import xpath from gabbletest import exec_test, sync_stream from servicetest import ( EventPattern, call_async, assertEquals, assertContains, assertLength ) import constants as cs from jingletest2 import JingleTest2, test_all_dialects, JingleProtocol031 import ns from gabbletest import make_muc_presence from mucutil import * from callutils import * from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) muc = "muji@test" def run_incoming_test(q, bus, conn, stream, bob_leaves_room = False): jp = JingleProtocol031 () jt = JingleTest2(jp, conn, q, stream, 'test@localhost', muc + "/bob") jt.prepare() forbidden = [ no_muji_presences (muc) ] self_handle = conn.GetSelfHandle() _, _, test_handle, bob_handle = \ join_muc_and_check(q, bus, conn, stream, muc) presence = make_muc_presence('owner', 'moderator', muc, 'bob') muji = ('muji', ns.MUJI, {}, [('content', ns.MUJI, { "name": "Voice" }, [( 'description', ns.JINGLE_RTP, {"media": "audio"}, jt.generate_payloads(jt.audio_codecs))])]) presence.addChild(jp._simple_xml(muji)) stream.send(presence) e = q.expect ('dbus-signal', signal='NewChannels', predicate=lambda e: \ e.args[0][0][1][cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_CALL ) (path, props) = e.args[0][0] assertContains((cs.CHANNEL_TYPE_CALL + '.InitialAudio', True), props.items()) assertContains((cs.CHANNEL_TYPE_CALL + '.InitialVideo', False), props.items()) general_tests (jp, q, bus, conn, stream, path, props) channel = bus.get_object (conn.bus_name, path) props = channel.GetAll (cs.CHANNEL_TYPE_CALL, dbus_interface = dbus.PROPERTIES_IFACE) content = bus.get_object (conn.bus_name, props['Contents'][0]) check_state (q, channel, cs.CALL_STATE_PENDING_RECEIVER) md = jt.get_call_audio_md_dbus() check_and_accept_offer (q, bus, conn, self_handle, content, md) channel.Accept (dbus_interface=cs.CHANNEL_TYPE_CALL) # Preparing stanza e = q.expect('stream-presence', to = muc + "/test") echo_muc_presence (q, stream, e.stanza, 'none', 'participant') # Codecs stanza e = q.expect('stream-presence', to = muc + "/test") echo_muc_presence (q, stream, e.stanza, 'none', 'participant') # Gabble shouldn't send new presences for a while q.forbid_events(forbidden) e = q.expect ('dbus-signal', signal = 'StreamsAdded') cstream = bus.get_object (conn.bus_name, e.args[0][0]) cstream.SetCredentials(jt.ufrag, jt.pwd, dbus_interface=cs.CALL_STREAM_IFACE_MEDIA) candidates = jt.get_call_remote_transports_dbus () cstream.AddCandidates (candidates, dbus_interface=cs.CALL_STREAM_IFACE_MEDIA) e = q.expect('stream-iq', predicate=jp.action_predicate('session-initiate')) jt.parse_session_initiate (e.query) jt.accept() # Bob adds a Video content presence = make_muc_presence('owner', 'moderator', muc, 'bob') presence.addElement ((ns.MUJI, 'muji')).addElement('preparing') stream.send(presence) presence = make_muc_presence('owner', 'moderator', muc, 'bob') muji = ('muji', ns.MUJI, {}, [('content', ns.MUJI, { "name": "Voice" }, [( 'description', ns.JINGLE_RTP, {"media": "audio"}, jt.generate_payloads(jt.audio_codecs))]), ('content', ns.MUJI, { "name": "Camera" }, [( 'description', ns.JINGLE_RTP, {"media": "video"}, jt.generate_payloads(jt.video_codecs))]), ]) presence.addChild(jp._simple_xml(muji)) stream.send(presence) # Gabble noticed bob added a content e = q.expect('dbus-signal', signal = 'ContentAdded') q.unforbid_events (forbidden) content = bus.get_object (conn.bus_name, e.args[0]) check_and_accept_offer (q, bus, conn, self_handle, content, jt.get_call_video_codecs_dbus(), check_codecs_changed = False) # Gabble sends a presence to prepare e = q.expect('stream-presence', to = muc + "/test") echo_muc_presence (q, stream, e.stanza, 'none', 'participant') # Gabble sends a presence with the video codecs e = q.expect('stream-presence', to = muc + "/test") echo_muc_presence (q, stream, e.stanza, 'none', 'participant') # Gabble adds a content to the jingle session and thus a stream is added e = q.expect ('dbus-signal', signal = 'StreamsAdded') cstream = bus.get_object (conn.bus_name, e.args[0][0]) candidates = jt.get_call_remote_transports_dbus () cstream.AddCandidates (candidates, dbus_interface=cs.CALL_STREAM_IFACE_MEDIA) # And now the content-add on the jingle streams e = q.expect('stream-iq', to = muc + "/bob", predicate = lambda x: \ xpath.queryForNodes("/iq/jingle[@action='content-add']", x.stanza)) # Bob leaves the call, bye bob if bob_leaves_room: presence = make_muc_presence('owner', 'moderator', muc, 'bob') presence['type'] = 'unavailable' else: presence = make_muc_presence('owner', 'moderator', muc, 'bob') stream.send(presence) (cmembers, _, _) = q.expect_many( EventPattern ('dbus-signal', signal = 'CallMembersChanged'), # Audio and video stream EventPattern ('dbus-signal', signal = 'StreamsRemoved'), EventPattern ('dbus-signal', signal = 'StreamsRemoved')) # Just bob left assertLength (1, cmembers.args[1]) def run_outgoing_test(q, bus, conn, stream, close_channel=False): jp = JingleProtocol031 () jt = JingleTest2(jp, conn, q, stream, 'test@localhost', muc + '/bob') jt.prepare() self_handle = conn.GetSelfHandle() # Not allowed to have muji related presences before we accept the channel forbidden = [ no_muji_presences (muc) ] (path, props) = create_muji_channel (q, conn, stream, muc) q.forbid_events(forbidden) general_tests (jp, q, bus, conn, stream, path, props) channel = bus.get_object (conn.bus_name, path) props = channel.GetAll (cs.CHANNEL_TYPE_CALL, dbus_interface = dbus.PROPERTIES_IFACE) content = bus.get_object (conn.bus_name, props['Contents'][0]) md = jt.get_call_audio_md_dbus() check_and_accept_offer (q, bus, conn, content, md) # Accept the channel, which means we can get muji presences q.unforbid_events (forbidden) channel.Accept() e = q.expect('stream-presence', to = muc + "/test") echo_muc_presence (q, stream, e.stanza, 'none', 'participant') mujinode = xpath.queryForNodes("/presence/muji", e.stanza) assertLength (1, mujinode) # The one with the codecs e = q.expect('stream-presence', to = muc + "/test") echo_muc_presence (q, stream, e.stanza, 'none', 'participant') # Gabble shouldn't send new presences for a while q.forbid_events(forbidden) presence = make_muc_presence('owner', 'moderator', muc, 'bob') presence.addElement ((ns.MUJI, 'muji')).addElement('preparing') stream.send(presence) presence = make_muc_presence('owner', 'moderator', muc, 'bob') muji = ('muji', ns.MUJI, {}, [('content', ns.MUJI, { "name": "Audio" }, [( 'description', ns.JINGLE_RTP, {"media": "audio"}, jt.generate_payloads(jt.audio_codecs))])]) presence.addChild(jp._simple_xml(muji)) stream.send(presence) q.expect('dbus-signal', signal = 'CallStateChanged') # Bob appears and starts a session right afterwards q.expect('dbus-signal', signal = 'CallMembersChanged') q.unforbid_events(forbidden) e = q.expect('dbus-signal', signal = 'NewMediaDescriptionOffer') offer = bus.get_object (conn.bus_name, e.args[0]) offer.Accept(md, dbus_interface=cs.CALL_CONTENT_MEDIADESCRIPTION) jt.incoming_call(audio = "Audio") e = q.expect ('dbus-signal', signal = 'StreamsAdded') cstream = bus.get_object (conn.bus_name, e.args[0][0]) candidates = jt.get_call_remote_transports_dbus () cstream.AddCandidates (candidates, dbus_interface=cs.CALL_STREAM_IFACE_MEDIA) # Fake our endpoint being connected endpoints = cstream.Get(cs.CALL_STREAM_IFACE_MEDIA, "Endpoints", dbus_interface=dbus.PROPERTIES_IFACE) assertLength (1, endpoints) endpoint = bus.get_object (conn.bus_name, endpoints[0]) endpoint.SetEndpointState (1, cs.MEDIA_STREAM_STATE_CONNECTED, dbus_interface=cs.CALL_STREAM_ENDPOINT) endpoint.SetEndpointState (2, cs.MEDIA_STREAM_STATE_CONNECTED, dbus_interface=cs.CALL_STREAM_ENDPOINT) e = q.expect ('stream-iq', predicate = jp.action_predicate ('session-accept')) stream.send(jp.xml(jp.ResultIq(jt.peer, e.stanza, []))) # But we want video as well ! c = channel.AddContent ("Camera!", cs.MEDIA_STREAM_TYPE_VIDEO, dbus_interface=cs.CHANNEL_TYPE_CALL) q.expect('dbus-signal', signal = 'ContentAdded') content = bus.get_object (conn.bus_name, c) # wait for the CodecOffer and Accept it q.expect('dbus-signal', signal = 'NewMediaDescriptionOffer') md = jt.get_call_video_md_dbus() check_and_accept_offer (q, bus, conn, content, md) # preparing e = q.expect('stream-presence', to = muc + "/test") echo_muc_presence (q, stream, e.stanza, 'none', 'participant') #codecs e = q.expect('stream-presence', to = muc + "/test") echo_muc_presence (q, stream, e.stanza, 'none', 'participant') # Bob would like to join our video party presence = make_muc_presence('owner', 'moderator', muc, 'bob') muji = ('muji', ns.MUJI, {}, [('content', ns.MUJI, { "name": "Audio" }, [( 'description', ns.JINGLE_RTP, {"media": "audio"}, jt.generate_payloads(jt.audio_codecs))]), ('content', ns.MUJI, { "name": "Camera!" }, [( 'description', ns.JINGLE_RTP, {"media": "video"}, jt.generate_payloads(jt.video_codecs))]), ]) presence.addChild(jp._simple_xml(muji)) stream.send(presence) # new codec offer as bob threw in some codecs q.expect('dbus-signal', signal='NewMediaDescriptionOffer') check_and_accept_offer (q, bus, conn, self_handle, content, codecs, check_codecs_changed = False) # Bob sends a content node = jp.SetIq(jt.peer, jt.jid, [ jp.Jingle(jt.sid, jt.peer, 'content-add', [ jp.Content('videostream', 'initiator', 'both', jp.Description('video', [ jp.PayloadType(name, str(rate), str(id), parameters) for (name, id, rate, parameters) in jt.video_codecs ]), jp.TransportGoogleP2P()) ]) ]) stream.send(jp.xml(node)) # We get a new stream q.expect('dbus-signal', signal = 'StreamsAdded') # Sync up the stream to ensure we sent out all the xmpp traffic that was # the result of a stream being added sync_stream (q, stream) # happiness.. Now let's hang up if close_channel: channel.Close() hangup_event = EventPattern ('dbus-signal', signal = "Closed", path = path) else: channel.Hangup (0, "", "", dbus_interface=cs.CHANNEL_TYPE_CALL) hangup_event = EventPattern ('dbus-signal', signal='CallStateChanged') # Should change the call state to ended, send a session-terminate to our # only peer and send a muc presence without any mention of muji q.forbid_events(forbidden) q.expect_many (EventPattern ('stream-presence', to = muc + "/test"), EventPattern ('stream-iq', predicate=jp.action_predicate ('session-terminate')), hangup_event) if not close_channel: channel.Close() q.expect ('dbus-signal', signal="Closed", path = path) try: channel.Close() raise AssertionError ("Channel didn't actually close") except DBusException: pass def general_tests (jp, q, bus, conn, stream, path, props): assertEquals (cs.HT_ROOM, props[cs.TARGET_HANDLE_TYPE]) channel = bus.get_object (conn.bus_name, path) chan_props = channel.GetAll (cs.CHANNEL_TYPE_CALL, dbus_interface = dbus.PROPERTIES_IFACE) contents = chan_props['Contents'] assertLength(1, contents) if __name__ == '__main__': print "FIXME: needs to be ported to Call1" raise SystemExit(77) exec_test (run_outgoing_test) exec_test (lambda q,b, c, s: run_outgoing_test (q, b, c, s, True)) exec_test (run_incoming_test) exec_test (lambda q,b, c, s: run_incoming_test (q, b, c, s, True)) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/call-google-relay.py�����������������������������������0000664�0001750�0001750�00000024702�12332441362�026151� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test getting relay from Google jingleinfo """ import config if not config.GOOGLE_RELAY_ENABLED: print "NOTE: built with --disable-google-relay" raise SystemExit(77) import dbus from dbus.exceptions import DBusException from functools import partial from servicetest import call_async, EventPattern, assertEquals from jingletest2 import GtalkProtocol04 from gabbletest import (exec_test, disconnect_conn, GoogleXmlStream, make_result_iq, sync_stream) from call_helper import CallTest, run_call_test import constants as cs import ns from twisted.words.protocols.jabber.client import IQ from twisted.web import http from httptest import listen_http TOO_SLOW_CLOSE = 1 TOO_SLOW_REMOVE_SELF = 2 TOO_SLOW_DISCONNECT = 3 class CallGoogleRelayTest(CallTest): initial_audio = True initial_video = True # A real request/response looks like this: # # GET /create_session HTTP/1.1 # Connection: Keep-Alive # Content-Length: 0 # Host: relay.l.google.com # User-Agent: farsight-libjingle # X-Google-Relay-Auth: censored # X-Talk-Google-Relay-Auth: censored # # HTTP/1.1 200 OK # Content-Type: text/plain # Date: Tue, 03 Mar 2009 18:33:28 GMT # Server: MediaProxy # Cache-Control: private, x-gzip-ok="" # Transfer-Encoding: chunked # # c3 # relay.ip=74.125.47.126 # relay.udp_port=19295 # relay.tcp_port=19294 # relay.ssltcp_port=443 # stun.ip=74.125.47.126 # stun.port=19302 # username=censored # password=censored # magic_cookie=censored # # 0 response_template = """c3 relay.ip=127.0.0.1 relay.udp_port=11111 relay.tcp_port=22222 relay.ssltcp_port=443 stun.ip=1.2.3.4 stun.port=12345 username=UUUUUUUU%d password=PPPPPPPP%d magic_cookie=MMMMMMMM """ def handle_request(req, n): req.setResponseCode(http.OK) req.setHeader("Content-Type", "text/plain") req.write(self.response_template % (n, n)) req.finish() def prepare(self): events = self.q.expect_many( EventPattern('stream-iq', query_ns=ns.GOOGLE_JINGLE_INFO), EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', query_ns=ns.ROSTER), ) CallTest.prepare(self, events=events) ji_event = events[0] listen_port = listen_http(self.q, 0) jingleinfo = make_result_iq(self.stream, ji_event.stanza) stun = jingleinfo.firstChildElement().addElement('stun') server = stun.addElement('server') server['host'] = 'resolves-to-1.2.3.4' server['udp'] = '12345' self.expected_stun_server = '1.2.3.4' self.expected_stun_port = 12345 # This bit is undocumented... but it has the same format as what we get # from Google Talk servers: # <iq to="censored" from="censored" id="73930208084" type="result"> # <query xmlns="google:jingleinfo"> # <stun> # <server host="stun.l.google.com" udp="19302"/> # <server host="stun4.l.google.com" udp="19302"/> # <server host="stun3.l.google.com" udp="19302"/> # <server host="stun1.l.google.com" udp="19302"/> # <server host="stun2.l.google.com" udp="19302"/> # </stun> # <relay> # <token>censored</token> # <server host="relay.google.com" udp="19295" tcp="19294" # tcpssl="443"/> # </relay> # </query> # </iq> relay = jingleinfo.firstChildElement().addElement('relay') relay.addElement('token', content='jingle all the way') server = relay.addElement('server') server['host'] = '127.0.0.1' server['udp'] = '11111' server['tcp'] = '22222' server['tcpssl'] = '443' # The special regression-test build of Gabble parses this attribute, # because we can't listen on port 80 server['gabble-test-http-port'] = str(listen_port.getHost().port) self.stream.send(jingleinfo) jingleinfo = None # Spoof some jingle info. This is a regression test for # <https://bugs.freedesktop.org/show_bug.cgi?id=34048>. We assert that # Gabble has ignored this stuff later. iq = IQ(self.stream, 'set') iq['from'] = "evil@evil.net" query = iq.addElement((ns.GOOGLE_JINGLE_INFO, "query")) stun = query.addElement('stun') server = stun.addElement('server') server['host'] = '6.6.6.6' server['udp'] = '6666' relay = query.addElement('relay') relay.addElement('token', content='mwohahahahaha') server = relay.addElement('server') server['host'] = '127.0.0.1' server['udp'] = '666' server['tcp'] = '999' server['tcpssl'] = '666' self.stream.send(iq) # Force Gabble to process the capabilities sync_stream(self.q, self.stream) def connect(self): CallTest.connect(self) req_pattern = EventPattern('http-request', method='GET', path='/create_session') req1, req2 = self.q.expect_many(req_pattern, req_pattern) if self.params['too-slow'] is not None: test_too_slow(req1, req2, too_slow) return def pickup(self): if self.params['too-slow'] is not None: return CallTest.pickup(self) # The new API for STUN servers etc. cstream_props = self.audio_stream.GetAll( cs.CALL_STREAM_IFACE_MEDIA, dbus_interface=dbus.PROPERTIES_IFACE) assert cstream_props['Transport'] == cs.CALL_STREAM_TRANSPORT_GTALK_P2P # If Gabble has erroneously paid attention to the contact # evil@evil.net who sent us a google:jingleinfo stanza, this assertion # will fail. assertEquals([(self.expected_stun_server, self.expected_stun_port)], cstream_props['STUNServers']) credentials_used = {} credentials = {} for relay in cstream_props['RelayInfo']: assert relay['ip'] == '127.0.0.1', cstream_props['RelayInfo'] assert relay['type'] in ('udp', 'tcp', 'tls') assert relay['component'] in (1, 2) if relay['type'] == 'udp': assert relay['port'] == 11111, cstream_props['RelayInfo'] elif relay['type'] == 'tcp': assert relay['port'] == 22222, cstream_props['RelayInfo'] elif relay['type'] == 'tls': assert relay['port'] == 443, cstream_props['RelayInfo'] assert relay['username'][:8] == 'UUUUUUUU', \ cstream_props['RelayInfo'] assert relay['password'][:8] == 'PPPPPPPP', \ cstream_props['RelayInfo'] assert relay['password'][8:] == relay['username'][8:], \ cstream_props['RelayInfo'] assert (relay['password'][8:], relay['type']) \ not in credentials_used credentials_used[(relay['password'][8:], relay['type'])] = 1 credentials[(relay['component'], relay['type'])] = \ relay['password'][8:] assert (1, 'udp') in credentials assert (1, 'tcp') in credentials assert (1, 'tls') in credentials assert (2, 'udp') in credentials assert (2, 'tcp') in credentials assert (2, 'tls') in credentials assert ('0', 'udp') in credentials_used assert ('0', 'tcp') in credentials_used assert ('0', 'tls') in credentials_used assert ('1', 'udp') in credentials_used assert ('1', 'tcp') in credentials_used assert ('1', 'tls') in credentials_used # consistency check, since we currently reimplement Get separately for k in cstream_props: assert cstream_props[k] == self.audio_stream.Get( cs.CALL_STREAM_IFACE_MEDIA, k, dbus_interface=dbus.PROPERTIES_IFACE) def test_too_slow(self, req1, req2, too_slow): """ Regression test for a bug where if the channel was closed before the HTTP responses arrived, the responses finally arriving crashed Gabble. """ # User gets bored, and ends the call. e = EventPattern('dbus-signal', signal='Closed', path=chan.object_path) if too_slow == TOO_SLOW_CLOSE: call_async(self.q, self.chan, 'Close', dbus_interface=cs.CHANNEL) elif too_slow == TOO_SLOW_REMOVE_SELF: self.chan.Hangup (0, "", "", dbus_interface=cs.CHANNEL_TYPE_CALL) elif too_slow == TOO_SLOW_DISCONNECT: disconnect_conn(q, conn, stream, [e]) try: chan.GetMembers() except dbus.DBusException, e: # This should fail because the object's gone away, not because # Gabble's crashed. assert cs.UNKNOWN_METHOD == e.get_dbus_name(), \ "maybe Gabble crashed? %s" % e else: # Gabble will probably also crash in a moment, because the http # request callbacks will be called after the channel's meant to # have died, which will cause the channel to try to call # methods on the (finalized) connection. assert False, "the channel should be dead by now" return # Hangup does not cause the channel to close # except if local user hangup if too_slow != TOO_SLOW_REMOVE_SELF: q.expect_many(e) # Now Google answers! self.handle_request(req1.request, 2) self.handle_request(req2.request, 3) # Make a misc method call to check that Gabble's still alive. sync_dbus(self.bus, self.q, self.conn) def exec_relay_test(incoming, too_slow=None): exec_test(partial(run_call_test, GtalkProtocol04(), incoming=incoming, klass=CallGoogleRelayTest, params={'too-slow': too_slow}), protocol=GoogleXmlStream) if __name__ == '__main__': exec_relay_test(True) exec_relay_test(False) exec_relay_test(True, TOO_SLOW_CLOSE) exec_relay_test(False, TOO_SLOW_CLOSE) exec_relay_test(True, TOO_SLOW_REMOVE_SELF) exec_relay_test(False, TOO_SLOW_REMOVE_SELF) exec_relay_test(True, TOO_SLOW_DISCONNECT) exec_relay_test(False, TOO_SLOW_DISCONNECT) ��������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/accept-extra-stream.py���������������������������������0000664�0001750�0001750�00000020107�12332441362�026516� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test that we can accept streams added after the call has been accepted. """ from servicetest import ( make_channel_proxy, EventPattern, sync_dbus, call_async, assertEquals, ) from gabbletest import exec_test, make_result_iq, sync_stream import constants as cs from jingletest2 import JingleProtocol031, JingleTest2 from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test(q, bus, conn, stream): worker(q, bus, conn, stream, remote_jid='foo@bar.com/Foo') def test_bare_jid(q, bus, conn, stream): worker(q, bus, conn, stream, remote_jid='foo@sip.bar.com') def worker(q, bus, conn, stream, remote_jid): jp = JingleProtocol031() jt2 = JingleTest2(jp, conn, q, stream, 'test@localhost', remote_jid) jt2.prepare() self_handle = conn.GetSelfHandle() remote_handle = conn.RequestHandles(cs.HT_CONTACT, [jt2.peer])[0] # Remote end calls us node = jp.SetIq(jt2.peer, jt2.jid, [ jp.Jingle(jt2.sid, jt2.peer, 'session-initiate', [ jp.Content('audiostream', 'initiator', 'both', jp.Description('audio', [ jp.PayloadType(name, str(rate), str(id), parameters) for (name, id, rate, parameters) in jt2.audio_codecs ]), jp.TransportGoogleP2P()) ]) ]) stream.send(jp.xml(node)) nc = q.expect('dbus-signal', signal='NewChannel', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args) path, ct, ht, h, sh = nc.args assert ct == cs.CHANNEL_TYPE_STREAMED_MEDIA, ct assert ht == cs.HT_CONTACT, ht assert h == remote_handle, h group = make_channel_proxy(conn, path, 'Channel.Interface.Group') sm = make_channel_proxy(conn, path, 'Channel.Type.StreamedMedia') ms = make_channel_proxy(conn, path, 'Channel.Interface.MediaSignalling') streams = sm.ListStreams() assert len(streams) == 1, streams audio_stream_id, h, media_type, state, direction, pending = streams[0] assert h == remote_handle, (h, remote_handle) assert media_type == cs.MEDIA_STREAM_TYPE_AUDIO, media_type assert state == cs.MEDIA_STREAM_STATE_DISCONNECTED, state # FIXME: This turns out to be Bidirectional; wjt thinks this sounds wrong # since the stream is (we hope) pending local send. #assert direction == cs.MEDIA_STREAM_DIRECTION_RECEIVE, direction assert pending == cs.MEDIA_STREAM_PENDING_LOCAL_SEND, pending session_handlers = ms.GetSessionHandlers() assert len(session_handlers) == 1, session_handlers session_handler = make_channel_proxy(conn, session_handlers[0][0], 'Media.SessionHandler') session_handler.Ready() nsh = q.expect('dbus-signal', signal='NewStreamHandler') stream_handler_path, stream_id, media_type, direction = nsh.args assert stream_id == audio_stream_id, (stream_id, audio_stream_id) assert media_type == cs.MEDIA_STREAM_TYPE_AUDIO, media_type # FIXME: As above #assert direction == cs.MEDIA_STREAM_DIRECTION_RECEIVE, direction stream_handler = make_channel_proxy(conn, stream_handler_path, 'Media.StreamHandler') stream_handler.NewNativeCandidate("fake", jt2.get_remote_transports_dbus()) stream_handler.Ready(jt2.get_audio_codecs_dbus()) stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) stream_handler.SupportedCodecs(jt2.get_audio_codecs_dbus()) # peer gets the transport e = q.expect('stream-iq', predicate=jp.action_predicate('transport-info')) assertEquals(jt2.peer, e.query['initiator']) stream.send(make_result_iq(stream, e.stanza)) # Make sure all the above's happened. sync_stream(q, stream) sync_dbus(bus, q, conn) # At last, accept the call group.AddMembers([self_handle], 'accepted') # Call is accepted, we become a member, and the stream that was pending # local send is now sending. memb, acc, _, _, _, = q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=[u'', [self_handle], [], [], [], self_handle, cs.GC_REASON_NONE]), EventPattern('stream-iq', predicate=lambda e: (e.query.name == 'jingle' and e.query['action'] == 'session-accept')), EventPattern('dbus-signal', signal='SetStreamSending', args=[True]), EventPattern('dbus-signal', signal='SetStreamPlaying', args=[True]), EventPattern('dbus-signal', signal='StreamDirectionChanged', args=[audio_stream_id, cs.MEDIA_STREAM_DIRECTION_BIDIRECTIONAL, 0]), ) # Respond to session-accept # FIXME: wjt thinks Gabble should accept the content-add without this. stream.send(jp.xml(jp.ResultIq('test@localhost', acc.stanza, []))) # Foo would like to gaze upon our beautiful complexion node = jp.SetIq(jt2.peer, jt2.jid, [ jp.Jingle(jt2.sid, jt2.peer, 'content-add', [ jp.Content('videostream', 'initiator', 'both', jp.Description('video', [ jp.PayloadType(name, str(rate), str(id), parameters) for (name, id, rate, parameters) in jt2.video_codecs ]), jp.TransportGoogleP2P()) ]) ]) stream.send(jp.xml(node)) added, nsh = q.expect_many( EventPattern('dbus-signal', signal='StreamAdded'), EventPattern('dbus-signal', signal='NewStreamHandler'), ) video_stream_id, h, type = added.args assert h == remote_handle, (h, remote_handle) assert type == cs.MEDIA_STREAM_TYPE_VIDEO, type stream_handler_path, stream_id, media_type, direction = nsh.args assert stream_id == video_stream_id, (stream_id, video_stream_id) assert media_type == cs.MEDIA_STREAM_TYPE_VIDEO, type # FIXME: As above #assert direction == cs.MEDIA_STREAM_DIRECTION_RECEIVE, direction video_handler = make_channel_proxy(conn, stream_handler_path, 'Media.StreamHandler') video_handler.NewNativeCandidate("fake", jt2.get_remote_transports_dbus()) video_handler.Ready(jt2.get_video_codecs_dbus()) video_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) video_handler.SupportedCodecs(jt2.get_video_codecs_dbus()) ti, _, _, _ = q.expect_many( # Peer gets the transport EventPattern('stream-iq', predicate=jp.action_predicate('transport-info')), # Gabble tells the peer we accepted EventPattern('stream-iq', predicate=jp.action_predicate('content-accept')), EventPattern('dbus-signal', signal='SetStreamPlaying', args=[True]), # It's not entirely clear that this *needs* to fire here... EventPattern('dbus-signal', signal='SetStreamSending', args=[False]), ) assertEquals(jt2.peer, ti.query['initiator']) stream.send(make_result_iq(stream, e.stanza)) # Okay, so now the stream's playing but not sending, and we should be still # pending local send: streams = sm.ListStreams() assert len(streams) == 2, streams video_streams = [s for s in streams if s[2] == cs.MEDIA_STREAM_TYPE_VIDEO] assert len(video_streams) == 1, streams stream_id, h, _, state, direction, pending = video_streams[0] assert stream_id == video_stream_id, (stream_id, video_stream_id) assert h == remote_handle, (h, remote_handle) assert state == cs.MEDIA_STREAM_STATE_CONNECTED, state assert direction == cs.MEDIA_STREAM_DIRECTION_RECEIVE, direction assert pending == cs.MEDIA_STREAM_PENDING_LOCAL_SEND, pending # Let's accept the stream; the direction should change, and we should be # told to start sending. call_async(q, sm, 'RequestStreamDirection', video_stream_id, cs.MEDIA_STREAM_DIRECTION_BIDIRECTIONAL) # The stream's direction should change, and we should be told to start # playing. q.expect_many( EventPattern('dbus-signal', signal='StreamDirectionChanged', args=[video_stream_id, cs.MEDIA_STREAM_DIRECTION_BIDIRECTIONAL, 0]), EventPattern('dbus-signal', signal='SetStreamSending', args=[True]), ) # That'll do, pig. That'll do. if __name__ == '__main__': exec_test(test) exec_test(test_bare_jid) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/test-incoming-iceudp.py��������������������������������0000664�0001750�0001750�00000006771�12332441362�026707� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test usage of ICE-UDP in incoming calls. """ from twisted.words.xish import xpath from gabbletest import exec_test from servicetest import ( make_channel_proxy, wrap_channel, assertEquals, EventPattern, assertLength, ) import ns import constants as cs from jingletest2 import * from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def worker(jp, q, bus, conn, stream): jp.features.append(ns.JINGLE_TRANSPORT_ICEUDP) jt2 = JingleTest2(jp, conn, q, stream, 'test@localhost', 'foo@bar.com/Foo') jt2.prepare() remote_handle = conn.RequestHandles(cs.HT_CONTACT, ["foo@bar.com/Foo"])[0] # Remote end calls us node = jp.SetIq(jt2.peer, jt2.jid, [ jp.Jingle(jt2.sid, jt2.peer, 'session-initiate', [ jp.Content('stream1', 'initiator', 'both', jp.Description('audio', [ jp.PayloadType(name, str(rate), str(id), parameters) for (name, id, rate, parameters) in jt2.audio_codecs ]), jp.TransportIceUdp()) ]) ]) stream.send(jp.xml(node)) nc, e = q.expect_many( EventPattern('dbus-signal', signal='NewChannel', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args), EventPattern('dbus-signal', signal='NewSessionHandler'), ) path = nc.args[0] chan = wrap_channel(bus.get_object(conn.bus_name, path), 'StreamedMedia') hrggh = chan.ListProperties(dbus_interface=cs.TP_AWKWARD_PROPERTIES) id = [x for x, name, _, _ in hrggh if name == 'nat-traversal'][0] nrgrg = chan.GetProperties([id], dbus_interface=cs.TP_AWKWARD_PROPERTIES) _, nat_traversal = nrgrg[0] assertEquals('ice-udp', nat_traversal) session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() chan.Group.AddMembers([conn.GetSelfHandle()], 'accepted') # S-E gets notified about a newly-created stream e = q.expect('dbus-signal', signal='NewStreamHandler') stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') stream_handler.NewNativeCandidate("fake", jt2.get_remote_transports_dbus()) stream_handler.Ready(jt2.get_audio_codecs_dbus()) stream_handler.StreamState(2) # First one is transport-info e = q.expect('stream-iq', predicate=jp.action_predicate('transport-info')) transport_stanza = xpath.queryForNodes( "/iq/jingle/content/transport[@xmlns='%s']" % ns.JINGLE_TRANSPORT_ICEUDP, e.stanza)[0] # username assertEquals(transport_stanza['ufrag'], jt2.remote_transports[0][7]) # password assertEquals(transport_stanza['pwd'], jt2.remote_transports[0][8]) children = list(transport_stanza.elements()) assertLength(1, children) stream.send(jp.xml(jp.ResultIq('test@localhost', e.stanza, []))) # Set codec intersection so gabble can accept the session stream_handler.SupportedCodecs(jt2.get_audio_codecs_dbus()) # Second one is session-accept e = q.expect('stream-iq', predicate=jp.action_predicate('session-accept')) assert xpath.queryForNodes("/iq/jingle/content/transport[@xmlns='%s']" % ns.JINGLE_TRANSPORT_ICEUDP, e.stanza) stream.send(jp.xml(jp.ResultIq('test@localhost', e.stanza, []))) # Connected! Blah, blah, ... jt2.terminate() e = q.expect('dbus-signal', signal='Close') def test031(q, bus, conn, stream): return worker(JingleProtocol031(),q, bus, conn, stream) if __name__ == '__main__': exec_test(test031) �������telepathy-gabble-0.18.3/tests/twisted/jingle/incoming-gmail-modern-jingle.py������������������������0000664�0001750�0001750�00000016365�12332441362�030302� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Tests workarounds for calls with the GMail client, which supports a (currently quirky) variation on the theme of modern Jingle. """ from servicetest import EventPattern, wrap_channel, make_channel_proxy, assertEquals from gabbletest import elem, elem_iq, exec_test from jingletest2 import JingleTest2, JingleProtocol031 import ns import constants as cs from twisted.words.xish import xpath from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) class GMail(JingleTest2): remote_caps = { 'ext': 'pmuc-v1 sms-v1 camera-v1 video-v1 voice-v1', 'ver': '1.1', 'node': 'http://mail.google.com/xmpp/client/caps', } def test(q, bus, conn, stream): peer = 'foo@gmail.com/gmail.7E1F07D0' self = 'test@localhost/test' jp = JingleProtocol031() jt = GMail(jp, conn, q, stream, 'test@localhost', peer) jt.prepare(send_roster=False) sid = 'c1025763497' iq_id = 'session_init_iq' si = elem_iq(stream, 'set', from_=peer, to=self, id=iq_id)( elem(ns.JINGLE, 'jingle', action='session-initiate', sid=sid, initiator=peer)( elem('content', name='video')( elem(ns.JINGLE_RTP, 'description', media='video')( elem('payload-type', id='99', name='H264-SVC')( elem('parameter', name='width', value='320'), elem('parameter', name='height', value='200'), elem('parameter', name='framerate', value='30'), ), # ... other codecs elided ... elem('encryption'), ), elem(ns.GOOGLE_P2P, 'transport'), ), elem('content', name='audio')( elem(ns.JINGLE_RTP, 'description', media='audio')( elem('payload-type', id='103', name='ISAC', clockrate='16000')( elem('parameter', name='bitrate', value='32000'), ), # ... other codecs elided ... elem('encryption'), ), elem(ns.GOOGLE_P2P, 'transport'), ) ), elem(ns.GOOGLE_SESSION, 'session', action='initiate', sid='c1025763497', initiator=peer)( elem(ns.GOOGLE_SESSION_VIDEO, 'description')( elem('payload-type', id='99', name='H264-SVC', width='320', height='200', framerate='30'), # ... other codecs elided ... elem(ns.JINGLE_RTP, 'encryption')( elem(ns.GOOGLE_SESSION_VIDEO, 'usage'), ), elem(ns.GOOGLE_SESSION_PHONE, 'payload-type', id='103', name='ISAC', bitrate='32000', clockrate='16000'), # ... other codecs elided ... elem(ns.JINGLE_RTP, 'encryption')( elem(ns.GOOGLE_SESSION_PHONE, 'usage'), ), ), ), ) stream.send(si) ok, nc, nsh = q.expect_many( # fd.o #65131: we have to tell Google which dialect we're speaking EventPattern('stream-iq', iq_type='result', query_name='jingle', query_ns=ns.JINGLE, iq_id=iq_id), EventPattern('dbus-signal', signal='NewChannels'), EventPattern('dbus-signal', signal='NewSessionHandler'), ) path, properties = nc.args[0][0] # It's an audio+video call assert properties[cs.INITIAL_AUDIO] assert properties[cs.INITIAL_VIDEO] # Google can't add and remove streams on the fly. We special-case GMail. assert properties[cs.IMMUTABLE_STREAMS] chan = wrap_channel(bus.get_object(conn.bus_name, path), 'StreamedMedia') session_handler = make_channel_proxy(conn, nsh.args[0], 'Media.SessionHandler') session_handler.Ready() path, _, _, _ = q.expect('dbus-signal', signal='NewStreamHandler').args stream1 = make_channel_proxy(conn, path, 'Media.StreamHandler') path, _, _, _ = q.expect('dbus-signal', signal='NewStreamHandler').args stream2 = make_channel_proxy(conn, path, 'Media.StreamHandler') stream1.Ready([]) stream2.Ready([]) # Audio rtcp stream.send( elem_iq(stream, from_=peer, to=self, type='set')( elem(ns.JINGLE, 'jingle', action='transport-info', sid=sid)( elem('content', name='audio')( elem(ns.GOOGLE_P2P, 'transport')( elem('candidate', address='172.22.64.192', port='54335', name='rtcp', username='+wJqkmRVYotCz+Rd', password='POWPzg5Pks4+ywAz', preference='1', protocol='udp', generation='0', network='1', type='local') ) ) ) ) ) q.expect('dbus-signal', signal='AddRemoteCandidate', path=stream1.object_path) # audio rtp stream.send( elem_iq(stream, from_=peer, to=self, type='set')( elem(ns.JINGLE, 'jingle', action='transport-info', sid=sid)( elem('content', name='audio')( elem(ns.GOOGLE_P2P, 'transport')( elem('candidate', address='172.22.64.192', port='54337', name='rtp', username='F7rgdWcCgH3Q/HgE', password='ioh2IDwd3iZEZHzM', preference='1', protocol='udp', generation='0', network='1', type='local') ) ) ) ) ) q.expect('dbus-signal', signal='AddRemoteCandidate', path=stream1.object_path) # video rtcp: note the weird name='' field which Gabble has to work around stream.send( elem_iq(stream, from_=peer, to=self, type='set')( elem(ns.JINGLE, 'jingle', action='transport-info', sid=sid)( elem('content', name='video')( elem(ns.GOOGLE_P2P, 'transport')( elem('candidate', address='172.22.64.192', port='54339', name='video_rtcp', username='fnLduEIu6VHsSOqh', password='IYeNu/HWzMpx2zrS', preference='1', protocol='udp', generation='0', network='1', type='local') ) ) ) ) ) q.expect('dbus-signal', signal='AddRemoteCandidate', path=stream2.object_path) # video rtp: ditto stream.send( elem_iq(stream, from_=peer, to=self, type='set')( elem(ns.JINGLE, 'jingle', action='transport-info', sid=sid)( elem('content', name='video')( elem(ns.GOOGLE_P2P, 'transport')( elem('candidate', address='172.22.64.192', port='54341', name='video_rtp', username='mZVBFdQ2LyAP6oyE', password='3uoyCHP8zwE+/Ylw', preference='1', protocol='udp', generation='0', network='1', type='local') ) ) ) ) ) q.expect('dbus-signal', signal='AddRemoteCandidate', path=stream2.object_path) # Test that we're sending with name='video_rtp' as well, but only for the video stream. stream1.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) e = q.expect('stream-iq', predicate=jp.action_predicate('transport-info')) candidate = xpath.queryForNodes( '/iq/jingle/content[@name="audio"]/transport/candidate', e.stanza)[0] assertEquals('rtp', candidate['name']) stream2.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) e = q.expect('stream-iq', predicate=jp.action_predicate('transport-info')) candidate = xpath.queryForNodes( '/iq/jingle/content[@name="video"]/transport/candidate', e.stanza)[0] assertEquals('video_rtp', candidate['name']) if __name__ == '__main__': exec_test(test) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/incoming-basics.py�������������������������������������0000664�0001750�0001750�00000017172�12332441362�025722� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test incoming call handling. """ import dbus from gabbletest import make_result_iq from servicetest import ( make_channel_proxy, unwrap, EventPattern, assertEquals, assertLength) from jingletest2 import JingleTest2, test_all_dialects import constants as cs from twisted.words.xish import xpath from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test(jp, q, bus, conn, stream, peer='foo@bar.com/Foo'): jt = JingleTest2(jp, conn, q, stream, 'test@localhost', peer) jt.prepare() self_handle = conn.GetSelfHandle() remote_handle = conn.RequestHandles(cs.HT_CONTACT, [jt.peer])[0] # Remote end calls us jt.incoming_call() # If this is a Jingle dialect that supports it, Gabble should send a # <ringing/> notification when it gets the session-initiate until Telepathy # has a way for the UI to do this. # https://bugs.freedesktop.org/show_bug.cgi?id=21964 ringing_event = jp.rtp_info_event_list("ringing") if jp.dialect == 'gtalk-v0.4': # With gtalk4, apparently we have to send transport-accept immediately, # not even just before we send our transport-info. wjt tested this, and # indeed if we don't send this for incoming calls, the call never # connects. ta_event = [ EventPattern('stream-iq', predicate=lambda x: xpath.queryForNodes("/iq/session[@type='transport-accept']", x.stanza)), ] else: ta_event = [] nc, e = q.expect_many( EventPattern('dbus-signal', signal='NewChannel', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args), EventPattern('dbus-signal', signal='NewSessionHandler'), *(ringing_event + ta_event) )[0:2] path, ct, ht, h, _ = nc.args assert ct == cs.CHANNEL_TYPE_STREAMED_MEDIA, ct assert ht == cs.HT_CONTACT, ht assert h == remote_handle, h media_chan = make_channel_proxy(conn, path, 'Channel.Interface.Group') media_iface = make_channel_proxy(conn, path, 'Channel.Type.StreamedMedia') # S-E was notified about new session handler, and calls Ready on it assert e.args[1] == 'rtp' session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() nsh_event = q.expect('dbus-signal', signal='NewStreamHandler') # S-E gets notified about a newly-created stream stream_handler = make_channel_proxy(conn, nsh_event.args[0], 'Media.StreamHandler') streams = media_iface.ListStreams() assertLength(1, streams) stream_id, stream_handle, stream_type, _, stream_direction, pending_flags =\ streams[0] assertEquals(remote_handle, stream_handle) assertEquals(cs.MEDIA_STREAM_TYPE_AUDIO, stream_type) assertEquals(cs.MEDIA_STREAM_DIRECTION_RECEIVE, stream_direction) assertEquals(cs.MEDIA_STREAM_PENDING_LOCAL_SEND, pending_flags) # Exercise channel properties channel_props = media_chan.GetAll( cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(remote_handle, channel_props['TargetHandle']) assertEquals(cs.HT_CONTACT, channel_props['TargetHandleType']) assertEquals((cs.HT_CONTACT, remote_handle), media_chan.GetHandle(dbus_interface=cs.CHANNEL)) assertEquals(jt.peer_bare_jid, channel_props['TargetID']) assertEquals(jt.peer_bare_jid, channel_props['InitiatorID']) assertEquals(remote_handle, channel_props['InitiatorHandle']) assertEquals(False, channel_props['Requested']) group_props = media_chan.GetAll( cs.CHANNEL_IFACE_GROUP, dbus_interface=dbus.PROPERTIES_IFACE) assert group_props['SelfHandle'] == self_handle, \ (group_props['SelfHandle'], self_handle) flags = group_props['GroupFlags'] assert flags & cs.GF_PROPERTIES, flags # Changing members in any way other than adding or removing yourself is # meaningless for incoming calls, and the flags need not be sent to change # your own membership. assert not flags & cs.GF_CAN_ADD, flags assert not flags & cs.GF_CAN_REMOVE, flags assert not flags & cs.GF_CAN_RESCIND, flags assert group_props['Members'] == [remote_handle], group_props['Members'] assert group_props['RemotePendingMembers'] == [], \ group_props['RemotePendingMembers'] # We're local pending because remote_handle invited us. assert group_props['LocalPendingMembers'] == \ [(self_handle, remote_handle, cs.GC_REASON_INVITED, '')], \ unwrap(group_props['LocalPendingMembers']) streams = media_chan.ListStreams( dbus_interface=cs.CHANNEL_TYPE_STREAMED_MEDIA) assert len(streams) == 1, streams assert len(streams[0]) == 6, streams[0] # streams[0][0] is the stream identifier, which in principle we can't # make any assertion about (although in practice it's probably 1) assert streams[0][1] == remote_handle, (streams[0], remote_handle) assert streams[0][2] == cs.MEDIA_STREAM_TYPE_AUDIO, streams[0] # We haven't connected yet assert streams[0][3] == cs.MEDIA_STREAM_STATE_DISCONNECTED, streams[0] # In Gabble, incoming streams start off with remote send enabled, and # local send requested assert streams[0][4] == cs.MEDIA_STREAM_DIRECTION_RECEIVE, streams[0] assert streams[0][5] == cs.MEDIA_STREAM_PENDING_LOCAL_SEND, streams[0] # Connectivity checks happen before we have accepted the call stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) stream_handler.Ready(jt.get_audio_codecs_dbus()) stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) stream_handler.SupportedCodecs(jt.get_audio_codecs_dbus()) # peer gets the transport e = q.expect('stream-iq', predicate=jp.action_predicate('transport-info')) assertEquals(jt.peer, e.query['initiator']) if jp.dialect in ['jingle-v0.15', 'jingle-v0.31']: content = xpath.queryForNodes('/iq/jingle/content', e.stanza)[0] assertEquals('initiator', content['creator']) stream.send(make_result_iq(stream, e.stanza)) # At last, accept the call media_chan.AddMembers([self_handle], 'accepted') # Call is accepted, we become a member, and the stream that was pending # local send is now sending. memb, acc, _, _, _ = q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=[u'', [self_handle], [], [], [], self_handle, cs.GC_REASON_NONE]), EventPattern('stream-iq', predicate=jp.action_predicate('session-accept')), EventPattern('dbus-signal', signal='SetStreamSending', args=[True]), EventPattern('dbus-signal', signal='SetStreamPlaying', args=[True]), EventPattern('dbus-signal', signal='StreamDirectionChanged', args=[stream_id, cs.MEDIA_STREAM_DIRECTION_BIDIRECTIONAL, 0]), ) stream.send(make_result_iq(stream, acc.stanza)) # Also, if this is a Jingle dialect that supports it, Gabble should send an # <active/> notification when the session-accept is acked (until the # Telepathy spec lets the UI say it's not ringing any more). active_event = jp.rtp_info_event("active") if active_event is not None: q.expect_many(active_event) # we are now both in members members = media_chan.GetMembers() assert set(members) == set([self_handle, remote_handle]), members # Connected! Blah, blah, ... # 'Nuff said jt.terminate() q.expect('dbus-signal', signal='Closed', path=path) if __name__ == '__main__': test_all_dialects(test) test_all_dialects(lambda jp, q, bus, conn, stream: test(jp, q, bus, conn, stream, 'foo@sip.bar.com')) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/test-incoming-call-reject.py���������������������������0000664�0001750�0001750�00000007423�12332441362�027616� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test incoming call handling - reject a call because we're busy, and for no reason. """ from twisted.words.xish import xpath from servicetest import make_channel_proxy, EventPattern, call_async from jingletest2 import JingleTest2, test_all_dialects import constants as cs from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test_busy(jp, q, bus, conn, stream): test(jp, q, bus, conn, stream, True) def test_no_reason(jp, q, bus, conn, stream): test(jp, q, bus, conn, stream, False) def test(jp, q, bus, conn, stream, busy): remote_jid = 'foo@bar.com/Foo' jt = JingleTest2(jp, conn, q, stream, 'test@localhost', remote_jid) jt.prepare() self_handle = conn.GetSelfHandle() remote_handle = conn.RequestHandles(cs.HT_CONTACT, [remote_jid])[0] # Remote end calls us jt.incoming_call() # FIXME: these signals are not observable by real clients, since they # happen before NewChannels. # The caller is in members e = q.expect('dbus-signal', signal='MembersChanged', args=[u'', [remote_handle], [], [], [], 0, 0]) # We're pending because of remote_handle e = q.expect('dbus-signal', signal='MembersChanged', args=[u'', [], [], [self_handle], [], remote_handle, cs.GC_REASON_INVITED]) # S-E gets notified about new session handler, and calls Ready on it e = q.expect('dbus-signal', signal='NewSessionHandler') assert e.args[1] == 'rtp' session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() media_chan = make_channel_proxy(conn, e.path, 'Channel.Interface.Group') # Exercise channel properties channel_props = media_chan.GetAll(cs.CHANNEL, dbus_interface=cs.PROPERTIES_IFACE) assert channel_props['TargetHandle'] == remote_handle assert channel_props['TargetHandleType'] == 1 assert channel_props['TargetID'] == 'foo@bar.com' assert channel_props['Requested'] == False assert channel_props['InitiatorID'] == 'foo@bar.com' assert channel_props['InitiatorHandle'] == remote_handle if busy: # First, try using a reason that doesn't make any sense call_async(q, media_chan, 'RemoveMembersWithReason', [self_handle], "what kind of a reason is Separated?!", cs.GC_REASON_SEPARATED) e = q.expect('dbus-error', method='RemoveMembersWithReason') assert e.error.get_dbus_name() == cs.INVALID_ARGUMENT # Now try a more sensible reason. media_chan.RemoveMembersWithReason([self_handle], "which part of 'Do Not Disturb' don't you understand?", cs.GC_REASON_BUSY) else: media_chan.RemoveMembers([self_handle], 'rejected') iq, mc, _ = q.expect_many( EventPattern('stream-iq', predicate=jp.action_predicate('session-terminate')), EventPattern('dbus-signal', signal='MembersChanged'), EventPattern('dbus-signal', signal='Closed'), ) _, added, removed, lp, rp, actor, reason = mc.args assert added == [], added assert set(removed) == set([self_handle, remote_handle]), \ (removed, self_handle, remote_handle) assert lp == [], lp assert rp == [], rp assert actor == self_handle, (actor, self_handle) if busy: assert reason == cs.GC_REASON_BUSY, reason else: assert reason == cs.GC_REASON_NONE, reason if jp.is_modern_jingle(): jingle = iq.query if busy: r = "/jingle/reason/busy" else: r = "/jingle/reason/cancel" assert xpath.queryForNodes(r, jingle) is not None, (jingle.toXml(), r) if __name__ == '__main__': test_all_dialects(test_busy) test_all_dialects(test_no_reason) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/call-muc-re-re-request.py������������������������������0000664�0001750�0001750�00000003223�12332440117�027035� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test basic outgoing and incoming call handling """ from gabbletest import exec_test from servicetest import call_async, assertEquals, assertNotEquals from jingletest2 import JingleProtocol031 import constants as cs from callutils import * from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) muc = "muji@test" def run_cancel_test(q, bus, conn, stream): jp = JingleProtocol031 () jt = JingleTest2(jp, conn, q, stream, 'test@localhost', muc + '/bob') jt.prepare() for x in xrange (0, 10): (path, props) = create_muji_channel (q, conn, stream, muc, x > 0) channel = bus.get_object (conn.bus_name, path) contents = channel.Get (cs.CHANNEL_TYPE_CALL, "Contents", dbus_interface = dbus.PROPERTIES_IFACE) content = bus.get_object (conn.bus_name, contents[0]) md = jt.get_call_audio_md_dbus() check_and_accept_offer (q, bus, conn, content, md) # Accept the channel channel.Accept() def preparing(e): node = xpath.queryForNodes("/presence/muji/preparing", e.stanza) return node is not None q.expect('stream-presence', to = muc + "/test", predicate=preparing) channel.Hangup(0, "", "", dbus_interface=cs.CHANNEL_TYPE_CALL) def notpreparing(e): node = xpath.queryForNodes("/presence/muji/preparing", e.stanza) return node is None q.expect('stream-presence', to = muc + "/test", predicate=notpreparing) if x % 2 == 0: channel.Close() if __name__ == '__main__': exec_test (run_cancel_test) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/hold-av.py���������������������������������������������0000664�0001750�0001750�00000042026�12332441362�024203� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test the Hold API. """ from gabbletest import make_result_iq, sync_stream from servicetest import ( assertEquals, wrap_channel, make_channel_proxy, call_async, EventPattern, sync_dbus) import constants as cs from jingletest2 import JingleTest2, test_all_dialects from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def mutable_stream_tests(jp, jt, q, bus, conn, stream, chan, handle): # ---- Test 13: while the call's on hold, we add a new stream --- # We shouldn't go off hold locally as a result, and the new StreamHandler # should tell s-e to hold the stream. pending_hold = [ EventPattern('dbus-signal', signal='HoldStateChanged', predicate=lambda e: e.args[0] == cs.HS_PENDING_HOLD), ] q.forbid_events(pending_hold) call_async(q, chan.StreamedMedia, 'RequestStreams', handle, [cs.MEDIA_STREAM_TYPE_AUDIO]) e = q.expect('dbus-signal', signal='NewStreamHandler') audio_stream_path = e.args[0] audio_stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') # Syncing here to make sure SetStreamHeld happens after Ready... sync_dbus(bus, q, conn) audio_stream_handler.Ready(jt.get_audio_codecs_dbus()) audio_stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) audio_stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) q.expect_many( EventPattern('dbus-signal', signal='SetStreamHeld', args=[True], path=audio_stream_path), EventPattern('dbus-signal', signal='SetStreamSending', args=[False], path=audio_stream_path), ) assertEquals(cs.HS_HELD, chan.Hold.GetHoldState()[0]) sync_dbus(bus, q, conn) # ---- Test 14: while the call's on hold, the peer adds a new stream ---- # Again, we shouldn't go off hold locally as a result, and the new # StreamHandler should tell s-e to hold the stream. node = jp.SetIq(jt.peer, jt.jid, [ jp.Jingle(jt.sid, jt.peer, 'content-add', [ jp.Content('videostream', 'initiator', 'both', jp.Description('video', [ jp.PayloadType(name, str(rate), str(id), parameters) for (name, id, rate, parameters) in jt.video_codecs ]), jp.TransportGoogleP2P()) ]) ]) stream.send(jp.xml(node)) e = q.expect('dbus-signal', signal='NewStreamHandler') video_stream_path = e.args[0] video_stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') # Syncing here to make sure SetStreamHeld happens after Ready... sync_dbus(bus, q, conn) video_stream_handler.Ready(jt.get_video_codecs_dbus()) video_stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) video_stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) q.expect_many( EventPattern('dbus-signal', signal='SetStreamHeld', args=[True], path=video_stream_path), EventPattern('dbus-signal', signal='SetStreamSending', args=[False], path=video_stream_path), ) assertEquals(cs.HS_HELD, chan.Hold.GetHoldState()[0]) sync_dbus(bus, q, conn) q.unforbid_events(pending_hold) def test(jp, q, bus, conn, stream): # These are 0- (for old dialects) or 1- (for new dialects) element lists # that can be splatted into expect_many with * hold_event = jp.rtp_info_event_list("hold") unhold_event = jp.rtp_info_event_list("unhold") # Let's forbid them until we're ready to start holding, to check that # Gabble doesn't send spurious notifications. q.forbid_events(hold_event) q.forbid_events(unhold_event) jt = JingleTest2(jp, conn, q, stream, 'test@localhost', 'foo@bar.com/Foo') jt.prepare() self_handle = conn.GetSelfHandle() handle = conn.RequestHandles(cs.HT_CONTACT, [jt.peer])[0] path = conn.RequestChannel(cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.HT_CONTACT, handle, True) chan = wrap_channel(bus.get_object(conn.bus_name, path), 'StreamedMedia', ['Hold']) call_async(q, chan.StreamedMedia, 'RequestStreams', handle, [cs.MEDIA_STREAM_TYPE_AUDIO, cs.MEDIA_STREAM_TYPE_VIDEO]) if not jp.can_do_video(): # Video on GTalk? Not so much. e = q.expect('dbus-error', method='RequestStreams') # The spec and implemention say this should be NotAvailable, but wjt # thinks it should be NotCapable. The spec bug is #20920. name = e.error.get_dbus_name() #assert name == cs.NOT_CAPABLE, name return # S-E gets notified about new session handler, and calls Ready on it e = q.expect('dbus-signal', signal='NewSessionHandler') assert e.args[1] == 'rtp' session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() e = q.expect('dbus-signal', signal='NewStreamHandler') # FIXME: we assume this one's the audio stream, just because we requested # that first audio_stream_path = e.args[0] audio_stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') audio_stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) audio_stream_handler.Ready(jt.get_audio_codecs_dbus()) audio_stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) e = q.expect('dbus-signal', signal='NewStreamHandler') video_stream_path = e.args[0] video_stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') video_stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) video_stream_handler.Ready(jt.get_video_codecs_dbus()) video_stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) e = q.expect('stream-iq', predicate=jp.action_predicate('session-initiate')) stream.send(make_result_iq(stream, e.stanza)) jt.parse_session_initiate(e.query) jt.accept() q.expect('stream-iq', iq_type='result') # ---- Test 1: GetHoldState returns unheld and unhold is a no-op ---- hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_UNHELD, hold_state chan.Hold.RequestHold(False) # We're about to start holding, so remove the ban on <hold/>. sync_stream(q, stream) q.unforbid_events(hold_event) # ---- Test 2: successful hold ---- call_async(q, chan.Hold, 'RequestHold', True) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[True]), EventPattern('dbus-return', method='RequestHold', value=()), *hold_event ) call_async(q, audio_stream_handler, 'HoldState', True) call_async(q, video_stream_handler, 'HoldState', True) q.expect_many( EventPattern('dbus-return', method='HoldState', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]), ) # ---- Test 3: GetHoldState returns held and hold is a no-op ---- q.forbid_events(hold_event) hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_HELD, hold_state chan.Hold.RequestHold(True) sync_stream(q, stream) q.unforbid_events(hold_event) # ---- Test 4: successful unhold ---- call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[False]), EventPattern('dbus-return', method='RequestHold', value=()), ) sync_stream(q, stream) q.unforbid_events(unhold_event) call_async(q, audio_stream_handler, 'HoldState', False) call_async(q, video_stream_handler, 'HoldState', False) q.expect_many( EventPattern('dbus-return', method='HoldState', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_UNHELD, cs.HSR_REQUESTED]), *unhold_event ) # ---- Test 5: GetHoldState returns False and unhold is a no-op ---- hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_UNHELD, hold_state chan.Hold.RequestHold(False) # ---- Test 6: 3 parallel calls to hold ---- hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_UNHELD, hold_state call_async(q, chan.Hold, 'RequestHold', True) call_async(q, chan.Hold, 'RequestHold', True) call_async(q, chan.Hold, 'RequestHold', True) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[True]), EventPattern('dbus-return', method='RequestHold', value=()), *hold_event ) call_async(q, audio_stream_handler, 'HoldState', True) call_async(q, video_stream_handler, 'HoldState', True) q.expect_many( EventPattern('dbus-return', method='HoldState', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]), ) # ---- Test 7: 3 parallel calls to unhold ---- q.forbid_events(unhold_event) call_async(q, chan.Hold, 'RequestHold', False) call_async(q, chan.Hold, 'RequestHold', False) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[False]), EventPattern('dbus-return', method='RequestHold', value=()), ) sync_stream(q, stream) q.unforbid_events(unhold_event) call_async(q, audio_stream_handler, 'HoldState', False) call_async(q, video_stream_handler, 'HoldState', False) q.expect_many( EventPattern('dbus-return', method='HoldState', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_UNHELD, cs.HSR_REQUESTED]), *unhold_event ) # ---- Test 8: hold, then change our minds before s-e has responded ---- hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_UNHELD, hold_state call_async(q, chan.Hold, 'RequestHold', True) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[True]), *hold_event ) # Gabble can't send <unhold/> until s-e confirms it has the resources q.forbid_events(unhold_event) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[False]), ) call_async(q, audio_stream_handler, 'HoldState', True) call_async(q, video_stream_handler, 'HoldState', True) call_async(q, audio_stream_handler, 'HoldState', False) sync_stream(q, stream) q.unforbid_events(unhold_event) call_async(q, video_stream_handler, 'HoldState', False) q.expect_many( EventPattern('dbus-return', method='HoldState', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_UNHELD, cs.HSR_REQUESTED]), *unhold_event ) hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_UNHELD, hold_state # ---- Test 9: unhold, then change our minds before s-e has responded ---- # Go to state "held" first call_async(q, chan.Hold, 'RequestHold', True) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[True]), EventPattern('dbus-return', method='RequestHold', value=()), *hold_event ) call_async(q, audio_stream_handler, 'HoldState', True) call_async(q, video_stream_handler, 'HoldState', True) q.expect_many( EventPattern('dbus-return', method='HoldState', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]), ) # Actually do test 9 q.forbid_events(hold_event + unhold_event) hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_HELD, hold_state call_async(q, chan.Hold, 'RequestHold', False) call_async(q, chan.Hold, 'RequestHold', True) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[False]), ) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[True]), ) call_async(q, audio_stream_handler, 'HoldState', False) call_async(q, video_stream_handler, 'HoldState', False) call_async(q, audio_stream_handler, 'HoldState', True) call_async(q, video_stream_handler, 'HoldState', True) q.expect_many( EventPattern('dbus-return', method='HoldState', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]), ) sync_stream(q, stream) q.unforbid_events(hold_event + unhold_event) hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_HELD, hold_state # ---- Test 10: attempting to unhold fails (both streams) ---- q.forbid_events(hold_event + unhold_event) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[False]), EventPattern('dbus-return', method='RequestHold', value=()), ) call_async(q, audio_stream_handler, 'UnholdFailure') call_async(q, video_stream_handler, 'UnholdFailure') q.expect_many( EventPattern('dbus-return', method='UnholdFailure', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_RESOURCE_NOT_AVAILABLE]), ) sync_stream(q, stream) q.unforbid_events(hold_event + unhold_event) # ---- Test 11: attempting to unhold fails (first stream) ---- q.forbid_events(hold_event + unhold_event) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[False]), EventPattern('dbus-return', method='RequestHold', value=()), ) call_async(q, audio_stream_handler, 'UnholdFailure') q.expect_many( EventPattern('dbus-return', method='UnholdFailure', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_RESOURCE_NOT_AVAILABLE]), ) sync_stream(q, stream) q.unforbid_events(hold_event + unhold_event) # ---- Test 12: attempting to unhold partially fails, so roll back ---- q.forbid_events(hold_event + unhold_event) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[False]), EventPattern('dbus-return', method='RequestHold', value=()), ) call_async(q, audio_stream_handler, 'HoldState', False) q.expect('dbus-return', method='HoldState', value=()) call_async(q, video_stream_handler, 'UnholdFailure') q.expect_many( EventPattern('dbus-signal', signal='SetStreamHeld', args=[True]), EventPattern('dbus-return', method='UnholdFailure', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_RESOURCE_NOT_AVAILABLE]), ) call_async(q, audio_stream_handler, 'HoldState', True) q.expect_many( EventPattern('dbus-return', method='HoldState', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_RESOURCE_NOT_AVAILABLE]), ) sync_stream(q, stream) q.unforbid_events(hold_event + unhold_event) if jp.has_mutable_streams(): mutable_stream_tests(jp, jt, q, bus, conn, stream, chan, handle) # ---- The end ---- chan.Group.RemoveMembers([self_handle], 'closed') # Test completed, close the connection e = q.expect('dbus-signal', signal='Close') #XXX - match against the path if __name__ == '__main__': test_all_dialects(test) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/call-content-adding-removal.py�������������������������0000664�0001750�0001750�00000013574�12225363340�030131� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test content adding and removal during the session. We start session with only one stream, then add one more, then remove the first one and lastly remove the second stream, which closes the session. """ from functools import partial from servicetest import call_async, assertEquals, assertLength, EventPattern from gabbletest import make_result_iq, sync_stream from jingletest2 import test_dialects, JingleProtocol015, JingleProtocol031 from call_helper import CallTest, run_call_test import constants as cs import dbus from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) class CallContentAddingRemovalTest(CallTest): # A/V initial_audio = True initial_video = True def pickup(self): peer_removes_final_content = self.params['peer-removes-final-content'] # Remove video content before remote pick the call self.video_content.Remove() e = self.q.expect('dbus-signal', signal='ContentRemoved') assertEquals(e.args[1][0], self.self_handle) assertEquals(e.args[1][1], cs.CALL_STATE_CHANGE_REASON_USER_REQUESTED) assertEquals(e.args[1][2], '') self.initial_video = False self.video_content = None self.video_content_name = None self.video_stream = None # ...but before the peer notices, they accept the call. CallTest.pickup(self) # Gabble sends content-remove for the video stream... e = self.q.expect('stream-iq', predicate=self.jp.action_predicate('content-remove')) # Only now the remote end removes the video stream; if gabble mistakenly # marked it as accepted on session acceptance, it'll crash right about # now. If it's good, stream will be really removed, and # we can proceed. self.stream.send(make_result_iq(self.stream, e.stanza)) # Actually, we *do* want video! content_path = self.chan.AddContent( "video1", cs.CALL_MEDIA_TYPE_VIDEO, cs.MEDIA_STREAM_DIRECTION_BIDIRECTIONAL, dbus_interface=cs.CHANNEL_TYPE_CALL); self.q.expect('dbus-signal', signal='ContentAdded') self.store_content(content_path, initial=False, incoming=False) md = self.jt2.get_call_video_md_dbus() self.check_and_accept_offer(self.video_content, md) candidates = self.jt2.get_call_remote_transports_dbus() self.video_stream.AddCandidates(candidates, dbus_interface=cs.CALL_STREAM_IFACE_MEDIA) e = self.q.expect('stream-iq', predicate=self.jp.action_predicate('content-add')) c = e.query.firstChildElement() assertEquals('initiator', c['creator']) endpoints = self.video_stream.Get(cs.CALL_STREAM_IFACE_MEDIA, "Endpoints", dbus_interface=dbus.PROPERTIES_IFACE) assertLength(1, endpoints) endpoint = self.bus.get_object(self.conn.bus_name, endpoints[0]) self.enable_endpoint(endpoint) # Now, the call draws to a close. # We first remove the original stream self.audio_content.Remove() self.initial_audio = False self.audio_content = None self.audio_content_name = None self.audio_stream = None e = self.q.expect('stream-iq', predicate=self.jp.action_predicate('content-remove')) content_remove_ack = make_result_iq(self.stream, e.stanza) if peer_removes_final_content: # The peer removes the final countdo content. From a footnote (!) in # XEP 0166: # If the content-remove results in zero content definitions for the # session, the entity that receives the content-remove SHOULD send # a session-terminate action to the other party (since a session # with no content definitions is void). # So, Gabble should respond to the content-remove with a # session-terminate. node = self.jp.SetIq(self.jt2.peer, self.jt2.jid, [ self.jp.Jingle(self.jt2.sid, self.jt2.peer, 'content-remove', [ self.jp.Content(c['name'], c['creator'], c['senders']) ]) ]) self.stream.send(self.jp.xml(node)) else: # The Telepathy client removes the second stream; Gabble should # terminate the session rather than sending a content-remove. self.video_content.Remove() self.initial_video = False self.video_content = None self.video_content_name = None self.video_stream = None st, ended = self.q.expect_many( EventPattern('stream-iq', predicate=self.jp.action_predicate('session-terminate')), # Gabble shouldn't wait for the peer to ack the terminate before # considering the call finished. EventPattern('dbus-signal', signal='CallStateChanged')) assertEquals(ended.args[0], cs.CALL_STATE_ENDED) # Only now does the peer ack the content-remove. This serves as a # regression test for contents outliving the session; if the content did # did't die properly, this crashed Gabble. self.stream.send(content_remove_ack) sync_stream(self.q, self.stream) # The peer can ack the terminate too, just for completeness. self.stream.send(make_result_iq(self.stream, st.stanza)) def hangup(self): pass if __name__ == '__main__': dialects = [JingleProtocol015, JingleProtocol031] test_dialects( partial(run_call_test, klass=CallContentAddingRemovalTest, incoming=False, params={'peer-removes-final-content': True}), dialects) test_dialects( partial(run_call_test, klass=CallContentAddingRemovalTest, incoming=False, params={'peer-removes-final-content': False}), dialects) ������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/outgoing-many-streams.py�������������������������������0000664�0001750�0001750�00000020726�12332441362�027125� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test making outgoing call using CreateChannel. This tests the happy scenario when the remote party accepts the call. """ import dbus from gabbletest import exec_test, sync_stream from servicetest import ( make_channel_proxy, call_async, EventPattern) import jingletest2 import gabbletest import constants as cs from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test(q, bus, conn, stream): worker(q, bus, conn, stream, 'foo@bar.com/Foo') worker(q, bus, conn, stream, 'foo@sip.bar.com') def worker(q, bus, conn, stream, peer): jp = jingletest2.JingleProtocol031() jt = jingletest2.JingleTest2(jp, conn, q, stream, 'test@localhost', peer) self_handle = conn.GetSelfHandle() jt.send_presence_and_caps() handle = conn.RequestHandles(cs.HT_CONTACT, [jt.peer])[0] call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: handle, }) ret, old_sig, new_sig = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('dbus-signal', signal='NewChannel', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args), EventPattern('dbus-signal', signal='NewChannels', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args[0][0][1].values()), ) path = ret.value[0] sig_path, sig_ct, sig_ht, sig_h, sig_sh = old_sig.args assert sig_path == path, (sig_path, path) assert sig_ct == cs.CHANNEL_TYPE_STREAMED_MEDIA, sig_ct assert sig_ht == cs.HT_CONTACT, sig_ht assert sig_h == handle, sig_h assert sig_sh == True # suppress handler assert len(new_sig.args) == 1 assert len(new_sig.args[0]) == 1 # one channel assert len(new_sig.args[0][0]) == 2 # two struct members assert new_sig.args[0][0][0] == path emitted_props = new_sig.args[0][0][1] assert emitted_props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAMED_MEDIA assert emitted_props[cs.TARGET_HANDLE_TYPE] == cs.HT_CONTACT assert emitted_props[cs.TARGET_HANDLE] == handle assert emitted_props[cs.TARGET_ID] == jt.peer_bare_jid, emitted_props assert emitted_props[cs.REQUESTED] == True assert emitted_props[cs.INITIATOR_HANDLE] == self_handle assert emitted_props[cs.INITIATOR_ID] == 'test@localhost' signalling_iface = make_channel_proxy(conn, path, 'Channel.Interface.MediaSignalling') media_iface = make_channel_proxy(conn, path, 'Channel.Type.StreamedMedia') group_iface = make_channel_proxy(conn, path, 'Channel.Interface.Group') # Exercise basic Channel Properties from spec 0.17.7 channel_props = group_iface.GetAll(cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE) assert channel_props.get('TargetHandle') == handle, \ channel_props.get('TargetHandle') assert channel_props.get('TargetHandleType') == cs.HT_CONTACT,\ channel_props.get('TargetHandleType') assert media_iface.GetHandle(dbus_interface=cs.CHANNEL) == (cs.HT_CONTACT, handle) assert channel_props.get('ChannelType') == cs.CHANNEL_TYPE_STREAMED_MEDIA,\ channel_props.get('ChannelType') interfaces = channel_props['Interfaces'] for i in [cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_MEDIA_SIGNALLING, cs.TP_AWKWARD_PROPERTIES, cs.CHANNEL_IFACE_HOLD]: assert i in interfaces, (i, interfaces) assert channel_props['TargetID'] == jt.peer_bare_jid, channel_props assert channel_props['Requested'] == True assert channel_props['InitiatorID'] == 'test@localhost' assert channel_props['InitiatorHandle'] == self_handle # Exercise Group Properties from spec 0.17.6 (in a basic way) group_props = group_iface.GetAll(cs.CHANNEL_IFACE_GROUP, dbus_interface=dbus.PROPERTIES_IFACE) assert 'HandleOwners' in group_props, group_props assert 'Members' in group_props, group_props assert 'LocalPendingMembers' in group_props, group_props assert 'RemotePendingMembers' in group_props, group_props assert 'GroupFlags' in group_props, group_props # The remote contact shouldn't be in remote pending yet (nor should it be # in members!) assert handle not in group_props['RemotePendingMembers'], group_props assert handle not in group_props['Members'], group_props list_streams_result = media_iface.ListStreams() assert len(list_streams_result) == 0, list_streams_result # Asking for 4 audio and 3 video streams is pathological, but we claim to # support up to 99 streams, so we should test a decent number of them. # # More practically, the success of this test implies that the simpler case # of one audio stream and one video stream should easily work. streams = media_iface.RequestStreams(handle, [cs.MEDIA_STREAM_TYPE_AUDIO, cs.MEDIA_STREAM_TYPE_VIDEO, cs.MEDIA_STREAM_TYPE_VIDEO, cs.MEDIA_STREAM_TYPE_AUDIO, cs.MEDIA_STREAM_TYPE_AUDIO, cs.MEDIA_STREAM_TYPE_VIDEO, cs.MEDIA_STREAM_TYPE_AUDIO]) assert len(streams) == 7, streams streams_by_id = {} for s in streams: streams_by_id[s[0]] = s assert len(s) == 6, s assert s[1] == handle, (s, handle) assert s[2] in (cs.MEDIA_STREAM_TYPE_AUDIO, cs.MEDIA_STREAM_TYPE_VIDEO), s # We haven't connected yet assert s[3] == cs.MEDIA_STREAM_STATE_DISCONNECTED, s # In Gabble, requested streams start off bidirectional assert s[4] == cs.MEDIA_STREAM_DIRECTION_BIDIRECTIONAL, s assert s[5] == 0, s # no pending send # the streams should all have unique IDs stream_ids = streams_by_id.keys() assert len(stream_ids) == 7 # the streams should come out in the same order as the requests assert streams[0][2] == cs.MEDIA_STREAM_TYPE_AUDIO, streams[0] assert streams[1][2] == cs.MEDIA_STREAM_TYPE_VIDEO, streams[0] assert streams[2][2] == cs.MEDIA_STREAM_TYPE_VIDEO, streams[0] assert streams[3][2] == cs.MEDIA_STREAM_TYPE_AUDIO, streams[0] assert streams[4][2] == cs.MEDIA_STREAM_TYPE_AUDIO, streams[0] assert streams[5][2] == cs.MEDIA_STREAM_TYPE_VIDEO, streams[0] assert streams[6][2] == cs.MEDIA_STREAM_TYPE_AUDIO, streams[0] # The ListStreams() result must be the streams we got from RequestStreams, # but this time the order is unimportant list_streams_result = media_iface.ListStreams() listed_streams_by_id = {} for s in list_streams_result: listed_streams_by_id[s[0]] = s assert listed_streams_by_id == streams_by_id, (listed_streams_by_id, streams_by_id) # S-E gets notified about new session handler, and calls Ready on it e = q.expect('dbus-signal', signal='NewSessionHandler') assert e.args[1] == 'rtp' session_handler_path = e.args[0] session_handler = make_channel_proxy(conn, session_handler_path, 'Media.SessionHandler') session_handler.Ready() stream_handler_paths = [] # give all 7 streams some candidates for i in xrange(7): e = q.expect('dbus-signal', signal='NewStreamHandler') stream_handler_paths.append(e.args[0]) stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) stream_handler.Ready(jt.get_audio_codecs_dbus()) stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) e = q.expect('stream-iq') assert e.query.name == 'jingle' assert e.query['action'] == 'session-initiate' stream.send(gabbletest.make_result_iq(stream, e.stanza)) jt.parse_session_initiate(e.query) jt.accept() q.expect('stream-iq', iq_type='result') # Time passes ... afterwards we close the chan group_iface.RemoveMembers([self_handle], 'closed') # Everything closes closes = [ EventPattern('dbus-signal', signal='Close', path=stream_handler_paths[i]) for i in range(0,7) ] removeds = [ EventPattern('dbus-signal', signal='StreamRemoved', args=[stream_ids[i]], path=path) for i in range(0,7) ] q.expect_many( EventPattern('dbus-signal', signal='ChannelClosed', args=[path]), *(closes + removeds) ) if __name__ == '__main__': exec_test(test) ������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/unknown-session.py�������������������������������������0000664�0001750�0001750�00000002243�12225363340�026026� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Tests that Gabble doesn't explode if it gets Jingle stanzas for unknown sessions. """ from gabbletest import exec_test from servicetest import assertEquals from jingletest2 import JingleProtocol031 import ns def assertHasChild(node, uri, name): try: node.elements(uri=uri, name=name).next() except StopIteration: raise AssertionError( "Expected <%s xmlns='%s'> to be a child of\n %s" % ( name, uri, node.toXml())) def test_send_action_for_unknown_session(q, bus, conn, stream): jp = JingleProtocol031() peer = 'guybrush@threepwo.od' iq = jp.SetIq(peer, 'test@localhost', [ jp.Jingle('fine-leather-jackets', peer, 'session-info', []) ]) stream.send(jp.xml(iq)) e = q.expect('stream-iq', iq_type='error', iq_id=iq[2]['id']) stanza = e.stanza error_node = stanza.children[-1] assertEquals('error', error_node.name) # http://xmpp.org/extensions/xep-0166.html#example-29 assertHasChild(error_node, ns.STANZA, 'item-not-found') assertHasChild(error_node, ns.JINGLE_ERRORS, 'unknown-session') if __name__ == '__main__': exec_test(test_send_action_for_unknown_session) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/dtmf.py������������������������������������������������0000664�0001750�0001750�00000015721�12332441362�023605� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test DTMF events. """ from twisted.words.xish import xpath from gabbletest import make_result_iq from servicetest import (call_async, wrap_channel, make_channel_proxy, EventPattern, sync_dbus, assertEquals) import constants as cs from jingletest2 import JingleTest2, test_all_dialects from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test(jp, q, bus, conn, stream): # this test uses multiple streams if not jp.is_modern_jingle(): return remote_jid = 'foo@bar.com/Foo' jt = JingleTest2(jp, conn, q, stream, 'test@localhost', remote_jid) jt.prepare() self_handle = conn.GetSelfHandle() handle = conn.RequestHandles(cs.HT_CONTACT, [remote_jid])[0] chan_path = conn.RequestChannel(cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.HT_CONTACT, handle, True) chan = wrap_channel(bus.get_object(conn.bus_name, chan_path), 'StreamedMedia', ['MediaSignalling', 'Group', 'CallState', 'DTMF']) chan_props = chan.Properties.GetAll(cs.CHANNEL) assert cs.CHANNEL_IFACE_DTMF in chan_props['Interfaces'], \ chan_props['Interfaces'] assertEquals('', chan.Properties.Get(cs.CHANNEL_IFACE_DTMF, 'InitialTones')) assertEquals('', chan.Properties.Get(cs.CHANNEL_IFACE_DTMF, 'DeferredTones')) chan.StreamedMedia.RequestStreams(handle, [cs.MEDIA_STREAM_TYPE_AUDIO]) # S-E gets notified about new session handler, and calls Ready on it e = q.expect('dbus-signal', signal='NewSessionHandler') assert e.args[1] == 'rtp' session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() e = q.expect('dbus-signal', signal='NewStreamHandler') audio_path = e.args[0] stream_handler = make_channel_proxy(conn, audio_path, 'Media.StreamHandler') stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) stream_handler.Ready(jt.get_audio_codecs_dbus()) stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) e = q.expect('stream-iq', predicate=jp.action_predicate('session-initiate')) stream.send(make_result_iq(stream, e.stanza)) jt.parse_session_initiate(e.query) jt.accept() # Gabble tells s-e to start sending q.expect('dbus-signal', signal='SetStreamSending', args=[True], path=audio_path) chan.StreamedMedia.RequestStreams(handle, [cs.MEDIA_STREAM_TYPE_AUDIO]) e = q.expect('dbus-signal', signal='NewStreamHandler') audio2_path = e.args[0] # The Stream_ID is specified to be ignored; we use 666 here. call_async(q, chan.DTMF, 'StartTone', 666, 3) q.expect_many( EventPattern('dbus-signal', signal='StartTelephonyEvent', path=audio2_path), EventPattern('dbus-signal', signal='StartTelephonyEvent', path=audio_path), EventPattern('dbus-signal', signal='SendingTones', args=['3'], path=chan_path), EventPattern('dbus-return', method='StartTone'), ) call_async(q, chan.DTMF, 'StopTone', 666) q.expect_many( EventPattern('dbus-signal', signal='StopTelephonyEvent', path=audio_path), EventPattern('dbus-signal', signal='StopTelephonyEvent', path=audio2_path), EventPattern('dbus-signal', signal='StoppedTones', args=[True], path=chan_path), EventPattern('dbus-return', method='StopTone'), ) call_async(q, chan.DTMF, 'MultipleTones', '123w*#') q.expect_many( EventPattern('dbus-signal', signal='StartTelephonyEvent', path=audio_path, args=[1]), EventPattern('dbus-signal', signal='StartTelephonyEvent', path=audio2_path, args=[1]), EventPattern('dbus-signal', signal='SendingTones', args=['123w*#'], path=chan_path), EventPattern('dbus-return', method='MultipleTones'), ) q.expect_many( EventPattern('dbus-signal', signal='StopTelephonyEvent', path=audio_path), EventPattern('dbus-signal', signal='StopTelephonyEvent', path=audio2_path), ) q.expect_many( EventPattern('dbus-signal', signal='StartTelephonyEvent', path=audio_path, args=[2]), EventPattern('dbus-signal', signal='StartTelephonyEvent', path=audio2_path, args=[2]), ) q.expect_many( EventPattern('dbus-signal', signal='StopTelephonyEvent', path=audio_path), EventPattern('dbus-signal', signal='StopTelephonyEvent', path=audio2_path), ) q.expect_many( EventPattern('dbus-signal', signal='StartTelephonyEvent', path=audio_path, args=[3]), EventPattern('dbus-signal', signal='StartTelephonyEvent', path=audio2_path, args=[3]), ) q.expect_many( EventPattern('dbus-signal', signal='StopTelephonyEvent', path=audio_path), EventPattern('dbus-signal', signal='StopTelephonyEvent', path=audio2_path), EventPattern('dbus-signal', signal='StoppedTones', args=[False], path=chan_path), EventPattern('dbus-signal', signal='TonesDeferred', args=['*#']), ) assertEquals('*#', chan.Properties.Get(cs.CHANNEL_IFACE_DTMF, 'DeferredTones')) forbidden = [EventPattern('dbus-signal', signal='StartTelephonyEvent', args=[9])] q.forbid_events(forbidden) # This is technically a race condition, but this dialstring is almost # certainly long enough that the Python script will win the race, i.e. # cancel before Gabble processes the whole dialstring. call_async(q, chan.DTMF, 'MultipleTones', '1,1' * 100) q.expect('dbus-return', method='MultipleTones') call_async(q, chan.DTMF, 'MultipleTones', '9') q.expect('dbus-error', method='MultipleTones', name=cs.SERVICE_BUSY) call_async(q, chan.DTMF, 'StartTone', 666, 9) q.expect('dbus-error', method='StartTone', name=cs.SERVICE_BUSY) call_async(q, chan.DTMF, 'StopTone', 666) q.expect_many( EventPattern('dbus-signal', signal='StopTelephonyEvent', path=audio_path), EventPattern('dbus-signal', signal='StopTelephonyEvent', path=audio2_path), EventPattern('dbus-signal', signal='StoppedTones', args=[True], path=chan_path), EventPattern('dbus-return', method='StopTone'), ) # emitting any sound resets TonesDeferred assertEquals('', chan.Properties.Get(cs.CHANNEL_IFACE_DTMF, 'DeferredTones')) q.unforbid_events(forbidden) chan.Group.RemoveMembers([self_handle], 'closed') e = q.expect('dbus-signal', signal='Closed', path=chan_path) if __name__ == '__main__': test_all_dialects(test) �����������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/stun-server.py�����������������������������������������0000664�0001750�0001750�00000032721�12332441362�025147� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test getting STUN server from Google jingleinfo """ from functools import partial import dbus import socket from gabbletest import make_result_iq, GoogleXmlStream, elem_iq, elem from servicetest import ( make_channel_proxy, EventPattern, assertEquals, assertLength, assertNotEquals, assertEquals ) from jingletest2 import test_all_dialects, JingleTest2 import constants as cs import ns from config import CHANNEL_TYPE_CALL_ENABLED, GOOGLE_RELAY_ENABLED, VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test_stun_server(stun_server_prop, expected_stun_servers=None): if expected_stun_servers is None: # If there is no stun server set, and it can't discover some from the # network, then gabble should fallback on the default fallback stun # server (stun.telepathy.im) # # This test uses the test-resolver which is set to # have 'stun.telepathy.im' resolve to '6.7.8.9' expected_stun_servers=[('6.7.8.9', 3478)] assertEquals(expected_stun_servers, stun_server_prop) def add_jingle_info(jingleinfo, stun_server, stun_port): stun = jingleinfo.firstChildElement().addElement('stun') server = stun.addElement('server') server['host'] = stun_server server['udp'] = stun_port relay = jingleinfo.firstChildElement().addElement('relay') relay.addElement('token', content='jingle all the way') def handle_jingle_info_query(q, stream, stun_server, stun_port): # See: http://code.google.com/apis/talk/jep_extensions/jingleinfo.html event = q.expect('stream-iq', query_ns=ns.GOOGLE_JINGLE_INFO, to=stream.authenticator.bare_jid) jingleinfo = make_result_iq(stream, event.stanza) add_jingle_info(jingleinfo, stun_server, stun_port) stream.send(jingleinfo) def push_jingle_info(q, stream, stun_server, stun_port): iq = elem_iq(stream, 'set')(elem(ns.GOOGLE_JINGLE_INFO, 'query')) add_jingle_info(iq, stun_server, stun_port) stream.send(iq) q.expect('stream-iq', iq_type='result', iq_id=iq['id']) def init_test(jp, q, conn, stream, google=False, google_push_replacements=None): jt = JingleTest2(jp, conn, q, stream, 'test@localhost', 'foo@bar.com/Foo') # If we need to override remote caps, feats, codecs or caps, # this is a good time to do it if google: handle_jingle_info_query(q, stream, 'resolves-to-1.2.3.4', '12345') if google_push_replacements is not None: # oh no! the server changed its mind! server, port = google_push_replacements push_jingle_info(q, stream, server, port) else: # We shouldn't be sending google:jingleinfo queries if the server # doesn't support it. q.forbid_events([ EventPattern('stream-iq', query_ns=ns.GOOGLE_JINGLE_INFO), ]) jt.send_presence_and_caps() remote_handle = conn.RequestHandles(1, ["foo@bar.com/Foo"])[0] return jt, remote_handle def test_streamed_media(jp, q, bus, conn, stream, expected_stun_servers=None, google=False, google_push_replacements=None, expected_relays=[]): # Initialize the test values jt, remote_handle = init_test(jp, q, conn, stream, google, google_push_replacements) # Remote end calls us jt.incoming_call() # FIXME: these signals are not observable by real clients, since they # happen before NewChannels. # The caller is in members e = q.expect('dbus-signal', signal='MembersChanged', args=[u'', [remote_handle], [], [], [], 0, 0]) # We're pending because of remote_handle e = q.expect('dbus-signal', signal='MembersChanged', args=[u'', [], [], [1L], [], remote_handle, cs.GC_REASON_INVITED]) # S-E gets notified about new session handler, and calls Ready on it e = q.expect('dbus-signal', signal='NewSessionHandler') assert e.args[1] == 'rtp' session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() e = q.expect('dbus-signal', signal='NewStreamHandler') stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') media_chan = make_channel_proxy(conn, e.path, 'Channel.Interface.Group') # Exercise channel properties channel_props = media_chan.GetAll( cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE) assert channel_props['TargetHandle'] == remote_handle assert channel_props['TargetHandleType'] == 1 assert channel_props['TargetID'] == 'foo@bar.com' assert channel_props['Requested'] == False assert channel_props['InitiatorID'] == 'foo@bar.com' assert channel_props['InitiatorHandle'] == remote_handle # The new API for STUN servers etc. sh_props = stream_handler.GetAll( 'org.freedesktop.Telepathy.Media.StreamHandler', dbus_interface=dbus.PROPERTIES_IFACE) assert sh_props['NATTraversal'] == 'gtalk-p2p' assert sh_props['CreatedLocally'] == False test_stun_server(sh_props['STUNServers'], expected_stun_servers) assert sh_props['RelayInfo'] == expected_relays # consistency check, since we currently reimplement Get separately for k in sh_props: assert sh_props[k] == stream_handler.Get( 'org.freedesktop.Telepathy.Media.StreamHandler', k, dbus_interface=dbus.PROPERTIES_IFACE), k # The old API for STUN servers etc. still needs supporting, for farsight 1 tp_prop_list = media_chan.ListProperties(dbus_interface=cs.TP_AWKWARD_PROPERTIES) tp_props = {} tp_prop_ids = {} for spec in tp_prop_list: tp_prop_ids[spec[0]] = spec[1] tp_props[spec[1]] = { 'id': spec[0], 'sig': spec[2], 'flags': spec[3] } assert 'nat-traversal' in tp_props assert tp_props['nat-traversal']['sig'] == 's' assert tp_props['nat-traversal']['flags'] == cs.PROPERTY_FLAG_READ assert 'stun-server' in tp_props assert tp_props['stun-server']['sig'] == 's' assert 'stun-port' in tp_props assert tp_props['stun-port']['sig'] in ('u', 'q') assert 'gtalk-p2p-relay-token' in tp_props assert tp_props['gtalk-p2p-relay-token']['sig'] == 's' assert tp_props['stun-server']['flags'] == cs.PROPERTY_FLAG_READ assert tp_props['stun-port']['flags'] == cs.PROPERTY_FLAG_READ if google: assert tp_props['gtalk-p2p-relay-token']['flags'] == cs.PROPERTY_FLAG_READ else: assert tp_props['gtalk-p2p-relay-token']['flags'] == 0 tp_prop_values = media_chan.GetProperties( [tp_props[k]['id'] for k in tp_props if tp_props[k]['flags']], dbus_interface=cs.TP_AWKWARD_PROPERTIES) for value in tp_prop_values: assert value[0] in tp_prop_ids tp_props[tp_prop_ids[value[0]]]['value'] = value[1] assert tp_props['nat-traversal']['value'] == 'gtalk-p2p' if expected_stun_servers is not None: expected_stun_server, expected_stun_port = expected_stun_servers[0] assert tp_props['stun-server']['value'] == expected_stun_server assert tp_props['stun-port']['value'] == expected_stun_port if google: assert tp_props['gtalk-p2p-relay-token']['value'] == 'jingle all the way' media_chan.RemoveMembers([dbus.UInt32(1)], 'rejected') q.expect_many( EventPattern('stream-iq', predicate=jp.action_predicate('session-terminate')), EventPattern('dbus-signal', signal='Closed'), ) def test_call(jp, q, bus, conn, stream, expected_stun_servers=None, google=False, google_push_replacements=None, expected_relays=[]): # Initialize the test values jt, remote_handle = init_test(jp, q, conn, stream, google, google_push_replacements) # Advertise that we can do new style calls conn.ContactCapabilities.UpdateCapabilities([ (cs.CLIENT + ".CallHandler", [ { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL, cs.CALL_INITIAL_AUDIO: True}, { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL, cs.CALL_INITIAL_VIDEO: True}, ], [ cs.CHANNEL_TYPE_CALL + '/gtalk-p2p', cs.CHANNEL_TYPE_CALL + '/ice', cs.CHANNEL_TYPE_CALL + '/video/h264', ]), ]) # Remote end calls us jt.incoming_call() e = q.expect('dbus-signal', signal='ServerInfoRetrieved') assertLength(0, e.args) assertEquals(e.interface, cs.CALL_STREAM_IFACE_MEDIA) e = q.expect('dbus-signal', signal='NewChannels', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args) assert e.args[0][0][0] call_chan = make_channel_proxy(conn, e.args[0][0][0], 'Channel') # Exercise channel properties channel_props = call_chan.GetAll( cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(remote_handle, channel_props['TargetHandle']) assertEquals(1, channel_props['TargetHandleType']) assertEquals('foo@bar.com', channel_props['TargetID']) assertEquals(False, channel_props['Requested']) assertEquals('foo@bar.com', channel_props['InitiatorID']) assertEquals(remote_handle, channel_props['InitiatorHandle']) # Get the call's Content object channel_props = call_chan.Get(cs.CHANNEL_TYPE_CALL, 'Contents', dbus_interface=dbus.PROPERTIES_IFACE) assertLength(1, channel_props) assert len(channel_props[0]) > 0 assertNotEquals('/', channel_props[0]) # Get the call's Stream object call_content = make_channel_proxy(conn, channel_props[0], 'Call.Content.Draft') content_props = call_content.Get(cs.CALL_CONTENT, 'Streams', dbus_interface=dbus.PROPERTIES_IFACE) assertLength(1, content_props) assert len(content_props[0]) > 0 assertNotEquals('/', content_props[0]) # Test the call's Stream's properties call_stream = make_channel_proxy(conn, content_props[0], 'Call.Stream.Interface.Media.Draft') stream_props = call_stream.GetAll(cs.CALL_STREAM_IFACE_MEDIA, dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(cs.CALL_STREAM_TRANSPORT_GTALK_P2P, stream_props['Transport']) test_stun_server(stream_props['STUNServers'], expected_stun_servers) assertEquals(expected_relays, stream_props['RelayInfo']) assertEquals(True, stream_props['HasServerInfo']) if __name__ == '__main__': # StreamedMedia tests test_all_dialects(partial(test_streamed_media, google=False)) test_all_dialects(partial(test_streamed_media, google=False, expected_stun_servers=[('5.4.3.2', 54321)]), params={'fallback-stun-server': 'resolves-to-5.4.3.2', 'fallback-stun-port': dbus.UInt16(54321)}) test_all_dialects(partial(test_streamed_media, google=False, expected_stun_servers=[('5.4.3.2', 1)]), params={'account': 'test@stunning.localhost'}) if GOOGLE_RELAY_ENABLED: test_all_dialects(partial(test_streamed_media, google=True, expected_stun_servers=[('1.2.3.4', 12345)]), protocol=GoogleXmlStream) test_all_dialects(partial(test_streamed_media, google=True, expected_stun_servers=[('5.4.3.2', 54321)]), protocol=GoogleXmlStream, params={'stun-server': 'resolves-to-5.4.3.2', 'stun-port': dbus.UInt16(54321)}) test_all_dialects(partial(test_streamed_media, google=True, expected_stun_servers=[('1.2.3.4', 12345)]), protocol=GoogleXmlStream, params={'fallback-stun-server': 'resolves-to-5.4.3.2', 'fallback-stun-port': dbus.UInt16(54321)}) test_all_dialects(partial(test_streamed_media, google=True, google_push_replacements=('resolves-to-5.4.3.2', '3838'), expected_stun_servers=[('5.4.3.2', 3838)]), protocol=GoogleXmlStream) else: print "NOTE: built with --disable-google-relay; omitting StreamedMedia tests with Google relay" # Call tests if CHANNEL_TYPE_CALL_ENABLED: test_all_dialects(partial(test_call, google=False)) test_all_dialects(partial(test_call, google=False, expected_stun_servers=[('5.4.3.2', 54321)]), params={'fallback-stun-server': 'resolves-to-5.4.3.2', 'fallback-stun-port': dbus.UInt16(54321)}) test_all_dialects(partial(test_call, google=False, expected_stun_servers=[('5.4.3.2', 1)]), params={'account': 'test@stunning.localhost'}) else: print "NOTE: built with --disable-channel-type-call; omitting Call tests" if CHANNEL_TYPE_CALL_ENABLED and GOOGLE_RELAY_ENABLED: test_all_dialects(partial(test_call, google=True, expected_stun_servers=[('1.2.3.4', 12345)]), protocol=GoogleXmlStream) test_all_dialects(partial(test_call, google=True, expected_stun_servers=[('5.4.3.2', 54321)]), protocol=GoogleXmlStream, params={'stun-server': 'resolves-to-5.4.3.2', 'stun-port': dbus.UInt16(54321)}) test_all_dialects(partial(test_call, google=True, expected_stun_servers=[('1.2.3.4', 12345)]), protocol=GoogleXmlStream, params={'fallback-stun-server': 'resolves-to-5.4.3.2', 'fallback-stun-port': dbus.UInt16(54321)}) test_all_dialects(partial(test_call, google=True, google_push_replacements=('resolves-to-5.4.3.2', '3838'), expected_stun_servers=[('5.4.3.2', 3838)]), protocol=GoogleXmlStream) else: print "NOTE: built with --disable-channel-type-call or with --disable-google-relay; omitting Call tests with Google relay" �����������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/call_helper.py�����������������������������������������0000664�0001750�0001750�00000102313�12332441362�025117� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Base classes for Call tests """ import config if not config.CHANNEL_TYPE_CALL_ENABLED: print "NOTE: built with --disable-channel-type-call" raise SystemExit(77) import dbus from dbus.exceptions import DBusException from functools import partial from servicetest import ( EventPattern, call_async, wrap_channel, wrap_content, assertEquals, assertDoesNotContain, assertContains, assertLength, assertNotEquals, DictionarySupersetOf) from gabbletest import sync_stream, make_result_iq from jingletest2 import JingleTest2, test_all_dialects import constants as cs import ns from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) class CallTest(object): SELF_JID = 'test@localhost' PEER_JID = 'foo@bar.com/Foo' # These can be changed as needed by base class initial_audio = True initial_video = False # The following will be set after initiate_call() chan = None audio_content = None audio_content_name = None audio_stream = None video_content = None video_content_name = None video_stream = None def __init__(self, jp, q, bus, conn, stream, incoming, params): self.jp = jp self.q = q self.bus = bus self.conn = conn self.stream = stream self.incoming = incoming self.params = params self.jt2 = JingleTest2(jp, conn, q, stream, self.SELF_JID, self.PEER_JID) self.can_change_direction = (jp.dialect not in ['gtalk-v0.3', 'gtalk-v0.4']) self.self_handle = conn.GetSelfHandle() self.peer_handle = conn.RequestHandles(1, ["foo@bar.com/Foo"])[0] def check_channel_state(self, state, wait = False): """Optionnally wait for channel state to be reached and check that the property has the right value""" if wait: self.q.expect('dbus-signal', signal='CallStateChanged', interface = cs.CHANNEL_TYPE_CALL, predicate = lambda e: e.args[0] == state) assertEquals(state, self.chan.Get(cs.CHANNEL_TYPE_CALL, 'CallState', dbus_interface=dbus.PROPERTIES_IFACE)) def check_stream_recv_state(self, stream, state): assertEquals(state, stream.Get(cs.CALL_STREAM_IFACE_MEDIA, 'ReceivingState', dbus_interface=dbus.PROPERTIES_IFACE)) def check_stream_send_state(self, stream, state): assertEquals(state, stream.Get(cs.CALL_STREAM_IFACE_MEDIA, 'SendingState', dbus_interface=dbus.PROPERTIES_IFACE)) def complete_receiving_state(self, stream): if stream is None: return self.check_stream_recv_state(stream, cs.CALL_STREAM_FLOW_STATE_PENDING_START) stream.CompleteReceivingStateChange(cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) self.q.expect('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA) def check_and_accept_offer(self, content, md, md_changed = True, offer_path = None): [path, remote_md] = content.Get(cs.CALL_CONTENT_IFACE_MEDIA, "MediaDescriptionOffer", dbus_interface=dbus.PROPERTIES_IFACE) if offer_path != None: assertEquals(offer_path, path) assertNotEquals("/", path) offer = self.bus.get_object(self.conn.bus_name, path) codecmap_property = offer.Get(cs.CALL_CONTENT_MEDIADESCRIPTION, "Codecs", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(remote_md[cs.CALL_CONTENT_MEDIADESCRIPTION + '.Codecs'], codecmap_property) offer.Accept(md, dbus_interface=cs.CALL_CONTENT_MEDIADESCRIPTION) current_md = content.Get(cs.CALL_CONTENT_IFACE_MEDIA, "LocalMediaDescriptions", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(md, current_md[self.peer_handle]) if md_changed: o = self.q.expect('dbus-signal', signal='LocalMediaDescriptionChanged') assertEquals([md], o.args) def store_content(self, content_path, initial = True, incoming = None): if incoming is None: incoming = self.incoming content = wrap_content(self.bus.get_object(self.conn.bus_name, content_path), ['DTMF', 'Media']) content_props = content.GetAll(cs.CALL_CONTENT, dbus_interface=dbus.PROPERTIES_IFACE) # Has one stream assertLength(1, content_props["Streams"]) if initial: assertEquals(cs.CALL_DISPOSITION_INITIAL, content_props["Disposition"]) else: assertEquals(cs.CALL_DISPOSITION_NONE, content_props["Disposition"]) # Implements Content.Interface.Media assertContains(cs.CALL_CONTENT_IFACE_MEDIA, content_props["Interfaces"]) if content_props['Type'] == cs.CALL_MEDIA_TYPE_AUDIO: # Implements Content.Interface.DTMF assertContains(cs.CALL_CONTENT_IFACE_DTMF, content_props["Interfaces"]) assertContains("Name", content_props.keys()) content_name = content_props["Name"] stream = self.bus.get_object(self.conn.bus_name, content_props["Streams"][0]) stream_props = stream.GetAll(cs.CALL_STREAM, dbus_interface = dbus.PROPERTIES_IFACE) assertDoesNotContain(self.self_handle, stream_props["RemoteMembers"].keys()) assertContains(self.peer_handle, stream_props["RemoteMembers"].keys()) assertEquals([cs.CALL_STREAM_IFACE_MEDIA], stream_props["Interfaces"]) assertEquals(self.can_change_direction, stream_props["CanRequestReceiving"]) if incoming: assertEquals(cs.CALL_SENDING_STATE_PENDING_SEND, stream_props["LocalSendingState"]) assertEquals(cs.CALL_SENDING_STATE_SENDING, stream_props["RemoteMembers"][self.peer_handle]) else: if initial: assertEquals(cs.CALL_SENDING_STATE_PENDING_SEND, stream_props["RemoteMembers"][self.peer_handle]) else: assertEquals(cs.CALL_SENDING_STATE_SENDING, stream_props["RemoteMembers"][self.peer_handle]) assertEquals(cs.CALL_SENDING_STATE_SENDING, stream_props["LocalSendingState"]) # Packetization should be RTP content_media_props = content.GetAll(cs.CALL_CONTENT_IFACE_MEDIA, dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(cs.CALL_CONTENT_PACKETIZATION_RTP, content_media_props["Packetization"]) # Check the directions stream_media_props = stream.GetAll(cs.CALL_STREAM_IFACE_MEDIA, dbus_interface=dbus.PROPERTIES_IFACE) if initial or incoming: assertEquals(cs.CALL_STREAM_FLOW_STATE_STOPPED, stream_media_props["SendingState"]) else: assertEquals(cs.CALL_STREAM_FLOW_STATE_PENDING_START, stream_media_props["SendingState"]) if initial: assertEquals(cs.CALL_STREAM_FLOW_STATE_STOPPED, stream_media_props["ReceivingState"]) else: assertEquals(cs.CALL_STREAM_FLOW_STATE_PENDING_START, stream_media_props["ReceivingState"]) assertEquals(False, stream_media_props["ICERestartPending"]) # Store the content and stream if content_props['Type'] == cs.CALL_MEDIA_TYPE_AUDIO: assert self.initial_audio == initial assert self.audio_content == None assert self.audio_stream == None self.audio_content = content self.audio_content_name = content_name self.audio_stream = stream elif content_props['Type'] == cs.CALL_MEDIA_TYPE_VIDEO: assert self.initial_video == initial assert self.video_content == None assert self.video_stream == None self.video_content = content self.video_content_name = content_name self.video_stream = stream else: assert not 'Bad content type value' def enable_endpoint(self, endpoint): endpoint.SetEndpointState(cs.CALL_STREAM_COMPONENT_DATA, cs.CALL_STREAM_ENDPOINT_STATE_FULLY_CONNECTED, dbus_interface=cs.CALL_STREAM_ENDPOINT) self.q.expect('dbus-signal', signal='EndpointStateChanged', interface=cs.CALL_STREAM_ENDPOINT) endpoint.SetEndpointState(cs.CALL_STREAM_COMPONENT_CONTROL, cs.CALL_STREAM_ENDPOINT_STATE_FULLY_CONNECTED, dbus_interface=cs.CALL_STREAM_ENDPOINT) self.q.expect('dbus-signal', signal='EndpointStateChanged', interface=cs.CALL_STREAM_ENDPOINT) state = endpoint.Get(cs.CALL_STREAM_ENDPOINT, "EndpointState", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(cs.CALL_STREAM_ENDPOINT_STATE_FULLY_CONNECTED, state[1]) assertEquals(cs.CALL_STREAM_ENDPOINT_STATE_FULLY_CONNECTED, state[2]) def advertise(self, initial_audio = True, initial_video = True): """Advertise that Call is supported""" self.conn.ContactCapabilities.UpdateCapabilities([ (cs.CLIENT + ".CallHandler", [ { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL, cs.CALL_INITIAL_AUDIO: initial_audio}, { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL, cs.CALL_INITIAL_VIDEO: initial_video}, ], [ cs.CHANNEL_TYPE_CALL + '/gtalk-p2p', cs.CHANNEL_TYPE_CALL + '/ice', cs.CHANNEL_TYPE_CALL + '/video/h264', ]), ]) def prepare(self, events=None): """Prepare the JingleTest2 object. This method can be override to trap special event linke jingleinfo.""" self.jt2.prepare(events=events) def initiate(self): """Brind the call to INITIALISING state. This method will fill the channel, contents and streams members.""" # Ensure a channel that doesn't exist yet. if self.incoming: if self.initial_audio and self.initial_video: self.jt2.incoming_call(audio='audio1', video='video1') elif self.initial_audio: self.jt2.incoming_call(audio='audio1', video=None) else: self.jt2.incoming_call(audio=None, video='video1') else: ret = self.conn.Requests.CreateChannel( { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: self.peer_handle, cs.CALL_INITIAL_AUDIO: self.initial_audio, cs.CALL_INITIAL_VIDEO: self.initial_video, }) signal = self.q.expect('dbus-signal', signal='NewChannels', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args[0][0][1].values()) assertLength(1, signal.args) assertLength(1, signal.args[0]) # one channel assertLength(2, signal.args[0][0]) # two struct members emitted_props = signal.args[0][0][1] assertEquals( cs.CHANNEL_TYPE_CALL, emitted_props[cs.CHANNEL_TYPE]) peer_bare_jid = self.PEER_JID.split('/')[0] assertEquals(self.peer_handle, emitted_props[cs.TARGET_HANDLE]) assertEquals(cs.HT_CONTACT, emitted_props[cs.TARGET_HANDLE_TYPE]) assertEquals(peer_bare_jid, emitted_props[cs.TARGET_ID]) assertEquals(not self.incoming, emitted_props[cs.REQUESTED]) if self.incoming: assertEquals(self.peer_handle, emitted_props[cs.INITIATOR_HANDLE]) assertEquals(peer_bare_jid, emitted_props[cs.INITIATOR_ID]) else: assertEquals(self.self_handle, emitted_props[cs.INITIATOR_HANDLE]) assertEquals(self.SELF_JID, emitted_props[cs.INITIATOR_ID]) assertEquals(self.initial_audio, emitted_props[cs.CALL_INITIAL_AUDIO]) assertEquals(self.initial_video, emitted_props[cs.CALL_INITIAL_VIDEO]) chan_path = signal.args[0][0][0] self.chan = wrap_channel( self.bus.get_object(self.conn.bus_name, chan_path), 'Call', ['Hold']) properties = self.chan.GetAll(cs.CHANNEL_TYPE_CALL, dbus_interface=dbus.PROPERTIES_IFACE) # Check if all the properties are there assertEquals(sorted([ "Contents", "CallMembers", "CallState", "CallFlags", "CallStateReason", "CallStateDetails", "HardwareStreaming", "InitialAudio", "InitialAudioName", "InitialVideo", "InitialVideoName", "MutableContents", "InitialTransport", "MemberIdentifiers" ]), sorted(properties.keys())) # Remote member is the target assertEquals([self.peer_handle], properties["CallMembers"].keys()) assertEquals(0, properties["CallMembers"][self.peer_handle]) # No Hardware Streaming for you assertEquals(False, properties["HardwareStreaming"]) # Store content and stream nb_contents = self.initial_audio + self.initial_video assertLength(nb_contents, properties["Contents"]) for content_path in properties["Contents"]: self.store_content(content_path) if self.initial_audio: assert self.audio_content if self.initial_video: assert self.video_content def accept_outgoing(self): """If call is incoming, accept the channel and complete the receiving state change. Then do state check. This method shall be called even if receiving a call to execute the state sanity checks.""" # Check if the channel is in the right pending state if not self.incoming: self.check_channel_state(cs.CALL_STATE_PENDING_INITIATOR) self.chan.Accept(dbus_interface=cs.CHANNEL_TYPE_CALL) if self.initial_audio: self.complete_receiving_state(self.audio_stream) # Don't start sending before the call is accepted locally or # remotely self.check_stream_send_state(self.audio_stream, cs.CALL_STREAM_FLOW_STATE_STOPPED) if self.initial_video: self.complete_receiving_state(self.video_stream) self.check_stream_send_state(self.video_stream, cs.CALL_STREAM_FLOW_STATE_STOPPED) # All Direction should be both now for outgoing if self.initial_audio: stream_props = self.audio_stream.GetAll(cs.CALL_STREAM, dbus_interface = dbus.PROPERTIES_IFACE) if self.incoming: assertEquals({self.peer_handle: cs.CALL_SENDING_STATE_SENDING}, stream_props["RemoteMembers"]) assertEquals(cs.CALL_SENDING_STATE_PENDING_SEND, stream_props["LocalSendingState"]) else: assertEquals( {self.peer_handle: cs.CALL_SENDING_STATE_PENDING_SEND}, stream_props["RemoteMembers"]) assertEquals(cs.CALL_SENDING_STATE_SENDING, stream_props["LocalSendingState"]) if self.initial_video: stream_props = self.video_stream.GetAll(cs.CALL_STREAM, dbus_interface = dbus.PROPERTIES_IFACE) if self.incoming: assertEquals({self.peer_handle: cs.CALL_SENDING_STATE_SENDING}, stream_props["RemoteMembers"]) assertEquals(cs.CALL_SENDING_STATE_PENDING_SEND, stream_props["LocalSendingState"]) else: assertEquals( {self.peer_handle: cs.CALL_SENDING_STATE_PENDING_SEND}, stream_props["RemoteMembers"]) assertEquals(cs.CALL_SENDING_STATE_SENDING, stream_props["LocalSendingState"]) self.check_channel_state(cs.CALL_STATE_INITIALISING) def connect_streams(self, contents, streams, mds, expect_after_si=None): # Expected to fail since we did not said we are controlling side try: contents[0].UpdateLocalMediaDescription(mds[0], dbus_interface=cs.CALL_CONTENT_IFACE_MEDIA) except DBusException, e: if e.get_dbus_name() != cs.NOT_AVAILABLE: raise e else: assert False expected = [] candidates = self.jt2.get_call_remote_transports_dbus() for i in range(len(contents)): self.check_and_accept_offer(contents[i], mds[i], md_changed=False) expected.append(EventPattern('dbus-signal', signal='LocalMediaDescriptionChanged', args=[mds[i]])) current_md = contents[i].Get(cs.CALL_CONTENT_IFACE_MEDIA, "LocalMediaDescriptions", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(mds[i], current_md[self.peer_handle]) streams[i].SetCredentials(self.jt2.ufrag, self.jt2.pwd, dbus_interface=cs.CALL_STREAM_IFACE_MEDIA) expected.append(EventPattern('dbus-signal', signal='LocalCredentialsChanged', args=[self.jt2.ufrag, self.jt2.pwd])) credentials = streams[i].GetAll(cs.CALL_STREAM_IFACE_MEDIA, dbus_interface=dbus.PROPERTIES_IFACE)["LocalCredentials"] assertEquals((self.jt2.ufrag, self.jt2.pwd), credentials) # Add candidates streams[i].AddCandidates(candidates, dbus_interface=cs.CALL_STREAM_IFACE_MEDIA) expected.append(EventPattern('dbus-signal', signal='LocalCandidatesAdded')) if not self.incoming: expected.append(EventPattern('stream-iq', predicate=self.jp.action_predicate('session-initiate'))) ret = self.q.expect_many(*expected) # Check the first LocalCandidatesAdded signal (third in the array) assertEquals(candidates, ret[2].args[0]) if not self.incoming: if expect_after_si is not None: sync_stream(self.q, self.stream) self.q.unforbid_events(expect_after_si) self.stream.send(make_result_iq(self.stream, ret[-1].stanza)) if expect_after_si is not None: self.q.expect_many(*expect_after_si) self.jt2.parse_session_initiate(ret[-1].query) endpoints = [] for stream in streams: stream.FinishInitialCandidates( dbus_interface=cs.CALL_STREAM_IFACE_MEDIA) local_candidates = stream.Get(cs.CALL_STREAM_IFACE_MEDIA, "LocalCandidates", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(candidates, local_candidates) endpoint_paths = stream.Get(cs.CALL_STREAM_IFACE_MEDIA, "Endpoints", dbus_interface=dbus.PROPERTIES_IFACE) assertLength(1, endpoint_paths) # There doesn't seem to be a good way to get the transport type from # the JP used, for now assume we prefer gtalk p2p and always pick # that.. transport = stream.Get(cs.CALL_STREAM_IFACE_MEDIA, "Transport", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(cs.CALL_STREAM_TRANSPORT_GTALK_P2P, transport) endpoint = self.bus.get_object(self.conn.bus_name, endpoint_paths[0]) endpoints.append(endpoint) endpoint_props = endpoint.GetAll(cs.CALL_STREAM_ENDPOINT, dbus_interface=dbus.PROPERTIES_IFACE) transport = endpoint_props["Transport"] assertEquals(cs.CALL_STREAM_TRANSPORT_GTALK_P2P, transport) remote_candidates = endpoint.Get(cs.CALL_STREAM_ENDPOINT, "RemoteCandidates", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals([], remote_candidates) selected_candidate = endpoint.Get(cs.CALL_STREAM_ENDPOINT, "SelectedCandidatePairs", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals([], selected_candidate) state = endpoint.Get(cs.CALL_STREAM_ENDPOINT, "EndpointState", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals({}, state) names = [] for content in contents: if content is self.audio_content: names.append(self.jt2.audio_names[0]) else: names.append(self.jt2.video_names[0]) for name in names: if self.jp.dialect == 'gtalk-v0.3': # Candidates must be sent one at a time. for candidate in self.jt2.get_call_remote_transports_dbus(): component, addr, port, props = candidate self.jt2.send_remote_candidates_call_xmpp( name, "initiator", [candidate]) self.q.expect('dbus-signal', signal='RemoteCandidatesAdded', interface=cs.CALL_STREAM_ENDPOINT, args=[[(component, addr, port, DictionarySupersetOf(props))]]) elif self.jp.dialect == 'gtalk-v0.4' and not self.incoming: # Don't test this case at all. pass else: self.jt2.send_remote_candidates_call_xmpp(name, "initiator") candidates = [] for component, addr, port, props in \ self.jt2.get_call_remote_transports_dbus(): candidates.append((component, addr, port, DictionarySupersetOf(props))) self.q.expect('dbus-signal', signal='RemoteCandidatesAdded', interface=cs.CALL_STREAM_ENDPOINT, args=[candidates]) # FIXME: makes sense to have same local and remote candidate? candidate1 = self.jt2.get_call_remote_transports_dbus()[0] candidate2 = self.jt2.get_call_remote_transports_dbus()[1] for endpoint in endpoints: # Expected to fail since we did not said we are controlling side try: endpoint.SetSelectedCandidatePair(candidate1, candidate1, dbus_interface=cs.CALL_STREAM_ENDPOINT) except DBusException, e: if e.get_dbus_name() != cs.INVALID_ARGUMENT: raise e else: assert false endpoint.SetControlling(True, dbus_interface=cs.CALL_STREAM_ENDPOINT) endpoint.SetSelectedCandidatePair(candidate1, candidate1, dbus_interface=cs.CALL_STREAM_ENDPOINT) pair = self.q.expect('dbus-signal', signal='CandidatePairSelected', interface=cs.CALL_STREAM_ENDPOINT) assertEquals(candidate1, pair.args[0]) assertEquals(candidate1, pair.args[1]) endpoint.SetSelectedCandidatePair(candidate2, candidate2, dbus_interface=cs.CALL_STREAM_ENDPOINT) # We have an RTCP candidate as well, so we should set this as # selected too. pair = self.q.expect('dbus-signal', signal='CandidatePairSelected', interface=cs.CALL_STREAM_ENDPOINT) assertEquals(candidate2, pair.args[0]) assertEquals(candidate2, pair.args[1]) pairs = endpoint.Get(cs.CALL_STREAM_ENDPOINT, "SelectedCandidatePairs", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(len(pairs), 2) assertEquals(pairs[0][0], pairs[0][1]) assertEquals(pairs[1][0], pairs[1][1]) if pairs[0][0] == candidate1: assertEquals(pairs[1][0], candidate2) else: assertEquals(pairs[0][0], candidate2) assertEquals(pairs[1][0], candidate1) # setting endpoints to CONNECTED should make the call state move # from INITIALISING to INITIALISED self.enable_endpoint(endpoint) self.check_channel_state(cs.CALL_STATE_INITIALISED) def connect(self, expect_after_si=None): """Negotiate all the codecs, bringing the channel to INITIALISED state""" contents = [] streams = [] mds = [] if self.initial_audio: # Setup media description contents.append(self.audio_content) streams.append(self.audio_stream) mds.append(self.jt2.get_call_audio_md_dbus(self.peer_handle)) if self.initial_video: contents.append(self.video_content) streams.append(self.video_stream) mds.append(self.jt2.get_call_video_md_dbus(self.peer_handle)) self.connect_streams(contents, streams, mds, expect_after_si=expect_after_si) def pickup(self, held=False): if self.initial_audio: self.check_stream_send_state(self.audio_stream, cs.CALL_STREAM_FLOW_STATE_STOPPED) if self.initial_video: self.check_stream_send_state(self.video_stream, cs.CALL_STREAM_FLOW_STATE_STOPPED) if self.incoming: # Act as if we're ringing self.chan.SetRinging(dbus_interface=cs.CHANNEL_TYPE_CALL) signal = self.q.expect('dbus-signal', signal='CallStateChanged') assertEquals(cs.CALL_FLAG_LOCALLY_RINGING, signal.args[1] & cs.CALL_FLAG_LOCALLY_RINGING) # And now pickup the call self.chan.Accept(dbus_interface=cs.CHANNEL_TYPE_CALL) expected = [ EventPattern('dbus-signal', signal='CallStateChanged'), EventPattern('stream-iq', predicate=self.jp.action_predicate('session-accept'))] if self.initial_audio: # SendingStateChanged is caused by chan.Accept expected.append(EventPattern('dbus-signal', signal='SendingStateChanged')) recv_state = self.audio_stream.GetAll( cs.CALL_STREAM_IFACE_MEDIA, dbus_interface=dbus.PROPERTIES_IFACE)["ReceivingState"] assertEquals(cs.CALL_STREAM_FLOW_STATE_PENDING_START, recv_state) self.audio_stream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) expected.append(EventPattern('dbus-signal', signal='ReceivingStateChanged')) if self.initial_video: # SendingStateChanged is caused by chan.Accept expected.append(EventPattern('dbus-signal', signal='SendingStateChanged')) recv_state = self.video_stream.GetAll( cs.CALL_STREAM_IFACE_MEDIA, dbus_interface=dbus.PROPERTIES_IFACE)["ReceivingState"] assertEquals(cs.CALL_STREAM_FLOW_STATE_PENDING_START, recv_state) self.video_stream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) expected.append(EventPattern('dbus-signal', signal='ReceivingStateChanged')) ret = self.q.expect_many(*expected) assertEquals(0, ret[0].args[1] & cs.CALL_FLAG_LOCALLY_RINGING) if self.initial_audio and self.initial_video: assertEquals(cs.CALL_STREAM_FLOW_STATE_PENDING_START, ret[2].args[0]) assertEquals(cs.CALL_STREAM_FLOW_STATE_PENDING_START, ret[3].args[0]) else: assertEquals(cs.CALL_STREAM_FLOW_STATE_PENDING_START, ret[2].args[0]) self.jt2.result_iq(ret[1]) else: if self.jp.is_modern_jingle(): # The other person's client starts ringing, and tells us so! node = self.jp.SetIq(self.jt2.peer, self.jt2.jid, [ self.jp.Jingle(self.jt2.sid, self.jt2.jid, 'session-info', [ ('ringing', ns.JINGLE_RTP_INFO_1, {}, []) ]) ]) self.stream.send(self.jp.xml(node)) o = self.q.expect('dbus-signal', signal="CallMembersChanged") assertEquals(cs.CALL_MEMBER_FLAG_RINGING, o.args[0][self.peer_handle]) self.jt2.accept() expected = [EventPattern('dbus-signal', signal='NewMediaDescriptionOffer')] if not held: if self.initial_audio: expected.append(EventPattern('dbus-signal', signal='SendingStateChanged')) if self.initial_video: expected.append(EventPattern('dbus-signal', signal='SendingStateChanged')) ret = self.q.expect_many(*expected) if not held: # Checking one of sending states assertEquals(cs.CALL_STREAM_FLOW_STATE_PENDING_START, ret[1].args[0]) if self.initial_audio: md = self.jt2.get_call_audio_md_dbus(self.peer_handle) self.check_and_accept_offer(self.audio_content, md, md_changed = False) if self.initial_video: md = self.jt2.get_call_video_md_dbus(self.peer_handle) self.check_and_accept_offer(self.video_content, md, md_changed = False) self.check_channel_state(cs.CALL_STATE_ACTIVE) # All Direction should be both sending now if self.initial_audio and not held: stream_props = self.audio_stream.GetAll(cs.CALL_STREAM, dbus_interface = dbus.PROPERTIES_IFACE) assertEquals({self.peer_handle: cs.CALL_SENDING_STATE_SENDING}, stream_props["RemoteMembers"]) assertEquals(cs.CALL_SENDING_STATE_SENDING, stream_props["LocalSendingState"]) assertEquals(cs.CALL_STREAM_FLOW_STATE_PENDING_START, self.audio_stream.Get(cs.CALL_STREAM_IFACE_MEDIA, "SendingState", dbus_interface = dbus.PROPERTIES_IFACE)) self.audio_stream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) o = self.q.expect('dbus-signal', signal='SendingStateChanged', interface = cs.CALL_STREAM_IFACE_MEDIA) assertEquals(cs.CALL_STREAM_FLOW_STATE_STARTED, o.args[0]) if self.initial_video and not held: stream_props = self.video_stream.GetAll(cs.CALL_STREAM, dbus_interface = dbus.PROPERTIES_IFACE) assertEquals({self.peer_handle: cs.CALL_SENDING_STATE_SENDING}, stream_props["RemoteMembers"]) assertEquals(cs.CALL_SENDING_STATE_SENDING, stream_props["LocalSendingState"]) assertEquals(cs.CALL_STREAM_FLOW_STATE_PENDING_START, self.video_stream.Get(cs.CALL_STREAM_IFACE_MEDIA, "SendingState", dbus_interface = dbus.PROPERTIES_IFACE)) self.video_stream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) o = self.q.expect('dbus-signal', signal='SendingStateChanged', interface = cs.CALL_STREAM_IFACE_MEDIA) assertEquals(cs.CALL_STREAM_FLOW_STATE_STARTED, o.args[0]) def hangup(self): if self.incoming: self.jt2.terminate() else: self.chan.Hangup(0, "", "", dbus_interface=cs.CHANNEL_TYPE_CALL) self.check_channel_state(cs.CALL_STATE_ENDED, wait = True) def run(self): if self.initial_video: if not self.initial_audio and not self.jp.can_do_video_only(): return elif not self.jp.can_do_video(): return self.advertise() self.prepare() self.initiate() self.accept_outgoing() self.connect() self.pickup() self.hangup() def run_call_test(jp, q, bus, conn, stream, klass=CallTest, incoming=False, params={}): test = klass(jp, q, bus, conn, stream, incoming, params) test.run() if __name__ == '__main__': test_all_dialects(partial(run_call_test, incoming=False)) test_all_dialects(partial(run_call_test, incoming=True)) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/call-basics.py�����������������������������������������0000664�0001750�0001750�00000037301�12332441362�025026� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test basic outgoing and incoming call handling """ import config if not config.CHANNEL_TYPE_CALL_ENABLED: print "NOTE: built with --disable-channel-type-call" raise SystemExit(77) import dbus from dbus.exceptions import DBusException from functools import partial from servicetest import EventPattern, assertEquals, assertContains, assertLength from call_helper import CallTest, run_call_test from jingletest2 import test_all_dialects import constants as cs import ns from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) class CallBasicsTest(CallTest): def test_connect_disconnect_endpoint(self): endpoints = self.audio_stream.Get(cs.CALL_STREAM_IFACE_MEDIA, "Endpoints", dbus_interface=dbus.PROPERTIES_IFACE) assertLength(1, endpoints) endpoint = self.bus.get_object(self.conn.bus_name, endpoints[0]) # Lets try disconnecting one endpoint.SetEndpointState(1, cs.CALL_STREAM_ENDPOINT_STATE_CONNECTING, dbus_interface=cs.CALL_STREAM_ENDPOINT) ret = self.q.expect_many( EventPattern('dbus-signal', signal='EndpointStateChanged'), EventPattern('dbus-signal', signal='CallStateChanged')) assertEquals(1, ret[0].args[0]) assertEquals(cs.CALL_STREAM_ENDPOINT_STATE_CONNECTING, ret[0].args[1]) assertEquals(cs.CALL_STATE_ACCEPTED, ret[1].args[0]) state = endpoint.Get(cs.CALL_STREAM_ENDPOINT, "EndpointState", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(cs.CALL_STREAM_ENDPOINT_STATE_CONNECTING, state[1]) # And reconnecting it endpoint.SetEndpointState(1, cs.CALL_STREAM_ENDPOINT_STATE_FULLY_CONNECTED, dbus_interface=cs.CALL_STREAM_ENDPOINT) ret = self.q.expect_many( EventPattern('dbus-signal', signal='EndpointStateChanged'), EventPattern('dbus-signal', signal='CallStateChanged')) assertEquals(1,ret[0].args[0]) assertEquals(cs.CALL_STREAM_ENDPOINT_STATE_FULLY_CONNECTED, ret[0].args[1]) assertEquals(cs.CALL_STATE_ACTIVE, ret[1].args[0]) state = endpoint.Get(cs.CALL_STREAM_ENDPOINT, "EndpointState", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(cs.CALL_STREAM_ENDPOINT_STATE_FULLY_CONNECTED, state[1]) # All Direction should still be both now stream_props = self.audio_stream.GetAll(cs.CALL_STREAM, dbus_interface = dbus.PROPERTIES_IFACE) assertEquals({self.peer_handle: cs.CALL_SENDING_STATE_SENDING}, stream_props["RemoteMembers"]) assertEquals(cs.CALL_SENDING_STATE_SENDING, stream_props["LocalSendingState"]) def test_content_addition(self): path = self.chan.AddContent("Webcam", cs.CALL_MEDIA_TYPE_VIDEO, cs.MEDIA_STREAM_DIRECTION_BIDIRECTIONAL, dbus_interface=cs.CHANNEL_TYPE_CALL) content = self.bus.get_object(self.conn.bus_name, path) content_properties = content.GetAll(cs.CALL_CONTENT, dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(cs.CALL_DISPOSITION_NONE, content_properties["Disposition"]) #assertEquals(self_handle, content_properties["Creator"]) assertContains("Webcam", content_properties["Name"]) md = self.jt2.get_call_video_md_dbus() self.check_and_accept_offer(content, md) cstream = self.bus.get_object(self.conn.bus_name, content_properties["Streams"][0]) candidates = self.jt2.get_call_remote_transports_dbus() cstream.AddCandidates(candidates, dbus_interface=cs.CALL_STREAM_IFACE_MEDIA) self.q.expect('stream-iq', predicate=self.jp.action_predicate('content-add')) content.Remove(dbus_interface=cs.CALL_CONTENT) self.q.expect('stream-iq', predicate=self.jp.action_predicate('content-remove')) def pickup(self): jt2 = self.jt2 jp = self.jp q = self.q cstream = self.audio_stream remote_handle = self.peer_handle can_change_direction = self.can_change_direction incoming = self.incoming # We pickup the call as we need active state to run this test CallTest.pickup(self) self.test_connect_disconnect_endpoint() # FIXME: This should eventually be break down in smaller test methods # Turn sending off and on again # but first, let's try direction changes requested by the other side if can_change_direction: content_name = jt2.audio_names[0] if incoming: jt2.content_modify(content_name, "initiator", "initiator") else: jt2.content_modify(content_name, "initiator", "responder") o = q.expect('dbus-signal', signal='LocalSendingStateChanged') assertEquals(cs.CALL_SENDING_STATE_PENDING_STOP_SENDING, o.args[0]) cstream.SetSending(False, dbus_interface = cs.CALL_STREAM) o = q.expect('dbus-signal', signal='SendingStateChanged') assertEquals(cs.CALL_STREAM_FLOW_STATE_PENDING_STOP, o.args[0]) cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) o = q.expect('dbus-signal', signal='SendingStateChanged', interface = cs.CALL_STREAM_IFACE_MEDIA) assertEquals(cs.CALL_STREAM_FLOW_STATE_STOPPED, o.args[0]) jt2.content_modify(content_name, "initiator", "both") o = q.expect('dbus-signal', signal='LocalSendingStateChanged') assertEquals(cs.CALL_SENDING_STATE_PENDING_SEND, o.args[0]) cstream.SetSending(True, dbus_interface = cs.CALL_STREAM) ret = q.expect_many( EventPattern('dbus-signal', signal='SendingStateChanged'), EventPattern('dbus-signal', signal='LocalSendingStateChanged')) assertEquals(cs.CALL_STREAM_FLOW_STATE_PENDING_START, ret[0].args[0]) assertEquals(cs.CALL_SENDING_STATE_SENDING, ret[1].args[0]) cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) o = q.expect('dbus-signal', signal='SendingStateChanged', interface = cs.CALL_STREAM_IFACE_MEDIA) assertEquals(cs.CALL_STREAM_FLOW_STATE_STARTED, o.args[0]) stream_props = cstream.GetAll(cs.CALL_STREAM, dbus_interface = dbus.PROPERTIES_IFACE) assertEquals({remote_handle: cs.CALL_SENDING_STATE_SENDING}, stream_props["RemoteMembers"]) assertEquals(cs.CALL_SENDING_STATE_SENDING, stream_props["LocalSendingState"]) cstream.SetSending(False, dbus_interface = cs.CALL_STREAM) ret = q.expect_many( EventPattern('dbus-signal', signal='SendingStateChanged'), EventPattern('dbus-signal', signal='LocalSendingStateChanged')) assertEquals(cs.CALL_STREAM_FLOW_STATE_PENDING_STOP, ret[0].args[0]) assertEquals(cs.CALL_SENDING_STATE_NONE, ret[1].args[0]) cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) o = q.expect('dbus-signal', signal='SendingStateChanged', interface = cs.CALL_STREAM_IFACE_MEDIA) assertEquals(cs.CALL_STREAM_FLOW_STATE_STOPPED, o.args[0]) stream_props = cstream.GetAll(cs.CALL_STREAM, dbus_interface = dbus.PROPERTIES_IFACE) assertEquals({remote_handle: cs.CALL_SENDING_STATE_SENDING}, stream_props["RemoteMembers"]) assertEquals(cs.CALL_SENDING_STATE_NONE, stream_props["LocalSendingState"]) # If possible, test the other side asking us to start then stop sending if can_change_direction: jt2.content_modify(content_name, "initiator", "both") o = q.expect('dbus-signal', signal='LocalSendingStateChanged') assertEquals(cs.CALL_SENDING_STATE_PENDING_SEND, o.args[0]) if incoming: jt2.content_modify(content_name, "initiator", "initiator") else: jt2.content_modify(content_name, "initiator", "responder") o = q.expect('dbus-signal', signal='LocalSendingStateChanged') assertEquals(cs.CALL_SENDING_STATE_NONE, o.args[0]) jt2.content_modify(content_name, "initiator", "both") o = q.expect('dbus-signal', signal='LocalSendingStateChanged') assertEquals(cs.CALL_SENDING_STATE_PENDING_SEND, o.args[0]) cstream.SetSending(True, dbus_interface = cs.CALL_STREAM) ret = q.expect_many( EventPattern('dbus-signal', signal='SendingStateChanged'), EventPattern('dbus-signal', signal='LocalSendingStateChanged')) assertEquals(cs.CALL_STREAM_FLOW_STATE_PENDING_START, ret[0].args[0]) assertEquals(cs.CALL_SENDING_STATE_SENDING, ret[1].args[0]) cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) stream_props = cstream.GetAll(cs.CALL_STREAM, dbus_interface = dbus.PROPERTIES_IFACE) assertEquals({remote_handle: cs.CALL_SENDING_STATE_SENDING}, stream_props["RemoteMembers"]) assertEquals(cs.CALL_SENDING_STATE_SENDING, stream_props["LocalSendingState"]) # Turn receiving off and on again try: cstream.RequestReceiving(remote_handle, False, dbus_interface = cs.CALL_STREAM) assert can_change_direction except dbus.DBusException, e: assertEquals(cs.NOT_CAPABLE, e.get_dbus_name()) assert not can_change_direction if can_change_direction: ret = q.expect_many( EventPattern('dbus-signal', signal='ReceivingStateChanged'), EventPattern('dbus-signal', signal='RemoteMembersChanged'), EventPattern('stream-iq', predicate=jp.action_predicate('content-modify'))) assertEquals(cs.CALL_STREAM_FLOW_STATE_PENDING_STOP, ret[0].args[0]) assert ret[1].args[0].has_key(remote_handle) cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) o = q.expect('dbus-signal', signal='ReceivingStateChanged', interface = cs.CALL_STREAM_IFACE_MEDIA) assertEquals(cs.CALL_STREAM_FLOW_STATE_STOPPED, o.args[0]) stream_props = cstream.GetAll(cs.CALL_STREAM, dbus_interface = dbus.PROPERTIES_IFACE) assertEquals({remote_handle: cs.CALL_SENDING_STATE_NONE}, stream_props["RemoteMembers"]) assertEquals(cs.CALL_SENDING_STATE_SENDING, stream_props["LocalSendingState"]) else: stream_props = cstream.GetAll(cs.CALL_STREAM, dbus_interface = dbus.PROPERTIES_IFACE) assertEquals({remote_handle: cs.CALL_SENDING_STATE_SENDING}, stream_props["RemoteMembers"]) assertEquals(cs.CALL_SENDING_STATE_SENDING, stream_props["LocalSendingState"]) try: cstream.RequestReceiving(remote_handle, True, dbus_interface = cs.CALL_STREAM) assert can_change_direction except dbus.DBusException, e: assertEquals(cs.NOT_CAPABLE, e.get_dbus_name()) assert not can_change_direction if can_change_direction: ret = q.expect_many( EventPattern('dbus-signal', signal='ReceivingStateChanged'), EventPattern('dbus-signal', signal='RemoteMembersChanged'), EventPattern('stream-iq', predicate=jp.action_predicate('content-modify'))) assertEquals(cs.CALL_STREAM_FLOW_STATE_PENDING_START, ret[0].args[0]) assert ret[1].args[0].has_key(remote_handle) assertEquals(cs.CALL_SENDING_STATE_PENDING_SEND, ret[1].args[0][remote_handle]) cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) ret = q.expect_many( EventPattern('dbus-signal', signal='ReceivingStateChanged'), EventPattern('dbus-signal', signal='RemoteMembersChanged')) assertEquals(cs.CALL_STREAM_FLOW_STATE_STARTED, ret[0].args[0]) assert ret[1].args[0].has_key(remote_handle) assertEquals(cs.CALL_SENDING_STATE_SENDING, ret[1].args[0][remote_handle]) stream_props = cstream.GetAll(cs.CALL_STREAM, dbus_interface = dbus.PROPERTIES_IFACE) assertEquals({remote_handle: cs.CALL_SENDING_STATE_SENDING}, stream_props["RemoteMembers"]) assertEquals(cs.CALL_SENDING_STATE_SENDING, stream_props["LocalSendingState"]) if can_change_direction: if incoming: jt2.content_modify(content_name, "initiator", "responder") else: jt2.content_modify(content_name, "initiator", "initiator") ret = q.expect_many( EventPattern('dbus-signal', signal='ReceivingStateChanged'), EventPattern('dbus-signal', signal='RemoteMembersChanged')) assertEquals(cs.CALL_STREAM_FLOW_STATE_PENDING_STOP, ret[0].args[0]) assert ret[1].args[0].has_key(remote_handle) assertEquals(cs.CALL_SENDING_STATE_NONE, ret[1].args[0][remote_handle]) cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) o = q.expect('dbus-signal', signal='ReceivingStateChanged') assertEquals(cs.CALL_STREAM_FLOW_STATE_STOPPED, o.args[0]) jt2.content_modify(content_name, "initiator", "both") ret = q.expect_many( EventPattern('dbus-signal', signal='ReceivingStateChanged'), EventPattern('dbus-signal', signal='RemoteMembersChanged')) assertEquals(cs.CALL_STREAM_FLOW_STATE_PENDING_START, ret[0].args[0]) assert ret[1].args[0].has_key(remote_handle) assertEquals(cs.CALL_SENDING_STATE_SENDING, ret[1].args[0][remote_handle]) cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) o = q.expect('dbus-signal', signal='ReceivingStateChanged') assertEquals(cs.CALL_STREAM_FLOW_STATE_STARTED, o.args[0]) try: self.test_content_addition() except DBusException, e: assertEquals(cs.NOT_AVAILABLE, e.get_dbus_name()) assert not jp.can_do_video() if __name__ == '__main__': test_all_dialects( partial(run_call_test, klass=CallBasicsTest, incoming=True)) test_all_dialects( partial(run_call_test, klass=CallBasicsTest, incoming=False)) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/google-relay.py����������������������������������������0000664�0001750�0001750�00000036246�12332441362�025246� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test getting relay from Google jingleinfo """ import config if not config.GOOGLE_RELAY_ENABLED: print "NOTE: built with --disable-google-relay" raise SystemExit(77) from functools import partial from gabbletest import exec_test, make_result_iq, sync_stream, \ GoogleXmlStream, disconnect_conn from servicetest import make_channel_proxy, \ EventPattern, call_async, sync_dbus, assertEquals, assertLength import jingletest2 import gabbletest import constants as cs import dbus import ns import config from twisted.words.protocols.jabber.client import IQ from twisted.web import http from httptest import listen_http from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) # A real request/response looks like this: # # GET /create_session HTTP/1.1 # Connection: Keep-Alive # Content-Length: 0 # Host: relay.l.google.com # User-Agent: farsight-libjingle # X-Google-Relay-Auth: censored # X-Talk-Google-Relay-Auth: censored # # HTTP/1.1 200 OK # Content-Type: text/plain # Date: Tue, 03 Mar 2009 18:33:28 GMT # Server: MediaProxy # Cache-Control: private, x-gzip-ok="" # Transfer-Encoding: chunked # # c3 # relay.ip=74.125.47.126 # relay.udp_port=19295 # relay.tcp_port=19294 # relay.ssltcp_port=443 # stun.ip=74.125.47.126 # stun.port=19302 # username=censored # password=censored # magic_cookie=censored # # 0 response_template = """c3 relay.ip=127.0.0.1 relay.udp_port=11111 relay.tcp_port=22222 relay.ssltcp_port=443 stun.ip=1.2.3.4 stun.port=12345 username=UUUUUUUU%d password=PPPPPPPP%d magic_cookie=MMMMMMMM """ def handle_request(req, n): req.setResponseCode(http.OK) req.setHeader("Content-Type", "text/plain") req.write(response_template % (n, n)) req.finish() TOO_SLOW_CLOSE = 1 TOO_SLOW_REMOVE_SELF = 2 TOO_SLOW_DISCONNECT = 3 TOO_SLOW_DISCONNECT_IMMEDIATELY = 4 def test(q, bus, conn, stream, incoming=True, too_slow=None, use_call=False): jp = jingletest2.JingleProtocol031() jt = jingletest2.JingleTest2(jp, conn, q, stream, 'test@localhost', 'foo@bar.com/Foo') if use_call: # wjt only updated just about enough of this test for Call to check for # one specific crash, not to verify that it all works... assert incoming assert too_slow in [TOO_SLOW_CLOSE, TOO_SLOW_DISCONNECT] # Tell Gabble we want to use Call. conn.ContactCapabilities.UpdateCapabilities([ (cs.CLIENT + ".CallHandler", [ { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL, cs.CALL_INITIAL_AUDIO: True}, { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL, cs.CALL_INITIAL_VIDEO: True}, ], [ cs.CHANNEL_TYPE_CALL + '/gtalk-p2p', cs.CHANNEL_TYPE_CALL + '/ice', cs.CHANNEL_TYPE_CALL + '/video/h264', ]), ]) # See: http://code.google.com/apis/talk/jep_extensions/jingleinfo.html ji_event = q.expect('stream-iq', query_ns=ns.GOOGLE_JINGLE_INFO, to='test@localhost') # Regression test for a bug where Gabble would crash if it disconnected # before receiving a reply to the google:jingleinfo query. if too_slow == TOO_SLOW_DISCONNECT_IMMEDIATELY: disconnect_conn(q, conn, stream, []) return listen_port = listen_http(q, 0) jingleinfo = make_result_iq(stream, ji_event.stanza) stun = jingleinfo.firstChildElement().addElement('stun') server = stun.addElement('server') server['host'] = 'resolves-to-1.2.3.4' server['udp'] = '12345' expected_stun_server = '1.2.3.4' expected_stun_port = 12345 # This bit is undocumented... but it has the same format as what we get # from Google Talk servers: # <iq to="censored" from="censored" id="73930208084" type="result"> # <query xmlns="google:jingleinfo"> # <stun> # <server host="stun.l.google.com" udp="19302"/> # <server host="stun4.l.google.com" udp="19302"/> # <server host="stun3.l.google.com" udp="19302"/> # <server host="stun1.l.google.com" udp="19302"/> # <server host="stun2.l.google.com" udp="19302"/> # </stun> # <relay> # <token>censored</token> # <server host="relay.google.com" udp="19295" tcp="19294" # tcpssl="443"/> # </relay> # </query> # </iq> relay = jingleinfo.firstChildElement().addElement('relay') relay.addElement('token', content='jingle all the way') server = relay.addElement('server') server['host'] = '127.0.0.1' server['udp'] = '11111' server['tcp'] = '22222' server['tcpssl'] = '443' # The special regression-test build of Gabble parses this attribute, # because we can't listen on port 80 server['gabble-test-http-port'] = str(listen_port.getHost().port) stream.send(jingleinfo) jingleinfo = None # Spoof some jingle info. This is a regression test for # <https://bugs.freedesktop.org/show_bug.cgi?id=34048>. We assert that # Gabble has ignored this stuff later. iq = IQ(stream, 'set') iq['from'] = "evil@evil.net" query = iq.addElement((ns.GOOGLE_JINGLE_INFO, "query")) stun = query.addElement('stun') server = stun.addElement('server') server['host'] = '6.6.6.6' server['udp'] = '6666' relay = query.addElement('relay') relay.addElement('token', content='mwohahahahaha') server = relay.addElement('server') server['host'] = '127.0.0.1' server['udp'] = '666' server['tcp'] = '999' server['tcpssl'] = '666' stream.send(iq) jt.send_presence_and_caps() remote_handle = conn.RequestHandles(cs.HT_CONTACT, ["foo@bar.com/Foo"])[0] self_handle = conn.GetSelfHandle() req_pattern = EventPattern('http-request', method='GET', path='/create_session') if incoming: # Remote end calls us jt.incoming_call() if use_call: def looks_like_a_call_to_me(event): channels, = event.args path, props = channels[0] return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_CALL new_channels = q.expect('dbus-signal', signal='NewChannels', predicate=looks_like_a_call_to_me) path = new_channels.args[0][0][0] media_chan = bus.get_object(conn.bus_name, path) else: # FIXME: these signals are not observable by real clients, since they # happen before NewChannels. # The caller is in members # We're pending because of remote_handle mc, _, e = q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=[u'', [remote_handle], [], [], [], 0, 0]), EventPattern('dbus-signal', signal='MembersChanged', args=[u'', [], [], [self_handle], [], remote_handle, cs.GC_REASON_INVITED]), EventPattern('dbus-signal', signal='NewSessionHandler')) media_chan = make_channel_proxy(conn, mc.path, 'Channel.Interface.Group') media_iface = make_channel_proxy(conn, mc.path, 'Channel.Type.StreamedMedia') else: call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: remote_handle, }) ret, old_sig, new_sig = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('dbus-signal', signal='NewChannel', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args), EventPattern('dbus-signal', signal='NewChannels', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args[0][0][1].values()), ) path = ret.value[0] media_chan = make_channel_proxy(conn, path, 'Channel.Interface.Group') media_iface = make_channel_proxy(conn, path, 'Channel.Type.StreamedMedia') call_async(q, media_iface, 'RequestStreams', remote_handle, [cs.MEDIA_STREAM_TYPE_AUDIO]) e = q.expect('dbus-signal', signal='NewSessionHandler') req1 = q.expect('http-request', method='GET', path='/create_session') req2 = q.expect('http-request', method='GET', path='/create_session') if too_slow is not None: test_too_slow(q, bus, conn, stream, req1, req2, media_chan, too_slow) return if incoming: assertLength(0, media_iface.ListStreams()) # Accept the call. media_chan.AddMembers([self_handle], '') # In response to the streams call, we now have two HTTP requests # (for RTP and RTCP) handle_request(req1.request, 0) handle_request(req2.request, 1) if incoming: # We accepted the call, and it should get a new, bidirectional stream # now that the relay info request has finished. This tests against a # regression of bug #24023. q.expect('dbus-signal', signal='StreamAdded', args=[1, remote_handle, cs.MEDIA_STREAM_TYPE_AUDIO]) q.expect('dbus-signal', signal='StreamDirectionChanged', args=[1, cs.MEDIA_STREAM_DIRECTION_BIDIRECTIONAL, 0]) else: # Now that we have the relay info, RequestStreams can return q.expect('dbus-return', method='RequestStreams') session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() e = q.expect('dbus-signal', signal='NewStreamHandler') stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') # Exercise channel properties channel_props = media_chan.GetAll( cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE) assert channel_props['TargetHandle'] == remote_handle assert channel_props['TargetHandleType'] == cs.HT_CONTACT assert channel_props['TargetID'] == 'foo@bar.com' assert channel_props['Requested'] == (not incoming) # The new API for STUN servers etc. sh_props = stream_handler.GetAll( cs.STREAM_HANDLER, dbus_interface=dbus.PROPERTIES_IFACE) assert sh_props['NATTraversal'] == 'gtalk-p2p' assert sh_props['CreatedLocally'] == (not incoming) # If Gabble has erroneously paid attention to the contact evil@evil.net who # sent us a google:jingleinfo stanza, this assertion will fail. assertEquals([(expected_stun_server, expected_stun_port)], sh_props['STUNServers']) credentials_used = {} credentials = {} for relay in sh_props['RelayInfo']: assert relay['ip'] == '127.0.0.1', sh_props['RelayInfo'] assert relay['type'] in ('udp', 'tcp', 'tls') assert relay['component'] in (1, 2) if relay['type'] == 'udp': assert relay['port'] == 11111, sh_props['RelayInfo'] elif relay['type'] == 'tcp': assert relay['port'] == 22222, sh_props['RelayInfo'] elif relay['type'] == 'tls': assert relay['port'] == 443, sh_props['RelayInfo'] assert relay['username'][:8] == 'UUUUUUUU', sh_props['RelayInfo'] assert relay['password'][:8] == 'PPPPPPPP', sh_props['RelayInfo'] assert relay['password'][8:] == relay['username'][8:], \ sh_props['RelayInfo'] assert (relay['password'][8:], relay['type']) not in credentials_used credentials_used[(relay['password'][8:], relay['type'])] = 1 credentials[(relay['component'], relay['type'])] = relay['password'][8:] assert (1, 'udp') in credentials assert (1, 'tcp') in credentials assert (1, 'tls') in credentials assert (2, 'udp') in credentials assert (2, 'tcp') in credentials assert (2, 'tls') in credentials assert ('0', 'udp') in credentials_used assert ('0', 'tcp') in credentials_used assert ('0', 'tls') in credentials_used assert ('1', 'udp') in credentials_used assert ('1', 'tcp') in credentials_used assert ('1', 'tls') in credentials_used # consistency check, since we currently reimplement Get separately for k in sh_props: assert sh_props[k] == stream_handler.Get( 'org.freedesktop.Telepathy.Media.StreamHandler', k, dbus_interface=dbus.PROPERTIES_IFACE), k media_chan.RemoveMembers([self_handle], '') if incoming: q.expect_many( EventPattern('stream-iq', predicate=lambda e: e.query is not None and e.query.name == 'jingle' and e.query['action'] == 'session-terminate'), EventPattern('dbus-signal', signal='Closed'), ) else: # We haven't sent a session-initiate, so we shouldn't expect to send a # session-terminate. q.expect('dbus-signal', signal='Closed') # Tests completed, close the connection def test_too_slow(q, bus, conn, stream, req1, req2, media_chan, too_slow): """ Regression test for a bug where if the channel was closed before the HTTP responses arrived, the responses finally arriving crashed Gabble. """ # User gets bored, and ends the call. e = EventPattern('dbus-signal', signal='Closed', path=media_chan.object_path) if too_slow == TOO_SLOW_CLOSE: call_async(q, media_chan, 'Close', dbus_interface=cs.CHANNEL) elif too_slow == TOO_SLOW_REMOVE_SELF: media_chan.RemoveMembers([conn.GetSelfHandle()], "", dbus_interface=cs.CHANNEL_IFACE_GROUP) elif too_slow == TOO_SLOW_DISCONNECT: disconnect_conn(q, conn, stream, [e]) try: media_chan.GetMembers() except dbus.DBusException, e: # This should fail because the object's gone away, not because # Gabble's crashed. assert cs.UNKNOWN_METHOD == e.get_dbus_name(), \ "maybe Gabble crashed? %s" % e else: # Gabble will probably also crash in a moment, because the http # request callbacks will be called after the channel's meant to # have died, which will cause the channel to try to call methods on # the (finalized) connection. assert False, "the channel should be dead by now" return q.expect_many(e) # Now Google answers! handle_request(req1.request, 2) handle_request(req2.request, 3) # Make a misc method call to check that Gabble's still alive. sync_dbus(bus, q, conn) def exec_relay_test(incoming, too_slow=None, use_call=False): exec_test( partial(test, incoming=incoming, too_slow=too_slow, use_call=use_call), protocol=GoogleXmlStream) if __name__ == '__main__': exec_relay_test(True) exec_relay_test(False) exec_relay_test(True, TOO_SLOW_CLOSE) exec_relay_test(False, TOO_SLOW_CLOSE) exec_relay_test(True, TOO_SLOW_REMOVE_SELF) exec_relay_test(False, TOO_SLOW_REMOVE_SELF) exec_relay_test(True, TOO_SLOW_DISCONNECT) exec_relay_test(False, TOO_SLOW_DISCONNECT) exec_relay_test(True, TOO_SLOW_DISCONNECT_IMMEDIATELY) if config.CHANNEL_TYPE_CALL_ENABLED: exec_relay_test(True, TOO_SLOW_CLOSE, use_call=True) exec_relay_test(True, TOO_SLOW_DISCONNECT, use_call=True) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/__init__.py��������������������������������������������0000644�0001750�0001750�00000000405�12225363340�024401� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Without this, caps/jingle-caps.py can't include jingle.jingletest2. # # I guess the rationale for requiring an __init__.py at # <http://docs.python.org/tutorial/modules.html#packages> makes sense, but it # was still kind of a pain. __all__ = ['jingletest2'] �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/call-muc-cancel.py�������������������������������������0000664�0001750�0001750�00000001374�12225363340�025572� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test closing the muc channel while a muji request is in flight """ from gabbletest import exec_test, disconnect_conn from servicetest import call_async import constants as cs from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) muc = "muji@test" def run_cancel_test(q, bus, conn, stream): call_async (q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: muc, cs.CALL_INITIAL_AUDIO: True, }, byte_arrays = True) q.expect('stream-presence', to = muc + "/test") disconnect_conn(q, conn, stream) if __name__ == '__main__': exec_test (run_cancel_test) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/decloak-peer.py����������������������������������������0000664�0001750�0001750�00000004272�12332441362�025205� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test use-case when client attempts to call an unsubscribed contact. Gabble should ask them to "de-cloak". """ from gabbletest import exec_test from servicetest import (make_channel_proxy, call_async, sync_dbus, assertEquals, assertLength) from jingletest2 import JingleProtocol031, JingleTest2 import dbus import constants as cs import ns from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test(q, bus, conn, stream): jp = JingleProtocol031() jt = JingleTest2(jp, conn, q, stream, 'test@localhost', 'foo@bar.com/Foo') jt2 = JingleTest2(jp, conn, q, stream, 'test@localhost', 'foo2@bar.com/Foo') # Make gabble think this is a different client jt2.remote_caps['node'] = 'http://example.com/fake-client1' run_test(q, bus, conn, stream, jt, True) run_test(q, bus, conn, stream, jt2, False) def run_test(q, bus, conn, stream, jt, decloak_allowed): """ Requests streams on a media channel to jt.remote_jid without having their presence at all. """ request = dbus.Dictionary({ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: jt.peer, }, signature='sv') path, props = conn.CreateChannel(request, dbus_interface=cs.CONN_IFACE_REQUESTS) media_iface = make_channel_proxy(conn, path, 'Channel.Type.StreamedMedia') handle = props[cs.TARGET_HANDLE] call_async(q, media_iface, 'RequestStreams', handle, [cs.MEDIA_STREAM_TYPE_AUDIO]) e = q.expect('stream-presence', to=jt.peer_bare_jid, presence_type=None) nodes = [ node for node in e.stanza.elements(uri=ns.TEMPPRES, name='temppres') ] assertLength(1, nodes) assertEquals('media', nodes[0].getAttribute('reason')) if decloak_allowed: jt.send_presence_and_caps() # RequestStreams should now happily complete q.expect('dbus-return', method='RequestStreams') else: q.expect('dbus-error', method='RequestStreams', name=cs.OFFLINE) if __name__ == '__main__': exec_test(test, timeout=10) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/test-outgoing-iceudp.py��������������������������������0000664�0001750�0001750�00000013410�12332441362�026723� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test outgoing call using ICE-UDP transport mechanism. """ from gabbletest import exec_test, sync_stream from servicetest import ( wrap_channel, make_channel_proxy, EventPattern, call_async, assertEquals) import gabbletest import dbus import time from twisted.words.xish import xpath import ns import constants as cs from jingletest2 import * from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def worker(jp, q, bus, conn, stream): jp.features.remove(ns.GOOGLE_P2P) jp.features.append(ns.JINGLE_TRANSPORT_ICEUDP) jt2 = JingleTest2(jp, conn, q, stream, 'test@localhost', 'foo@bar.com/Foo') jt2.prepare() remote_handle = conn.RequestHandles(cs.HT_CONTACT, ["foo@bar.com/Foo"])[0] call_async(q, conn, 'RequestChannel', cs.CHANNEL_TYPE_STREAMED_MEDIA, 0, 0, True) ret, old_sig, new_sig = q.expect_many( EventPattern('dbus-return', method='RequestChannel'), EventPattern('dbus-signal', signal='NewChannel', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args), EventPattern('dbus-signal', signal='NewChannels', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args[0][0][1].values()), ) path = ret.value[0] chan = wrap_channel(bus.get_object(conn.bus_name, path), 'StreamedMedia') chan.StreamedMedia.RequestStreams(remote_handle, [cs.MEDIA_STREAM_TYPE_AUDIO]) # S-E gets notified about new session handler, and calls Ready on it e = q.expect('dbus-signal', signal='NewSessionHandler') assert e.args[1] == 'rtp' # The 'nat-traversal' tp property should be "ice-udp" hrggh = chan.ListProperties(dbus_interface=cs.TP_AWKWARD_PROPERTIES) id = [x for x, name, _, _ in hrggh if name == 'nat-traversal'][0] nrgrg = chan.GetProperties([id], dbus_interface=cs.TP_AWKWARD_PROPERTIES) _, nat_traversal = nrgrg[0] assertEquals('ice-udp', nat_traversal) session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() e = q.expect('dbus-signal', signal='NewStreamHandler') stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') stream_handler.NewNativeCandidate("fake", jt2.get_remote_transports_dbus()) stream_handler.Ready(jt2.get_audio_codecs_dbus()) stream_handler.StreamState(2) e = q.expect('stream-iq', predicate=jp.action_predicate('session-initiate')) # The session-initiate "MUST include a <transport/> child element qualified # by the [ice-udp] namespace" node = xpath.queryForNodes("/iq/jingle/content/transport[@xmlns='%s']" % ns.JINGLE_TRANSPORT_ICEUDP, e.stanza)[0] jt2.parse_session_initiate(e.query) # ...which SHOULD contain the higher-priority ICE candidates. We supplied # one candidate, so... assertEquals('username', node['ufrag']) assertEquals('password', node['pwd']) node = [ x for x in node.children if type(x) != unicode ][0] assertEquals('candidate', node.name) assert node['foundation'] is not None stream.send(jp.xml(jp.ResultIq('test@localhost', e.stanza, []))) # Make sure that it doesn't send a duplicate of our one ICE candidate here. ti_event = [ EventPattern('stream-iq', predicate=jp.action_predicate('transport-info')) ] q.forbid_events(ti_event) sync_stream(q, stream) q.unforbid_events(ti_event) # XEP-0166 6.4 Negotiation: "The allowable negotiations include: # Exchanging particular transport candidates via the transport-info action." candidate = ( "192.168.0.69", # host 668, # port 0, # protocol = TP_MEDIA_STREAM_BASE_PROTO_UDP "RTP", # protocol subtype "AVP", # profile 1.0, # preference 0, # transport type = TP_MEDIA_STREAM_TRANSPORT_TYPE_LOCAL, "username", "password" ) transport = jp.TransportIceUdp([candidate]) node = jp.SetIq(jt2.peer, jt2.jid, [ jp.Jingle(jt2.sid, jt2.peer, 'transport-info', [ jp.Content('Audio', 'initiator', 'both', transport = transport) ]) ]) stream.send(jp.xml(node)) candidate_e, result_e = q.expect_many( EventPattern('dbus-signal', signal='AddRemoteCandidate'), EventPattern('stream-iq', iq_type='result')) fake_, (returned_candidate,) = candidate_e.args assertEquals(candidate, returned_candidate[1:]) candidate = ( "192.168.0.69", # host 670, # port 0, # protocol = TP_MEDIA_STREAM_BASE_PROTO_UDP "RTP", # protocol subtype "AVP", # profile 1.0, # preference 0, # transport type = TP_MEDIA_STREAM_TRANSPORT_TYPE_LOCAL, "username", "password" ) transport = jp.TransportIceUdp([candidate]) # It is also valid to send transports in the accept. # This is what pidgin does. node = jp.SetIq(jt2.peer, jt2.jid, [ jp.Jingle(jt2.sid, jt2.peer, 'session-accept', [ jp.Content('Audio', 'initiator', 'both', jp.Description('audio', [ jp.PayloadType(name, str(rate), str(id), parameters) for (name, id, rate, parameters) in jt2.audio_codecs ]), transport) ]) ]) stream.send(jp.xml(node)) candidate_e, result_e = q.expect_many( EventPattern('dbus-signal', signal='AddRemoteCandidate'), EventPattern('stream-iq', iq_type='result')) fake_, (returned_candidate,) = candidate_e.args assertEquals(candidate, returned_candidate[1:]) chan.Close() e = q.expect('stream-iq', predicate=jp.action_predicate('session-terminate')) def test031(q, bus, conn, stream): return worker(JingleProtocol031(),q, bus, conn, stream) if __name__ == '__main__': exec_test(test031) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/test-content-adding-removal.py�������������������������0000664�0001750�0001750�00000014742�12332441362�030173� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test content adding and removal during the session. We start session with only one stream, then add one more, then remove the first one and lastly remove the second stream, which closes the session. """ from gabbletest import make_result_iq, sync_stream from servicetest import ( wrap_channel, make_channel_proxy, assertEquals, EventPattern) from jingletest2 import ( JingleTest2, test_dialects, JingleProtocol031, JingleProtocol015, ) import constants as cs from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def gabble_terminates(jp, q, bus, conn, stream): test(jp, q, bus, conn, stream, False) def peer_terminates(jp, q, bus, conn, stream): test(jp, q, bus, conn, stream, True) def test(jp, q, bus, conn, stream, peer_removes_final_content): jt = JingleTest2(jp, conn, q, stream, 'test@localhost', 'foo@bar.com/Foo') jt.prepare() handle = conn.RequestHandles(cs.HT_CONTACT, [jt.peer])[0] path = conn.RequestChannel( cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.HT_CONTACT, handle, True) chan = wrap_channel(bus.get_object(conn.bus_name, path), 'StreamedMedia') chan.StreamedMedia.RequestStreams(handle, [cs.MEDIA_STREAM_TYPE_AUDIO]) # S-E gets notified about new session handler, and calls Ready on it e = q.expect('dbus-signal', signal='NewSessionHandler') assert e.args[1] == 'rtp' session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() e = q.expect('dbus-signal', signal='NewStreamHandler') stream_id = e.args[1] stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) # Before sending the initiate, request another stream chan.StreamedMedia.RequestStreams(handle, [cs.MEDIA_STREAM_TYPE_VIDEO]) e = q.expect('dbus-signal', signal='NewStreamHandler') stream_id2 = e.args[1] stream_handler2 = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') stream_handler2.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) # Before the CM can initiate session, we modify a stream direction. This # should result in a no-op since there's no need to inform the peer of # change. chan.StreamedMedia.RequestStreamDirection(stream_id2, cs.MEDIA_STREAM_DIRECTION_RECEIVE) # We set both streams as ready, which will trigger the session initiate stream_handler.Ready(jt.get_audio_codecs_dbus()) stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) stream_handler2.Ready(jt.get_audio_codecs_dbus()) stream_handler2.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) # We changed our mind locally, don't want video chan.StreamedMedia.RemoveStreams([stream_id2]) e = q.expect('stream-iq', predicate=jp.action_predicate('session-initiate')) stream.send(make_result_iq(stream, e.stanza)) jt.parse_session_initiate(e.query) # Gabble sends content-remove for the video stream... e2 = q.expect('stream-iq', predicate=jp.action_predicate('content-remove')) # ...but before the peer notices, they accept the call. jt.accept() # Only now the remote end removes the video stream; if gabble mistakenly # marked it as accepted on session acceptance, it'll crash right about # now. If it's good, stream will be really removed, and # we can proceed. stream.send(make_result_iq(stream, e2.stanza)) q.expect('dbus-signal', signal='StreamRemoved') # Actually, we *do* want video! chan.StreamedMedia.RequestStreams(handle, [cs.MEDIA_STREAM_TYPE_VIDEO]) e = q.expect('dbus-signal', signal='NewStreamHandler') stream2_id = e.args[1] stream_handler2 = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') stream_handler2.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) stream_handler2.Ready(jt.get_audio_codecs_dbus()) stream_handler2.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) e = q.expect('stream-iq', predicate=jp.action_predicate('content-add')) c = e.query.firstChildElement() assertEquals('initiator', c['creator']) stream.send(make_result_iq(stream, e.stanza)) # Peer accepts jt.content_accept(e.query, 'video') # Let's start sending and receiving video! q.expect_many( EventPattern('dbus-signal', signal='SetStreamPlaying', args=[True]), EventPattern('dbus-signal', signal='SetStreamSending', args=[True]), ) # Now, the call draws to a close. # We first remove the original stream chan.StreamedMedia.RemoveStreams([stream_id]) e = q.expect('stream-iq', predicate=jp.action_predicate('content-remove')) content_remove_ack = make_result_iq(stream, e.stanza) if peer_removes_final_content: # The peer removes the final countdo^W content. From a footnote (!) in # XEP 0166: # If the content-remove results in zero content definitions for the # session, the entity that receives the content-remove SHOULD send # a session-terminate action to the other party (since a session # with no content definitions is void). # So, Gabble should respond to the content-remove with a # session-terminate. node = jp.SetIq(jt.peer, jt.jid, [ jp.Jingle(jt.sid, jt.peer, 'content-remove', [ jp.Content(c['name'], c['creator'], c['senders']) ]) ]) stream.send(jp.xml(node)) else: # The Telepathy client removes the second stream; Gabble should # terminate the session rather than sending a content-remove. chan.StreamedMedia.RemoveStreams([stream2_id]) st, closed = q.expect_many( EventPattern('stream-iq', predicate=jp.action_predicate('session-terminate')), # Gabble shouldn't wait for the peer to ack the terminate before # considering the call finished. EventPattern('dbus-signal', signal='Closed', path=path)) # Only now does the peer ack the content-remove. This serves as a # regression test for contents outliving the session; if the content didn't # die properly, this crashed Gabble. stream.send(content_remove_ack) sync_stream(q, stream) # The peer can ack the terminate too, just for completeness. stream.send(make_result_iq(stream, st.stanza)) if __name__ == '__main__': test_dialects(gabble_terminates, [JingleProtocol015, JingleProtocol031]) test_dialects(peer_terminates, [JingleProtocol015, JingleProtocol031]) ������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/stream-errors-on-terminate.py��������������������������0000664�0001750�0001750�00000012136�12332441362�030055� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test StreamError events and on session terminate, both directions. """ import dbus from gabbletest import make_result_iq, sync_stream, exec_test from servicetest import ( make_channel_proxy, unwrap, EventPattern, assertEquals, assertLength) from jingletest2 import JingleTest2, JingleProtocol031 import constants as cs from twisted.words.xish import xpath from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def _session_terminate_predicate(event, msg): reason = xpath.queryForNodes("/iq" "/jingle[@action='session-terminate']" "/reason/failed-application", event.stanza) reason_text = xpath.queryForString("/iq/jingle/reason/text", event.stanza) return reason is not None and reason_text == msg def _test_terminate_reason(jp, q, bus, conn, stream, incoming): jt = JingleTest2(jp, conn, q, stream, 'test@localhost', 'foo@bar.com/Foo') jt.prepare() self_handle = conn.GetSelfHandle() remote_handle = conn.RequestHandles(cs.HT_CONTACT, [jt.peer])[0] if incoming: jt.incoming_call() else: ret = conn.Requests.CreateChannel( { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: remote_handle, cs.INITIAL_AUDIO: True }) nc, e = q.expect_many( EventPattern('dbus-signal', signal='NewChannel', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args), EventPattern('dbus-signal', signal='NewSessionHandler')) path = nc.args[0] media_chan = make_channel_proxy(conn, path, 'Channel.Interface.Group') media_iface = make_channel_proxy(conn, path, 'Channel.Type.StreamedMedia') # S-E was notified about new session handler, and calls Ready on it session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() nsh_event = q.expect('dbus-signal', signal='NewStreamHandler') # S-E gets notified about a newly-created stream stream_handler = make_channel_proxy(conn, nsh_event.args[0], 'Media.StreamHandler') group_props = media_chan.GetAll( cs.CHANNEL_IFACE_GROUP, dbus_interface=dbus.PROPERTIES_IFACE) if incoming: assertEquals([remote_handle], group_props['Members']) assertEquals(unwrap(group_props['LocalPendingMembers']), [(self_handle, remote_handle, cs.GC_REASON_INVITED, '')]) else: assertEquals([self_handle], group_props['Members']) streams = media_chan.ListStreams( dbus_interface=cs.CHANNEL_TYPE_STREAMED_MEDIA) stream_id = streams[0][0] stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) stream_handler.Ready(jt.dbusify_codecs([("FOO", 5, 8000, {})])) msg = u"None of the codecs are good for us, damn!" expected_events = [] if incoming: q.expect('dbus-signal', signal='SetRemoteCodecs') stream_handler.Error(cs.MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED, msg) expected_events = [EventPattern( "stream-iq", iq_type="set", predicate=lambda x: _session_terminate_predicate(x, msg))] rejector = self_handle else: stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) session_initiate = q.expect( 'stream-iq', predicate=jp.action_predicate('session-initiate')) q.expect('dbus-signal', signal='MembersChanged', path=path, args=['', [], [], [], [remote_handle], self_handle, cs.GC_REASON_INVITED]) jt.parse_session_initiate(session_initiate.query) stream.send(jp.xml(jp.ResultIq('test@localhost', session_initiate.stanza, []))) jt.terminate('failed-application', msg) rejector = remote_handle expected_events += [ EventPattern('dbus-signal', signal='StreamError', interface=cs.CHANNEL_TYPE_STREAMED_MEDIA, path=path, args=[stream_id, cs.MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED, msg]), EventPattern('dbus-signal', signal='MembersChanged', interface=cs.CHANNEL_IFACE_GROUP, path=path, args=[msg, [], [self_handle, remote_handle], [], [], rejector, cs.GC_REASON_ERROR])] q.expect_many(*expected_events) q.expect('dbus-signal', signal='Closed', path=path) def test_terminate_outgoing(jp, q, bus, conn, stream): _test_terminate_reason(jp, q, bus, conn, stream, False) def test_terminate_incoming(jp, q, bus, conn, stream): _test_terminate_reason(jp, q, bus, conn, stream, True) if __name__ == '__main__': for f in (test_terminate_incoming, test_terminate_outgoing): exec_test( lambda q, b, c, s: f(JingleProtocol031(), q, b, c, s)) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/misuse.py����������������������������������������������0000664�0001750�0001750�00000003172�12332441362�024155� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test misuse of the streamed media API, which should return error messages rather than asserting Gabble. """ from dbus import DBusException from servicetest import make_channel_proxy, wrap_channel, assertEquals from gabbletest import exec_test from jingletest2 import JingleTest2, JingleProtocol031 import constants as cs from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test(q, bus, conn, stream): jp = JingleProtocol031() remote_jid = 'foo@example.com/misc' jt = JingleTest2(jp, conn, q, stream, 'test@localhost', remote_jid) jt.prepare() self_handle = conn.GetSelfHandle() remote_handle = conn.RequestHandles(cs.HT_CONTACT, [remote_jid])[0] path, _ = conn.Requests.CreateChannel({ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: remote_handle}) chan = wrap_channel(bus.get_object(conn.bus_name, path), 'StreamedMedia') # In Gabble, the StreamedMedia channel is secretly also the SessionHandler. # Let's make up a proxy and call some methods on it. They should fail # gracefully, rather than crashing Gabble. session_handler = make_channel_proxy(conn, path, 'Media.SessionHandler') try: session_handler.Ready() except DBusException, e: assertEquals(cs.NOT_AVAILABLE, e.get_dbus_name()) try: session_handler.Error(0, "slowing down but with a sense of speeding up") except DBusException, e: assertEquals(cs.NOT_AVAILABLE, e.get_dbus_name()) if __name__ == '__main__': exec_test(test) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/payload-types.py���������������������������������������0000664�0001750�0001750�00000007160�12332441362�025444� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Regression test for https://bugs.freedesktop.org/show_bug.cgi?id=18918 """ import dbus from gabbletest import exec_test from servicetest import wrap_channel, make_channel_proxy import jingletest2 import constants as cs from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test(q, bus, conn, stream): jp = jingletest2.JingleProtocol031() jt = jingletest2.JingleTest2(jp, conn, q, stream, 'test@localhost', 'foo@bar.com/Foo') self_handle = conn.GetSelfHandle() jt.send_presence_and_caps() handle = conn.RequestHandles(cs.HT_CONTACT, [jt.peer])[0] path = conn.RequestChannel( cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.HT_CONTACT, handle, True) channel = wrap_channel(bus.get_object(conn.bus_name, path), 'StreamedMedia') # Test that codec parameters are correctly sent in <parameter> children of # <payload-type> rather than as attributes of the latter. channel.StreamedMedia.RequestStreams(handle, [cs.MEDIA_STREAM_TYPE_AUDIO]) # S-E gets notified about new session handler, and calls Ready on it e = q.expect('dbus-signal', signal='NewSessionHandler') assert e.args[1] == 'rtp' session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() e = q.expect('dbus-signal', signal='NewStreamHandler') stream_id = e.args[1] stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) codecs = dbus.Array( [ (96, 'speex', 0, 16000, 0, {'vbr': 'on'}) ], signature='(usuuua{ss})') stream_handler.Ready(codecs) stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) e = q.expect('stream-iq') content = list(e.query.elements())[0] assert content.name == 'content' for child in content.elements(): if child.name == 'description': description = child break assert description is not None # there should be one <payload-type> tag for speex: assert len(list(description.elements())) == 1 payload_type = list(description.elements())[0] assert payload_type.name == 'payload-type' assert payload_type['name'] == 'speex' # the vbr parameter should not be an attribute on the <payload-type>, but # a child <parameter/> tag assert 'vbr' not in payload_type.attributes assert len(list(payload_type.elements())) == 1 parameter = list(payload_type.elements())[0] assert parameter.name == 'parameter' assert parameter['name'] == 'vbr' assert parameter['value'] == 'on' channel.Close() # Test that codec parameters are correctly extracted from <parameter> # children of <payload-type> rather than from attributes of the latter. jt.audio_codecs = [ ('GSM', 3, 8000, {'misc': 'other'}) ] jt.incoming_call() e = q.expect('dbus-signal', signal='NewSessionHandler') assert e.args[1] == 'rtp' session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() e = q.expect('dbus-signal', signal='NewStreamHandler') stream_id = e.args[1] stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') stream_handler.Ready( dbus.Array( [], signature='(usuuua{ss})')) e = q.expect('dbus-signal', signal='SetRemoteCodecs') for codec in e.args[0]: id, name, type, rate, channels, parameters = codec assert len(parameters) == 1, parameters assert parameters['misc'] == 'other', parameters if __name__ == '__main__': exec_test(test) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/call-dtmf.py�������������������������������������������0000664�0001750�0001750�00000016756�12225363340�024527� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test DMTF events in a Call channel """ import dbus from dbus.exceptions import DBusException from functools import partial from servicetest import call_async, EventPattern, assertEquals from jingletest2 import test_all_dialects from call_helper import CallTest, run_call_test import constants as cs from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) class CallDtmfTest(CallTest): def test_dtmf(self): content = self.audio_content q = self.q # The Stream_ID is specified to be ignored; we use 666 here. assertEquals(False, content.Get(cs.CALL_CONTENT_IFACE_DTMF, 'CurrentlySendingTones', dbus_interface=dbus.PROPERTIES_IFACE)); call_async(q, content.DTMF, 'StartTone', 3) q.expect_many( EventPattern('dbus-signal', signal='DTMFChangeRequested', args = [3, cs.CALL_SENDING_STATE_PENDING_SEND]), EventPattern('dbus-return', method='StartTone'), ) assertEquals(True, content.Get(cs.CALL_CONTENT_IFACE_DTMF, 'CurrentlySendingTones', dbus_interface=dbus.PROPERTIES_IFACE)); content.Media.AcknowledgeDTMFChange(3, cs.CALL_SENDING_STATE_SENDING) q.expect('dbus-signal', signal='SendingTones', args=['3']) call_async(q, content.DTMF, 'StopTone') q.expect_many( EventPattern('dbus-signal', signal='DTMFChangeRequested', args = [3, cs.CALL_SENDING_STATE_PENDING_STOP_SENDING]), EventPattern('dbus-return', method='StopTone'), ) call_async(q, content.Media, 'AcknowledgeDTMFChange', 3, cs.CALL_SENDING_STATE_NONE) q.expect_many( EventPattern('dbus-signal', signal='StoppedTones', args=[False]), EventPattern('dbus-return', method='AcknowledgeDTMFChange'), ) assertEquals(False, content.Get(cs.CALL_CONTENT_IFACE_DTMF, 'CurrentlySendingTones', dbus_interface=dbus.PROPERTIES_IFACE)); call_async(q, content.DTMF, 'MultipleTones', '123') q.expect_many( EventPattern('dbus-return', method='MultipleTones'), EventPattern('dbus-signal', signal='DTMFChangeRequested', args = [1, cs.CALL_SENDING_STATE_PENDING_SEND]), ) content.Media.AcknowledgeDTMFChange(1, cs.CALL_SENDING_STATE_SENDING) q.expect('dbus-signal', signal='SendingTones', args=['123']) q.expect('dbus-signal', signal='DTMFChangeRequested', args = [1, cs.CALL_SENDING_STATE_PENDING_STOP_SENDING]) content.Media.AcknowledgeDTMFChange(1, cs.CALL_SENDING_STATE_NONE) q.expect_many( EventPattern('dbus-signal', signal='DTMFChangeRequested', args = [2, cs.CALL_SENDING_STATE_PENDING_SEND]), ) content.Media.AcknowledgeDTMFChange(2, cs.CALL_SENDING_STATE_SENDING) q.expect('dbus-signal', signal='SendingTones', args=['23']), q.expect('dbus-signal', signal='DTMFChangeRequested', args = [2, cs.CALL_SENDING_STATE_PENDING_STOP_SENDING]) content.Media.AcknowledgeDTMFChange(2, cs.CALL_SENDING_STATE_NONE) q.expect_many( EventPattern('dbus-signal', signal='DTMFChangeRequested', args = [3, cs.CALL_SENDING_STATE_PENDING_SEND]), ) content.Media.AcknowledgeDTMFChange(3, cs.CALL_SENDING_STATE_SENDING) q.expect('dbus-signal', signal='SendingTones', args=['3']), q.expect('dbus-signal', signal='DTMFChangeRequested', args = [3, cs.CALL_SENDING_STATE_PENDING_STOP_SENDING]) content.Media.AcknowledgeDTMFChange(3, cs.CALL_SENDING_STATE_NONE) q.expect_many( EventPattern('dbus-signal', signal='StoppedTones', args=[False]) ) call_async(q, content.DTMF, 'MultipleTones', '1,1' * 100) q.expect_many( EventPattern('dbus-signal', signal='DTMFChangeRequested', args = [1, cs.CALL_SENDING_STATE_PENDING_SEND]), EventPattern('dbus-return', method='MultipleTones'), ) call_async(q, content.DTMF, 'MultipleTones', '9') q.expect('dbus-error', method='MultipleTones', name=cs.SERVICE_BUSY) call_async(q, content.DTMF, 'StartTone', 9) q.expect('dbus-error', method='StartTone', name=cs.SERVICE_BUSY) call_async(q, content.DTMF, 'StopTone') q.expect_many( EventPattern('dbus-signal', signal='DTMFChangeRequested', args = [1, cs.CALL_SENDING_STATE_PENDING_STOP_SENDING]), EventPattern('dbus-return', method='StopTone'), ) call_async(q, content.Media, 'AcknowledgeDTMFChange', 1, cs.CALL_SENDING_STATE_NONE) q.expect_many( EventPattern('dbus-signal', signal='StoppedTones', args=[True]), EventPattern('dbus-return', method='AcknowledgeDTMFChange'), ) call_async(q, content.DTMF, 'MultipleTones', '1w2') q.expect_many( EventPattern('dbus-signal', signal='DTMFChangeRequested', args = [1, cs.CALL_SENDING_STATE_PENDING_SEND]), EventPattern('dbus-return', method='MultipleTones'), ) content.Media.AcknowledgeDTMFChange(1, cs.CALL_SENDING_STATE_SENDING) q.expect('dbus-signal', signal='SendingTones', args=['1w2']), q.expect('dbus-signal', signal='DTMFChangeRequested', args = [1, cs.CALL_SENDING_STATE_PENDING_STOP_SENDING]) call_async(q, content.Media, 'AcknowledgeDTMFChange', 1, cs.CALL_SENDING_STATE_NONE) q.expect_many( EventPattern('dbus-signal', signal='TonesDeferred', args=['2']), EventPattern('dbus-signal', signal='StoppedTones', args=[False]), EventPattern('dbus-return', method='AcknowledgeDTMFChange'), ) assertEquals('2', content.Get(cs.CALL_CONTENT_IFACE_DTMF, 'DeferredTones', dbus_interface=dbus.PROPERTIES_IFACE)); call_async(q, content.DTMF, 'StartTone', 7) q.expect_many( EventPattern('dbus-signal', signal='DTMFChangeRequested', args = [7, cs.CALL_SENDING_STATE_PENDING_SEND]), EventPattern('dbus-return', method='StartTone'), ) # Checked that DeferredTones is properly reset assertEquals('', content.Get(cs.CALL_CONTENT_IFACE_DTMF, 'DeferredTones', dbus_interface=dbus.PROPERTIES_IFACE)); content.Media.AcknowledgeDTMFChange(7, cs.CALL_SENDING_STATE_SENDING) q.expect('dbus-signal', signal='SendingTones', args=['7']), call_async(q, content.DTMF, 'StopTone') q.expect_many( EventPattern('dbus-signal', signal='DTMFChangeRequested', args = [7, cs.CALL_SENDING_STATE_PENDING_STOP_SENDING]), EventPattern('dbus-return', method='StopTone'), ) content.Media.AcknowledgeDTMFChange(7, cs.CALL_SENDING_STATE_NONE) q.expect('dbus-signal', signal='StoppedTones', args=[False]) def pickup(self): CallTest.pickup(self) self.test_dtmf() if __name__ == '__main__': test_all_dialects( partial(run_call_test, klass=CallDtmfTest, incoming=False)) ������������������telepathy-gabble-0.18.3/tests/twisted/jingle/incoming-call-stream-error.py��������������������������0000664�0001750�0001750�00000007774�12332441362�030020� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test handling of Error() call on stream handler. This tests a regression in which MembersChanged was emitted with reason other than GC_REASON_ERROR. """ from servicetest import EventPattern, assertEquals, make_channel_proxy from jingletest2 import JingleTest2, test_all_dialects import constants as cs from twisted.words.xish import xpath from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def _session_terminate_predicate(event, reason, msg, jp): matches = jp.match_jingle_action(event.query, 'session-terminate') if matches and jp.is_modern_jingle(): reason = xpath.queryForNodes("/iq" "/jingle[@action='session-terminate']" "/reason/%s" % reason, event.stanza) reason_text = xpath.queryForString("/iq/jingle/reason/text", event.stanza) return bool(reason) and reason_text == msg return matches def _test(jp, q, bus, conn, stream, jingle_reason, group_change_reason, stream_error): jt = JingleTest2(jp, conn, q, stream, 'test@localhost', 'foo@bar.com/Foo') jt.prepare() self_handle = conn.GetSelfHandle() remote_handle = conn.RequestHandles(cs.HT_CONTACT, ["foo@bar.com/Foo"])[0] # Ring ring! jt.incoming_call() new_channel, new_session_handler = q.expect_many( EventPattern('dbus-signal', signal='NewChannel', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args), EventPattern('dbus-signal', signal='NewSessionHandler')) assertEquals(cs.CHANNEL_TYPE_STREAMED_MEDIA, new_channel.args[1]) assertEquals(cs.HT_CONTACT, new_channel.args[2]) assertEquals(remote_handle, new_channel.args[3]) assertEquals('rtp', new_session_handler.args[1]) channel_path = new_channel.args[0] # Client calls Ready on new session handler. session_handler = make_channel_proxy( conn, new_session_handler.args[0], 'Media.SessionHandler') session_handler.Ready() # Client gets notified about a newly created stream... new_stream_handler = q.expect('dbus-signal', signal='NewStreamHandler') stream_id = new_stream_handler.args[1] stream_handler = make_channel_proxy( conn, new_stream_handler.args[0], 'Media.StreamHandler') stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) stream_handler.Ready(jt.dbusify_codecs([("FOO", 5, 8000, {})])) q.expect('dbus-signal', signal='SetRemoteCodecs') msg = u"o noes" # ...but something goes wrong. stream_handler.Error(stream_error, msg) q.expect("stream-iq", iq_type="set", predicate=lambda x: _session_terminate_predicate(x, jingle_reason, msg, jp)) # Bye bye members. mc = q.expect('dbus-signal', signal='MembersChanged', interface=cs.CHANNEL_IFACE_GROUP, path=channel_path, args=[msg, [], [self_handle, remote_handle], [], [], self_handle, group_change_reason]) q.expect('dbus-signal', signal='StreamError', interface=cs.CHANNEL_TYPE_STREAMED_MEDIA, args=[stream_id, stream_error, msg]) # Bye bye stream q.expect('dbus-signal', signal='Close') q.expect('dbus-signal', signal='StreamRemoved') # Bye bye channel. q.expect('dbus-signal', signal='Closed') q.expect('dbus-signal', signal='ChannelClosed') def test_connection_error(jp, q, bus, conn, stream): _test(jp, q, bus, conn, stream, "connectivity-error", cs.GC_REASON_ERROR, cs.MEDIA_STREAM_ERROR_NETWORK_ERROR) def test_codec_negotiation_fail(jp, q, bus, conn, stream): _test(jp, q, bus, conn, stream, "failed-application", cs.GC_REASON_ERROR, cs.MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED) if __name__ == '__main__': test_all_dialects(test_connection_error) test_all_dialects(test_codec_negotiation_fail) ����telepathy-gabble-0.18.3/tests/twisted/jingle/session-id-collision.py��������������������������������0000664�0001750�0001750�00000002656�12332441362�026724� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Regression test for a bug where Gabble did not namespace session IDs by the peer, leading to hilarity (and possible DOSing) if two peers picked the same sid. """ from jingletest2 import JingleTest2, test_all_dialects import constants as cs from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test(jp, q, bus, conn, stream): jt1 = JingleTest2(jp, conn, q, stream, 'test@localhost', 'edgar@collabora.co.uk/Monitor') jt2 = JingleTest2(jp, conn, q, stream, 'test@localhost', 'wcc@collabora.co.uk/Pillow') jt1.prepare() jt2.send_presence_and_caps() # Two peers happen to pick the same Jingle session ID jt1.sid = '1' jt2.sid = '1' jt1.incoming_call() q.expect('dbus-signal', signal='NewChannel', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args) # If Gabble confuses the two sessions, it'll NAK the IQ rather than # realising this is a new call. jt2.incoming_call() q.expect('dbus-signal', signal='NewChannel', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args) # On the other hand, if the same person calls twice with the same sid, # Gabble _should_ NAK the second s-i. jt2.incoming_call() q.expect('stream-iq', iq_type='error', predicate=jp.action_predicate('session-initiate')) if __name__ == '__main__': test_all_dialects(test) ����������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/jingletest2.py�����������������������������������������0000664�0001750�0001750�00000076510�12332441362�025110� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# New API for making it easier to write Jingle tests. The idea # is not so much to hide away the details (this makes tests # unreadable), but to make the expressions denser and more concise. # Helper classes support different dialects so the test can # be invoked for different (possibly all) dialects. from functools import partial from twisted.words.xish import domish, xpath import random from gabbletest import sync_stream, exec_test from servicetest import EventPattern import dbus import ns import os import constants as cs class JingleProtocol(object): """ Defines a simple DSL for constructing Jingle messages. """ def __init__(self, dialect): self.dialect = dialect self.id_seq = 0 def _simple_xml(self, node): "Construct domish.Element tree from tree of tuples" name, namespace, attribs, children = node el = domish.Element((namespace, name)) for key, val in attribs.items(): el[key] = val for c in children: if isinstance(c, tuple): el.addChild(self._simple_xml(c)) elif isinstance(c, unicode): el.addContent(c) else: raise ValueError("invalid child object %r of type %r" % (c, type(c))) return el def xml(self, node): "Returns XML from tree of tuples" return self._simple_xml(node).toXml() def Iq(self, type, id, frm, to, children): "Creates an IQ element" if not id: id = 'seq%d' % self.id_seq self.id_seq += 1 return ('iq', 'jabber:client', { 'type': type, 'from': frm, 'to': to, 'id': id }, children) def SetIq(self, frm, to, children): "Creates a set IQ element" return self.Iq('set', None, frm, to, children) def ResultIq(self, to, iq, children): "Creates a result IQ element" return self.Iq('result', iq['id'], iq['to'], to, children) def ErrorIq(self, iq, errtype, errchild): "Creates an error IQ element, and includes the original stanza" return self.Iq('error', iq['id'], iq['to'], iq['from'], [ iq.firstChildElement(), ('error', None, { 'type': errtype, 'xmlns': ns.STANZA, }, [ errchild ]) ]) def PayloadType(self, name, rate, id, parameters={}, **kw): "Creates a <payload-type> element" kw['name'] = name kw['rate'] = rate kw['id'] = id children = [self.Parameter(name, value) for name, value in parameters.iteritems()] return ('payload-type', None, kw, children) def Parameter(self, name, value): "Creates a <parameter> element" return ('parameter', None, {'name': name, 'value': value}, []) def TransportGoogleP2PCall (self, username, password, call_remote_candidates=[]): candidates = [] for (component, host, port, props) in call_remote_candidates: candidates.append(("candidate", None, { "name": "rtp", "address": host, "port": str(port), "protocol": "udp", "preference": str(props["priority"] / 65536.0), "type": ["INVALID NONE", "local", "stun", "INVALID PEER RFLX", "relay"][props["type"]], "network": "0", "generation": "0",# Increment this yourself if you care. "component": str(component), # 1 is rtp, 2 is rtcp "username": props.get("username", username), "password": props.get("password", password), }, [])) #NOTE: subtype and profile are unused return ('transport', ns.GOOGLE_P2P, {}, candidates) def TransportGoogleP2P(self, remote_transports=[]): """ Creates a <transport> element for Google P2P transport. If remote_transports is present, and of the form [(host, port, proto, subtype, profile, pref, transtype, user, pwd)] (basically a list of Media_Stream_Handler_Transport without the component number) then it will be converted to xml and added. """ candidates = [] for i, (host, port, proto, subtype, profile, pref, transtype, user, pwd ) in enumerate(remote_transports): candidates.append(("candidate", None, { "name": "rtp", "address": host, "port": str(port), "protocol": ["udp", "tcp"][proto], "preference": str(pref), "type": ["local", "stun", "relay"][transtype], "network": "0", "generation": "0",# Increment this yourself if you care. "component": "1", # 1 is rtp, 2 is rtcp "username": user, "password": pwd, }, [])) #NOTE: subtype and profile are unused return ('transport', ns.GOOGLE_P2P, {}, candidates) def TransportIceUdp(self, remote_transports=[]): """ Creates a <transport> element for ICE-UDP transport. If remote_transports is present, and of the form [(host, port, proto, subtype, profile, pref, transtype, user, pwd)] (basically a list of Media_Stream_Handler_Transport without the component number) then it will be converted to xml and added. """ candidates = [] attrs = {} for (host, port, proto, subtype, profile, pref, transtype, user, pwd ) in remote_transports: if "ufrag" not in attrs: attrs = {"ufrag": user, "pwd": pwd} else: assert (user == attrs["ufrag"] and pwd == attrs["pwd"] ), "user and pwd should be the same across all candidates." node = ("candidate", None, { # ICE-CORE says it can be arbitrary string, even though XEP # gives an int as an example. "foundation": "fake", "ip": host, "port": str(port), "protocol": ["udp", "tcp"][proto], # Gabble multiplies by 65536 so we should too. "priority": str(int(pref * 65536)), "type": ["host", "srflx", "srflx"][transtype], "network": "0", "generation": "0",# Increment this yourself if you care. "component": "1", # 1 is rtp, 2 is rtcp }, []) #NOTE: subtype and profile are unused candidates.append(node) return ('transport', ns.JINGLE_TRANSPORT_ICEUDP, attrs, candidates) def Presence(self, frm, to, caps): "Creates <presence> stanza with specified capabilities" children = [] if caps: children = [ ('c', ns.CAPS, caps, []) ] return ('presence', 'jabber:client', { 'from': frm, 'to': to }, children) def Query(self, node, xmlns, children): "Creates <query> element" attrs = {} if node: attrs['node'] = node return ('query', xmlns, attrs, children) def Feature(self, var): "Creates <feature> element" return ('feature', None, { 'var': var }, []) def action_predicate(self, action): def f(e): return self.match_jingle_action(e.query, action) return f def match_jingle_action(self, q, action): return q is not None and q.name == 'jingle' and q['action'] == action def _extract_session_id(self, query): return query['sid'] def validate_session_initiate(self, query): raise NotImplementedError() def can_do_video(self): return True def can_do_video_only(self): return self.can_do_video() def separate_contents(self): return True def has_mutable_streams(self): return True def is_modern_jingle(self): return False def rtp_info_event(self, name): return None def rtp_info_event_list(self, name): e = self.rtp_info_event(name) return [e] if e is not None else [] class GtalkProtocol03(JingleProtocol): features = [ ns.GOOGLE_FEAT_VOICE, ns.GOOGLE_FEAT_VIDEO ] def __init__(self): JingleProtocol.__init__(self, 'gtalk-v0.3') def _action_map(self, action): map = { 'session-initiate': 'initiate', 'session-terminate': 'terminate', 'session-accept': 'accept', 'transport-info': 'candidates' } if action in map: return map[action] else: return action def Jingle(self, sid, initiator, action, children): action = self._action_map(action) return ('session', ns.GOOGLE_SESSION, { 'type': action, 'initiator': initiator, 'id': sid }, children) def PayloadType(self, name, rate, id, parameters={}, **kw): p = JingleProtocol.PayloadType(self, name, rate, id, parameters, **kw) if "type" in kw: namespaces = { "audio": ns.GOOGLE_SESSION_PHONE, "video": ns.GOOGLE_SESSION_VIDEO, } p = p[:1] + (namespaces[kw["type"]],) + p[2:] return p # Gtalk has only one content, and <content> node is implicit. Also it # never mixes payloads and transport information. It's up to the call of # this function to ensure it never calls it with both mixed def Content(self, name, creator, senders=None, description=None, transport=None): # Normally <content> has <description> and <transport>, but we only # use <description> unless <transport> has candidates. assert description == None or len(transport[3]) == 0 if description != None: return description else: assert len(transport[3]) == 1, \ "gtalk 0.3 only lets you send one candidate at a time." \ "You sent %r" % [transport] return transport[3][0] def Description(self, type, children): if type == 'audio': namespace = ns.GOOGLE_SESSION_PHONE elif type == 'video': namespace = ns.GOOGLE_SESSION_VIDEO else: namespace = 'unexistent-namespace' return ('description', namespace, {}, children) def match_jingle_action(self, q, action): action = self._action_map(action) return q is not None and q.name == 'session' and q['type'] == action def _extract_session_id(self, query): return query['id'] def can_do_video_only(self): return False def validate_session_initiate(self, query): sid = self._extract_session_id(query) # No transport in GTalk03 assert xpath.queryForNodes('/session/transport', query) == None # Exactly one description in Gtalk03 descs = xpath.queryForNodes('/session/description', query) assert len(descs) == 1 desc = descs[0] # the ds is either audio or video assert desc.uri in [ ns.GOOGLE_SESSION_PHONE, ns.GOOGLE_SESSION_VIDEO ] if desc.uri == ns.GOOGLE_SESSION_VIDEO: # If it's a video call there should be some audio codecs as well assert xpath.queryForNodes( '/session/description/payload-type[@xmlns="%s"]' % ns.GOOGLE_SESSION_PHONE, query) return (sid, ['fake-audio'], ['fake-video']) else: return (sid, ['fake-audio'], []) def separate_contents(self): return False def has_mutable_streams(self): return False class GtalkProtocol04(JingleProtocol): features = [ ns.GOOGLE_FEAT_VOICE, ns.GOOGLE_P2P ] def __init__(self): JingleProtocol.__init__(self, 'gtalk-v0.4') def _action_map(self, action): map = { 'session-initiate': 'initiate', 'session-terminate': 'terminate', 'session-accept': 'accept', } if action in map: return map[action] else: return action def Jingle(self, sid, initiator, action, children): # ignore Content and go straight for its children if len(children) == 1 and children[0][0] == 'dummy-content': # Either have just a transport or a description + transport # without candidates children = children[0][3] action = self._action_map(action) return ('session', ns.GOOGLE_SESSION, { 'type': action, 'initiator': initiator, 'id': sid }, children) # hacky: parent Jingle node should just pick up our children def Content(self, name, creator, senders=None, description=None, transport=None): return ('dummy-content', None, {}, [node for node in [description, transport] if node != None]) def Description(self, type, children): return ('description', ns.GOOGLE_SESSION_PHONE, {}, children) def match_jingle_action(self, q, action): action = self._action_map(action) return q is not None and q.name == 'session' and q['type'] == action def _extract_session_id(self, query): return query['id'] def validate_session_initiate(self, query): # FIXME: validate it! return (self._extract_session_id(query), ['fake-audio'], []) def can_do_video(self): return False class JingleProtocol015(JingleProtocol): features = [ ns.GOOGLE_P2P, ns.JINGLE_015, ns.JINGLE_015_AUDIO, ns.JINGLE_015_VIDEO ] def __init__(self): JingleProtocol.__init__(self, 'jingle-v0.15') def Jingle(self, sid, initiator, action, children): return ('jingle', ns.JINGLE_015, { 'action': action, 'initiator': initiator, 'sid': sid }, children) # Note: senders weren't mandatory in this dialect def Content(self, name, creator, senders = None, description=None, transport=None): attribs = { 'name': name, 'creator': creator } if senders: attribs['senders'] = senders return ('content', None, attribs, [node for node in [description, transport] if node != None]) def Description(self, type, children): if type == 'audio': namespace = ns.JINGLE_015_AUDIO elif type == 'video': namespace = ns.JINGLE_015_VIDEO else: namespace = 'unexistent-namespace' return ('description', namespace, { 'type': type }, children) def validate_session_initiate(self, query): contents = xpath.queryForNodes( '/jingle[@xmlns="%s"]/content' % ns.JINGLE_015, query) audio, video = [], [] for c in contents: a_desc = xpath.queryForNodes( '/content/description[@xmlns="%s"]' % ns.JINGLE_015_AUDIO, c) v_desc = xpath.queryForNodes( '/content/description[@xmlns="%s"]' % ns.JINGLE_015_VIDEO, c) if a_desc is not None: assert len(a_desc) == 1, c.toXml() assert v_desc is None audio.append(c['name']) elif v_desc is not None: assert len(v_desc) == 1, c.toXml() assert a_desc is None video.append(c['name']) else: assert False, c.toXml() assert len(audio) + len(video) > 0, query.toXml() return (self._extract_session_id(query), audio, video) class JingleProtocol031(JingleProtocol): features = [ ns.JINGLE, ns.JINGLE_RTP, ns.JINGLE_RTP_AUDIO, ns.JINGLE_RTP_VIDEO, ns.GOOGLE_P2P ] def __init__(self): JingleProtocol.__init__(self, 'jingle-v0.31') def Jingle(self, sid, initiator, action, children): return ('jingle', ns.JINGLE, { 'action': action, 'initiator': initiator, 'sid': sid }, children) def Content(self, name, creator, senders=None, description=None, transport=None): if not senders: senders = 'both' return ('content', None, { 'name': name, 'creator': creator, 'senders': senders }, [node for node in [description, transport] if node != None]) def Description(self, type, children): return ('description', ns.JINGLE_RTP, { 'media': type }, children) def is_modern_jingle(self): return True def rtp_info_event(self, name): def p(e): query = e.query if not self.match_jingle_action(query, 'session-info'): return False n = query.firstChildElement() return n is not None and n.uri == ns.JINGLE_RTP_INFO_1 and \ n.name == name return EventPattern('stream-iq', predicate=p) def validate_session_initiate(self, query): contents = xpath.queryForNodes( '/jingle[@xmlns="%s"]/content' % ns.JINGLE, query) audio, video = [], [] for c in contents: descs = xpath.queryForNodes( '/content/description[@xmlns="%s"]' % ns.JINGLE_RTP, c) assert len(descs) == 1, c.toXml() d = descs[0] if d['media'] == 'audio': audio.append(c['name']) elif d['media'] == 'video': video.append(c['name']) else: assert False, c.toXml() assert len(audio) + len(video) > 0, query.toXml() return (self._extract_session_id(query), audio, video) class JingleTest2(object): # Default caps for the remote end remote_caps = { 'ext': '', 'ver': '0.0.0', 'node': 'http://example.com/fake-client0' } # Default audio codecs for the remote end audio_codecs = [ ('GSM', 3, 8000, {}), ('PCMA', 8, 8000, {}), ('PCMU', 0, 8000, {}) ] # Default video codecs for the remote end. I have no idea what's # a suitable value here... video_codecs = [ ('WTF', 96, 90000, {}) ] ufrag = "SessionUfrag" pwd = "SessionPwd" # Default candidates for the remote end remote_call_candidates = [# Local candidates (1, "192.168.0.1", 666, {"type": cs.CALL_STREAM_CANDIDATE_TYPE_HOST, #"Foundation":, "protocol": cs.MEDIA_STREAM_BASE_PROTO_UDP, "priority": 10000, #"base-ip": }), (2, "192.168.0.1", 667, {"type": cs.CALL_STREAM_CANDIDATE_TYPE_HOST, #"Foundation":, "protocol": cs.MEDIA_STREAM_BASE_PROTO_UDP, "priority": 10000, #"base-ip": }), # STUN candidates have their own ufrag (1, "168.192.0.1", 10666, {"type": cs.CALL_STREAM_CANDIDATE_TYPE_SERVER_REFLEXIVE, #"Foundation":, "protocol": cs.MEDIA_STREAM_BASE_PROTO_UDP, "priority": 100, #"base-ip":, "username": "STUNRTPUfrag", "password": "STUNRTPPwd" }), (2, "168.192.0.1", 10667, {"type": cs.CALL_STREAM_CANDIDATE_TYPE_SERVER_REFLEXIVE, #"Foundation":, "protocol": cs.MEDIA_STREAM_BASE_PROTO_UDP, "priority": 100, #"base-ip":, "username": "STUNRTCPUfrag", "password": "STUNRTCPPwd" }), # Candidates found using UPnP or somesuch? (1, "131.111.12.50", 10666, {"type": cs.CALL_STREAM_CANDIDATE_TYPE_HOST, #"Foundation":, "protocol": cs.MEDIA_STREAM_BASE_PROTO_UDP, "priority": 1000, #"base-ip": }), (2, "131.111.12.50", 10667, {"type": cs.CALL_STREAM_CANDIDATE_TYPE_HOST, #"Foundation":, "protocol": cs.MEDIA_STREAM_BASE_PROTO_UDP, "priority": 1000, #"base-ip": }), ] remote_transports = [ ( "192.168.0.1", # host 666, # port 0, # protocol = TP_MEDIA_STREAM_BASE_PROTO_UDP "RTP", # protocol subtype "AVP", # profile 1.0, # preference 0, # transport type = TP_CALL_STREAM_CANDIDATE_TYPE_HOST, "username", "password" ) ] def __init__(self, jp, conn, q, stream, jid, peer): self.jp = jp self.conn = conn self.q = q self.jid = jid self.peer = peer self.peer_bare_jid = peer.split('/', 1)[0] self.stream = stream self.sid = 'sess' + str(int(random.random() * 10000)) def prepare(self, send_presence=True, send_roster=True, events=None): # If we need to override remote caps, feats, codecs or caps, # we should do it prior to calling this method. if events is None: # Catch events: authentication, our presence update, # status connected, vCard query # If we don't catch the vCard query here, it can trip us up later: # http://bugs.freedesktop.org/show_bug.cgi?id=19161 events = self.q.expect_many( EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', query_ns=ns.ROSTER), ) # some Jingle tests care about our roster relationship to the peer if send_roster: roster = events[-1] roster.stanza['type'] = 'result' item = roster.query.addElement('item') item['jid'] = 'publish@foo.com' item['subscription'] = 'from' item = roster.query.addElement('item') item['jid'] = 'subscribe@foo.com' item['subscription'] = 'to' item = roster.query.addElement('item') item['jid'] = 'publish-subscribe@foo.com' item['subscription'] = 'both' self.stream.send(roster.stanza) if send_presence: self.send_presence_and_caps() def send_presence(self): # We need remote end's presence for capabilities self.stream.send(self.jp.xml( self.jp.Presence(self.peer, self.jid, self.remote_caps))) # Gabble doesn't trust it, so makes a disco return self.q.expect('stream-iq', query_ns=ns.DISCO_INFO, to=self.peer) def send_remote_disco_reply(self, query_stanza): self.stream.send(self.jp.xml(self.jp.ResultIq(self.jid, query_stanza, [ self.jp.Query(None, ns.DISCO_INFO, [ self.jp.Feature(x) for x in self.jp.features ]) ]) )) def send_presence_and_caps(self): event = self.send_presence() self.send_remote_disco_reply(event.stanza) # Force Gabble to process the caps before doing any more Jingling sync_stream(self.q, self.stream) def generate_payloads(self, codecs, **kwargs): return [ self.jp.PayloadType(payload_name, str(rate), str(id), parameters, **kwargs) for (payload_name, id, rate, parameters) in codecs ] def generate_contents(self, transports=[]): assert len(self.audio_names + self.video_names) > 0 jp = self.jp assert len(self.video_names) == 0 or jp.can_do_video() contents = [] if not jp.separate_contents() and self.video_names: assert jp.can_do_video() assert self.audio_names payload = self.generate_payloads (self.video_codecs) + \ self.generate_payloads (self.audio_codecs, type="audio") contents.append( jp.Content('stream0', 'initiator', 'both', jp.Description('video', payload), jp.TransportGoogleP2P(transports)) ) else: def mk_content(name, media, codecs): payload = self.generate_payloads (codecs) contents.append( jp.Content(name, 'initiator', 'both', jp.Description(media, payload), jp.TransportGoogleP2P(transports)) ) for name in self.audio_names: mk_content(name, 'audio', self.audio_codecs) for name in self.video_names: mk_content(name, 'video', self.video_codecs) return contents def incoming_call(self, audio = "audio1", video = None): jp = self.jp self.audio_names = [ audio ] if audio != None else [] self.video_names = [ video ] if video != None else [] contents = self.generate_contents() node = jp.SetIq(self.peer, self.jid, [ jp.Jingle(self.sid, self.peer, 'session-initiate', contents), ]) self.stream.send(jp.xml(node)) def parse_session_initiate (self, query): # Validate the session initiate and get some useful info from it self.sid, self.audio_names, self.video_names = \ self.jp.validate_session_initiate(query) def accept(self): jp = self.jp contents = self.generate_contents() node = jp.SetIq(self.peer, self.jid, [ jp.Jingle(self.sid, self.peer, 'session-accept', contents) ]) self.stream.send(jp.xml(node)) def content_accept(self, query, media): """ Accepts a content-add stanza containing a single <content> of the given media type. """ jp = self.jp assert jp.separate_contents() c = query.firstChildElement() if media == 'audio': codecs = self.audio_codecs elif media == 'video': codecs = self.video_codecs else: assert False # Remote end finally accepts node = jp.SetIq(self.peer, self.jid, [ jp.Jingle(self.sid, self.peer, 'content-accept', [ jp.Content(c['name'], c['creator'], c['senders'], jp.Description(media, [ jp.PayloadType(name, str(rate), str(id), parameters) for (name, id, rate, parameters) in codecs ]), jp.TransportGoogleP2P()) ]) ]) self.stream.send(jp.xml(node)) def content_modify(self, name, creator, senders): jp = self.jp assert jp.separate_contents() node = jp.SetIq(self.peer, self.jid, [ jp.Jingle(self.sid, self.peer, 'content-modify', [ jp.Content(name, creator, senders)])]) self.stream.send(jp.xml(node)) def terminate(self, reason=None, text=""): jp = self.jp if reason is not None and jp.is_modern_jingle(): body = [("reason", None, {}, [(reason, None, {}, []), ("text", None, {}, [text]), ] )] else: body = [] iq = jp.SetIq(self.peer, self.jid, [ jp.Jingle(self.sid, self.peer, 'session-terminate', body) ]) self.stream.send(jp.xml(iq)) def result_iq(self, iniq, children = []): jp = self.jp iq = jp.ResultIq(self.peer, {'id': iniq.iq_id, 'to': self.peer}, children) self.stream.send(jp.xml(iq)) def send_remote_candidates_call_xmpp(self, name, creator, candidates=None): jp = self.jp if candidates is None: candidates = self.remote_call_candidates node = jp.SetIq(self.peer, self.jid, [ jp.Jingle(self.sid, self.peer, 'transport-info', [ jp.Content(name, creator, transport=jp.TransportGoogleP2PCall (self.ufrag, self.pwd, candidates)) ] ) ]) self.stream.send(jp.xml(node)) def remote_candidates(self, name, creator): jp = self.jp node = jp.SetIq(self.peer, self.jid, [ jp.Jingle(self.sid, self.peer, 'transport-info', [ jp.Content(name, creator, transport=jp.TransportGoogleP2P (self.remote_transports)) ] ) ]) self.stream.send(jp.xml(node)) def dbusify_codecs(self, codecs): dbussed_codecs = [ (id, name, 0, rate, 0, params ) for (name, id, rate, params) in codecs ] return dbus.Array(dbussed_codecs, signature='(usuuua{ss})') def dbusify_codecs_with_params (self, codecs): return self.dbusify_codecs(codecs) def get_audio_codecs_dbus(self): return self.dbusify_codecs(self.audio_codecs) def get_video_codecs_dbus(self): return self.dbusify_codecs(self.video_codecs) def dbusify_call_codecs(self, codecs): dbussed_codecs = [ (id, name, rate, 0, False, params) for (name, id, rate, params) in codecs ] return dbus.Array(dbussed_codecs, signature='(usuuba{ss})') def dbusify_call_codecs_with_params(self, codecs): return dbusify_call_codecs (self, codecs) def __get_call_audio_codecs_dbus(self): return self.dbusify_call_codecs(self.audio_codecs) def __get_call_video_codecs_dbus(self): return self.dbusify_call_codecs(self.video_codecs) def get_call_audio_md_dbus(self, handle = 0): d = dbus.Dictionary( { cs.CALL_CONTENT_MEDIADESCRIPTION + '.Codecs': self.__get_call_audio_codecs_dbus(), }, signature='sv') if handle != 0: d[cs.CALL_CONTENT_MEDIADESCRIPTION + '.RemoteContact'] = dbus.UInt32 (handle) return d def get_call_video_md_dbus(self, handle = 0): d = dbus.Dictionary( { cs.CALL_CONTENT_MEDIADESCRIPTION + '.Codecs': self.__get_call_video_codecs_dbus(), }, signature='sv') if handle != 0: d[cs.CALL_CONTENT_MEDIADESCRIPTION + '.RemoteContact'] = dbus.UInt32 (handle) return d def get_remote_transports_dbus(self): return dbus.Array([ (dbus.UInt32(1 + i), host, port, proto, subtype, profile, pref, transtype, user, pwd) for i, (host, port, proto, subtype, profile, pref, transtype, user, pwd) in enumerate(self.remote_transports) ], signature='(usuussduss)') def get_call_remote_transports_dbus(self): return dbus.Array(self.remote_call_candidates, signature='(usqa{sv})') def test_dialects(f, dialects, params=None, protocol=None): for dialect in dialects: exec_test(partial(f, dialect()), params=params, protocol=protocol) def test_all_dialects(f, params=None, protocol=None): dialectmap = { "jingle015": JingleProtocol015, "jingle031": JingleProtocol031, "gtalk03": GtalkProtocol03, "gtalk04": GtalkProtocol04 } dialects = [] jd = os.getenv("JINGLE_DIALECTS") if jd == None: dialects = dialectmap.values() else: for d in jd.split (','): dialects.append(dialectmap[d]) test_dialects(f, dialects, params=params, protocol=protocol) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/call-hold-av.py����������������������������������������0000664�0001750�0001750�00000135310�12332441362�025113� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test the Hold API. """ import dbus from dbus.exceptions import DBusException from functools import partial from servicetest import (call_async, EventPattern, assertEquals, assertLength, sync_dbus) from jingletest2 import test_all_dialects from gabbletest import sync_stream from call_helper import CallTest, run_call_test import constants as cs from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) class CallHoldAVTest(CallTest): # Audio and Video test initial_audio = True initial_video = True def mutable_stream_tests(self): jp = self.jp jt = self.jt2 q = self.q bus = self.bus conn = self.conn stream = self.stream chan = self.chan # ---- Test 13: while the call's on hold, we add a new content --- # We shouldn't go off hold locally as a result, and the new # StreamHandler should tell s-e to hold the stream. pending_hold = [ EventPattern('dbus-signal', signal='HoldStateChanged', predicate=lambda e: e.args[0] == cs.HS_PENDING_HOLD), ] q.forbid_events(pending_hold) content_path = chan.AddContent('added_audio', cs.MEDIA_STREAM_TYPE_AUDIO, cs.MEDIA_STREAM_DIRECTION_BIDIRECTIONAL, dbus_interface=cs.CHANNEL_TYPE_CALL) q.expect ('dbus-signal', signal='ContentAdded') content = bus.get_object (conn.bus_name, content_path) assertEquals (cs.MEDIA_STREAM_TYPE_AUDIO, content.Get(cs.CALL_CONTENT, 'Type', dbus_interface=dbus.PROPERTIES_IFACE)) stream_paths = content.Get(cs.CALL_CONTENT, "Streams", dbus_interface=dbus.PROPERTIES_IFACE) assertLength (1, stream_paths) cstream = bus.get_object (conn.bus_name, stream_paths[0]) md = jt.get_call_audio_md_dbus() [path, _] = content.Get(cs.CALL_CONTENT_IFACE_MEDIA, "MediaDescriptionOffer", dbus_interface=dbus.PROPERTIES_IFACE) offer = bus.get_object (conn.bus_name, path) offer.Accept (md, dbus_interface=cs.CALL_CONTENT_MEDIADESCRIPTION) assertEquals(cs.CALL_STREAM_FLOW_STATE_STOPPED, cstream.Get(cs.CALL_STREAM_IFACE_MEDIA, 'SendingState', dbus_interface=dbus.PROPERTIES_IFACE)) assertEquals(cs.CALL_STREAM_FLOW_STATE_STOPPED, cstream.Get(cs.CALL_STREAM_IFACE_MEDIA, 'ReceivingState', dbus_interface=dbus.PROPERTIES_IFACE)) content_paths = chan.Get(cs.CHANNEL_TYPE_CALL, 'Contents', dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(cs.HS_HELD, chan.Hold.GetHoldState()[0]) sync_dbus(bus, q, conn) # --- Test 14: while the call's on hold, the peer adds a new stream ---- # Again, we shouldn't go off hold locally as a result, and the new # StreamHandler should tell s-e to hold the stream. node = jp.SetIq(jt.peer, jt.jid, [ jp.Jingle(jt.sid, jt.peer, 'content-add', [ jp.Content('videostream', 'initiator', 'both', jp.Description('video', [ jp.PayloadType(name, str(rate), str(id), parameters) for (name, id, rate, parameters) in jt.video_codecs ]), jp.TransportGoogleP2P()) ]) ]) stream.send(jp.xml(node)) e = q.expect ('dbus-signal', signal='ContentAdded') content = bus.get_object (conn.bus_name, e.args[0]) assertEquals (cs.MEDIA_STREAM_TYPE_VIDEO, content.Get(cs.CALL_CONTENT, 'Type', dbus_interface=dbus.PROPERTIES_IFACE)) stream_paths = content.Get(cs.CALL_CONTENT, "Streams", dbus_interface=dbus.PROPERTIES_IFACE) assertLength (1, stream_paths) cstream = bus.get_object (conn.bus_name, stream_paths[0]) md = jt.get_call_video_md_dbus() [path, _] = content.Get(cs.CALL_CONTENT_IFACE_MEDIA, "MediaDescriptionOffer", dbus_interface=dbus.PROPERTIES_IFACE) offer = bus.get_object (conn.bus_name, path) offer.Accept (md, dbus_interface=cs.CALL_CONTENT_MEDIADESCRIPTION) assertEquals(cs.CALL_STREAM_FLOW_STATE_STOPPED, cstream.Get(cs.CALL_STREAM_IFACE_MEDIA, 'SendingState', dbus_interface=dbus.PROPERTIES_IFACE)) assertEquals(cs.CALL_STREAM_FLOW_STATE_STOPPED, cstream.Get(cs.CALL_STREAM_IFACE_MEDIA, 'ReceivingState', dbus_interface=dbus.PROPERTIES_IFACE)) content_paths = chan.Get(cs.CHANNEL_TYPE_CALL, 'Contents', dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(cs.HS_HELD, chan.Hold.GetHoldState()[0]) sync_dbus(bus, q, conn) q.unforbid_events(pending_hold) def initiate(self): CallTest.initiate(self) q = self.q jp = self.jp cstream = self.audio_stream chan = self.chan audio_cstream = self.audio_stream recv_state = audio_cstream.GetAll(cs.CALL_STREAM_IFACE_MEDIA, dbus_interface=dbus.PROPERTIES_IFACE)["ReceivingState"] send_state = audio_cstream.GetAll(cs.CALL_STREAM_IFACE_MEDIA, dbus_interface=dbus.PROPERTIES_IFACE)["SendingState"] assertEquals (cs.CALL_STREAM_FLOW_STATE_STOPPED, recv_state) assertEquals (cs.CALL_STREAM_FLOW_STATE_STOPPED, send_state) video_cstream = self.video_stream recv_state = video_cstream.GetAll(cs.CALL_STREAM_IFACE_MEDIA, dbus_interface=dbus.PROPERTIES_IFACE)["ReceivingState"] send_state = video_cstream.GetAll(cs.CALL_STREAM_IFACE_MEDIA, dbus_interface=dbus.PROPERTIES_IFACE)["SendingState"] assertEquals (cs.CALL_STREAM_FLOW_STATE_STOPPED, recv_state) assertEquals (cs.CALL_STREAM_FLOW_STATE_STOPPED, send_state) # These are 0- (for old dialects) or 1- (for new dialects) element lists # that can be splatted into expect_many with * self.hold_event = jp.rtp_info_event_list("hold") self.unhold_event = jp.rtp_info_event_list("unhold") # Before we have accepted any streams, GetHoldState returns Unheld and # unhold is a no-op. assertEquals((cs.HS_UNHELD, cs.HSR_REQUESTED), chan.Hold.GetHoldState()) chan.Hold.RequestHold(False) q.forbid_events(self.hold_event) q.forbid_events(self.unhold_event) assertEquals((cs.HS_UNHELD, cs.HSR_REQUESTED), chan.Hold.GetHoldState()) chan.Hold.RequestHold(False) # Before we have any streams, RequestHold(True) should work because # there are no streams, it should take effect at once. It certainly # shouldn't send anything to the peer. q.forbid_events(self.hold_event) q.forbid_events(self.unhold_event) call_async(q, chan.Hold, 'RequestHold', True) q.expect('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]) q.expect('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]) assertEquals((cs.HS_HELD, cs.HSR_REQUESTED), chan.Hold.GetHoldState()) # If we unhold, it should succeed immediately again, because there are # no resources to reclaim. call_async(q, chan.Hold, 'RequestHold', False) q.expect('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]) q.expect('dbus-signal', signal='HoldStateChanged', args=[cs.HS_UNHELD, cs.HSR_REQUESTED]) assertEquals((cs.HS_UNHELD, cs.HSR_REQUESTED), chan.Hold.GetHoldState()) # Put the call back on hold ... call_async(q, chan.Hold, 'RequestHold', True) q.expect('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]) q.expect('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]) assertEquals((cs.HS_HELD, cs.HSR_REQUESTED), chan.Hold.GetHoldState()) def connect(self): assertEquals((cs.HS_HELD, cs.HSR_REQUESTED), self.chan.Hold.GetHoldState()) assertEquals((cs.HS_HELD, cs.HSR_REQUESTED), self.chan.Hold.GetHoldState()) CallTest.connect(self, expect_after_si=self.hold_event) def accept_outgoing(self): # We are on hold, no states to complete here self.check_channel_state(cs.CALL_STATE_PENDING_INITIATOR) self.chan.Accept(dbus_interface=cs.CHANNEL_TYPE_CALL) self.check_channel_state(cs.CALL_STATE_INITIALISING) def pickup(self): CallTest.pickup(self, held=True) q = self.q stream = self.stream chan = self.chan audio_cstream = self.audio_stream video_cstream = self.video_stream assertEquals((cs.HS_HELD, cs.HSR_REQUESTED), chan.Hold.GetHoldState()) recv_state = audio_cstream.Get(cs.CALL_STREAM_IFACE_MEDIA, "ReceivingState", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals (cs.CALL_STREAM_FLOW_STATE_STOPPED, recv_state) send_state = audio_cstream.Get(cs.CALL_STREAM_IFACE_MEDIA, "SendingState", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals (cs.CALL_STREAM_FLOW_STATE_STOPPED, send_state) recv_state = video_cstream.Get(cs.CALL_STREAM_IFACE_MEDIA, "ReceivingState", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals (cs.CALL_STREAM_FLOW_STATE_STOPPED, recv_state) send_state = video_cstream.Get(cs.CALL_STREAM_IFACE_MEDIA, "SendingState", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals (cs.CALL_STREAM_FLOW_STATE_STOPPED, send_state) # Now we decide we do actually want to speak to them, and unhold. # Ensure that if Gabble sent the <unhold/> stanza too early it's already # arrived. sync_stream(q, stream) q.forbid_events(self.unhold_event) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-return', method='RequestHold', value=()), ) # Ensure that if Gabble sent the <unhold/> stanza too early it's already # arrived. sync_stream(q, stream) q.unforbid_events(self.unhold_event) audio_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) audio_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_UNHELD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), *self.unhold_event ) # Hooray! Now let's check that Hold works properly once the call's fully # established. # ---- Test 1: GetHoldState returns unheld and unhold is a no-op ---- hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_UNHELD, hold_state chan.Hold.RequestHold(False) # ---- Test 2: successful hold ---- call_async(q, chan.Hold, 'RequestHold', True) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-return', method='RequestHold', value=()), *self.hold_event ) audio_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) audio_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), ) # ---- Test 3: GetHoldState returns held and hold is a no-op ---- hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_HELD, hold_state chan.Hold.RequestHold(True) # ---- Test 4: successful unhold ---- q.forbid_events(self.unhold_event) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-return', method='RequestHold', value=()), ) # Ensure that if Gabble sent the <unhold/> stanza too early it's already # arrived. sync_stream(q, stream) q.unforbid_events(self.unhold_event) audio_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) audio_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_UNHELD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), *self.unhold_event ) # ---- Test 5: GetHoldState returns False and unhold is a no-op ---- hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_UNHELD, hold_state chan.Hold.RequestHold(False) # ---- Test 6: 3 parallel calls to hold ---- hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_UNHELD, hold_state call_async(q, chan.Hold, 'RequestHold', True) call_async(q, chan.Hold, 'RequestHold', True) call_async(q, chan.Hold, 'RequestHold', True) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-return', method='RequestHold', value=()), *self.hold_event ) audio_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) audio_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]), ) # ---- Test 7: 3 parallel calls to unhold ---- q.forbid_events(self.unhold_event) call_async(q, chan.Hold, 'RequestHold', False) call_async(q, chan.Hold, 'RequestHold', False) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-return', method='RequestHold', value=()), ) # Ensure that if Gabble sent the <unhold/> stanza too early it's already # arrived. sync_stream(q, stream) q.unforbid_events(self.unhold_event) audio_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) audio_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_UNHELD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), *self.unhold_event ) # ---- Test 8: hold, then change our minds before s-e has responded ---- hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_UNHELD, hold_state call_async(q, chan.Hold, 'RequestHold', True) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), *self.hold_event ) q.forbid_events(self.unhold_event) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), # Gabble shouldn't send <unhold/> here because s-e might have # already relinquished the audio hardware. ) sync_stream(q, stream) q.unforbid_events(self.unhold_event) try: audio_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) except dbus.DBusException, e: assertEquals (cs.INVALID_ARGUMENT, e.get_dbus_name ()) try: audio_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) except dbus.DBusException, e: assertEquals (cs.INVALID_ARGUMENT, e.get_dbus_name ()) try: video_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) except dbus.DBusException, e: assertEquals (cs.INVALID_ARGUMENT, e.get_dbus_name ()) try: video_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) except dbus.DBusException, e: assertEquals (cs.INVALID_ARGUMENT, e.get_dbus_name ()) audio_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) audio_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_UNHELD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), *self.unhold_event ) hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_UNHELD, hold_state # --- Test 9: unhold, then change our minds before s-e has responded ---- # Go to state "held" first call_async(q, chan.Hold, 'RequestHold', True) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-return', method='RequestHold', value=()), *self.hold_event ) audio_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) audio_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]), ) # Actually do test 9 hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_HELD, hold_state # Check that Gabble doesn't send another <hold/>, or send <unhold/> # before we change our minds. q.forbid_events(self.unhold_event + self.hold_event) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), ) call_async(q, chan.Hold, 'RequestHold', True) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), ) audio_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) audio_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]), ) hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_HELD, hold_state sync_stream(q, stream) # ---- Test 10: attempting to unhold fails (both streams) ---- call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-return', method='RequestHold', value=()), ) audio_cstream.ReportSendingFailure(0, "", "", dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.ReportSendingFailure(0, "", "", dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_RESOURCE_NOT_AVAILABLE]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), ) audio_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_RESOURCE_NOT_AVAILABLE]), ) # ---- Test 11: attempting to unhold fails (audio stream) ---- call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-return', method='RequestHold', value=()), ) audio_cstream.ReportReceivingFailure(0, "", "", dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_RESOURCE_NOT_AVAILABLE]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), ) audio_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_RESOURCE_NOT_AVAILABLE]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), ) sync_stream(q, stream) # ---- Test 12: attempting to unhold partially fails (video stream) ---- call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-return', method='RequestHold', value=()), ) video_cstream.ReportReceivingFailure(0, "", "", dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_RESOURCE_NOT_AVAILABLE]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), ) audio_cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) audio_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) video_cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_RESOURCE_NOT_AVAILABLE]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), ) sync_stream(q, stream) q.unforbid_events(self.unhold_event + self.hold_event) if self.jp.has_mutable_streams(): self.mutable_stream_tests() if __name__ == '__main__': test_all_dialects(partial(run_call_test, klass=CallHoldAVTest, incoming=False)) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/preload-caps-crash.py����������������������������������0000644�0001750�0001750�00000003022�12225363340�026310� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Regression test for a crash in which PRESENCE_CAP_GOOGLE_VOICE is preloaded and we don't have any per_channel_manager_caps by the time we receive a call, when called by gtalk2voip.com on behalf of a sipphone.com user. """ import dbus from gabbletest import make_result_iq, exec_test, sync_stream from servicetest import ( make_channel_proxy, unwrap, EventPattern, assertEquals, assertLength) from jingletest2 import JingleTest2, GtalkProtocol03 import constants as cs import ns from twisted.words.xish import xpath class MyJingleTest(JingleTest2): remote_caps = { 'ext': 'sidebar voice-v1', 'node': 'http://www.google.com/xmpp/client/caps', 'ver': '1.0.0.104' } def test(q, bus, conn, stream): jp = GtalkProtocol03() jt = MyJingleTest(jp, conn, q, stream, 'test@localhost', 'foo@gtalk2voip.com') jt.prepare(send_presence=False) # Send the presence from a bare JID to our bare JID... stream.send(jp.xml(jp.Presence('foo@gtalk2voip.com', 'test@localhost', jt.remote_caps))) event = q.expect('stream-iq', query_ns=ns.DISCO_INFO, to='foo@gtalk2voip.com') # ... then immediately send from a bare JID to our full JID stream.send(jp.xml(jp.Presence('foo@gtalk2voip.com', 'test@localhost/test', jt.remote_caps))) stream.send(jp.xml(jp.ResultIq('test@localhost/test', event.stanza, [ jp.Query(None, ns.DISCO_INFO, [ jp.Feature(x) for x in jp.features ]) ]) )) sync_stream(q, stream) if __name__ == '__main__': exec_test(test) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/call-codecoffer.py�������������������������������������0000664�0001750�0001750�00000024372�12332441362�025665� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Testing different methods related to the CodecOffer interface. """ import dbus from dbus.exceptions import DBusException from servicetest import (EventPattern, assertEquals, assertLength, assertNotEquals ) import ns import constants as cs from jingletest2 import JingleTest2, test_dialects, JingleProtocol031 from config import CHANNEL_TYPE_CALL_ENABLED, VOIP_ENABLED if not CHANNEL_TYPE_CALL_ENABLED: print "NOTE: built with --disable-channel-type-call" raise SystemExit(77) if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def check_offer (bus, conn, content): [path, md] = content.Get(cs.CALL_CONTENT_IFACE_MEDIA, "MediaDescriptionOffer", dbus_interface=dbus.PROPERTIES_IFACE) assertNotEquals ("/", path) offer = bus.get_object (conn.bus_name, path) md_property = offer.Get (cs.CALL_CONTENT_MEDIADESCRIPTION, "Codecs", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals (md[cs.CALL_CONTENT_MEDIADESCRIPTION + ".Codecs"], md_property) def accept_offer (q, bus, conn, self_handle, remote_handle, content, md_props, offer_path = None, codecs_changed = True): [path, _] = content.Get (cs.CALL_CONTENT_IFACE_MEDIA, "MediaDescriptionOffer", dbus_interface=dbus.PROPERTIES_IFACE) offer = bus.get_object (conn.bus_name, path) offer.Accept (md_props, dbus_interface=cs.CALL_CONTENT_MEDIADESCRIPTION) current_mds = content.Get (cs.CALL_CONTENT_IFACE_MEDIA, "RemoteMediaDescriptions", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals (md_props[cs.CALL_CONTENT_MEDIADESCRIPTION + '.Codecs'], current_mds[remote_handle][cs.CALL_CONTENT_MEDIADESCRIPTION + '.Codecs']) if codecs_changed: o = q.expect ('dbus-signal', signal='RemoteMediaDescriptionsChanged') assertEquals (md_props[cs.CALL_CONTENT_MEDIADESCRIPTION + '.Codecs'], o.args[0][remote_handle][cs.CALL_CONTENT_MEDIADESCRIPTION + '.Codecs']) def reject_offer (q, bus, conn, content, codecs, offer_path = None): [path, _] = content.Get(cs.CALL_CONTENT_IFACE_MEDIA, "MediaDescriptionOffer", dbus_interface=dbus.PROPERTIES_IFACE) offer = bus.get_object (conn.bus_name, path) offer.Reject ((0, 0, "", ""), dbus_interface=cs.CALL_CONTENT_MEDIADESCRIPTION) def update_codecs(jt2): contents = jt2.generate_contents() node = jt2.jp.SetIq(jt2.peer, jt2.jid, [ jt2.jp.Jingle(jt2.sid, jt2.peer, 'description-info', contents), ]) jt2.stream.send(jt2.jp.xml(node)) def prepare_test(jp, q, bus, conn, stream): remote_jid = 'foo@bar.com/Foo' jt2 = JingleTest2(jp, conn, q, stream, 'test@localhost', remote_jid) jt2.prepare() self_handle = conn.GetSelfHandle() remote_handle = conn.RequestHandles(1, ["foo@bar.com/Foo"])[0] # Advertise that we can do new style calls conn.ContactCapabilities.UpdateCapabilities([ (cs.CLIENT + ".CallHandler", [ { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL, cs.CALL_INITIAL_AUDIO: True}, { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL, cs.CALL_INITIAL_VIDEO: True}, ], [ cs.CHANNEL_TYPE_CALL + '/gtalk-p2p', cs.CHANNEL_TYPE_CALL + '/ice', cs.CHANNEL_TYPE_CALL + '/video/h264', ]), ]) return remote_jid, jt2, self_handle, remote_handle def try_to_access_old_offer(conn, path): try: offer = bus.get_object (conn.bus_name, path) ret = offer.GetAll (cs.CALL_CONTENT_MEDIADESCRIPTION, dbus_interface=dbus.PROPERTIES_IFACE) except Exception, e: pass else: assert False, 'Offer still exists' def test_incoming(jp, q, bus, conn, stream): remote_jid, jt2, self_handle, remote_handle = prepare_test(jp, q, bus, conn, stream) jt2.incoming_call() ret = q.expect_many(EventPattern('dbus-signal', signal='NewChannels', predicate=lambda e: cs.CHANNEL_TYPE_CALL in e.args[0][0][1].values()), EventPattern('dbus-signal', signal='NewMediaDescriptionOffer')) chan = bus.get_object(conn.bus_name, ret[0].args[0][0][0]) properties = chan.GetAll(cs.CHANNEL_TYPE_CALL, dbus_interface=dbus.PROPERTIES_IFACE) content = bus.get_object (conn.bus_name, properties["Contents"][0]) md = jt2.get_call_audio_md_dbus() check_offer(bus, conn, content) accept_offer(q, bus, conn, self_handle, remote_handle, content, md) update_codecs(jt2) signal = q.expect('dbus-signal', signal='NewMediaDescriptionOffer') check_offer(bus, conn, content) reject_offer(q, bus, conn, content, md) update_codecs(jt2) signal = q.expect('dbus-signal', signal='NewMediaDescriptionOffer') check_offer(bus, conn, content) accept_offer(q, bus, conn, self_handle, remote_handle, content, md, codecs_changed = False) update_codecs(jt2) signal = q.expect('dbus-signal', signal='NewMediaDescriptionOffer') check_offer(bus, conn, content) [path, _] = content.Get (cs.CALL_CONTENT_IFACE_MEDIA, "MediaDescriptionOffer", dbus_interface=dbus.PROPERTIES_IFACE) chan.Close(dbus_interface=cs.CHANNEL) signal = q.expect('dbus-signal', signal='ChannelClosed') try_to_access_old_offer(conn, path) try: ret = conn.GetAll (cs.CONN, dbus_interface=dbus.PROPERTIES_IFACE) except Exception, e: print 'Gabble probably crashed' raise e else: # depending on the age of our telepathy-glib, we have at least # SelfHandle, and might also have Interfaces and Status assert len(ret) > 0 def test_outgoing(jp, q, bus, conn, stream): remote_jid, jt2, self_handle, remote_handle = prepare_test(jp, q, bus, conn, stream) # make a new outgoing call conn.CreateChannel({ cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL, cs.TARGET_HANDLE: remote_handle, cs.CALL_INITIAL_AUDIO: True, cs.CALL_INITIAL_VIDEO: False }, dbus_interface=cs.CONN_IFACE_REQUESTS) ret = q.expect_many(EventPattern('dbus-signal', signal='NewChannels', predicate=lambda e: cs.CHANNEL_TYPE_CALL in e.args[0][0][1].values()), # a codec offer appears already! EventPattern('dbus-signal', signal='NewMediaDescriptionOffer')) # all the basic stuff is already tested in call-basics.py chan = bus.get_object(conn.bus_name, ret[0].args[0][0][0]) # there is no remote codec information, so this should be empty assertEquals(ret[1].args[1][cs.CALL_CONTENT_MEDIADESCRIPTION + ".Codecs"], []) # get a list of audio codecs we can support md = jt2.get_call_audio_md_dbus(remote_handle) # make sure UpdateCodecs fails props = chan.GetAll(cs.CHANNEL_TYPE_CALL, dbus_interface=dbus.PROPERTIES_IFACE) content = bus.get_object(conn.bus_name, props["Contents"][0]) try: content.UpdateLocalMediaDescription(md, dbus_interface=cs.CALL_CONTENT_IFACE_MEDIA) except DBusException, e: # this should fail now that there is a codec offer around if e.get_dbus_name() != cs.NOT_AVAILABLE: raise e else: assert false # we'll need these later content_props = content.GetAll(cs.CALL_CONTENT, dbus_interface=dbus.PROPERTIES_IFACE) # make an offer they can't refuse offer = bus.get_object(conn.bus_name, ret[1].args[0]) props = offer.GetAll(cs.CALL_CONTENT_MEDIADESCRIPTION, dbus_interface=dbus.PROPERTIES_IFACE) # this also needs to be empty assertEquals(props["Codecs"], []) offer.Accept(md, dbus_interface=cs.CALL_CONTENT_MEDIADESCRIPTION) o = q.expect('dbus-signal', signal='RemoteMediaDescriptionsChanged') chan.Accept(dbus_interface=cs.CHANNEL_TYPE_CALL) cstream = bus.get_object(conn.bus_name, content_props["Streams"][0]) recv_state = cstream.Get(cs.CALL_STREAM_IFACE_MEDIA, "ReceivingState", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals (cs.CALL_STREAM_FLOW_STATE_PENDING_START, recv_state) cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) # add candidates candidates = jt2.get_call_remote_transports_dbus () cstream.AddCandidates (candidates, dbus_interface=cs.CALL_STREAM_IFACE_MEDIA) ret = q.expect_many(EventPattern('dbus-signal', signal='LocalCandidatesAdded'), EventPattern('stream-iq', predicate=jp.action_predicate('session-initiate'))) assertEquals (candidates, ret[0].args[0]) jt2.parse_session_initiate(ret[1].query) cstream.FinishInitialCandidates (dbus_interface=cs.CALL_STREAM_IFACE_MEDIA) local_candidates = cstream.Get(cs.CALL_STREAM_IFACE_MEDIA, "LocalCandidates", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals (candidates, local_candidates) endpoints = cstream.Get(cs.CALL_STREAM_IFACE_MEDIA, "Endpoints", dbus_interface=dbus.PROPERTIES_IFACE) assertLength (1, endpoints) # accept with a subset of the codecs old_codecs = jt2.audio_codecs jt2.audio_codecs = jt2.audio_codecs[:-1] # all but the last one # session-accept jt2.accept() ret = q.expect('dbus-signal', signal='NewMediaDescriptionOffer') # make sure the codec offer has the updated codecs assertEquals(ret.args[1][cs.CALL_CONTENT_MEDIADESCRIPTION + ".Codecs"], md[cs.CALL_CONTENT_MEDIADESCRIPTION + ".Codecs"][:-1]) # accept new offer offer = bus.get_object(conn.bus_name, ret.args[0]) md[cs.CALL_CONTENT_MEDIADESCRIPTION + ".Codecs"].pop() offer.Accept(md, dbus_interface=cs.CALL_CONTENT_MEDIADESCRIPTION) # now we should both have the smaller set of codecs, easy o = q.expect ('dbus-signal', signal='RemoteMediaDescriptionsChanged') assertEquals (md[cs.CALL_CONTENT_MEDIADESCRIPTION + ".Codecs"], o.args[0][remote_handle][cs.CALL_CONTENT_MEDIADESCRIPTION + ".Codecs"]) chan.Close(dbus_interface=cs.CHANNEL) signal = q.expect('dbus-signal', signal='ChannelClosed') try_to_access_old_offer(conn, ret.args[0]) if __name__ == '__main__': test_dialects(test_incoming, [JingleProtocol031]) test_dialects(test_outgoing, [JingleProtocol031]) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/test-wait-for-caps.py����������������������������������0000664�0001750�0001750�00000006711�12332441362�026303� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test use-case when client requests going online and immediately attempts to call a contact. Gabble should delay the RequestStreams call until caps have arrived. """ from functools import partial from gabbletest import exec_test from servicetest import make_channel_proxy, call_async, sync_dbus import jingletest2 import dbus import constants as cs from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test(q, bus, conn, stream, channel_type): jp = jingletest2.JingleProtocol031() jt = jingletest2.JingleTest2(jp, conn, q, stream, 'test@localhost', 'foo@bar.com/Foo') jt2 = jingletest2.JingleTest2(jp, conn, q, stream, 'test@localhost', 'foo2@bar.com/Foo') # Make gabble think this is a different client jt2.remote_caps['node'] = 'http://example.com/fake-client1' run_test(q, bus, conn, stream, jt, True, channel_type) run_test(q, bus, conn, stream, jt2, False, channel_type) def run_test(q, bus, conn, stream, jt, request_before_presence, channel_type): """ Requests streams on a media channel to jt.peer, either before their presence is received (if request_before_presence is True) or after their presence is received but before we've got a disco response for their capabilities (otherwise). """ # We intentionally DON'T set remote presence yet. Since Gabble is still # unsure whether to treat contact as offline for this purpose, it # will tentatively allow channel creation and contact handle addition request = dbus.Dictionary({ cs.CHANNEL_TYPE: channel_type, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: jt.peer, }, signature='sv') if channel_type == cs.CHANNEL_TYPE_CALL: request[cs.CALL_INITIAL_AUDIO] = True if channel_type == cs.CHANNEL_TYPE_STREAMED_MEDIA: path, props = conn.CreateChannel(request, dbus_interface=cs.CONN_IFACE_REQUESTS) media_iface = make_channel_proxy(conn, path, 'Channel.Type.StreamedMedia') handle = props[cs.TARGET_HANDLE] sync_dbus(bus, q, conn) def call_request_streams(): if channel_type == cs.CHANNEL_TYPE_STREAMED_MEDIA: call_async(q, media_iface, 'RequestStreams', handle, [cs.MEDIA_STREAM_TYPE_AUDIO]) else: call_async(q, conn.Requests, 'CreateChannel', request) if request_before_presence: # Request streams before either <presence> or caps have arrived. Gabble # should wait for both to arrive before returning from RequestStreams. call_request_streams() # Ensure Gabble's received the method call. sync_dbus(bus, q, conn) # Now send the presence. info_event = jt.send_presence() else: info_event = jt.send_presence() # Now call RequestStreams; it should wait for the disco reply. call_request_streams() jt.send_remote_disco_reply(info_event.stanza) # RequestStreams should now happily complete if channel_type == cs.CHANNEL_TYPE_STREAMED_MEDIA: q.expect('dbus-return', method='RequestStreams') else: q.expect('dbus-return', method='CreateChannel') if __name__ == '__main__': exec_test(partial(test, channel_type=cs.CHANNEL_TYPE_STREAMED_MEDIA), timeout=10) exec_test(partial(test, channel_type=cs.CHANNEL_TYPE_CALL), timeout=10) �������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/test-description-info.py�������������������������������0000664�0001750�0001750�00000020377�12332441362�027107� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test emition and handling of codec update using description-info """ from gabbletest import exec_test, sync_stream from servicetest import ( wrap_channel, assertEquals, make_channel_proxy, unwrap, EventPattern, call_async) from jingletest2 import JingleTest2, JingleProtocol031 import constants as cs from twisted.words.xish import xpath from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def extract_params(payload_type): ret = {} for node in payload_type.elements(): assert node.name == 'parameter' ret[node['name']] = node['value'] return ret def early_description_info(q, bus, conn, stream): test(q, bus, conn, stream, send_early_description_info=True) def test(q, bus, conn, stream, send_early_description_info=False): jp = JingleProtocol031() jt2 = JingleTest2(jp, conn, q, stream, 'test@localhost', 'foo@bar.com/Foo') jt2.prepare() self_handle = conn.GetSelfHandle() remote_handle = conn.RequestHandles(cs.HT_CONTACT, ["foo@bar.com/Foo"])[0] # Remote end calls us jt2.incoming_call() # FIXME: these signals are not observable by real clients, since they # happen before NewChannels. # The caller is in members e = q.expect('dbus-signal', signal='MembersChanged', args=[u'', [remote_handle], [], [], [], 0, 0]) # We're pending because of remote_handle e = q.expect('dbus-signal', signal='MembersChanged', args=[u'', [], [], [self_handle], [], remote_handle, cs.GC_REASON_INVITED]) chan = wrap_channel(bus.get_object(conn.bus_name, e.path), 'StreamedMedia') # S-E gets notified about new session handler, and calls Ready on it e = q.expect('dbus-signal', signal='NewSessionHandler') assert e.args[1] == 'rtp' if send_early_description_info: """ Regression test for a bug where Gabble would crash if you sent it description-info before calling Ready() on the relevant StreamHandler, and then for a bug where Gabble would never accept the call if a description-info was received before all StreamHandlers were Ready(). """ node = jp.SetIq(jt2.peer, jt2.jid, [ jp.Jingle(jt2.sid, jt2.peer, 'description-info', [ jp.Content('stream1', 'initiator', 'both', jp.Description('audio', [ ])) ]) ]) stream.send(jp.xml(node)) sync_stream(q, stream) session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() chan.Group.AddMembers([self_handle], 'accepted') # S-E gets notified about a newly-created stream e = q.expect('dbus-signal', signal='NewStreamHandler') id1 = e.args[1] stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') # We are now in members too e = q.expect('dbus-signal', signal='MembersChanged', args=[u'', [self_handle], [], [], [], self_handle, cs.GC_REASON_NONE]) # we are now both in members members = chan.Group.GetMembers() assert set(members) == set([self_handle, remote_handle]), members local_codecs = [('GSM', 3, 8000, {}), ('PCMA', 8, 8000, {'helix':'woo yay'}), ('PCMU', 0, 8000, {}) ] local_codecs_dbus = jt2.dbusify_codecs_with_params(local_codecs) stream_handler.NewNativeCandidate("fake", jt2.get_remote_transports_dbus()) stream_handler.Ready(local_codecs_dbus) stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) stream_handler.CodecsUpdated(local_codecs_dbus) local_codecs = [('GSM', 3, 8000, {}), ('PCMA', 8, 8000, {'gstreamer':'rock on'}), ('PCMU', 0, 8000, {}) ] local_codecs_dbus = jt2.dbusify_codecs_with_params(local_codecs) stream_handler.CodecsUpdated(local_codecs_dbus) # First IQ is transport-info; also, we expect to be told what codecs the # other end wants. e, src = q.expect_many( EventPattern('stream-iq', predicate=jp.action_predicate('transport-info')), EventPattern('dbus-signal', signal='SetRemoteCodecs') ) assertEquals('foo@bar.com/Foo', e.query['initiator']) assert jt2.audio_codecs == [ (name, id, rate, parameters) for id, name, type, rate, channels, parameters in unwrap(src.args[0]) ], \ (jt2.audio_codecs, unwrap(src.args[0])) stream.send(jp.xml(jp.ResultIq('test@localhost', e.stanza, []))) # S-E reports codec intersection, after which gabble can send acceptance stream_handler.SupportedCodecs(local_codecs_dbus) # Second one is session-accept e = q.expect('stream-iq', predicate=jp.action_predicate('session-accept')) # farstream is buggy, and tells tp-fs to tell Gabble to change the third # codec's clockrate. This isn't legal, so Gabble says no. new_codecs = [ ('GSM', 3, 8000, {}), ('PCMA', 8, 8000, {}), ('PCMU', 0, 4000, {}) ] call_async(q, stream_handler, 'CodecsUpdated', jt2.dbusify_codecs(new_codecs)) event = q.expect('dbus-error', method='CodecsUpdated') assert event.error.get_dbus_name() == cs.INVALID_ARGUMENT, \ event.error.get_dbus_name() # With its tail between its legs, tp-fs decides it wants to add some # parameters to the first two codecs, not changing the third. new_codecs = [ ('GSM', 3, 8000, {'type': 'banana'}), ('PCMA', 8, 8000, {'helix': 'BUFFERING'}), ('PCMU', 0, 8000, {}) ] stream_handler.CodecsUpdated(jt2.dbusify_codecs_with_params(new_codecs)) audio_content = jt2.audio_names[0] e = q.expect('stream-iq', iq_type='set', predicate=lambda x: xpath.queryForNodes("/iq/jingle[@action='description-info']", x.stanza)) payload_types = xpath.queryForNodes( "/iq/jingle/content[@name='%s']/description/payload-type" % audio_content, e.stanza) # Gabble SHOULD only include the changed codecs in description-info assert len(payload_types) == 2, payload_types payload_types_tupled = [ (pt['name'], int(pt['id']), int(pt['clockrate']), extract_params(pt)) for pt in payload_types ] assert sorted(payload_types_tupled) == sorted(new_codecs[0:2]), \ (payload_types_tupled, new_codecs[0:2]) # The remote end decides it wants to change the number of channels in the # third codec. This is not meant to happen, so Gabble should send it an IQ # error back. node = jp.SetIq(jt2.peer, jt2.jid, [ jp.Jingle(jt2.sid, jt2.peer, 'description-info', [ jp.Content(audio_content, 'initiator', 'both', jp.Description('audio', [ jp.PayloadType('PCMU', '1600', '0') ])) ]) ]) stream.send(jp.xml(node)) q.expect('stream-iq', iq_type='error', predicate=lambda x: x.stanza['id'] == node[2]['id']) # Instead, the remote end decides to add a parameter to the third codec. new_codecs = [ ('GSM', 3, 8000, {}), ('PCMA', 8, 8000, {}), ('PCMU', 0, 8000, {'choppy': 'false'}), ] # As per the XEP, it only sends the ones which have changed. c = new_codecs[2] node = jp.SetIq(jt2.peer, jt2.jid, [ jp.Jingle(jt2.sid, jt2.peer, 'description-info', [ jp.Content(audio_content, 'initiator', 'both', jp.Description('audio', [ jp.PayloadType(c[0], str(c[2]), str(c[1]), c[3]) ])) ]) ]) stream.send(jp.xml(node)) # Gabble should patch its idea of the remote codecs with the update it just # got, and emit SetRemoteCodecs for them all. e = q.expect('dbus-signal', signal='SetRemoteCodecs') new_codecs_dbus = unwrap(jt2.dbusify_codecs_with_params(new_codecs)) announced = unwrap(e.args[0]) assert new_codecs_dbus == announced, (new_codecs_dbus, announced) # We close the session by removing the stream chan.StreamedMedia.RemoveStreams([id1]) e = q.expect('stream-iq', iq_type='set', predicate=lambda x: xpath.queryForNodes("/iq/jingle[@action='session-terminate']", x.stanza)) if __name__ == '__main__': exec_test(test) exec_test(early_description_info) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/callutils.py�������������������������������������������0000664�0001750�0001750�00000005413�12332441362�024644� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Utilities for the call channel class """ import dbus from dbus.exceptions import DBusException from twisted.words.xish import xpath from gabbletest import exec_test from servicetest import ( make_channel_proxy, wrap_channel, EventPattern, call_async, assertEquals, assertContains, assertLength, assertNotEquals ) import constants as cs from jingletest2 import JingleTest2, test_all_dialects import ns from mucutil import echo_muc_presence def check_state (q, chan, state, wait = False): if wait: q.expect('dbus-signal', signal='CallStateChanged', interface = cs.CHANNEL_TYPE_CALL, predicate = lambda e: e.args[0] == state) properties = chan.GetAll(cs.CHANNEL_TYPE_CALL, dbus_interface=dbus.PROPERTIES_IFACE) assertEquals (state, properties["CallState"]) def check_and_accept_offer (q, bus, conn, content, md, in_remote_handle = 0, offer_path = None, md_changed = True): [path, remote_md] = content.Get(cs.CALL_CONTENT_IFACE_MEDIA, "MediaDescriptionOffer", dbus_interface=dbus.PROPERTIES_IFACE) remote_handle = remote_md[cs.CALL_CONTENT_MEDIADESCRIPTION + '.RemoteContact'] if in_remote_handle != 0: assertEquals(remote_handle, in_remote_handle) if offer_path != None: assertEquals (offer_path, path) assertNotEquals ("/", path) offer = bus.get_object (conn.bus_name, path) codecmap_property = offer.Get (cs.CALL_CONTENT_MEDIADESCRIPTION, "Codecs", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals (remote_md[cs.CALL_CONTENT_MEDIADESCRIPTION + '.Codecs'], codecmap_property) offer.Accept (md, dbus_interface=cs.CALL_CONTENT_MEDIADESCRIPTION) current_md = content.Get(cs.CALL_CONTENT_IFACE_MEDIA, "LocalMediaDescriptions", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals (md, current_md[remote_handle]) if md_changed: o = q.expect ('dbus-signal', signal='LocalMediaDescriptionChanged') assertEquals ([md], o.args) def no_muji_presences (muc): return EventPattern ('stream-presence', to = muc + "/test", predicate = lambda x: xpath.queryForNodes("/presence/muji", x.stanza)) def create_muji_channel (q, conn, stream, muc, in_muc = False): call_async (q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: muc, cs.CALL_INITIAL_AUDIO: True, cs.CALL_INITIAL_AUDIO_NAME: "Audio", }, byte_arrays = True) if not in_muc: e = q.expect('stream-presence', to = muc + "/test") echo_muc_presence (q, stream, e.stanza, 'none', 'participant') e = q.expect ('dbus-return', method='CreateChannel') return e.value �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/test-wait-for-caps-incomplete.py�����������������������0000664�0001750�0001750�00000005454�12332441362�030443� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test that Gabble properly cleans up delayed RequestStream contexts and returns an error when Disconnect is called and there are incomplete requests. """ from functools import partial from gabbletest import exec_test, disconnect_conn from servicetest import make_channel_proxy, call_async, sync_dbus, EventPattern import constants as cs from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test(q, bus, conn, stream, channel_type): peer = 'foo@bar.com/Foo' # We intentionally DON'T set remote presence yet. Since Gabble is still # unsure whether to treat contact as offline for this purpose, it # will tentatively allow channel creation and contact handle addition handle = conn.RequestHandles(cs.HT_CONTACT, [peer])[0] if channel_type == cs.CHANNEL_TYPE_STREAMED_MEDIA: path = conn.RequestChannel(cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.HT_CONTACT, handle, True) media_iface = make_channel_proxy(conn, path, 'Channel.Type.StreamedMedia') # So it turns out that the calls to RequestStreams and Disconnect could be # reordered while the first waits on the result of introspecting the # channel's object which is kicked off by making a proxy object for it, # whereas the connection proxy is long ago introspected. Isn't dbus-python # great? Syncing here forces that introspection to finish so we can rely on # the ordering of RequestStreams and Disconnect. Yay. sync_dbus(bus, q, conn) # Now we request streams before either <presence> or caps have arrived if channel_type == cs.CHANNEL_TYPE_STREAMED_MEDIA: call_async(q, media_iface, 'RequestStreams', handle, [cs.MEDIA_STREAM_TYPE_AUDIO]) before_events, after_events = disconnect_conn(q, conn, stream, [EventPattern('dbus-error', method='RequestStreams')]) # RequestStreams should now return NotAvailable assert before_events[0].error.get_dbus_name() == cs.NOT_AVAILABLE, \ before_events[0].error else: call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: channel_type, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_ID: peer, cs.CALL_INITIAL_AUDIO: True }) before_events, after_events = disconnect_conn(q, conn, stream, [EventPattern('dbus-error', method='CreateChannel')]) # CreateChannel should now return Disconnected assert before_events[0].error.get_dbus_name() == cs.DISCONNECTED, \ before_events[0].error if __name__ == '__main__': exec_test(partial(test, channel_type=cs.CHANNEL_TYPE_STREAMED_MEDIA), timeout=10) exec_test(partial(test, channel_type=cs.CHANNEL_TYPE_CALL), timeout=10) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/stream-handler-error.py��������������������������������0000664�0001750�0001750�00000004116�12332441362�026704� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test handling of errors from StreamHandler during calls. This is a regression test for a bug introduced by 54021cee0ad38 which removed an idle callback masking refcounting assumptions. """ from functools import partial from gabbletest import exec_test from servicetest import make_channel_proxy import jingletest2 import constants as cs from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test(q, bus, conn, stream, call_error_on): jp = jingletest2.JingleProtocol031() jt = jingletest2.JingleTest2(jp, conn, q, stream, 'test@localhost', 'foo@bar.com/Foo') remote_handle = conn.RequestHandles(1, [jt.peer])[0] # Remote end calls us jt.incoming_call() # FIXME: these signals are not observable by real clients, since they # happen before NewChannels. # The caller is in members e = q.expect('dbus-signal', signal='MembersChanged', args=[u'', [remote_handle], [], [], [], 0, 0]) # We're pending because of remote_handle e = q.expect('dbus-signal', signal='MembersChanged', args=[u'', [], [], [1L], [], remote_handle, cs.GC_REASON_INVITED]) media_chan_suffix = e.path e = q.expect('dbus-signal', signal='NewSessionHandler') session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') if call_error_on == 'session': session_handler.Error(0, "this has been deprecated for years") else: session_handler.Ready() e = q.expect('dbus-signal', signal='NewStreamHandler') # S-E gets notified about a newly-created stream stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') # Something goes wrong immediately! stream_handler.Error(0, "i'll have the eggs tostada please") # Gabble doesn't fall over, and the channel closes nicely. e = q.expect('dbus-signal', signal='Closed', path=media_chan_suffix) if __name__ == '__main__': exec_test(partial(test, call_error_on='stream')) exec_test(partial(test, call_error_on='session')) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/test-content-complex.py��������������������������������0000664�0001750�0001750�00000024106�12332441362�026744� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test everything related to contents """ from gabbletest import sync_stream from servicetest import ( make_channel_proxy, assertEquals, EventPattern) import constants as cs from jingletest2 import ( JingleTest2, JingleProtocol015, JingleProtocol031, test_dialects) from twisted.words.xish import xpath from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def worker(jp, q, bus, conn, stream): def make_stream_request(stream_type): media_iface.RequestStreams(remote_handle, [stream_type]) e = q.expect('dbus-signal', signal='NewStreamHandler') stream_id = e.args[1] stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') stream_handler.NewNativeCandidate("fake", jt2.get_remote_transports_dbus()) stream_handler.Ready(jt2.get_audio_codecs_dbus()) stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) return (stream_handler, stream_id) jt2 = JingleTest2(jp, conn, q, stream, 'test@localhost', 'foo@bar.com/Foo') jt2.prepare() self_handle = conn.GetSelfHandle() remote_handle = conn.RequestHandles(cs.HT_CONTACT, ["foo@bar.com/Foo"])[0] # Remote end calls us jt2.incoming_call() # FIXME: these signals are not observable by real clients, since they # happen before NewChannels. # The caller is in members e = q.expect('dbus-signal', signal='MembersChanged', args=[u'', [remote_handle], [], [], [], 0, 0]) # We're pending because of remote_handle e = q.expect('dbus-signal', signal='MembersChanged', args=[u'', [], [], [self_handle], [], remote_handle, cs.GC_REASON_INVITED]) media_chan = make_channel_proxy(conn, e.path, 'Channel.Interface.Group') signalling_iface = make_channel_proxy(conn, e.path, 'Channel.Interface.MediaSignalling') media_iface = make_channel_proxy(conn, e.path, 'Channel.Type.StreamedMedia') # S-E gets notified about new session handler, and calls Ready on it e = q.expect('dbus-signal', signal='NewSessionHandler') assert e.args[1] == 'rtp' session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() media_chan.AddMembers([self_handle], 'accepted') # S-E gets notified about a newly-created stream e = q.expect('dbus-signal', signal='NewStreamHandler') id1 = e.args[1] stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') # We are now in members too e = q.expect('dbus-signal', signal='MembersChanged', args=[u'', [self_handle], [], [], [], self_handle, cs.GC_REASON_NONE]) # we are now both in members members = media_chan.GetMembers() assert set(members) == set([self_handle, remote_handle]), members stream_handler.NewNativeCandidate("fake", jt2.get_remote_transports_dbus()) stream_handler.Ready(jt2.get_audio_codecs_dbus()) stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) # First one is transport-info e = q.expect('stream-iq', predicate=jp.action_predicate('transport-info')) assertEquals('foo@bar.com/Foo', e.query['initiator']) # stream.send(gabbletest.make_result_iq(stream, e.stanza)) stream.send(jp.xml(jp.ResultIq('test@localhost', e.stanza, []))) # S-E reports codec intersection, after which gabble can send acceptance stream_handler.SupportedCodecs(jt2.get_audio_codecs_dbus()) # Second one is session-accept e = q.expect('stream-iq', predicate=jp.action_predicate('session-accept')) # stream.send(gabbletest.make_result_iq(stream, e.stanza)) stream.send(jp.xml(jp.ResultIq('test@localhost', e.stanza, []))) # Here starts the interesting part of this test # Remote end tries to create a content we can't handle node = jp.SetIq(jt2.peer, jt2.jid, [ jp.Jingle(jt2.sid, jt2.peer, 'content-add', [ jp.Content('bogus', 'initiator', 'both', jp.Description('hologram', [ jp.PayloadType(name, str(rate), str(id), parameters) for (name, id, rate, parameters) in jt2.audio_codecs ]), jp.TransportGoogleP2P()) ]) ]) stream.send(jp.xml(node)) # In older Jingle, this is a separate namespace, which isn't # recognized, but it's a valid request, so it gets ackd and rejected if jp.dialect == 'jingle-v0.15': # Gabble should acknowledge content-add q.expect('stream-iq', iq_type='result') # .. and then send content-reject for the bogus content e = q.expect('stream-iq', iq_type='set', predicate=lambda x: xpath.queryForNodes("/iq/jingle[@action='content-reject']/content[@name='bogus']", x.stanza)) # In new Jingle, this is a bogus subtype of recognized namespace, # so Gabble returns a bad request error else: q.expect('stream-iq', iq_type='error') # Remote end then tries to create a content with a name it's already used node = jp.SetIq(jt2.peer, jt2.jid, [ jp.Jingle(jt2.sid, jt2.peer, 'content-add', [ jp.Content(jt2.audio_names[0], 'initiator', 'both', jp.Description('audio', [ jp.PayloadType(name, str(rate), str(id), parameters) for (name, id, rate, parameters) in jt2.audio_codecs ]), jp.TransportGoogleP2P()) ]) ]) stream.send(jp.xml(node)) # Gabble should return error (content already exists) q.expect('stream-iq', iq_type='error') # We try to add a stream (stream_handler2, id2) = make_stream_request(cs.MEDIA_STREAM_TYPE_VIDEO) # Gabble should now send content-add e = q.expect('stream-iq', iq_type='set', predicate=lambda x: xpath.queryForNodes("/iq/jingle[@action='content-add']", x.stanza)) c = e.query.firstChildElement() assert c['creator'] == 'responder', c['creator'] stream.send(jp.xml(jp.ResultIq('test@localhost', e.stanza, []))) # We try to add yet another stream (stream_handler3, id3) = make_stream_request(cs.MEDIA_STREAM_TYPE_VIDEO) # Gabble should send another content-add e = q.expect('stream-iq', iq_type='set', predicate=lambda x: xpath.queryForNodes("/iq/jingle[@action='content-add']", x.stanza)) d = e.query.firstChildElement() assertEquals('responder', d['creator']) stream.send(jp.xml(jp.ResultIq('test@localhost', e.stanza, []))) # Remote end rejects the first stream we tried to add. node = jp.SetIq(jt2.peer, jt2.jid, [ jp.Jingle(jt2.sid, jt2.peer, 'content-reject', [ jp.Content(c['name'], c['creator'], c['senders']) ]) ]) stream.send(jp.xml(node)) # Gabble removes the stream q.expect('dbus-signal', signal='StreamRemoved', interface=cs.CHANNEL_TYPE_STREAMED_MEDIA) # Remote end tries to add a content with the same name as the second one we # just added node = jp.SetIq(jt2.peer, jt2.jid, [ jp.Jingle(jt2.sid, jt2.peer, 'content-add', [ jp.Content(d['name'], 'initiator', 'both', jp.Description('audio', [ jp.PayloadType(name, str(rate), str(id), parameters) for (name, id, rate, parameters) in jt2.audio_codecs ]), jp.TransportGoogleP2P()) ]) ]) stream.send(jp.xml(node)) # Because stream names are namespaced by creator, Gabble should be okay # with that. q.expect_many( EventPattern('stream-iq', iq_type='result', iq_id=node[2]['id']), EventPattern('dbus-signal', signal='StreamAdded'), ) # Remote end thinks better of that, and removes the similarly-named stream # it tried to add. node = jp.SetIq(jt2.peer, jt2.jid, [ jp.Jingle(jt2.sid, jt2.peer, 'content-remove', [ jp.Content(d['name'], 'initiator', d['senders']) ]) ]) stream.send(jp.xml(node)) q.expect_many( EventPattern('stream-iq', iq_type='result', iq_id=node[2]['id']), EventPattern('dbus-signal', signal='StreamRemoved'), ) # Remote end finally accepts. When Gabble did not namespace contents by # their creator, it would NAK this IQ: # - Gabble (responder) created a stream called 'foo'; # - test suite (initiator) created a stream called 'foo', which Gabble # decided would replace its own stream called 'foo'; # - test suite removed its 'foo'; # - test suite accepted Gabble's 'foo', but Gabble didn't believe a stream # called 'foo' existed any more. node = jp.SetIq(jt2.peer, jt2.jid, [ jp.Jingle(jt2.sid, jt2.peer, 'content-accept', [ jp.Content(d['name'], d['creator'], d['senders'], jp.Description('video', [ jp.PayloadType(name, str(rate), str(id), parameters) for (name, id, rate, parameters ) in jt2.audio_codecs ]), jp.TransportGoogleP2P()) ]) ]) stream.send(jp.xml(node)) # We get remote codecs e = q.expect('dbus-signal', signal='SetRemoteCodecs') # Now, both we and remote peer try to remove the content simultaneously: # Telepathy client calls RemoveStreams... media_iface.RemoveStreams([id3]) # ...so Gabble sends a content-remove... e = q.expect('stream-iq', iq_type='set', predicate=lambda x: xpath.queryForNodes("/iq/jingle[@action='content-remove']", x.stanza)) # ...but before it's acked the peer sends its own content-remove... node = jp.SetIq(jt2.peer, jt2.jid, [ jp.Jingle(jt2.sid, jt2.peer, 'content-remove', [ jp.Content(c['name'], c['creator'], c['senders']) ]) ]) stream.send(jp.xml(node)) # ...and we don't want Gabble to break when that happens. sync_stream(q, stream) # Now we want to remove the first stream media_iface.RemoveStreams([id1]) # Since this is the last stream, Gabble will just terminate the session. e = q.expect('stream-iq', iq_type='set', predicate=lambda x: xpath.queryForNodes("/iq/jingle[@action='session-terminate']", x.stanza)) if __name__ == '__main__': test_dialects(worker, [JingleProtocol015, JingleProtocol031]) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/outgoing-basics.py�������������������������������������0000664�0001750�0001750�00000032401�12332441362�025742� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test basic outgoing call handling, using CreateChannel and all three variations of RequestChannel. """ from functools import partial import dbus from twisted.words.xish import xpath from gabbletest import exec_test from servicetest import ( make_channel_proxy, wrap_channel, EventPattern, call_async, assertEquals, assertContains, assertLength, ) import constants as cs from jingletest2 import JingleTest2, test_all_dialects from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) # There are various deprecated APIs for requesting calls, documented at # <http://telepathy.freedesktop.org/wiki/Requesting StreamedMedia channels>. # These are ordered from most recent to most deprecated. CREATE = 0 # CreateChannel({TargetHandleType: Contact, TargetHandle: h}); # RequestStreams() REQUEST_ANONYMOUS = 1 # RequestChannel(HandleTypeNone, 0); RequestStreams() REQUEST_ANONYMOUS_AND_ADD = 2 # RequestChannel(HandleTypeNone, 0); # AddMembers([h], ...); RequestStreams(h,...) REQUEST_NONYMOUS = 3 # RequestChannel(HandleTypeContact, h); # RequestStreams(h, ...) def create(jp, q, bus, conn, stream, peer='foo@bar.com/Res'): worker(jp, q, bus, conn, stream, CREATE, peer) def request_anonymous(jp, q, bus, conn, stream, peer='publish@foo.com/Res'): worker(jp, q, bus, conn, stream, REQUEST_ANONYMOUS, peer) def request_anonymous_and_add(jp, q, bus, conn, stream, peer='publish-subscribe@foo.com/Res'): worker(jp, q, bus, conn, stream, REQUEST_ANONYMOUS_AND_ADD, peer) def request_nonymous(jp, q, bus, conn, stream, peer='subscribe@foo.com/Res'): worker(jp, q, bus, conn, stream, REQUEST_NONYMOUS, peer) def worker(jp, q, bus, conn, stream, variant, peer): jt2 = JingleTest2(jp, conn, q, stream, 'test@localhost', peer) jt2.prepare(send_presence=True, send_roster=True) self_handle = conn.GetSelfHandle() remote_handle = conn.RequestHandles(1, [jt2.peer])[0] if variant == REQUEST_NONYMOUS: path = conn.RequestChannel(cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.HT_CONTACT, remote_handle, True) elif variant == CREATE: path = conn.Requests.CreateChannel({ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: remote_handle, })[0] else: path = conn.RequestChannel(cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.HT_NONE, 0, True) old_sig, new_sig = q.expect_many( EventPattern('dbus-signal', signal='NewChannel', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args), EventPattern('dbus-signal', signal='NewChannels', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args[0][0][1].values()), ) if variant == REQUEST_NONYMOUS or variant == CREATE: assertEquals( [path, cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.HT_CONTACT, remote_handle, True], old_sig.args) else: assertEquals( [path, cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.HT_NONE, 0, True], old_sig.args) assertLength(1, new_sig.args) assertLength(1, new_sig.args[0]) # one channel assertLength(2, new_sig.args[0][0]) # two struct members emitted_props = new_sig.args[0][0][1] assertEquals( cs.CHANNEL_TYPE_STREAMED_MEDIA, emitted_props[cs.CHANNEL_TYPE]) if variant == REQUEST_NONYMOUS or variant == CREATE: assertEquals(remote_handle, emitted_props[cs.TARGET_HANDLE]) assertEquals(cs.HT_CONTACT, emitted_props[cs.TARGET_HANDLE_TYPE]) assertEquals(jt2.peer_bare_jid, emitted_props[cs.TARGET_ID]) else: assertEquals(0, emitted_props[cs.TARGET_HANDLE]) assertEquals(cs.HT_NONE, emitted_props[cs.TARGET_HANDLE_TYPE]) assertEquals('', emitted_props[cs.TARGET_ID]) assertEquals(True, emitted_props[cs.REQUESTED]) assertEquals(self_handle, emitted_props[cs.INITIATOR_HANDLE]) assertEquals('test@localhost', emitted_props[cs.INITIATOR_ID]) chan = wrap_channel(bus.get_object(conn.bus_name, path), 'StreamedMedia', ['MediaSignalling']) # Exercise basic Channel Properties channel_props = chan.Properties.GetAll(cs.CHANNEL) assertEquals(cs.CHANNEL_TYPE_STREAMED_MEDIA, channel_props.get('ChannelType')) if variant == REQUEST_NONYMOUS or variant == CREATE: assertEquals(remote_handle, channel_props['TargetHandle']) assertEquals(cs.HT_CONTACT, channel_props['TargetHandleType']) assertEquals(jt2.peer_bare_jid, channel_props['TargetID']) assertEquals((cs.HT_CONTACT, remote_handle), chan.GetHandle()) else: assertEquals(0, channel_props['TargetHandle']) assertEquals(cs.HT_NONE, channel_props['TargetHandleType']) assertEquals('', channel_props['TargetID']) assertEquals((cs.HT_NONE, 0), chan.GetHandle()) for interface in [ cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_MEDIA_SIGNALLING, cs.TP_AWKWARD_PROPERTIES, cs.CHANNEL_IFACE_HOLD]: assertContains(interface, channel_props['Interfaces']) assertEquals(True, channel_props['Requested']) assertEquals('test@localhost', channel_props['InitiatorID']) assertEquals(conn.GetSelfHandle(), channel_props['InitiatorHandle']) # Exercise Group Properties group_props = chan.Properties.GetAll(cs.CHANNEL_IFACE_GROUP) assertEquals([self_handle], group_props['Members']) assertEquals([], group_props['LocalPendingMembers']) if variant == REQUEST_NONYMOUS: # In this variant, they're meant to be in RP even though we've sent # nothing assertEquals([remote_handle], group_props['RemotePendingMembers']) else: # For an anonymous channel, the peer isn't yet known; for a Create-d # channel, the peer only appears in RP when we actually send them the # session-initiate assertEquals([], group_props['RemotePendingMembers']) if variant == REQUEST_ANONYMOUS_AND_ADD: # but we should be allowed to add the peer. chan.Group.AddMembers([remote_handle], 'I love backwards compat') base_flags = cs.GF_MEMBERS_CHANGED_DETAILED | cs.GF_PROPERTIES | cs.GF_MESSAGE_REMOVE \ | cs.GF_MESSAGE_REJECT | cs.GF_MESSAGE_RESCIND if variant == REQUEST_ANONYMOUS_AND_ADD or variant == REQUEST_ANONYMOUS: expected_flags = base_flags | cs.GF_CAN_ADD else: expected_flags = base_flags assertEquals(expected_flags, group_props['GroupFlags']) assertEquals({}, group_props['HandleOwners']) assertEquals([], chan.StreamedMedia.ListStreams()) streams = chan.StreamedMedia.RequestStreams(remote_handle, [cs.MEDIA_STREAM_TYPE_AUDIO]) assertEquals(streams, chan.StreamedMedia.ListStreams()) assertLength(1, streams) # streams[0][0] is the stream identifier, which in principle we can't # make any assertion about (although in practice it's probably 1) assertEquals(( remote_handle, cs.MEDIA_STREAM_TYPE_AUDIO, # We haven't connected yet cs.MEDIA_STREAM_STATE_DISCONNECTED, # In Gabble, requested streams start off bidirectional cs.MEDIA_STREAM_DIRECTION_BIDIRECTIONAL, 0), streams[0][1:]) # S-E gets notified about new session handler, and calls Ready on it e = q.expect('dbus-signal', signal='NewSessionHandler') assert e.args[1] == 'rtp' session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() e = q.expect('dbus-signal', signal='NewStreamHandler') stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') stream_handler.NewNativeCandidate("fake", jt2.get_remote_transports_dbus()) stream_handler.Ready(jt2.get_audio_codecs_dbus()) stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) sh_props = stream_handler.GetAll( cs.STREAM_HANDLER, dbus_interface=dbus.PROPERTIES_IFACE) assertEquals('gtalk-p2p', sh_props['NATTraversal']) assertEquals(True, sh_props['CreatedLocally']) if variant == CREATE: # When we actually send XML to the peer, they should pop up in remote # pending. session_initiate, _ = q.expect_many( EventPattern('stream-iq', iq_type='set', predicate=lambda e: jp.match_jingle_action(e.query, 'session-initiate')), EventPattern('dbus-signal', signal='MembersChanged', args=["", [], [], [], [remote_handle], self_handle, cs.GC_REASON_INVITED]), ) else: forbidden = [] if peer.split('/', 1)[0] in ( 'publish@foo.com', 'publish-subscribe@foo.com'): forbidden = [EventPattern('stream-presence')] q.forbid_events(forbidden) else: # we're calling someone not on our roster, so we'll send directed # presence first presence = q.expect('stream-presence') assert (xpath.queryForNodes('/presence/c', presence.stanza) is not None) assert (xpath.queryForNodes( '/presence/x[@xmlns="vcard-temp:x:update"]', presence.stanza) is not None) session_initiate = q.expect('stream-iq', predicate=jp.action_predicate('session-initiate')) if forbidden: q.unforbid_events(forbidden) jt2.parse_session_initiate(session_initiate.query) stream.send(jp.xml(jp.ResultIq('test@localhost', session_initiate.stanza, []))) # Check the Group interface's properties again. Regardless of the call # requesting API in use, the state should be the same here: group_props = chan.Properties.GetAll(cs.CHANNEL_IFACE_GROUP) assertContains('HandleOwners', group_props) assertEquals([self_handle], group_props['Members']) assertEquals([], group_props['LocalPendingMembers']) assertEquals([remote_handle], group_props['RemotePendingMembers']) if jp.dialect == 'gtalk-v0.4': node = jp.SetIq(jt2.peer, jt2.jid, [ jp.Jingle(jt2.sid, jt2.peer, 'transport-accept', [ jp.TransportGoogleP2P() ]) ]) stream.send(jp.xml(node)) # FIXME: expect transport-info, then if we're gtalk3, send # candidates, and check that gabble resends transport-info as # candidates jt2.accept() q.expect_many( EventPattern('stream-iq', iq_type='result'), # Call accepted EventPattern('dbus-signal', signal='MembersChanged', args=['', [remote_handle], [], [], [], remote_handle, cs.GC_REASON_NONE]), ) # Time passes ... afterwards we close the chan chan.Group.RemoveMembers([self_handle], 'closed') # Make sure gabble sends proper terminate action if jp.dialect.startswith('gtalk'): terminate = EventPattern('stream-iq', predicate=lambda x: xpath.queryForNodes("/iq/session[@type='terminate']", x.stanza)) else: terminate = EventPattern('stream-iq', predicate=lambda x: xpath.queryForNodes("/iq/jingle[@action='session-terminate']", x.stanza)) mc_event, _, _ = q.expect_many( EventPattern('dbus-signal', signal='MembersChanged'), EventPattern('dbus-signal', signal='Close'), terminate, ) # Check that we're the actor assertEquals(self_handle, mc_event.args[5]) def rccs(q, bus, conn, stream): """ Tests that the connection's RequestableChannelClasses for StreamedMedia are sane. """ rccs = conn.Properties.Get(cs.CONN_IFACE_REQUESTS, 'RequestableChannelClasses') # Test Channel.Type.StreamedMedia media_classes = [ rcc for rcc in rccs if rcc[0][cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAMED_MEDIA ] assertLength(1, media_classes) fixed, allowed = media_classes[0] assertEquals(cs.HT_CONTACT, fixed[cs.TARGET_HANDLE_TYPE]) expected_allowed = [ cs.TARGET_ID, cs.TARGET_HANDLE, cs.INITIAL_VIDEO, cs.INITIAL_AUDIO ] allowed.sort() expected_allowed.sort() assertEquals(expected_allowed, allowed) # Test Channel.Type.Call media_classes = [ rcc for rcc in rccs if rcc[0][cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_CALL ] assertLength(2, media_classes) hts = [] for mc in media_classes: fixed, allowed = mc hts.append (fixed[cs.TARGET_HANDLE_TYPE]) expected_allowed = [ cs.TARGET_ID, cs.TARGET_HANDLE, cs.CALL_INITIAL_VIDEO, cs.CALL_INITIAL_AUDIO, cs.CALL_INITIAL_VIDEO_NAME, cs.CALL_INITIAL_AUDIO_NAME, cs.CALL_MUTABLE_CONTENTS ] allowed.sort() expected_allowed.sort() assertEquals(expected_allowed, allowed) assertEquals(sorted([cs.HT_CONTACT, cs.HT_ROOM]), sorted(hts)) if __name__ == '__main__': exec_test(rccs) test_all_dialects(create) test_all_dialects(request_anonymous) test_all_dialects(request_anonymous_and_add) test_all_dialects(request_nonymous) test_all_dialects(partial(create, peer='foo@gw.bar.com')) test_all_dialects(partial(request_anonymous, peer='foo@gw.bar.com')) test_all_dialects(partial(request_anonymous_and_add, peer='foo@gw.bar.com')) test_all_dialects(partial(request_nonymous, peer='foo@gw.bar.com')) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/transport-info-parsing.py������������������������������0000664�0001750�0001750�00000005116�12332441362�027276� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test whether we parse the transport info with multiple contents correctly """ from gabbletest import exec_test from servicetest import ( make_channel_proxy, EventPattern, assertEquals, assertNotEquals ) from jingletest2 import * from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test(q, bus, conn, stream, peer='foo@bar.com/Foo'): jp = JingleProtocol031() jt = JingleTest2(jp, conn, q, stream, 'test@localhost', peer) jt.prepare() # Remote end calls us jt.incoming_call(audio = "Audio", video = "Video") e = q.expect ('dbus-signal', signal='NewSessionHandler') handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') handler.Ready() events = q.expect_many ( EventPattern('dbus-signal', signal='NewStreamHandler'), EventPattern('dbus-signal', signal='NewStreamHandler') ) for e in events: handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') handler.Ready([]) candidate0 = ( "1.2.3.4", # host 666, # port 0, # protocol = TP_MEDIA_STREAM_BASE_PROTO_UDP "RTP", # protocol subtype "AVP", # profile 1.0, # preference 0, # transport type = TP_MEDIA_STREAM_TRANSPORT_TYPE_LOCAL, "username", "password" ) candidate1 = ( "5.6.7.8", # host 999, # port 0, # protocol = TP_MEDIA_STREAM_BASE_PROTO_UDP "RTP", # protocol subtype "AVP", # profile 1.0, # preference 0, # transport type = TP_MEDIA_STREAM_TRANSPORT_TYPE_LOCAL, "username", "password" ) node = jp.SetIq(jt.peer, jt.jid, [ jp.Jingle(jt.sid, jt.peer, 'transport-info', [ jp.Content('Audio', 'initiator', 'both', transport = jp.TransportGoogleP2P([candidate0])), jp.Content('Video', 'initiator', 'both', transport = jp.TransportGoogleP2P([candidate1])), ] ) ]) stream.send(jp.xml(node)) q.expect ('stream-iq', iq_type='result') (c0, c1) = q.expect_many( EventPattern('dbus-signal', signal='AddRemoteCandidate'), EventPattern('dbus-signal', signal='AddRemoteCandidate')) assertNotEquals(c0.path, c1.path) mapping = { 666: candidate0, 999: candidate1} # Candidate without component number to compare candidate = c0.args[1][0][1:] assertEquals(mapping[candidate[1]], candidate) candidate = c1.args[1][0][1:] assertEquals(mapping[candidate[1]], candidate) if __name__ == '__main__': exec_test(test) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/hold-audio.py������������������������������������������0000664�0001750�0001750�00000036173�12332441362�024704� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test the Hold API. """ from gabbletest import make_result_iq, sync_stream from servicetest import ( assertEquals, sync_dbus, make_channel_proxy, call_async, EventPattern, wrap_channel, ) import constants as cs from jingletest2 import JingleTest2, test_all_dialects from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test(jp, q, bus, conn, stream): remote_jid = 'foo@bar.com/Foo' jt = JingleTest2(jp, conn, q, stream, 'test@localhost', remote_jid) jt.prepare() self_handle = conn.GetSelfHandle() handle = conn.RequestHandles(cs.HT_CONTACT, [remote_jid])[0] path = conn.RequestChannel(cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.HT_CONTACT, handle, True) chan = wrap_channel(bus.get_object(conn.bus_name, path), 'StreamedMedia', ['Hold']) # These are 0- (for old dialects) or 1- (for new dialects) element lists # that can be splatted into expect_many with * hold_event = jp.rtp_info_event_list("hold") unhold_event = jp.rtp_info_event_list("unhold") # Before we have any streams, GetHoldState returns Unheld and unhold is a # no-op. assertEquals((cs.HS_UNHELD, cs.HSR_NONE), chan.Hold.GetHoldState()) chan.Hold.RequestHold(False) # Before we have any streams, RequestHold(True) should work; because there # are no streams, it should take effect at once. It certainly shouldn't # send anything to the peer. q.forbid_events(hold_event) q.forbid_events(unhold_event) call_async(q, chan.Hold, 'RequestHold', True) q.expect('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]) q.expect('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]) assertEquals((cs.HS_HELD, cs.HSR_REQUESTED), chan.Hold.GetHoldState()) # If we unhold, it should succeed immediately again, because there are no # resources to reclaim. call_async(q, chan.Hold, 'RequestHold', False) q.expect('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]) q.expect('dbus-signal', signal='HoldStateChanged', args=[cs.HS_UNHELD, cs.HSR_REQUESTED]) assertEquals((cs.HS_UNHELD, cs.HSR_REQUESTED), chan.Hold.GetHoldState()) # Put the call back on hold ... call_async(q, chan.Hold, 'RequestHold', True) q.expect('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]) q.expect('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]) assertEquals((cs.HS_HELD, cs.HSR_REQUESTED), chan.Hold.GetHoldState()) # ... and request a stream. chan.StreamedMedia.RequestStreams(handle, [cs.MEDIA_STREAM_TYPE_AUDIO]) # S-E gets notified about new session handler, and calls Ready on it e = q.expect('dbus-signal', signal='NewSessionHandler') assert e.args[1] == 'rtp' session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() e = q.expect('dbus-signal', signal='NewStreamHandler') stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') # Syncing here to make sure SetStreamHeld happens after Ready... sync_dbus(bus, q, conn) stream_handler.Ready(jt.get_audio_codecs_dbus()) stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) # Now Gabble tells the streaming implementation to go on hold (because it # said it was Ready), and the session is initiated. e = q.expect_many( EventPattern('dbus-signal', signal='SetStreamHeld', args=[True]), EventPattern('stream-iq', predicate=jp.action_predicate('session-initiate')), )[1] # Ensure that if Gabble sent the <hold/> stanza too early it's already # arrived. sync_stream(q, stream) q.unforbid_events(hold_event) stream.send(make_result_iq(stream, e.stanza)) # We've acked the s-i, so we do speak Jingle; Gabble should send the # <hold/> notification. q.expect_many(*hold_event) # The call's still on hold, both before and after the streaming # implementation says it's okay with that (re-entering PENDING_HOLD seems # silly). assertEquals((cs.HS_HELD, cs.HSR_REQUESTED), chan.Hold.GetHoldState()) stream_handler.HoldState(True) assertEquals((cs.HS_HELD, cs.HSR_REQUESTED), chan.Hold.GetHoldState()) # The peer answers the call; they're still on hold. jt.parse_session_initiate(e.query) jt.accept() q.expect('stream-iq', iq_type='result') assertEquals((cs.HS_HELD, cs.HSR_REQUESTED), chan.Hold.GetHoldState()) # Now we decide we do actually want to speak to them, and unhold. # Ensure that if Gabble sent the <unhold/> stanza too early it's already # arrived. sync_stream(q, stream) q.forbid_events(unhold_event) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[False]), EventPattern('dbus-return', method='RequestHold', value=()), ) # Ensure that if Gabble sent the <unhold/> stanza too early it's already # arrived. sync_stream(q, stream) q.unforbid_events(unhold_event) call_async(q, stream_handler, 'HoldState', False) q.expect_many( EventPattern('dbus-return', method='HoldState', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_UNHELD, cs.HSR_REQUESTED]), *unhold_event ) # Hooray! Now let's check that Hold works properly once the call's fully # established. # ---- Test 1: GetHoldState returns unheld and unhold is a no-op ---- hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_UNHELD, hold_state chan.Hold.RequestHold(False) # ---- Test 2: successful hold ---- call_async(q, chan.Hold, 'RequestHold', True) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[True]), EventPattern('dbus-return', method='RequestHold', value=()), *hold_event ) call_async(q, stream_handler, 'HoldState', True) q.expect_many( EventPattern('dbus-return', method='HoldState', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]), ) # ---- Test 3: GetHoldState returns held and hold is a no-op ---- hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_HELD, hold_state chan.Hold.RequestHold(True) # ---- Test 4: successful unhold ---- q.forbid_events(unhold_event) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[False]), EventPattern('dbus-return', method='RequestHold', value=()), ) # Ensure that if Gabble sent the <unhold/> stanza too early it's already # arrived. sync_stream(q, stream) q.unforbid_events(unhold_event) call_async(q, stream_handler, 'HoldState', False) q.expect_many( EventPattern('dbus-return', method='HoldState', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_UNHELD, cs.HSR_REQUESTED]), *unhold_event ) # ---- Test 5: GetHoldState returns False and unhold is a no-op ---- hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_UNHELD, hold_state chan.Hold.RequestHold(False) # ---- Test 6: 3 parallel calls to hold ---- hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_UNHELD, hold_state call_async(q, chan.Hold, 'RequestHold', True) call_async(q, chan.Hold, 'RequestHold', True) call_async(q, chan.Hold, 'RequestHold', True) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[True]), EventPattern('dbus-return', method='RequestHold', value=()), *hold_event ) call_async(q, stream_handler, 'HoldState', True) q.expect_many( EventPattern('dbus-return', method='HoldState', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]), ) # ---- Test 7: 3 parallel calls to unhold ---- q.forbid_events(unhold_event) call_async(q, chan.Hold, 'RequestHold', False) call_async(q, chan.Hold, 'RequestHold', False) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[False]), EventPattern('dbus-return', method='RequestHold', value=()), ) # Ensure that if Gabble sent the <unhold/> stanza too early it's already # arrived. sync_stream(q, stream) q.unforbid_events(unhold_event) call_async(q, stream_handler, 'HoldState', False) q.expect_many( EventPattern('dbus-return', method='HoldState', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_UNHELD, cs.HSR_REQUESTED]), *unhold_event ) # ---- Test 8: hold, then change our minds before s-e has responded ---- hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_UNHELD, hold_state call_async(q, chan.Hold, 'RequestHold', True) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[True]), *hold_event ) q.forbid_events(unhold_event) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[False]), # Gabble shouldn't send <unhold/> here because s-e might have already # relinquished the audio hardware. ) sync_stream(q, stream) q.unforbid_events(unhold_event) call_async(q, stream_handler, 'HoldState', True) q.expect('dbus-return', method='HoldState', value=()) call_async(q, stream_handler, 'HoldState', False) q.expect_many( EventPattern('dbus-return', method='HoldState', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_UNHELD, cs.HSR_REQUESTED]), *unhold_event ) hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_UNHELD, hold_state # ---- Test 9: unhold, then change our minds before s-e has responded ---- # Go to state "held" first call_async(q, chan.Hold, 'RequestHold', True) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[True]), EventPattern('dbus-return', method='RequestHold', value=()), *hold_event ) call_async(q, stream_handler, 'HoldState', True) q.expect_many( EventPattern('dbus-return', method='HoldState', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]), ) # Actually do test 9 hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_HELD, hold_state # Check that Gabble doesn't send another <hold/>, or send <unhold/> before # we change our minds. q.forbid_events(unhold_event + hold_event) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[False]), ) call_async(q, chan.Hold, 'RequestHold', True) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[True]), ) call_async(q, stream_handler, 'HoldState', False) call_async(q, stream_handler, 'HoldState', True) q.expect_many( EventPattern('dbus-return', method='HoldState', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]), ) hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_HELD, hold_state sync_stream(q, stream) q.unforbid_events(unhold_event + hold_event) # ---- Test 10: attempting to unhold fails ---- # Check that Gabble doesn't send another <hold/>, or send <unhold/> even # though unholding fails. q.forbid_events(unhold_event + hold_event) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[False]), EventPattern('dbus-return', method='RequestHold', value=()), ) call_async(q, stream_handler, 'UnholdFailure') q.expect_many( EventPattern('dbus-return', method='UnholdFailure', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_RESOURCE_NOT_AVAILABLE]), ) sync_stream(q, stream) q.unforbid_events(unhold_event + hold_event) # ---- Test 11: when we successfully unhold, the peer gets <unhold/> --- q.forbid_events(unhold_event) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SetStreamHeld', args=[False]), EventPattern('dbus-return', method='RequestHold', value=()), ) # Ensure that if Gabble sent the <unhold/> stanza too early it's already # arrived. sync_stream(q, stream) q.unforbid_events(unhold_event) call_async(q, stream_handler, 'HoldState', False) q.expect_many( EventPattern('dbus-return', method='HoldState', value=()), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_UNHELD, cs.HSR_REQUESTED]), *unhold_event ) # ---- The end ---- chan.Group.RemoveMembers([self_handle], 'closed') # Test completed, close the connection e = q.expect('dbus-signal', signal='Close') #XXX - match against the path if __name__ == '__main__': test_all_dialects(test) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/call-hold-audio.py�������������������������������������0000664�0001750�0001750�00000067504�12225363340�025617� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test the Hold API. """ import dbus from dbus.exceptions import DBusException from functools import partial from servicetest import call_async, EventPattern, assertEquals, assertLength from jingletest2 import test_all_dialects from gabbletest import sync_stream from call_helper import CallTest, run_call_test import constants as cs from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) class CallHoldAudioTest(CallTest): def initiate(self): CallTest.initiate(self) q = self.q jp = self.jp cstream = self.audio_stream chan = self.chan recv_state = cstream.GetAll(cs.CALL_STREAM_IFACE_MEDIA, dbus_interface=dbus.PROPERTIES_IFACE)["ReceivingState"] send_state = cstream.GetAll(cs.CALL_STREAM_IFACE_MEDIA, dbus_interface=dbus.PROPERTIES_IFACE)["SendingState"] assertEquals (cs.CALL_STREAM_FLOW_STATE_STOPPED, recv_state) assertEquals (cs.CALL_STREAM_FLOW_STATE_STOPPED, send_state) # These are 0- (for old dialects) or 1- (for new dialects) element lists # that can be splatted into expect_many with * self.hold_event = jp.rtp_info_event_list("hold") self.unhold_event = jp.rtp_info_event_list("unhold") # Before we have accepted any streams, GetHoldState returns Unheld and # unhold is a no-op. assertEquals((cs.HS_UNHELD, cs.HSR_REQUESTED), chan.Hold.GetHoldState()) chan.Hold.RequestHold(False) q.forbid_events(self.hold_event) q.forbid_events(self.unhold_event) assertEquals((cs.HS_UNHELD, cs.HSR_REQUESTED), chan.Hold.GetHoldState()) chan.Hold.RequestHold(False) # Before we have any streams, RequestHold(True) should work; because # there are no streams, it should take effect at once. It certainly # should't send anything to the peer. q.forbid_events(self.hold_event) q.forbid_events(self.unhold_event) call_async(q, chan.Hold, 'RequestHold', True) q.expect('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]) q.expect('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]) assertEquals((cs.HS_HELD, cs.HSR_REQUESTED), chan.Hold.GetHoldState()) # If we unhold, it should succeed immediately again, because there are # no resources to reclaim. call_async(q, chan.Hold, 'RequestHold', False) q.expect('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]) q.expect('dbus-signal', signal='HoldStateChanged', args=[cs.HS_UNHELD, cs.HSR_REQUESTED]) assertEquals((cs.HS_UNHELD, cs.HSR_REQUESTED), chan.Hold.GetHoldState()) # Put the call back on hold ... call_async(q, chan.Hold, 'RequestHold', True) q.expect('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]) q.expect('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]) assertEquals((cs.HS_HELD, cs.HSR_REQUESTED), chan.Hold.GetHoldState()) def connect(self): assertEquals((cs.HS_HELD, cs.HSR_REQUESTED), self.chan.Hold.GetHoldState()) assertEquals((cs.HS_HELD, cs.HSR_REQUESTED), self.chan.Hold.GetHoldState()) CallTest.connect(self, expect_after_si=self.hold_event) def accept_outgoing(self): # We are on hold, no states to complete here self.check_channel_state(cs.CALL_STATE_PENDING_INITIATOR) self.chan.Accept(dbus_interface=cs.CHANNEL_TYPE_CALL) self.check_channel_state(cs.CALL_STATE_INITIALISING) def pickup(self): CallTest.pickup(self, held=True) q = self.q stream = self.stream chan = self.chan cstream = self.audio_stream assertEquals((cs.HS_HELD, cs.HSR_REQUESTED), chan.Hold.GetHoldState()) recv_state = cstream.Get(cs.CALL_STREAM_IFACE_MEDIA, "ReceivingState", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals (cs.CALL_STREAM_FLOW_STATE_STOPPED, recv_state) send_state = cstream.Get(cs.CALL_STREAM_IFACE_MEDIA, "SendingState", dbus_interface=dbus.PROPERTIES_IFACE) assertEquals (cs.CALL_STREAM_FLOW_STATE_STOPPED, send_state) # Now we decide we do actually want to speak to them, and unhold. # Ensure that if Gabble sent the <unhold/> stanza too early it's already # arrived. sync_stream(q, stream) q.forbid_events(self.unhold_event) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-return', method='RequestHold', value=()), ) # Ensure that if Gabble sent the <unhold/> stanza too early it's already # arrived. sync_stream(q, stream) q.unforbid_events(self.unhold_event) cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_UNHELD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), *self.unhold_event ) # Hooray! Now let's check that Hold works properly once the call's fully # established. # ---- Test 1: GetHoldState returns unheld and unhold is a no-op ---- hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_UNHELD, hold_state chan.Hold.RequestHold(False) # ---- Test 2: successful hold ---- call_async(q, chan.Hold, 'RequestHold', True) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-return', method='RequestHold', value=()), *self.hold_event ) cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), ) # ---- Test 3: GetHoldState returns held and hold is a no-op ---- hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_HELD, hold_state chan.Hold.RequestHold(True) # ---- Test 4: successful unhold ---- q.forbid_events(self.unhold_event) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-return', method='RequestHold', value=()), ) # Ensure that if Gabble sent the <unhold/> stanza too early it's already # arrived. sync_stream(q, stream) q.unforbid_events(self.unhold_event) cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_UNHELD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), *self.unhold_event ) # ---- Test 5: GetHoldState returns False and unhold is a no-op ---- hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_UNHELD, hold_state chan.Hold.RequestHold(False) # ---- Test 6: 3 parallel calls to hold ---- hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_UNHELD, hold_state call_async(q, chan.Hold, 'RequestHold', True) call_async(q, chan.Hold, 'RequestHold', True) call_async(q, chan.Hold, 'RequestHold', True) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-return', method='RequestHold', value=()), *self.hold_event ) cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]), ) # ---- Test 7: 3 parallel calls to unhold ---- q.forbid_events(self.unhold_event) call_async(q, chan.Hold, 'RequestHold', False) call_async(q, chan.Hold, 'RequestHold', False) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-return', method='RequestHold', value=()), ) # Ensure that if Gabble sent the <unhold/> stanza too early it's already # arrived. sync_stream(q, stream) q.unforbid_events(self.unhold_event) cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_UNHELD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), *self.unhold_event ) # ---- Test 8: hold, then change our minds before s-e has responded ---- hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_UNHELD, hold_state call_async(q, chan.Hold, 'RequestHold', True) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), *self.hold_event ) q.forbid_events(self.unhold_event) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), # Gabble shouldn't send <unhold/> here because s-e might have # already relinquished the audio hardware. ) sync_stream(q, stream) q.unforbid_events(self.unhold_event) try: cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) except dbus.DBusException, e: assertEquals (cs.INVALID_ARGUMENT, e.get_dbus_name ()) try: cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) except dbus.DBusException, e: assertEquals (cs.INVALID_ARGUMENT, e.get_dbus_name ()) cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_UNHELD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), *self.unhold_event ) hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_UNHELD, hold_state # ---- Test 9: unhold, then change our minds before s-e has responded -- # Go to state "held" first call_async(q, chan.Hold, 'RequestHold', True) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-return', method='RequestHold', value=()), *self.hold_event ) cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]), ) # Actually do test 9 hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_HELD, hold_state # Check that Gabble doesn't send another <hold/>, or send <unhold/> # before we change our minds. q.forbid_events(self.unhold_event + self.hold_event) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), ) call_async(q, chan.Hold, 'RequestHold', True) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), ) cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_REQUESTED]), ) hold_state = chan.Hold.GetHoldState() assert hold_state[0] == cs.HS_HELD, hold_state sync_stream(q, stream) q.unforbid_events(self.unhold_event + self.hold_event) # ---- Test 10: attempting to unhold fails in the sending bit ---- # Check that Gabble doesn't send another <hold/>, or send <unhold/> even # though unholding fails. q.forbid_events(self.unhold_event + self.hold_event) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-return', method='RequestHold', value=()), ) cstream.ReportSendingFailure(0, "", "", dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_RESOURCE_NOT_AVAILABLE]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), ) cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_RESOURCE_NOT_AVAILABLE]), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), ) # ---- Test 11: attempting to unhold fails in the receiving bit ---- call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-return', method='RequestHold', value=()), ) cstream.ReportReceivingFailure(0, "", "", dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_HOLD, cs.HSR_RESOURCE_NOT_AVAILABLE]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_STOP], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), ) cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STOPPED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_HELD, cs.HSR_RESOURCE_NOT_AVAILABLE]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STOPPED], interface = cs.CALL_STREAM_IFACE_MEDIA), ) sync_stream(q, stream) q.unforbid_events(self.unhold_event + self.hold_event) # ---- Test 12: when we successfully unhold, the peer gets <unhold/> --- q.forbid_events(self.unhold_event) call_async(q, chan.Hold, 'RequestHold', False) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_PENDING_UNHOLD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_PENDING_START], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-return', method='RequestHold', value=()), ) # Ensure that if Gabble sent the <unhold/> stanza too early it's already # arrived. sync_stream(q, stream) q.unforbid_events(self.unhold_event) cstream.CompleteReceivingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) cstream.CompleteSendingStateChange( cs.CALL_STREAM_FLOW_STATE_STARTED, dbus_interface = cs.CALL_STREAM_IFACE_MEDIA) q.expect_many( EventPattern('dbus-signal', signal='HoldStateChanged', args=[cs.HS_UNHELD, cs.HSR_REQUESTED]), EventPattern('dbus-signal', signal='SendingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), EventPattern('dbus-signal', signal='ReceivingStateChanged', args = [cs.CALL_STREAM_FLOW_STATE_STARTED], interface = cs.CALL_STREAM_IFACE_MEDIA), *self.unhold_event ) if __name__ == '__main__': test_all_dialects(partial(run_call_test, klass=CallHoldAudioTest, incoming=False)) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/call-state.py������������������������������������������0000664�0001750�0001750�00000026051�12332441362�024702� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test exposing incoming <hold/>, <ringing/> and <active/> notifications via the CallState interface. """ from twisted.words.xish import xpath from gabbletest import make_result_iq from servicetest import ( wrap_channel, make_channel_proxy, EventPattern, sync_dbus) import ns import constants as cs from jingletest2 import JingleTest2, test_all_dialects from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test(jp, q, bus, conn, stream): remote_jid = 'foo@bar.com/Foo' jt = JingleTest2(jp, conn, q, stream, 'test@localhost', remote_jid) jt.prepare() self_handle = conn.GetSelfHandle() handle = conn.RequestHandles(cs.HT_CONTACT, [remote_jid])[0] path = conn.RequestChannel(cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.HT_CONTACT, handle, True) chan = wrap_channel(bus.get_object(conn.bus_name, path), 'StreamedMedia', ['MediaSignalling', 'Group', 'CallState']) chan_props = chan.Properties.GetAll(cs.CHANNEL) assert cs.CHANNEL_IFACE_CALL_STATE in chan_props['Interfaces'], \ chan_props['Interfaces'] call_states = chan.CallState.GetCallStates() assert call_states == { handle: 0 } or \ call_states == {}, call_states chan.StreamedMedia.RequestStreams(handle, [cs.MEDIA_STREAM_TYPE_AUDIO]) # S-E gets notified about new session handler, and calls Ready on it e = q.expect('dbus-signal', signal='NewSessionHandler') assert e.args[1] == 'rtp' session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() e = q.expect('dbus-signal', signal='NewStreamHandler') audio_path = e.args[0] stream_handler = make_channel_proxy(conn, audio_path, 'Media.StreamHandler') stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) stream_handler.Ready(jt.get_audio_codecs_dbus()) stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) e = q.expect('stream-iq', predicate=jp.action_predicate('session-initiate')) stream.send(make_result_iq(stream, e.stanza)) jt.parse_session_initiate(e.query) if jp.is_modern_jingle(): # The other person's client starts ringing, and tells us so! node = jp.SetIq(jt.peer, jt.jid, [ jp.Jingle(jt.sid, jt.jid, 'session-info', [ ('ringing', ns.JINGLE_RTP_INFO_1, {}, []) ]) ]) stream.send(jp.xml(node)) # If this is an old Jingle dialect, Gabble should treat the # session-initiate ack as ringing notification; if it's modern Jingle, we # just sent a ringing notification. q.expect('dbus-signal', signal='CallStateChanged', args=[handle, cs.CALL_STATE_RINGING]) call_states = chan.CallState.GetCallStates() assert call_states == { handle: cs.CALL_STATE_RINGING }, call_states if jp.is_modern_jingle(): # We're waiting in a queue, so the other person's client tells us we're on # hold. Gabble should ack the IQ, and set the call state to Ringing | Held. # Also, Gabble certainly shouldn't tell s-e to start sending. (Although it # might tell it not to; we don't mind.) node = jp.SetIq(jt.peer, jt.jid, [ jp.Jingle(jt.sid, jt.jid, 'session-info', [ ('hold', ns.JINGLE_RTP_INFO_1, {}, []) ]) ]) stream.send(jp.xml(node)) forbidden = [ EventPattern('dbus-signal', signal='SetStreamSending', args=[True], path=audio_path), ] q.forbid_events(forbidden) q.expect_many( EventPattern('stream-iq', iq_type='result', iq_id=node[2]['id']), EventPattern('dbus-signal', signal='CallStateChanged', args=[handle, cs.CALL_STATE_RINGING | cs.CALL_STATE_HELD]), ) call_states = chan.CallState.GetCallStates() assert call_states == { handle: cs.CALL_STATE_RINGING | cs.CALL_STATE_HELD }, call_states # We're at the head of a queue, so the other person's client tells us we're # no longer on hold. The call centre phone's still ringing, though. s-e # still shouldn't start sending. node = jp.SetIq(jt.peer, jt.jid, [ jp.Jingle(jt.sid, jt.jid, 'session-info', [ ('unhold', ns.JINGLE_RTP_INFO_1, {}, []) ]) ]) stream.send(jp.xml(node)) q.expect_many( EventPattern('stream-iq', iq_type='result', iq_id=node[2]['id']), EventPattern('dbus-signal', signal='CallStateChanged', args=[handle, cs.CALL_STATE_RINGING]), ) call_states = chan.CallState.GetCallStates() assert call_states == { handle: cs.CALL_STATE_RINGING }, call_states sync_dbus(bus, q, conn) q.unforbid_events(forbidden) jt.accept() if jp.is_modern_jingle(): # The other person's client decides it's not ringing any more node = jp.SetIq(jt.peer, jt.jid, [ jp.Jingle(jt.sid, jt.jid, 'session-info', [ ('active', ns.JINGLE_RTP_INFO_1, {}, []) ]) ]) stream.send(jp.xml(node)) # Gabble tells s-e to start sending, and removes the Ringing flag, either # because we got <active/> or because of the session-accept in ye olde # Jingle. q.expect_many( EventPattern('dbus-signal', signal='SetStreamSending', args=[True], path=audio_path), EventPattern('dbus-signal', signal='CallStateChanged', args=[ handle, 0 ]), ) call_states = chan.CallState.GetCallStates() assert call_states == { handle: 0 } or call_states == {}, call_states # The rest of the test concerns things we only support in the glorious # modern Jingle future. if not jp.is_modern_jingle(): return # The other person puts us on hold. Gabble should ack the session-info IQ, # tell s-e to stop sending on the held stream, and set the call state. node = jp.SetIq(jt.peer, jt.jid, [ jp.Jingle(jt.sid, jt.jid, 'session-info', [ ('hold', ns.JINGLE_RTP_INFO_1, {}, []) ]) ]) stream.send(jp.xml(node)) q.expect_many( EventPattern('stream-iq', iq_type='result', iq_id=node[2]['id']), EventPattern('dbus-signal', signal='SetStreamSending', args=[False], path=audio_path), EventPattern('dbus-signal', signal='CallStateChanged', args=[handle, cs.CALL_STATE_HELD]), ) call_states = chan.CallState.GetCallStates() assert call_states == { handle: cs.CALL_STATE_HELD }, call_states # The peer pings us with an empty session-info; Gabble should just ack it. node = jp.SetIq(jt.peer, jt.jid, [ jp.Jingle(jt.sid, jt.jid, 'session-info', [])]) stream.send(jp.xml(node)) q.expect('stream-iq', iq_type='result', iq_id=node[2]['id']) call_states = chan.CallState.GetCallStates() assert call_states == { handle: cs.CALL_STATE_HELD }, call_states # The peer sends us some unknown-namespaced misc in a session-info; Gabble # should nak it with <unsupported-info/> node = jp.SetIq(jt.peer, jt.jid, [ jp.Jingle(jt.sid, jt.jid, 'session-info', [ ('boiling', 'com.example.Kettle', {}, []) ]) ]) stream.send(jp.xml(node)) e = q.expect('stream-iq', iq_type='error', iq_id=node[2]['id']) xpath.queryForNodes("/jingle/error/unsupported-info", e.query) call_states = chan.CallState.GetCallStates() assert call_states == { handle: cs.CALL_STATE_HELD }, call_states # The other person unholds us; Gabble should ack the session-info IQ, tell # s-e to start sending on the now-active stream, and set the call state. node = jp.SetIq(jt.peer, jt.jid, [ jp.Jingle(jt.sid, jt.jid, 'session-info', [ ('active', ns.JINGLE_RTP_INFO_1, {}, []) ]) ]) stream.send(jp.xml(node)) q.expect_many( EventPattern('stream-iq', iq_type='result', iq_id=node[2]['id']), EventPattern('dbus-signal', signal='SetStreamSending', args=[True], path=audio_path), EventPattern('dbus-signal', signal='CallStateChanged', args=[handle, 0]), ) call_states = chan.CallState.GetCallStates() assert call_states == { handle: 0 } or call_states == {}, call_states # Okay, let's get a second stream involved! chan.StreamedMedia.RequestStreams(handle, [cs.MEDIA_STREAM_TYPE_VIDEO]) e = q.expect('dbus-signal', signal='NewStreamHandler') video_path = e.args[0] stream_handler2 = make_channel_proxy(conn, video_path, 'Media.StreamHandler') stream_handler2.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) stream_handler2.Ready(jt.get_video_codecs_dbus()) stream_handler2.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) e = q.expect('stream-iq', predicate=jp.action_predicate('content-add')) stream.send(make_result_iq(stream, e.stanza)) jt.content_accept(e.query, 'video') q.expect('dbus-signal', signal='SetStreamSending', args=[True], path=video_path) call_states = chan.CallState.GetCallStates() assert call_states == { handle: 0 } or call_states == {}, call_states # The other person puts us on hold. Gabble should ack the session-info IQ, # tell s-e to stop sending on both streams, and set the call state. node = jp.SetIq(jt.peer, jt.jid, [ jp.Jingle(jt.sid, jt.jid, 'session-info', [ ('hold', ns.JINGLE_RTP_INFO_1, {}, []) ]) ]) stream.send(jp.xml(node)) q.expect_many( EventPattern('stream-iq', iq_type='result', iq_id=node[2]['id']), EventPattern('dbus-signal', signal='SetStreamSending', args=[False], path=audio_path), EventPattern('dbus-signal', signal='SetStreamSending', args=[False], path=video_path), EventPattern('dbus-signal', signal='CallStateChanged', args=[handle, cs.CALL_STATE_HELD]), ) call_states = chan.CallState.GetCallStates() assert call_states == { handle: cs.CALL_STATE_HELD }, call_states # Now the other person sets the audio stream to mute. We can't represent # mute yet, but Gabble shouldn't take this to mean the call is active, as # one stream being muted doesn't change the fact that the call's on hold. # FIXME: hardcoded stream id node = jp.SetIq(jt.peer, jt.jid, [ jp.Jingle(jt.sid, jt.jid, 'session-info', [ ('mute', ns.JINGLE_RTP_INFO_1, {'name': 'Audio', 'creator': 'initiator'}, []) ]) ]) stream.send(jp.xml(node)) forbidden = [ EventPattern('dbus-signal', signal='SetStreamSending', args=[True], path=audio_path), EventPattern('dbus-signal', signal='CallStateChanged', args=[ handle, 0 ]), ] q.forbid_events(forbidden) q.expect('stream-iq', iq_type='result', iq_id=node[2]['id']) call_states = chan.CallState.GetCallStates() assert call_states == { handle: cs.CALL_STATE_HELD }, call_states sync_dbus(bus, q, conn) q.unforbid_events(forbidden) # That'll do, pig. chan.Group.RemoveMembers([self_handle], 'closed') e = q.expect('dbus-signal', signal='Close') #XXX - match against the path if __name__ == '__main__': test_all_dialects(test) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/jingle/dtmf-no-audio.py���������������������������������������0000664�0001750�0001750�00000005467�12332441362�025324� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test inability to send DTMF events on a video-only call. """ from twisted.words.xish import xpath from gabbletest import make_result_iq from servicetest import (call_async, wrap_channel, make_channel_proxy, EventPattern, sync_dbus) import constants as cs from jingletest2 import JingleTest2, test_all_dialects from config import VOIP_ENABLED if not VOIP_ENABLED: print "NOTE: built with --disable-voip" raise SystemExit(77) def test(jp, q, bus, conn, stream): if not jp.can_do_video_only(): return remote_jid = 'foo@bar.com/Foo' jt = JingleTest2(jp, conn, q, stream, 'test@localhost', remote_jid) jt.prepare() self_handle = conn.GetSelfHandle() handle = conn.RequestHandles(cs.HT_CONTACT, [remote_jid])[0] chan_path = conn.RequestChannel(cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.HT_CONTACT, handle, True) chan = wrap_channel(bus.get_object(conn.bus_name, chan_path), 'StreamedMedia', ['MediaSignalling', 'Group', 'CallState', 'DTMF']) chan_props = chan.Properties.GetAll(cs.CHANNEL) assert cs.CHANNEL_IFACE_DTMF in chan_props['Interfaces'], \ chan_props['Interfaces'] chan.StreamedMedia.RequestStreams(handle, [cs.MEDIA_STREAM_TYPE_VIDEO]) # S-E gets notified about new session handler, and calls Ready on it e = q.expect('dbus-signal', signal='NewSessionHandler') assert e.args[1] == 'rtp' session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() e = q.expect('dbus-signal', signal='NewStreamHandler') video_path = e.args[0] stream_handler = make_channel_proxy(conn, video_path, 'Media.StreamHandler') stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) stream_handler.Ready(jt.get_video_codecs_dbus()) stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) e = q.expect('stream-iq', predicate=jp.action_predicate('session-initiate')) stream.send(make_result_iq(stream, e.stanza)) jt.parse_session_initiate(e.query) jt.accept() # Gabble tells s-e to start sending q.expect('dbus-signal', signal='SetStreamSending', args=[True], path=video_path) # We don't actually have an audio stream, so this is a non-starter. call_async(q, chan.DTMF, 'StartTone', 666, 3) q.expect('dbus-error', method='StartTone', name=cs.NOT_AVAILABLE) call_async(q, chan.DTMF, 'MultipleTones', '**666##') q.expect('dbus-error', method='MultipleTones', name=cs.NOT_AVAILABLE) # We can still stop all the tones that are playing (a no-op). call_async(q, chan.DTMF, 'StopTone', 666) q.expect('dbus-return', method='StopTone') chan.Group.RemoveMembers([self_handle], 'closed') e = q.expect('dbus-signal', signal='Closed', path=chan_path) if __name__ == '__main__': test_all_dialects(test) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/��������������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�022131� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/disconnect-during-pep.py��������������������������������0000664�0001750�0001750�00000002257�12332441362�026703� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Regression test for https://bugs.freedesktop.org/show_bug.cgi?id=31412 """ import dbus from servicetest import call_async, EventPattern, sync_dbus from gabbletest import (exec_test, make_result_iq, acknowledge_iq, disconnect_conn) import constants as cs def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) handle = conn.RequestHandles(cs.HT_CONTACT, ['bob@foo.com'])[0] call_async(q, conn.Aliasing, 'RequestAliases', [handle]) # First, Gabble sends a PEP query event = q.expect('stream-iq', to='bob@foo.com', iq_type='get', query_ns='http://jabber.org/protocol/pubsub', query_name='pubsub') # We disconnect too soon to get a reply disconnect_conn(q, conn, stream) # fd.o #31412 was that while the request pipeline was shutting down, # it would give the PEP query an error; the aliasing code would # respond by falling back to vCard via the request pipeline, which # was no longer there, *crash*. # check that Gabble hasn't crashed sync_dbus(bus, q, conn) if __name__ == '__main__': exec_test(test) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/test-avatar-multiple-resources.py�����������������������0000644�0001750�0001750�00000004452�12225363340�030573� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test avatar support with multiple resources as defined in XEP-0153 section 4.3. """ import base64 from twisted.words.xish import domish from servicetest import call_async, EventPattern, sync_dbus from gabbletest import exec_test, acknowledge_iq, make_result_iq, sync_stream import constants as cs import ns def make_presence(jid, sha1sum): p = domish.Element((None, 'presence')) p['from'] = jid x = p.addElement((ns.VCARD_TEMP_UPDATE, 'x')) x.addElement('photo', content=sha1sum) return p def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) sync_stream(q, stream) sync_dbus(bus, q, conn) # A presence from a contact stream.send(make_presence('contact1@localhost/client', 'SHA1SUM-FOR-CONTACT1')) event = q.expect('dbus-signal', signal='AvatarUpdated') assert event.args[0] == 2, event.args assert event.args[1] == "SHA1SUM-FOR-CONTACT1", event.args AvatarRetrieved_event = EventPattern('dbus-signal', signal='AvatarRetrieved') AvatarUpdated_event = EventPattern('dbus-signal', signal='AvatarUpdated') StreamPresence_event = EventPattern('stream-presence') StreamIqVcard_event = EventPattern('stream-iq', query_ns='vcard-temp') # A presence from myself on another resource stream.send(make_presence('test@localhost/resource1', 'SHA1SUM-FOR-MYSELF-RES1')) q.forbid_events([AvatarRetrieved_event, AvatarUpdated_event]) stream_presence, stream_iq = q.expect_many( EventPattern('stream-presence'), EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard')) sync_dbus(bus, q, conn) q.unforbid_events([AvatarRetrieved_event, AvatarUpdated_event]) # If the server wrongly send a presence stanza with our resource, # AvatarUpdated must not be emitted q.forbid_events([StreamPresence_event, StreamIqVcard_event, AvatarRetrieved_event, AvatarUpdated_event]) stream.send(make_presence('test@localhost/Resource', 'SHA1SUM-FOR-MYSELF')) sync_dbus(bus, q, conn) sync_stream(q, stream) q.unforbid_events([StreamPresence_event, StreamIqVcard_event, AvatarRetrieved_event, AvatarUpdated_event]) if __name__ == '__main__': exec_test(test) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/test-alias.py�������������������������������������������0000664�0001750�0001750�00000003116�12332441362�024543� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test alias support. """ from servicetest import call_async, EventPattern from gabbletest import exec_test, make_result_iq, acknowledge_iq import constants as cs def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) handle = conn.RequestHandles(1, ['bob@foo.com'])[0] call_async(q, conn.Aliasing, 'RequestAliases', [handle]) # Nack PEP query. event = q.expect('stream-iq', to='bob@foo.com', iq_type='get', query_ns='http://jabber.org/protocol/pubsub', query_name='pubsub') items = event.query.firstChildElement() assert items.name == 'items' assert items['node'] == "http://jabber.org/protocol/nick" result = make_result_iq(stream, event.stanza) result['type'] = 'error' error = result.addElement('error') error['type'] = 'auth' error.addElement('forbidden', 'urn:ietf:params:xml:ns:xmpp-stanzas') stream.send(result) event = q.expect('stream-iq', to='bob@foo.com', query_ns='vcard-temp', query_name='vCard') result = make_result_iq(stream, event.stanza) vcard = result.firstChildElement() vcard.addElement('NICKNAME', content='Bobby') stream.send(result) q.expect('dbus-signal', signal='AliasesChanged', args=[[(handle, u'Bobby')]]) q.expect('dbus-return', method='RequestAliases', value=(['Bobby'],)) # A second request should be satisfied from the cache. assert conn.Aliasing.RequestAliases([handle]) == ['Bobby'] if __name__ == '__main__': exec_test(test) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/set-avatar.py�������������������������������������������0000664�0001750�0001750�00000006607�12225363340�024554� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Tests the very simple case of "setting your own avatar". """ from twisted.words.xish import xpath from servicetest import call_async, assertEquals from gabbletest import ( exec_test, expect_and_handle_get_vcard, expect_and_handle_set_vcard, ) import base64 import functools def test(q, bus, conn, stream, image_data, mime_type): call_async(q, conn.Avatars, 'SetAvatar', image_data, mime_type) expect_and_handle_get_vcard(q, stream) def check(vcard): assertEquals(mime_type, xpath.queryForString('/vCard/PHOTO/TYPE', vcard)) binval = xpath.queryForString('/vCard/PHOTO/BINVAL', vcard) # <http://xmpp.org/extensions/xep-0153.html#bizrules-image> says: # # 5. The image data MUST conform to the base64Binary datatype and thus # be encoded in accordance with Section 6.8 of RFC 2045, which # recommends that base64 data should have lines limited to at most # 76 characters in length. lines = binval.split('\n') for line in lines: assert len(line) <= 76, line assertEquals(image_data, base64.decodestring(binval)) expect_and_handle_set_vcard(q, stream, check=check) q.expect('dbus-return', method='SetAvatar') def test_little_avatar(q, bus, conn, stream): test(q, bus, conn, stream, image_data='Guy.brush', mime_type='image/x-mighty-pirate') def test_massive_avatar(q, bus, conn, stream): """Regression test for <https://bugs.freedesktop.org/show_bug.cgi?id=57080>, where a too-small buffer was allocated if the base64-encoded avatar spanned multiple lines. """ avatar = '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\xec\x00\x00\x00\x94\x04\x03\x00\x00\x00b\x8c\xd8\x8b\x00\x00\x00\x18PLTEap\x00\xff\x99\x99\xff\xff\xff\xff3\x99\xff\xcc\x99\x99\x99\x99\xff\x99\xff\x00\x00\x00\xcdt\xca\x11\x00\x00\x00\x01tRNS\x00@\xe6\xd8f\x00\x00\x00\x01bKGD\x00\x88\x05\x1dH\x00\x00\x00\tpHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xdc\x0b\x0e\x0f"%\xd9\xcd\xe5\x8c\x00\x00\x01\x88IDATx\xda\xed\xdb=n\xc20\x14\xc0\xf1l\xcc\x0c\\ K\x0f\x10\t.P\x95\xb9\x95\x10\x07\xa0jW\x96\xe0\xeb\x97\x90 ?\xdb\x0f;\x1f.i\xa3\xff\x9bBb\xfb\x17$\xec\xbc\xd8\xa6(ba\xa6E12`aa\xc7\xb2\xd7z\xaf\xd3\xe2\xda\xc2\x19\x16vN\xd68\xe6\xdb\xd7\xb0\xf8\xb4U\xf7\x83\xfa\x11,,l\x1eVm\xf8TU\xd5\xd6\x1eo\xc3\x12\xb0\xb0\xb03\xb1\n2$`aa\xe7c\xe3\xf1\xdd\xbeU^\xc2[\x14\xec\xaa-t\x86\x85\xfd\x93lC\xd6\x87[\x1c-\xedu \xe3\x16\x82\x85\x85\x9d\xca\xea\xb3\x93QVd\xa8\x82\xedZ\xbd\x84\xec\xc1)\x00\x0b\x0b\x9b\x83\x15\xa7\xee\xf2\x88\xe1\xc2k\xc5\x1d&`a\x9f\xc0\x1a\xf1#\x175\\\xb6ID\xfb\xb0\xf1\x80\x85\x85\xcd\xc1Z\xb9\xf6\xe4\xd8p\xd1\xdc\xc4n )\xbf\x19,\xecrX\x99@\x8aK\x1d\xfbp\xbe\xd1\xeb\xb3\x1feY\xbe\xa87R\xb6W`aa\x97\xc1\xda\xb9W\xd3g\x94\xd2_2\xfd|\xbc\xfb\xa8d\x12\xb0\xb0\xbf\xc7\xfa}Ie\xc5\n\xc4\x9d}_\xdfb\x93z\xce\xae\xbb\x80\x85\x85\xcd\xcf\x86\x9b[\xf4Er\x85=\xba\xd9\xb68\xacaaa\x9f\xc8F7\x93\xea\x8fz%\x06\xadh\xc2\xc2\xe6`\xdd\x9c5\x1d\xfb\x9e\x136\x89\xcd-\xb0\xb0\xb0cYwM\xdb\xe4\x8c\xc4n4X\xd8e\xb1\xb6\xf4\xca}`\x86\x9dO)\xe0e\x8e\xe9\xed\x9c\xb0\xb0\xb0\x13\xd8\xb0\x87\x8b\xb9\xd7\xc7\xd5\x95B\xfd\xffP\x0e\x0b\xfb?\xd9\x1f\xd9\xb2to\xf9Q\xd6\xee\x00\x00\x00\x00IEND\xaeB`\x82' test(q, bus, conn, stream, image_data=avatar, mime_type='image/png') if __name__ == '__main__': exec_test(test_little_avatar) exec_test(test_massive_avatar) �������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/refresh-contact-info.py���������������������������������0000664�0001750�0001750�00000005543�12332441362�026523� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test ContactInfo support. """ from servicetest import call_async, EventPattern, assertEquals, sync_dbus from gabbletest import exec_test, acknowledge_iq, make_result_iq import constants as cs import dbus def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) handle = conn.RequestHandles(1, ['bob@foo.com'])[0] call_async(q, conn.ContactInfo, 'RefreshContactInfo', [handle]) event = q.expect('stream-iq', to='bob@foo.com', query_ns='vcard-temp', query_name='vCard') result = make_result_iq(stream, event.stanza) result.firstChildElement().addElement('FN', content='Bob') n = result.firstChildElement().addElement('N') n.addElement('GIVEN', content='Bob') result.firstChildElement().addElement('NICKNAME', content=r'bob,bob1\,,bob2,bob3\,bob4') label = result.firstChildElement().addElement('LABEL') label.addElement('LINE', content='42 West Wallaby Street') label.addElement('LINE', content="Bishop's Stortford\n") label.addElement('LINE', content='Huntingdon') org = result.firstChildElement().addElement('ORG') # ORG is a sequence of decreasingly large org.units, starting # with the organisation name itself (but here we've moved the org name # to the end, to make sure that works.) org.addElement('ORGUNIT', content='Dept. of Examples') org.addElement('ORGUNIT', content='Exemplary Team') org.addElement('ORGNAME', content='Collabora Ltd.') stream.send(result) q.expect('dbus-signal', signal='ContactInfoChanged', args=[handle, [(u'fn', [], [u'Bob']), (u'n', [], [u'', u'Bob', u'', u'', u'']), (u'nickname', [], [r'bob,bob1\,,bob2,bob3\,bob4']), # LABEL comes out as a single blob of text (u'label', [], ['42 West Wallaby Street\n' "Bishop's Stortford\n" 'Huntingdon\n']), # ORG is a sequence of decreasingly large org.units, starting # with the organisation (u'org', [], [u'Collabora Ltd.', u'Dept. of Examples', u'Exemplary Team']), ]]) # ContactInfoChanged should not be signalled again forbidden = [EventPattern('dbus-signal', signal='ContactInfoChanged')] q.forbid_events(forbidden) # Refresh the contact info again; gabble should contact the server again call_async(q, conn.ContactInfo, 'RefreshContactInfo', [handle]) event = q.expect('stream-iq', to='bob@foo.com', query_ns='vcard-temp', query_name='vCard') sync_dbus(bus, q, conn) q.unforbid_events(forbidden) if __name__ == '__main__': exec_test(test) �������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/test-avatar.py������������������������������������������0000664�0001750�0001750�00000001743�12332441362�024734� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test avatar support. """ import base64 from servicetest import call_async, EventPattern from gabbletest import exec_test, acknowledge_iq, make_result_iq import constants as cs def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) handle = conn.RequestHandles(1, ['bob@foo.com'])[0] call_async(q, conn.Avatars, 'RequestAvatar', handle, byte_arrays=True) event = q.expect('stream-iq', iq_type='get', to='bob@foo.com', query_ns='vcard-temp', query_name='vCard') result = make_result_iq(stream, event.stanza) photo = result.firstChildElement().addElement('PHOTO') photo.addElement('TYPE', content='image/png') photo.addElement('BINVAL', content=base64.b64encode('hello')) stream.send(result) q.expect('dbus-return', method='RequestAvatar', value=('hello', 'image/png')) if __name__ == '__main__': exec_test(test) �����������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/test-save-alias-to-vcard.py�����������������������������0000644�0001750�0001750�00000001321�12225363340�027206� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Regression test. - the 'alias' connection parameter is set - our vCard doesn't have a NICKNAME field - we crash when trying to save a vcard with NICKNAME set to the alias parameter """ from gabbletest import ( exec_test, expect_and_handle_get_vcard, expect_and_handle_set_vcard) def test(q, bus, conn, stream): expect_and_handle_get_vcard(q, stream) def check_vcard(vcard): for e in vcard.elements(): if e.name == 'NICKNAME': assert str(e) == 'Some Guy', e.toXml() return assert False, vcard.toXml() expect_and_handle_set_vcard(q, stream, check_vcard) if __name__ == '__main__': exec_test(test, params={'alias': 'Some Guy'}) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/get-contact-info.py�������������������������������������0000664�0001750�0001750�00000005661�12332441362�025645� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test ContactInfo support. """ from servicetest import call_async, EventPattern, assertEquals from gabbletest import exec_test, acknowledge_iq, make_result_iq import constants as cs import dbus def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) # returning an empty vcard will cause ContactInfoChanged to fire q.expect('dbus-signal', signal='ContactInfoChanged') handle = conn.RequestHandles(1, ['bob@foo.com'])[0] call_async(q, conn.ContactInfo, 'RefreshContactInfo', [handle]) event = q.expect('stream-iq', to='bob@foo.com', query_ns='vcard-temp', query_name='vCard') result = make_result_iq(stream, event.stanza) result.firstChildElement().addElement('FN', content='Bob') n = result.firstChildElement().addElement('N') n.addElement('GIVEN', content='Bob') result.firstChildElement().addElement('NICKNAME', content=r'bob,bob1\,,bob2,bob3\,bob4') label = result.firstChildElement().addElement('LABEL') label.addElement('LINE', content='42 West Wallaby Street') label.addElement('LINE', content="Bishop's Stortford\n") label.addElement('LINE', content='Huntingdon') org = result.firstChildElement().addElement('ORG') # ORG is a sequence of decreasingly large org.units, starting # with the organisation name itself (but here we've moved the org name # to the end, to make sure that works.) org.addElement('ORGUNIT', content='Dept. of Examples') org.addElement('ORGUNIT', content='Exemplary Team') org.addElement('ORGNAME', content='Collabora Ltd.') stream.send(result) q.expect('dbus-signal', signal='ContactInfoChanged') contact_info = [(u'fn', [], [u'Bob']), (u'n', [], [u'', u'Bob', u'', u'', u'']), (u'nickname', [], [r'bob,bob1\,,bob2,bob3\,bob4']), # LABEL comes out as a single blob of text (u'label', [], ['42 West Wallaby Street\n' "Bishop's Stortford\n" 'Huntingdon\n']), # ORG is a sequence of decreasingly large org.units, starting # with the organisation (u'org', [], [u'Collabora Ltd.', u'Dept. of Examples', u'Exemplary Team']), ] # The request should be satisfied from the cache. assertEquals( {handle: contact_info}, conn.ContactInfo.GetContactInfo([handle])) # check the ContactAttribute assertEquals( {handle: {cs.CONN_IFACE_CONTACT_INFO + '/info': contact_info, 'org.freedesktop.Telepathy.Connection/contact-id': 'bob@foo.com'}}, conn.Contacts.GetContactAttributes([handle], [cs.CONN_IFACE_CONTACT_INFO], False)) if __name__ == '__main__': exec_test(test) �������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/test-alias-message.py�����������������������������������0000664�0001750�0001750�00000007622�12332441362�026173� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# vim: set fileencoding=utf-8 : """ Tests grabbing aliases from incoming messages, as described by <http://xmpp.org/extensions/xep-0172.html#message>. This test has nothing to do with vcards, just like a lot of other tests in the vcard/ directory. """ from servicetest import EventPattern, assertEquals, wrap_channel from gabbletest import exec_test, elem, expect_and_handle_get_vcard from mucutil import join_muc, make_muc_presence import constants as cs import ns def test(q, bus, conn, stream): expect_and_handle_get_vcard(q, stream) jid = u'bora.horza.gobuchul@culture.lit' alias = u'Horza' handle = conn.RequestHandles(cs.HT_CONTACT, [jid])[0] # We don't have an interesting alias for Horza assertEquals({handle: jid}, conn.Aliasing.GetAliases([handle])) # Horza sends us a message containing his preferred nickname. stream.send( elem('message', from_=jid, type='chat')( elem('body')(u"It's a long story."), elem(ns.NICK, 'nick')(alias) )) _, mr = q.expect_many( EventPattern('dbus-signal', signal='AliasesChanged', args=[[(handle, alias)]]), EventPattern('dbus-signal', signal='MessageReceived'), ) channel = wrap_channel(bus.get_object(conn.bus_name, mr.path), 'Text') # So now we know his alias. assertEquals({handle: alias}, conn.Aliasing.GetAliases([handle])) # Presumably to avoid non-contacts being able to make Gabble's memory # footprint grow forever, Gabble throws the alias away when we close the # channel. header = mr.args[0][0] channel.Text.AcknowledgePendingMessages([header['pending-message-id']]) channel.Close() # FIXME: Gabble forgets the alias, but it doesn't signal that it has done # so; it probably should. # q.expect('dbus-signal', signal='AliasesChanged', args=[[(handle, jid)]]) assertEquals({handle: jid}, conn.Aliasing.GetAliases([handle])) # Basically the same test, but in a MUC. # # It's a bit questionable whether this ought to work. # <http://xmpp.org/extensions/xep-0172.html#muc> doesn't have anything to # say about including <nick/> in messages; it does talk about including # <nick> in your MUC presence, which is actually equally sketchy! If I join # a muc with the resource '/wjt', and you join with resource '/ohai' but # say that your nickname is 'wjt', what on earth is Alice's UI supposed to # show when you send a message? # # But anyway, at the time of writing this "works", so I'm adding a test to # make it explicit. Perhaps in future we might change this test to verify # that it doesn't "work". room_jid = 'clear-air-turbulence@culture.lit' _, muc, _, _ = join_muc(q, bus, conn, stream, room_jid) bob_jid = room_jid + '/bob' bob_handle = conn.RequestHandles(cs.HT_CONTACT, [bob_jid])[0] assertEquals({bob_handle: 'bob'}, conn.Aliasing.GetAliases([bob_handle])) stream.send( elem('message', from_=bob_jid, type='groupchat')( elem('body')(u'My religion dies with me.'), elem(ns.NICK, 'nick')(alias), )) q.expect_many( EventPattern('dbus-signal', signal='AliasesChanged', args=[[(bob_handle, alias)]]), EventPattern('dbus-signal', signal='MessageReceived'),) assertEquals({bob_handle: alias}, conn.Aliasing.GetAliases([bob_handle])) muc.Close() q.expect('stream-presence', to=room_jid + '/test') echo = make_muc_presence('member', 'none', room_jid, 'test') echo['type'] = 'unavailable' stream.send(echo) q.expect('dbus-signal', signal='ChannelClosed') # FIXME: Gabble forgets the alias, but it doesn't signal that it has done # so; it probably should. # q.expect('dbus-signal', signal='AliasesChanged', # args=[[(bob_handle, 'bob')]]) assertEquals({bob_handle: 'bob'}, conn.Aliasing.GetAliases([bob_handle])) if __name__ == '__main__': exec_test(test) ��������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/test-avatar-async.py������������������������������������0000664�0001750�0001750�00000020350�12332441362�026042� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test support for retrieving avatars asynchronously using RequestAvatars. """ import base64 import hashlib from twisted.words.xish import domish from servicetest import EventPattern, sync_dbus, assertEquals from gabbletest import (exec_test, acknowledge_iq, make_result_iq, sync_stream, send_error_reply, make_presence) import constants as cs import ns import dbus avatar_retrieved_event = EventPattern('dbus-signal', signal='AvatarRetrieved') avatar_request_event = EventPattern('stream-iq', query_ns='vcard-temp') def test_get_avatar(q, bus, conn, stream, contact, handle, in_cache=False): conn.Avatars.RequestAvatars([handle]) if in_cache: q.forbid_events([avatar_request_event]) else: iq_event = q.expect('stream-iq', to=contact, query_ns='vcard-temp', query_name='vCard') iq = make_result_iq(stream, iq_event.stanza) vcard = iq.firstChildElement() photo = vcard.addElement('PHOTO') photo.addElement('TYPE', content='image/png') photo.addElement('BINVAL', content=base64.b64encode('hello')) stream.send(iq) event = q.expect('dbus-signal', signal='AvatarRetrieved') assertEquals(handle, event.args[0]) assertEquals(hashlib.sha1('hello').hexdigest(), event.args[1]) assertEquals('hello', event.args[2]) assertEquals('image/png', event.args[3]) if in_cache: sync_stream(q, stream) q.unforbid_events([avatar_request_event]) def test(q, bus, conn, stream): iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') # When we start, there is no avatar acknowledge_iq(stream, iq_event.stanza) self_handle = conn.GetSelfHandle() # Another resource confirms we have no avatar. We don't request our vCard # because we already know there is no avatar presence_stanza = make_presence('test@localhost/noavatar', to='test@localhost/Resource', show='away', status='At the pub', photo="") q.forbid_events([avatar_request_event, avatar_retrieved_event]) # Gabble must resist temptation to send vCard requests even with several # presence stanza sent! stream.send(presence_stanza) stream.send(presence_stanza) sync_stream(q, stream) # Twice because the vCard request is done in sync_stream(q, stream) # g_idle_add q.unforbid_events([avatar_request_event, avatar_retrieved_event]) # Request on the first contact. Test the cache. handle = conn.RequestHandles(cs.HT_CONTACT, ['bob@foo.com'])[0] test_get_avatar(q, bus, conn, stream, 'bob@foo.com', handle, in_cache=False) test_get_avatar(q, bus, conn, stream, 'bob@foo.com', handle, in_cache=True) # Request another vCard and get resource-constraint busy_contact = 'jean@busy-server.com' busy_handle = conn.RequestHandles(cs.HT_CONTACT, [busy_contact])[0] conn.Avatars.RequestAvatars([busy_handle]) iq_event = q.expect('stream-iq', to=busy_contact, query_ns='vcard-temp', query_name='vCard') iq = iq_event.stanza error = domish.Element((None, 'error')) error['code'] = '500' error['type'] = 'wait' error.addElement((ns.STANZA, 'resource-constraint')) q.forbid_events([avatar_retrieved_event, avatar_request_event]) send_error_reply(stream, iq, error) # Request the same vCard again during the suspended delay # We should not get the avatar conn.Avatars.RequestAvatars([busy_handle]) sync_stream(q, stream) sync_dbus(bus, q, conn) q.unforbid_events([avatar_retrieved_event, avatar_request_event]) # Request on a different contact, on another server # We should get the avatar handle = conn.RequestHandles(cs.HT_CONTACT, ['bob2@foo.com'])[0] test_get_avatar(q, bus, conn, stream, 'bob2@foo.com', handle) # Try again the contact on the busy server. # We should not get the avatar # Note: the timeout is 3 seconds for the test suites. We assume that # a few stanza with be processed fast enough to avoid the race. q.forbid_events([avatar_retrieved_event, avatar_request_event]) conn.Avatars.RequestAvatars([busy_handle]) sync_stream(q, stream) sync_dbus(bus, q, conn) q.unforbid_events([avatar_retrieved_event, avatar_request_event]) # After 3 seconds, we receive a new vCard request on the busy server iq_event = q.expect('stream-iq', to=busy_contact, query_ns='vcard-temp', query_name='vCard') iq = make_result_iq(stream, iq_event.stanza) vcard = iq.firstChildElement() photo = vcard.addElement('PHOTO') photo.addElement('TYPE', content='image/png') photo.addElement('BINVAL', content=base64.b64encode('hello')) stream.send(iq) event = q.expect('dbus-signal', signal='AvatarRetrieved') assertEquals(busy_handle, event.args[0]) assertEquals(hashlib.sha1('hello').hexdigest(), event.args[1]) assertEquals('hello', event.args[2]) assertEquals('image/png', event.args[3]) # Test with our own avatar test@localhost/Resource2 presence_stanza = make_presence('test@localhost/Resource2', to='test@localhost/Resource', show='away', status='At the pub', photo=hashlib.sha1(':-D').hexdigest()) stream.send(presence_stanza) iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') iq = make_result_iq(stream, iq_event.stanza) vcard = iq.firstChildElement() photo = vcard.addElement('PHOTO') photo.addElement('TYPE', content='image/png') photo.addElement('BINVAL', content=base64.b64encode(':-D')) # do not send the vCard reply now. First, send another presence. q.forbid_events([avatar_request_event]) stream.send(presence_stanza) sync_stream(q, stream) # Now send the reply. stream.send(iq) # Which results in an AvatarUpdated signal event = q.expect('dbus-signal', signal='AvatarUpdated') assertEquals(self_handle, event.args[0]) assertEquals(hashlib.sha1(':-D').hexdigest(), event.args[1]) # So Gabble has the right hash, and no need to ask the vCard again stream.send(presence_stanza) sync_stream(q, stream) q.unforbid_events([avatar_request_event]) # But if the hash is different, the vCard is asked again presence_stanza = make_presence('test@localhost/Resource2', to='test@localhost/Resource', show='away', status='At the pub', photo=hashlib.sha1('\o/').hexdigest()) stream.send(presence_stanza) iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') iq = make_result_iq(stream, iq_event.stanza) vcard = iq.firstChildElement() photo = vcard.addElement('PHOTO') photo.addElement('TYPE', content='image/png') photo.addElement('BINVAL', content=base64.b64encode('\o/')) stream.send(iq) event = q.expect('dbus-signal', signal='AvatarUpdated') assertEquals(self_handle, event.args[0]) assertEquals(hashlib.sha1('\o/').hexdigest(), event.args[1]) # Gabble must reply without asking the vCard to the server because the # avatar must be in the cache q.forbid_events([avatar_request_event]) data, mime = conn.Avatars.RequestAvatar(self_handle, byte_arrays=True) assertEquals('\o/', data) data, mime = conn.Avatars.RequestAvatar(handle, byte_arrays=True) assertEquals('hello', data) q.unforbid_events([avatar_request_event]) # First, ensure the pipeline is full contacts = ['random_user_%s@bigserver.com' % i for i in range(1, 100) ] handles = conn.RequestHandles(cs.HT_CONTACT, contacts) conn.Avatars.RequestAvatars(handles) # Then, request yet another avatar. The request will time out before # the IQ is sent, which used to trigger a crash in Gabble # (LP#445847). So, we assert that the error is NotAvailable (rather # than the error returned when the service crashes). try: conn.Avatars.RequestAvatar(handles[-1]) except dbus.DBusException, e: assertEquals(cs.NOT_AVAILABLE, e.get_dbus_name()) else: assert False if __name__ == '__main__': exec_test(test) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/test-vcard-cache.py�������������������������������������0000664�0001750�0001750�00000003021�12332441362�025605� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Tests basic vCard caching functionality. """ from servicetest import call_async, EventPattern from gabbletest import exec_test, acknowledge_iq, sync_stream import constants as cs def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) # Force Gabble to process the vCard before calling any methods. sync_stream(q, stream) # Request our alias and avatar, expect them to be resolved from cache. handle = conn.GetSelfHandle() call_async(q, conn.Avatars, 'RequestAvatar', handle) call_async(q, conn.Aliasing, 'RequestAliases', [handle]) # FIXME - find out why RequestAliases returns before RequestAvatar even # though everything's cached. Probably due to queueing, which means # conn-avatars don't look into the cache before making a request. Prolly # should make vcard_request look into the cache itself, and return # immediately. Or not, if it's g_idle()'d. So it's better if conn-aliasing # look into the cache itself. r1, r2 = q.expect_many( EventPattern('dbus-return', method='RequestAliases'), EventPattern('dbus-error', method='RequestAvatar')) # Default alias is our jid assert r1.value[0] == ['test@localhost'] # We don't have a vCard yet assert r2.error.get_dbus_name() == cs.NOT_AVAILABLE, \ r2.error.get_dbus_name() assert r2.error.args[0] == 'contact vCard has no photo' if __name__ == '__main__': exec_test(test) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/test-alias-empty-vcard.py�������������������������������0000664�0001750�0001750�00000002725�12332441362�027001� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Regression test for a bug where receiving an empty vCard could make RequesAliases fail to return. """ from servicetest import call_async, EventPattern from gabbletest import exec_test, make_result_iq, acknowledge_iq import constants as cs def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) handle = conn.RequestHandles(1, ['bob@foo.com'])[0] call_async(q, conn.Aliasing, 'RequestAliases', [handle]) # Nack PEP query. event = q.expect('stream-iq', to='bob@foo.com', iq_type='get', query_ns='http://jabber.org/protocol/pubsub', query_name='pubsub') items = event.query.firstChildElement() assert items.name == 'items' assert items['node'] == "http://jabber.org/protocol/nick" result = make_result_iq(stream, event.stanza) result['type'] = 'error' error = result.addElement('error') error['type'] = 'auth' error.addElement('forbidden', 'urn:ietf:params:xml:ns:xmpp-stanzas') stream.send(result) event = q.expect('stream-iq', to='bob@foo.com', query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) q.expect('dbus-return', method='RequestAliases', value=([u'bob@foo.com'],)) # A second request should be satisfied from the cache. assert conn.Aliasing.RequestAliases([handle]) == ['bob@foo.com'] if __name__ == '__main__': exec_test(test) �������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/supported-fields.py�������������������������������������0000664�0001750�0001750�00000010024�12225363340�025762� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- coding: utf-8 -*- """Feature test for ContactInfo.SupportedFields """ # Copyright © 2010 Collabora Ltd. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA from servicetest import (EventPattern, assertEquals, call_async) from gabbletest import (exec_test, GoogleXmlStream) import constants as cs PARAMS_EXACT = cs.CONTACT_INFO_FIELD_FLAG_PARAMETERS_EXACT OVERWRITTEN_BY_NICKNAME = cs.CONTACT_INFO_FIELD_FLAG_OVERWRITTEN_BY_NICKNAME UNLIMITED = 0xffffffffL def types(s): ret = ['type=%s' % t for t in s.split()] ret.sort() return ret def check_google_props(props): assertEquals(cs.CONTACT_INFO_FLAG_CAN_SET, props['ContactInfoFlags']) sf = props['SupportedFields'] sf.sort() for f in sf: f[1].sort() # type-parameters assertEquals([ ('fn', [], PARAMS_EXACT | OVERWRITTEN_BY_NICKNAME, 1), ('n', [], PARAMS_EXACT, 1), ('url', [], PARAMS_EXACT, UNLIMITED), ], sf) def check_normal_props(props): assertEquals(cs.CONTACT_INFO_FLAG_CAN_SET, props['ContactInfoFlags']) sf = props['SupportedFields'] sf.sort() for f in sf: f[1].sort() # type-parameters assertEquals([ ('adr', types('home work postal parcel dom intl pref'), 0, UNLIMITED), ('bday', [], PARAMS_EXACT, UNLIMITED), ('email', types('home work internet pref x400'), 0, UNLIMITED), ('fn', [], PARAMS_EXACT, 1), ('geo', [], PARAMS_EXACT, 1), ('label', types('home work postal parcel dom intl pref'), 0, UNLIMITED), ('mailer', [], PARAMS_EXACT, UNLIMITED), ('n', [], PARAMS_EXACT, 1), ('nickname', [], PARAMS_EXACT | OVERWRITTEN_BY_NICKNAME, UNLIMITED), ('note', [], PARAMS_EXACT, UNLIMITED), ('org', [], PARAMS_EXACT, UNLIMITED), ('prodid', [], PARAMS_EXACT, UNLIMITED), ('rev', [], PARAMS_EXACT, UNLIMITED), ('role', [], PARAMS_EXACT, UNLIMITED), ('sort-string', [], PARAMS_EXACT, UNLIMITED), ('tel', types('home work voice fax pager msg cell video bbs ' 'modem isdn pcs pref'), 0, UNLIMITED), ('title', [], PARAMS_EXACT, UNLIMITED), ('tz', [], PARAMS_EXACT, UNLIMITED), ('uid', [], PARAMS_EXACT, UNLIMITED), ('url', [], PARAMS_EXACT, UNLIMITED), ('x-desc', [], PARAMS_EXACT, UNLIMITED), ('x-jabber', [], PARAMS_EXACT, UNLIMITED), ], sf) def test_google(q, bus, conn, stream): test(q, bus, conn, stream, is_google=True) def test(q, bus, conn, stream, is_google=False): props = conn.GetAll(cs.CONN_IFACE_CONTACT_INFO, dbus_interface=cs.PROPERTIES_IFACE) check_normal_props(props) conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) props = conn.GetAll(cs.CONN_IFACE_CONTACT_INFO, dbus_interface=cs.PROPERTIES_IFACE) if is_google: check_google_props(props) # on a Google server, we can't use most vCard fields call_async(q, conn.ContactInfo, 'SetContactInfo', [('x-jabber', [], ['wee.ninja@collabora.co.uk'])]) q.expect('dbus-error', method='SetContactInfo', name=cs.INVALID_ARGUMENT) else: check_normal_props(props) if __name__ == '__main__': exec_test(test, do_connect=False) exec_test(test_google, protocol=GoogleXmlStream, do_connect=False) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/test-alias-pep.py���������������������������������������0000664�0001750�0001750�00000004152�12332441362�025326� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test PEP alias support. """ from servicetest import call_async, EventPattern, assertEquals, assertLength from gabbletest import exec_test, make_result_iq, acknowledge_iq, elem import constants as cs import ns def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) handle = conn.RequestHandles(cs.HT_CONTACT, ['bob@foo.com'])[0] call_async(q, conn.Aliasing, 'RequestAliases', [handle]) event = q.expect('stream-iq', to='bob@foo.com', iq_type='get', query_ns=ns.PUBSUB, query_name='pubsub') items = event.query.firstChildElement() assertEquals('items', items.name) assertEquals(ns.NICK, items['node']) result = make_result_iq(stream, event.stanza) pubsub = result.firstChildElement() items = pubsub.addElement('items') items['node'] = ns.NICK item = items.addElement('item') item.addElement('nick', ns.NICK, content='Bobby') stream.send(result) q.expect('dbus-signal', signal='AliasesChanged', args=[[(handle, u'Bobby')]]) q.expect('dbus-return', method='RequestAliases', value=(['Bobby'],)) # A second request should be satisfied from the cache. assertEquals(['Bobby'], conn.Aliasing.RequestAliases([handle])) # Bobby grows up, decides he hates his nickname. # This is a regression test for # <https://bugs.freedesktop.org/show_bug.cgi?id=21817>, where this would # crash Gabble. message = elem('message', from_='bob@foo.com')( elem((ns.PUBSUB_EVENT), 'event')( elem('items', node=ns.NICK)( elem('item')( elem(ns.NICK, 'nick') ) ) ) ) stream.send(message.toXml()) event = q.expect('dbus-signal', signal='AliasesChanged') aliases = event.args[0] assertLength(1, aliases) h, a = aliases[0] assertEquals(handle, h) # The contact explicitly cleared their PEP nick; Gabble should fall back to # their JID. assertEquals(a, 'bob@foo.com') if __name__ == '__main__': exec_test(test) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/test-avatar-tokens.py�����������������������������������0000664�0001750�0001750�00000003226�12332441362�026233� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test GetAvatarTokens() and GetKnownAvatarTokens(). """ from twisted.words.xish import domish from servicetest import unwrap, EventPattern from gabbletest import exec_test, make_result_iq import ns import constants as cs def make_presence(jid, sha1sum): p = domish.Element((None, 'presence')) p['from'] = jid p['to'] = 'test@localhost/Resource' x = p.addElement((ns.VCARD_TEMP_UPDATE, 'x')) x.addElement('photo', content=sha1sum) return p def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns=ns.ROSTER, query_name='query') result = make_result_iq(stream, event.stanza) item = result.addElement('item') item['jid'] = 'amy@foo.com' item['subscription'] = 'both' item = result.addElement('item') item['jid'] = 'bob@foo.com' item['subscription'] = 'both' item = result.addElement('item') item['jid'] = 'che@foo.com' item['subscription'] = 'both' stream.send(result) stream.send(make_presence('amy@foo.com', 'SHA1SUM-FOR-AMY')) stream.send(make_presence('bob@foo.com', 'SHA1SUM-FOR-BOB')) stream.send(make_presence('che@foo.com', None)) q.expect('dbus-signal', signal='AvatarUpdated') handles = conn.RequestHandles(1, [ 'amy@foo.com', 'bob@foo.com', 'che@foo.com', 'daf@foo.com' ]) tokens = unwrap(conn.Avatars.GetAvatarTokens(handles)) assert tokens == ['SHA1SUM-FOR-AMY', 'SHA1SUM-FOR-BOB', '', ''] tokens = unwrap(conn.Avatars.GetKnownAvatarTokens(handles)) tokens = sorted(tokens.items()) assert tokens == [(2, 'SHA1SUM-FOR-AMY'), (3, 'SHA1SUM-FOR-BOB'), (4, u'')] if __name__ == '__main__': exec_test(test) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/clear-avatar.py�����������������������������������������0000664�0001750�0001750�00000001375�12225363340�025044� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Tests the very simple case of "clearing your own avatar". """ from servicetest import call_async from gabbletest import ( exec_test, expect_and_handle_get_vcard, expect_and_handle_set_vcard, current_vcard ) def test(q, bus, conn, stream): photo = current_vcard.addElement((None, 'PHOTO')) photo.addElement((None, 'TYPE')).addContent('image/fake') photo.addElement((None, 'BINVAL')).addContent('NYANYANYANYANYAN') call_async(q, conn.Avatars, 'ClearAvatar') expect_and_handle_get_vcard(q, stream) def check(vcard): assert len(vcard.children) == 0, vcard.toXml() expect_and_handle_set_vcard(q, stream, check=check) q.expect('dbus-return', method='ClearAvatar') if __name__ == '__main__': exec_test(test) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/test-avatar-retrieved.py��������������������������������0000664�0001750�0001750�00000002303�12332441362�026714� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test that gabble emits only one AvatarRetrieved for multiple queued RequestAvatar calls for the same contact. """ import base64 from servicetest import EventPattern from gabbletest import exec_test, acknowledge_iq, make_result_iq import constants as cs def test(q, bus, conn, stream): iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, iq_event.stanza) handle = conn.RequestHandles(1, ['bob@foo.com'])[0] conn.Avatars.RequestAvatars([handle]) conn.Avatars.RequestAvatars([handle]) conn.Avatars.RequestAvatars([handle]) conn.Avatars.RequestAvatars([handle]) iq_event = q.expect('stream-iq', to='bob@foo.com', query_ns='vcard-temp', query_name='vCard') iq = make_result_iq(stream, iq_event.stanza) vcard = iq.firstChildElement() photo = vcard.addElement('PHOTO') photo.addElement('TYPE', content='image/png') photo.addElement('BINVAL', content=base64.b64encode('hello')) stream.send(iq) event = q.expect('dbus-signal', signal='AvatarRetrieved') q.forbid_events([EventPattern('dbus-signal', signal='AvatarRetrieved')]) if __name__ == '__main__': exec_test(test) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/test-set-alias.py���������������������������������������0000664�0001750�0001750�00000003655�12332441362�025344� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test alias setting support. """ from servicetest import EventPattern, assertEquals, assertLength from gabbletest import ( exec_test, acknowledge_iq, expect_and_handle_get_vcard, expect_and_handle_set_vcard, ) import constants as cs import ns def validate_pep_update(pep_update, expected_nickname): publish = pep_update.query.elements(uri=ns.PUBSUB, name='publish').next() assertEquals(ns.NICK, publish['node']) item = publish.elements(uri=ns.PUBSUB, name='item').next() nick = item.elements(uri=ns.NICK, name='nick').next() if expected_nickname is not None: assertEquals(expected_nickname, nick.children[0]) else: assertLength(0, nick.children) def test(q, bus, conn, stream): self_handle = conn.GetSelfHandle() conn.Aliasing.SetAliases({self_handle: 'lala'}) expect_and_handle_get_vcard(q, stream) pep_update = q.expect('stream-iq', iq_type='set', query_ns=ns.PUBSUB, query_name='pubsub') validate_pep_update(pep_update, 'lala') acknowledge_iq(stream, pep_update.stanza) def check(vCard): nickname = vCard.elements(uri=ns.VCARD_TEMP, name='NICKNAME').next() assertEquals('lala', nickname.children[0]) expect_and_handle_set_vcard(q, stream, check=check) event = q.expect('dbus-signal', signal='AliasesChanged', args=[[(self_handle, u'lala')]]) conn.Aliasing.SetAliases({self_handle: ''}) pep_update = q.expect('stream-iq', iq_type='set', query_ns=ns.PUBSUB, query_name='pubsub') validate_pep_update(pep_update, None) expect_and_handle_get_vcard(q, stream) def check(vCard): # The vCard should be empty, rather than having an empty <NICKNAME/> # element. assertLength(0, vCard.children) expect_and_handle_set_vcard(q, stream, check=check) event = q.expect('dbus-signal', signal='AliasesChanged', args=[[(self_handle, u'test@localhost')]]) if __name__ == '__main__': exec_test(test) �����������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/test-vcard-race.py��������������������������������������0000664�0001750�0001750�00000005237�12332441362�025467� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Regression test for https://bugs.freedesktop.org/show_bug.cgi?id=11201 - We try to set our own alias and our own avatar at about the same time - SetAliases requests vCard v1 - SetAvatar requests vCard v1 - SetAliases receives v1, writes back v2 with new NICKNAME - SetAvatar receives v1, writes back v2' with new PHOTO - Change to NICKNAME in v2 is lost """ import base64 from twisted.words.xish import xpath from servicetest import call_async, sync_dbus, assertEquals from gabbletest import ( exec_test, expect_and_handle_get_vcard, expect_and_handle_set_vcard, make_result_iq, sync_stream) import ns def test(q, bus, conn, stream): expect_and_handle_get_vcard(q, stream) # Ensure that Gabble's actually got the initial vCard reply; if it hasn't # processed it by the time we call SetAliases, the latter will wait for it # to reply and then set immediately. sync_stream(q, stream) handle = conn.GetSelfHandle() call_async(q, conn.Aliasing, 'SetAliases', {handle: 'Some Guy'}) # SetAliases requests vCard v1 get_vcard_event = q.expect('stream-iq', query_ns=ns.VCARD_TEMP, query_name='vCard', iq_type='get') iq = get_vcard_event.stanza vcard = iq.firstChildElement() assert vcard.name == 'vCard', vcard.toXml() call_async(q, conn.Avatars, 'SetAvatar', 'hello', 'image/png') # We don't expect Gabble to send a second vCard request, since there's one # outstanding. But we want to ensure that SetAvatar reaches Gabble before # the empty vCard does. sync_dbus(bus, q, conn) # Send back current empty vCard result = make_result_iq(stream, iq) # result already includes the <vCard/> from the query, which is all we need stream.send(result) def has_nickname_and_photo(vcard): nicknames = xpath.queryForNodes('/vCard/NICKNAME', vcard) assert nicknames is not None assert len(nicknames) == 1 assert str(nicknames[0]) == 'Some Guy' photos = xpath.queryForNodes('/vCard/PHOTO', vcard) assert photos is not None and len(photos) == 1, repr(photos) types = xpath.queryForNodes('/PHOTO/TYPE', photos[0]) binvals = xpath.queryForNodes('/PHOTO/BINVAL', photos[0]) assert types is not None and len(types) == 1, repr(types) assert binvals is not None and len(binvals) == 1, repr(binvals) assert str(types[0]) == 'image/png' got = str(binvals[0]).strip() exp = base64.b64encode('hello') assertEquals(exp, got) # Now Gabble should set a new vCard with both of the above changes. expect_and_handle_set_vcard(q, stream, has_nickname_and_photo) if __name__ == '__main__': exec_test(test) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/set-contact-info.py�������������������������������������0000664�0001750�0001750�00000031265�12332440117�025655� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test ContactInfo setting support. """ from servicetest import (EventPattern, call_async, assertEquals, assertLength, assertContains, sync_dbus) from gabbletest import exec_test, acknowledge_iq, sync_stream import constants as cs from twisted.words.xish import xpath from twisted.words.protocols.jabber.client import IQ def repeat_previous_vcard(stream, iq, previous): result = IQ(stream, 'result') result['id'] = iq['id'] to = iq.getAttribute('to') if to is not None: result["from"] = to result.addRawXml(previous.firstChildElement().toXml()) stream.send(result) def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') call_async(q, conn.ContactInfo, 'SetContactInfo', [(u'fn', [], [u'Wee Ninja']), (u'n', [], [u'Ninja', u'Wee', u'', u'', u'-san']), (u'org', [], ['Collabora, Ltd.']), (u'adr', ['type=work','type=postal','type=parcel'], ['', '', '11 Kings Parade', 'Cambridge', 'Cambridgeshire', 'CB2 1SJ', 'UK']), (u'label', ['type=work'], [ '11 Kings Parade\n' 'Cambridge\n' 'Cambridgeshire\n' 'CB2 1SJ\n' 'UK\n']), (u'tel', ['type=voice','type=work'], ['+44 1223 362967']), (u'tel', ['type=voice','type=work'], ['+44 7700 900753']), (u'email', ['type=internet','type=pref'], ['wee.ninja@collabora.co.uk']), (u'email', ['type=internet'], ['wee.ninja@example.com']), (u'x-jabber', [], ['wee.ninja@collabora.co.uk']), (u'x-jabber', [], ['wee.ninja@example.com']), (u'url', [], ['http://www.thinkgeek.com/geektoys/plush/8823/']), (u'nickname', [], [u'HR Ninja']), (u'nickname', [], [u'Enforcement Ninja'])]) # We don't acknowledge the initial vCard get until we're sure that Gabble's # received our call to SetContactInfo. This ensures that it will issue a # set when we send the reply, rather than issuing another get to ensure the # vCard is really, absolutely up to date before editing it. sync_dbus(bus, q, conn) acknowledge_iq(stream, event.stanza) vcard_set_event = q.expect('stream-iq', iq_type='set', query_ns='vcard-temp', query_name='vCard') assertLength(2, xpath.queryForNodes('/iq/vCard/NICKNAME', vcard_set_event.stanza)) nicknames = [] for nickname in xpath.queryForNodes('/iq/vCard/NICKNAME', vcard_set_event.stanza): nicknames.append(str(nickname)) assertEquals(['HR Ninja', 'Enforcement Ninja'], nicknames) assertEquals(None, xpath.queryForNodes('/iq/vCard/PHOTO', vcard_set_event.stanza)) assertLength(1, xpath.queryForNodes('/iq/vCard/N', vcard_set_event.stanza)) assertEquals('Wee', xpath.queryForString('/iq/vCard/N/GIVEN', vcard_set_event.stanza)) assertEquals('Ninja', xpath.queryForString('/iq/vCard/N/FAMILY', vcard_set_event.stanza)) assertEquals('-san', xpath.queryForString('/iq/vCard/N/SUFFIX', vcard_set_event.stanza)) assertEquals('Wee Ninja', xpath.queryForString('/iq/vCard/FN', vcard_set_event.stanza)) assertLength(1, xpath.queryForNodes('/iq/vCard/ORG', vcard_set_event.stanza)) assertEquals('Collabora, Ltd.', xpath.queryForString('/iq/vCard/ORG/ORGNAME', vcard_set_event.stanza)) assertEquals(None, xpath.queryForNodes('/iq/vCard/ORG/ORGUNIT', vcard_set_event.stanza)) assertLength(1, xpath.queryForNodes('/iq/vCard/LABEL', vcard_set_event.stanza)) lines = xpath.queryForNodes('/iq/vCard/LABEL/LINE', vcard_set_event.stanza) assertLength(5, lines) for i, exp_line in enumerate(['11 Kings Parade', 'Cambridge', 'Cambridgeshire', 'CB2 1SJ', 'UK']): assertEquals(exp_line, str(lines[i])) assertLength(2, xpath.queryForNodes('/iq/vCard/TEL', vcard_set_event.stanza)) for tel in xpath.queryForNodes('/iq/vCard/TEL', vcard_set_event.stanza): assertLength(1, xpath.queryForNodes('/TEL/NUMBER', tel)) assertContains(xpath.queryForString('/TEL/NUMBER', tel), ('+44 1223 362967', '+44 7700 900753')) assertLength(1, xpath.queryForNodes('/TEL/VOICE', tel)) assertLength(1, xpath.queryForNodes('/TEL/WORK', tel)) assertLength(2, xpath.queryForNodes('/iq/vCard/EMAIL', vcard_set_event.stanza)) for email in xpath.queryForNodes('/iq/vCard/EMAIL', vcard_set_event.stanza): assertContains(xpath.queryForString('/EMAIL/USERID', email), ('wee.ninja@example.com', 'wee.ninja@collabora.co.uk')) assertLength(1, xpath.queryForNodes('/EMAIL/INTERNET', email)) if 'collabora' in xpath.queryForString('/EMAIL/USERID', email): assertLength(1, xpath.queryForNodes('/EMAIL/PREF', email)) else: assertEquals(None, xpath.queryForNodes('/EMAIL/PREF', email)) assertLength(2, xpath.queryForNodes('/iq/vCard/JABBERID', vcard_set_event.stanza)) for jid in xpath.queryForNodes('/iq/vCard/JABBERID', vcard_set_event.stanza): assertContains(xpath.queryForString('/JABBERID', jid), ('wee.ninja@example.com', 'wee.ninja@collabora.co.uk')) acknowledge_iq(stream, vcard_set_event.stanza) q.expect_many( EventPattern('dbus-return', method='SetContactInfo'), EventPattern('dbus-signal', signal='AliasesChanged', predicate=lambda e: e.args[0][0][1] == 'HR Ninja'), EventPattern('dbus-signal', signal='ContactInfoChanged'), ) # Exercise various invalid SetContactInfo operations sync_stream(q, stream) sync_dbus(bus, q, conn) forbidden = [EventPattern('stream-iq', query_ns='vcard-temp')] q.forbid_events(forbidden) # unknown field call_async(q, conn.ContactInfo, 'SetContactInfo', [('x-salary', [], ['547 espressos per month'])]) q.expect('dbus-error', method='SetContactInfo', name=cs.INVALID_ARGUMENT) # not enough values for a simple field call_async(q, conn.ContactInfo, 'SetContactInfo', [('fn', [], [])]) q.expect('dbus-error', method='SetContactInfo', name=cs.INVALID_ARGUMENT) # too many values for a simple field call_async(q, conn.ContactInfo, 'SetContactInfo', [('fn', [], ['Wee', 'Ninja'])]) q.expect('dbus-error', method='SetContactInfo', name=cs.INVALID_ARGUMENT) # unsupported type-parameter for a simple field call_async(q, conn.ContactInfo, 'SetContactInfo', [('fn', ['language=ja'], ['Wee Ninja'])]) q.expect('dbus-error', method='SetContactInfo', name=cs.INVALID_ARGUMENT) # unsupported type-parameter for a structured field call_async(q, conn.ContactInfo, 'SetContactInfo', [(u'n', ['language=ja'], [u'Ninja', u'Wee', u'', u'', u'-san'])]) q.expect('dbus-error', method='SetContactInfo', name=cs.INVALID_ARGUMENT) # unsupported type-parameter for LABEL call_async(q, conn.ContactInfo, 'SetContactInfo', [('label', ['language=en'], ['Collabora Ltd.\n11 Kings Parade'])]) q.expect('dbus-error', method='SetContactInfo', name=cs.INVALID_ARGUMENT) # not enough values for LABEL call_async(q, conn.ContactInfo, 'SetContactInfo', [('label', [], [])]) q.expect('dbus-error', method='SetContactInfo', name=cs.INVALID_ARGUMENT) # too many values for LABEL call_async(q, conn.ContactInfo, 'SetContactInfo', [('label', [], ['11 Kings Parade', 'Cambridge'])]) q.expect('dbus-error', method='SetContactInfo', name=cs.INVALID_ARGUMENT) # unsupported type-parameter for ORG call_async(q, conn.ContactInfo, 'SetContactInfo', [('org', ['language=en'], ['Collabora Ltd.'])]) q.expect('dbus-error', method='SetContactInfo', name=cs.INVALID_ARGUMENT) # empty ORG call_async(q, conn.ContactInfo, 'SetContactInfo', [('org', [], [])]) q.expect('dbus-error', method='SetContactInfo', name=cs.INVALID_ARGUMENT) # not enough values for N call_async(q, conn.ContactInfo, 'SetContactInfo', [('n', [], ['Ninja'])]) q.expect('dbus-error', method='SetContactInfo', name=cs.INVALID_ARGUMENT) # too many values for N call_async(q, conn.ContactInfo, 'SetContactInfo', [('n', [], 'what could it mean if you have too many field values?'.split())]) q.expect('dbus-error', method='SetContactInfo', name=cs.INVALID_ARGUMENT) q.unforbid_events(forbidden) # Following a reshuffle, Company Policy Enforcement is declared to be # a sub-department within Human Resources, and the ninja no longer # qualifies for a company phone vcard_in = [(u'fn', [], [u'Wee Ninja']), (u'n', [], [u'Ninja', u'Wee', u'', u'', u'-san']), (u'org', [], ['Collabora, Ltd.', 'Human Resources', 'Company Policy Enforcement']), (u'adr', ['type=work','type=postal','type=parcel'], ['', '', '11 Kings Parade', 'Cambridge', 'Cambridgeshire', 'CB2 1SJ', 'UK']), (u'tel', ['type=voice','type=work'], ['+44 1223 362967']), (u'email', ['type=internet','type=pref'], ['wee.ninja@collabora.co.uk']), (u'email', ['type=internet'], ['wee.ninja@example.com']), (u'url', [], ['http://www.thinkgeek.com/geektoys/plush/8823/']), (u'nickname', [], [u'HR Ninja']), (u'nickname', [], [u'Enforcement Ninja'])] call_async(q, conn.ContactInfo, 'SetContactInfo', vcard_in) event = q.expect('stream-iq', iq_type='get', query_ns='vcard-temp', query_name='vCard') repeat_previous_vcard(stream, event.stanza, vcard_set_event.stanza) _, vcard_set_event = q.expect_many( EventPattern('dbus-signal', signal='ContactInfoChanged'), EventPattern('stream-iq', iq_type='set', query_ns='vcard-temp', query_name='vCard'), ) assertLength(1, xpath.queryForNodes('/iq/vCard/ORG', vcard_set_event.stanza)) assertEquals('Collabora, Ltd.', xpath.queryForString('/iq/vCard/ORG/ORGNAME', vcard_set_event.stanza)) units = xpath.queryForNodes('/iq/vCard/ORG/ORGUNIT', vcard_set_event.stanza) assertLength(2, units) for i, exp_unit in enumerate(['Human Resources', 'Company Policy Enforcement']): assertEquals(exp_unit, str(units[i])) assertLength(1, xpath.queryForNodes('/iq/vCard/TEL', vcard_set_event.stanza)) for tel in xpath.queryForNodes('/iq/vCard/TEL', vcard_set_event.stanza): assertLength(1, xpath.queryForNodes('/TEL/NUMBER', tel)) assertEquals('+44 1223 362967', xpath.queryForString('/TEL/NUMBER', tel)) assertLength(1, xpath.queryForNodes('/TEL/VOICE', tel)) assertLength(1, xpath.queryForNodes('/TEL/WORK', tel)) acknowledge_iq(stream, vcard_set_event.stanza) _, event = q.expect_many( EventPattern('dbus-return', method='SetContactInfo'), EventPattern('dbus-signal', signal='ContactInfoChanged'), ) vcard_out = event.args[1][:] # the only change we expect to see is that perhaps the fields are # re-ordered, and perhaps the types on the 'tel' are re-ordered assertEquals(vcard_in[4][0], 'tel') vcard_in[4][1].sort() assertEquals(vcard_out[4][0], 'tel') vcard_out[4][1].sort() assertEquals(vcard_in, vcard_out) # Finally, the ninja decides that publishing his contact details is not # very ninja-like, and decides to be anonymous. The first (most important) # of his nicknames from the old vCard is kept, due to nickname's dual role # as ContactInfo and the alias. call_async(q, conn.ContactInfo, 'SetContactInfo', []) event = q.expect('stream-iq', iq_type='get', query_ns='vcard-temp', query_name='vCard') repeat_previous_vcard(stream, event.stanza, vcard_set_event.stanza) vcard_set_event = q.expect('stream-iq', iq_type='set', query_ns='vcard-temp', query_name='vCard') assertLength(1, xpath.queryForNodes('/iq/vCard/*', vcard_set_event.stanza)) assertEquals('HR Ninja', xpath.queryForString('/iq/vCard/NICKNAME', vcard_set_event.stanza)) acknowledge_iq(stream, vcard_set_event.stanza) q.expect_many( EventPattern('dbus-return', method='SetContactInfo'), EventPattern('dbus-signal', signal='ContactInfoChanged'), ) if __name__ == '__main__': exec_test(test) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/overlapping-sets.py�������������������������������������0000664�0001750�0001750�00000012716�12332441362�026005� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ import base64 from twisted.words.xish import xpath import constants as cs from servicetest import (EventPattern, call_async, sync_dbus, assertEquals, assertLength) from gabbletest import ( acknowledge_iq, exec_test, expect_and_handle_get_vcard, make_result_iq, sync_stream, disconnect_conn) import ns def test(q, bus, conn, stream): # Initial vCard request. Respond only after we call SetAliases(). vcard_get_event = q.expect('stream-iq', iq_type='get', to=None, query_ns=ns.VCARD_TEMP, query_name='vCard') sync_stream(q, stream) handle = conn.GetSelfHandle() call_async(q, conn.Aliasing, 'SetAliases', {handle: 'Robert the Bruce'}) sync_dbus(bus, q, conn) acknowledge_iq(stream, vcard_get_event.stanza) # Gabble sets a new vCard with our nickname. vcard_set_event = q.expect('stream-iq', iq_type='set', query_ns=ns.VCARD_TEMP, query_name='vCard') assertEquals('Robert the Bruce', xpath.queryForString('/iq/vCard/NICKNAME', vcard_set_event.stanza)) assertEquals(None, xpath.queryForNodes('/iq/vCard/PHOTO', vcard_set_event.stanza)) assertEquals(None, xpath.queryForNodes('/iq/vCard/FN', vcard_set_event.stanza)) assertEquals(None, xpath.queryForNodes('/iq/vCard/N', vcard_set_event.stanza)) # Before the server replies, the user sets their avatar call_async(q, conn.Avatars, 'SetAvatar', 'hello', 'image/png') sync_dbus(bus, q, conn) # This acknowledgement is for the nickname acknowledge_iq(stream, vcard_set_event.stanza) hello_binval = base64.b64encode('hello') # This sets the avatar vcard_set_event = q.expect('stream-iq', iq_type='set', query_ns=ns.VCARD_TEMP, query_name='vCard') assertEquals('Robert the Bruce', xpath.queryForString('/iq/vCard/NICKNAME', vcard_set_event.stanza)) assertLength(1, xpath.queryForNodes('/iq/vCard/PHOTO', vcard_set_event.stanza)) assertEquals('image/png', xpath.queryForString('/iq/vCard/PHOTO/TYPE', vcard_set_event.stanza)) binval = xpath.queryForString('/iq/vCard/PHOTO/BINVAL', vcard_set_event.stanza) assertEquals(hello_binval, binval.strip()) assertEquals(None, xpath.queryForNodes('/iq/vCard/FN', vcard_set_event.stanza)) assertEquals(None, xpath.queryForNodes('/iq/vCard/N', vcard_set_event.stanza)) # Before the server replies, the user sets their ContactInfo call_async(q, conn.ContactInfo, 'SetContactInfo', [(u'fn', [], [u'King Robert I']), (u'n', [], [u'de Brus', u'Robert', u'', u'King', u'']), (u'nickname', [], [u'Bob'])]) sync_dbus(bus, q, conn) # This acknowledgement is for the avatar; SetAvatar won't happen # until this has acknowledge_iq(stream, vcard_set_event.stanza) # This sets the ContactInfo vcard_set_event, _ = q.expect_many( EventPattern('stream-iq', iq_type='set', query_ns=ns.VCARD_TEMP, query_name='vCard'), EventPattern('dbus-return', method='SetAvatar')) assertEquals('Bob', xpath.queryForString('/iq/vCard/NICKNAME', vcard_set_event.stanza)) assertLength(1, xpath.queryForNodes('/iq/vCard/PHOTO', vcard_set_event.stanza)) assertEquals('image/png', xpath.queryForString('/iq/vCard/PHOTO/TYPE', vcard_set_event.stanza)) binval = xpath.queryForString('/iq/vCard/PHOTO/BINVAL', vcard_set_event.stanza) assertEquals(hello_binval, binval.strip()) assertLength(1, xpath.queryForNodes('/iq/vCard/N', vcard_set_event.stanza)) assertEquals('Robert', xpath.queryForString('/iq/vCard/N/GIVEN', vcard_set_event.stanza)) assertEquals('de Brus', xpath.queryForString('/iq/vCard/N/FAMILY', vcard_set_event.stanza)) assertEquals('King', xpath.queryForString('/iq/vCard/N/PREFIX', vcard_set_event.stanza)) assertEquals('King Robert I', xpath.queryForString('/iq/vCard/FN', vcard_set_event.stanza)) # Before the server replies, the user unsets their avatar call_async(q, conn.Avatars, 'SetAvatar', '', '') sync_dbus(bus, q, conn) # This acknowledgement is for the ContactInfo; SetContactInfo won't happen # until this has acknowledge_iq(stream, vcard_set_event.stanza) vcard_set_event, _ = q.expect_many( EventPattern('stream-iq', iq_type='set', query_ns=ns.VCARD_TEMP, query_name='vCard'), EventPattern('dbus-return', method='SetContactInfo')) assertEquals('Bob', xpath.queryForString('/iq/vCard/NICKNAME', vcard_set_event.stanza)) assertEquals(None, xpath.queryForNodes('/iq/vCard/PHOTO', vcard_set_event.stanza)) assertLength(1, xpath.queryForNodes('/iq/vCard/N', vcard_set_event.stanza)) assertEquals('Robert', xpath.queryForString('/iq/vCard/N/GIVEN', vcard_set_event.stanza)) assertEquals('de Brus', xpath.queryForString('/iq/vCard/N/FAMILY', vcard_set_event.stanza)) assertEquals('King', xpath.queryForString('/iq/vCard/N/PREFIX', vcard_set_event.stanza)) assertEquals('King Robert I', xpath.queryForString('/iq/vCard/FN', vcard_set_event.stanza)) # This acknowledgement is for the avatar; SetAvatar won't finish # until this is received acknowledge_iq(stream, vcard_set_event.stanza) q.expect('dbus-return', method='SetAvatar') # Now Gabble gets disconnected. sync_stream(q, stream) disconnect_conn(q, conn, stream) if __name__ == '__main__': exec_test(test) ��������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/update-get-failed.py������������������������������������0000664�0001750�0001750�00000002124�12332441362�025754� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test the case where the vCard get made prior to a vCard set fails. """ from servicetest import call_async, EventPattern from gabbletest import ( acknowledge_iq, elem, exec_test, make_result_iq, sync_stream) import constants as cs import ns def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) # Force Gabble to process the vCard before calling any methods. sync_stream(q, stream) handle = conn.GetSelfHandle() call_async(q, conn.Avatars, 'SetAvatar', 'william shatner', 'image/x-actor-name') event = q.expect('stream-iq', iq_type='get', to=None, query_ns='vcard-temp', query_name='vCard') reply = make_result_iq(stream, event.stanza) reply['type'] = 'error' reply.addChild(elem('error')( elem(ns.STANZA, 'forbidden')(), elem(ns.STANZA, 'text')(u'zomg whoops'))) stream.send(reply) event = q.expect('dbus-error', method='SetAvatar', name=cs.NOT_AVAILABLE) if __name__ == '__main__': exec_test(test) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/update-rejected.py��������������������������������������0000644�0001750�0001750�00000002333�12225363340�025540� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Regression test for fd.o #20442, where the XMPP error returned by a server that doesn't like the avatar you tried to set was not mapped to a TP error before being sent over the bus. """ from twisted.words.xish import domish from servicetest import call_async from gabbletest import exec_test, expect_and_handle_get_vcard, send_error_reply, sync_stream import ns import constants as cs def test(q, bus, conn, stream): expect_and_handle_get_vcard(q, stream) sync_stream(q, stream) call_async(q, conn.Avatars, 'SetAvatar', 'william shatner', 'image/x-actor-name') # Gabble request the last version of the vCard before changing it expect_and_handle_get_vcard(q, stream) set_vcard_event = q.expect('stream-iq', query_ns=ns.VCARD_TEMP, query_name='vCard', iq_type='set') iq = set_vcard_event.stanza error = domish.Element((None, 'error')) error['code'] = '400' error['type'] = 'modify' error.addElement((ns.STANZA, 'bad-request')) send_error_reply(stream, iq, error) event = q.expect('dbus-error', method='SetAvatar') assert event.error.get_dbus_name() == cs.INVALID_ARGUMENT, \ event.error.get_dbus_name() if __name__ == '__main__': exec_test(test) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/redundant-set.py����������������������������������������0000644�0001750�0001750�00000003157�12225363340�025255� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Regression test for <http://bugs.freedesktop.org/show_bug.cgi?id=25341>, where Gabble redundantly re-set the user's own vCard even if nothing had changed. """ from servicetest import EventPattern, sync_dbus from gabbletest import exec_test, make_result_iq, sync_stream, GoogleXmlStream import constants as cs def not_google(q, bus, conn, stream): test(q, bus, conn, stream, False) def google(q, bus, conn, stream): test(q, bus, conn, stream, True) def test(q, bus, conn, stream, is_google): iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') result = make_result_iq(stream, iq_event.stanza) # Testing reveals that Google's vCard server does not actually support # NICKNAME (or indeed any fields beside FN, N and PHOTO): if you set a # vCard including it, it accepts the request but strips out the unsupported # fields. So if the server looks like Google, it's a redundant set # operation on FN that we want to avoid. if is_google: vcard = result.firstChildElement() vcard.addElement('FN', content='oh hello there') else: vcard = result.firstChildElement() vcard.addElement('NICKNAME', content='oh hello there') stream.send(result) q.forbid_events([ EventPattern('stream-iq', iq_type='set', query_ns='vcard-temp', query_name='vCard') ]) sync_stream(q, stream) sync_dbus(bus, q, conn) if __name__ == '__main__': exec_test(not_google, params={ 'alias': 'oh hello there' }) exec_test(google, params={ 'alias': 'oh hello there' }, protocol=GoogleXmlStream) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/set-set-disconnect.py�����������������������������������0000664�0001750�0001750�00000001703�12332440117�026205� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Regression test for crash when disconnecting in the middle of a set. """ from servicetest import EventPattern, call_async, sync_dbus from gabbletest import exec_test, acknowledge_iq, expect_and_handle_get_vcard, sync_stream, disconnect_conn import constants as cs def test(q, bus, conn, stream): expect_and_handle_get_vcard(q, stream) sync_stream(q, stream) call_async( q, conn.Avatars, 'SetAvatar', 'Guy.brush', 'image/x-mighty-pirate') expect_and_handle_get_vcard(q, stream) iq_event = q.expect( 'stream-iq', iq_type='set', query_ns='vcard-temp', query_name='vCard') call_async( q, conn.Avatars, 'SetAvatar', 'LeChuck.brush', 'image/x-ghost-pirate') disconnect_conn(q, conn, stream) q.expect('dbus-error', method='SetAvatar', name=cs.NOT_AVAILABLE) q.expect('dbus-error', method='SetAvatar', name=cs.NOT_AVAILABLE) sync_dbus(bus, q, conn) if __name__ == '__main__': exec_test(test) �������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/vcard/item-not-found.py���������������������������������������0000644�0001750�0001750�00000002350�12225363340�025337� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Regression test for <http://bugs.freedesktop.org/show_bug.cgi?id=25987> where Gabble didn't understand that <item-not-found/> just means the user doesn't have a vCard yet, and so it can go right ahead and set one. """ from twisted.words.xish import domish from servicetest import call_async from gabbletest import ( exec_test, sync_stream, send_error_reply, expect_and_handle_set_vcard, ) import ns def expect_get_and_send_item_not_found(q, stream): get_vcard_event = q.expect('stream-iq', query_ns=ns.VCARD_TEMP, query_name='vCard', iq_type='get') error = domish.Element((None, 'error')) error['type'] = 'cancel' error.addElement((ns.STANZA, 'item-not-found')) send_error_reply(stream, get_vcard_event.stanza, error) def test(q, bus, conn, stream): expect_get_and_send_item_not_found(q, stream) sync_stream(q, stream) call_async( q, conn.Avatars, 'SetAvatar', 'Guy.brush', 'image/x-mighty-pirate') # Gabble checks again, but we still don't have a vCard expect_get_and_send_item_not_found(q, stream) # Never mind! It creates a new one. expect_and_handle_set_vcard(q, stream) q.expect('dbus-return', method='SetAvatar') if __name__ == '__main__': exec_test(test) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/console.py����������������������������������������������������0000664�0001750�0001750�00000005564�12332441362�023051� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" A smoketest for the XMPP console API. """ from servicetest import ( ProxyWrapper, EventPattern, call_async, assertEquals, assertContains, assertNotEquals, sync_dbus, ) from gabbletest import exec_test, acknowledge_iq, elem, elem_iq from config import PLUGINS_ENABLED from twisted.words.xish import domish import ns CONSOLE_PLUGIN_IFACE = "org.freedesktop.Telepathy.Gabble.Plugin.Console" STACY = 'stacy@pilgrim.lit' if not PLUGINS_ENABLED: print "NOTE: built without --enable-plugins, not testing XMPP console" raise SystemExit(77) def send_unrecognised_get(q, stream): stream.send( elem_iq(stream, 'get')( elem('urn:unimaginative', 'dont-handle-me-bro') )) return q.expect('stream-iq', iq_type='error') def test(q, bus, conn, stream): path, _ = conn.Future.EnsureSidecar(CONSOLE_PLUGIN_IFACE) console = ProxyWrapper(bus.get_object(conn.bus_name, path), CONSOLE_PLUGIN_IFACE) assert not console.Properties.Get(CONSOLE_PLUGIN_IFACE, 'SpewStanzas') es = [ EventPattern('dbus-signal', signal='StanzaReceived'), EventPattern('dbus-signal', signal='StanzaSent'), ] q.forbid_events(es) call_async(q, console, 'SendIQ', 'get', STACY, '<coffee xmlns="urn:unimaginative"/>') e = q.expect('stream-iq', iq_type='get', query_ns='urn:unimaginative', query_name='coffee') acknowledge_iq(stream, e.stanza) e = q.expect('dbus-return', method='SendIQ') type_, body = e.value assertEquals('result', type_) # We just assume the body works. # Turn on signalling incoming and outgoing stanzas console.Properties.Set(CONSOLE_PLUGIN_IFACE, 'SpewStanzas', True) sync_dbus(bus, q, conn) q.unforbid_events(es) send_unrecognised_get(q, stream) e = q.expect('dbus-signal', signal='StanzaReceived') xml, = e.args assertContains('<iq', xml) assertContains('<dont-handle-me-bro', xml) signal = q.expect('dbus-signal', signal='StanzaSent') assertContains('service-unavailable', signal.args[0]) # Turn off spewing out stanzas; check it works. console.Properties.Set(CONSOLE_PLUGIN_IFACE, 'SpewStanzas', False) q.forbid_events(es) send_unrecognised_get(q, stream) sync_dbus(bus, q, conn) # Try sending just any old stanza console.SendStanza(''' <message to='%(stacy)s' type='headline'> <body> Hi sis. </body> </message>''' % { 'stacy': STACY }) e = q.expect('stream-message', to=STACY, message_type='headline') # Make sure that Wocky has filled in the jabber:client namespace we # carelessly omitted. message = e.stanza assertEquals('message', message.name) assertEquals(ns.CLIENT, message.uri) body = message.firstChildElement() assertEquals('body', body.name) assertEquals(ns.CLIENT, body.uri) if __name__ == '__main__': exec_test(test) ��������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tools/��������������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�022172� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tools/servicedir-uninstalled/���������������������������������0000775�0001750�0001750�00000000000�12332445275�026651� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tools/servicedir-uninstalled/tmp-session-bus.conf.in����������0000644�0001750�0001750�00000001640�11662445070�033172� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!-- This configuration file controls the per-user-login-session message bus. Add a session-local.conf and edit that rather than changing this file directly. --> <!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> <busconfig> <!-- Our well-known bus type, don't change this --> <type>session</type> <listen>unix:tmpdir=/tmp</listen> <servicedir>@abs_top_builddir@/tests/twisted/tools/servicedir-uninstalled</servicedir> <policy context="default"> <!-- Allow everything to be sent --> <allow send_destination="*" eavesdrop="true"/> <!-- Allow everything to be received --> <allow eavesdrop="true"/> <!-- Allow anyone to own anything --> <allow own="*"/> </policy> <!-- This is included last so local configuration can override what's in this standard file --> </busconfig> ������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tools/servicedir-uninstalled/gabble.service.in����������������0000664�0001750�0001750�00000000205�12332440117�032037� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������[D-BUS Service] Name=org.freedesktop.Telepathy.ConnectionManager.gabble Exec=@abs_top_builddir@/tests/twisted/tools/exec-with-log.sh �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tools/with-session-bus.sh�������������������������������������0000664�0001750�0001750�00000005557�12223562023�025753� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/bin/sh # with-session-bus.sh - run a program with a temporary D-Bus session daemon # # The canonical location of this program is the telepathy-glib tools/ # directory, please synchronize any changes with that copy. # # Copyright (C) 2007-2008 Collabora Ltd. <http://www.collabora.co.uk/> # # Copying and distribution of this file, with or without modification, # are permitted in any medium without royalty provided the copyright # notice and this notice are preserved. set -e me=with-session-bus dbus_daemon_args="--print-address=5 --print-pid=6 --fork" sleep=0 usage () { echo "usage: $me [options] -- program [program_options]" >&2 echo "Requires write access to the current directory." >&2 echo "" >&2 echo "If \$WITH_SESSION_BUS_FORK_DBUS_MONITOR is set, fork dbus-monitor" >&2 echo "with the arguments in \$WITH_SESSION_BUS_FORK_DBUS_MONITOR_OPT." >&2 echo "The output of dbus-monitor is saved in $me-<pid>.dbus-monitor-logs" >&2 exit 2 } while test "z$1" != "z--"; do case "$1" in --sleep=*) sleep="$1" sleep="${sleep#--sleep=}" shift ;; --session) dbus_daemon_args="$dbus_daemon_args --session" shift ;; --config-file=*) # FIXME: assumes config file doesn't contain any special characters dbus_daemon_args="$dbus_daemon_args $1" shift ;; --also-for-system) with_system_bus=1 shift ;; *) usage ;; esac done shift if test "z$1" = "z"; then usage; fi exec 5> $me-$$.address exec 6> $me-$$.pid cleanup () { pid=`head -n1 $me-$$.pid` if test -n "$pid" ; then if [ -n "$CHECK_TWISTED_VERBOSE" ] || [ -n "$VERBOSE_TESTS" ]; then echo "Killing temporary bus daemon: $pid" >&2 fi kill -INT "$pid" fi rm -f $me-$$.address rm -f $me-$$.pid } trap cleanup INT HUP TERM dbus-daemon $dbus_daemon_args if [ -n "$CHECK_TWISTED_VERBOSE" ] || [ -n "$VERBOSE_TESTS" ]; then { echo -n "Temporary bus daemon is "; cat $me-$$.address; } >&2 { echo -n "Temporary bus daemon PID is "; head -n1 $me-$$.pid; } >&2 fi e=0 # These might be non-null when run from e.g. gnome-terminal 3.8, which uses # an activatable service for its windows; we don't want to inherit them either unset DBUS_STARTER_ADDRESS unset DBUS_STARTER_BUS_TYPE DBUS_SESSION_BUS_ADDRESS="`cat $me-$$.address`" export DBUS_SESSION_BUS_ADDRESS if [ -n "$with_system_bus" ] ; then DBUS_SYSTEM_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS" export DBUS_SYSTEM_BUS_ADDRESS fi if [ -n "$WITH_SESSION_BUS_FORK_DBUS_MONITOR" ] ; then echo "Forking dbus-monitor $WITH_SESSION_BUS_FORK_DBUS_MONITOR_OPT" >&2 dbus-monitor $WITH_SESSION_BUS_FORK_DBUS_MONITOR_OPT \ > $me-$$.dbus-monitor-logs 2>&1 & fi if [ -n "$GABBLE_TEST_BUSTLE" ]; then echo "Forking bustle-dbus-monitor" >&2 bustle-dbus-monitor > tools/$me-$$.bustle-logs 2>&1 & fi "$@" || e=$? if test $sleep != 0; then sleep $sleep fi trap - INT HUP TERM cleanup exit $e �������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tools/servicedir/���������������������������������������������0000775�0001750�0001750�00000000000�12332445275�024331� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tools/servicedir/tmp-session-bus.conf.in����������������������0000644�0001750�0001750�00000001614�11662445070�030653� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!-- This configuration file controls the per-user-login-session message bus. Add a session-local.conf and edit that rather than changing this file directly. --> <!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> <busconfig> <!-- Our well-known bus type, don't change this --> <type>session</type> <listen>unix:tmpdir=/tmp</listen> <servicedir>@gabbletestsdir@/twisted/tools/servicedir</servicedir> <policy context="default"> <!-- Allow everything to be sent --> <allow send_destination="*" eavesdrop="true"/> <!-- Allow everything to be received --> <allow eavesdrop="true"/> <!-- Allow anyone to own anything --> <allow own="*"/> </policy> <!-- This is included last so local configuration can override what's in this standard file --> </busconfig> ��������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tools/servicedir/gabble.service.in����������������������������0000664�0001750�0001750�00000000172�12332440117�027522� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������[D-BUS Service] Name=org.freedesktop.Telepathy.ConnectionManager.gabble Exec=@gabbletestsdir@/twisted/tools/run-gabble.sh ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tools/run-gabble.sh.in����������������������������������������0000775�0001750�0001750�00000000552�12223562023�025144� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/bin/sh G_DEBUG=fatal-warnings,fatal-criticals export G_DEBUG GABBLE_TIMING=1 export GABBLE_TIMING GABBLE_PLUGIN_DIR="@gabbletestsdir@/plugins:@pluginexecdir@" export GABBLE_PLUGIN_DIR WOCKY_CAPS_CACHE=:memory: export WOCKY_CAPS_CACHE WOCKY_CAPS_CACHE_SIZE=50 export WOCKY_CAPS_CACHE_SIZE ulimit -c unlimited @gabbletestsdir@/twisted/telepathy-gabble-debug ������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/tools/exec-with-log.sh.in�������������������������������������0000664�0001750�0001750�00000003676�12332441362�025614� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/bin/sh cd "@abs_top_builddir@/tests/twisted/tools" GABBLE_DEBUG=all GIBBER_DEBUG=all WOCKY_DEBUG=all export GABBLE_DEBUG export GIBBER_DEBUG export WOCKY_DEBUG GABBLE_TIMING=1 export GABBLE_TIMING GABBLE_PLUGIN_DIR="@abs_top_builddir@/plugins/.libs" export GABBLE_PLUGIN_DIR WOCKY_CAPS_CACHE=:memory: export WOCKY_CAPS_CACHE WOCKY_CAPS_CACHE_SIZE=50 export WOCKY_CAPS_CACHE_SIZE G_MESSAGES_DEBUG=all export G_MESSAGES_DEBUG ulimit -c unlimited exec >> gabble-testing.log 2>&1 G_SLICE=debug-blocks export G_SLICE if test -n "$GABBLE_TEST_VALGRIND"; then G_DEBUG=${G_DEBUG:+"${G_DEBUG},"}gc-friendly export G_DEBUG G_SLICE=${G_SLICE},always-malloc export G_SLICE DBUS_DISABLE_MEM_POOLS=1 export DBUS_DISABLE_MEM_POOLS GABBLE_WRAPPER="valgrind --leak-check=full --num-callers=20" GABBLE_WRAPPER="$GABBLE_WRAPPER --show-reachable=yes" GABBLE_WRAPPER="$GABBLE_WRAPPER --gen-suppressions=all" GABBLE_WRAPPER="$GABBLE_WRAPPER --child-silent-after-fork=yes" GABBLE_WRAPPER="$GABBLE_WRAPPER --suppressions=@abs_top_srcdir@/tests/suppressions/tp-glib.supp" GABBLE_WRAPPER="$GABBLE_WRAPPER --suppressions=@abs_top_srcdir@/tests/suppressions/gabble.supp" elif test -n "$GABBLE_TEST_REFDBG"; then if test -z "$REFDBG_OPTIONS" ; then REFDBG_OPTIONS="btnum=10" export REFDBG_OPTIONS fi if test -z "$GABBLE_WRAPPER" ; then GABBLE_WRAPPER="refdbg" fi elif test -n "$GABBLE_TEST_STRACE"; then GABBLE_WRAPPER="strace -o strace.log" elif test -n "$GABBLE_TEST_BACKTRACE"; then GABBLE_WRAPPER="gdb -x run_and_bt.gdb" fi # Prevent libproxy from hitting the network for wpad configuration PX_MODULE_BLACKLIST=config_wpad export PX_MODULE_BLACKLIST G_DEBUG=fatal-warnings,fatal-criticals" ${G_DEBUG}" export G_DEBUG exec @abs_top_builddir@/libtool --mode=execute $GABBLE_WRAPPER ../telepathy-gabble-debug ������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/search/�������������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�022277� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/search/extended.py��������������������������������������������0000644�0001750�0001750�00000021613�12225363340�024443� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Tests Contact Search channels to a simulated XEP-0055 service, with extensibility via Data Forms """ import dbus from twisted.words.xish import xpath from gabbletest import exec_test, acknowledge_iq from servicetest import ( call_async, unwrap, make_channel_proxy, EventPattern, assertEquals, assertSameSets, ) from search_helper import call_create, answer_extended_field_query, make_search, send_results_extended from pprint import pformat import constants as cs import ns server = 'jud.localhost' g_jid = 'guybrush.threepwood@lucasarts.example.com' f_jid = 'freddiet@pgwodehouse.example.com' def test(q, bus, conn, stream): for f in [complete_search, complete_search2, openfire_search, double_nick, no_x_in_reply]: f(q, bus, conn, stream) def do_one_search(q, bus, conn, stream, fields, expected_search_keys, terms, results): call_create(q, conn, server) ret, nc_sig = answer_extended_field_query(q, stream, server, fields) path, props = ret.value props = unwrap(props) assert props[cs.CONTACT_SEARCH_SERVER] == server, pformat(props) assert sorted(props[cs.CONTACT_SEARCH_ASK]) == expected_search_keys, \ sorted(props[cs.CONTACT_SEARCH_ASK]) assert cs.CONTACT_SEARCH_STATE not in props, pformat(props) c = make_channel_proxy(conn, path, 'Channel') c_props = dbus.Interface(c, cs.PROPERTIES_IFACE) c_search = dbus.Interface(c, cs.CHANNEL_TYPE_CONTACT_SEARCH) state = c_props.Get(cs.CHANNEL_TYPE_CONTACT_SEARCH, 'SearchState') assert state == cs.SEARCH_NOT_STARTED, state # We make a search. iq = make_search(q, c_search, c_props, server, terms) query = iq.firstChildElement() fields_sent = xpath.queryForNodes( '/iq/query[@xmlns="%s"]/x[@xmlns="%s"][@type="submit"]/field' % (ns.SEARCH, ns.X_DATA), iq) assert fields_sent is not None # check FORM_TYPE f = fields_sent[0] assert f['type'] == 'hidden' assert f['var'] == 'FORM_TYPE' value = f.firstChildElement() assert value.name == 'value' assert value.children[0] == ns.SEARCH # extract search fields search_fields = [] for f in fields_sent[1:]: value = f.firstChildElement() assert value.name == 'value' search_fields.append((f['var'], value.children[0])) # Server sends the results of the search. send_results_extended(stream, iq, results, fields) return search_fields, c, c_search, c_props def search_done(q, c, c_search, c_props): ssc = q.expect('dbus-signal', signal='SearchStateChanged') assert ssc.args[0] == cs.SEARCH_COMPLETED, ssc.args # We call Stop after the search has completed; it should succeed, but leave # the channel in state Completed rather than changing it to Failed for # reason Cancelled. call_async(q, c_search, 'Stop') event = q.expect('dbus-return', method='Stop') state = c_props.Get(cs.CHANNEL_TYPE_CONTACT_SEARCH, 'SearchState') assert state == cs.SEARCH_COMPLETED, (state, cs.SEARCH_COMPLETED) c.Close() q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed'), ) def complete_search(q, bus, conn, stream): fields = [('first', 'text-single', 'Given Name', []), ('last', 'text-single', 'Family Name', []), ('x-gender', 'list-single', 'Gender', [('male', 'Male'), ('female', 'Female')])] expected_search_keys = ['x-gender', 'x-n-family', 'x-n-given'] terms = { 'x-n-family': 'Threepwood' } g_results = { 'jid': g_jid, 'first': 'Guybrush', 'last': 'Threepwood', 'nick': 'Fancy Pants', 'x-gender': 'Male', 'email': g_jid } f_results = { 'jid': f_jid, 'first': 'Frederick', 'last': 'Threepwood', 'nick': 'Freddie', 'x-gender': 'Male', 'email': f_jid } results = { g_jid: g_results, f_jid: f_results } search_fields, chan, c_search, c_props = do_one_search (q, bus, conn, stream, fields, expected_search_keys, terms, results.values()) assert len(search_fields) == 1 assert ('last', 'Threepwood') in search_fields, search_fields e = q.expect('dbus-signal', signal='SearchResultReceived') infos = e.args[0] assertSameSets(results.keys(), infos.keys()) for id in results.keys(): i = infos[id] r = results[id] i_ = pformat(unwrap(i)) assert ("n", [], [r['last'], r['first'], "", "", ""]) in i, i_ assert ("nickname", [], [r['nick']]) in i, i_ assert ("email", [], [r['email']]) in i, i_ assert ("x-gender", [], [r['x-gender']]) in i, i_ assert ("x-n-family", [], [r['last']]) in i, i_ assert ("x-n-given", [], [r['first']]) in i, i_ assert len(i) == 6, i_ search_done(q, chan, c_search, c_props) def complete_search2(q, bus, conn, stream): # uses other, dataform specific, fields fields = [('given', 'text-single', 'Name', []), ('family', 'text-single', 'Family Name', []), ('nickname', 'text-single', 'Nickname', [])] expected_search_keys = ['nickname', 'x-n-family', 'x-n-given'] terms = { 'x-n-family': 'Threepwood' } g_results = { 'jid': g_jid, 'given': 'Guybrush', 'family': 'Threepwood', 'nickname': 'Fancy Pants', 'email': g_jid } f_results = { 'jid': f_jid, 'given': 'Frederick', 'family': 'Threepwood', 'nickname': 'Freddie', 'email': f_jid } results = { g_jid: g_results, f_jid: f_results } search_fields, chan, c_search, c_props = do_one_search (q, bus, conn, stream, fields, expected_search_keys, terms, results.values()) assert len(search_fields) == 1 assert ('family', 'Threepwood') in search_fields, search_fields e = q.expect('dbus-signal', signal='SearchResultReceived') infos = e.args[0] assertSameSets(results.keys(), infos.keys()) for id in results.keys(): i = infos[id] r = results[id] i_ = pformat(unwrap(i)) assert ("n", [], [r['family'], r['given'], "", "", ""]) in i, i_ assert ("nickname", [], [r['nickname']]) in i, i_ assert ("email", [], [r['email']]) in i, i_ assert ("x-n-family", [], [r['family']]) in i, i_ assert ("x-n-given", [], [r['given']]) in i, i_ assert len(i) == 5, i_ search_done(q, chan, c_search, c_props) def openfire_search(q, bus, conn, stream): # Openfire only supports one text field and a bunch of checkboxes fields = [('search', 'text-single', 'Search', []), ('Username', 'boolean', 'Username', []), ('Name', 'boolean', 'Name', []), ('Email', 'boolean', 'Email', [])] expected_search_keys = [''] terms = { '': '*badger*' } jid = 'badger@mushroom.org' results = {jid : { 'jid': jid, 'Name': 'Badger Badger', 'Email': jid, 'Username': 'badger'}} search_fields, chan, c_search, c_props = do_one_search (q, bus, conn, stream, fields, expected_search_keys, terms, results.values()) assert len(search_fields) == 4 assert ('search', '*badger*') in search_fields, search_fields assert ('Username', '1') in search_fields, search_fields assert ('Name', '1') in search_fields, search_fields assert ('Email', '1') in search_fields, search_fields r = q.expect('dbus-signal', signal='SearchResultReceived') infos = r.args[0] assertSameSets(results.keys(), infos.keys()) for id in results.keys(): i = infos[id] r = results[id] i_ = pformat(unwrap(i)) assert ("fn", [], [r['Name']]) in i, i_ assert ("email", [], [r['Email']]) in i, i_ assert len(i) == 2 # Server supports 'nickname' and 'nick' which are both mapped to the # "nickname" in Telepathy def double_nick(q, bus, conn, stream): fields = [('nickname', 'text-single', 'NickName', []), ('nick', 'text-single', 'Nick', []),] # ensure that 'nickname' is not added twice expected_search_keys = ['nickname'] terms = { 'nickname': 'Badger' } results = { } search_fields, chan, c_search, c_props = do_one_search (q, bus, conn, stream, fields, expected_search_keys, terms, results.values()) def no_x_in_reply(q, bus, conn, stream): fields = [('nickname', 'text-single', 'NickName', []), ('nick', 'text-single', 'Nick', []),] terms = { 'nickname': 'Badger' } call_create(q, conn, server) ret, nc_sig = answer_extended_field_query(q, stream, server, fields) path, _ = ret.value c = make_channel_proxy(conn, path, 'Channel') c_props = dbus.Interface(c, cs.PROPERTIES_IFACE) c_search = dbus.Interface(c, cs.CHANNEL_TYPE_CONTACT_SEARCH) iq = make_search(q, c_search, c_props, server, terms) # The server sends back an IQ with a <query/> but no <x/> inside the query. acknowledge_iq(stream, iq) # Gabble should tell us the query failed, and not crash. event = q.expect('dbus-signal', signal='SearchStateChanged') state = event.args[0] assertEquals(cs.SEARCH_FAILED, state) if __name__ == '__main__': exec_test(test) ���������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/search/search_helper.py���������������������������������������0000664�0001750�0001750�00000007662�12332440117�025456� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import dbus from twisted.words.protocols.jabber.client import IQ from servicetest import call_async, EventPattern from gabbletest import make_result_iq import constants as cs import ns def call_create(q, conn, server): request = dbus.Dictionary( { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CONTACT_SEARCH, }, signature='sv') if server is not None: request[cs.CONTACT_SEARCH_SERVER] = server call_async(q, conn.Requests, 'CreateChannel', request) def _wait_for_server_query(q, stream, server): # Gabble asks the server what search fields it supports iq_event = q.expect('stream-iq', to=server, query_ns=ns.SEARCH) iq = iq_event.stanza result = make_result_iq(stream, iq) query = result.firstChildElement() query.addElement("instructions", content="cybar?") return result, query def _send_server_reply(q, stream, result): stream.send(result) ret = q.expect('dbus-return', method='CreateChannel') nc_sig = q.expect('dbus-signal', signal='NewChannels') return (ret, nc_sig) def answer_field_query(q, stream, server): result, query = _wait_for_server_query(q, stream, server) # The server says it supports all the fields in unextended XEP 0055 for f in ["first", "last", "nick", "email"]: query.addElement(f) return _send_server_reply(q, stream, result) def answer_extended_field_query(q, stream, server, fields): result, query = _wait_for_server_query(q, stream, server) x = query.addElement((ns.X_DATA, 'x')) x['type'] = 'form' x.addElement('title', content="User Directory Search") x.addElement('instructions', content="mooh?") # add FORM_TYPE field = x.addElement('field') field['type'] = 'hidden' field['var'] = 'FORM_TYPE' field.addElement('value', content=ns.SEARCH) # add fields for var, type, label, options in fields: field = x.addElement('field') field['var'] = var field['type'] = type field['label'] = label # add options (if any) for value, label in options: option = field.addElement('option') option['label'] = label v = option.addElement('value', content=value) return _send_server_reply(q, stream, result) def make_search(q, c_search, c_props, server, terms): call_async(q, c_search, 'Search', terms) _, ssc_event, iq_event = q.expect_many( EventPattern('dbus-return', method='Search'), EventPattern('dbus-signal', signal='SearchStateChanged'), EventPattern('stream-iq', to=server, query_ns=ns.SEARCH, iq_type='set'), ) assert ssc_event.args[0] == cs.SEARCH_IN_PROGRESS state = c_props.Get(cs.CHANNEL_TYPE_CONTACT_SEARCH, 'SearchState') assert state == cs.SEARCH_IN_PROGRESS, state return iq_event.stanza def send_results(stream, iq, results): result = make_result_iq(stream, iq) query = result.firstChildElement() for jid, first, last, nick in results: item = query.addElement('item') item['jid'] = jid item.addElement('first', content=first) item.addElement('last', content=last) item.addElement('nick', content=nick) item.addElement('email', content=jid) stream.send(result) def send_results_extended(stream, iq, results, fields): result = make_result_iq(stream, iq) query = result.firstChildElement() x = query.addElement((ns.X_DATA, 'x')) x['type'] = 'result' x.addElement('title', content='Search result') # add reported fields reported = x.addElement('reported') for var, type, label, options in fields: field = reported.addElement('field') field['var'] = var field['label'] = label # add results for r in results: item = x.addElement('item') for var, value in r.items(): field = item.addElement('field') field['var'] = var field.addElement('value', content=value) stream.send(result) ������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/search/no-server-property.py����������������������������������0000644�0001750�0001750�00000010177�12225363340�026450� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Tests Contact Search channels to a simulated XEP-0055 service, without passing the Server property """ import dbus from twisted.words.xish import xpath from functools import partial from gabbletest import exec_test, sync_stream, make_result_iq, acknowledge_iq, elem_iq, elem, disconnect_conn from servicetest import EventPattern, assertEquals from search_helper import call_create, answer_field_query import constants as cs import ns JUD_SERVER = 'jud.localhost' def server_discovered(q, bus, conn, stream, server=None): iq_event, disco_event = q.expect_many( EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS)) acknowledge_iq(stream, iq_event.stanza) # no search server has been discovered yet. The CreateChannel operation # will be completed once the disco process is finished. call_create(q, conn, server=server) # reply to IQ query reply = make_result_iq(stream, disco_event.stanza) query = xpath.queryForNodes('/iq/query', reply)[0] item = query.addElement((None, 'item')) item['jid'] = JUD_SERVER stream.send(reply) # wait for the disco#info query event = q.expect('stream-iq', to=JUD_SERVER, query_ns=ns.DISCO_INFO) reply = elem_iq(stream, 'result', id=event.stanza['id'], from_=JUD_SERVER)( elem(ns.DISCO_INFO, 'query')( elem('identity', category='directory', type='user', name='vCard User Search')(), elem('feature', var=ns.SEARCH)())) stream.send(reply) # JUD_SERVER is used as default, and shows up as the Server property on the # resulting channel. ret, _ = answer_field_query(q, stream, JUD_SERVER) _, properties = ret.value assertEquals(JUD_SERVER, properties[cs.CONTACT_SEARCH_SERVER]) # Now that the search server has been discovered, it is used right away. call_create(q, conn, server=server) ret, _ = answer_field_query(q, stream, JUD_SERVER) _, properties = ret.value assertEquals(JUD_SERVER, properties[cs.CONTACT_SEARCH_SERVER]) def no_server_discovered(q, bus, conn, stream, server=None): iq_event, disco_event = q.expect_many( EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS)) acknowledge_iq(stream, iq_event.stanza) # no search server has been discovered yet. The CreateChannel operation # will fail once the disco process is finished. call_create(q, conn, server=server) # reply to IQ query. No search server is present reply = make_result_iq(stream, disco_event.stanza) stream.send(reply) # creation of the channel failed e = q.expect('dbus-error', method='CreateChannel', name=cs.INVALID_ARGUMENT) # This server doesn't have a search server. We can't create Search channel # without specifying a Server property call_create(q, conn, server=server) e = q.expect('dbus-error', method='CreateChannel') assertEquals(cs.INVALID_ARGUMENT, e.error.get_dbus_name()) def disconnect_before_disco(q, bus, conn, stream, server=None): iq_event, disco_event = q.expect_many( EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS)) acknowledge_iq(stream, iq_event.stanza) # try to create a channel before the disco process is completed. # This creation will fail call_create(q, conn, server=server) # connection is disconnected. CreateChannel fails disconnect_conn(q, conn, stream, [ EventPattern('dbus-error', method='CreateChannel', name=cs.DISCONNECTED)]) if __name__ == '__main__': exec_test(server_discovered) exec_test(no_server_discovered) exec_test(disconnect_before_disco) # We also test that Gabble does something sensible if you set Server to the # empty string, rather than omitting it. exec_test(partial(server_discovered, server='')) exec_test(partial(no_server_discovered, server='')) exec_test(partial(disconnect_before_disco, server='')) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/search/ceci-nest-pas-un-serveur.py����������������������������0000644�0001750�0001750�00000014233�12225363340�027407� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Tests requesting search channels to, and performing contact searches against, fake servers which are broken in various ways. """ import dbus from twisted.words.protocols.jabber.client import IQ from twisted.words.xish import domish from gabbletest import exec_test, send_error_reply, make_result_iq from servicetest import ( call_async, unwrap, make_channel_proxy, EventPattern, assertDBusError ) from pprint import pformat import constants as cs import ns def call_create(q, conn, server): """ Calls CreateChannel for the given contact search server, and returns the IQ stanza received by the server. """ request = dbus.Dictionary( { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CONTACT_SEARCH, cs.CONTACT_SEARCH_SERVER: server, }, signature='sv') call_async(q, conn.Requests, 'CreateChannel', request) iq_event = q.expect('stream-iq', to=server, query_ns=ns.SEARCH) return iq_event.stanza def not_a_search_server(q, stream, conn): iq = call_create(q, conn, 'notajud.localhost') e = domish.Element((None, 'error')) e['type'] = 'cancel' e.addElement((ns.STANZA, 'service-unavailable')) send_error_reply(stream, iq, e) event = q.expect('dbus-error', method='CreateChannel') assertDBusError(cs.NOT_AVAILABLE, event.error) def returns_invalid_fields(q, stream, conn): iq = call_create(q, conn, 'broken.localhost') result = make_result_iq(stream, iq) query = result.firstChildElement() for f in ["first", "shoe-size", "nick", "star-sign"]: query.addElement(f) stream.send(result) event = q.expect('dbus-error', method='CreateChannel') assertDBusError(cs.NOT_AVAILABLE, event.error) def returns_error_from_search(q, stream, conn): server = 'nofunforyou.localhost' iq = call_create(q, conn, server) result = make_result_iq(stream, iq) query = result.firstChildElement() query.addElement("first") stream.send(result) event = q.expect('dbus-return', method='CreateChannel') c = make_channel_proxy(conn, event.value[0], 'Channel') c_search = dbus.Interface(c, cs.CHANNEL_TYPE_CONTACT_SEARCH) call_async(q, c_search, 'Search', {'x-n-given': 'World of Goo'}) iq_event, _ = q.expect_many( EventPattern('stream-iq', to=server, query_ns=ns.SEARCH), EventPattern('dbus-signal', signal='SearchStateChanged'), ) iq = iq_event.stanza error = domish.Element((None, 'error')) error['type'] = 'modify' error.addElement((ns.STANZA, 'not-acceptable')) error.addElement((ns.STANZA, 'text'), content="We don't believe in games here.") send_error_reply(stream, iq, error) ssc = q.expect('dbus-signal', signal='SearchStateChanged') new_state, reason, details = ssc.args assert new_state == cs.SEARCH_FAILED, new_state assert reason == cs.PERMISSION_DENIED, reason # We call stop after the search has failed; it should succeed and do nothing. call_async(q, c_search, 'Stop') event = q.expect('dbus-return', method='Stop') c.Close() def returns_bees_from_search(q, stream, conn): server = 'hivemind.localhost' iq = call_create(q, conn, server) result = make_result_iq(stream, iq) query = result.firstChildElement() query.addElement("nick") stream.send(result) event = q.expect('dbus-return', method='CreateChannel') c = make_channel_proxy(conn, event.value[0], 'Channel') c_search = dbus.Interface(c, cs.CHANNEL_TYPE_CONTACT_SEARCH) call_async(q, c_search, 'Search', {'nickname': 'Buzzy'}) iq_event, _ = q.expect_many( EventPattern('stream-iq', to=server, query_ns=ns.SEARCH), EventPattern('dbus-signal', signal='SearchStateChanged'), ) iq = iq_event.stanza result = IQ(stream, 'result') result['id'] = iq['id'] result['from'] = iq['to'] result.addElement((ns.SEARCH, 'bees')).addElement('bzzzzzzz') stream.send(result) ssc = q.expect('dbus-signal', signal='SearchStateChanged') new_state, reason, details = ssc.args assert new_state == cs.SEARCH_FAILED, new_state assert reason == cs.NOT_AVAILABLE, reason # We call stop after the search has failed; it should succeed and do nothing. call_async(q, c_search, 'Stop') event = q.expect('dbus-return', method='Stop') c.Close() def disconnected_before_reply(q, stream, conn): iq = call_create(q, conn, 'slow.localhost') call_async(q, conn, 'Disconnect') event = q.expect('dbus-error', method='CreateChannel') assertDBusError(cs.DISCONNECTED, event.error) def forbidden(q, stream, conn): iq = call_create(q, conn, 'notforyou.localhost') e = domish.Element((None, 'error')) e['type'] = 'cancel' e.addElement((ns.STANZA, 'forbidden')) send_error_reply(stream, iq, e) event = q.expect('dbus-error', method='CreateChannel') assertDBusError(cs.PERMISSION_DENIED, event.error) def invalid_jid(q, stream, conn): iq = call_create(q, conn, 'invalid.localhost') e = domish.Element((None, 'error')) e['type'] = 'cancel' e.addElement((ns.STANZA, 'jid-malformed')) send_error_reply(stream, iq, e) event = q.expect('dbus-error', method='CreateChannel') assertDBusError(cs.INVALID_ARGUMENT, event.error) def really_invalid_jid(q, stream, conn): request = dbus.Dictionary( { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CONTACT_SEARCH, cs.CONTACT_SEARCH_SERVER: 'this is literally bullshit', }, signature='sv') call_async(q, conn.Requests, 'CreateChannel', request) # If the JID is actually malformed, we shouldn't even get as far as trying # to talk to it. event = q.expect('dbus-error', method='CreateChannel') assertDBusError(cs.INVALID_ARGUMENT, event.error) def test(q, bus, conn, stream): not_a_search_server(q, stream, conn) returns_invalid_fields(q, stream, conn) returns_error_from_search(q, stream, conn) returns_bees_from_search(q, stream, conn) forbidden(q, stream, conn) invalid_jid(q, stream, conn) really_invalid_jid(q, stream, conn) disconnected_before_reply(q, stream, conn) stream.sendFooter() q.expect('dbus-return', method='Disconnect') if __name__ == '__main__': exec_test(test) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/search/unextended.py������������������������������������������0000644�0001750�0001750�00000012767�12225363340�025020� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Tests Contact Search channels to a simulated XEP-0055 service, without extensibility via Data Forms """ import dbus from twisted.words.protocols.jabber.client import IQ from gabbletest import exec_test, sync_stream from servicetest import ( call_async, unwrap, make_channel_proxy, EventPattern, assertSameSets, ) from search_helper import call_create, answer_field_query, make_search, send_results from pprint import pformat import constants as cs import ns g_jid = 'guybrush.threepwood@lucasarts.example.com' f_jid = 'freddiet@pgwodehouse.example.com' g_results = (g_jid, 'Guybrush', 'Threepwood', 'Fancy Pants') f_results = (f_jid, 'Frederick', 'Threepwood', 'Freddie') results = { g_jid: g_results, f_jid: f_results } def test(q, bus, conn, stream): for f in [complete_search, cancelled_while_in_progress]: f(q, bus, conn, stream, 'jud.localhost') def complete_search(q, bus, conn, stream, server): call_create(q, conn, server) # the channel is not yet in conn.Requests.Channels as it's not ready yet channels = conn.Get(cs.CONN_IFACE_REQUESTS, 'Channels', dbus_interface=cs.PROPERTIES_IFACE) for path, props in channels: assert props[cs.CHANNEL_TYPE] != cs.CHANNEL_TYPE_CONTACT_SEARCH ret, nc_sig = answer_field_query(q, stream, server) path, props = ret.value props = unwrap(props) expected_search_keys = ['email', 'nickname', 'x-n-family', 'x-n-given'] assert props[cs.CONTACT_SEARCH_SERVER] == server, pformat(props) assert sorted(props[cs.CONTACT_SEARCH_ASK]) == expected_search_keys, \ pformat(props) assert cs.CONTACT_SEARCH_STATE not in props, pformat(props) # check that channel is listed in conn.Requests.Channels channels = conn.Get(cs.CONN_IFACE_REQUESTS, 'Channels', dbus_interface=cs.PROPERTIES_IFACE) assert (path, props) in channels c = make_channel_proxy(conn, path, 'Channel') c_props = dbus.Interface(c, cs.PROPERTIES_IFACE) c_search = dbus.Interface(c, cs.CHANNEL_TYPE_CONTACT_SEARCH) state = c_props.Get(cs.CHANNEL_TYPE_CONTACT_SEARCH, 'SearchState') assert state == cs.SEARCH_NOT_STARTED, state # We make a search. iq = make_search(q, c_search, c_props, server, { 'x-n-family': 'Threepwood' }) query = iq.firstChildElement() i = 0 for field in query.elements(): assert field.name == 'last', field.toXml() assert field.children[0] == u'Threepwood', field.children[0] i += 1 assert i == 1, query # Server sends the results of the search. send_results(stream, iq, results.values()) r = q.expect('dbus-signal', signal='SearchResultReceived') infos = r.args[0] assertSameSets(results.keys(), infos.keys()) for id in results.keys(): i = infos[id] r = results[id] i_ = pformat(unwrap(i)) assert ("n", [], [r[2], r[1], "", "", ""]) in i, i_ assert ("nickname", [], [r[3]]) in i, i_ assert ("email", [], [r[0]]) in i, i_ assert ("x-n-family", [], [r[2]]) in i, i_ assert ("x-n-given", [], [r[1]]) in i, i_ assert len(i) == 5, i_ ssc = q.expect('dbus-signal', signal='SearchStateChanged') assert ssc.args[0] == cs.SEARCH_COMPLETED, ssc.args # We call Stop after the search has completed; it should succeed, but leave # the channel in state Completed rather than changing it to Failed for # reason Cancelled. call_async(q, c_search, 'Stop') event = q.expect('dbus-return', method='Stop') state = c_props.Get(cs.CHANNEL_TYPE_CONTACT_SEARCH, 'SearchState') assert state == cs.SEARCH_COMPLETED, (state, cs.SEARCH_COMPLETED) c.Close() q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed'), ) def cancelled_while_in_progress(q, bus, conn, stream, server): call_create(q, conn, server) ret, _ = answer_field_query(q, stream, server) path, props = ret.value c = make_channel_proxy(conn, path, 'Channel') c_props = dbus.Interface(c, cs.PROPERTIES_IFACE) c_search = dbus.Interface(c, cs.CHANNEL_TYPE_CONTACT_SEARCH) iq = make_search(q, c_search, c_props, server, { 'x-n-family': 'Threepwood' }) # Before the server sends back the results, the client cancels the search. call_async(q, c_search, 'Stop') ret, ssc = q.expect_many( EventPattern('dbus-return', method='Stop'), EventPattern('dbus-signal', signal='SearchStateChanged'), ) assert ssc.args[0] == cs.SEARCH_FAILED, ssc.args assert ssc.args[1] == cs.CANCELLED, ssc.args state = c_props.Get(cs.CHANNEL_TYPE_CONTACT_SEARCH, 'SearchState') assert state == cs.SEARCH_FAILED, (state, cs.SEARCH_FAILED) # Now the server sends us the results; SearchResultReceived shouldn't fire search_result_received_event = EventPattern('dbus-signal', signal='SearchResultReceived') q.forbid_events([search_result_received_event]) send_results(stream, iq, results.values()) # Make sure Gabble's received the results. sync_stream(q, stream) # Hooray! We survived. Now let's call Stop again; it should succeed but do # nothing. search_state_changed_event = EventPattern('dbus-signal', signal='SearchStateChanged') q.forbid_events([search_state_changed_event]) call_async(q, c_search, 'Stop') ssc = q.expect('dbus-return', method='Stop') c.Close() q.unforbid_events([search_result_received_event, search_state_changed_event]) if __name__ == '__main__': exec_test(test) ���������telepathy-gabble-0.18.3/tests/twisted/olpc/���������������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�021767� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/olpc/olpc-muc-prop-change.py����������������������������������0000664�0001750�0001750�00000035177�12332441362�026267� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test OLPC MUC properties. """ import dbus from twisted.words.xish import domish, xpath from gabbletest import exec_test, acknowledge_iq, make_muc_presence from servicetest import call_async, EventPattern import constants as cs import ns from mucutil import echo_muc_presence def test(q, bus, conn, stream): iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, iq_event.stanza) buddy_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo') act_prop_iface = dbus.Interface(conn, 'org.laptop.Telepathy.ActivityProperties') bob_handle = conn.RequestHandles(1, ['bob@localhost'])[0] # Bob invites us to a chatroom, pre-seeding properties message = domish.Element(('jabber:client', 'message')) message['from'] = 'bob@localhost' message['to'] = 'test@localhost' properties = message.addElement( (ns.OLPC_ACTIVITY_PROPS, 'properties')) properties['room'] = 'chat@conf.localhost' properties['activity'] = 'foo_id' property = properties.addElement((None, 'property')) property['type'] = 'str' property['name'] = 'title' property.addContent('From the invitation') property = properties.addElement((None, 'property')) property['type'] = 'bool' property['name'] = 'private' property.addContent('1') stream.send(message) message = domish.Element((None, 'message')) message['from'] = 'chat@conf.localhost' message['to'] = 'test@localhost' x = message.addElement((ns.MUC_USER, 'x')) invite = x.addElement((None, 'invite')) invite['from'] = 'bob@localhost' reason = invite.addElement((None, 'reason')) reason.addContent('No good reason') stream.send(message) event = q.expect('dbus-signal', signal='NewChannel') assert event.args[1] == cs.CHANNEL_TYPE_TEXT assert event.args[2] == 2 # handle type assert event.args[3] == 1 # handle room_handle = 1 text_chan = bus.get_object(conn.bus_name, event.args[0]) chan_iface = dbus.Interface(text_chan, cs.CHANNEL) group_iface = dbus.Interface(text_chan, cs.CHANNEL_IFACE_GROUP) members = group_iface.GetAllMembers()[0] local_pending = group_iface.GetAllMembers()[1] remote_pending = group_iface.GetAllMembers()[2] assert len(members) == 1 assert conn.InspectHandles(1, members)[0] == 'bob@localhost' bob_handle = members[0] assert len(local_pending) == 1 # FIXME: the username-part-is-nickname assumption assert conn.InspectHandles(1, local_pending)[0] == \ 'chat@conf.localhost/test' assert len(remote_pending) == 0 room_self_handle = group_iface.GetSelfHandle() assert room_self_handle == local_pending[0] # by now, we should have picked up the extra activity properties buddy_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo') call_async(q, buddy_iface, 'GetActivities', bob_handle) event = q.expect('stream-iq', iq_type='get', to='bob@localhost') # Bob still has no (public) activities event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'bob@localhost' stream.send(event.stanza) event = q.expect('dbus-return', method='GetActivities') assert event.value == ([('foo_id', room_handle)],) props = act_prop_iface.GetProperties(room_handle) assert len(props) == 2 assert props['title'] == 'From the invitation' assert props['private'] == True # Now Bob changes the properties message = domish.Element(('jabber:client', 'message')) message['from'] = 'bob@localhost' message['to'] = 'test@localhost' properties = message.addElement( (ns.OLPC_ACTIVITY_PROPS, 'properties')) properties['room'] = 'chat@conf.localhost' properties['activity'] = 'foo_id' property = properties.addElement((None, 'property')) property['type'] = 'str' property['name'] = 'title' property.addContent('Mushroom, mushroom') property = properties.addElement((None, 'property')) property['type'] = 'bool' property['name'] = 'private' property.addContent('0') stream.send(message) event = q.expect('dbus-signal', signal='ActivityPropertiesChanged') assert event.args == [room_handle, {'title': 'Mushroom, mushroom', 'private': False }] assert act_prop_iface.GetProperties(room_handle) == \ event.args[1] # OK, now accept the invitation call_async(q, group_iface, 'AddMembers', [room_self_handle], 'Oh, OK then') q.expect_many( EventPattern('stream-presence', to='chat@conf.localhost/test'), EventPattern('dbus-signal', signal='MembersChanged', args=['', [], [bob_handle], [], [room_self_handle], 0, cs.GC_REASON_INVITED]), EventPattern('dbus-return', method='AddMembers'), ) # Send presence for own membership of room. stream.send(make_muc_presence('owner', 'moderator', 'chat@conf.localhost', 'test')) event = q.expect('dbus-signal', signal='MembersChanged') assert event.args == ['', [room_self_handle], [], [], [], 0, 0] call_async(q, buddy_iface, 'SetActivities', [('foo_id', room_handle)]) event = q.expect('stream-iq', iq_type='set') # Now that it's not private, it'll go in my PEP event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) q.expect('dbus-return', method='SetActivities') # Bob changes the properties and tells the room he's done so message = domish.Element(('jabber:client', 'message')) message['from'] = 'chat@conf.localhost/bob' message['to'] = 'chat@conf.localhost' properties = message.addElement( (ns.OLPC_ACTIVITY_PROPS, 'properties')) properties['activity'] = 'foo_id' property = properties.addElement((None, 'property')) property['type'] = 'str' property['name'] = 'title' property.addContent('Badger badger badger') property = properties.addElement((None, 'property')) property['type'] = 'bool' property['name'] = 'private' property.addContent('0') stream.send(message) event = q.expect('stream-iq', iq_type='set') message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITY_PROPS properties = xpath.queryForNodes('/activities/properties', activities[0]) assert (properties is not None and len(properties) == 1), repr(properties) assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS assert properties[0]['room'] == 'chat@conf.localhost' assert properties[0]['activity'] == 'foo_id' property = xpath.queryForNodes('/properties/property', properties[0]) assert (property is not None and len(property) == 2), repr(property) seen = set() for p in property: seen.add(p['name']) if p['name'] == 'title': assert p['type'] == 'str' assert str(p) == 'Badger badger badger' elif p['name'] == 'private': assert p['type'] == 'bool' assert str(p) == '0' else: assert False, 'Unexpected property %s' % p['name'] assert 'title' in seen, seen assert 'private' in seen, seen event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) act_prop_iface = dbus.Interface(conn, 'org.laptop.Telepathy.ActivityProperties') # test sets the title and sets private back to True call_async(q, act_prop_iface, 'SetProperties', room_handle, {'title': 'I can set the properties too', 'private': True}) event = q.expect('stream-message', to='chat@conf.localhost') message = event.stanza properties = xpath.queryForNodes('/message/properties', message) assert (properties is not None and len(properties) == 1), repr(properties) assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS assert properties[0]['room'] == 'chat@conf.localhost' assert properties[0]['activity'] == 'foo_id' property = xpath.queryForNodes('/properties/property', properties[0]) assert (property is not None and len(property) == 2), repr(property) seen = set() for p in property: seen.add(p['name']) if p['name'] == 'title': assert p['type'] == 'str' assert str(p) == 'I can set the properties too' elif p['name'] == 'private': assert p['type'] == 'bool' assert str(p) == '1' else: assert False, 'Unexpected property %s' % p['name'] assert 'title' in seen, seen assert 'private' in seen, seen event = q.expect('stream-iq', iq_type='set') event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITY_PROPS properties = xpath.queryForNodes('/activities/properties', activities[0]) assert properties is None, repr(properties) event = q.expect('stream-iq', iq_type='set') event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITIES activity = xpath.queryForNodes('/activities/activity', activities[0]) assert activity is None, repr(activity) q.expect('dbus-return', method='SetProperties') # test sets the title and sets private back to True call_async(q, act_prop_iface, 'SetProperties', room_handle, {'title': 'I can set the properties too', 'private': False}) event = q.expect('stream-message', to='chat@conf.localhost') message = event.stanza properties = xpath.queryForNodes('/message/properties', message) assert (properties is not None and len(properties) == 1), repr(properties) assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS assert properties[0]['room'] == 'chat@conf.localhost' assert properties[0]['activity'] == 'foo_id' property = xpath.queryForNodes('/properties/property', properties[0]) assert (property is not None and len(property) == 2), repr(property) seen = set() for p in property: seen.add(p['name']) if p['name'] == 'title': assert p['type'] == 'str' assert str(p) == 'I can set the properties too' elif p['name'] == 'private': assert p['type'] == 'bool' assert str(p) == '0' else: assert False, 'Unexpected property %s' % p['name'] assert 'title' in seen, seen assert 'private' in seen, seen event = q.expect('stream-iq', iq_type='set') event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITY_PROPS properties = xpath.queryForNodes('/activities/properties', activities[0]) assert (properties is not None and len(properties) == 1), repr(properties) assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS assert properties[0]['room'] == 'chat@conf.localhost' assert properties[0]['activity'] == 'foo_id' property = xpath.queryForNodes('/properties/property', properties[0]) assert (property is not None and len(property) == 2), repr(property) seen = set() for p in property: seen.add(p['name']) if p['name'] == 'title': assert p['type'] == 'str' assert str(p) == 'I can set the properties too' elif p['name'] == 'private': assert p['type'] == 'bool' assert str(p) == '0' else: assert False, 'Unexpected property %s' % p['name'] assert 'title' in seen, seen assert 'private' in seen, seen event = q.expect('stream-iq', iq_type='set') event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITIES activity = xpath.queryForNodes('/activities/activity', activities[0]) assert (activity is not None and len(activity) == 1), repr(activity) assert activity[0]['room'] == 'chat@conf.localhost' assert activity[0]['type'] == 'foo_id' # sic q.expect('dbus-return', method='SetProperties') chan_iface.Close() # we must echo the MUC presence so the room will actually close event = q.expect('stream-presence', to='chat@conf.localhost/test', presence_type='unavailable') echo_muc_presence(q, stream, event.stanza, 'none', 'participant') event = q.expect('stream-iq', iq_type='set') event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITIES activity = xpath.queryForNodes('/activities/activity', activities[0]) assert activity is None, repr(activity) event = q.expect('stream-iq', iq_type='set') event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITY_PROPS properties = xpath.queryForNodes('/activities/properties', activities[0]) assert properties is None, repr(properties) if __name__ == '__main__': exec_test(test) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/olpc/test-olpc-bundle.py��������������������������������������0000664�0001750�0001750�00000004317�12332440117�025515� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""test OLPC bundle. We shouldn't announce OLPC features until we use the OLPC interface""" import dbus from servicetest import call_async, EventPattern from gabbletest import exec_test, acknowledge_iq from twisted.words.xish import domish, xpath import ns import constants as cs olpc_features = set([ns.OLPC_BUDDY_PROPS_NOTIFY, ns.OLPC_ACTIVITIES_NOTIFY, ns.OLPC_CURRENT_ACTIVITY_NOTIFY, ns.OLPC_ACTIVITY_PROPS_NOTIFY]) def test(q, bus, conn, stream): iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, iq_event.stanza) # send diso request m = domish.Element((None, 'iq')) m['from'] = 'alice@jabber.laptop.org' m['id'] = '1' m['type'] = 'get' query = m.addElement('query') query['xmlns'] = ns.DISCO_INFO stream.send(m) # wait for disco response event = q.expect('stream-iq', iq_type='result', query_ns=ns.DISCO_INFO, to='alice@jabber.laptop.org') features = set([str(f['var']) for f in xpath.queryForNodes('/iq/query/feature', event.stanza)]) # OLPC NS aren't announced assert len(olpc_features.intersection(features)) == 0 # Use OLPC interface buddy_info_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo') call_async(q, buddy_info_iface, 'SetProperties', {'color': '#ff0000,#0000ff'}) # wait for <presence> stanza event = q.expect('stream-presence') c_nodes = xpath.queryForNodes('/presence/c', event.stanza) assert c_nodes is not None assert len(c_nodes) == 1 # send diso request m = domish.Element((None, 'iq')) m['from'] = 'alice@jabber.laptop.org' m['id'] = '2' m['type'] = 'get' query = m.addElement('query') query['xmlns'] = ns.DISCO_INFO stream.send(m) # wait for disco response event = q.expect('stream-iq', iq_type='result', query_ns=ns.DISCO_INFO, to='alice@jabber.laptop.org') assert event.stanza['id'] == '2' # OLPC NS are now announced features = set([str(f['var']) for f in xpath.queryForNodes('/iq/query/feature', event.stanza)]) assert olpc_features.issubset(features) if __name__ == '__main__': exec_test(test) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/olpc/test-olpc-set-props-preload.py���������������������������0000664�0001750�0001750�00000003045�12332440117�027621� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ """ Test connecting to a server. """ import dbus from twisted.words.xish import xpath from gabbletest import exec_test import ns def test(q, bus, conn, stream): buddy_info_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo') buddy_info_iface.SetProperties({'color': '#ff0000,#0000ff'}) conn.Connect() # buddy activities event = q.expect('stream-iq', iq_type='set', query_name='pubsub') assert xpath.queryForNodes( "/iq[@type='set']/pubsub[@xmlns='%s']" "/publish[@node='%s']" % (ns.PUBSUB, ns.OLPC_ACTIVITIES), event.stanza) # activity properties event = q.expect('stream-iq', iq_type='set', query_name='pubsub') assert xpath.queryForNodes( "/iq[@type='set']/pubsub[@xmlns='%s']" "/publish[@node='%s']" % (ns.PUBSUB, ns.OLPC_ACTIVITY_PROPS), event.stanza) # buddy properties event = q.expect('stream-iq', iq_type='set', query_name='pubsub') iq = event.stanza nodes = xpath.queryForNodes( "/iq[@type='set']/pubsub[@xmlns='%s']" "/publish[@node='%s']" % (ns.PUBSUB, ns.OLPC_BUDDY_PROPS), iq) assert nodes nodes = xpath.queryForNodes( "/publish/item" "/properties[@xmlns='%s']" "/property" % (ns.OLPC_BUDDY_PROPS), nodes[0]) assert len(nodes) == 1 assert nodes[0]['type'] == 'str' assert nodes[0]['name'] == 'color' text = str(nodes[0]) assert text == '#ff0000,#0000ff', text iq['type'] = 'result' stream.send(iq) if __name__ == '__main__': exec_test(test, do_connect=False) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/olpc/util.py��������������������������������������������������0000664�0001750�0001750�00000005434�12332440117�023312� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import dbus from servicetest import call_async, EventPattern from gabbletest import make_result_iq, elem, elem_iq from twisted.words.xish import domish, xpath from twisted.words.protocols.jabber.client import IQ import constants as cs import ns def properties_to_xml(properties): result = [] for key, (type, value) in properties.iteritems(): property = domish.Element((None, 'property')) property['type'] = type property['name'] = key property.addContent(value) result.append(property) return result def _make_pubsub_event_msg(from_, node): # manually create the item node as we need a ref on it item = domish.Element((None, 'item')) message = elem('message', from_=from_, to='test@localhost')( elem(ns.PUBSUB_EVENT, 'event')( elem('items', node=node)(item))) return message, item def send_buddy_changed_properties_msg(stream, from_, props): message, item = _make_pubsub_event_msg(from_, ns.OLPC_BUDDY_PROPS) properties = item.addElement((ns.OLPC_BUDDY_PROPS, 'properties')) for child in properties_to_xml(props): properties.addChild(child) stream.send(message) def send_buddy_changed_current_act_msg(stream, from_, id, room): message, item = _make_pubsub_event_msg(from_, ns.OLPC_CURRENT_ACTIVITY) activity = item.addElement((ns.OLPC_CURRENT_ACTIVITY, 'activity')) activity['room'] = room activity['type'] = id stream.send(message) def answer_to_current_act_pubsub_request(stream, request, id, room): # check request structure assert request['type'] == 'get' items = xpath.queryForNodes( '/iq/pubsub[@xmlns="%s"]/items' % ns.PUBSUB, request)[0] assert items['node'] == ns.OLPC_CURRENT_ACTIVITY reply = make_result_iq(stream, request) reply['from'] = request['to'] pubsub = reply.firstChildElement() items = pubsub.addElement((None, 'items')) items['node'] = ns.OLPC_CURRENT_ACTIVITY item = items.addElement((None, 'item')) item['id'] = 'itemID' activity = item.addElement((ns.OLPC_CURRENT_ACTIVITY, 'activity')) activity['room'] = room activity['type'] = id reply.send() def answer_error_to_pubsub_request(stream, request): # look for node's name in the request items = xpath.queryForNodes('/iq/pubsub/items', request)[0] node = items['node'] reply = IQ(stream, "error") reply['id'] = request['id'] reply['from'] = request['to'] pubsub = reply.addElement((ns.PUBSUB, 'pubsub')) items = pubsub.addElement((None, 'items')) items['node'] = node error = reply.addElement((None, 'error')) error['type'] = 'auth' error.addElement((ns.STANZA, 'not-authorized')) error.addElement(("%s#errors" % ns.PUBSUB, 'presence-subscription-required')) stream.send(reply) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/olpc/olpc-muc-invitation.py�����������������������������������0000664�0001750�0001750�00000021105�12332441362�026232� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test OLPC extensions to MUC invitations. """ import dbus from twisted.words.xish import domish, xpath from gabbletest import exec_test, make_muc_presence from servicetest import call_async, EventPattern import constants as cs import ns def test(q, bus, conn, stream): handles = {} handles['bob'] = conn.RequestHandles(1, ['bob@localhost'])[0] buddy_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo') act_prop_iface = dbus.Interface(conn, 'org.laptop.Telepathy.ActivityProperties') call_async(q, buddy_iface, 'GetActivities', handles['bob']) event = q.expect('stream-iq', iq_type='get', to='bob@localhost') # Bob has no activities event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'bob@localhost' stream.send(event.stanza) event = q.expect('dbus-return', method='GetActivities') # initially, Bob has no activities assert event.value == ([],) # Bob sends an activity properties message message = domish.Element(('jabber:client', 'message')) message['from'] = 'bob@localhost' message['to'] = 'test@localhost' properties = message.addElement((ns.OLPC_ACTIVITY_PROPS, 'properties')) properties['room'] = 'chat@conf.localhost' properties['activity'] = 'foo_id' property = properties.addElement((None, 'property')) property['type'] = 'str' property['name'] = 'color' property.addContent('#ffff00,#00ffff') property = properties.addElement((None, 'property')) property['type'] = 'bool' property['name'] = 'private' property.addContent('1') stream.send(message) event = q.expect('dbus-signal', signal='ActivityPropertiesChanged') handles['chat'], props = event.args assert props == {'color': '#ffff00,#00ffff', 'private' : True} event = q.expect('dbus-signal', signal='ActivitiesChanged') assert event.args[0] == handles['bob'] acts = event.args[1] assert len(acts) == 1 assert acts[0] == ('foo_id', handles['chat']) props = act_prop_iface.GetProperties(handles['chat']) assert props == {'color': '#ffff00,#00ffff', 'private' : True} # Bobs invites us to the activity message = domish.Element((None, 'message')) message['from'] = 'chat@conf.localhost' message['to'] = 'test@localhost' x = message.addElement((ns.MUC_USER, 'x')) invite = x.addElement((None, 'invite')) invite['from'] = 'bob@localhost' reason = invite.addElement((None, 'reason')) reason.addContent('No good reason') stream.send(message) event = q.expect('dbus-signal', signal='NewChannel') assert event.args[1] == cs.CHANNEL_TYPE_TEXT assert event.args[2] == 2 # handle type assert event.args[3] == handles['chat'] # handle text_chan = bus.get_object(conn.bus_name, event.args[0]) group_iface = dbus.Interface(text_chan, cs.CHANNEL_IFACE_GROUP) members = group_iface.GetAllMembers()[0] local_pending = group_iface.GetAllMembers()[1] remote_pending = group_iface.GetAllMembers()[2] assert len(members) == 1 assert conn.InspectHandles(1, members)[0] == 'bob@localhost' assert len(local_pending) == 1 # FIXME: the username-part-is-nickname assumption assert conn.InspectHandles(1, local_pending)[0] == \ 'chat@conf.localhost/test' assert len(remote_pending) == 0 handles['chat_self'] = group_iface.GetSelfHandle() assert handles['chat_self'] == local_pending[0] # by now, we should have picked up the extra activity properties call_async(q, buddy_iface, 'GetActivities', handles['bob']) event = q.expect('stream-iq', iq_type='get', to='bob@localhost') # Bob still has no (public) activities event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'bob@localhost' stream.send(event.stanza) event = q.expect('dbus-return', method='GetActivities') assert event.value == ([('foo_id', handles['chat'])],) # OK, now accept the invitation call_async(q, group_iface, 'AddMembers', [handles['chat_self']], 'Oh, OK then') _, event, _ = q.expect_many( EventPattern('stream-presence', to='chat@conf.localhost/test'), EventPattern('dbus-signal', signal='MembersChanged'), EventPattern('dbus-return', method='AddMembers') ) assert event.args == ['', [], [handles['bob']], [], [handles['chat_self']], 0, cs.GC_REASON_INVITED] # Send presence for own membership of room. stream.send(make_muc_presence('owner', 'moderator', 'chat@conf.localhost', 'test')) event = q.expect('dbus-signal', signal='MembersChanged') assert event.args == ['', [handles['chat_self']], [], [], [], 0, 0] call_async(q, buddy_iface, 'SetActivities', [('foo_id', handles['chat'])]) event = q.expect('stream-iq', iq_type='set') event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) q.expect('dbus-return', method='SetActivities') call_async(q, act_prop_iface, 'SetProperties', handles['chat'], {'color': '#ffff00,#00ffff', 'private': True}) event = q.expect('dbus-signal', signal='ActivityPropertiesChanged') chat_handle, props = event.args assert chat_handle == handles['chat'] assert props == {'color': '#ffff00,#00ffff', 'private' : True} q.expect('dbus-return', method='SetProperties') # Test sending an invitation handles['alice'] = conn.RequestHandles(1, ['alice@localhost'])[0] call_async(q, group_iface, 'AddMembers', [handles['alice']], 'I want to test invitations') event = q.expect('stream-message', to='alice@localhost') message = event.stanza properties = xpath.queryForNodes('/message/properties', message) assert (properties is not None and len(properties) == 1), repr(properties) assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS assert properties[0]['room'] == 'chat@conf.localhost' assert properties[0]['activity'] == 'foo_id' property = xpath.queryForNodes('/properties/property', properties[0]) assert (property is not None and len(property) == 2), repr(property) seen = set() for p in property: seen.add(p['name']) if p['name'] == 'color': assert p['type'] == 'str' assert str(p) == '#ffff00,#00ffff' elif p['name'] == 'private': assert p['type'] == 'bool' assert str(p) == '1' else: assert False, 'Unexpected property %s' % p['name'] assert 'color' in seen, seen assert 'private' in seen, seen event = q.expect('stream-message', to='chat@conf.localhost') message = event.stanza x = xpath.queryForNodes('/message/x', message) assert (x is not None and len(x) == 1), repr(x) assert x[0].uri == ns.MUC_USER invites = xpath.queryForNodes('/x/invite', x[0]) assert (invites is not None and len(invites) == 1), repr(invites) assert invites[0]['to'] == 'alice@localhost' reasons = xpath.queryForNodes('/invite/reason', invites[0]) assert (reasons is not None and len(reasons) == 1), repr(reasons) assert str(reasons[0]) == 'I want to test invitations' call_async(q, act_prop_iface, 'SetProperties', handles['chat'], {'color': '#f00baa,#f00baa', 'private': True}) event, apc_event, _ = q.expect_many( EventPattern('stream-message', to='alice@localhost'), EventPattern('dbus-signal', signal='ActivityPropertiesChanged'), EventPattern('dbus-return', method='SetProperties'), ) message = event.stanza properties = xpath.queryForNodes('/message/properties', message) assert (properties is not None and len(properties) == 1), repr(properties) assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS assert properties[0]['room'] == 'chat@conf.localhost' assert properties[0]['activity'] == 'foo_id' property = xpath.queryForNodes('/properties/property', properties[0]) assert (property is not None and len(property) == 2), repr(property) seen = set() for p in property: seen.add(p['name']) if p['name'] == 'color': assert p['type'] == 'str' assert str(p) == '#f00baa,#f00baa' elif p['name'] == 'private': assert p['type'] == 'bool' assert str(p) == '1' else: assert False, 'Unexpected property %s' % p['name'] assert 'color' in seen, seen assert 'private' in seen, seen chat_handle, props = apc_event.args assert chat_handle == handles['chat'] assert props == {'color': '#f00baa,#f00baa', 'private' : True} if __name__ == '__main__': exec_test(test) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/olpc/change-notifications.py����������������������������������0000664�0001750�0001750�00000001754�12332441362�026435� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" test OLPC Buddy properties change notifications """ # FIXME: merge this file to other tests ? from servicetest import EventPattern from gabbletest import exec_test, acknowledge_iq import constants as cs from util import send_buddy_changed_properties_msg import ns def test(q, bus, conn, stream): iq_event, disco_event = q.expect_many( EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS)) acknowledge_iq(stream, iq_event.stanza) handles = {} handles['alice'] = conn.RequestHandles(1, ['alice@localhost'])[0] # Alice, one our friends changed her properties send_buddy_changed_properties_msg(stream, 'alice@localhost', {'color': ('str', '#005FE4,#00A0FF')}) event = q.expect('dbus-signal', signal='PropertiesChanged', args=[handles['alice'], {'color' : '#005FE4,#00A0FF'}]) if __name__ == '__main__': exec_test(test) ��������������������telepathy-gabble-0.18.3/tests/twisted/olpc/current-activity.py��������������������������������������0000664�0001750�0001750�00000004547�12332441362�025660� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" test OLPC Buddy properties current activity """ import dbus from servicetest import call_async, EventPattern from gabbletest import exec_test, acknowledge_iq import constants as cs from util import (send_buddy_changed_current_act_msg, answer_to_current_act_pubsub_request, answer_error_to_pubsub_request) import ns def test(q, bus, conn, stream): iq_event, disco_event = q.expect_many( EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS)) acknowledge_iq(stream, iq_event.stanza) buddy_info_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo') handles = {} # Alice is one of our friend so we receive her PEP notifications handles['alice'] = conn.RequestHandles(1, ['alice@localhost'])[0] # Try to get Alice's currrent-activity call_async(q, buddy_info_iface, "GetCurrentActivity", handles['alice']) # Alice's current-activity is not in the cache so Gabble sends a PEP query event = q.expect('stream-iq', iq_type='get', query_name='pubsub') answer_to_current_act_pubsub_request(stream, event.stanza, 'activity1', 'room1@conference.localhost') event = q.expect('dbus-return', method='GetCurrentActivity') id, handles['room1'] = event.value assert id == 'activity1' assert conn.InspectHandles(2, [handles['room1']]) == \ ['room1@conference.localhost'] # Retry to get Alice's current-activity # Alice's current-activity is now in the cache so Gabble doesn't # send PEP query assert buddy_info_iface.GetCurrentActivity(handles['alice']) == \ ('activity1', handles['room1']) # Alice changed her current-activity send_buddy_changed_current_act_msg(stream, 'alice@localhost', 'activity2', 'room2@conference.localhost') event = q.expect('dbus-signal', signal='CurrentActivityChanged') contact, id, handles['room2'] = event.args assert contact == handles['alice'] assert id == 'activity2' assert conn.InspectHandles(2, [handles['room2']]) == \ ['room2@conference.localhost'] # Get Alice's current-activity as the cache have to be updated assert buddy_info_iface.GetCurrentActivity(handles['alice']) == \ ('activity2', handles['room2']) if __name__ == '__main__': exec_test(test) ���������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/gateways.py���������������������������������������������������0000664�0001750�0001750�00000007576�12332441362�023240� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test the gateways plugin """ import dbus from twisted.words.xish import domish, xpath from servicetest import ( sync_dbus, call_async, EventPattern, assertEquals, assertContains, ) from gabbletest import ( exec_test, send_error_reply, acknowledge_iq, sync_stream, make_presence, ) import constants as cs import ns from config import PLUGINS_ENABLED PLUGIN_IFACE = "org.freedesktop.Telepathy.Gabble.Plugin.Gateways" if not PLUGINS_ENABLED: print "NOTE: built without --enable-plugins, not testing plugins" raise SystemExit(77) def test_success(q, gateways_iface, stream): call_async(q, gateways_iface, 'Register', 'talkd.example.com', '1970', 's3kr1t') e = q.expect('stream-iq', iq_type='set', query_name='query', query_ns=ns.REGISTER, to='talkd.example.com') assertEquals('1970', xpath.queryForString('/query/username', e.query)) assertEquals('s3kr1t', xpath.queryForString('/query/password', e.query)) acknowledge_iq(stream, e.stanza) q.expect_many( EventPattern('dbus-return', method='Register'), EventPattern('stream-presence', presence_type='subscribe', to='talkd.example.com'), ) stream.send(make_presence('talkd.example.com', type='subscribed')) def test_conflict(q, gateways_iface, stream): call_async(q, gateways_iface, 'Register', 'sip.example.com', '8675309', 'jenny') e = q.expect('stream-iq', iq_type='set', query_name='query', query_ns=ns.REGISTER, to='sip.example.com') assertEquals('8675309', xpath.queryForString('/query/username', e.query)) assertEquals('jenny', xpath.queryForString('/query/password', e.query)) error = domish.Element((None, 'error')) error['type'] = 'cancel' error['code'] = '409' error.addElement((ns.STANZA, 'conflict')) send_error_reply(stream, e.stanza, error) q.expect('dbus-error', method='Register', name=cs.REGISTRATION_EXISTS) def test_not_acceptable(q, gateways_iface, stream): call_async(q, gateways_iface, 'Register', 'fully-captcha-enabled.example.com', 'lalala', 'stoats') e = q.expect('stream-iq', iq_type='set', query_name='query', query_ns=ns.REGISTER, to='fully-captcha-enabled.example.com') assertEquals('lalala', xpath.queryForString('/query/username', e.query)) assertEquals('stoats', xpath.queryForString('/query/password', e.query)) error = domish.Element((None, 'error')) error['type'] = 'modify' error['code'] = '406' error.addElement((ns.STANZA, 'not-acceptable')) send_error_reply(stream, e.stanza, error) q.expect('dbus-error', method='Register', name=cs.NOT_AVAILABLE) def test(q, bus, conn, stream): # Request a sidecar thate we support before we're connected; it should just # wait around until we're connected. call_async(q, conn.Future, 'EnsureSidecar', PLUGIN_IFACE) conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) # Now we're connected, the call we made earlier should return. path, props = q.expect('dbus-return', method='EnsureSidecar').value # This sidecar doesn't even implement get_immutable_properties; it # should just get the empty dict filled in for it. assertEquals({}, props) gateways_iface = dbus.Interface(bus.get_object(conn.bus_name, path), PLUGIN_IFACE) test_success(q, gateways_iface, stream) test_conflict(q, gateways_iface, stream) test_not_acceptable(q, gateways_iface, stream) call_async(q, conn, 'Disconnect') q.expect_many( EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_DISCONNECTED, cs.CSR_REQUESTED]), EventPattern('stream-closed'), ) stream.sendFooter() q.expect('dbus-return', method='Disconnect') if __name__ == '__main__': exec_test(test, do_connect=False) ����������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/Makefile.in���������������������������������������������������0000664�0001750�0001750�00000152331�12332443655�023104� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @ENABLE_INSTALLED_TESTS_TRUE@gabbledebug_PROGRAMS = \ @ENABLE_INSTALLED_TESTS_TRUE@ telepathy-gabble-debug$(EXEEXT) @ENABLE_INSTALLED_TESTS_FALSE@noinst_PROGRAMS = \ @ENABLE_INSTALLED_TESTS_FALSE@ telepathy-gabble-debug$(EXEEXT) DIST_COMMON = $(top_srcdir)/tools/check-coding-style.mk \ $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(am__nobase_dist_twistedtests_SCRIPTS_DIST) \ $(top_srcdir)/depcomp \ $(am__nobase_dist_twistedtests_DATA_DIST) subdir = tests/twisted ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_config_dir.m4 \ $(top_srcdir)/m4/compiler.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/tp-compiler-flag.m4 \ $(top_srcdir)/m4/tp-compiler-warnings.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(gabbledebugdir)" \ "$(DESTDIR)$(twistedtestsdir)" "$(DESTDIR)$(twistedtestsdir)" \ "$(DESTDIR)$(twistedtestsdir)" "$(DESTDIR)$(twistedtestsdir)" PROGRAMS = $(gabbledebug_PROGRAMS) $(noinst_PROGRAMS) am_telepathy_gabble_debug_OBJECTS = main-debug.$(OBJEXT) \ test-resolver.$(OBJEXT) telepathy_gabble_debug_OBJECTS = $(am_telepathy_gabble_debug_OBJECTS) am__DEPENDENCIES_1 = telepathy_gabble_debug_DEPENDENCIES = \ $(top_builddir)/src/libgabble-convenience.la \ $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = telepathy_gabble_debug_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(telepathy_gabble_debug_LDFLAGS) \ $(LDFLAGS) -o $@ am__nobase_dist_twistedtests_SCRIPTS_DIST = tools/with-session-bus.sh am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } SCRIPTS = $(nobase_dist_twistedtests_SCRIPTS) \ $(nobase_nodist_twistedtests_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(telepathy_gabble_debug_SOURCES) DIST_SOURCES = $(telepathy_gabble_debug_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__nobase_dist_twistedtests_DATA_DIST = addressing.py \ avatar-requirements.py caps/advertise-contact-caps.py \ caps/advertise-legacy.py caps/broken-reply.py \ caps/caps-cache.py caps/caps-persistent-cache.py \ caps/compat-bundles.py caps/disco-without-node.py \ caps/double-disco.py caps/from-bare-jid.py caps/hashed-caps.py \ caps_helper.py caps/initial-caps.py caps/jingle-caps.py \ caps/offline.py caps/receive-jingle.py caps/trust-thyself.py \ caps/tube-caps.py client-types.py cm/protocol.py \ connect/disco-error-from-bare-jid.py connect/disco-facebook.py \ connect/disconnect-timeout.py connect/disco-no-reply.py \ connect/network-error.py connect/stream-closed.py \ connect/test-connection-params.py connect/test-fail.py \ connect/test-nonblocking-tls.py connect/test-success.py \ connect/test-twice.py console.py dataforms.py gateways.py \ last-activity.py mail-notification.py muc/avatars.py \ muc/banned.py muc/chat-states.py muc/conference.py \ muc/kicked.py muc/name-conflict.py muc/password.py \ muc/presence-before-closing.py muc/renamed.py \ muc/room-config.py muc/roomlist.py muc/room.py \ muc/scrollback.py muc/send-error.py muc/subject.py \ muc/test-ensure.py muc/test-muc-alias.py \ muc/test-muc-invitation.py muc/test-muc-ownership.py \ muc/test-muc.py olpc/change-notifications.py \ olpc/current-activity.py olpc/olpc-muc-invitation.py \ olpc/olpc-muc-prop-change.py olpc/test-olpc-bundle.py \ olpc/test-olpc-set-props-preload.py pep-support.py \ plugin-channel-managers.py power-save.py presence/decloak.py \ presence/error.py presence/initial-contact-presence.py \ presence/initial-presence.py presence/invisible_xep_0126.py \ presence/invisible_xep_0186.py presence/plugins.py \ presence/presence.py presence/set-idempotence.py \ presence/shared-status.py pubsub.py roster/authorize.py \ roster/edit-before-roster.py roster/ensure.py \ roster/groups-12791.py roster/groups.py \ roster/initial-aliases.py roster/push-from-contact.py \ roster/push-without-id.py roster/removed-from-rp-subscribe.py \ roster/request-group-after-roster.py \ roster/request-group-before-roster.py \ roster/test-google-roster.py \ roster/test-roster-item-deletion.py roster/test-roster.py \ roster/test-roster-subscribe.py \ roster/test-save-alias-to-roster.py sasl/abort.py \ sasl/close.py sasl/complex.py sasl/jabber_auth.py \ sasl/plain.py sasl/telepathy-password.py \ search/ceci-nest-pas-un-serveur.py search/extended.py \ search/no-server-property.py search/unextended.py \ servicetest.py sidecar-own-caps.py sidecars.py test-debug.py \ test-fallback-socks5-proxy.py test-location.py \ test-register.py text/destroy.py text/ensure.py \ text/facebook-own-message.py text/initiate.py \ text/initiate-requestotron.py text/receipts.py text/respawn.py \ text/send-error.py text/send-to-correct-resource.py \ text/test-chat-state.py text/test-text-delayed.py \ text/test-text-no-body.py text/test-text.py \ tls/legacy-jabber.py tls/server-tls-channel.py version.py \ file-transfer/test-caps-file-transfer.py \ file-transfer/test-ibb-too-early.py \ file-transfer/test-receive-file-and-close-socket-while-receiving.py \ file-transfer/test-receive-file-and-disconnect.py \ file-transfer/test-receive-file-and-sender-disconnect-while-pending.py \ file-transfer/test-receive-file-and-sender-disconnect-while-transfering.py \ file-transfer/test-receive-file-decline.py \ file-transfer/test-receive-file.py \ file-transfer/test-send-file-and-cancel-immediately.py \ file-transfer/test-send-file-declined.py \ file-transfer/test-send-file-provide-immediately.py \ file-transfer/test-send-file-send-before-accept.py \ file-transfer/test-send-file-to-unknown-contact.py \ file-transfer/test-send-file-wait-to-provide.py \ file-transfer/test-uri.py file-transfer/metadata.py \ file-transfer/ft-client-caps.py \ jingle-share/test-caps-file-transfer.py \ jingle-share/test-multift.py \ jingle-share/test-receive-file-and-close-socket-while-receiving.py \ jingle-share/test-receive-file-and-disconnect.py \ jingle-share/test-receive-file-and-sender-disconnect-while-pending.py \ jingle-share/test-receive-file-and-sender-disconnect-while-transfering.py \ jingle-share/test-receive-file-decline.py \ jingle-share/test-send-file-and-cancel-immediately.py \ jingle-share/test-send-file.py \ jingle-share/test-send-file-send-before-accept.py \ jingle-share/test-send-file-wait-to-provide.py \ tubes/accept-muc-dbus-tube.py tubes/accept-muc-stream-tube.py \ tubes/accept-private-dbus-tube.py \ tubes/accept-private-stream-tube.py \ tubes/check-create-tube-return.py \ tubes/close-muc-with-closed-tube.py \ tubes/create-invalid-tube-channels.py tubes/ensure-si-tube.py \ tubes/offer-muc-dbus-tube.py tubes/offer-muc-stream-tube.py \ tubes/offer-no-caps.py tubes/offer-private-dbus-tube.py \ tubes/offer-private-stream-tube.py \ tubes/request-invalid-dbus-tube.py \ tubes/test-get-available-tubes.py tubes/test-socks5-muc.py \ jingle/accept-extra-stream.py jingle/call-basics.py \ jingle/call-codecoffer.py \ jingle/call-content-adding-removal.py jingle/call-dtmf.py \ jingle/call-google-relay.py jingle/call-hold-audio.py \ jingle/call-hold-av.py jingle/call-muc-cancel.py \ jingle/call-muc.py jingle/call-muc-re-re-request.py \ jingle/call-state.py jingle/decloak-peer.py \ jingle/dtmf-no-audio.py jingle/dtmf.py jingle/google-relay.py \ jingle/hold-audio.py jingle/hold-av.py \ jingle/incoming-basics.py jingle/incoming-call-stream-error.py \ jingle/incoming-gmail-modern-jingle.py \ jingle/initial-audio-video.py jingle/misuse.py \ jingle/outgoing-basics.py jingle/outgoing-ensure.py \ jingle/outgoing-many-streams.py jingle/payload-types.py \ jingle/preload-caps-crash.py jingle/session-id-collision.py \ jingle/stream-errors-on-content-reject.py \ jingle/stream-errors-on-terminate.py \ jingle/stream-handler-error.py jingle/stun-server.py \ jingle/test-content-adding-removal.py \ jingle/test-content-complex.py jingle/test-description-info.py \ jingle/test-incoming-call-reject.py \ jingle/test-incoming-iceudp.py \ jingle/test-outgoing-call-rejected.py \ jingle/test-outgoing-iceudp.py \ jingle/test-wait-for-caps-incomplete.py \ jingle/test-wait-for-caps.py jingle/transport-info-parsing.py \ jingle/unknown-session.py vcard/clear-avatar.py \ vcard/disconnect-during-pep.py vcard/get-contact-info.py \ vcard/item-not-found.py vcard/overlapping-sets.py \ vcard/redundant-set.py vcard/refresh-contact-info.py \ vcard/set-avatar.py vcard/set-contact-info.py \ vcard/set-set-disconnect.py vcard/supported-fields.py \ vcard/test-alias-empty-vcard.py vcard/test-alias-message.py \ vcard/test-alias-pep.py vcard/test-alias.py \ vcard/test-avatar-async.py \ vcard/test-avatar-multiple-resources.py vcard/test-avatar.py \ vcard/test-avatar-retrieved.py vcard/test-avatar-tokens.py \ vcard/test-save-alias-to-vcard.py vcard/test-set-alias.py \ vcard/test-vcard-cache.py vcard/test-vcard-race.py \ vcard/update-get-failed.py vcard/update-rejected.py \ bytestream.py connect/torture.py constants.py \ file-transfer/file_transfer_helper.py gabbletest.py \ httptest.py jingle/call_helper.py jingle/callutils.py \ jingle/__init__.py jingle/jingletest2.py \ jingle-share/file_transfer_helper.py \ jingle-share/jingleshareutils.py mucutil.py ns.py olpc/util.py \ presence/__init__.py presence/invisible_helper.py \ rostertest.py sasl/saslutil.py search/search_helper.py \ test-helper.py tls-cert.pem tls-key.pem tubes/tubetestutil.py DATA = $(nobase_dist_twistedtests_DATA) \ $(nobase_nodist_twistedtests_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLIENT_TYPE = @CLIENT_TYPE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_CODING_STYLE_CHECKS = @ENABLE_CODING_STYLE_CHECKS@ ENABLE_PLUGINS = @ENABLE_PLUGINS@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NICE_CFLAGS = @NICE_CFLAGS@ NICE_LIBS = @NICE_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOUP_CFLAGS = @SOUP_CFLAGS@ SOUP_LIBS = @SOUP_LIBS@ STRIP = @STRIP@ TEST_PYTHON = @TEST_PYTHON@ TP_GLIB_CFLAGS = @TP_GLIB_CFLAGS@ TP_GLIB_LIBS = @TP_GLIB_LIBS@ VERSION = @VERSION@ WOCKY_CFLAGS = @WOCKY_CFLAGS@ WOCKY_LIBS = @WOCKY_LIBS@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gabbletestsdir = @gabbletestsdir@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ pluginexecdir = @pluginexecdir@ pluginexeclibdir = @pluginexeclibdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ TWISTED_TESTS = addressing.py avatar-requirements.py \ caps/advertise-contact-caps.py caps/advertise-legacy.py \ caps/broken-reply.py caps/caps-cache.py \ caps/caps-persistent-cache.py caps/compat-bundles.py \ caps/disco-without-node.py caps/double-disco.py \ caps/from-bare-jid.py caps/hashed-caps.py caps_helper.py \ caps/initial-caps.py caps/jingle-caps.py caps/offline.py \ caps/receive-jingle.py caps/trust-thyself.py caps/tube-caps.py \ client-types.py cm/protocol.py \ connect/disco-error-from-bare-jid.py connect/disco-facebook.py \ connect/disconnect-timeout.py connect/disco-no-reply.py \ connect/network-error.py connect/stream-closed.py \ connect/test-connection-params.py connect/test-fail.py \ connect/test-nonblocking-tls.py connect/test-success.py \ connect/test-twice.py console.py dataforms.py gateways.py \ last-activity.py mail-notification.py muc/avatars.py \ muc/banned.py muc/chat-states.py muc/conference.py \ muc/kicked.py muc/name-conflict.py muc/password.py \ muc/presence-before-closing.py muc/renamed.py \ muc/room-config.py muc/roomlist.py muc/room.py \ muc/scrollback.py muc/send-error.py muc/subject.py \ muc/test-ensure.py muc/test-muc-alias.py \ muc/test-muc-invitation.py muc/test-muc-ownership.py \ muc/test-muc.py olpc/change-notifications.py \ olpc/current-activity.py olpc/olpc-muc-invitation.py \ olpc/olpc-muc-prop-change.py olpc/test-olpc-bundle.py \ olpc/test-olpc-set-props-preload.py pep-support.py \ plugin-channel-managers.py power-save.py presence/decloak.py \ presence/error.py presence/initial-contact-presence.py \ presence/initial-presence.py presence/invisible_xep_0126.py \ presence/invisible_xep_0186.py presence/plugins.py \ presence/presence.py presence/set-idempotence.py \ presence/shared-status.py pubsub.py roster/authorize.py \ roster/edit-before-roster.py roster/ensure.py \ roster/groups-12791.py roster/groups.py \ roster/initial-aliases.py roster/push-from-contact.py \ roster/push-without-id.py roster/removed-from-rp-subscribe.py \ roster/request-group-after-roster.py \ roster/request-group-before-roster.py \ roster/test-google-roster.py \ roster/test-roster-item-deletion.py roster/test-roster.py \ roster/test-roster-subscribe.py \ roster/test-save-alias-to-roster.py sasl/abort.py \ sasl/close.py sasl/complex.py sasl/jabber_auth.py \ sasl/plain.py sasl/telepathy-password.py \ search/ceci-nest-pas-un-serveur.py search/extended.py \ search/no-server-property.py search/unextended.py \ servicetest.py sidecar-own-caps.py sidecars.py test-debug.py \ test-fallback-socks5-proxy.py test-location.py \ test-register.py text/destroy.py text/ensure.py \ text/facebook-own-message.py text/initiate.py \ text/initiate-requestotron.py text/receipts.py text/respawn.py \ text/send-error.py text/send-to-correct-resource.py \ text/test-chat-state.py text/test-text-delayed.py \ text/test-text-no-body.py text/test-text.py \ tls/legacy-jabber.py tls/server-tls-channel.py version.py \ $(NULL) $(TWISTED_FT_TESTS) $(TWISTED_TUBE_TESTS) \ $(TWISTED_JINGLE_TESTS) $(TWISTED_VCARD_TESTS) TWISTED_TUBE_TESTS = \ tubes/accept-muc-dbus-tube.py \ tubes/accept-muc-stream-tube.py \ tubes/accept-private-dbus-tube.py \ tubes/accept-private-stream-tube.py \ tubes/check-create-tube-return.py \ tubes/close-muc-with-closed-tube.py \ tubes/create-invalid-tube-channels.py \ tubes/ensure-si-tube.py \ tubes/offer-muc-dbus-tube.py \ tubes/offer-muc-stream-tube.py \ tubes/offer-no-caps.py \ tubes/offer-private-dbus-tube.py \ tubes/offer-private-stream-tube.py \ tubes/request-invalid-dbus-tube.py \ tubes/test-get-available-tubes.py \ tubes/test-socks5-muc.py \ $(NULL) TWISTED_VCARD_TESTS = \ vcard/clear-avatar.py \ vcard/disconnect-during-pep.py \ vcard/get-contact-info.py \ vcard/item-not-found.py \ vcard/overlapping-sets.py \ vcard/redundant-set.py \ vcard/refresh-contact-info.py \ vcard/set-avatar.py \ vcard/set-contact-info.py \ vcard/set-set-disconnect.py \ vcard/supported-fields.py \ vcard/test-alias-empty-vcard.py \ vcard/test-alias-message.py \ vcard/test-alias-pep.py \ vcard/test-alias.py \ vcard/test-avatar-async.py \ vcard/test-avatar-multiple-resources.py \ vcard/test-avatar.py \ vcard/test-avatar-retrieved.py \ vcard/test-avatar-tokens.py \ vcard/test-save-alias-to-vcard.py \ vcard/test-set-alias.py \ vcard/test-vcard-cache.py \ vcard/test-vcard-race.py \ vcard/update-get-failed.py \ vcard/update-rejected.py \ $(NULL) TWISTED_JINGLE_TESTS = \ jingle/accept-extra-stream.py \ jingle/call-basics.py \ jingle/call-codecoffer.py \ jingle/call-content-adding-removal.py \ jingle/call-dtmf.py \ jingle/call-google-relay.py \ jingle/call-hold-audio.py \ jingle/call-hold-av.py \ jingle/call-muc-cancel.py \ jingle/call-muc.py \ jingle/call-muc-re-re-request.py \ jingle/call-state.py \ jingle/decloak-peer.py \ jingle/dtmf-no-audio.py \ jingle/dtmf.py \ jingle/google-relay.py \ jingle/hold-audio.py \ jingle/hold-av.py \ jingle/incoming-basics.py \ jingle/incoming-call-stream-error.py \ jingle/incoming-gmail-modern-jingle.py \ jingle/initial-audio-video.py \ jingle/misuse.py \ jingle/outgoing-basics.py \ jingle/outgoing-ensure.py \ jingle/outgoing-many-streams.py \ jingle/payload-types.py \ jingle/preload-caps-crash.py \ jingle/session-id-collision.py \ jingle/stream-errors-on-content-reject.py \ jingle/stream-errors-on-terminate.py \ jingle/stream-handler-error.py \ jingle/stun-server.py \ jingle/test-content-adding-removal.py \ jingle/test-content-complex.py \ jingle/test-description-info.py \ jingle/test-incoming-call-reject.py \ jingle/test-incoming-iceudp.py \ jingle/test-outgoing-call-rejected.py \ jingle/test-outgoing-iceudp.py \ jingle/test-wait-for-caps-incomplete.py \ jingle/test-wait-for-caps.py \ jingle/transport-info-parsing.py \ jingle/unknown-session.py \ $(NULL) TWISTED_FT_TESTS = \ file-transfer/test-caps-file-transfer.py \ file-transfer/test-ibb-too-early.py \ file-transfer/test-receive-file-and-close-socket-while-receiving.py \ file-transfer/test-receive-file-and-disconnect.py \ file-transfer/test-receive-file-and-sender-disconnect-while-pending.py \ file-transfer/test-receive-file-and-sender-disconnect-while-transfering.py \ file-transfer/test-receive-file-decline.py \ file-transfer/test-receive-file.py \ file-transfer/test-send-file-and-cancel-immediately.py \ file-transfer/test-send-file-declined.py \ file-transfer/test-send-file-provide-immediately.py \ file-transfer/test-send-file-send-before-accept.py \ file-transfer/test-send-file-to-unknown-contact.py \ file-transfer/test-send-file-wait-to-provide.py \ file-transfer/test-uri.py \ file-transfer/metadata.py \ file-transfer/ft-client-caps.py \ jingle-share/test-caps-file-transfer.py \ jingle-share/test-multift.py \ jingle-share/test-receive-file-and-close-socket-while-receiving.py \ jingle-share/test-receive-file-and-disconnect.py \ jingle-share/test-receive-file-and-sender-disconnect-while-pending.py \ jingle-share/test-receive-file-and-sender-disconnect-while-transfering.py \ jingle-share/test-receive-file-decline.py \ jingle-share/test-send-file-and-cancel-immediately.py \ jingle-share/test-send-file.py \ jingle-share/test-send-file-send-before-accept.py \ jingle-share/test-send-file-wait-to-provide.py \ $(NULL) # other files used by the twisted tests, but are not tests and are not built # source TWISTED_OTHER_FILES = \ bytestream.py \ connect/torture.py \ constants.py \ file-transfer/file_transfer_helper.py \ gabbletest.py \ httptest.py \ jingle/call_helper.py \ jingle/callutils.py \ jingle/__init__.py \ jingle/jingletest2.py \ jingle-share/file_transfer_helper.py \ jingle-share/jingleshareutils.py \ mucutil.py \ ns.py \ olpc/util.py \ presence/__init__.py \ presence/invisible_helper.py \ rostertest.py \ sasl/saslutil.py \ search/search_helper.py \ test-helper.py \ tls-cert.pem \ tls-key.pem \ tubes/tubetestutil.py \ $(NULL) # Install files in each directory. They could be tests, pristine data files, # scripts or built source @ENABLE_INSTALLED_TESTS_TRUE@twistedtestsdir = @gabbletestsdir@/twisted @ENABLE_INSTALLED_TESTS_TRUE@nobase_nodist_twistedtests_SCRIPTS = \ @ENABLE_INSTALLED_TESTS_TRUE@ run-test.sh \ @ENABLE_INSTALLED_TESTS_TRUE@ tools/exec-with-log.sh \ @ENABLE_INSTALLED_TESTS_TRUE@ tools/run-gabble.sh \ @ENABLE_INSTALLED_TESTS_TRUE@ $(NULL) @ENABLE_INSTALLED_TESTS_TRUE@nobase_dist_twistedtests_SCRIPTS = \ @ENABLE_INSTALLED_TESTS_TRUE@ tools/with-session-bus.sh \ @ENABLE_INSTALLED_TESTS_TRUE@ $(NULL) @ENABLE_INSTALLED_TESTS_TRUE@nobase_dist_twistedtests_DATA = \ @ENABLE_INSTALLED_TESTS_TRUE@ $(TWISTED_TESTS) \ @ENABLE_INSTALLED_TESTS_TRUE@ $(TWISTED_OTHER_FILES) \ @ENABLE_INSTALLED_TESTS_TRUE@ $(NULL) @ENABLE_INSTALLED_TESTS_TRUE@nobase_nodist_twistedtests_DATA = \ @ENABLE_INSTALLED_TESTS_TRUE@ config.py \ @ENABLE_INSTALLED_TESTS_TRUE@ gabble-twisted-tests.list \ @ENABLE_INSTALLED_TESTS_TRUE@ $(installed_conf_files) \ @ENABLE_INSTALLED_TESTS_TRUE@ $(service_files) # set to 6 when using refdbg, to give Gabble time to exit CHECK_TWISTED_SLEEP = 0 @ENABLE_DEBUG_FALSE@DEBUGGING_PYBOOL = False @ENABLE_DEBUG_TRUE@DEBUGGING_PYBOOL = True @ENABLE_PLUGINS_FALSE@PLUGINS_ENABLED_PYBOOL = False @ENABLE_PLUGINS_TRUE@PLUGINS_ENABLED_PYBOOL = True @ENABLE_CHANNEL_TYPE_CALL_FALSE@CHANNEL_TYPE_CALL_ENABLED_PYBOOL = False @ENABLE_CHANNEL_TYPE_CALL_TRUE@CHANNEL_TYPE_CALL_ENABLED_PYBOOL = True @ENABLE_GOOGLE_RELAY_FALSE@GOOGLE_RELAY_ENABLED_PYBOOL = False @ENABLE_GOOGLE_RELAY_TRUE@GOOGLE_RELAY_ENABLED_PYBOOL = True @ENABLE_FILE_TRANSFER_FALSE@FILE_TRANSFER_ENABLED_PYBOOL = False @ENABLE_FILE_TRANSFER_TRUE@FILE_TRANSFER_ENABLED_PYBOOL = True @ENABLE_VOIP_FALSE@VOIP_ENABLED_PYBOOL = False @ENABLE_VOIP_TRUE@VOIP_ENABLED_PYBOOL = True @ENABLE_JINGLE_FILE_TRANSFER_FALSE@JINGLE_FILE_TRANSFER_ENABLED_PYBOOL = False @ENABLE_JINGLE_FILE_TRANSFER_TRUE@JINGLE_FILE_TRANSFER_ENABLED_PYBOOL = True BUILT_SOURCES = config.py $(service_files) $(installed_conf_files) \ $(uninstalled_service_files) $(uninstalled_conf_files) \ gabble-twisted-tests.list run-test.sh tools/exec-with-log.sh \ tools/run-gabble.sh $(NULL) @ENABLE_INSTALLED_TESTS_TRUE@gabbledebugdir = @gabbletestsdir@/twisted telepathy_gabble_debug_SOURCES = \ main-debug.c \ test-resolver.c \ test-resolver.h telepathy_gabble_debug_LDADD = \ $(top_builddir)/src/libgabble-convenience.la \ $(ALL_LIBS) telepathy_gabble_debug_LDFLAGS = -export-dynamic AM_CFLAGS = $(ERROR_CFLAGS) @DBUS_CFLAGS@ @GLIB_CFLAGS@ @WOCKY_CFLAGS@ \ @TP_GLIB_CFLAGS@ \ -I $(top_srcdir)/src -I $(top_builddir)/src \ -I $(top_srcdir)/lib -I $(top_builddir)/lib \ -I $(top_srcdir) -I $(top_builddir) ALL_LIBS = @DBUS_LIBS@ @GLIB_LIBS@ @WOCKY_LIBS@ @TP_GLIB_LIBS@ CLEANFILES = gabble-[1-9]*.log *.pyc */*.pyc config.py \ $(BUILT_SOURCES) tools/gabble-testing.log check_misc_sources = $(TESTS) # D-Bus service file for testing installed_service_in_files = tools/servicedir/gabble.service.in service_files = tools/servicedir/org.freedesktop.Telepathy.ConnectionManager.gabble.service uninstalled_service_in_files = tools/servicedir-uninstalled/gabble.service.in uninstalled_service_files = tools/servicedir-uninstalled/org.freedesktop.Telepathy.ConnectionManager.gabble.service # D-Bus config file for testing installed_conf_in_files = tools/servicedir/tmp-session-bus.conf.in installed_conf_files = $(installed_conf_in_files:.conf.in=.conf) uninstalled_conf_in_files = tools/servicedir-uninstalled/tmp-session-bus.conf.in uninstalled_conf_files = $(uninstalled_conf_in_files:.conf.in=.conf) EXTRA_DIST = \ $(installed_service_in_files) \ $(uninstalled_service_in_files) \ $(installed_conf_in_files) \ $(uninstalled_conf_in_files) \ tools/exec-with-log.sh.in \ tools/run-gabble.sh.in \ run-test.sh.in \ $(NULL) all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/tools/check-coding-style.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/twisted/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu tests/twisted/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/tools/check-coding-style.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-gabbledebugPROGRAMS: $(gabbledebug_PROGRAMS) @$(NORMAL_INSTALL) @list='$(gabbledebug_PROGRAMS)'; test -n "$(gabbledebugdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(gabbledebugdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(gabbledebugdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(gabbledebugdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(gabbledebugdir)$$dir" || exit $$?; \ } \ ; done uninstall-gabbledebugPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(gabbledebug_PROGRAMS)'; test -n "$(gabbledebugdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(gabbledebugdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(gabbledebugdir)" && rm -f $$files clean-gabbledebugPROGRAMS: @list='$(gabbledebug_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list telepathy-gabble-debug$(EXEEXT): $(telepathy_gabble_debug_OBJECTS) $(telepathy_gabble_debug_DEPENDENCIES) $(EXTRA_telepathy_gabble_debug_DEPENDENCIES) @rm -f telepathy-gabble-debug$(EXEEXT) $(AM_V_CCLD)$(telepathy_gabble_debug_LINK) $(telepathy_gabble_debug_OBJECTS) $(telepathy_gabble_debug_LDADD) $(LIBS) install-nobase_dist_twistedtestsSCRIPTS: $(nobase_dist_twistedtests_SCRIPTS) @$(NORMAL_INSTALL) @list='$(nobase_dist_twistedtests_SCRIPTS)'; test -n "$(twistedtestsdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(twistedtestsdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(twistedtestsdir)" || exit 1; \ fi; \ $(am__nobase_strip_setup); \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e "s|$$srcdirstrip/||" -e 'h;s|[^/]*$$||; s|^$$|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ case $$type in \ d) echo " $(MKDIR_P) '$(DESTDIR)$(twistedtestsdir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(twistedtestsdir)/$$dir" || exit $$?;; \ f) \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(twistedtestsdir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(twistedtestsdir)$$dir" || exit $$?; \ } \ ;; esac \ ; done uninstall-nobase_dist_twistedtestsSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(nobase_dist_twistedtests_SCRIPTS)'; test -n "$(twistedtestsdir)" || exit 0; \ $(am__nobase_strip_setup); \ files=`$(am__nobase_strip) \ -e 'h;s,.*/,,;$(transform);x;s|[^/]*$$||;G;s,\n,,'`; \ dir='$(DESTDIR)$(twistedtestsdir)'; $(am__uninstall_files_from_dir) install-nobase_nodist_twistedtestsSCRIPTS: $(nobase_nodist_twistedtests_SCRIPTS) @$(NORMAL_INSTALL) @list='$(nobase_nodist_twistedtests_SCRIPTS)'; test -n "$(twistedtestsdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(twistedtestsdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(twistedtestsdir)" || exit 1; \ fi; \ $(am__nobase_strip_setup); \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e "s|$$srcdirstrip/||" -e 'h;s|[^/]*$$||; s|^$$|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ case $$type in \ d) echo " $(MKDIR_P) '$(DESTDIR)$(twistedtestsdir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(twistedtestsdir)/$$dir" || exit $$?;; \ f) \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(twistedtestsdir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(twistedtestsdir)$$dir" || exit $$?; \ } \ ;; esac \ ; done uninstall-nobase_nodist_twistedtestsSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(nobase_nodist_twistedtests_SCRIPTS)'; test -n "$(twistedtestsdir)" || exit 0; \ $(am__nobase_strip_setup); \ files=`$(am__nobase_strip) \ -e 'h;s,.*/,,;$(transform);x;s|[^/]*$$||;G;s,\n,,'`; \ dir='$(DESTDIR)$(twistedtestsdir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main-debug.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-resolver.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_dist_twistedtestsDATA: $(nobase_dist_twistedtests_DATA) @$(NORMAL_INSTALL) @list='$(nobase_dist_twistedtests_DATA)'; test -n "$(twistedtestsdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(twistedtestsdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(twistedtestsdir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(twistedtestsdir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(twistedtestsdir)/$$dir"; }; \ echo " $(INSTALL_DATA) $$xfiles '$(DESTDIR)$(twistedtestsdir)/$$dir'"; \ $(INSTALL_DATA) $$xfiles "$(DESTDIR)$(twistedtestsdir)/$$dir" || exit $$?; }; \ done uninstall-nobase_dist_twistedtestsDATA: @$(NORMAL_UNINSTALL) @list='$(nobase_dist_twistedtests_DATA)'; test -n "$(twistedtestsdir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(twistedtestsdir)'; $(am__uninstall_files_from_dir) install-nobase_nodist_twistedtestsDATA: $(nobase_nodist_twistedtests_DATA) @$(NORMAL_INSTALL) @list='$(nobase_nodist_twistedtests_DATA)'; test -n "$(twistedtestsdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(twistedtestsdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(twistedtestsdir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(twistedtestsdir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(twistedtestsdir)/$$dir"; }; \ echo " $(INSTALL_DATA) $$xfiles '$(DESTDIR)$(twistedtestsdir)/$$dir'"; \ $(INSTALL_DATA) $$xfiles "$(DESTDIR)$(twistedtestsdir)/$$dir" || exit $$?; }; \ done uninstall-nobase_nodist_twistedtestsDATA: @$(NORMAL_UNINSTALL) @list='$(nobase_nodist_twistedtests_DATA)'; test -n "$(twistedtestsdir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(twistedtestsdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(PROGRAMS) $(SCRIPTS) $(DATA) installdirs: for dir in "$(DESTDIR)$(gabbledebugdir)" "$(DESTDIR)$(twistedtestsdir)" "$(DESTDIR)$(twistedtestsdir)" "$(DESTDIR)$(twistedtestsdir)" "$(DESTDIR)$(twistedtestsdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-gabbledebugPROGRAMS clean-generic clean-libtool \ clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-gabbledebugPROGRAMS \ install-nobase_dist_twistedtestsDATA \ install-nobase_dist_twistedtestsSCRIPTS \ install-nobase_nodist_twistedtestsDATA \ install-nobase_nodist_twistedtestsSCRIPTS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-gabbledebugPROGRAMS \ uninstall-nobase_dist_twistedtestsDATA \ uninstall-nobase_dist_twistedtestsSCRIPTS \ uninstall-nobase_nodist_twistedtestsDATA \ uninstall-nobase_nodist_twistedtestsSCRIPTS .MAKE: all check check-am install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am check-local clean \ clean-gabbledebugPROGRAMS clean-generic clean-libtool \ clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am \ install-gabbledebugPROGRAMS install-html install-html-am \ install-info install-info-am install-man \ install-nobase_dist_twistedtestsDATA \ install-nobase_dist_twistedtestsSCRIPTS \ install-nobase_nodist_twistedtestsDATA \ install-nobase_nodist_twistedtestsSCRIPTS install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am \ uninstall-gabbledebugPROGRAMS \ uninstall-nobase_dist_twistedtestsDATA \ uninstall-nobase_dist_twistedtestsSCRIPTS \ uninstall-nobase_nodist_twistedtestsDATA \ uninstall-nobase_nodist_twistedtestsSCRIPTS @ENABLE_INSTALLED_TESTS_TRUE@ $(NULL) check-local: check-coding-style check-twisted check-twisted: $(BUILT_SOURCES) @WANT_TWISTED_TESTS_TRUE@ rm -f tools/core @WANT_TWISTED_TESTS_TRUE@ rm -f tools/vgcore.* @WANT_TWISTED_TESTS_TRUE@ rm -f tools/gabble-testing.log @WANT_TWISTED_TESTS_TRUE@ rm -f tools/strace.log @WANT_TWISTED_TESTS_TRUE@ if test -n "$$GABBLE_TEST_REFDBG"; then \ @WANT_TWISTED_TESTS_TRUE@ sleep=6; \ @WANT_TWISTED_TESTS_TRUE@ else \ @WANT_TWISTED_TESTS_TRUE@ sleep=$(CHECK_TWISTED_SLEEP); \ @WANT_TWISTED_TESTS_TRUE@ fi; \ @WANT_TWISTED_TESTS_TRUE@ failed=0; \ @WANT_TWISTED_TESTS_TRUE@ GABBLE_TEST_UNINSTALLED=1 \ @WANT_TWISTED_TESTS_TRUE@ GABBLE_TEST_SLEEP="--sleep=$$sleep" \ @WANT_TWISTED_TESTS_TRUE@ GABBLE_ABS_TOP_SRCDIR=@abs_top_srcdir@ \ @WANT_TWISTED_TESTS_TRUE@ GABBLE_ABS_TOP_BUILDDIR=@abs_top_builddir@ \ @WANT_TWISTED_TESTS_TRUE@ sh run-test.sh "$(TWISTED_TESTS)" || failed=1; \ @WANT_TWISTED_TESTS_TRUE@ if test -e tools/core; then\ @WANT_TWISTED_TESTS_TRUE@ echo -e "\033[0;31;1mCore dump exists: tools/core\033[0m";\ @WANT_TWISTED_TESTS_TRUE@ exit 1;\ @WANT_TWISTED_TESTS_TRUE@ fi; \ @WANT_TWISTED_TESTS_TRUE@ if test $$failed = 1; then\ @WANT_TWISTED_TESTS_TRUE@ exit 1;\ @WANT_TWISTED_TESTS_TRUE@ fi; @WANT_TWISTED_TESTS_FALSE@ @echo "Configured without Twisted test support. To enable them," @WANT_TWISTED_TESTS_FALSE@ @echo "ensure that these Python modules are available:" @WANT_TWISTED_TESTS_FALSE@ @echo " • twisted.words.xish.domish" @WANT_TWISTED_TESTS_FALSE@ @echo " • twisted.words.protocols.jabber" @WANT_TWISTED_TESTS_FALSE@ @echo " • twisted.internet.reactor" @WANT_TWISTED_TESTS_FALSE@ @echo "and then re-run configure." config.py: Makefile $(AM_V_GEN) { \ echo "PACKAGE_STRING = \"$(PACKAGE_STRING)\""; \ echo "CLIENT_TYPE = '$(CLIENT_TYPE)'"; \ echo "DEBUGGING = $(DEBUGGING_PYBOOL)"; \ echo "PLUGINS_ENABLED = $(PLUGINS_ENABLED_PYBOOL)"; \ echo "CHANNEL_TYPE_CALL_ENABLED = $(CHANNEL_TYPE_CALL_ENABLED_PYBOOL)"; \ echo "GOOGLE_RELAY_ENABLED = $(GOOGLE_RELAY_ENABLED_PYBOOL)"; \ echo "FILE_TRANSFER_ENABLED = $(FILE_TRANSFER_ENABLED_PYBOOL)"; \ echo "VOIP_ENABLED = $(VOIP_ENABLED_PYBOOL)"; \ echo "JINGLE_FILE_TRANSFER_ENABLED = $(JINGLE_FILE_TRANSFER_ENABLED_PYBOOL)"; \ } > $@ check-coding-style: @fail=0; \ if test -n "$(check_misc_sources)"; then \ tools_dir=$(top_srcdir)/tools \ sh $(top_srcdir)/tools/check-misc.sh \ $(addprefix $(srcdir)/,$(check_misc_sources)) || fail=1; \ fi; \ if test -n "$(check_c_sources)"; then \ tools_dir=$(top_srcdir)/tools \ sh $(top_srcdir)/tools/check-c-style.sh \ $(addprefix $(srcdir)/,$(check_c_sources)) || fail=1; \ fi;\ if test yes = "$(ENABLE_CODING_STYLE_CHECKS)"; then \ exit "$$fail";\ else \ exit 0;\ fi # the following used to be in tools/ gabble-twisted-tests.list: Makefile $(AM_V_GEN)echo $(TWISTED_TESTS) > $@ run-test.sh: run-test.sh.in Makefile $(AM_V_GEN)sed -e "s|[@]gabbletestsdir[@]|@gabbletestsdir@|g" \ -e "s|[@]PYTHON[@]|$(PYTHON)|g" \ -e "s|[@]TEST_PYTHON[@]|$(TEST_PYTHON)|g" \ $< > $@ @chmod +x $@ tools/run-gabble.sh: tools/run-gabble.sh.in Makefile @mkdir -p tools $(AM_V_GEN)sed \ -e "s|[@]gabbletestsdir[@]|@gabbletestsdir@|g" \ -e "s|[@]pluginexecdir[@]|@pluginexecdir@|g" \ -e "s|[@]libdir[@]|$(libdir)|g" \ $< > $@ @chmod +x $@ tools/exec-with-log.sh: tools/exec-with-log.sh.in $(MKDIR_P) tools $(AM_V_GEN)sed -e "s|[@]abs_top_builddir[@]|@abs_top_builddir@|g" \ -e "s|[@]abs_top_srcdir[@]|@abs_top_srcdir@|g" $< > $@ @chmod +x $@ # The wildcard % matches both config files! tools/%.conf: tools/%.conf.in Makefile $(MKDIR_P) tools/servicedir $(MKDIR_P) tools/servicedir-uninstalled $(AM_V_GEN)sed -e "s|[@]gabbletestsdir[@]|@gabbletestsdir@|g" \ -e "s|[@]abs_top_builddir[@]|@abs_top_builddir@|g" $< > $@ # We don't use the full filename for the .in because > 99 character filenames # in tarballs are non-portable (and automake 1.8 doesn't let us build # non-archaic tarballs) tools/servicedir/org.freedesktop.Telepathy.ConnectionManager.%.service: tools/servicedir/%.service.in Makefile $(MKDIR_P) tools/servicedir $(AM_V_GEN)sed -e "s|[@]gabbletestsdir[@]|@gabbletestsdir@|g" $< > $@ tools/servicedir-uninstalled/org.freedesktop.Telepathy.ConnectionManager.%.service: tools/servicedir-uninstalled/%.service.in $(MKDIR_P) tools/servicedir-uninstalled $(AM_V_GEN)sed -e "s|[@]abs_top_builddir[@]|@abs_top_builddir@|g" $< > $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/power-save.py�������������������������������������������������0000664�0001750�0001750�00000016762�12332441362�023501� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test entering and leaving power saving mode. """ import config import constants as cs from gabbletest import exec_test, GoogleXmlStream, make_result_iq, \ send_error_reply, disconnect_conn, make_presence, sync_stream, elem, \ acknowledge_iq from servicetest import call_async, Event, assertEquals, EventPattern, \ assertContains, assertDoesNotContain, sync_dbus import ns import dbus import dbus.service from twisted.internet import reactor from twisted.words.xish import domish def expect_command(q, name): event = q.expect('stream-iq', query_name='query', query_ns=ns.GOOGLE_QUEUE) # Regression test: when we split MCE out of Gabble and moved Gabble's code # to conn-power-saving, this erroneously became a 'get'. assertEquals('set', event.iq_type) command = event.query.firstChildElement() assertEquals(name, command.name) return event.stanza def test_error(q, bus, conn, stream): assertContains(cs.CONN_IFACE_POWER_SAVING, conn.Get(cs.CONN, "Interfaces", dbus_interface=cs.PROPERTIES_IFACE)) assertEquals (False, conn.Get(cs.CONN_IFACE_POWER_SAVING, "PowerSavingActive", dbus_interface=cs.PROPERTIES_IFACE)) call_async(q, conn.PowerSaving, 'SetPowerSaving', True) stanza = expect_command(q, 'enable') error = domish.Element((None, 'error')) error.addElement((ns.STANZA, 'service-unavailable')) send_error_reply(stream, stanza, error) q.expect('dbus-error', method='SetPowerSaving', name=cs.NOT_AVAILABLE) # Power saving state should remain false assertEquals (False, conn.Get(cs.CONN_IFACE_POWER_SAVING, "PowerSavingActive", dbus_interface=cs.PROPERTIES_IFACE)) def test_local_queueing(q, bus, conn, stream): assertContains(cs.CONN_IFACE_POWER_SAVING, conn.Get(cs.CONN, "Interfaces", dbus_interface=cs.PROPERTIES_IFACE)) assertEquals (False, conn.Get(cs.CONN_IFACE_POWER_SAVING, "PowerSavingActive", dbus_interface=cs.PROPERTIES_IFACE)) event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) presence_update = [EventPattern('dbus-signal', signal='PresencesChanged')] q.forbid_events(presence_update) call_async(q, conn.PowerSaving, 'SetPowerSaving', True) q.expect_many(EventPattern('dbus-return', method='SetPowerSaving'), EventPattern('dbus-signal', signal='PowerSavingChanged', args=[True])) assertEquals (True, conn.Get(cs.CONN_IFACE_POWER_SAVING, "PowerSavingActive", dbus_interface=cs.PROPERTIES_IFACE)) # These presence stanzas should be queued stream.send(make_presence('amy@foo.com', show='away', status='At the pub')) stream.send(make_presence('bob@foo.com', show='xa', status='Somewhere over the rainbow')) # Pep notifications too message = elem('message', from_='bob@foo.com')( elem((ns.PUBSUB_EVENT), 'event')( elem('items', node=ns.NICK)( elem('item')( elem(ns.NICK, 'nick')(u'Robert') ) ) ) ) stream.send(message.toXml()) sync_dbus(bus, q, conn) q.unforbid_events(presence_update) # Incoming important stanza will flush the queue m = domish.Element((None, 'message')) m['from'] = 'foo@bar.com/Pidgin' m['id'] = '123' m['type'] = 'chat' m.addElement('body', content='important message') stream.send(m) # Presence updates should come in the original order ... p1 = q.expect('dbus-signal', signal='PresencesChanged') p2 = q.expect('dbus-signal', signal='PresencesChanged') assertEquals('away', p1.args[0].values()[0][1]) assertEquals('xa', p2.args[0].values()[0][1]) # .. followed by the result of PEP notification .. event = q.expect('dbus-signal', signal='AliasesChanged') # .. and finally the message that flushed the stanza queue q.expect('dbus-signal', signal='NewChannel') sync_stream(q, stream) q.forbid_events(presence_update) stream.send(make_presence('carl@foo.com', show='away', status='Home')) # Carl's presence update is queued sync_dbus(bus, q, conn) q.unforbid_events(presence_update) # Disable powersaving, flushing the queue conn.PowerSaving.SetPowerSaving(False) q.expect('dbus-signal', signal='PresencesChanged') def test(q, bus, conn, stream): assertContains(cs.CONN_IFACE_POWER_SAVING, conn.Get(cs.CONN, "Interfaces", dbus_interface=cs.PROPERTIES_IFACE)) assertEquals (False, conn.Get(cs.CONN_IFACE_POWER_SAVING, "PowerSavingActive", dbus_interface=cs.PROPERTIES_IFACE)) call_async(q, conn.PowerSaving, 'SetPowerSaving', True) stanza = expect_command(q, 'enable') stream.send(make_result_iq(stream, stanza, False)) q.expect_many(EventPattern('dbus-return', method='SetPowerSaving'), EventPattern('dbus-signal', signal='PowerSavingChanged', args=[True])) assertEquals (True, conn.Get(cs.CONN_IFACE_POWER_SAVING, "PowerSavingActive", dbus_interface=cs.PROPERTIES_IFACE)) pattern = [EventPattern('stream-iq', query_name='query', query_ns=ns.GOOGLE_QUEUE), EventPattern('dbus-signal', signal='PowerSavingChanged', args=[True])] q.forbid_events(pattern) # Enabling power saving again should be a no-op. call_async(q, conn.PowerSaving, 'SetPowerSaving', True) q.expect('dbus-return', method='SetPowerSaving') q.unforbid_events(pattern) call_async(q, conn.PowerSaving, 'SetPowerSaving', False) stanza = expect_command(q, 'disable') stream.send(make_result_iq(stream, stanza, False)) event, _, _ = q.expect_many( EventPattern('stream-iq', query_name='query', query_ns=ns.GOOGLE_QUEUE), EventPattern('dbus-return', method='SetPowerSaving'), EventPattern('dbus-signal', signal='PowerSavingChanged', args=[False])) command = event.query.firstChildElement() assertEquals("flush", command.name) assertEquals (False, conn.Get(cs.CONN_IFACE_POWER_SAVING, "PowerSavingActive", dbus_interface=cs.PROPERTIES_IFACE)) def test_disconnect(q, bus, conn, stream): assertContains(cs.CONN_IFACE_POWER_SAVING, conn.Get(cs.CONN, "Interfaces", dbus_interface=cs.PROPERTIES_IFACE)) assertEquals (False, conn.Get(cs.CONN_IFACE_POWER_SAVING, "PowerSavingActive", dbus_interface=cs.PROPERTIES_IFACE)) call_async(q, conn.PowerSaving, 'SetPowerSaving', True) stanza = expect_command(q, 'enable') disconnect_conn(q, conn, stream) if __name__ == '__main__': exec_test(test, protocol=GoogleXmlStream) exec_test(test_local_queueing) exec_test(test_error, protocol=GoogleXmlStream) exec_test(test_disconnect, protocol=GoogleXmlStream) ��������������telepathy-gabble-0.18.3/tests/twisted/httptest.py���������������������������������������������������0000644�0001750�0001750�00000001526�12225363340�023256� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ from twisted.web import http from twisted.internet import reactor from servicetest import Event class Request(http.Request): def process(self): self.queue.append(Event('http-request', method=self.method, path=self.path, request=self)) class HTTPChannel(http.HTTPChannel): def requestFactory(self, *misc): request = Request(*misc) request.queue = self.queue return request class HTTPFactory(http.HTTPFactory): protocol = HTTPChannel def __init__(self, queue): http.HTTPFactory.__init__(self) self.queue = queue def buildProtocol(self, addr): protocol = http.HTTPFactory.buildProtocol(self, addr) protocol.queue = self.queue return protocol def listen_http(q, port=0): return reactor.listenTCP(port, HTTPFactory(q), interface='localhost') ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/mail-notification.py������������������������������������������0000664�0001750�0001750�00000030317�12332441362�025007� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������""" Test Connection.Interface.MailNotification """ from twisted.words.xish import domish from gabbletest import exec_test, make_result_iq, GoogleXmlStream from servicetest import EventPattern import constants as cs import ns import dbus def check_properties_empty(conn, expected_flags=0): """Check that all mail notification properties are empty and that mail notification flags match the expected flags""" flags = conn.Get( cs.CONN_IFACE_MAIL_NOTIFICATION, 'MailNotificationFlags', dbus_interface=cs.PROPERTIES_IFACE) assert flags == expected_flags mail_count = conn.Get( cs.CONN_IFACE_MAIL_NOTIFICATION, 'UnreadMailCount', dbus_interface=cs.PROPERTIES_IFACE) assert mail_count == 0 unread_mails = conn.Get( cs.CONN_IFACE_MAIL_NOTIFICATION, 'UnreadMails', dbus_interface=cs.PROPERTIES_IFACE) assert len(unread_mails) == 0 def test_google_featured(q, bus, conn, stream): """Test functionnality when google mail notification is supported""" inbox_url = 'http://mail.google.com/mail' # E-mail thread 1 data thread1_id = "1" # Dates are 32bit unsigned integers, let's use the biggest possible value thread1_date = (pow(2,32) - 1) * 1000L thread1_url = 'http://mail.google.com/mail/#inbox/%x' % long(thread1_id) thread1_senders = [('John Smith', 'john@smith.com'), ('Denis Tremblay', 'denis@tremblay.qc.ca')] thread1_subject = "subject1" thread1_snippet = "body1" # Email thread 2 data thread2_id = "2" thread2_date = 1234L thread2_url = 'http://mail.google.com/mail/#inbox/%x' % long(thread2_id) thread2_senders = [('Sam Gratte', 'sam@gratte.edu'),] thread2_subject = "subject2" thread2_snippet = "body2" # Email thread 3 data thread3_id = "3" thread3_date = 1235L thread3_url = 'http://mail.google.com/mail/#inbox/%x' % long(thread3_id) thread3_senders = [('Le Chat', 'le@chat.fr'),] thread3_subject = "subject3" thread3_snippet = "body3" # Supported mail notification flags Supports_Unread_Mail_Count = 1 Supports_Unread_Mails = 2 Supports_Request_Inbox_URL = 8 Supports_Request_Mail_URL = 16 Thread_Based = 32 expected_flags = Supports_Unread_Mail_Count\ | Supports_Unread_Mails\ | Supports_Request_Inbox_URL\ | Supports_Request_Mail_URL\ | Thread_Based # Nobody is subscribed yet, attributes should all be empty, and # mail notification flags are set properly. check_properties_empty(conn, expected_flags) # Check that Gabble queries mail data on initial interest. conn.AddClientInterest([cs.CONN_IFACE_MAIL_NOTIFICATION]) event = q.expect('stream-iq', query_ns=ns.GOOGLE_MAIL_NOTIFY) result = make_result_iq(stream, event.stanza, False) mailbox = result.addElement('mailbox') mailbox['xmlns'] = ns.GOOGLE_MAIL_NOTIFY mailbox['url'] = inbox_url # Set e-mail thread 1 mail = mailbox.addElement('mail-thread-info') mail['tid'] = thread1_id mail['date'] = str(thread1_date) senders = mail.addElement('senders') for t1_sender in thread1_senders: sender = senders.addElement('sender') sender['name'] = t1_sender[0] sender['address'] = t1_sender[1] sender['unread'] = '1' mail.addElement('subject', content=thread1_subject) mail.addElement('snippet', content=thread1_snippet) # Set e-mail thread 2 mail = mailbox.addElement('mail-thread-info') mail['tid'] = thread2_id mail['date'] = str(thread2_date) senders = mail.addElement('senders') for t2_sender in thread2_senders: sender = senders.addElement('sender') sender['name'] = t2_sender[0] sender['address'] = t2_sender[1] sender['unread'] = '1' sender = senders.addElement('sender') sender['name'] = 'Read Sender' sender['address'] = 'read@sender.net' mail.addElement('subject', content=thread2_subject) mail.addElement('snippet', content=thread2_snippet) stream.send(result) # Then we expect UnreadMailsChanged with all the mail information. event = q.expect('dbus-signal', signal="UnreadMailsChanged") # Check that inbox URL is correct stored_url = conn.MailNotification.RequestInboxURL() assert stored_url[0] == inbox_url assert stored_url[1] == 0 # HTTP GET assert len(stored_url[2]) == 0 # UnreadMailsChanged(u: count, aa{sv}: mails_added, ax: mails_removed) unread_count = event.args[0] mails_added = event.args[1] mails_removed = event.args[2] # Get stored data to check we have same thing stored_unread_count = conn.Get( cs.CONN_IFACE_MAIL_NOTIFICATION, 'UnreadMailCount', dbus_interface=cs.PROPERTIES_IFACE) stored_unread_mails = conn.Get( cs.CONN_IFACE_MAIL_NOTIFICATION, 'UnreadMails', dbus_interface=cs.PROPERTIES_IFACE) assert unread_count == 2 assert stored_unread_count == unread_count assert len(stored_unread_mails) == unread_count assert len(mails_added) == unread_count assert len(mails_removed) == 0 # Extract mails from signal, order is unknown mail1 = None mail2 = None for mail in mails_added: if mail['id'] == thread1_id: mail1 = mail elif mail['id'] == thread2_id: mail2 = mail else: assert False, "Gabble sent an unknown mail id=" + str(mail['id']) # Validate added e-mails with original data. assert mail1 != None # While date is in millisecond, the received timestamp is in seconds thus # we need to divided by 1000 assert mail1['received-timestamp'] == thread1_date / 1000 assert mail1['subject'] == thread1_subject assert mail1['truncated'] == True assert mail1['content'] == thread1_snippet assert mail1['senders'] == thread1_senders assert mail2 != None assert mail2['received-timestamp'] == thread2_date / 1000 assert mail2['subject'] == thread2_subject assert mail2['truncated'] == True assert mail2['content'] == thread2_snippet assert mail2['senders'] == thread2_senders # Extract mails from stored mails, order is unkown stored_mail1 = None stored_mail2 = None for mail in stored_unread_mails: if mail['id'] == thread1_id: stored_mail1 = mail elif mail['id'] == thread2_id: stored_mail2 = mail else: assert False, "Gabble stored an unkown mail id=" + str(mail['id']) # Validate stored e-mails with original data assert stored_mail1 != None assert stored_mail1['received-timestamp'] == thread1_date / 1000 assert stored_mail1['subject'] == thread1_subject assert stored_mail1['truncated'] == True assert stored_mail1['content'] == thread1_snippet assert stored_mail1['senders'] == thread1_senders assert stored_mail2 != None assert stored_mail2['received-timestamp'] == thread2_date / 1000 assert stored_mail2['subject'] == thread2_subject assert stored_mail2['truncated'] == True assert stored_mail2['content'] == thread2_snippet assert stored_mail2['senders'] == thread2_senders # Check the we can get an URL for a specific mail mail_url1 = conn.MailNotification.RequestMailURL( stored_mail1['id'], stored_mail1['url-data']); mail_url2 = conn.MailNotification.RequestMailURL( stored_mail2['id'], stored_mail2['url-data']); assert mail_url1[0] == thread1_url assert mail_url1[1] == 0 assert len(mail_url1[2]) == 0 assert mail_url2[0] == thread2_url assert mail_url2[1] == 0 assert len(mail_url2[2]) == 0 # Now we want to validate the update mechanism. Thus we wil send an # new-mail event, wait for gabble to query the latest mail and reply # a different list. m = domish.Element((None, 'iq')) m['type'] = 'set' m['from'] = 'test@localhost' m['id'] = '3' m.addElement((ns.GOOGLE_MAIL_NOTIFY, 'new-mail')) stream.send(m) # Wait for mail information request event = q.expect('stream-iq', query_ns=ns.GOOGLE_MAIL_NOTIFY) result = make_result_iq(stream, event.stanza, False) mailbox = result.addElement('mailbox') mailbox['xmlns'] = ns.GOOGLE_MAIL_NOTIFY # We alter the URL to see if it gets detected mailbox['url'] = inbox_url + 'diff' # Set e-mail thread 1 and change snippet to see if it's detected mail = mailbox.addElement('mail-thread-info') mail['tid'] = str(thread1_id) mail['date'] = str(thread1_date) senders = mail.addElement('senders') for t1_sender in thread1_senders: sender = senders.addElement('sender') sender['name'] = t1_sender[0] sender['address'] = t1_sender[1] sender['unread'] = '1' mail.addElement('subject', content=thread1_subject) mail.addElement('snippet', content=thread1_snippet + 'diff') # We don't set the thread 2, as if it was removed # Set e-mail thread 3 mail = mailbox.addElement('mail-thread-info') mail['tid'] = str(thread3_id) mail['date'] = str(thread3_date) senders = mail.addElement('senders') for t3_sender in thread3_senders: sender = senders.addElement('sender') sender['name'] = t3_sender[0] sender['address'] = t3_sender[1] sender['unread'] = '1' mail.addElement('subject', content=thread3_subject) mail.addElement('snippet', content=thread3_snippet) stream.send(result) event = q.expect('dbus-signal', signal='UnreadMailsChanged') unread_count = event.args[0] mails_added = event.args[1] mails_removed = event.args[2] # Validate that changed is set for correct items assert unread_count == 2 assert len(mails_added) == 2 assert mails_added[0]['id'] in (thread1_id, thread3_id) assert mails_added[1]['id'] in (thread1_id, thread3_id) assert mails_added[0]['id'] != mails_added[1]['id'] assert len(mails_removed) == 1 assert mails_removed[0] == thread2_id # Check attribue MailAddres mail_address = conn.Get( cs.CONN_IFACE_MAIL_NOTIFICATION, 'MailAddress', dbus_interface=cs.PROPERTIES_IFACE) assert mail_address == "test@localhost" # Unsubscribe and check that all data has been dropped conn.RemoveClientInterest([cs.CONN_IFACE_MAIL_NOTIFICATION]) check_properties_empty(conn, expected_flags) def test_no_google_featured(q, bus, conn, stream): """Check that Gabble reacts correctly when called on MailNotification while the feature is not supported.""" # Google mail notification is not supported, gabble should not emit any # signals. forbidden = [EventPattern('dbus-signal', signal='MailsReceived'), EventPattern('dbus-signal', signal='UnreadMailsChanged'), EventPattern('stream-iq', query_ns=ns.GOOGLE_MAIL_NOTIFY)] q.forbid_events(forbidden) # Make sure gabble does not query mail data on an unexpected new-mail # notification. m = domish.Element((None, 'iq')) m['type'] = 'set' m['from'] = 'test@localhost' m['id'] = '2' m.addElement((ns.GOOGLE_MAIL_NOTIFY, 'new-mail')) stream.send(m) # AddClientInterest and RemoveClientInterest always trivially "succeed" conn.AddClientInterest([cs.CONN_IFACE_MAIL_NOTIFICATION]) conn.RemoveClientInterest([cs.CONN_IFACE_MAIL_NOTIFICATION]) try: conn.MailNotification.RequestInboxURL() except dbus.DBusException, e: assert e.get_dbus_name() == cs.NOT_IMPLEMENTED try: conn.MailNotification.RequestMailURL("1", "http://test.com/mail") except dbus.DBusException, e: assert e.get_dbus_name() == cs.NOT_IMPLEMENTED # Make sure all properties return with empty or 0 data including # MailNotificationFlags check_properties_empty(conn) q.unforbid_events(forbidden) def test(q, bus, conn, stream): interfaces = conn.GetInterfaces() if stream.__class__ is GoogleXmlStream: assert cs.CONN_IFACE_MAIL_NOTIFICATION in interfaces test_google_featured(q, bus, conn, stream) else: assert cs.CONN_IFACE_MAIL_NOTIFICATION not in interfaces test_no_google_featured(q, bus, conn, stream) if __name__ == '__main__': exec_test(test, protocol=GoogleXmlStream) exec_test(test) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/twisted/test-resolver.h�����������������������������������������������0000664�0001750�0001750�00000004132�12223562023�024007� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * test-resolver.c - Source for TestResolver * Copyright © 2009 Collabora Ltd. * @author Vivek Dasmohapatra <vivek@collabora.co.uk> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_RESOLVER_H__ #define __TEST_RESOLVER_H__ #include <gio/gio.h> #include <glib.h> G_BEGIN_DECLS GType test_resolver_get_type (void); #define TEST_TYPE_RESOLVER (test_resolver_get_type ()) #define TEST_RESOLVER(o) \ (G_TYPE_CHECK_INSTANCE_CAST ((o), TEST_TYPE_RESOLVER, TestResolver)) #define TEST_RESOLVER_CLASS(k) \ (G_TYPE_CHECK_CLASS_CAST((k), TEST_TYPE_RESOLVER, TestResolverClass)) #define TEST_IS_RESOLVER(o) \ (G_TYPE_CHECK_INSTANCE_TYPE ((o), TEST_TYPE_RESOLVER)) #define TEST_IS_RESOLVER_CLASS(k) \ (G_TYPE_CHECK_CLASS_TYPE ((k), TEST_TYPE_RESOLVER)) #define TEST_RESOLVER_GET_CLASS(o) \ (G_TYPE_INSTANCE_GET_CLASS ((o), TEST_TYPE_RESOLVER, TestResolverClass)) typedef struct { GResolver parent_instance; GList *fake_A; GList *fake_SRV; } TestResolver; typedef struct { GResolverClass parent_class; } TestResolverClass; void test_resolver_reset (TestResolver *tr); gboolean test_resolver_add_A (TestResolver *tr, const char *hostname, const char *addr); gboolean test_resolver_add_SRV (TestResolver *tr, const char *service, const char *protocol, const char *domain, const char *addr, guint16 port); G_END_DECLS #endif /* __TEST_RESOLVER_H__ */ ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/test-presence.c�������������������������������������������������������0000664�0001750�0001750�00000017525�12332440117�022274� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ #include "config.h" #include <string.h> #ifdef HAVE_UNISTD_H # include <unistd.h> #endif #include <glib.h> #include "src/debug.h" #include "src/presence.h" #include "src/namespaces.h" static void big_test_of_doom (void) { const gchar *resource; GabblePresence *presence; GabbleCapabilitySet *cap_set; time_t now = time (NULL); GPtrArray *data_forms = g_ptr_array_new (); /* When we create a new presence, we know nothing about the contact in * question's presence. */ presence = gabble_presence_new (); g_assert (GABBLE_PRESENCE_UNKNOWN == presence->status); g_assert (NULL == presence->status_message); /* offline presence from no resource: we now know something about this * contact's presence. */ g_assert (TRUE == gabble_presence_update (presence, NULL, GABBLE_PRESENCE_OFFLINE, NULL, 0, NULL, now)); g_assert (GABBLE_PRESENCE_OFFLINE == presence->status); g_assert (NULL == presence->status_message); /* offline presence from unknown resource: no change */ g_assert (FALSE == gabble_presence_update (presence, "foo", GABBLE_PRESENCE_OFFLINE, NULL, 0, NULL, now)); /* available presence from unknown resource: change */ g_assert (TRUE == gabble_presence_update (presence, "foo", GABBLE_PRESENCE_AVAILABLE, NULL, 0, NULL, now)); /* accumulated presence has changed; status message unchanged */ g_assert (GABBLE_PRESENCE_AVAILABLE == presence->status); g_assert (NULL == presence->status_message); /* available presence again; no change */ g_assert (FALSE == gabble_presence_update (presence, "foo", GABBLE_PRESENCE_AVAILABLE, NULL, 0, NULL, now)); /* available presence again, but with status message: change */ g_assert (TRUE == gabble_presence_update (presence, "foo", GABBLE_PRESENCE_AVAILABLE, "status message", 0, NULL, now)); /* accumulated presence unchanged; status message changed */ g_assert (GABBLE_PRESENCE_AVAILABLE == presence->status); g_assert (0 == strcmp ("status message", presence->status_message)); /* same presence again; no change */ g_assert (FALSE == gabble_presence_update (presence, "foo", GABBLE_PRESENCE_AVAILABLE, "status message", 0, NULL, now)); /* time passes */ now++; /* presence from different resource, but equal present-ness and equal * status message; unchanged */ g_assert (FALSE == gabble_presence_update (presence, "bar", GABBLE_PRESENCE_AVAILABLE, "status message", 0, NULL, now)); g_assert (GABBLE_PRESENCE_AVAILABLE == presence->status); g_assert (0 == strcmp ("status message", presence->status_message)); /* but if we were to make a voip call, we would prefer the newer one */ g_assert (0 == strcmp ("bar", gabble_presence_pick_resource_by_caps (presence, 0, NULL, NULL))); /* mountain ranges form */ now++; /* presence from different resource, but equal present-ness and different * status message; changed */ g_assert (TRUE == gabble_presence_update (presence, "baz", GABBLE_PRESENCE_AVAILABLE, "dingbats", 0, NULL, now)); g_assert (GABBLE_PRESENCE_AVAILABLE == presence->status); g_assert (0 == strcmp ("dingbats", presence->status_message)); /* babies are born */ now++; /* presence with higher priority; presence and message changed */ g_assert (TRUE == gabble_presence_update (presence, "bar", GABBLE_PRESENCE_AVAILABLE, "dingoes", 1, NULL, now)); g_assert (GABBLE_PRESENCE_AVAILABLE == presence->status); g_assert (0 == strcmp ("dingoes", presence->status_message)); /* third-world dictators are deposed */ now++; /* now foo is newer, so the next voip call would prefer that */ g_assert (FALSE == gabble_presence_update (presence, "foo", GABBLE_PRESENCE_AVAILABLE, "status message", 0, NULL, now)); g_assert (0 == strcmp ("foo", gabble_presence_pick_resource_by_caps (presence, 0, NULL, NULL))); /* portal 2 is released */ now++; /* presence from first resource with greated present-ness: change */ g_assert (TRUE == gabble_presence_update (presence, "foo", GABBLE_PRESENCE_CHAT, "status message", 0, NULL, now)); /* seasons change */ now++; /* make bar be the latest presence: no change, since foo is more present */ g_assert (FALSE == gabble_presence_update (presence, "bar", GABBLE_PRESENCE_AVAILABLE, "dingoes", 1, NULL, now)); /* we still prefer foo for the voip calls, because it's more present */ g_assert (0 == strcmp ("foo", gabble_presence_pick_resource_by_caps (presence, 0, NULL, NULL))); g_assert (GABBLE_PRESENCE_CHAT == presence->status); g_assert (0 == strcmp ("status message", presence->status_message)); /* no resource has the Google voice cap */ resource = gabble_presence_pick_resource_by_caps (presence, 0, gabble_capability_set_predicate_has, NS_GOOGLE_FEAT_VOICE); g_assert (NULL == resource); /* give voice cap to second resource, but make priority negative */ g_assert (FALSE == gabble_presence_update (presence, "bar", GABBLE_PRESENCE_AVAILABLE, "dingoes", -1, NULL, now)); cap_set = gabble_capability_set_new (); gabble_capability_set_add (cap_set, NS_GOOGLE_FEAT_VOICE); gabble_presence_set_capabilities (presence, "bar", cap_set, data_forms, 0); gabble_capability_set_free (cap_set); /* no resource with non-negative priority has the Google voice cap */ resource = gabble_presence_pick_resource_by_caps (presence, 0, gabble_capability_set_predicate_has, NS_GOOGLE_FEAT_VOICE); g_assert (NULL == resource); /* give voice cap to first resource */ cap_set = gabble_capability_set_new (); gabble_capability_set_add (cap_set, NS_GOOGLE_FEAT_VOICE); gabble_presence_set_capabilities (presence, "foo", cap_set, data_forms, 0); gabble_capability_set_free (cap_set); /* resource has voice cap */ resource = gabble_presence_pick_resource_by_caps (presence, 0, gabble_capability_set_predicate_has, NS_GOOGLE_FEAT_VOICE); g_assert (0 == strcmp ("foo", resource)); /* presence turns up from null resource; it trumps other presence regardless * of whether status is more present or not */ g_assert (TRUE == gabble_presence_update (presence, NULL, GABBLE_PRESENCE_OFFLINE, "gone", 0, NULL, now)); g_assert (GABBLE_PRESENCE_OFFLINE == presence->status); g_assert (0 == strcmp ("gone", presence->status_message)); /* caps are gone too */ resource = gabble_presence_pick_resource_by_caps (presence, 0, gabble_capability_set_predicate_has, NS_GOOGLE_FEAT_VOICE); g_assert (NULL == resource); g_ptr_array_unref (data_forms); g_object_unref (presence); } /* * prefer_higher_priority_resources: * * This is a regression test for a bug which didn't actually happen, but would * have happened (and would not have been caught by the other tests in this * file) had a series of apparently-tautological if(){}s been turned into * if(){}else if(){} as suggested in a review comment * <https://bugs.freedesktop.org/show_bug.cgi?id=32139#c3>. */ static void prefer_higher_priority_resources (void) { GabblePresence *presence = gabble_presence_new (); time_t now = time (NULL); /* 'foo' and 'bar' are equally available, at the same time, but bar has a * lower priority. */ gabble_presence_update (presence, "foo", GABBLE_PRESENCE_AVAILABLE, "foo", 10, NULL, now); gabble_presence_update (presence, "bar", GABBLE_PRESENCE_AVAILABLE, "bar", 5, NULL, now); /* We should be sure to prefer "foo"'s status message to "bar"'s. */ g_assert_cmpstr (presence->status_message, ==, "foo"); g_object_unref (presence); } int main (int argc, char **argv) { int ret; g_type_init (); gabble_capabilities_init (NULL); gabble_debug_set_flags_from_env (); g_test_init (&argc, &argv, NULL); g_test_add_func ("/presence/big-test-of-doom", big_test_of_doom); g_test_add_func ("/presence/prefer-higher-priority-resources", prefer_higher_priority_resources); ret = g_test_run (); gabble_capabilities_finalize (NULL); gabble_debug_free (); return ret; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/test-parse-message.c��������������������������������������������������0000664�0001750�0001750�00000022411�12332440117�023212� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ #include "config.h" #include <string.h> #include <glib-object.h> #include "src/util.h" #include "src/message-util.h" /* Test the most basic <message> possible. */ static void test1 (void) { WockyStanza *msg; gboolean ret; const gchar *from; time_t stamp; TpChannelTextMessageType type; TpChannelTextSendError send_error; TpDeliveryStatus delivery_status; const gchar *id; const gchar *body; gint state; msg = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, "foo@bar.com", NULL, '@', "id", "a867c060-bd3f-4ecc-a38f-3e306af48e4c", NULL); ret = gabble_message_util_parse_incoming_message ( msg, &from, &stamp, &type, &id, &body, &state, &send_error, &delivery_status); g_assert (ret); g_assert_cmpstr (id, ==, "a867c060-bd3f-4ecc-a38f-3e306af48e4c"); g_assert_cmpstr (from, ==, "foo@bar.com"); g_assert_cmpuint (stamp, ==, 0); g_assert_cmpuint (type, ==, TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE); g_assert_cmpstr (body, ==, NULL); g_assert_cmpuint (state, ==, -1); g_assert_cmpuint (send_error, ==, GABBLE_TEXT_CHANNEL_SEND_NO_ERROR); g_object_unref (msg); } /* A <message> with a simple body. Parsed as a NOTICE because it doesn't have * a 'type' attribute. */ static void test2 (void) { WockyStanza *msg; gboolean ret; const gchar *from; time_t stamp; TpChannelTextMessageType type; TpChannelTextSendError send_error; TpDeliveryStatus delivery_status; const gchar *id; const gchar *body; gint state; msg = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, "foo@bar.com", NULL, '@', "id", "a867c060-bd3f-4ecc-a38f-3e306af48e4c", '(', "body", '$', "hello", ')', NULL); ret = gabble_message_util_parse_incoming_message ( msg, &from, &stamp, &type, &id, &body, &state, &send_error, &delivery_status); g_assert (ret); g_assert_cmpstr (id, ==, "a867c060-bd3f-4ecc-a38f-3e306af48e4c"); g_assert_cmpstr (from, ==, "foo@bar.com"); g_assert_cmpuint (stamp, ==, 0); g_assert_cmpuint (type, ==, TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE); g_assert_cmpstr (body, ==, "hello"); g_assert_cmpuint (state, ==, -1); g_assert_cmpuint (send_error, ==, GABBLE_TEXT_CHANNEL_SEND_NO_ERROR); g_object_unref (msg); } /* Simple type="chat" message. */ static void test3 (void) { WockyStanza *msg; gboolean ret; const gchar *from; time_t stamp; TpChannelTextMessageType type; TpChannelTextSendError send_error; TpDeliveryStatus delivery_status; const gchar *id; const gchar *body; gint state; msg = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "foo@bar.com", NULL, '@', "id", "a867c060-bd3f-4ecc-a38f-3e306af48e4c", '(', "body", '$', "hello", ')', NULL); ret = gabble_message_util_parse_incoming_message ( msg, &from, &stamp, &type, &id, &body, &state, &send_error, &delivery_status); g_assert (ret); g_assert_cmpstr (id, ==, "a867c060-bd3f-4ecc-a38f-3e306af48e4c"); g_assert_cmpstr (from, ==, "foo@bar.com"); g_assert_cmpuint (stamp, ==, 0); g_assert_cmpuint (type, ==, TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL); g_assert_cmpstr (body, ==, "hello"); g_assert_cmpuint (state, ==, -1); g_assert_cmpuint (send_error, ==, GABBLE_TEXT_CHANNEL_SEND_NO_ERROR); g_object_unref (msg); } /* A simple error. */ static void test_error (void) { WockyStanza *msg; gboolean ret; const gchar *from; time_t stamp; TpChannelTextMessageType type; TpChannelTextSendError send_error; TpDeliveryStatus delivery_status; const gchar *id; const gchar *body; gint state; msg = wocky_stanza_build ( WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_ERROR, "foo@bar.com", NULL, '@', "id", "a867c060-bd3f-4ecc-a38f-3e306af48e4c", '(', "error", '$', "oops", ')', NULL); ret = gabble_message_util_parse_incoming_message ( msg, &from, &stamp, &type, &id, &body, &state, &send_error, &delivery_status); g_assert (ret); g_assert_cmpstr (id, ==, "a867c060-bd3f-4ecc-a38f-3e306af48e4c"); g_assert_cmpstr (from, ==, "foo@bar.com"); g_assert_cmpuint (stamp, ==, 0); g_assert_cmpuint (type, ==, TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE); g_assert_cmpstr (body, ==, NULL); g_assert_cmpuint (state, ==, -1); g_assert_cmpuint (send_error, ==, TP_CHANNEL_TEXT_SEND_ERROR_UNKNOWN); g_assert_cmpuint (delivery_status, ==, TP_DELIVERY_STATUS_PERMANENTLY_FAILED); g_object_unref (msg); } /* A more complicated error, described in XEP-0086 as a "simple error response". */ static void test_another_error (void) { WockyStanza *msg; gboolean ret; const gchar *from; time_t stamp; TpChannelTextMessageType type; TpChannelTextSendError send_error; TpDeliveryStatus delivery_status; const gchar *id; const gchar *body; gint state; const gchar *message = "Wherefore art thou, Romeo?"; msg = wocky_stanza_build ( WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_ERROR, "romeo@montague.net/garden", "juliet@capulet.com/balcony", '@', "id", "a867c060-bd3f-4ecc-a38f-3e306af48e4c", '(', "body", '$', message, ')', '(', "error", '@', "code", "404", '@', "type", "cancel", '(', "item-not-found", ':', "urn:ietf:params:xml:ns:xmpp-stanzas", ')', ')', NULL); ret = gabble_message_util_parse_incoming_message ( msg, &from, &stamp, &type, &id, &body, &state, &send_error, &delivery_status); g_assert (ret); g_assert_cmpstr (id, ==, "a867c060-bd3f-4ecc-a38f-3e306af48e4c"); g_assert_cmpstr (from, ==, "romeo@montague.net/garden"); g_assert_cmpuint (stamp, ==, 0); g_assert_cmpuint (type, ==, TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE); g_assert_cmpstr (body, ==, message); g_assert_cmpuint (state, ==, -1); g_assert_cmpuint (send_error, ==, TP_CHANNEL_TEXT_SEND_ERROR_INVALID_CONTACT); g_assert_cmpuint (delivery_status, ==, TP_DELIVERY_STATUS_PERMANENTLY_FAILED); g_object_unref (msg); } /* One million, seven hundred seventy-one thousand, five hundred sixty-one * errors. */ static void test_yet_another_error (void) { WockyStanza *msg; gboolean ret; const gchar *from; time_t stamp; TpChannelTextMessageType type; TpChannelTextSendError send_error; TpDeliveryStatus delivery_status; const gchar *id; const gchar *body; gint state; const gchar *message = "Its trilling seems to have a tranquilizing effect on " "the human nervous system."; msg = wocky_stanza_build ( WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_ERROR, "other@starfleet.us/Enterprise", "spock@starfleet.us/Enterprise", '@', "id", "a867c060-bd3f-4ecc-a38f-3e306af48e4c", '(', "body", '$', message, ')', '(', "error", '@', "code", "404", '@', "type", "wait", '(', "recipient-unavailable", ':', "urn:ietf:params:xml:ns:xmpp-stanzas", ')', ')', NULL); ret = gabble_message_util_parse_incoming_message ( msg, &from, &stamp, &type, &id, &body, &state, &send_error, &delivery_status); g_assert (ret); g_assert_cmpstr (id, ==, "a867c060-bd3f-4ecc-a38f-3e306af48e4c"); g_assert_cmpstr (from, ==, "other@starfleet.us/Enterprise"); g_assert_cmpuint (stamp, ==, 0); g_assert_cmpuint (type, ==, TP_CHANNEL_TEXT_MESSAGE_TYPE_NOTICE); g_assert_cmpstr (body, ==, message); g_assert_cmpuint (state, ==, -1); g_assert_cmpuint (send_error, ==, TP_CHANNEL_TEXT_SEND_ERROR_OFFLINE); g_assert_cmpuint (delivery_status, ==, TP_DELIVERY_STATUS_TEMPORARILY_FAILED); g_object_unref (msg); } static void test_google_offline (void) { WockyStanza *msg; gboolean ret; const gchar *from; time_t stamp; TpChannelTextMessageType type; TpChannelTextSendError send_error; TpDeliveryStatus delivery_status; const gchar *id; const gchar *body; gint state; msg = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, "foo@bar.com", NULL, '@', "id", "a867c060-bd3f-4ecc-a38f-3e306af48e4c", '(', "body", '$', "hello", ')', '(', "x", ':', "jabber:x:delay", '@', "stamp", "20070927T13:24:14", ')', '(', "time", ':', "google:timestamp", '@', "ms", "1190899454656", ')', NULL); ret = gabble_message_util_parse_incoming_message ( msg, &from, &stamp, &type, &id, &body, &state, &send_error, &delivery_status); g_assert (ret); g_assert_cmpstr (id, ==, "a867c060-bd3f-4ecc-a38f-3e306af48e4c"); g_assert_cmpstr (from, ==, "foo@bar.com"); g_assert_cmpuint (stamp, ==, 1190899454); g_assert_cmpuint (type, ==, TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL); g_assert_cmpstr (body, ==, "hello"); g_assert_cmpuint (state, ==, -1); g_assert_cmpuint (send_error, ==, GABBLE_TEXT_CHANNEL_SEND_NO_ERROR); g_object_unref (msg); } int main ( int argc, char *argv[]) { g_type_init (); g_test_init (&argc, &argv, NULL); g_test_add_func ("/parse-message/1", test1); g_test_add_func ("/parse-message/2", test2); g_test_add_func ("/parse-message/3", test3); g_test_add_func ("/parse-message/error", test_error); g_test_add_func ("/parse-message/another-error", test_another_error); g_test_add_func ("/parse-message/yet-another-error", test_yet_another_error); g_test_add_func ("/parse-message/google-offline", test_google_offline); return g_test_run (); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/test-jid-decode.c�����������������������������������������������������0000664�0001750�0001750�00000002462�11720700311�022444� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ #include "config.h" #include <string.h> #include <wocky/wocky.h> #include "src/util.h" static void test_pass ( const gchar *jid, const gchar *expected_node, const gchar *expected_domain, const gchar *expected_resource) { gchar *node = NULL; gchar *domain = NULL; gchar *resource = NULL; g_assert (wocky_decode_jid (jid, &node, &domain, &resource)); g_assert (!tp_strdiff (expected_node, node)); g_assert (!tp_strdiff (expected_domain, domain)); g_assert (!tp_strdiff (expected_resource, resource)); g_free (node); g_free (domain); g_free (resource); } static void test_fail (const gchar *jid) { gchar *node = NULL; gchar *domain = NULL; gchar *resource = NULL; g_assert (!wocky_decode_jid (jid, &node, &domain, &resource)); g_assert (node == NULL); g_assert (domain == NULL); g_assert (resource == NULL); } int main (void) { test_fail (""); test_pass ("bar", NULL, "bar", NULL); test_pass ("foo@bar", "foo", "bar", NULL); test_pass ("foo@bar/baz", "foo", "bar", "baz"); test_fail ("@bar"); test_fail ("foo@bar/"); test_pass ("Foo@Bar/Baz", "foo", "bar", "Baz"); test_fail ("foo@@"); test_fail ("foo&bar@baz"); test_pass ("foo/bar@baz", NULL, "foo", "bar@baz"); test_pass ("foo@bar/foo@bar/foo@bar", "foo", "bar", "foo@bar/foo@bar"); return 0; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/test-handles.c��������������������������������������������������������0000664�0001750�0001750�00000004247�12332441362�022106� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ #include "config.h" #include <string.h> #include <glib.h> #include <glib-object.h> #include <telepathy-glib/telepathy-glib.h> #include <telepathy-glib/telepathy-glib-dbus.h> #include "src/connection.h" static void test_handles (guint handle_type) { TpHandleRepoIface *repos[NUM_TP_HANDLE_TYPES]; TpHandleRepoIface *tp_repo = NULL; GError *error = NULL; guint i; TpHandle handle = 0; const gchar *jid = "handle.test@foobar"; const gchar *return_jid; for (i = 0; i < NUM_TP_HANDLE_TYPES; i++) { repos[i] = NULL; } _gabble_connection_create_handle_repos (NULL, repos); tp_repo = repos[handle_type]; g_assert (tp_repo != NULL); /* Handle zero is never valid */ g_assert (tp_handle_is_valid (tp_repo, 0, &error) == FALSE); /* this should probably be InvalidHandle, but it was InvalidArgument in * older telepathy-glib */ g_assert (error->code == TP_ERROR_INVALID_ARGUMENT || error->code == TP_ERROR_INVALID_HANDLE); g_error_free (error); error = NULL; /* Properly return error when handle isn't in the repo */ g_assert (tp_handle_is_valid (tp_repo, 65536, &error) == FALSE); /* this should really be InvalidHandle, but it was InvalidArgument in * older telepathy-glib */ g_assert (error->code == TP_ERROR_INVALID_ARGUMENT || error->code == TP_ERROR_INVALID_HANDLE); g_error_free (error); error = NULL; /* Properly return when error out argument isn't provided */ g_assert (tp_handle_is_valid (tp_repo, 65536, NULL) == FALSE); /* It's not there to start with, unless we're using the static repo */ handle = tp_handle_lookup (tp_repo, jid, NULL, NULL); g_assert (handle == 0); /* ... but when we call tp_handle_ensure we get a new ref to it */ handle = tp_handle_ensure (tp_repo, jid, NULL, NULL); g_assert (handle != 0); /* Try to inspect it */ return_jid = tp_handle_inspect (tp_repo, handle); g_assert (!strcmp (return_jid, jid)); for (i = 0; i < NUM_TP_HANDLE_TYPES; i++) { if (repos[i]) g_object_unref ((GObject *) repos[i]); } } int main (int argc, char **argv) { g_type_init (); test_handles (TP_HANDLE_TYPE_CONTACT); test_handles (TP_HANDLE_TYPE_ROOM); return 0; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/Makefile.in�����������������������������������������������������������0000664�0001750�0001750�00000136215�12332443655�021424� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @ENABLE_INSTALLED_TESTS_TRUE@gabbletests_PROGRAMS = $(am__EXEEXT_1) @ENABLE_INSTALLED_TESTS_FALSE@noinst_PROGRAMS = $(am__EXEEXT_1) TESTS = $(am__EXEEXT_1) DIST_COMMON = $(top_srcdir)/tools/check-coding-style.mk \ $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp $(top_srcdir)/test-driver README subdir = tests ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_config_dir.m4 \ $(top_srcdir)/m4/compiler.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/tp-compiler-flag.m4 \ $(top_srcdir)/m4/tp-compiler-warnings.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__EXEEXT_1 = test-dtube-unique-names$(EXEEXT) \ test-gabble-idle-weak$(EXEEXT) test-handles$(EXEEXT) \ test-jid-decode$(EXEEXT) test-parse-message$(EXEEXT) \ test-presence$(EXEEXT) test-tp-error-from-wocky$(EXEEXT) am__installdirs = "$(DESTDIR)$(gabbletestsdir)" \ "$(DESTDIR)$(gabbletestsdir)" PROGRAMS = $(gabbletests_PROGRAMS) $(noinst_PROGRAMS) test_dtube_unique_names_SOURCES = test-dtube-unique-names.c test_dtube_unique_names_OBJECTS = test-dtube-unique-names.$(OBJEXT) test_dtube_unique_names_LDADD = $(LDADD) test_dtube_unique_names_DEPENDENCIES = \ $(top_builddir)/src/libgabble-convenience.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = test_gabble_idle_weak_SOURCES = test-gabble-idle-weak.c test_gabble_idle_weak_OBJECTS = test-gabble-idle-weak.$(OBJEXT) test_gabble_idle_weak_LDADD = $(LDADD) test_gabble_idle_weak_DEPENDENCIES = \ $(top_builddir)/src/libgabble-convenience.la test_handles_SOURCES = test-handles.c test_handles_OBJECTS = test-handles.$(OBJEXT) test_handles_LDADD = $(LDADD) test_handles_DEPENDENCIES = \ $(top_builddir)/src/libgabble-convenience.la test_jid_decode_SOURCES = test-jid-decode.c test_jid_decode_OBJECTS = test-jid-decode.$(OBJEXT) test_jid_decode_LDADD = $(LDADD) test_jid_decode_DEPENDENCIES = \ $(top_builddir)/src/libgabble-convenience.la test_parse_message_SOURCES = test-parse-message.c test_parse_message_OBJECTS = test-parse-message.$(OBJEXT) test_parse_message_LDADD = $(LDADD) test_parse_message_DEPENDENCIES = \ $(top_builddir)/src/libgabble-convenience.la test_presence_SOURCES = test-presence.c test_presence_OBJECTS = test-presence.$(OBJEXT) test_presence_LDADD = $(LDADD) test_presence_DEPENDENCIES = \ $(top_builddir)/src/libgabble-convenience.la am_test_tp_error_from_wocky_OBJECTS = tp-error-from-wocky.$(OBJEXT) test_tp_error_from_wocky_OBJECTS = \ $(am_test_tp_error_from_wocky_OBJECTS) test_tp_error_from_wocky_LDADD = $(LDADD) test_tp_error_from_wocky_DEPENDENCIES = \ $(top_builddir)/src/libgabble-convenience.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = test-dtube-unique-names.c test-gabble-idle-weak.c \ test-handles.c test-jid-decode.c test-parse-message.c \ test-presence.c $(test_tp_error_from_wocky_SOURCES) DIST_SOURCES = test-dtube-unique-names.c test-gabble-idle-weak.c \ test-handles.c test-jid-decode.c test-parse-message.c \ test-presence.c $(test_tp_error_from_wocky_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } DATA = $(gabbletests_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ check recheck distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLIENT_TYPE = @CLIENT_TYPE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_CODING_STYLE_CHECKS = @ENABLE_CODING_STYLE_CHECKS@ ENABLE_PLUGINS = @ENABLE_PLUGINS@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NICE_CFLAGS = @NICE_CFLAGS@ NICE_LIBS = @NICE_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOUP_CFLAGS = @SOUP_CFLAGS@ SOUP_LIBS = @SOUP_LIBS@ STRIP = @STRIP@ TEST_PYTHON = @TEST_PYTHON@ TP_GLIB_CFLAGS = @TP_GLIB_CFLAGS@ TP_GLIB_LIBS = @TP_GLIB_LIBS@ VERSION = @VERSION@ WOCKY_CFLAGS = @WOCKY_CFLAGS@ WOCKY_LIBS = @WOCKY_LIBS@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gabbletestsdir = @gabbletestsdir@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ pluginexecdir = @pluginexecdir@ pluginexeclibdir = @pluginexeclibdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = twisted suppressions tests_list = \ test-dtube-unique-names \ test-gabble-idle-weak \ test-handles \ test-jid-decode \ test-parse-message \ test-presence \ test-tp-error-from-wocky @ENABLE_INSTALLED_TESTS_TRUE@gabbletests_DATA = gabble-C-tests.list LDADD = $(top_builddir)/src/libgabble-convenience.la AM_CFLAGS = $(ERROR_CFLAGS) @DBUS_CFLAGS@ @GLIB_CFLAGS@ @WOCKY_CFLAGS@ \ @TP_GLIB_CFLAGS@ \ -I $(top_srcdir) -I $(top_builddir) \ -I $(top_srcdir)/lib -I $(top_builddir)/lib TESTS_ENVIRONMENT = \ abs_top_builddir=@abs_top_builddir@ \ G_DEBUG=fatal-warnings,fatal-criticals \ sh $(top_srcdir)/tests/twisted/tools/with-session-bus.sh \ --config-file=$(top_builddir)/tests/twisted/tools/servicedir-uninstalled/tmp-session-bus.conf -- check_c_sources = \ $(dbus_test_sources) \ test-dtube-unique-names.c \ test-presence.c \ test-jid-decode.c \ test-handles.c \ test-parse-message.c \ tp-error-from-wocky.c test_tp_error_from_wocky_SOURCES = tp-error-from-wocky.c all: all-recursive .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/tools/check-coding-style.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu tests/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/tools/check-coding-style.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-gabbletestsPROGRAMS: $(gabbletests_PROGRAMS) @$(NORMAL_INSTALL) @list='$(gabbletests_PROGRAMS)'; test -n "$(gabbletestsdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(gabbletestsdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(gabbletestsdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(gabbletestsdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(gabbletestsdir)$$dir" || exit $$?; \ } \ ; done uninstall-gabbletestsPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(gabbletests_PROGRAMS)'; test -n "$(gabbletestsdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(gabbletestsdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(gabbletestsdir)" && rm -f $$files clean-gabbletestsPROGRAMS: @list='$(gabbletests_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list test-dtube-unique-names$(EXEEXT): $(test_dtube_unique_names_OBJECTS) $(test_dtube_unique_names_DEPENDENCIES) $(EXTRA_test_dtube_unique_names_DEPENDENCIES) @rm -f test-dtube-unique-names$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_dtube_unique_names_OBJECTS) $(test_dtube_unique_names_LDADD) $(LIBS) test-gabble-idle-weak$(EXEEXT): $(test_gabble_idle_weak_OBJECTS) $(test_gabble_idle_weak_DEPENDENCIES) $(EXTRA_test_gabble_idle_weak_DEPENDENCIES) @rm -f test-gabble-idle-weak$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_gabble_idle_weak_OBJECTS) $(test_gabble_idle_weak_LDADD) $(LIBS) test-handles$(EXEEXT): $(test_handles_OBJECTS) $(test_handles_DEPENDENCIES) $(EXTRA_test_handles_DEPENDENCIES) @rm -f test-handles$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_handles_OBJECTS) $(test_handles_LDADD) $(LIBS) test-jid-decode$(EXEEXT): $(test_jid_decode_OBJECTS) $(test_jid_decode_DEPENDENCIES) $(EXTRA_test_jid_decode_DEPENDENCIES) @rm -f test-jid-decode$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_jid_decode_OBJECTS) $(test_jid_decode_LDADD) $(LIBS) test-parse-message$(EXEEXT): $(test_parse_message_OBJECTS) $(test_parse_message_DEPENDENCIES) $(EXTRA_test_parse_message_DEPENDENCIES) @rm -f test-parse-message$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_parse_message_OBJECTS) $(test_parse_message_LDADD) $(LIBS) test-presence$(EXEEXT): $(test_presence_OBJECTS) $(test_presence_DEPENDENCIES) $(EXTRA_test_presence_DEPENDENCIES) @rm -f test-presence$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_presence_OBJECTS) $(test_presence_LDADD) $(LIBS) test-tp-error-from-wocky$(EXEEXT): $(test_tp_error_from_wocky_OBJECTS) $(test_tp_error_from_wocky_DEPENDENCIES) $(EXTRA_test_tp_error_from_wocky_DEPENDENCIES) @rm -f test-tp-error-from-wocky$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_tp_error_from_wocky_OBJECTS) $(test_tp_error_from_wocky_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-dtube-unique-names.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-gabble-idle-weak.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-handles.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-jid-decode.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-parse-message.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-presence.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tp-error-from-wocky.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-gabbletestsDATA: $(gabbletests_DATA) @$(NORMAL_INSTALL) @list='$(gabbletests_DATA)'; test -n "$(gabbletestsdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(gabbletestsdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(gabbletestsdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(gabbletestsdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(gabbletestsdir)" || exit $$?; \ done uninstall-gabbletestsDATA: @$(NORMAL_UNINSTALL) @list='$(gabbletests_DATA)'; test -n "$(gabbletestsdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(gabbletestsdir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test-dtube-unique-names.log: test-dtube-unique-names$(EXEEXT) @p='test-dtube-unique-names$(EXEEXT)'; \ b='test-dtube-unique-names'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test-gabble-idle-weak.log: test-gabble-idle-weak$(EXEEXT) @p='test-gabble-idle-weak$(EXEEXT)'; \ b='test-gabble-idle-weak'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test-handles.log: test-handles$(EXEEXT) @p='test-handles$(EXEEXT)'; \ b='test-handles'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test-jid-decode.log: test-jid-decode$(EXEEXT) @p='test-jid-decode$(EXEEXT)'; \ b='test-jid-decode'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test-parse-message.log: test-parse-message$(EXEEXT) @p='test-parse-message$(EXEEXT)'; \ b='test-parse-message'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test-presence.log: test-presence$(EXEEXT) @p='test-presence$(EXEEXT)'; \ b='test-presence'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test-tp-error-from-wocky.log: test-tp-error-from-wocky$(EXEEXT) @p='test-tp-error-from-wocky$(EXEEXT)'; \ b='test-tp-error-from-wocky'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-TESTS check-local check: check-recursive all-am: Makefile $(PROGRAMS) $(DATA) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(gabbletestsdir)" "$(DESTDIR)$(gabbletestsdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-gabbletestsPROGRAMS clean-generic clean-libtool \ clean-noinstPROGRAMS mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-gabbletestsDATA install-gabbletestsPROGRAMS install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-gabbletestsDATA uninstall-gabbletestsPROGRAMS .MAKE: $(am__recursive_targets) check-am install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-TESTS check-am check-local clean \ clean-gabbletestsPROGRAMS clean-generic clean-libtool \ clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am \ install-gabbletestsDATA install-gabbletestsPROGRAMS \ install-html install-html-am install-info install-info-am \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ recheck tags tags-am uninstall uninstall-am \ uninstall-gabbletestsDATA uninstall-gabbletestsPROGRAMS gabble-C-tests.list: $(AM_V_GEN)echo $(tests_list) > $@ check-valgrind: $(TESTS) G_SLICE=always-malloc \ G_DEBUG=gc-friendly \ $(MAKE) \ TESTS_ENVIRONMENT="$(TESTS_ENVIRONMENT) \ libtool --mode=execute valgrind \ --leak-check=full \ --show-reachable=no \ --gen-suppressions=all \ --num-callers=20 \ --suppressions=@abs_top_srcdir@/tests/suppressions/gabble.supp \ --suppressions=@abs_top_srcdir@/tests/suppressions/tp-glib.supp \ --error-exitcode=1" \ check-TESTS check-coding-style: @fail=0; \ if test -n "$(check_misc_sources)"; then \ tools_dir=$(top_srcdir)/tools \ sh $(top_srcdir)/tools/check-misc.sh \ $(addprefix $(srcdir)/,$(check_misc_sources)) || fail=1; \ fi; \ if test -n "$(check_c_sources)"; then \ tools_dir=$(top_srcdir)/tools \ sh $(top_srcdir)/tools/check-c-style.sh \ $(addprefix $(srcdir)/,$(check_c_sources)) || fail=1; \ fi;\ if test yes = "$(ENABLE_CODING_STYLE_CHECKS)"; then \ exit "$$fail";\ else \ exit 0;\ fi check-local: check-coding-style # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/suppressions/���������������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�022124� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/suppressions/Makefile.am����������������������������������������������0000644�0001750�0001750�00000000047�11423525546�024157� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������EXTRA_DIST = gabble.supp tp-glib.supp �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/suppressions/gabble.supp����������������������������������������������0000644�0001750�0001750�00000007022�11423525546�024250� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Gabble leaks { we leak one default resource hash per process Memcheck:Leak ... fun:g_compute_checksum_for_data fun:sha1_hex fun:gabble_connection_constructed } { Test resolver leaks the records that were added Memcheck:Leak ... fun:test_resolver_add_A } # Glib type registration one-time leaks { g_type_init_with_debug_flags leaks one-time per registered type Memcheck:Leak ... fun:g_type_init_with_debug_flags } { g_type_register_fundamental, same story Memcheck:Leak ... fun:g_type_register_fundamental } { Various mixins set type qdata, types stay alive Memcheck:Leak ... fun:g_type_set_qdata } { Information about static interface lives forever Memcheck:Leak ... fun:g_type_add_interface_static } { Type prerequisites Memcheck:Leak ... fun:g_type_interface_add_prerequisite } { Various memory is never freed when first initializing a type class Memcheck:Leak ... fun:g_type_class_ref } # Glib mainloop one time leaks { Default main context stays alive an keeps an array around for pending fds Memcheck:Leak fun:malloc fun:g_malloc fun:g_main_context_iterate } { Default main context stays alive an keeps an array for pending dispatches Memcheck:Leak ... fun:g_ptr_array_add fun:g_main_context_check fun:g_main_context_iterate } { Global hashtable of signal handlers, memory allocated when resized Memcheck:Leak fun:calloc fun:g_malloc0 fun:g_hash_table_remove_internal fun:g_signal_handlers_destroy } { g_main_loop_run constructs a GStaticPrivate GMainDispatch Memcheck:Leak ... fun:get_dispatch } # glib one-time initialisaton of various bits { Random seed initialization Memcheck:Leak ... fun:g_rand_new fun:g_random_int_range } { GDataSet has a global hashtable that leaks per process Memcheck:Leak ... fun:g_data_initialize } { GIO has a static mapping to various connection factories Memcheck:Leak ... fun:g_socket_connection_factory_register_type } { GLib has a static copy of the userdir Memcheck:Leak ... fun:g_init_user_config_dir } { Caching of the tmp location Memcheck:Leak ... fun:g_get_any_init_do } { thread init causes g_get_language_name to cache stuff Memcheck:Leak ... fun:g_get_language_names } { Thread initialisation Memcheck:Leak ... fun:g_private_new_posix_impl } { Thread initialisation Memcheck:Leak ... fun:g_thread_init_glib } # telepathy-glib leaks the dbus connection, which causes dbus to have some # stuff around on exit... { the subtree that stores objects is reallocated in _register_g_object Memcheck:Leak ... fun:dbus_g_connection_register_g_object } { As we leak a connection, the corresponding dataslots bookkeeping is leaked Memcheck:Leak ... fun:dbus_realloc fun:_dbus_data_slot_allocator_alloc fun:tp_dbus_daemon_constructor } { As we leak a connection, the corresponding dataslots bookkeeping is leaked Memcheck:Leak ... fun:dbus_realloc fun:_dbus_data_slot_list_set fun:dbus_connection_set_data fun:tp_dbus_daemon_constructor } # dbus-glib type registration one-time leaks { dbus-glib specialized GTypes are permanent Memcheck:Leak ... fun:lookup_or_register_specialized } { dbus-glib object type information leaks Memcheck:Leak ... fun:dbus_g_object_type_install_info } # misc library one-time leaks { global gnutls data Memcheck:Leak ... fun:gnutls_global_init } { selinux, we just don't know Memcheck:Leak fun:malloc fun:getdelim obj:/lib/libselinux.so.1 } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/suppressions/tp-glib.supp���������������������������������������������0000644�0001750�0001750�00000010201�11423525546�024363� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Valgrind error suppression file # ============================= libc ================================== { ld.so initialization + selinux Memcheck:Leak ... fun:_dl_init obj:/lib/ld-*.so } { dlopen initialization, triggered by handle-leak-debug code Memcheck:Leak ... fun:__libc_dlopen_mode fun:init fun:backtrace fun:handle_leak_debug_bt fun:dynamic_ensure_handle fun:tp_handle_ensure } # ============================= GLib ================================== { g_set_prgname copies its argument Memcheck:Leak ... fun:g_set_prgname } { one g_get_charset per child^Wprocess Memcheck:Leak ... fun:g_get_charset } { GQuarks can't be freed Memcheck:Leak ... fun:g_quark_from_static_string } { GQuarks can't be freed Memcheck:Leak ... fun:g_quark_from_string } { interned strings can't be freed Memcheck:Leak ... fun:g_intern_string } { interned strings can't be freed Memcheck:Leak ... fun:g_intern_static_string } { shared global default g_main_context Memcheck:Leak ... fun:g_main_context_new fun:g_main_context_default } { GTest initialization Memcheck:Leak ... fun:g_test_init fun:main } { GTest admin Memcheck:Leak ... fun:g_test_add_vtable } { GTest pseudorandomness Memcheck:Leak ... fun:g_rand_new_with_seed_array fun:test_run_seed ... fun:g_test_run } { GSLice initialization Memcheck:Leak ... fun:g_malloc0 fun:g_slice_init_nomessage fun:g_slice_alloc } # ============================= GObject =============================== { g_type_init Memcheck:Leak ... fun:g_type_init } { g_type_register_static Memcheck:Leak ... fun:g_type_register_static } # ============================= dbus-glib ============================= { dbus-glib, https://bugs.freedesktop.org/show_bug.cgi?id=14125 Memcheck:Addr4 fun:g_hash_table_foreach obj:/usr/lib/libdbus-glib-1.so.2.1.0 fun:g_object_run_dispose } { registering marshallers is permanent Memcheck:Leak ... fun:dbus_g_object_register_marshaller_array fun:dbus_g_object_register_marshaller } { dbus-glib specialized GTypes are permanent Memcheck:Leak ... fun:dbus_g_type_specialized_init } { libdbus shared connection Memcheck:Leak ... fun:dbus_g_bus_get } { dbus-gobject registrations aren't freed unless we fall off the bus Memcheck:Leak ... fun:g_slist_append fun:dbus_g_connection_register_g_object } { DBusGProxy slots aren't freed unless we fall off the bus Memcheck:Leak ... fun:dbus_connection_allocate_data_slot ... fun:dbus_g_proxy_constructor } { error registrations are for life, not just for Christmas Memcheck:Leak ... fun:dbus_g_error_domain_register } # ============================= telepathy-glib ======================== { tp_dbus_daemon_constructor @daemons once per DBusConnection Memcheck:Leak ... fun:g_slice_alloc fun:tp_dbus_daemon_constructor } { tp_proxy_subclass_add_error_mapping refs the enum Memcheck:Leak ... fun:g_type_class_ref fun:tp_proxy_subclass_add_error_mapping } { tp_proxy_or_subclass_hook_on_interface_add never frees its list Memcheck:Leak ... fun:tp_proxy_or_subclass_hook_on_interface_add } { tp_dbus_daemon_constructor filter not freed til we fall off the bus Memcheck:Leak ... fun:dbus_connection_add_filter fun:tp_dbus_daemon_constructor } # ============================= unclassified ========================== { creating param specs in tp_proxy_class_intern_init Memcheck:Leak fun:memalign fun:posix_memalign fun:slab_allocator_alloc_chunk fun:g_slice_alloc fun:g_slice_alloc0 fun:g_type_create_instance fun:g_param_spec_internal fun:g_param_spec_string } { ld.so initialization on glibc 2.9 Memcheck:Cond fun:_dl_relocate_object fun:dl_main fun:_dl_sysdep_start fun:_dl_start obj:/lib/ld-2.9.so } { ld.so initialization on glibc 2.9 Memcheck:Cond fun:strlen fun:_dl_init_paths fun:dl_main fun:_dl_sysdep_start fun:_dl_start obj:/lib/ld-2.9.so } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/suppressions/Makefile.in����������������������������������������������0000664�0001750�0001750�00000031255�12332443655�024177� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tests/suppressions DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_config_dir.m4 \ $(top_srcdir)/m4/compiler.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/tp-compiler-flag.m4 \ $(top_srcdir)/m4/tp-compiler-warnings.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLIENT_TYPE = @CLIENT_TYPE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_CODING_STYLE_CHECKS = @ENABLE_CODING_STYLE_CHECKS@ ENABLE_PLUGINS = @ENABLE_PLUGINS@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NICE_CFLAGS = @NICE_CFLAGS@ NICE_LIBS = @NICE_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOUP_CFLAGS = @SOUP_CFLAGS@ SOUP_LIBS = @SOUP_LIBS@ STRIP = @STRIP@ TEST_PYTHON = @TEST_PYTHON@ TP_GLIB_CFLAGS = @TP_GLIB_CFLAGS@ TP_GLIB_LIBS = @TP_GLIB_LIBS@ VERSION = @VERSION@ WOCKY_CFLAGS = @WOCKY_CFLAGS@ WOCKY_LIBS = @WOCKY_LIBS@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gabbletestsdir = @gabbletestsdir@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ pluginexecdir = @pluginexecdir@ pluginexeclibdir = @pluginexeclibdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = gabble.supp tp-glib.supp all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/suppressions/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu tests/suppressions/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/tests/test-gabble-idle-weak.c�����������������������������������������������0000664�0001750�0001750�00000003162�12332440117�023534� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "config.h" #include <glib.h> #include "src/util.h" static gboolean idle_quit_called = FALSE; static GMainLoop *loop = NULL; static GObject *object; static gboolean idle_quit (gpointer data) { /* This callback should be called exactly once per test. */ g_assert (idle_quit_called == FALSE); idle_quit_called = TRUE; g_assert (data == object); g_main_loop_quit (loop); return FALSE; } /* Test 1: Source removed before object finalised. */ static void test_1 (void) { idle_quit_called = FALSE; object = g_object_new (G_TYPE_OBJECT, NULL); g_object_set_data (object, "foo", GUINT_TO_POINTER (42)); loop = g_main_loop_new (NULL, FALSE); gabble_idle_add_weak (idle_quit, object); g_main_loop_run (loop); g_object_unref (object); g_main_loop_unref (loop); g_assert (idle_quit_called == TRUE); } static gboolean idle_unref (gpointer data) { g_object_unref (G_OBJECT (data)); return FALSE; } /* Test 2: Object finalised before source removed. */ static void test_2 (void) { idle_quit_called = FALSE; object = g_object_new (G_TYPE_OBJECT, NULL); g_object_set_data (object, "foo", GUINT_TO_POINTER (42)); loop = g_main_loop_new (NULL, FALSE); g_idle_add (idle_unref, object); /* This idle quit shouldn't be called because the previous idle will unref * the object and trigger the weak notify. */ gabble_idle_add_weak (idle_quit, object); /* This one will be called, however. */ g_idle_add (idle_quit, object); g_main_loop_run (loop); g_main_loop_unref (loop); g_assert (idle_quit_called == TRUE); } int main (void) { g_type_init (); test_1(); test_2(); return 0; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/m4/�������������������������������������������������������������������������0000775�0001750�0001750�00000000000�12332445274�016524� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/m4/Makefile.am��������������������������������������������������������������0000644�0001750�0001750�00000000156�11423525545�020560� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������EXTRA_DIST = \ tp-compiler-flag.m4 \ tp-compiler-warnings.m4 \ compiler.m4 \ ax_config_dir.m4 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/m4/compiler.m4��������������������������������������������������������������0000644�0001750�0001750�00000005017�11203043217�020564� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# compiler.m4 - autoconf macros for compiler settings # # Copyright © 2005 Scott James Remnant <scott@netsplit.com>. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR # ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # COMPILER_WARNINGS # ---------------------- # Add configure option to enable additional compiler warnings and treat # them as errors. AC_DEFUN([COMPILER_WARNINGS], [AC_ARG_ENABLE(compiler-warnings, AS_HELP_STRING([--enable-compiler-warnings], [Enable additional compiler warnings]), [if test "x$enable_compiler_warnings" = "xyes"; then if test "x$GCC" = "xyes"; then CFLAGS="-Wall -Werror $CFLAGS" fi if test "x$GXX" = "xyes"; then CXXFLAGS="-Wall -Werror $CXXFLAGS" fi fi])dnl ])# COMPILER_WARNINGS # COMPILER_OPTIMISATIONS # --------------------------- # Add configure option to disable optimisations. AC_DEFUN([COMPILER_OPTIMISATIONS], [AC_ARG_ENABLE(compiler-optimisations, AS_HELP_STRING([--disable-compiler-optimisations], [Disable compiler optimisations]), [if test "x$enable_compiler_optimisations" = "xno"; then [CFLAGS=`echo "$CFLAGS" | sed -e "s/ -O[1-9]*\b/ -O0/g"`] fi])dnl ])# COMPILER_OPTIMISATIONS # COMPILER_COVERAGE # ---------------------- # Add configure option to enable coverage data. AC_DEFUN([COMPILER_COVERAGE], [AC_ARG_ENABLE(compiler-coverage, AS_HELP_STRING([--enable-compiler-coverage], [Enable generation of coverage data]), [if test "x$enable_compiler_coverage" = "xyes"; then if test "x$GCC" = "xyes"; then CFLAGS="$CFLAGS -fprofile-arcs -ftest-coverage" fi fi])dnl ])# COMPILER_COVERAGE �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/m4/libtool.m4���������������������������������������������������������������0000644�0001750�0001750�00001057564�12332443652�020450� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool 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. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ]) # serial 57 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_CC_BASENAME(CC) # ------------------- # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. m4_defun([_LT_CC_BASENAME], [for cc_temp in $1""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from `configure', and `config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # `config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain="$ac_aux_dir/ltmain.sh" ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the `libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to `config.status' so that its # declaration there will have the same value as in `configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # <var>='`$ECHO "$<var>" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags="_LT_TAGS"dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the `libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into `config.status', and then the shell code to quote escape them in # for loops in `config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # `#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test $lt_write_fail = 0 && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ \`$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to <bug-libtool@gnu.org>." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test $[#] != 0 do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try \`$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try \`$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test "$silent" = yes && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # _LT_COPYING _LT_LIBTOOL_TAGS # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) _LT_PROG_REPLACE_SHELLFNS mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS="$save_LDFLAGS" ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[[012]]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test "$lt_cv_ld_force_load" = "yes"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" m4_if([$1], [CXX], [ if test "$lt_cv_apple_cc_single_mod" != "yes"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script which will find a shell with a builtin # printf (which we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case "$ECHO" in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [ --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified).], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([${with_sysroot}]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and in which our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD="${LD-ld}_sol2" fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test x"[$]$2" = xyes; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" ]) if test x"[$]$2" = xyes; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n $lt_cv_sys_max_cmd_len ; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "$cross_compiling" = yes; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include <dlfcn.h> #endif #include <stdio.h> #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links="nottested" if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", [Define to the sub-directory in which libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existent directories. if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib<name>.so # instead of lib<name>.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Add ABI-specific directories to the system library path. sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([], [sys_lib_dlsearch_path_spec], [2], [Run-time system search path for libraries]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program which can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program which can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in *GNU* | *'with BFD'*) test "$with_gnu_ld" != no && break ;; *) test "$with_gnu_ld" != yes && break ;; esac fi done IFS="$lt_save_ifs" else lt_cv_path_LD="$LD" # Let the user override the test with a path. fi]) LD="$lt_cv_path_LD" if test -n "$LD"; then AC_MSG_RESULT($LD) else AC_MSG_RESULT(no) fi test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) _LT_PATH_LD_GNU AC_SUBST([LD]) _LT_TAGDECL([], [LD], [1], [The linker used to build libraries]) ])# LT_PATH_LD # Old names: AU_ALIAS([AM_PROG_LD], [LT_PATH_LD]) AU_ALIAS([AC_PROG_LD], [LT_PATH_LD]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_LD], []) dnl AC_DEFUN([AC_PROG_LD], []) # _LT_PATH_LD_GNU #- -------------- m4_defun([_LT_PATH_LD_GNU], [AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld, [# I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 </dev/null` in *GNU* | *'with BFD'*) lt_cv_prog_gnu_ld=yes ;; *) lt_cv_prog_gnu_ld=no ;; esac]) with_gnu_ld=$lt_cv_prog_gnu_ld ])# _LT_PATH_LD_GNU # _LT_CMD_RELOAD # -------------- # find reload flag for linker # -- PORTME Some linkers may need a different reload flag. m4_defun([_LT_CMD_RELOAD], [AC_CACHE_CHECK([for $LD option to reload object files], lt_cv_ld_reload_flag, [lt_cv_ld_reload_flag='-r']) reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test "$GCC" != yes; then reload_cmds=false fi ;; darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac _LT_TAGDECL([], [reload_flag], [1], [How to create reloadable object files])dnl _LT_TAGDECL([], [reload_cmds], [2])dnl ])# _LT_CMD_RELOAD # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_MAGIC_METHOD], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) AC_CACHE_CHECK([how to recognize dependent libraries], lt_cv_deplibs_check_method, [lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix[[4-9]]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[[45]]*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi]) if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64 which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global defined # symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach <jrb3@best.com> says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS="$save_LDFLAGS"]) if test "$lt_cv_irix_exported_symbol" = yes; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ;; esac fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting ${shlibpath_var} if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report which library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC="$lt_save_CC" ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GXX" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared # libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach <jrb3@best.com> says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ func_to_tool_file "$lt_outputfile"~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; gnu*) ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd2*) # C++ shared libraries are fairly broken _LT_TAGVAR(ld_shlibs, $1)=no ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(GCC, $1)="$GXX" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test "$_lt_caught_CXX_error" != yes AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case ${prev}${p} in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" || test $p = "-R"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test "$pre_test_object_deps_done" = no; then case ${prev} in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)="${prev}${p}" else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)="$p" else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)="$p" else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test "X$F77" = "Xno"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_F77" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$G77" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" CFLAGS="$lt_save_CFLAGS" fi # test "$_lt_disable_F77" != yes AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test "X$FC" = "Xno"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_FC" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test "$_lt_disable_FC" != yes AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [AC_MSG_CHECKING([whether the shell understands some XSI constructs]) # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes AC_MSG_RESULT([$xsi_shell]) _LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) AC_MSG_CHECKING([whether the shell understands "+="]) lt_shell_append=no ( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes AC_MSG_RESULT([$lt_shell_append]) _LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) # ------------------------------------------------------ # In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and # '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. m4_defun([_LT_PROG_FUNCTION_REPLACE], [dnl { sed -e '/^$1 ()$/,/^} # $1 /c\ $1 ()\ {\ m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) } # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: ]) # _LT_PROG_REPLACE_SHELLFNS # ------------------------- # Replace existing portable implementations of several shell functions with # equivalent extended shell implementations where those features are available.. m4_defun([_LT_PROG_REPLACE_SHELLFNS], [if test x"$xsi_shell" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"}]) _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl func_split_long_opt_name=${1%%=*} func_split_long_opt_arg=${1#*=}]) _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) fi if test x"$lt_shell_append" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl func_quote_for_eval "${2}" dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) fi ]) # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine which file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS ��������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/m4/lt~obsolete.m4�����������������������������������������������������������0000644�0001750�0001750�00000013756�12332443652�021350� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) ������������������telepathy-gabble-0.18.3/m4/ltversion.m4�������������������������������������������������������������0000644�0001750�0001750�00000001262�12332443652�021010� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 3337 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.2]) m4_define([LT_PACKAGE_REVISION], [1.3337]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.2' macro_revision='1.3337' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/m4/ltoptions.m4�������������������������������������������������������������0000644�0001750�0001750�00000030073�12332443652�021020� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, # Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 7 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option `$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl `shared' nor `disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the `shared' and # `disable-shared' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the `static' and # `disable-static' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the `fast-install' # and `disable-fast-install' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the `pic-only' and `no-pic' # LT_INIT options. # MODE is either `yes' or `no'. If omitted, it defaults to `both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for lt_pkg in $withval; do IFS="$lt_save_ifs" if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS="$lt_save_ifs" ;; esac], [pic_mode=default]) test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/m4/ltsugar.m4���������������������������������������������������������������0000644�0001750�0001750�00000010424�12332443652�020444� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59 which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/m4/tp-compiler-flag.m4������������������������������������������������������0000644�0001750�0001750�00000001704�11423525545�022130� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������dnl A version of AS_COMPILER_FLAG that supports both C and C++. dnl Based on: dnl as-compiler-flag.m4 0.1.0 dnl autostars m4 macro for detection of compiler flags dnl David Schleef <ds@schleef.org> dnl $Id: as-compiler-flag.m4,v 1.1 2005/06/18 18:02:46 burgerman Exp $ dnl TP_COMPILER_FLAG(CFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED]) dnl Tries to compile with the given CFLAGS and CXXFLAGS. dnl dnl Runs ACTION-IF-ACCEPTED if the compiler for the currently selected dnl AC_LANG can compile with the flags, and ACTION-IF-NOT-ACCEPTED otherwise. AC_DEFUN([TP_COMPILER_FLAG], [ AC_MSG_CHECKING([to see if compiler understands $1]) save_CFLAGS="$CFLAGS" save_CXXFLAGS="$CXXFLAGS" CFLAGS="$CFLAGS $1" CXXFLAGS="$CXXFLAGS $1" AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no]) CFLAGS="$save_CFLAGS" CXXFLAGS="$save_CXXFLAGS" if test "X$flag_ok" = Xyes ; then $2 true else $3 true fi AC_MSG_RESULT([$flag_ok]) ]) ������������������������������������������������������������telepathy-gabble-0.18.3/m4/Makefile.in��������������������������������������������������������������0000664�0001750�0001750�00000031306�12332443655�020575� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = m4 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_config_dir.m4 \ $(top_srcdir)/m4/compiler.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/tp-compiler-flag.m4 \ $(top_srcdir)/m4/tp-compiler-warnings.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLIENT_TYPE = @CLIENT_TYPE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_CODING_STYLE_CHECKS = @ENABLE_CODING_STYLE_CHECKS@ ENABLE_PLUGINS = @ENABLE_PLUGINS@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NICE_CFLAGS = @NICE_CFLAGS@ NICE_LIBS = @NICE_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOUP_CFLAGS = @SOUP_CFLAGS@ SOUP_LIBS = @SOUP_LIBS@ STRIP = @STRIP@ TEST_PYTHON = @TEST_PYTHON@ TP_GLIB_CFLAGS = @TP_GLIB_CFLAGS@ TP_GLIB_LIBS = @TP_GLIB_LIBS@ VERSION = @VERSION@ WOCKY_CFLAGS = @WOCKY_CFLAGS@ WOCKY_LIBS = @WOCKY_LIBS@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gabbletestsdir = @gabbletestsdir@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ pluginexecdir = @pluginexecdir@ pluginexeclibdir = @pluginexeclibdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ tp-compiler-flag.m4 \ tp-compiler-warnings.m4 \ compiler.m4 \ ax_config_dir.m4 all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu m4/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu m4/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/m4/tp-compiler-warnings.m4��������������������������������������������������0000644�0001750�0001750�00000002401�11423525545�023042� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������dnl TP_COMPILER_WARNINGS(VARIABLE, WERROR_BY_DEFAULT, DESIRABLE, UNDESIRABLE) dnl $1 (VARIABLE): the variable to put flags into dnl $2 (WERROR_BY_DEFAULT): a command returning true if -Werror should be the dnl default dnl $3 (DESIRABLE): warning flags we want (e.g. all extra shadow) dnl $4 (UNDESIRABLE): warning flags we don't want (e.g. dnl missing-field-initializers unused-parameter) AC_DEFUN([TP_COMPILER_WARNINGS], [ AC_REQUIRE([AC_ARG_ENABLE])dnl AC_REQUIRE([AC_HELP_STRING])dnl AC_REQUIRE([TP_COMPILER_FLAG])dnl tp_warnings="" for tp_flag in $3; do TP_COMPILER_FLAG([-W$tp_flag], [tp_warnings="$tp_warnings -W$tp_flag"]) done tp_error_flags="-Werror" TP_COMPILER_FLAG([-Werror], [tp_werror=yes], [tp_werror=no]) for tp_flag in $4; do TP_COMPILER_FLAG([-Wno-$tp_flag], [tp_warnings="$tp_warnings -Wno-$tp_flag"]) TP_COMPILER_FLAG([-Wno-error=$tp_flag], [tp_error_flags="$tp_error_flags -Wno-error=$tp_flag"], [tp_werror=no]) done AC_ARG_ENABLE([Werror], AC_HELP_STRING([--disable-Werror], [compile without -Werror (normally enabled in development builds)]), tp_werror=$enableval, :) if test "x$tp_werror" = xyes && $2; then $1="$tp_warnings $tp_error_flags" else $1="$tp_warnings" fi ]) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/m4/ax_config_dir.m4���������������������������������������������������������0000644�0001750�0001750�00000007255�11423525545�021570� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������dnl Copied from Audacity 1.3.10 which itself is licensed under the GPL v2 or dnl any later version dnl Function to configure a sub-library now, because we need to know the result dnl of the configuration now in order to take decisions. dnl We don't worry about whether the configuration worked or not - it is dnl assumed that the next thing after this will be a package-specific check to dnl see if the package is actually available. (Hint: use pkg-config and dnl -uninstalled.pc files if available). dnl code based on a simplification of _AC_OUTPUT_SUBDIRS in dnl /usr/share/autoconf/autoconf/status.m4 which implements part of dnl AC_CONFIG_SUBDIRS AC_DEFUN([AX_CONFIG_DIR], [AC_REQUIRE([AC_DISABLE_OPTION_CHECKING])] [m4_append([_AC_LIST_SUBDIRS], [$1], [])] [ # Remove --cache-file and --srcdir arguments so they do not pile up. ax_sub_configure_args= ax_prev= eval "set x $ac_configure_args" shift for ax_arg do if test -n "$ax_prev"; then ax_prev= continue fi case $ax_arg in -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ax_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \ | --c=*) ;; --config-cache | -C) ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ax_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ax_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) ;; *) case $ax_arg in *\'*) ax_arg=`echo "$ax_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac ax_sub_configure_args="$ax_sub_configure_args '$ax_arg'" ;; esac done # Always prepend --prefix to ensure using the same prefix # in subdir configurations. ax_arg="--prefix=$prefix" case $ax_arg in *\'*) ax_arg=`echo "$ax_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac ax_sub_configure_args="'$ax_arg' $ax_sub_configure_args" # Pass --silent if test "$silent" = yes; then ax_sub_configure_args="--silent $ax_sub_configure_args" fi ax_popdir=`pwd` AC_MSG_NOTICE([Configuring sources in $1]) dnl for out-of-place builds srcdir and builddir will be different, and dnl builddir may not exist, so we must create it AS_MKDIR_P(["$1"]) dnl and also set the variables. As this isn't autoconf, the following may be dnl risky: _AC_SRCDIRS(["$1"]) cd "$1" # Check for guested configure; otherwise get Cygnus style configure. if test -f "configure.gnu"; then ax_sub_configure=$ac_srcdir/configure.gnu elif test -f "$ac_srcdir/configure"; then ax_sub_configure=$ac_srcdir/configure elif test -f "$ac_srcdir/configure.in"; then # This should be Cygnus configure. ax_sub_configure=$ac_aux_dir/configure else AC_MSG_WARN([no configuration information is in $1]) ax_sub_configure= fi # The recursion is here. if test -n "$ax_sub_configure"; then # Make the cache file name correct relative to the subdirectory. case $cache_file in [[\\/]]* | ?:[[\\/]]* ) ax_sub_cache_file=$cache_file ;; *) # Relative name. ax_sub_cache_file=$ac_top_build_prefix$cache_file ;; esac AC_MSG_NOTICE([running $SHELL $ax_sub_configure $ax_sub_configure_args --cache-file=$ax_sub_cache_file --srcdir=$ac_srcdir]) # The eval makes quoting arguments work. eval "\$SHELL \"\$ax_sub_configure\" $ax_sub_configure_args \ --cache-file=\"\$ax_sub_cache_file\" --srcdir=\"\$ax_srcdir\"" fi cd "$ax_popdir" AC_MSG_NOTICE([Done configuring in $1]) ]) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/install-sh������������������������������������������������������������������0000755�0001750�0001750�00000033255�12332443655�020217� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/bin/sh # install - install a program, script, or datafile scriptversion=2011-11-20.07; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/config.sub������������������������������������������������������������������0000755�0001750�0001750�00000105503�12332443655�020172� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012, 2013 Free Software Foundation, Inc. timestamp='2012-12-29' # This file 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 3 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, see <http://www.gnu.org/licenses/>. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches with a ChangeLog entry to config-patches@gnu.org. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to <config-patches@gnu.org>." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 \ | ns16k | ns32k \ | open8 \ | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i386-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-* | ppc64p7-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/ChangeLog�������������������������������������������������������������������0000644�0001750�0001750�00001246662�12332445275�017776� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������commit f10f557fd67ec11738670828a553496960c0d411 Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2014-05-07 16:33:17 +0200 0.18.2 commit 5776d2f6bf2dce4efc7754793abf9db1dd731c30 Merge: 8eda233 83939c6 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2014-05-07 15:42:59 +0100 Merge remote-tracking branch 'origin/telepathy-gabble-0.18' into telepathy-gabble-0.18 commit 83939c69969a369824bedae9146a80ab22f2dcc2 Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2014-05-07 16:17:28 +0200 wocky: update Fix https://bugs.freedesktop.org/show_bug.cgi?id=76465 commit 8eda2330d0353845167018e962157053d039a9c0 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2014-03-20 09:57:39 +0000 0.18.2 commit 865a6d69604782326eb5aa3dcc67c744f2b1680c Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2014-03-19 14:05:35 +0000 Update Wocky * data-form: reformat <code> blocks so recent gtk-doc can cope * jingle-content: reset idle ID in its callback commit 226f1eae705a3c05715b4213fbff5b05b995af5e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-06-22 19:16:55 +0100 plugin-loader: clear GError after g_dir_open fails Bug: https://bugs.freedesktop.org/show_bug.cgi?id=66085 Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk> commit 892d6d57b6e8bec11bc7693b5f58cffac158a184 Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2013-10-28 16:21:08 +0100 Use the proper 'Ice' Call capability Also, use token constants when possible. commit c2d7b345aa52e3f5d70d4657f0dbab7c3f62042a Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2013-10-02 15:58:59 +0200 private-tube-factory: tube ID is a guint64 Fix a crash on 64 bits archs. https://bugs.freedesktop.org/show_bug.cgi?id=70038 commit a1faa740ca8773d731d168f19569d6a7d230df85 Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2013-10-02 15:39:46 +0200 conn-presence: fix enum cast warning Thanks clang... https://bugs.freedesktop.org/show_bug.cgi?id=70038 commit 527de4d26ef96e2a049781cdecc4e6e1a05622d3 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-09-09 13:00:30 +0100 Add a regression test for #68829 Bug: https://bugs.freedesktop.org/show_bug.cgi?id=68829 Reviewed-by: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> commit 0899652383fa881d275ab6ab578009e898675762 Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2013-09-06 12:38:19 +0200 set nano flag commit 8ca68d3c4dd43d974dfd4d2a0e0d9b55605a4a10 Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2013-09-06 12:17:18 +0200 prepare 0.18.1 commit 82a38589b201e71a613567fff2df98d82aaad232 Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2013-09-06 12:11:05 +0200 wocky: update to gabble-0.18 HEAD Needed to fix connection to Facebok (fdo#68829). commit 8e27c66d058a72583579384f3dd307e798a8ba73 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-08-09 17:31:07 +0100 nano version, release name commit 1537fdb051a75fc432eb6cb18d42a5f33afb28ac Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-08-09 15:54:45 +0100 0.18.0 commit 80f731d13c3a6d97f531955f1806a436c545236a Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-08-09 15:53:15 +0100 more NEWS commit 2d22f5d22a5d859998971e6c20ab7b0e8108bcb8 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-08-09 16:44:56 +0100 tests/twisted: make the necessary directories to put *.conf in This fails during parallel distcheck. Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk> commit 11971e65916a87e240504f0c105a12f151ca797f Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-08-09 16:44:21 +0100 Update Wocky again Bug: https://bugs.freedesktop.org/show_bug.cgi?id=67953 commit b5138f5abc201c6f3140e1bafa0c8f52031339f4 Author: Samuel Thibault <sthibault@debian.org> Date: 2013-08-09 15:49:24 +0100 errno is actually a reserved word in C, avoid it [Commit message added -smcv] Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=714534 Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk> commit cb6fa296255213c842ca119ab4b0e1796e8a2c6e Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-08-09 15:27:42 +0100 NEWS for 0.18 commit 3a01321d2b2f49fdb2788126513408242d8a114e Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-08-09 15:24:51 +0100 Update Wocky to a version whose tests pass Bug: https://bugs.freedesktop.org/show_bug.cgi?id=67875 Bug: https://bugs.freedesktop.org/show_bug.cgi?id=67900 Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk> commit a4be3bf914b0a3ab7ecba92e3a199310241f1197 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-08-06 15:37:18 +0100 Turn off deprecation warnings, this is a stable branch Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk> commit 1a5bfd386fb23b0690fe99722ed46d2eb1608a85 Merge: 6df8c13 42c0c8f Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-08-06 15:29:35 +0100 Merge branch 'telepathy-gabble-0.16' Conflicts: NEWS commit 42c0c8f2b03a8ac9b94f268d41f379f8773c885f Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-08-06 15:28:30 +0100 NEWS commit 08ac84725bdc135e199146f180be2ea474b452c9 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-08-06 15:28:24 +0100 roster/groups: don't rely on an implementation detail Before telepathy-glib 0.20.3 and 0.21.1, we had this incorrect sequence (pseudocode) for each group: * NewChannels(the group) * GroupsChanged([the group], added: [...], removed: []) * NewChannels(the group) In 0.20.3 and 0.20.1, we removed the second emission of NewChannels. Unfortunately, that broke this test, which was specifically expecting GroupsChanged followed by NewChannels. Rather than reversing the assumption, I'm doing it properly, by expecting the events in no particular order. Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=67828 Reviewed-by: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> commit 6df8c13f5817b3c9f6e7f0592195257a3d857147 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-05-30 14:26:19 +0100 run-test.sh.in: make the indentation make sense The Python invocation is indented, because it's a command-line argument for the sh invocation. The case shouldn't be. Reviewed-by: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65290 commit 54d037ab9b532e70a7fa80ad69a18bed58ccb480 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-04-11 19:33:29 +0100 gabbletest: add hooks for hazetest I need these so that hazetest can just override what it needs, rather than actually modifying the copy of gabbletest. https://bugs.freedesktop.org/show_bug.cgi?id=65658 commit 4b23e0ec83024ebbfcaaeb12cdcd086f7a640b9f Merge: 4d4fc2f 794a02b Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-06-11 14:49:31 +0100 Merge branch 'telepathy-gabble-0.16' and update NEWS commit 794a02b84472ddbbadd6f5f920e2c523f68b27fc Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-06-11 14:46:51 +0100 NEWS for recent changes commit fa48076ccef7e5c8c4a08a88c399d0dbbb3ac624 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-06-11 14:39:42 +0100 Avoid having two of the same set of commands run in parallel A rule like this: _gen/x.c _gen/x.h: prerequisites $(AM_V_GEN)x-generator doesn't consider x.c and x.h together. Instead, it expands to two rules, one to generate x.c and one to generate x.h, which happen to run the same commands. This means that in the worst case, you can end up running x-generator twice in parallel, and they'll race with each other and overwrite or delete each other's output. Based on commit 36c2a545c from telepathy-glib. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=64285 Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk> Reviewed-by: Xavier Claessens <xavier.claessens@collabora.co.uk> Conflicts: extensions/Makefile.am commit 4d4fc2f948dcaaa029c065d5c7e48238eefa3423 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-06-03 11:14:12 +0100 Use run-test.sh to run uninstalled tests commit fcc3900f4e6f6c9a58d95d15af8175b5d04fdaf4 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-06-03 09:14:54 +0100 Adapt run-test.sh to be able to run the tests uninstalled When autoreconfiscated with Automake 1.13, the way in which we were (ab?)using Automake's test driver no longer works. We can't just switch back to the old serial test driver without a dependency on at least Automake 1.12, either. However, run-test.sh (which was already used for installed tests) is quite capable of running uninstalled tests, with a bit of adjustment: * if GABBLE_TEST_UNINSTALLED is set, expect GABBLE_ABS_TOP_SRCDIR, GABBLE_ABS_TOP_BUILDDIR and optionally GABBLE_TEST_SLEEP in the environment * look for installed or uninstalled files, as appropriate * use TEST_PYTHON (which might differ from PYTHON) * use python -u (unbuffered stdout) for better debugging Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65290 Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk> Reviewed-by: Xavier Claessens <xavier.claessens@collabora.co.uk> commit 2a54c7cd0c55d636f33666f4a6ac626e3c6f0f55 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-05-30 13:57:57 +0100 .gitignore: automake 1.13 installs test-driver Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65290 Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk> Reviewed-by: Xavier Claessens <xavier.claessens@collabora.co.uk> commit 7931b9960bc4d357ff04e7381c9d91e161be969d Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-06-04 12:41:12 +0100 Remove obsolete GLib < 2.32 code paths We now depend on 2.32. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65290 Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk> Reviewed-by: Xavier Claessens <xavier.claessens@collabora.co.uk> commit 2a8a6a50be5241627108a23f1dd1ba8d12693f8b Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-05-30 14:02:19 +0100 Officially depend on GLib 2.32 In practice we depend on it anyway, via telepathy-glib 0.19.9. Also update the telepathy-glib dependency in the .pc files to match configure.ac. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65290 Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk> Reviewed-by: Xavier Claessens <xavier.claessens@collabora.co.uk> commit bae4f7493376cccb2cd629e56b4e4cc0624720b6 Merge: 991c397 5a349b2 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-06-06 16:28:31 +0100 Merge branch 'telepathy-gabble-0.16' Conflicts: NEWS configure.ac commit 991c397c6cd33fa970afe8fa46143ae9201b2002 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-06-06 16:27:58 +0100 nano version commit 5a349b2323f8bfd8a5d18c1bc2d79ef14689c0fe Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-06-04 18:34:14 +0100 Disable unreliable test-case It has a race condition or something. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=49595 Reviewed-by: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> commit 83bb468e0d4b386d88821ba2981f981214e9ebc6 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-06-04 12:40:45 +0100 Initialize libdbus for thread-safety libdbus is not thread-safe by default. This is a long-standing design flaw (<https://bugs.freedesktop.org/show_bug.cgi?id=54972>). We call into GIO, which calls into glib-networking, which can (at least in recent versions) invoke libproxy in a thread. libproxy apparently has a Network-Manager plugin, which uses libdbus in that thread; meanwhile, we use libdbus in the main thread and everything goes badly for us. (It's possible that this crash is only reproducible with broken connectivity: I wrote this patch on a train, with intermittent mobile broadband coverage.) In libdbus < 1.7.4, libraries cannot safely initialize libdbus for multi-threading, because that initialization is not itself thread-safe (!); in particular, glib-networking cannot safely initialize libdbus. So, we have to do it. I have written patches to make libdbus thread-safe-by-default, but they haven't all been reviewed and merged yet, and in any case they won't be in a stable libdbus until 1.8. Until then, each application has to discover and fix this bug individually. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65296 Reviewed-by: Xavier Claessens <xavier.claessens@collabora.co.uk> commit f14dfc2f19025a0f9252e58d8b1f6cd8ba6a2744 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-06-06 13:43:22 +0100 Prepare 0.17.5 commit f844ca21c4074201ebb4f3e78531ae29dff97e6f Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-06-04 18:34:14 +0100 Disable unreliable test-case It has a race condition or something. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=49595 Reviewed-by: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> commit 67d009ba2e6ac6d21c659d7586670e3e40b5ec3e Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-06-04 12:40:45 +0100 Initialize libdbus for thread-safety libdbus is not thread-safe by default. This is a long-standing design flaw (<https://bugs.freedesktop.org/show_bug.cgi?id=54972>). We call into GIO, which calls into glib-networking, which can (at least in recent versions) invoke libproxy in a thread. libproxy apparently has a Network-Manager plugin, which uses libdbus in that thread; meanwhile, we use libdbus in the main thread and everything goes badly for us. (It's possible that this crash is only reproducible with broken connectivity: I wrote this patch on a train, with intermittent mobile broadband coverage.) In libdbus < 1.7.4, libraries cannot safely initialize libdbus for multi-threading, because that initialization is not itself thread-safe (!); in particular, glib-networking cannot safely initialize libdbus. So, we have to do it. I have written patches to make libdbus thread-safe-by-default, but they haven't all been reviewed and merged yet, and in any case they won't be in a stable libdbus until 1.8. Until then, each application has to discover and fix this bug individually. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65296 Reviewed-by: Xavier Claessens <xavier.claessens@collabora.co.uk> commit e7efe3e1470e060b5c214f9678b7b16b7f154b47 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-06-04 12:38:38 +0100 NEWS commit 72c46475b6b116b431ef26ea711a53e951c2abab Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-06-04 12:33:16 +0100 Update Wocky to fix a regression caused by #65131 commit d26688c2472ffe697e7495b2e480a1ca335ddce8 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-06-03 12:40:50 +0100 Avoid having two of the same set of commands run in parallel A rule like this: _gen/x.c _gen/x.h: prerequisites $(AM_V_GEN)x-generator doesn't consider x.c and x.h together. Instead, it expands to two rules, one to generate x.c and one to generate x.h, which happen to run the same commands. This means that in the worst case, you can end up running x-generator twice in parallel, and they'll race with each other and overwrite or delete each other's output. Based on commit 36c2a545c from telepathy-glib. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=64285 Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk> Reviewed-by: Xavier Claessens <xavier.claessens@collabora.co.uk> commit 0c7953c80da6aa0fef030669c0588a3451678498 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-05-30 20:34:47 +0100 Update Wocky for fd.o #65131, and test it Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65131 Reviewed-by: Xavier Claessens <xavier.claessens@collabora.co.uk> commit 7e8aec731742c07513419e3c3582337871b066d3 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-05-30 17:03:11 +0100 nano version and retroactive release name commit 9e7500178fa2395c8955680e5c17c40a4b981407 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-05-30 17:01:16 +0100 nano version commit cface3d679b42bb30e4d489fd493bb6784c275e2 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-05-30 16:24:38 +0100 prepare 0.17.4 commit 4cf2247825fba29a4432bbea9fb1522cd80af599 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-05-30 14:32:51 +0100 vcard/supported-fields: catch up with fd.o #64319 Reviewed-by: Xavier Claessens <xavier.claessens@collabora.co.uk> commit 880a75bbf354d48a706c56afafd381040a1d9de8 Merge: 3157284 84a2068 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-05-30 12:55:31 +0100 Merge branch 'telepathy-gabble-0.16' Conflicts: NEWS configure.ac lib/ext/wocky commit 84a20687c54c84aa61c9f3a606c8eb3bd14a8544 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-05-29 17:31:47 +0100 Prepare version 0.16.6 commit 1e99c77f8d8a686c4c1714a959c062bda6dc0c44 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-05-29 12:05:09 +0100 Add a regression test for fd.o #65036 Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65036 Reviewed-by: Will Thompson <will.thompson@collabora.co.uk> commit c1d101558de76e3ebacd05fb032764a126d28468 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-05-28 12:04:44 +0100 tests: fix JabberAuthenticator when self.emit_events is False We don't currently use JabberAuthenticator in this mode, so nobody noticed that it didn't work. I'm about to add a test that does use it. commit e8623e79ec356d4e72286140aa31656dc87b0567 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-05-29 17:22:51 +0100 NEWS: update and describe configuration changes for fd.o #65036 Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65036 Reviewed-by: Will Thompson <will.thompson@collabora.co.uk> [added CVE ID now that we have one -smcv] commit f35fa75276d6e04ea9f99e2df05a75284be920e8 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-05-29 17:21:00 +0100 Update Wocky for fd.o #65036 Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65036 commit 3157284e58195cab12a404752f7d96e3c4ea650b Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2013-05-08 13:07:34 +0200 X-TELEPATHY-PASSWORD is not supported if username isn't known Fixes https://bugs.freedesktop.org/show_bug.cgi?id=64354 commit 57e62a7871be3209fca3046aaf99cdd055fef59d Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2013-05-07 15:48:55 +0200 Google vcard can now have an URL field Fixes https://bugs.freedesktop.org/show_bug.cgi?id=64319 commit 7d81f2e320573647b2049c02a31db0aa3d554e77 Merge: ac6b926 f53ea2d Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-04-04 16:22:08 +0100 Merge branch 'telepathy-gabble-0.16' commit f53ea2d64807cf625ca49f6163b77a36a8282f0d Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-04-04 16:21:33 +0100 Merge with-session-bus.sh changes from telepathy-glib We also have local changes, which should go "upstream" to telepathy-glib at some point. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=63119 commit ac6b926a59d30888a5a62779da16d45f99eeb292 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2013-03-18 11:46:12 +0000 Update Wocky for #61792 commit 712d271f74b4ff1cd904c66d3e258ec544a933a4 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-03-04 12:22:00 +0000 Bump nano-version commit 39aa8ff053de4d127af69bdbe2e896a4f098b284 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-03-01 16:45:42 +0000 Update Wocky to fix distcheck commit f831ac1e20cdc9212ffae24fadd38621e735d61b Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-03-01 15:16:04 +0000 Version 0.17.3 commit e5ff011d3d17cef59e48f47f06f3adae91d9b657 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-03-01 15:15:52 +0000 NEWS for 0.17.3 commit 675565c73c265b7a545f45165ed97299890453fc Merge: 73c8044 ff28128 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-03-01 15:11:53 +0000 Merge branch 'telepathy-gabble-0.16' Conflicts: NEWS configure.ac lib/ext/wocky commit 73c80443fd8594212f1a0f9fb8a99a0a4d691dbc Merge: 0bffd2d fa8be7c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-03-01 15:09:04 +0000 Merge branch '43166-muc-rate-limit' commit ff28128c7699b7fee5757a742f07b4cf9c98764c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-03-01 15:02:50 +0000 Bump nano-version to 0.16.5.1 commit ed05203947880a0f4c45a7f95316e4cc28b23442 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-03-01 12:24:16 +0000 Version 0.16.5 commit 4882535eeeb5843e26dd2b6f0aeaff3f201cbfe6 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-03-01 09:16:25 +0000 NEWS for 0.16.5 commit 110c5af4da0dfd7cd658a1d12047f0dbc79ae2d6 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-02-25 09:51:22 +0000 Update Wocky snapshot to fix 61433 commit fa8be7c05185ce92696a5771b556e70b8eb99a00 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-02-22 08:31:18 +0000 MUC: stop sending chat states after <error type=wait> Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=43166#c0 commit f843f499be4c16683a4a5b054a5bf747254b2050 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-02-22 08:16:23 +0000 muc/chat-states: fix and uncomment commented chunk This didn't work as-is because the <presence type='unavailable'> had no <x> child. Using make_muc_presence() does the job nicely. commit 114c5bc092a9645ecb26cb3310b01d6c8fc08cbc Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-02-22 08:15:30 +0000 muc/chat-states: tidy up checking message bodies commit 62fa6bd989afaec604f420692e10e7716a28496c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-02-15 08:57:14 +0000 muc: test resource-constraint is exposed reasonably https://bugs.freedesktop.org/show_bug.cgi?id=43166#c7 commit cc90a503a9a9ef4aab30b60512f3129de0c0b752 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-02-20 09:26:39 +0000 Test Prosody's MUC's rate limit is exposed correctly now There were a combination of problems before: * The server's error message was not exposed in the delivery report; * Wocky didn't recognise policy-violation; * There was a bug in Wocky's error parsing code which clobbered the message type. So many bugs for such a small stanza! commit 96e5379434adde498624517188be9183e3d4a443 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-02-20 09:19:56 +0000 Map policy-violation to Send_Error_Permission_Denied This code is used by prosody's MUC rate-limiter. commit 21b752bf71edc6889161dca905c3c8300c254355 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-02-20 09:15:04 +0000 Update Wocky snapshot The improvements are: * A new error code, WOCKY_XMPP_ERROR_POLICY_VIOLATION, added in RFC 6120 and used by Prosody's MUC rate-limiting; * Fixes to the error parsing code when error conditions are not recognised; * Tweaks to WockyMuc's error signals to include the full GError and WockyXmppErrorType in both. commit 8f315a9dc0e575375a8e592bf84591bdec64afc0 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-02-15 08:55:25 +0000 muc-channel: include error message in delivery reports commit 717c765b11fe101d9f32bb352f0377ccc762726d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-02-15 08:56:42 +0000 muc/send-error: refactor There will be more cases shortly commit f842fbbb1c09cbb60c379006958f178e7f2d34aa Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-02-15 08:39:36 +0000 muc-channel: pass full error into _receive commit e80923ff9fb329d39962e4fdb7ba800a1f2a2cb3 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-02-15 08:21:11 +0000 muc-channel: pull extracting stanza errors up Really, WockyMuc::message-error should give the error text too, not just the error code, but we'll come to that. commit 0bffd2d8302d81a804f5186f17445abae16b1d85 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-02-12 10:21:54 +0000 tests: don't block on Disconnect() without sending </stream> These three tests were making blocking calls to Disconnect() rather than using the disconnect_conn() helper. As a result, Gabble was waiting 5 seconds for the test server to send back </stream:stream> before timing out. Using disconnect_conn(), which sends the stream close back properly, shaves between 15 and 18 wasted seconds off the test suite. commit 0d65aee3d0c72ebf4c2713945524ae5b80e01c08 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-01-17 12:51:22 +0000 NEWS for the Jingle code moving to Wocky commit 1741adad14a19046aaea8109751d6f7680df0631 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-01-16 10:41:32 +0000 Update Wocky snapshot for wocky.h with Jingle headers commit 1cdfcf9b9be0b76c3c9fc2cc98683f9e10a8f8a8 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2013-01-08 15:09:19 +0000 Remove reference to GabbleMediaSessionMode This enum is obsolete. commit e9cc205c266f628e74c47b4a1bb949be8cc4b8c3 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-12-12 16:08:34 +0000 Delete all the Jingle code which moved to Wocky The astute reader will notice that I added a call to jingle_share_register() to jingle-mint.c. commit f91a1063b57b8b50bd3301633e8620051be2e906 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-12-12 15:25:15 +0000 Update Wocky snapshot to contain Jingle code! commit 8bb1176913d7bbb7beaf63c61b3f95dcc4b8c3a5 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-12-11 16:43:39 +0000 jingle-types: Remove reference to GabbleJingleShare This isn't getting moved into Wocky. commit 3936c9dfd5e184abc9d807be8582657aaed81c9a Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-12-11 15:09:14 +0000 jingle-transport-iface: fix header comments commit efc093b82db19196d66e02100316295c0cc7e92e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-21 16:11:32 +0000 Rename most of GabbleJingle* to WockyJingle* This renames the classes I'm moving to Wocky, and updates all the remaining code to cope. A few things are missed out because it's only reasonable to change them when the code is in Wocky: • GABBLE_TYPE_STUN_SERVER_SOURCE (the GEnum for WockyStunServerSource) can't be renamed easily because it is generated by Gabble's enumtype thing. • GABBLE_DEBUG_MEDIA. Here's the program I used, for posterity. #!/usr/bin/perl -pi use strict; BEGIN { undef $/; } my @Classes = qw(Factory Session Transport_Iface Transport_IceUdp Transport_RawUdp Transport_Google Content Info Media_Rtp Relay); for my $Class (@Classes) { my $FullClass = "Jingle$Class"; $FullClass =~ s/_//g; my $under_class = "jingle_" . lc($Class); my $UNDER_CLASS = uc($under_class); s/Gabble$FullClass/Wocky$FullClass/g; s/gabble_$under_class/wocky_$under_class/g; s/GABBLE_$UNDER_CLASS/WOCKY_$UNDER_CLASS/g; s/GABBLE_TYPE_$UNDER_CLASS/WOCKY_TYPE_$UNDER_CLASS/g; s/GABBLE_IS_$UNDER_CLASS/WOCKY_IS_$UNDER_CLASS/g; } s/GabbleGoogleRelay/WockyGoogleRelay/g; s/gabble_google_relay/wocky_google_relay/g; s/GABBLE_N_JINGLE_RELAY_TYPES/WOCKY_N_JINGLE_RELAY_TYPES/g; s/gabble_stun_server/wocky_stun_server/g; s/GABBLE_STUN_SERVER/WOCKY_STUN_SERVER/g; # Can't rename GABBLE_TYPE_STUN_SERVER_SOURCE because it's generated. Blah. s/GabbleStunServer/WockyStunServer/g; my @Blah_Blah = qw(Candidate State Action Content_Senders Transport_Type Transport_Protocol Candidate_Type Reason Transport_State Dialect Content_State Media_Type Codec Media_Description Feedback_Message Rtp_Header_Extension Media_Profile); for my $Class (@Blah_Blah) { my $FullClass = "Jingle$Class"; $FullClass =~ s/_//g; my $under_class = "jingle_" . lc($Class); my $UNDER_CLASS = uc($under_class); s/\b$FullClass/Wocky$FullClass/g; s/\b_$FullClass/_Wocky$FullClass/g; s/\b$under_class/wocky_$under_class/g; s/\b$UNDER_CLASS/WOCKY_$UNDER_CLASS/g; } s/MAX_JINGLE_STATES/WOCKY_N_JINGLE_STATES/g; s/JINGLE_IS_GOOGLE_DIALECT/WOCKY_JINGLE_DIALECT_IS_GOOGLE/g; commit 0f1435f548071f873d7626643f250b04b53931c9 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-12-07 19:31:31 +0000 Bump nano-version to 0.17.2.1 commit 301a588cbac0745f5f737c0d8d3e45d69e88dddf Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-12-07 18:53:18 +0000 Version 0.17.2 commit bf5dcce04b9063c9482def3041dd80b79d47f5b7 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-12-07 16:13:16 +0000 tests: don't crash in verbose mode on unicode in stanzas We have this hack that sets __repr__ on domish.Element to call its toXml() method, which ends up being used by the verbose logging code when it dumps all of an event's attributes. Unfortunately, this blows up if a stanza contains non-ASCII characters, because repr() tries to convert unicode to str using .encode('ascii'). This made running jingle/test-send-file in verbose mode fail, because the file being sent by the test has a non-ASCII filename. The fix is to make the __repr__ hack escape non-ASCII characters using the unicode-escape codec. commit 55930f39965c9d9ba356aaba4a24fe4f687a5d3d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-12-07 12:59:12 +0000 NEWS for 0.17.2 to date. commit 51e301d6366e7e5f0f203f19fd594cef27ae05db Merge: c33a817 52beb82 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-12-06 18:35:37 +0000 Merge branch 'xep-0184' https://bugs.freedesktop.org/show_bug.cgi?id=47378 commit 52beb82932c6c31f43e6b4465a22f5543cff1d06 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-01 15:55:35 +0000 Advertise support for message receipts commit a997153f14872719d9be2a0947b58ab29e1ec3a1 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-01 15:54:57 +0000 Add missing cap for jabber:iq:last commit 70765bfe80f49dabe5396d8be50fa61daf66b705 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-10-31 23:32:41 +0000 Test all this receipt stuff. I did write this test as I went along, but I forgot to commit it. Whoops. commit 121fa91e6939dca982e631d104405cb2735b1ecb Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-10-31 23:06:04 +0000 im-channel: send delivery reports when requested... ...and the sender is able to see that we are online, is not blocked, and so on. This is not a presence leak: all this allows the peer to do that they cannot already do is determine that our internet connection has not died without our server noticing. Sending a receipt as soon as the message is signalled to the UI, rather than after it's acknowledged, is absolutely compliant with XEP-0184 §4: > Finally, this protocol does not enable the sender to know that the intended > recipient has read the message[, ...] that an end user client has > presented the message to a human user (if any), etc. commit 4af3fe1066bfd36894fb10f80148269ed94d6c11 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-10-31 23:04:22 +0000 roster: obey blocked-ness in gets_presence_from_us This should be irrelevant because blocked contacts shouldn't be able to send us anything which would cause us to send back a reply (eg. jabber:iq:last would be blocked by our server), but just to reassure the reader. commit 6077e9b79db0b7a36bc581f4dd049030289cdf72 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-10-31 22:52:52 +0000 im-channel: clean up obsolete docstring In 574d146 I removed the “magical adventure” aspect of _gabble_im_channel_receive(). commit ee3a7d4deec58856d7d1a01ad71157a9b88185b8 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-10-31 22:44:07 +0000 Support requesting delivery reports when asked to. commit a990012f6e48af641686741ea52506230cdcaaad Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-10-31 20:19:18 +0000 Emit delivery reports for XEP-0184 receipts. commit c33a817b5bcf9f6bec7c744e4c5a3f0b96df4118 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-20 17:46:50 +0000 Don't crash on <success> after closing auth channel. commit a743f0475e440b8b9712df20bb8d997ff6f23177 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-20 16:21:30 +0000 tests: add a couple more cases to sasl/abort There's no reason these should be any different, but I thought it might be worth trying them anyway. commit be0be56f6c097f1a54c64421303dfeb3b930d7a6 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-20 16:06:17 +0000 Don't crash on <challenge> after closing auth channel https://bugs.freedesktop.org/show_bug.cgi?id=52146 commit e33a5de2806bcf63543fdabb3e8607e9d699ca1c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-20 16:02:04 +0000 auth-manager: clarify _challenge_async() Keeping our own GSimpleAsyncResult rather than leaving it up to the channel means _finish() doesn't have to worry about what happens if the channel closes. The g_assert_not_reached () is not safe, but is equivalent to the previous behaviour (wrongly chaining up to the parent class makes it assert). Next, a fix… commit 9854f7cb36f71093855af32747aea0031679cf6a Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-20 14:45:13 +0000 auth-manager: propagate failure both up and across If we're delegating up to Wocky's internal SASL machinery, it might want to know about the handshake failing. If a SASL channel is open, we should let it know so that it can let its handler know that the handshake failed. If we're using X-TELEPATHY-PASSWORD, both these conditions are true. commit 5077f330e3c43d6b0ad5747a4151f9b8492cb21f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-20 14:09:42 +0000 auth-manager: rename 'falling_back' field to 'chaining_up' commit 37cbec4ae810668e08764fd5f364708cd6f4c766 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-20 14:09:19 +0000 auth-manager: ensure falling_back is TRUE when we're chaining up commit 6b8656685c4c640a4e753cc94379b87a2ffbfadf Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-20 14:04:50 +0000 auth-manager: simplify chaining up in _start_auth_async() Rather than using whether or not priv->channel is NULL in _start_auth_finish() to determine how to handle the result, let's always keep our own GSimpleAsyncResult. In this case it doesn't matter very much, because priv->channel in practice can't become NULL in the gap between the callback being called and Wocky calling _start_auth_finish(). In the other cases it does matter, and causes crashes. I'll be fixing those next. commit 8fd563ccf66e89aaa20bb37f397aa21b23b7d012 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-19 18:00:52 +0000 auth-manager: save GError from channel when it closes commit 2b05a3888537cda55710c804d79010677456e503 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-19 17:56:55 +0000 sasl-channel: stash a GError when Close()d commit 2dcfd322daa652c4aeb5adbf7b523e5cd36c8309 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-19 17:51:23 +0000 sasl-channel: stash a GError in more cases. commit 84e56d9c2c1c1ec20c8228c887140149dad3c07a Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-19 17:25:11 +0000 sasl-channel: split changing state and setting errors commit d096c9b10d5c0d7787dccd05cd3dae23ffed99a4 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-13 18:02:15 +0000 sasl-channel: don't crash on Abort() then <challenge> commit 0d347435075681741a6ffba1b75fdeb147e63143 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-13 17:53:30 +0000 sasl-channel: refactor completing operations to a function commit a4a45536a7a3c3b489d8f229e6305b014e18e983 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-06 18:11:45 +0000 Add commented-out regression tests for fd.o#52146 test_close_then_challenge() and test_close_then_success() each trigger similar bugs. test_abort_then_challenge() and test_abort_then_success() both trigger the same bugs by a different route, which I don't think my first attempt at fixing the original bug would have caught. test_close_then_failure() and test_abort_then_failure() pass, and are here for completeness. commit 05c044cc47d87222176aee3bfdc278d176d93abe Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-13 16:47:05 +0000 sasl/abort: clean up common test code commit ea9c62166997004b97dc4a044d44df57ea4c9d91 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-06 17:51:52 +0000 sasl/abort.py: clean up invoking test cases commit 19b535ebbacf6cc20c0c3fe82cf51815e391f362 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-13 17:13:43 +0000 gabbletest: exit if we can't connect to the bus Previously, if the bus wasn't there (perhaps I killed it when trying and failing to ^C the test suite?) the test would just sit there forever after the unhandled exception made its way up to the mainloop. commit 13470c3c4f1602190bcf427911ceb6bb784d9cda Merge: d2db709 204d30f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-12-06 17:37:01 +0000 Merge branch 'vcard-manager-use-nodes' https://bugs.freedesktop.org/show_bug.cgi?id=57603 commit 204d30fa664a2fde56529f451348c457a6e8a57a Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-27 10:37:37 +0000 vcard-manager: find no-op replacements with wocky_node_equal By representing the replacement we have in mind as a WockyNode[Tree], we don't have to reimplement the comparison. commit dbe5edf811d8585866eb4ac605676963a7f19601 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-27 10:27:40 +0000 vcard-manager: represent new node tree as a node tree. commit 1327065e89774ae1f7ffe07dcc473f21d4bdac60 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-27 09:46:00 +0000 vcard-manager: refactor applying edits I found it incredibly hard to follow the old structure; a despatch table with one function per case is much clearer, albeit a little longer. commit ad66082f7e91932db4b8cdd07941951c4d6174f7 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-26 17:13:35 +0000 vcard-manager: don't repeatedly copy while editing Previouly, the entire <vCard> would be copied for every single edit in the queue, which is dumb: we can just make a copy, patch it according to each edit, and send it if it's changed. commit f7baa0f159e36f0f859fecca4e2af726ac1a6553 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-26 17:08:29 +0000 vcard-manager: fix is_significant() gabble_vcard_manager_replace_is_significant() is meant to check whether we're actually changing a value, but in fact it basically always claimed we're not, because it forgot to make a note of whether it's seen the relevant element. By fixing this, we can remove a redundant check at the end of gabble_vcard_manager_edit_info_apply(). commit dbd66dd645e5e17f8915cce28163f7ba34dba73f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-26 17:00:28 +0000 vcard-manager: clarify commentary in CLEAR path commit de157563532a3196dc55a14ee9e3887a4529ec4b Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-26 16:58:48 +0000 Test ClearAvatar() I wasn't sure from reading the code that this actually worked any more, and it wasn't tested. I'm happy to say that it does work. commit 2deced34fe350538fceb9ca8775f0cd8f91ddc15 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-26 16:43:43 +0000 vcard-manager: split up gargantuan edit_info_apply() commit b4604cc6017a7426f716ac4664ccd82b10bad1aa Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-26 15:11:25 +0000 vcard-manager: copy vcards using WockyNodeTree. This is actually less efficient than what was there before, because it copies the tree twice. I think this is symptomatic of Gabble's edit representation being wrong. commit 9f3562e849f56bb3ecfbdf985722db3deeb00a40 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-26 16:01:19 +0000 Update Wocky snapshot for beautiful new node API commit 5497c9d72b41b47c0e2bc7c6c2ec1bec8bca14be Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-26 14:38:30 +0000 vcard-manager: use WockyNodeTree to copy vCard nodes There's actually another implementation of copying a node tree in this file which is a little more involved. I wasn't going to touch it when I thought there was just one, but finding TWO… commit 202014297342e5ba2361879734c6784f71b2cd54 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-26 13:51:54 +0000 vcard-manager: add children more neatly commit 7ff6d247658199261df73db47b0216fd53a05c09 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-26 16:09:30 +0000 ft-channel: add metadata forms a bit less stupidly commit d2db709101b0784e8689433ec547cb826f469a6b Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-27 23:35:58 +0000 conn-presence: stop using _gabble_connection_send_with_reply() _gabble_connection_send_with_reply() does not call its callback if it doesn't get a reply. This means all these cases were leaking the GSimpleAsyncResult if the connection died while the IQ was in flight. commit 9687c65355f885bc17d7f5f6c849c5f333397021 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-27 18:40:29 +0000 Regression test for malformed privacy list replies commit 86ba1bdac4b88ae23b5f37e349afabacb840f03c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-27 18:07:56 +0000 Tidy up privacy list test very slightly commit 2c1e66315f34380a387ea11a81c227066c38e204 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-27 18:06:44 +0000 Regression test for 57521 commit c7d2dfbe19eb5a3c1c9dfbefa61fb48b3416e064 Merge: 3fe57e7 3b10a7f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-12-06 16:28:34 +0000 Merge branch 'telepathy-gabble-0.16' commit 3b10a7f1b0fcb728210eb12231df8b1a4c289c3b Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-27 18:40:06 +0000 privacy lists: don't crash on malformed replies commit 0d908c122903a384882eff7de0e9ec6d6058d661 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-27 17:45:51 +0000 Don't crash when creating invisible privacy list fails. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=57521 commit 3fe57e731b2518e22ba21efb4d16f50564363a2f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-03-29 15:27:11 +0100 bytestream-socks5: send empty offer if we can't initiate. This looks pretty ridiculous, so needs some explanation. If you have no network connection (suppose you're on a train, testing tubes using Prosody on localhost), then get_local_interfaces_ips() returns NULL (the loopback interface is explicitly skipped). So previously, after the recipient has accepted the tube, gabble_bytestream_socks5_initiate() would fail for the initiator. bytestream-multiple doesn't fall back if it fails immediately; so the whole bytestream-establishment fails. The initiator's tube channel would close, but no stanza gets sent to the peer to tell it to stop waiting for the bytestream offer, so it's just hanging there waiting forever. Just making bytestream-multiple fall back immediately doesn't help, because the peer is still expecting a SOCKS5 offer, rather than a in-band bytestream offer, so rejects it. Unlike Jingle, SI doesn't have a way to cancel an offer once it's been accepted but before the transport has been negotiated. So… if we send the peer an empty offer, they'll send back an error, and both sides know to fall back (if they understand bytestream-multiple) or give up (if not). There is no test case for this, because it's difficult to make get_local_interfaces_ips() or gibber_listener_listen_tcp() fail from the test suite. I tested it with a pair of simple D-Bus tube clients and no network connection, and/or hacking get_local_interfaces_ips() to always return NULL. Although this trick is schema-compliant <http://xmpp.org/extensions/xep-0065.html#schema>, it's not compliant with the wording of XEP-0065. Quoth §5.3.1 <http://xmpp.org/extensions/xep-0065.html#direct-proto-initiate>: > The <query/> element MUST contain one or more <streamhost/> elements, > each of which MUST possess the 'host', 'jid', and 'port' attributes. But it also says: > If the request is malformed …, the Target MUST return an error of > <bad-request/>. So this should work with any (robust) implementation. The option would be to (try to) start listening before sending the SI offer—if it fails, don't offer to use SOCKS5 bytestreams. https://bugs.freedesktop.org/show_bug.cgi?id=48050 commit dfe1f729d0026ee72202f43733d9d3376b9d8447 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-03-29 13:45:47 +0100 bytestream_factory_negotiate_stream(): don't pass stream id to callbacks None of them use it, so… commit 6f95a1e49fb7e59eeeb3d4581e678a6c3141868d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-03-29 13:41:25 +0100 bytestream_factory_negotiate_stream(): remove return value It's always TRUE, so it's unneeded. commit aacafd899c775acada617c61c0418ba25166e274 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-03-29 13:35:29 +0100 bytestream_factory_negotiate_stream(): use send_iq_async This clarifies that this function can never fail, which can be the next thing we clean up… commit a6dcef8cd434e05ffbdb569ecdceca68cd2bc04a Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-03-29 13:29:04 +0100 bytestream-factory: stop NIHing TpWeakRef Step one in cleaning up gabble_bytestream_factory_negotiate_stream() is to simplify its context structure. commit 191c3fbfa4f5309227e664273cd8b300871b04b9 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-03-29 13:06:24 +0100 Split gabble_bytestream_socks5_initiate() in two This more clearly separates the code which sets up the listener (which can fail) and the subsequent code to transmit IP addresses to the peer (which cannot fail), I think. commit a188bd209fc34195a0ccd2d12485c1da68265299 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-03-29 11:56:58 +0100 bytestream-socks5: stop using _conn_send_with_reply This makes it clearer that gabble_bytestream_socks5_initiate() can only fail synchronously for local reasons. _gabble_connection_send_with_reply() only returns FALSE if we have no porter; but from the moment we go to state CONNECTED (before which you can't request channels) to the moment the connection is disconnected, we do have a porter. commit 0adea4c2574e53a687e20177175c18a5ce038767 Merge: d5b1bc6 89239d4 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-12-06 12:43:41 +0000 Merge branch '57546-there-can-be-only-one-jingletest' https://bugs.freedesktop.org/show_bug.cgi?id=57546 commit d5b1bc6cc7d76aa32bd441703c2da72213fa33ea Merge: de8905b 6bc2931 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-12-06 12:30:46 +0000 Merge branch '57615-misc-cleanup' commit de8905b5bb098c6f0468e9a2856006d1583ad80c Merge: b735dc9 fbd33aa Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-12-06 12:26:28 +0000 Merge branch '25961-stun-srv' https://bugs.freedesktop.org/show_bug.cgi?id=25961 https://bugs.freedesktop.org/show_bug.cgi?id=25385 commit b735dc9c1320b9a6c206a0856758c60c130428a8 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-12-06 12:04:17 +0000 test-multift: clean up a bit commit dd3d88b53132946ed313da29e30523761e4f9fcd Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-12-06 11:55:14 +0000 test-multift: don't rely on q.expect timing out Previously, this test checked that events didn't happen by waiting for them to happen, asserting if they did, and catching the TimeoutError which occurred if they didn't. But it's more obvious what's happening to forbid the event, take all the actions, and then sync the stream to make sure it hasn't appeared. Plus, it shaves 6 seconds off the test. commit 57ba5c87466279069bf332006e2d0947c4807633 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-12-06 11:18:15 +0000 Fix file transfer tests for these new interfaces commit cf1795dec89679ec14cf8d48d0826d616299a654 Author: Daniele E. Domenichelli <daniele.domenichelli@gmail.com> Date: 2012-11-29 15:16:01 +0100 Export o.f.T.Channel.Type.FileTransfer.FUTURE interface commit 2bbb612f31af9b8a84f8db44c68aab92a424d92d Author: Daniele E. Domenichelli <daniele.domenichelli@gmail.com> Date: 2012-11-29 12:45:36 +0100 Fix o.f.T.Channel.Interface.FileTransfer.Metadata Fixes: fd.o#57267 commit 6bc2931e859d9c23b8d81fede23c0a962514dfae Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-27 15:40:29 +0000 Don't use add_child_with_content with NULL/"" content This is harmless, but looks messy. It's leftover clutter from the loudmouth era. commit 6dacd571ae133e9f8ada918e6222b79c932e0788 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-27 15:08:04 +0000 Avoid manually setting WockyNode.ns where sensible. There's still one case in the Jingle code which seems justifiable. commit 0a7fd199e0ce6b1e67fc18cdae023c9ce9b608b4 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-27 14:45:13 +0000 jingle-session: tidy up sending content-reject in idle commit 89239d474941b766d2f41e9ee2a89094a3d4d980 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-26 09:50:12 +0000 Remove the olde jingletest commit 8e19ae80d2696f42fc472440ec10c89bb844d932 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-26 09:37:02 +0000 jingle/google-relay: use jingletest2 commit 240e6529fdc298cc399aa78a45947664c6f2c2dc Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-26 09:34:17 +0000 jingle/test-wait-for-caps-incomplete: don't use jingletest This test didn't actually use any of the jingle protocol stuff at all—it's just a caps test. commit 01bd7ab1c9088ce4151cdca32e58585fb95334e1 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-26 09:31:56 +0000 jingle/test-wait-for-caps-incomplete: unskip half the test The connection doesn't seem to leak any more. I added this in 07822b272 because <https://bugs.freedesktop.org/show_bug.cgi?id=29790>. I haven't investigated fully, but the test passes, sooooo... :) commit d4ffb25c14d5686c9419ece0826fe2e0de9491fe Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-26 09:20:46 +0000 jingle/test-wait-for-caps: use jingletest2 commit 4aed845bc67b1d98b6d6f69bc1a5c4dbd2ac4deb Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-26 09:13:54 +0000 jingle/stream-handler: use jingletest2 commit d31e229e8bdc3dad3e7d98bf291c103cb4948c8f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-26 09:10:39 +0000 jingle/payload-types: use jingletest2 commit c52894a5facb58465bc6933277e16307f978a767 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-26 09:01:29 +0000 jingle/payload-types: clean up a bit commit 7cdccfed7508e5a915dcd62f8936393e67884b56 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-26 08:56:05 +0000 jingle/payload-types: remove obsolete FIXME commit 804cf93f08c79b400cdca43b45895b2922f05464 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-24 13:34:46 +0000 jingle/outgoing-many-streams: use jingletest2 commit c953579854451a79a005ca2a5663f3230c30efc8 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-23 18:47:45 +0000 jingle/decloak-peer: use jingletest2 commit a6b807a29ec90046327a937c15bfe37e9f1fb6c9 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-23 18:36:35 +0000 jingletest2: make classes new-style commit fbd33aa489c1d9c129e2815ed86678ceacb0ad0d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-26 09:46:21 +0000 jingle/stun-server: use jingletest2 In passing, test all dialects. (Though I think this may be a little overzealous.) https://bugs.freedesktop.org/show_bug.cgi?id=25385 commit 84b84e7a04cc5e5d4ca51b187f7be6ebf7886062 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-23 17:20:39 +0000 JingleInfo: add a TODO for Google returning >1 STUN servers commit 5e5080f7cd7984fb4c62cee1a1856406dc210d0e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-23 16:29:56 +0000 tls/server-tls-channel: use with statement when reading certs commit 783e0913e2c70290ef99b86241fd60478d4abdba Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-23 10:04:08 +0000 jingle-info: discover a STUN server using SRV Derived from a patch by Mike Ruprecht. https://bugs.freedesktop.org/show_bug.cgi?id=25961 commit 286eadd02129048ec5c7ee7c693358db5916cf9a Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-23 14:17:51 +0000 jingle-info: don't discard google:jingleinfo pushes. Previously, Google's reply to our original google:jingleinfo query would be used correctly, but the act of passing it to gabble_jingle_info_take_stun_server would set get_stun_from_jingle to FALSE, causing any later calls to got_jingle_info_stanza() to ignore the updated STUN server information. We address this by distinguishing between user-set and server-provided STUN servers, as opposed to just between fallback or not. commit 149ef25677a0d4cf366c4fd0217f839d5d364ded Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-23 09:56:52 +0000 jingle/stun-server: pluralize expected stun servers commit c342df10d1a2e7f04bd40afd46549cc0a9f8ca8c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-23 09:47:25 +0000 gabbletest: properly support domains other than @localhost I need to be able to vary the domain to do a variety of STUN SRV tests. Previously, whatever domain Gabble tried to connect as, the server would just bind you back to @localhost. The only test which tried to do something exotic was the Facebook own-message test, and that one seemed to work anyway… oh well! commit aae6367f43cf9fd509571e52ea87c7bee5d6124f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-23 15:51:11 +0000 tests: share more code between XmppAuthenticator subclasses commit 106749d45b6075798f15c970d8cb44501fb4eced Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-22 18:04:30 +0000 jingle-info: make get_stun_server plural In practice it still returns at most one server, but just you wait… commit da988bf629a94eaaa7cd5971705f3aec4b3cb1c5 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-22 17:41:42 +0000 JingleInfo: refactor google:jingleinfo feature stuff commit e4396c735cd7ba89ab5131bc345c609d927c2ee6 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-22 16:27:37 +0000 test-resolver: remove unused field for a real GResolver commit a12bb8705eb0810b67f83dae7185a182bb1225bd Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-22 16:21:35 +0000 jingle/stun-server: remove unneeded do_connect=False This used to be needed to ensure that the query Gabble sends right after connecting wasn't swallowed by the expect() calls that gabbletest makes after Connect(). But now that Sjoerd's split the dbus and stream event queues, this is no longer a problem: the only stream event it awaits is stream-authenticated, which is certainly before the jingleinfo query. commit 98add3fb1749366229fc0c211f0fa939d3dfc267 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-22 16:17:51 +0000 tests: use partial in a few places for neatness commit 7852403fa7f216d43fe583a1345cd57eef0ac5a8 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-22 14:44:05 +0000 tests: unduplicate fallback stun server check commit 8a7399906b40e99b6a0b5b3a7eff0879f7cca361 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-22 14:42:12 +0000 tests: use ns.GOOGLE_JINGLE_INFO constant commit ecee60dfc33f05e56eb2d2b34faf188943ff8931 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-23 18:26:20 +0000 jingle: correctly send back unknown-session errors I broke this in c1be75d9 but it wasn't tested. Luckily WOCKY_JINGLE_ERROR_UNKNOWN_SESSION (2) is a valid WockyXmppError too so we didn't crash before, we just sent <gone> instead. https://bugs.freedesktop.org/show_bug.cgi?id=33789 is relevant. commit 1e107a46a34f2251968478052dd4a8239ec2356b Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-22 10:44:37 +0000 Update Wocky snapshot for deconsting G[S]Lists commit 28ddadbd3a3ce84bf3619d83dee005d320f3a915 Author: Olivier Crête <olivier.crete@collabora.co.uk> Date: 2011-03-01 14:22:37 -0500 Don't put const before GSList, the g_slist* functions aren't const-marked commit 1d6c3044f13488e5457a31be631dec8e12068b6b Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-12 14:10:57 +0000 Update Wocky snapshot to validate stanza namespaces This breaks the console plugin, which checks if an entered stanza is of a known type, but <message xmlns=''> is not the same as <message xmlns='jabber:client'> so Wocky now says the former has type UNKNOWN. The plugin already had some code to fix up empty namespaces, but it's after the type check. For a better fix, I added API to give non-streaming WockyXmppReaders a default namespace, and used it here. In the course of fixing this, I found that telling the console to send this: <message> <body> hai </body> </message> would send this: <message xmlns='jabber:client'> <body xmlns=''> hai </body> </message> which is wrong: the empty namespace was not being fixed up recursively. This is fixed as a side-effect of the default-namespace property, but this patch also adds a test. https://bugs.freedesktop.org/show_bug.cgi?id=57016 commit b09e286aa47dfafcc0809cee0e4fe97fd87f95c8 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-14 15:37:05 +0000 vcard/set-avatar: improve test commit e27b7af0d486b80fe370bd9bcbe6e109dfe1aec9 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-14 15:32:42 +0000 Make line-wrapped base64 allocation clearer commit fbee99b49de53621a8a5a38534d4cc423296aeef Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-14 15:27:13 +0000 Add a regression test for line-wrapping avatars commit eae50abaec48f182b9cbe4cd2d0882f20c04be65 Author: Alban Browaeys <prahal@yahoo.com> Date: 2012-11-13 18:49:17 +0100 Fix allocation of the string passed to g_base64_encode_step. As per g_base64 documentation the minimum size is : avatar->len / 3 + 1) *4 + 4) and if line breaks are enabled: + ((avatar->len / 3 + 1) * 4 + 4) / 72 + 1 https://bugs.freedesktop.org/show_bug.cgi?id=57080 commit 67bbddce3fcc200ba97957963939b770797d68a1 Merge: 37102bb 89346a8 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-09 17:18:10 +0000 Merge branch 'telepathy-gabble-0.16' Conflicts: NEWS configure.ac commit 89346a8c8f48add8b090b31a9c63f8239f9bf761 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-09 17:12:48 +0000 post-release nano-version bump to 0.16.4.1 commit b71ded41ee9ddad4a6b6be85759526dc39c55c79 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-09 16:47:26 +0000 Version 0.16.4 commit b27c3518e2efd5151a24bbc7232155a32effefa7 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-09 16:47:12 +0000 NEWS for 0.16.4 commit 37102bbdc665c58cd17dbb635fde31027e5d6111 Author: Debarshi Ray <rishi@gnu.org> Date: 2012-11-09 16:55:42 +0100 caps-channel-manager: Drop reset_caps, which is now unused Fixes: https://bugs.freedesktop.org/56181 commit 64b405cb025a00c3962a415dd90119771517cf6a Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-06 16:46:44 +0000 muc_factory_broadcast_presence(): don't crash if disconnected Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=52362 (I hope) commit 1bd50bc9f5e1cab09b506cea8dd1985b98dfe5e1 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-06 16:46:44 +0000 muc_factory_broadcast_presence(): don't crash if disconnected Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=52362 (I hope) commit d300a2e432294c77a55cdc45cd5d7b3f653e13ff Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-05 16:06:06 +0000 muc-factory: clarify cancelling queued requests. commit 5f262b5741724c0210f51e07691ba830682f5f25 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-05 15:53:23 +0000 muc-factory: use find_text_channel function. Reducing the number of places we directly access priv->text_channels will make it easier to do the right thing when it's NULL. commit 42f4043b305a6e07f8ad87deaf96c6fc6e9f2b59 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-05 15:12:22 +0000 sidecars: fix enqueuing requests made before connecting tp_base_connection_get_status() returns DISCONNECTED in two states: when the connection is yet to connect (internally, it is in state NEW) and when the connection is defunct. tp_base_connection_is_destroyed() allows us to distinguish the two in this case. This was introduced in commit fde8437 and was caught by gateways.py. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=55908 commit 8d4226c28153f054afc16d6b7e7d738b5359ee42 Author: Heiher <admin@heiher.info> Date: 2012-11-05 14:29:37 +0000 Use GLib's base64 implementation rather than Gabble's own (Patch modified to add aggravating signed <-> unsigned casts, and to adjust some tests to cope with GLib appending a trailing newline where Gabble's home-grown line-breaking did not.) Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=54760 Signed-off-by: Will Thompson <will.thompson@collabora.co.uk> commit 1e5c99563e671ca7dece95a1fa66d5a20cb9c722 Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2012-02-09 15:12:02 +0000 test: protocol.py: make the test pass when plugins add new statuses https://bugs.freedesktop.org/show_bug.cgi?id=45988 commit 683414706b5f83f193143e4765cd1437698d8fd3 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-05 13:51:44 +0000 tubes/accept-muc-stream-tube: remove unused imports commit 4002ab7685dc58053133f3998d31dbc2270f8829 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-11-05 13:49:58 +0000 accept-muc-*-tube.py: accept the list of interfaces in either order The order swapped in commit fde8437a, and in principle it should never have mattered anyway. (Simon noticed this. I changed the patch in response to Jonny's review.) Bug: https://bugs.freedesktop.org/show_bug.cgi?id=55911 commit e4c126a0ded1eb0c68bdf03d86acd64728c7beb0 Author: Debarshi Ray <rishi@gnu.org> Date: 2012-10-19 16:17:35 +0200 connection: Don't reset the capabilities in UpdateCapabilities This ensures that a running Gabble process will always create Call1 channels once it has seen such a client in its lifetime. Remove gabble_caps_channel_manager_reset_capabilities and its implementation in GabbleMediaFactory, since it is not used anymore. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=56181 Reviewed-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk> commit 3a068ebe96a0586247f4f597877a0dab78b47779 Author: Debarshi Ray <rishi@gnu.org> Date: 2012-10-19 16:17:35 +0200 connection: Don't reset the capabilities in UpdateCapabilities This ensures that a running Gabble process will always create Call1 channels once it has seen such a client in its lifetime. Remove gabble_caps_channel_manager_reset_capabilities and its implementation in GabbleMediaFactory, since it is not used anymore. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=56181 Reviewed-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk> commit 5c161a8c2eea38dd847c7e0c5a30aec529eb68e8 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-09-17 15:10:56 +0100 update wocky snapshot This is for the WockyConnector::connection-established signal. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit d2ca56c6a3850e58e66d9dc86eba14aa2a32b53c Merge: 373713d 6a82d4d Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-09-17 15:08:08 +0100 Merge branch 'tcp-nodelay' commit 373713d8c9d5a0a2810e57b5f5033a6b9ac516f2 Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-09-11 16:25:35 +0200 Remove useless tp_handle_unref() commit fde8437a4c41f20dfe8da2439db73a0008ed4fce Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-09-11 15:36:13 +0200 Stop accessing sealed tp-glib structs commit 5fd48d98fe83c974d6e024cf4fcb8735a0016460 Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-09-10 17:48:51 +0200 Disable tp-glib single include commit 351b8e5f6eae3e7d75479e65173049a8dfa4bd04 Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-09-11 12:15:55 +0200 Prevent post 0.20 tp-glib API usage commit 9801e21b3489f20f8f6c88e2e40154e8e7da726a Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-09-10 17:47:10 +0200 Update tools from telepathy-glib I know this adds useless tools, but it's easier to have a raw copy of tp-glib's directory. We should consider using a git submodule tbh. commit c7fd1d5ef73cf7ef64b54b378ae7940bb5ba369c Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-09-11 15:58:04 +0200 Bump nano version commit 86f15f2e3057dea4fd52ad0840c6b77cf379c47e Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-09-11 15:54:55 +0200 Prepare 0.17.1 release commit eb53bcaffc16ae388d3cda3b13e7088d84f80388 Merge: 4c720bc 2a17888 Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-09-11 15:49:33 +0200 Merge branch 'telepathy-gabble-0.16' Conflicts: NEWS configure.ac commit 2a1788842f38aaadb028ddd96f7e82f6db7e70b8 Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-09-11 15:43:05 +0200 Bump nano version commit 406c9d74b100184197780d8bd6c68c6e393eeb76 Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-09-11 15:39:40 +0200 Prepare 0.16.3 release commit 4c720bc262ea35b802606910b63b57f28929bdc6 Merge: 36b4819 5c2184c Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-09-11 12:02:09 +0100 Merge branch 'telepathy-gabble-0.16' Conflicts: NEWS configure.ac src/conn-addressing.c src/jingle-info.c src/media-channel-hold.c src/message-util.c src/muc-tube-dbus.c src/muc-tube-stream.c src/olpc-activity.c src/presence-cache.c src/protocol.c src/room-config.c commit 5c2184c21b1e8878394834a3b1ef9096a3c51087 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-09-11 11:26:03 +0100 NEWS for 0.16 commit 8a6e9461f9cc12788532441bcc6f43fa7df4913f Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-09-07 15:22:30 +0100 Verify that every caps 'ext' we ever advertise can be disco'd without error Bug: https://bugs.freedesktop.org/show_bug.cgi?id=54634 Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk> Reviewed-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk> commit da14b4e86d503b30054b10b5e7b00eae7ba1add5 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-09-07 15:19:30 +0100 Now that camera-v1 has a caps URI, don't treat it as part of video-v1 Bug: https://bugs.freedesktop.org/show_bug.cgi?id=54634 Reviewed-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk> Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk> commit fbfa8c138da1a4f00c74af4bda98e858a203a58b Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-09-07 15:18:23 +0100 Add Google camera-v1 as a first-class caps bundle This is partly a point of principle - given any caps bundle that we have ever advertised support for, we should be prepared to define when asked - but mainly a workaround for the iChat bug mentioned in commit af55ea3d. If we return an error, it will keep disco'ing us repeatedly in a loop. This leaves us with the problem of finding out what the bundle contains. In Google's usage it is only its name that is important (ignoring that XEP-0115 explicitly makes bundle names opaque), but replying to disco requests for it requires us to be able to turn it into a set of 0 or more capability URIs. Because of the Google server bug mentioned in commit cd0da0a8, we can't just ask a Google client, because they're all on Google servers, so they can't usefully be disco'd. We assume here that it behaves like the voice-v1 and video-v1 bundles in containing exactly one URI, and that that URI corresponds to the bundle name in the same way. Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk> Reviewed-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=54634 commit 1866bc54eecf2fa6ce00b37d196cd904f8a0203b Author: Sjoerd Simons <sjoerd.simons@collabora.co.uk> Date: 2012-09-11 11:45:16 +0200 Pass RemoteContact key into UpdateLocalMediaDescription Now that telepathy-glib actually correctly checks what is passed to UpdateLocalMediaDescription ensure we always pass the RemoteContact key in the dictionary. commit 61cb4d227d1cbbf85d08f94c28036ba9d831f2fb Author: Sjoerd Simons <sjoerd.simons@collabora.co.uk> Date: 2012-09-11 11:06:28 +0200 Don't assume NewDebugMessage will occur before NewChannel commit e3aae2b2143c8b851e5814f6711aff75d4a1d197 Author: Sjoerd Simons <sjoerd.simons@collabora.co.uk> Date: 2012-09-11 10:30:36 +0200 Make the installed file generation depend on Makefile Make the rules for generating files part of the installed tests depend on the Makefile such that it gets regenerated after runing configure with a different prefix commit 217f39faabeece4946030ea14b6f26bda40fa276 Author: Sjoerd Simons <sjoerd.simons@collabora.co.uk> Date: 2012-09-11 10:14:48 +0200 sed pluginexecdir in run-gabble.sh Commit 352d2da805561ec0164a6e800cd3c3e3bbc629f3 starting using pluginexecdir instead of ${libdir}/telepathy/gabble-0. Unfortunately the generation of run-gabble.sh wasn't adapated commit ccc8f443c94d14d9dd94a5f4fbc84183159e8d33 Author: Sjoerd Simons <sjoerd.simons@collabora.co.uk> Date: 2012-09-11 10:10:52 +0200 Set gabble twisted location both for installed and uninstalled tests Set GABBLE_TWISTED_PATH in the environment which points to either the installed (when using run-test.sh) or the srcdir location (when using make check) commit 36b4819e116fbbcca22c7c87d72d31353b6802bb Author: Sjoerd Simons <sjoerd.simons@collabora.co.uk> Date: 2012-09-11 11:45:16 +0200 Pass RemoteContact key into UpdateLocalMediaDescription Now that telepathy-glib actually correctly checks what is passed to UpdateLocalMediaDescription ensure we always pass the RemoteContact key in the dictionary. commit ed9e8cf54b708276cfa02a589a77af7ce6ac447c Author: Sjoerd Simons <sjoerd.simons@collabora.co.uk> Date: 2012-09-11 11:06:28 +0200 Don't assume NewDebugMessage will occur before NewChannel commit 204fa429bbe263d0f88540957b613572f002259c Author: Sjoerd Simons <sjoerd.simons@collabora.co.uk> Date: 2012-09-11 10:30:36 +0200 Make the installed file generation depend on Makefile Make the rules for generating files part of the installed tests depend on the Makefile such that it gets regenerated after runing configure with a different prefix commit a8bab9887ce33c580b74e43d75fe4b64a1edfecb Author: Sjoerd Simons <sjoerd.simons@collabora.co.uk> Date: 2012-09-11 10:14:48 +0200 sed pluginexecdir in run-gabble.sh Commit 352d2da805561ec0164a6e800cd3c3e3bbc629f3 starting using pluginexecdir instead of ${libdir}/telepathy/gabble-0. Unfortunately the generation of run-gabble.sh wasn't adapated commit 41cccaa8baf6970810ea406a86c04029c2230849 Author: Sjoerd Simons <sjoerd.simons@collabora.co.uk> Date: 2012-09-11 10:10:52 +0200 Set gabble twisted location both for installed and uninstalled tests Set GABBLE_TWISTED_PATH in the environment which points to either the installed (when using run-test.sh) or the srcdir location (when using make check) commit 223a234ad1b30608b122670d8504d33fd6c05d42 Author: Luis Araujo <luis.araujo@collabora.co.uk> Date: 2012-09-07 17:12:47 +0100 run-test.sh.in: print pass/fail status Some automated testing frameworks, including LAVA, ignore exit status and rely on screen-scraping results from log output. Use the Automake convention here (each match of ^(PASS|FAIL|SKIP): (.*)$ is a test result). [commit message added -smcv] Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=52049 commit 6f4aeea22388d325f056882224b87429da1e702c Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-09-07 15:26:19 +0100 Turn off deprecation warnings, this is a stable branch Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk> commit 6a82d4dab2a3d89bb15d4e93f9dfe10be609d210 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-08-30 21:27:03 +0100 only set TCP_NODELAY if GABBLE_NODELAY is set Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 1600f7b3759a095f76754b62de0ad920221bb721 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-05-04 11:34:56 +0100 gabbletest: set TCP_NODELAY on Twisted's XMPP server socket http://i.imgur.com/mWH7b.jpg Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 1420fafea0aa209323f6245afd3f3d9f6452fe8d Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-05-04 11:34:22 +0100 debug build: set TCP_NODELAY on sockets that Wocky creates Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit e193a39e1272931c9470884a42f1a97655438e9a Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-08-28 14:19:19 +0100 NEWS: updated Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit d4c7189ee40a9eb8a0831c78b2dbd5a54e221237 Merge: e5aed68 1ed31aa Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-08-28 12:19:56 +0100 Merge branch 'only-one-tube' Conflicts: src/tubes-channel.c src/tubes-channel.h Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit e5aed68fb70d5450f3dd463b13aef7e52900232f Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-08-28 12:19:12 +0100 configure: bump dependency on tp-glib Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 97c72b2036065b7b3f4862692656b87e9a07ae62 Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-08-14 16:39:35 +0200 Bump nano version commit e60e4f72356ccfe6f8b62c04709430d8debbb737 Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-08-14 16:07:30 +0200 Prepare 0.17.0 commit 1bdfdfcfc0457a33d19df9d8deaeb3bc42d424a6 Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-08-14 15:49:41 +0200 Make sure "make -j3 maintainer-foo" works commit 9f6c4a07d6a3f4776dca92864fe356442b75d19c Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-08-14 15:53:18 +0200 Bump nano version commit 46be2e2be7e11d9270907b886085c962ee361861 Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-08-14 15:41:52 +0200 Prepare 0.16.2 commit 49dc42c7ee6a77858d6e57df919a3008122661c1 Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-08-14 15:49:41 +0200 Make sure "make -j3 maintainer-foo" works commit 1ed31aae5ef79aa7ffc92143ad1b80400c37197e Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-07-24 13:15:39 +0100 muc-factory: clarify code deciding whether to announce text channels Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 5c8c83a0637f3c44d7e608372454b6aa6410b032 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-07-20 12:44:15 +0100 muc-channel: remove ::appeared signal, replace with is_respawning check Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 73b0cbbf9eda1ca4922f562bc99f209e7fac326e Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-07-20 12:17:07 +0100 private-tubes-factory: add further assertions in parsing a tube invite Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 77dafcbc1a7f1de2c6de8f82fd60c3b7eac2a3d3 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-07-20 12:03:50 +0100 private-tubes-factory: ensure (not lookup) handles from tube invites Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 745b5ddcaf5220f2976cabd60a966c52eb25f440 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-07-19 17:30:25 +0100 tubes: use 64bit uints for tube IDs everywhere Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 18f0ca014a92fcc40be0f4658a247687739fc1dd Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-07-18 17:40:32 +0100 private-tubes-factory: simplify emit_new_channel code Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit dbae4d1275181d9c792616a53b328d5de02035b5 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-07-18 17:34:16 +0100 private-tubes-factory: add a comment about who owns new channels Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 1ed620dc1a64533f8aeaa668f510c930c2aa6f5e Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-07-18 17:27:38 +0100 private-tubes-factory: correct logic in looking up existing tubes Good catch, Simon! Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 7dca54edf28f95a911d95aa7fc6c6d333e31b915 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-07-18 17:25:17 +0100 private-tubes-factory: appease the code style checker Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit eeb872711256df80c71f3dac2f8de718f0c0d64d Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-04-05 12:11:59 -0400 muc-channel: disappear from the bus when not requested Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 3b045801e426844af922b5a34a86f4ca0765a6f3 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-05-18 09:44:58 +0100 muc-channel: use TP_PROP more than appending the property to an iface name Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit ba5b6373c4b42c572f44f9559aad995a81115d8f Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-26 17:57:54 -0400 tubes-channel: remove Hooray! Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit faaec035ccef8d2b3f196d923c412f7fecfef1bc Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-26 17:56:59 -0400 muc-channel: remove "tube" property Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 1b08b38de7166ae229555ff9aecf49278d67a97c Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-26 17:53:31 -0400 muc-factory: simplify code to get IM channel from InitialChannels Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 5b5ffc4516a4fe2ef2ac5b0c131ae1b2610de789 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-26 17:53:20 -0400 muc-factory: remove dead comment Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 353db90ad65b2f5749384505bd8372ca8264f44c Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-26 17:52:33 -0400 muc-channel: enable SI stream requests again This code came from GabbleTubesChannel. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit f5b269b50df5b859fee0c168deafa97b107d9ad7 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-26 17:35:17 -0400 muc-factory: fix listing of channels Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 2aea52346a9c1a4adc6e373888298d9a6c50e52a Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-26 17:29:57 -0400 tubes test: fix up now that we return text & tube channels together Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 07dca90ececeee6613a6c0057f3d1b68a6b8ea5c Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-26 17:27:23 -0400 muc-channel: remove unused methods Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 8305b566af9b3b0219a417dd9e854d32a8ec06fb Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-26 17:24:37 -0400 muc-channel: send Tube presence where appropriate This was removed GabbleTubesChannel. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit d6ade9e4a2cfae7054dfc75a39cc6d724bdb7933 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-26 17:11:53 -0400 muc-channel: add way to request single Tube channels Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 9568e3b1c68648781b39d4968d71128ba07ede96 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-26 16:51:24 -0400 muc-factory: remove Tubes channels from Tube channel requests Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 87fc93eba8527d5c183c0121190ac75d07f39beb Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-23 19:16:25 -0400 muc-channel: store Tube channels here Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 64cf190a7fc4ed8e8bbd340c9581e3ddfff9d4e6 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-23 18:55:04 -0400 muc-factory: remove Tubes channel handling code Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 88777ca5ca7847d6f7b27a590d26f283a286f7ad Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-23 18:51:37 -0400 muc-factory: stop exposing Tubes channels in RCCs Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 95ea89f326c9d2b34eda734a77344664e6f56bf0 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-23 18:49:39 -0400 private-tubes-factory: make extract_tube_information public This should probably go in a tubes-util file or something... Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 6ae35c68a9451257b6cc136ed3dbd857241fdcd6 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-23 18:48:38 -0400 private-tubes-factory: make error messages more specific Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 2fd80cbc062c60402d3bc93e0b08dcba3b6d6732 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-07-16 17:48:14 +0100 jingle caps test: add a test for Google caps with a random node Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 5752b2a7b92f91fb80874272137a89151c630f21 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-07-16 17:45:55 +0100 presence-cache: ignore caps nodes when we see google 'ext' features Google keeps changing the node for its voice-v1, video-v1, share-v1, etc. features. Let's just ignore it from now on and if there's no hash treat it as if it might be Google. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 1158ce4649fe88dc410769665def19e5e702c9ec Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-07-16 14:04:12 +0100 presence-cache: parse caps URIs as a pair of node and fragment Previously we'd always throw the node and fragment together like: node + '#' + fragment Separating them has the advantage of being able to only look at the fragment later (without using string tricks) and ignore the node. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit f88ae541292e0ff4abd9214bef4c7b99a55dc4e9 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-07-11 11:53:03 +0100 server-tls-manager: deal with modification of the GList while iterating it Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 5de7189fa93918cc1dda3bfdf8d5833b63e43020 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-07-11 11:53:03 +0100 server-tls-manager: deal with modification of the GList while iterating it Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit c04d52520e405649a2878902a0c825558b5a91ac Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-05-28 10:30:55 +0200 Implement WLM jidlookup See description: http://msdn.microsoft.com/en-us/library/live/hh550849.aspx https://bugs.freedesktop.org/show_bug.cgi?id=50341 commit 8947be225e17d1cee96cf41586f495dcd35c6904 Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-06-20 15:24:58 +0200 0.16.1 release commit 9abf25885dd71047746ea496ea3bdaff7f3499e7 Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-06-13 14:41:10 +0200 GabbleServerTLSManager: Support multiple consecutive TLS verifications WockyConnector could now restart connection with another host, and so needs to re-verify TLS. commit 788a8fcfc2946eae5327665b9e7c8a71a9475a9c Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-06-13 14:41:10 +0200 GabbleServerTLSManager: Support multiple consecutive TLS verifications WockyConnector could now restart connection with another host, and so needs to re-verify TLS. commit 287fb2d9fabd2703c17020c4fd9493e8531c0a03 Author: Marcus Lundblad <ml@update.uu.se> Date: 2012-05-18 13:29:12 +0200 Fix for initiating a video call from an Android tablet. Reviewed-by: Sjoerd Simons <sjoerd@greynoise.nl> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=36998 commit bced2f61312ab407964ac3ef0653183eb3b8c6cc Author: Marcus Lundblad <ml@update.uu.se> Date: 2012-05-15 22:40:04 +0200 Make Android 4.0 GTalk contacts appear as capable of a/v calls. Reviewed-by: Sjoerd Simons <sjoerd@greynoise.nl> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=36998 commit e1673f4fb2818a8c2906b056a0a62d28cdd54097 Author: Marcus Lundblad <ml@update.uu.se> Date: 2012-05-18 13:29:12 +0200 Fix for initiating a video call from an Android tablet. Reviewed-by: Sjoerd Simons <sjoerd@greynoise.nl> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=36998 commit dad87309ae85ca4a45e393c1e351b309fc8097a6 Author: Marcus Lundblad <ml@update.uu.se> Date: 2012-05-15 22:40:04 +0200 Make Android 4.0 GTalk contacts appear as capable of a/v calls. Reviewed-by: Sjoerd Simons <sjoerd@greynoise.nl> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=36998 commit 89751765986de2390c53e83ec41a4ea59aabd62c Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-05-30 13:56:20 +0100 Include missing config.h at the beginning of jingle-info.c commit fa3b39e7a84fa985a5f7bac664fa6af8a355e622 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-05-30 13:34:20 +0100 Use meta-headers for everything Reviewed-by: Xavier Claessens <xavier.claessens@collabora.co.uk> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=49384 commit a71f4c62ac847c8d2cf78cb6b7db62786b82dd1b Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-20 19:01:46 -0400 private-tubes-factory: remove some duplication Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit f9eca443d693dbde73e92cd7a2eee6980b69114f Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-20 15:22:25 -0400 connection: make a better guess at the final number of channel managers Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit d9f90c7b16df1ed85fbabbdaa34ea418e29e38f3 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-20 15:11:13 -0400 private-tubes-factory: remove old Tubes code Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 7490deaff7d3acf2cbecb947d3dfe984e782eb94 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-20 15:04:05 -0400 private-tubes-factory: move SI tube request handling to here Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 5d804b3926c93becaea7d017fcdae766d13fe056 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-20 11:22:11 -0400 private-tubes-factory: implement handle_si_stream_request ...instead of popping into TubesChannel. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 143bdcde2369f6bd001d3b86eef15ffb20a499d3 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-15 16:49:49 -0400 private-tubes-factory: only create Tube channels for tube offers extract_tube_information has been copied verbatum from tubes-channel.c. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 867dea173d0c9ac876199fca0b532ff1126987d6 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-15 16:41:39 -0400 private-tubes-factory: remove Tubes channels from RCCs Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 5747291212d7f6ccc92ceb4cc198a292985d203a Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-15 16:41:11 -0400 private-tubes-factory: create only Tube channels for requests Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit c10809c97c20c1d3a55740f4e93eac26664b88a9 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-15 16:36:42 -0400 tube tests: remove all Chan.T.Tubes tests Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 4f67d0e00694967c31ab35ab6eec0a325bc19d5d Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-05-17 17:57:50 +0100 configure: ignore post 0.18 deprecations so we can build against tp-glib master Gabble still uses emit_new_channels and tp_handle_{,un}ref, but for now we can ignore it with this. config.h had to be included in the right place for a lot of source files. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 7667bb74e99e236c15f34b7f9266073441d3afde Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-05-10 15:11:56 +0200 Fix a leak in: tp_handles_unref() does not unref the array commit b7eaf004dd62f4425cc6027420533b493640d70d Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-05-10 14:59:46 +0200 Stop using tp_handle_ref/unref commit 591ee25d44a016b38067d1f9a8772dca0fbca09c Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-05-10 15:11:56 +0200 Fix a leak in: tp_handles_unref() does not unref the array commit df5e6d51ff66b5e84efdb1a1dfb28e584c2d5f3e Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-05-09 18:44:05 +0200 Bump telepathy-glib required version to 0.19.0 commit 13eebb3cb90c31bcb27e70958e4664174cdce621 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-05-01 15:17:26 +0200 Improve ChatState test commit 956a5f821854494228981c2b7d3095a9a0687427 Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-04-30 23:24:01 +0200 Use TpMessageMixin to implement ChatState commit cbfa9d06a8e4cc93b15e4a8b53819638ab09d67c Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-05-07 18:54:08 +0100 Set G_MESSAGES_DEBUG during testing With recent GLib, we don't see debug messages otherwise. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=49596 Reviewed-by: Xavier Claessens <xavier.claessens@collabora.co.uk> commit 3ee4f3fe45cd9b045081532bb4213582938a00f8 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-05-07 17:29:22 +0100 Use non-deprecated TpIntset APIs Bug: https://bugs.freedesktop.org/show_bug.cgi?id=49596 Reviewed-by: Xavier Claessens <xavier.claessens@collabora.co.uk> commit c4b8ceb361748495be477bd3de49ac87c1a5bb2a Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-05-07 16:58:51 +0100 Use TP_ERROR instead of deprecated TP_ERRORS Bug: https://bugs.freedesktop.org/show_bug.cgi?id=49596 Reviewed-by: Xavier Claessens <xavier.claessens@collabora.co.uk> commit eda09f9123a74dcc7e1b5ad52816ff70d794dec2 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-05-04 14:47:49 +0100 Stop using deprecated debug-ansi.h Bug: https://bugs.freedesktop.org/show_bug.cgi?id=49596 Reviewed-by: Xavier Claessens <xavier.claessens@collabora.co.uk> commit 0b2ba1be64a70c74408919b8717457042ce23648 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-04-05 13:28:10 -0400 servicetest: TextTestRunner might not be in unittest.runner Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit f9fd6bebc5f8774395433dfb055b68ddd5de84de Merge: 208a634 b8dd9b0 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-04-05 12:49:14 -0400 Merge branch 'shutup-servicetest' commit 0015b83d5746ec5fab3e4205c56ec599a5726bfa Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2012-04-04 09:49:48 +0200 use new GLib API checking macros commit 70aaaad2f9391453f7d8c9cb1ebad349d4b96421 Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2012-04-04 09:44:51 +0200 Depends on GLib 2.30 telepathy-glib 0.18.0 already depends on this version so that won't change much in practice and it will allow us to use GLIB_VERSION_* macros (GLIB_VERSION_2_24 doesn't exist). commit 7eac882fe8f48cc3145cff24fecf499b87c38f2d Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2012-04-04 09:48:28 +0200 gibber-unix-transport: stop defining _GNU_SOURCE config.h does it for us now. commit b89caf381ba7a38c1ac98fe4b04a261cf62c1ad1 Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2012-04-04 09:34:41 +0200 add missing config.h includes commit 579eb4f247b7383d4f50f79e7802f9b48ffadf7a Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2012-04-04 09:34:25 +0200 include config.h in the generated gabble-enumtypes.c commit 208a634498e965a6087c6fb59a6d220e91163faf Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-04-02 17:47:49 -0400 start on version 0.17.0 Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit ae9e1ce5a377bcd2d19d169bdede8ca264032754 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-04-02 17:43:20 -0400 start on version 0.16.1 Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 4291d1d472bc22ea1423e5ef2dc063eb1782ac15 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-04-02 17:05:53 -0400 version 0.16.0 Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit b0112d03c77dfe4b506168ccffcc1eb4bb83d29f Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-04-02 17:04:52 -0400 NEWS: summary for 0.16.0 Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 40322ddb3228a9687bee25ee4c85a5dffeccefe2 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-04-02 17:13:10 -0400 configure: update dependency on tp-glib Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 4d9133a523d95207699b3ede02b26e7e2c272fdd Merge: 71dcf75 44582af Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-04-02 17:50:28 +0100 Merge branch '47999-handle-ibb-errors' commit 44582af04f111e4ba855afceb814997fce812a4e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-03-28 14:53:43 +0100 bytestream-ibb: handle IQ send errors This is untested, but the existing tests still pass… https://bugs.freedesktop.org/show_bug.cgi?id=47999 commit b8f84c653318b18c5070085e66fca011f04bcb65 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-03-28 14:26:12 +0100 bytestream-ibb: correct send_data's return value. This function returns the number of messages sent, not a boolean. commit 71dcf75998ea8a332903def7b6513df5e4e6d819 Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2011-12-13 16:43:57 +0000 New test: connect/test-connection-params.py https://bugs.freedesktop.org/show_bug.cgi?id=43828 commit 45d81af51417a79bd2fd7c98b0980ba7e725dd5c Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2011-12-13 12:16:07 +0000 ContactList: downloading the roster at connection depends on a connection parameter https://bugs.freedesktop.org/show_bug.cgi?id=43828 commit deb67c35893b1770533eb48c4e7ec0840afc8926 Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2012-02-23 16:29:49 +0000 Update dependency on telepathy-glib https://bugs.freedesktop.org/show_bug.cgi?id=43826 https://bugs.freedesktop.org/show_bug.cgi?id=43828 commit 687ec45023294d6003f987ff0dfc72986fdb7f46 Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2012-01-04 14:22:02 +0000 gabble_roster_unpublish_async: correct the source tag commit 5d7a8f948c504b842781e99f77bebcb94bf610a0 Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2012-01-04 14:21:42 +0000 gabble_roster_authorize_publication_async: correct the source tag commit 352d2da805561ec0164a6e800cd3c3e3bbc629f3 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-03-09 13:38:04 +0000 Replace plugindir with an AC_ARG_VAR so it can be passed to configure This lets you configure the plugin directory: ./configure pluginexecdir='${libdir}/my-gabble-plugins' The directory-name variable has 'exec' in it because Automake installs unknown directory names with 'exec' in their variable name during "make install-exec", and other unknown directory names during "make install-data". Bug: https://bugs.freedesktop.org/show_bug.cgi?id=46417 Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit f06469da5cfc7c8dc750bce82099dde4b528a20b Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-03-09 13:35:37 +0000 Install non-ABI-stable libraries used by plugins to a private directory This avoids having Gabble and Salut, or old Gabble and a future stable Wocky, fight over the libwocky.so symlink. If you're building for a tightly controlled platform where Gabble and Salut are definitely using the same Wocky version, you can put them in the normal libdir with ./configure pluginexeclibdir='${libdir}' or (when Salut has been updated with this change) make them share a private library directory: ./configure pluginexeclibdir='${libdir}/telepathy/ytstenut-1.0' Bug: https://bugs.freedesktop.org/show_bug.cgi?id=46417 Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit c535a29358002b3b48c3df7bedecfbf73ab4553f Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-03-09 12:42:10 +0000 Avoid non-portable use of += in configure.ac Bug: https://bugs.freedesktop.org/show_bug.cgi?id=46417 Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit b942885bb6bca2e56b1a24737fcb8cf266d9cb61 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-03-09 13:04:13 +0000 Avoid Wocky trying to install into --prefix=NONE Bug: https://bugs.freedesktop.org/show_bug.cgi?id=46417 Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 531bffcfaf8bed572259981d4d900e7f1e42e473 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-03-09 12:41:46 +0000 configure.ac: remove apostrophe from a help message so syntax highlighting works Bug: https://bugs.freedesktop.org/show_bug.cgi?id=46417 Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit fed5695cc026ab4076197de2a28a5f7bbe69dacb Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-03-09 12:24:44 +0000 telepathy-gabble.pc: link to Wocky Bug: https://bugs.freedesktop.org/show_bug.cgi?id=46417 Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit c8da384dd9f311296145cdb49a2279f624502708 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-22 19:20:56 -0400 start on 0.15.6 Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit b26a704c87968bc1db29a2917c2ca0bdf10ed999 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-22 19:09:06 -0400 version 0.15.5 Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit b7350b195bae44bda93e767b7a8a5616c558102a Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-22 18:52:51 -0400 configure: depend on telepathy-glib 0.17.7 Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit b82352ce6eb3bab55e09f58ce07a3fd1d90ce319 Merge: 21ec409 27fa0aa Author: Marco Barisione <marco@barisione.org> Date: 2012-03-22 17:52:20 +0000 Merge branch 'disable-voip' Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=47502 Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 27fa0aa72eb61ecffb26998f535f66e4ae992ae6 Author: Marco Barisione <marco@barisione.org> Date: 2012-03-09 08:33:54 +0000 Allow to disable VoIP-related code with --disable-voip commit a69250eac91ac827ff90cf8a03d6540b68a5d001 Author: Marco Barisione <marco@barisione.org> Date: 2012-03-16 16:14:15 +0000 There is no need to include non-compiled files in EXTRA_DIST Automake makes sure that all the source files, even if they are not being compiled at the moment, will be distributed when doing make dist. commit 21ec409017f58d1ff863cc8c26d42108931ecabb Author: Olivier Crête <olivier.crete@collabora.com> Date: 2012-03-16 14:18:25 -0400 CallStream: Replace want_send with the local sending state of the Stream Also require the newest telepathy-glib commit 78db4e43dcbc8e8fabe87e05a9231b3b6555116a Author: Olivier Crête <olivier.crete@collabora.com> Date: 2012-03-16 14:17:51 -0400 CallStream: Set local sending to true if a locally-created content wants to send commit b9926cf5413dde094ae134a84b349e26ffeabfa4 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2012-03-13 19:01:35 -0400 Also check the sending state of non-initial streams commit a1414b8e991a4a51bb9cc09af29f4e3b56e23289 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2012-03-13 18:44:30 -0400 tests: Expect new contents to be pending_start receiving commit 12e43de2942da80fb31e59ba334d5813af895fd6 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2012-03-09 17:12:24 -0500 Fix unit tests to use the Telepathy candidate types commit 72e98283ca6a53b31f45a3fb410324bfba7ec1e1 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2012-03-09 16:52:32 -0500 Convert Telepathy types to Jingle types correctly commit ceb7985d76f8d2c614344b4b6c68d152384b695b Author: Olivier Crête <olivier.crete@collabora.com> Date: 2012-03-09 16:45:47 -0500 Correctly convert JingleCandidateType to Telepathy types commit 8bbc8e408464f65f5cc93ff18109661f297b39d8 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-09 10:29:40 -0500 tube-iface: remove duplicated properties These wouldn't *have* to disappear, but GObject was complaining because GabbleTubeIface:connection was implemented in TpBaseChannel as type TpBaseConnection, when it was expecting a GabbleConnection. Stop crying, you baby. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 0d57767b5f669d51049257bac918a98de798b9e0 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-02-23 12:19:42 +0000 Link plugins in the same way on Unix as on Windows Reviewed-by: Olli Salli <olli.salli@collabora.co.uk> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=46417 commit a167423acad1bbc41d764710fbc1de4347906da6 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-02-23 12:01:26 +0000 Build Wocky as a version-specific shared library Reviewed-by: Olli Salli <olli.salli@collabora.co.uk> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=46417 commit 9a52bb20676a5290b3778cecb9d5bbc74a928db7 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-02-23 12:29:42 +0000 Use the standard EXEEXT variable rather than reinventing it commit b8dd9b07c8a90a84bccc0cb348c5801a29d6c68b Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-03-07 15:28:14 -0500 servicetest: silence unittest The output when running all the tests is made really ugly by this appearing out of nowhere. Only print the unittest stuff if CHECK_TWISTED_VERBOSE is set. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 0a7c66f48e2a4f5f1b80237def4063fa952ccc71 Merge: 52fac35 c8f08ce Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-03-01 17:07:08 +0000 Merge branch 'detp-jingle' https://bugs.freedesktop.org/show_bug.cgi?id=46513 Conflicts: src/ft-channel.c commit 52fac3507be8db06a9e1ae1b7a3c98a28d02da44 Merge: 10785ff 491db17 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-02-29 15:02:55 -0500 Merge branch 'base-channels' Conflicts: src/Makefile.am src/tube-dbus.c Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit c8f08ceb6e7f44303d1950a565e47f170129e524 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-29 13:22:22 +0000 CallStream style: add a missing blank line. commit de5eb4bebefa0d68d7ec081ed5845479c5aeae9e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-29 13:20:50 +0000 JingleMint: rename ::new-session to ::incoming-session This is Simon's idea, and it's a good one. It makes it clearly a different signal to JingleFactory::new-session, too. commit f6d4a38fc058300dc2422f61f469ed6a86697ed8 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-29 13:14:05 +0000 JingleInfo: chain up at the end of dispose Simon noticed: > Surely dispose should chain up at the end, not the beginning? I see > dispose and finalize as progressively breaking the functionality of > the object's classes, most-derived first. Yup! commit cdc02ea04db52b24d84be250893b3bdc750baafe Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-29 13:12:47 +0000 JingleSession: don't leak in initiate/accept callbacks Simon noticed: > "Send session-{initiate,accept} IQs using porter directly.", > 72ea73343252: I think you're leaking sess in the callbacks, except in > the early-return cases where the state has become inappropriate? He's quite right. commit 10785ffc0e61d98d6bc23b5281872d7268b3a3a1 Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-02-29 11:26:31 +0100 Include config.h to have GLIB_DISABLE_DEPRECATION_WARNINGS defined commit a6ef0c0b9d2747baaaa049a6c441da7b94d65265 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-23 12:59:29 +0000 JingleSession: make _new() take a dialect. Everywhere that creates a new session knows the dialect it wants to use, so let's pass it right into the constructor. commit da9f352766edf270c907421ea610549593c46325 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-20 15:24:12 +0000 Represent Jingle relays by a struct, not an aa{sv} This has the dual benefits of removing Telepathy data structures from google-relay.c, and of simplifying the use of these structures in gtalk-file-collection.c. commit 089a5f2de461d90f9089a68dc11ada1cfc6f58b1 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-20 12:35:02 +0000 Jingle*: stop including util.h commit ae1d315c9bae65a5dd9c1eacbdcda1aa2ec6408f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-20 12:32:12 +0000 JingleFactory: drop use of gabble_signal_connect_weak() Wocky doesn't have an equivalent of this function. It's relatively little work to explicitly disconnect from the sessions' ::query-cap signals, so let's do that. commit ca86afb5cde89cc1832ed002a59cef6f51916ef4 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-17 19:19:44 +0000 Remove unused JingleInitiator type. It would actually be better if a two-element version of this without the INVALID element had been used throughout rather than booleans to represent the direction of a session… but oh well. commit d88193074f1f1d9f4d618932821dbab36a474182 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-17 19:07:19 +0000 Move Jingle enums and typedefs to a new jingle-types.h For some reason the enums lived in jingle-factory.h before. We do need a separate header for the typedefs because some of the Jingle headers are mutually dependent. commit ac9ee4a66f56f8c033f150eb5c8a4a9999e475e3 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-17 19:10:27 +0000 JingleFactory: correct TpChannelGroupChangeReason reference commit 003e72bc1d8cf70aa595f036ebcfb7e2a542efbb Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-17 18:55:27 +0000 JingleFactory: drop GabbleConnection dependency. So with this patch, GabbleJingleFactory takes a construct-time WockySession property rather than a GabbleConnection; GabbleJingleMint only creats the factory when the porter (and hence session) becomes available. With this, we've removed the core Jingle code's last significant Gabble/Telepathy dependency. commit 745b27e041cb9db5b6a1eb920fdaf480a65d4762 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-17 18:35:05 +0000 JingleFactory: store WockySession as well as Porter This makes ::porter-available the only place in jingle-factory.c which uses the connection non-trivially, laying the ground for removing it… commit 081f2e7776614e6e8147909c0e5ab9593a85f2dd Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-17 18:28:08 +0000 JingleFactory: propagate caps queries out to Mint commit 4a27eccf389050be52eb4701263e832634fe63ca Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-17 18:22:01 +0000 JingleFactory: move pre-initiate presence pushes to Mint commit 035f99f9c5ea8dbff493555921b6056756106215 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-17 18:18:44 +0000 JingleFactory: emit ::new-session for outgoing sessions too commit 46c47589c95f923453b9f4e3fe4aa6d648e8447b Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-17 18:11:12 +0000 JingleFactory: explain why create_session() can't emit new-session commit ad631083a88dfdea01b2a9957eeff9594a97ed7b Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-17 17:55:21 +0000 JingleFactory: move connection status monitoring to Mint commit b6ff8bff994babae4afb0e00b8d388b2c37cff8b Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-17 17:49:12 +0000 JingleFactory: call stop() from dispose() This is currently redundant, but will prevent crashing in a hypothetical situation where the factory gets disposed without anyone calling stop() on it first. commit 3676e46472aad8a8205cf8618a15b45d07690e2e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-17 17:47:48 +0000 JingleFactory: refactor handler-unregistration to a method This will be used by the mint to stop the factory accepting new incoming sessions when the connection starts disconnecting. commit 618234580dcb23f076d0cc75b69f2cbcc92b96a6 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-17 17:42:19 +0000 Wrap JingleFactory in a new class, JingleMint. The intention is to move all Gabble-specific code into JingleMint, leaving only the pure angle-bracket distillate behind in JingleFactory, which can then be moved to Wocky. But as of this commit, JingleMint is basically an empty shell: it immediately creates a JingleFactory, and proxies its ::new-session signal. As described in the comments, “mint” is meant in the “factory which makes coins” sense. It seemed like a better name than JingleFactoryFactory. commit 8b958fc8c845755832b44e00ffb30e235c82994e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-17 17:32:14 +0000 JingleFactory: add _new() method commit 77d5d99e9b608d080cc46c523880eccdc1d5360c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-17 13:59:35 +0000 JingleFactory: correct ::new-session's signature GabbleJingleSessions are not mere pointers: they are objects! commit f40f6c4db3079aa7b4befe70c8a709d49144cc6f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-17 12:07:07 +0000 Split Telepathy<->Jingle enum mapping out of Jingle code commit 51ec259c494d42c30adfb982646eda2805b2ec3d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-17 11:56:35 +0000 JingleMediaRtp: drop use of TP_ERRORS Depending on whether an illegal codec update comes from the network or from the local system, we end up wanting either a WOCKY_XMPP_ERROR or a TP_ERROR (to throw back over the wire or in a D-Bus method error, respectively). Previously, this choice was made inside JingleMediaRtp; this patch moves the conversion out to GabbleMediaStream. (The Call codepaths all pass NULL for the GError **... great.) commit 729d3f4f06eba69e499805b004383aba521c7a35 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-17 10:41:17 +0000 Jingle*: spell out tp_clear_{boxed,pointer} Wocky doesn't have things like this. GLib, however, does have g_clear_object() so we can use that in place of tp_clear_object. commit feb1266ce56e12359a9f2d6ff2325acd0c3a8b56 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-17 10:28:27 +0000 JingleSession: spell out tp_str_empty() Wocky doesn't have an equivalent function. commit b1be04b448e5860f7cadc27ac7a20a81367f4b3a Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-17 10:26:53 +0000 Jingle*: use wocky_strdiff rather than tp_strdiff commit 10f9eccfb8e3e1e8f88315b41e6a60a26185db26 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-16 20:00:23 +0000 JingleSession: remove GabbleConnection property. commit dada0afc57d852209a78494c3af12e3704790f1c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-16 19:48:01 +0000 JingleSession: move pre-initiate presence pushes to Factory This change has the same rationale as the previous. commit 78629e08e943bcca2a0d28648c853f5ac50e93b5 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-16 18:02:50 +0000 JingleSession: delegate capability queries to factory The two remaining bits of code that use GabbleConnection inside GabbleJingleSession use the caps cache and the roster. There is really no good code for these inside Wocky just now (well, WockyRoster exists, but it's not what Gabble uses so the point is moot). I've resigned myself to the fact that GabbleJingleFactory will have to stick around in some form—not least to listen for ::porter-available, and also to dig stun server parameters out of GabbleConnection. So I think the best path to breaking GabbleJingleSession's Gabble addiction is to add some signals which get handled by the Gabble-specific remnants of the JingleFactory. Meanwhile, I noticed that the caps-checking code didn't actually work for the bare-JID case, so fixed that up while moving the code. commit 28f25af9b2f95103bacb3ab3a005b6cb102950fc Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-16 17:36:48 +0000 JingleSession: get own full JID from porter. commit e1a08344fcfaac717bd533c7ea990f82b3c3732d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-16 17:34:38 +0000 JingleSession: add a porter property. commit fd17643d8495e4f3fe87fe3660f7008ee1953eb7 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-16 17:26:31 +0000 JingleFactory: pass self to JingleSession This avoids the JingleSession having to go via its GabbleConnection to get back to the JingleFactory which created it. commit 39b90872eb4939ba4b4262ababc7ae54743fa465 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-16 16:04:47 +0000 JingleContent: don't store a GabbleConnection. commit 41c4e316f12c7bbd285702ca74e3e4c2d7af6ee2 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-16 16:27:16 +0000 CallStream: don't grab Connection from JingleContent. commit 2863cdcee0c4d464a0f15f587e20f3a8f67c5014 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-16 16:03:06 +0000 MediaStream: don't grab Connection from JingleContent. Previously, GabbleMediaStream was getting to the JingleFactory for its content via the connection object stored by the content. Instead, go via the JingleSession stored by the content (so that we can stop storing the connection in the content). commit 679cfd663064781d1ca60d5ed8dae8cab85cb594 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-16 16:21:06 +0000 MediaStream: add a TpDBusDaemon property. Previously it was retrieved from the JingleContent, via the GabbleConnection it stores. But the Jingle code shouldn't know anything about Telepathy. commit 5410295679bb8ff4a0aad3eb38cc5717124fb5c5 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-16 15:41:11 +0000 JingleFactory: remove prototype for long-dead function. I removed _jingle_factory_unregister_session() way back in 2009 with commit fd410e9. commit a101f15d96f43c4a5c3da10d6acf485ad22bafa9 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-16 13:11:57 +0000 JingleSession: remove unused handle-repo-dynamic import. commit 570ad5f69f99f4eace580998d0e5df76f100e74f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-23 12:36:36 +0000 JingleInfo: don't crash when disconnecting before reply. For some reason I can't quite discern, this didn't crash before the previous patch but does afterwards. Oh well. Here's a fix. commit 51767ee2ec4423c00199fe4e0411f0b83d61aa2f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-16 11:21:40 +0000 Split google:jingleinfo code out from JingleFactory I am a terrible person and included a couple of changes in this which are not just moving code around: • When parsing STUN server info out of a jingle:info stanza, we no longer use GABBLE_PARAMS_DEFAULT_STUN_PORT as the default if the <server> element does not have a udp='' attribute. (Which seems uncontroversial: if the server erroneously leaves out that attribute, the chances of it happening to listen on GABBLE_PARAMS_DEFAULT_STUN_PORT is pretty low.) • Rather than using conn_util_send_iq_async(), we use wocky_porter_send_iq_async() plus wocky_stanza_extract_errors() to send the jingleinfo request. Wocky doesn't have something like conn_util_send_iq_async(), and this branch is really about removing Gabble dependencies from the Jingle code. commit f2b8df3800135b115bd801921a626bc7edde90e0 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-15 15:56:26 +0000 JingleFactory: store WockyPorter commit 90b7b2911a76ed9335d161d88fd6a7dd7a2ba41e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-15 15:42:21 +0000 gabble_jingle_session_send: drop callback arguments. Since nothing uses the weak_object argument any more, we can drop it, and hence stop using _gabble_connection_send_with_reply() in favour of wocky_porter_send_iq_async() directly. One less bit of Gabble inside the Jingle code! commit 72ea73343252d8ac6b792f9f4035cd511290a33d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-15 15:41:40 +0000 Send session-{initiate,accept} IQs using porter directly. This is the second and final place where the callback arguments to gabble_jingle_session_send() were used. commit a2e03f323dcb96d3043baef52a04eb41f22c6440 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-15 15:40:22 +0000 Content: use porter directly to send content-remove This is one of only two places which passes a callback to gabble_jingle_session_send(), so let's just spell it out. commit d039d1900888a828e2fc686c331cdfcaca8931ef Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-15 15:12:04 +0000 Session: tolerate being outlived by contents Never disconnecting these signals happens to be safe because GabbleJingleSession always holds the last reference to GabbleJingleContent, but it feels fragile. commit 91e8bc6b3a74cfdf2aaf685fc8883f3344c4e228 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-15 12:56:23 +0000 Jingle transports: stop using GabbleConnection commit 534bfa15133ead76a46a22f9f8e788c159fb2541 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-15 12:48:08 +0000 JingleSession: add and use factory accessor. commit 8080a905390ad9ca51059db15277930af6cc6bae Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-15 12:06:15 +0000 JingleSession: localize use of peer handle. Now that we only use a handle in one place, let's move everything to do with it there. commit 1dbbf70e672bcccef88c19b66ebb47bf4897a7fa Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-15 12:04:30 +0000 JingleSession: remove "peer" GObject property. commit bd654d2d812a1d5edae9796a20fca0b81dbfbaf7 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-15 12:02:32 +0000 JingleSession: remove get_peer_handle. The session unfortunately still uses the handle internally… commit a15ae7cf17528dd7a0d24386025cfe450c93cda2 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-15 11:59:50 +0000 media-factory: stop using gabble_jingle_session_get_peer_handle commit 7f40e47b980f917fa01d8d1f1012e4fb5a6f1559 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-15 11:54:10 +0000 ft-manager: stop using gabble_jingle_session_get_peer_handle commit b8ac1245d91828644f8ef37a9d107a12ae087275 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-14 18:00:52 +0000 Call: stop using gabble_jingle_session_get_peer_handle commit 363b2c580cb5500979020221b74e4889c59f93c2 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-07 11:55:42 +0000 MediaChannel: store peer's handle. This removes its dependency on GabbleJingleSession knowing about handles, and is less code. commit d884caf42e3e4608b5db84a6d1411c67aa9db925 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-03 17:38:09 +0100 MediaChannel: use gabble_jingle_session_get_peer_handle() Previously for some reason this was using g_object_get (..., "peer"). Calling a function instead makes it easier to see what needs changing. commit 819be150a66f99a1be524f31e0c8985aa613553d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-03 16:29:58 +0000 JingleSession: look up presence by WockyContact. commit ca9f3991776c9c277178f88c51941b6cad09800a Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-03 16:27:31 +0000 PresenceCache: add WockyContact-based lookup. commit c5328de7a89e2882036b64ba19a2c5bc3e8e70ce Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-07 19:26:01 +0000 util: add helper to fetch TpHandle for WockyContact commit 97d9c5ae3afc425eb8db91cbe83c37289e1baa5d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-16 15:21:34 +0000 JingleMediaRTP: use jingle_session_peer_has_cap() The body of content_has_cap() is basically identical to the body of gabble_jingle_session_peer_has_cap(), so let's delete the former. commit 63ade9c2226b72739b53039e26a31b483162aba5 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-16 15:15:56 +0000 JingleSession: rename _peer_has_quirk to _peer_has_cap There's nothing quirk-specific about the function. commit 8bd15af6cae7e90c97b81690a44bd2e43e1ab5e8 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-03 16:25:24 +0000 JingleFactory: stop dabbling in handles. commit bc53ec13c956191ab00cdf29236effac6d98651e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-03 16:18:11 +0000 JingleSession: remove defunct handle refcounting commit 2ad876aee650c4977f214a6d14b6852e164a6a82 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-03 16:15:34 +0000 JingleSession: grab resource from WockyResourceContact commit 439380da7a6a49f5e5255dcf691c24f3aec669ad Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-03 16:11:19 +0000 JingleSession: hold a WockyContact. commit b516378e41944381ccea6f29821ce7ac41a4cada Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-03 15:40:02 +0000 JingleFactory: exclude handle from session map keys The handle doesn't provide any additional information over the JID; it is a relic of when the format was "<handle>\n<resource>\n<session id>". commit 512c7492c2cb925e0260043a89170cda0907566c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-01 16:55:46 +0000 JingleSession: move TpHandle peer to private structure commit 1fc97cba57211fa8075c08ed63d882950b0d9451 Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2012-02-13 13:25:25 +0100 groups.py: test RenameGroup() This has been started as a regression test for fdo#45982 which turned to be a tp-glib bug. So we shouldn't merge this commit to master until we depend on a fixed tp-glib. commit f6eda33b8127fd18a81495c221fed4ac57eba37e Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2012-02-13 11:51:11 +0100 groups.py: factor out send_roster_push() https://bugs.freedesktop.org/show_bug.cgi?id=45982 commit 40283718ad184b014f4941a3126e5dfa0ed0640c Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2012-02-13 11:43:17 +0100 groups.py: factor out parse_roster_change_request() https://bugs.freedesktop.org/show_bug.cgi?id=45982 commit dcc73750bceb0e7b1bd865fde5744583cb75300c Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-02-21 21:59:58 +0000 Nano version commit 04c7829858da40f943363cfc3e61aa76f68c59ac Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-02-21 21:02:10 +0000 Distribute jingle/call_helper.py too commit c59a2f0b3612ba830154156279d0c6e03daf1e5c Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-02-21 20:31:25 +0000 Distribute headers more normally, and stop trying to distribute gabble/debug.h There is no gabble/debug.h. The only effect of putting a .h file in SOURCES is to get it included in the distribution tarball, so this wasn't visible until we tried to make a release, and apparently nobody runs distcheck any more or something. commit 920b112a30b0c0f86d150d5fa6aa07779f22c50a Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-02-21 19:44:54 +0000 Update telepathy.am from telepathy-glib 0.17.5 to fix out-of-tree releases commit 5cb548e7650846ae51142e8d9464de693775ffe0 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-02-21 19:41:30 +0000 Prepare 0.15.4 commit 8d7efad30c8633d6df4a0635eb7f78f2fa326e9a Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2012-02-21 16:56:09 +0100 accept-*-stream-tube.py: don't test with Credentials access control It fails on recent Linux because of Twisted; see fdo #45443. commit ce467279e0df62ef43ccf30a2724323f2290aac9 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-02-21 13:30:40 +0000 Update Wocky for #46379 commit b2bf243653dfd394648913cca94f379fc09bb71a Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2012-01-18 15:22:51 +0100 presence-cache: hardcode gtalk's bot caps Thanks Google for not implementing disco query on the bot... https://bugs.freedesktop.org/show_bug.cgi?id=44855 commit 205df6480b16d66cf74144b37b197251678a565d Merge: 3d6ba70 b40042c Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2012-02-21 10:18:53 +0100 Merge branch 'call1' into master+call1 I added the dependency on tp-glib 0.17.5 as it's required for Call1. Conflicts: src/Makefile.am commit 3d6ba70935c402e1e2b39716ca6014c22aa1520e Merge: 571037b 299ab6d Author: Olli Salli <olli.salli@collabora.co.uk> Date: 2012-02-20 15:49:04 +0200 Merge remote-tracking branch 'siraj/plugin-api-update' Reviewed-by: Olli Salli (oggis) <olli.salli@collabora.co.uk> commit b40042c598476bc14f578b1d121c14eb9da59c3e Merge: 2aff6d0 7a0e8d7 Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2012-02-20 10:51:16 +0100 Merge remote-tracking branch 'tester/call1-addcontent-direction' into call1 Conflicts: tests/twisted/jingle/call-dtmf.py commit 299ab6dbdd3fb0e290b57201c92bdf1b46b58aa3 Author: Siraj Razick <siraj.razick@collabora.co.uk> Date: 2012-02-17 16:16:00 -0500 test-plugin: Remove the duplicate TpBaseConnection Gabble and Salut Plugin API was updated to remove the dupliate TpBaseconnection from create_channel_managers. This patch updates the plugin-base to match the API change commit e651270a8a58da63e3f6fe739a6491942604cea5 Author: Siraj Razick <siraj.razick@collabora.co.uk> Date: 2012-02-17 15:35:49 -0500 plugins: Remove the dupliate TpBaseConnection from create_channel_managers create_channel_managers already passes a GabblePluginConnection which can be casted into TpBaseConnection. So removing the duplicate TpBaseConnection pointer from the API commit 2aff6d0ac4102835c5e125850eef6062011d910d Author: Olivier Crête <olivier.crete@collabora.com> Date: 2012-02-16 16:55:05 -0500 tests: the SendingTones signal now only happens when actually sending tones commit 9a90f92a6a4f50b33800ca2885efeb7785ad94ca Author: Olivier Crête <olivier.crete@collabora.com> Date: 2012-02-16 16:54:36 -0500 tests: Correct the order of the DTMFChangeRequested signal according to the spec commit 7a0e8d7f6edf24c96857a72af39940b555a1cf8c Author: Olivier Crête <olivier.crete@collabora.com> Date: 2012-02-16 16:19:28 -0500 Add a direction parameter to AddContent commit 491db173ad4da5ce4f5ff8d90d1a7ea20aed7785 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-02-14 18:54:37 -0500 tube-stream: subclass TpBaseChannel See also: exactly the same commit to GabbleTubeDBus. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit efbde4c8755e1bf55752ddb170d80a122f482afa Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-02-03 19:44:09 -0500 tube-dbus: subclass TpBaseChannel This one is complicated because the old GabbleTubeDBus handled both TargetHandleType as Contact *and* Room. TpBaseChannel sets the TargetHandleType per class so makes this hard. The easiest way to do this is to have a really dummy subclass for MUCs to change the TargetHandleType (and interfaces, to add Group). It would be nice in future to move the actual MUC stuff into GabbleMucTubeDbus, but that's for another day. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 571037bf029f2cd46f85a50d7d2b0892ae50be10 Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2012-02-09 18:39:19 +0100 Disable GLib deprecation warnings commit 8b537d968d0fb0047d9143ab05ce5a5bc2c4a1d7 Author: Alvaro Soliverez <alvaro.soliverez@collabora.co.uk> Date: 2012-02-09 08:13:53 -0300 Fixed android build after plugin API refactor Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=45824 commit e3ddd734e9c9c711ad44837b6d1f548718b0fbbf Merge: 359a1ae 07c6ad3 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2012-02-08 14:16:47 +0100 Merge remote-tracking branch 'nicolas/call1' into call1 commit 07c6ad32bbfc377c7fe09cb6e5bc8c0ce10ef464 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-02-08 14:00:47 +0100 Remove unwanted debug print in call-content-adding-removal commit ee5304dc3ed64d11670d53b9068a69ff1df598c2 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-02-08 14:00:27 +0100 Add missing call test into makefile list commit 2e543e74a65f9cb2da584f35d2348b6b57fabd78 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-02-08 11:25:20 +0100 Implement a call version of content-adding-removal commit daa6d7252861dbb9c7951330d413975573d45b89 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-02-08 11:24:57 +0100 Remove now unused advertise_call helper commit ba58cf5e5784e51c4c311d4c4a273bd383ee7173 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-02-08 11:24:33 +0100 Remove unused header in call-muc commit c33c3060db31e3d6578a00ea2a611181a760e062 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-02-08 11:24:16 +0100 Port call-hold-av test to CallTest commit 7f27e6ffcb7f67f5e3c624015f28082852fee9a5 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-02-08 11:24:05 +0100 Port call-hold-audio test to CallTest commit d3864c978337e6bff417b48e2f51844030b8365d Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-02-08 11:23:48 +0100 Port call-google-relay test to CallTest commit 9bd7bc624705ffc897225027cc47c2ed5ee0d339 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-02-08 11:23:24 +0100 Port call-dtmf test to CallTest commit 8e8501ce2b8d843b42254cb87e0f67d540006005 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-02-08 11:23:14 +0100 Port call-dtmf-no-audio test to CallTest commit 4da073f860d3d994b614d0c8bb33dceaa8e4f0a9 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-02-08 11:22:50 +0100 Remove uneeded header in call-codecoffer commit 729a6e979e0b302ccd3d582549118c3787bd3b7b Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-02-08 11:22:26 +0100 Port call-basics test to CallTest commit 00a76e3668c2c10ab2b3cceaf6cc4e1a3eb70c97 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-02-08 11:21:33 +0100 Add CallTest base class This base class can be use to greatly reduce Call test code size commit 0c9c11eee409aba15c58d9e91ab7d8f0eb1b7c7b Author: Olli Salli <ollisal@gmail.com> Date: 2012-02-07 18:37:47 +0200 Only pass -fPIC cflag to submodules if compiler doesn't warn or error from it Reviewed-by: Siraj Razick <siraj.razick@collabora.co.uk> commit 5c780cf06292a80271bbe5a35d5d10a9eba5e8d2 Author: Olli Salli <ollisal@gmail.com> Date: 2012-02-07 15:28:26 +0200 Update NEWS commit 5ed3540f9321fed01df2729a37477f219ab1b9cb Author: Olli Salli <ollisal@gmail.com> Date: 2012-02-07 15:02:14 +0200 Compile submodules with -fPIC to fix gabble-plugins.so link on linux/x86_64 Reviewed-by: Simon McVittie (smcv) <simon.mcvittie@collabora.co.uk> commit 415706b45a63915dcd442fab7364a6d9ade1d79c Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-02-07 13:40:11 +0100 call: Fix last content remove special case when the last content in a session is removed, the XEP says the content-remove signal must be replaced with session-terminated. This case is handled in gabble_jingle_session_remove_content, but call was bypassing it by using gabble_jingle_content_remove() directly. commit 82d8ca3198eef823c7bfca836e537926ebc49149 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-02-07 13:38:20 +0100 Add CallStreamComponent enum in constants commit 0e697dc4f035d78efc27a652efa8c5c3bdaf52a2 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-02-07 13:37:59 +0100 Add CallStateChangeReason enum in constants commit 78b6994fab54d317f77bbfdcfc47446ed4ba3701 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-02-07 13:37:21 +0100 jingle: Fix comment typo commit 359a1ae278a9c33dd0bc41394912166ac2b5ecda Merge: e073905 b33adc6 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-06 17:47:58 +0000 Merge branch 'master' into call1 Conflicts: src/Makefile.am For reasons I don't fully understand (presumably headers moving around a bit?) I had to add includes of <telepathy-glib/gtypes.h> or <telepathy-glib/interfaces.h> to: • src/call-content.c • src/private-tubes-factory.c • src/protocol.c • src/util.c But otherwise this has been an uneventful merge! commit 0c0dccb8135ca48e4222a408043dc93b3fcf4a98 Author: Siraj Razick <siraj.razick@collabora.co.uk> Date: 2012-01-25 16:32:32 -0500 Windows specfic changes to produce plugins as dll's Using -module doesn't produce .dll files when compiling for windows These changes enable us to output .dll files for plugins. https://bugs.freedesktop.org/show_bug.cgi?id=44649 commit f54da139bb483fce675d6f11bfc000ec2d6732aa Author: Siraj Razick <siraj.razick@collabora.co.uk> Date: 2012-01-13 11:32:48 -0500 fd.o#44649 - Gabble plugin API symbols should be factored out to a separate library This patch refactors gabble connection by introducing a new GInterface which the plugins will link agaist. And GabbleConnection implements the new Interface. https://bugs.freedesktop.org/show_bug.cgi?id=44649 commit bb63a668664a2003c966b7e3d9806c98d0875bf5 Author: Siraj Razick <siraj.razick@collabora.co.uk> Date: 2012-02-06 11:02:19 -0500 Change the plugin API to create_sidecar_async and create_sidecar_finish All gabble plugins should implement these two methods hereafter. This patch also updates all the internal plugins to use this new API. https://bugs.freedesktop.org/show_bug.cgi?id=44331 commit b33adc647bf4e6dc75efba1abd74380d4bbb18d1 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-06 15:22:43 +0000 Update Wocky snapshot for DEBUG_* namespacing commit 87841786d0ed60fb093c3343e185805db500de7a Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-06 14:40:36 +0000 NEWS for single-header Wocky. commit ee48ee9a8c440bbd0c1efa49fc9cd346a92883d3 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-01 16:09:56 +0000 Update Wocky snapshot for One Big Header. https://bugs.freedesktop.org/show_bug.cgi?id=27489 commit 3e0c8b55b81207f7842495b4ab9f59f0de655ae3 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-02-03 14:31:13 -0500 ft-channel: subclass TpBaseChannel Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit ab745cbdead64a313fe3e8859cec5bf7c4382dc9 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-02-01 16:07:25 -0500 Revert "Merge remote-tracking branch 'siraj/plugin-api-change'" This reverts commit bf805ba0b2ecced81e5c2830a79d021a42da91a7, reversing changes made to 1296a2f5ce46e77787ca42eadb1c2ca4a957a09b. commit 1d41beb99b03f828fd204e6e18fa7499360937b9 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-02-01 16:07:06 -0500 Revert "Merge remote-tracking branch 'siraj/windows-compile-fix'" This reverts commit a687785628216f8f73c699096e9aae4a07b811c6, reversing changes made to bf805ba0b2ecced81e5c2830a79d021a42da91a7. commit a687785628216f8f73c699096e9aae4a07b811c6 Merge: bf805ba e4cccf0 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-02-01 13:54:00 -0500 Merge remote-tracking branch 'siraj/windows-compile-fix' Conflicts: lib/loudmouth/Makefile.am plugins/console.c src/Makefile.am src/connection.c src/error.c src/plugin-loader.c src/plugin.c Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit bf805ba0b2ecced81e5c2830a79d021a42da91a7 Merge: 1296a2f 026e84f Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2012-02-01 13:40:56 -0500 Merge remote-tracking branch 'siraj/plugin-api-change' Conflicts: lib/loudmouth/Makefile.am Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit e4cccf0a604c7cdf1107aa9b5d9cdaa996bcc702 Author: Siraj Razick <siraj.razick@collabora.co.uk> Date: 2012-01-25 16:32:32 -0500 Windows specfic changes to produce plugins as dll's Using -module doesn't produce .dll files when compiling for windows These changes enable us to output .dll files for plugins. https://bugs.freedesktop.org/show_bug.cgi?id=44649 commit 1296a2f5ce46e77787ca42eadb1c2ca4a957a09b Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-01 12:49:04 +0000 NEWS for <presence type=error/> improvement commit e7fbb73258ab0eb00eb239f277ae5ad4ed0f9ee5 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-01 11:16:51 +0000 Presence: show better error status messages. When you get <presence type='error'>, any <status/> element in the presence is an echo of a stanza you sent out. So the message in that is not the contact's presence: it's either your status, or maybe the message you sent with a subscription request, depending on whether we got the <presence type='error'/> for a roster contact or someone we tried to subscribe to. So instead, I think we should use the text of the error (if any) as the status for such contacts, falling back to the error element name if the server is unkind and doesn't include an error message. Yes, this means strings will show up in the UI in the server's locale, but this is hardly news. https://bugs.freedesktop.org/show_bug.cgi?id=45491 Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk> commit cdcbaaa7a6e2b1056be96dda77d8a8363f78539d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-01 11:30:01 +0000 NEWS for deLoudmouthing etc. commit de0f8a21f82234e1fcc2a84994b07dc2bf1cc45a Merge: fbf798b c0a4dca Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-01 11:22:50 +0000 Merge branch 'unhandled-iqs' Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=34975 Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk> Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit fbf798b5fce94bc932fde45bc5579652acb05cd7 Merge: 281673e 6c68414 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-02-01 11:21:36 +0000 Merge branch 'node-iter-get-child-with-namespace' Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=33911 Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk> commit c0a4dca930b1e43d716df1295545fbf1856dae1a Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-31 15:15:04 +0000 send_with_reply: remove stale reference to iq_unknown_cb commit d8feabf6ef67e5b7e5b0a4d01ef983bea877f0b5 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-31 17:15:28 +0000 Connection: rely on Wocky replying to unhandled IQs. https://bugs.freedesktop.org/show_bug.cgi?id=34975 commit 6c684143294c9dc2becc3af0887f907c760bf8af Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-30 17:29:09 +0000 conn-olpc: give _get_child_with_namespace a clearer name. commit d8a2087662fe895eef24296fab7755c5b5ead197 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-30 17:27:17 +0000 conn-olpc: adopt lm_message_node_get_child_with_namespace This is now only used within this code, and I am too scared of breaking code I know nothing about to stop using it here too, so I'm just going to leave it here, probably with a new name. commit 7b258fc5ea423927878cd63e6f0a01ffe11d2869 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-30 17:23:32 +0000 conn-aliasing: use <item> passed to ::changed handler. commit 821409f5203dc6b640ef6e0c00e0c343facc3a82 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-30 17:21:30 +0000 Update Wocky submodule for PepService changes This new snapshot changes WockyPepService to provide a pointer to the <item/> node in wocky_pep_service_get_finish() and WockyPepService::changed. This commit only updates conn-location.c to actually take advantage of it, but soon… commit 8601d29953e44416e5413c8e8053f980397f04b3 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-30 15:26:01 +0000 location: stop using lm_message_node_get_child_with_namespace() The test change illustrates the problem with using lm_message_node_get_child_with_namespace(): the test suite was sending a broken stanza, and we still accepted it. It should have sent: <iq type=result> <pubsub> <items> <item> <geoloc> But instead it sent: <iq type=result> <pubsub> <items> <item> <geoloc> This patch would be smaller if <https://bugs.freedesktop.org/show_bug.cgi?id=45400> were fixed. commit 3403ab38582559b2293feb17f69f2df90e6ed229 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-30 14:58:32 +0000 tubes: stop using lm_message_node_get_child_with_namespace These cases weren't completely obvious to me, being unfamiliar with the tubes protocol. But they all wanted to be wocky_node_get_child_ns() too, really. commit 603aeb65562002ca1aa6273acf8580f88486e345 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-30 14:31:46 +0000 ft-channel: spell out finding <si><file> node. commit aa11a7ed781c48ffda4d00f303776603d2f6ada5 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-28 10:47:32 +0000 _grab_nickname: use wocky_node_get_child_ns This is called on a variety of nodes from different stanza types, but in all cases (as far as I can tell) the <nick/> element is a direct child of 'node'. commit 2db196ba241a2a22fd07ef6aa97ca9b559c26934 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-28 10:32:42 +0000 presence: explicitly hunt for privacy list node. commit bd3c28af3b96bf73256e8e0fc42470f0cf43039e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-28 10:17:54 +0000 Replace trivial uses of lm_message_node_get_child_with_namespace These are the cases where it was relatively quickly apparent to me that we only needed a direct child, not a deeper descendent. commit 5d91fadfb646437363c9f1e60f1deb279b09e180 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-28 09:59:21 +0000 util: remove node_iter commit 25980c6c7f70e2d3ff7d012b8e3a6a7cbed644e8 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-28 09:58:13 +0000 bytestream-socks5: remove degenerate node_iter use. commit 12a2a93c80a33723fdc6bfc031850b20e462b1b6 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-28 09:56:00 +0000 disco: move to WockyNodeIter commit 582a4e1fa932a81397c9b47992ceec673fe62419 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-28 09:51:34 +0000 conn-*: move to WockyNodeIter commit 48175abc011072b8c4e5fb4c01342f71ab33a982 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-28 09:50:53 +0000 conn-olpc: use WockyNodeIter The huge change is just reindenting the body of that loop inside an if block. There's no clean way to initialize a WockyNodeIter to be empty if your starting node is NULL. commit 50d3ef27080c66f95fa254f7c39fcc1f2c8b6d4b Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-28 09:42:59 +0000 tubes: move to WockyNodeIter commit d61893c1abc031c9179a6b7565ba5d55075d1b8e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-28 09:41:08 +0000 muc: move to WockyNodeIter commit 5a7f08a3c78e8f4e33d3ddcf0a4450ae69cb92fd Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-28 09:38:37 +0000 roster: move to WockyNodeIter commit 1c53458f88e5aa97b47640a58e41b1db46b0092b Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-28 09:35:58 +0000 vcard-manager: move to WockyNodeIter commit ca262307fcbd3cf9bf6cd5b6e2268fcfa4badac4 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-28 09:33:20 +0000 Connection: move to WockyNodeIter commit c1d1d52bb4ab166a4df0ac5c46e46257698db5f0 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 23:40:10 +0000 search: move to WockyNodeIter In one place, I actually replaced a confusing use of NodeIter with wocky_node_get_content_from_child(). I think the result is much clearer. commit dd33dbffeefd72d3db74569d59f4975001e554d9 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 23:37:17 +0000 Jingle: migrate to WockyNodeIter commit c2c973e622f77d30a3d5cecf8ca2308dcb291b51 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 23:29:19 +0000 bytestream-factory: move to WockyNodeIter commit c7ee7f1ea0d9f0898679f892ce42a583967108e0 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 22:55:40 +0000 util: remove unused wocky_node_get_attribute_with_namespace commit 051d07d18a364c054d6f5ff50c8636281198fba2 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 22:54:46 +0000 disco: use wocky_node_get_child_ns commit 32ab1ebc7d68611187a15f545f82af8dd2399c0b Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 22:53:25 +0000 search-channel: stop using lm_message_node_get_child_with_namespace In all cases, we wanted a direct child. commit 9dc5bfd7a376277180cecf9a77cf0882d3e6d292 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 22:53:10 +0000 message-util: stop using lm_message_node_get_child_with_namespace In every case, we wanted a direct child of some node. commit 383a34f1b2c2405c9b940f0024fe9ca92754dee7 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 22:52:55 +0000 util: explain why lm_message_node_get_child_with_namespace is bad commit 281673e30aa5012ec3425a59fddcb24d8c2ac18b Merge: c2279a6 14732bf Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-31 17:18:13 +0000 Merge branch 'quietmouth' commit c2279a6b7dda2060e198d5407f22228d2c3be9ed Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-01-26 19:00:24 +0000 Fix a typo commit 5d7c87b1c753558c8c2525623a88103c1084fe2a Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-01-31 11:25:51 +0000 tubetestutil: clear list in a way that doesn't make it a local variable commit 2a2893a89248f22af2894cc2c6555da0ec365ed4 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2012-01-31 11:25:34 +0000 Update Wocky for fd.o #43992 commit f1e67f8d9a348aac23821878779f7a45dad9719c Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-01-30 16:27:37 -0500 Cleanup twisted tests import commit 2b5dbb4be2fa9890f332368d21cd92dd4dda67d9 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-12-21 12:37:02 +0000 tubetestutil: use temporary files as unix socket paths This is all an attempt to make the unix socket path shorter. Fixes: fd.o#43981 Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit e0739058a22dae127e5410fd8ab4fb5dc2d49ad1 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2012-01-30 16:08:54 +0000 Disable call-muc.py tests that isn't ported commit 4fe564149c374a2b30a4bfb8467b5d41f1fd4816 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2012-01-30 16:05:34 +0000 Make call-muc-re-re-request.py test pass commit 14732bf5081f20aa314c3530e4c6a38155f75a62 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-28 12:55:34 +0000 disco: don't crash on replies whose <query/> is missing This is a regression from the BYE-BYE-LOUDMOUTH branch. The logic in request_reply_cb is meant to be: • if the stanza is an error, pass (with 'err' having been filled in); • else, if there is no <query/> node in the reply, set 'err' to that effect; • now call the callback; it is guaranteed that if err is NULL, query_node is not NULL. I inverted the check for the return value of wocky_stanza_extract_errors(): it returns TRUE if 'reply_msg' was an error, not FALSE. commit a7c0fccb5bbf66e05a0062a3d7056b6d1c57bd9a Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 22:08:56 +0000 Remove vestigial Loudmouth headers and build system commit fb5672370cad426fa90a4906824704a4f5699cc9 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 21:56:19 +0000 Delete LmConnection API. This is it! There is now nothing left but a build system and some empty headers. The last functional vestige was the GCancellable used in _gabble_connection_send_with_reply(), which I basically just moved to GabbleConnection. That function should really die as well, but I'll leave that for another lifetime. commit 9fed5574a65c7d7318cd1c86e7e9ffc741139966 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 21:39:44 +0000 Remove LmHandlerResult The callback type for _gabble_connection_send_with_reply returned one of these. All instances, bar two, returned LM_HANDLER_RESULT_REMOVE_MESSAGE, which makes sense, because if you send an IQ you had better be prepared to handle the reply. When I removed lm_connection_send_with_reply(), I stopped _gabble_connection_send_with_reply() paying attention to the return value, with no apparent ill effects. The two which returned LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS were: • the disco pipeline's reply handler, in the case where the request is no longer in the pipeline (such as in a timeout). I checked, and as far as I can tell nothing is trying to scrape any information out of zombie disco replies. • the request pipeline's reply handler, in the same case. I couldn't be bothered to check for this, but I don't think it will pose any ill effects because normally the handler is the highest-priority callback, so anyone trying to catch these would not catch the ones which were not cancelled… which seems unlikely. commit cea17f274de06f7a7db6bcc68fa10cbdc083feb6 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 21:38:03 +0000 conn-olpc: remove an orphaned prototype commit 7319d124c880f0d8858ac137768bddd5c6ebc869 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 21:24:26 +0000 Remove LmMessageHandler API. LmHandlerResult shows up in _gabble_connection_send_with_reply(), so we can't ditch that just yet. commit 5881a6456bad0b47dba58134dfabd7f766b2cd17 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 21:18:43 +0000 connect/torture: skip if $REALLY_TORTURE is unset commit 0e1bb7601788afb19dea55e3fae5d4243bda4898 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 21:18:35 +0000 BytestreamFactory: stop using LmMessageHandler commit 9a567a7cf16759f8f692cf827211db81a76b2b1e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 20:46:25 +0000 PrivateTubesFactory: stop using LmMessageHandler commit afef96c60473b99b0fee8c3fbd7d777a3c9e4883 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 20:31:52 +0000 PresenceCache: use wocky_node_get_content_from_child This shortens some code a bit. commit 0bb2b04020b63e760f919f7b9c725b878f4df419 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 20:29:17 +0000 PresenceCache: remove duplicated code. commit 6d80ecf861640a76297ba8963027bc280931307f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 20:27:36 +0000 PresenceCache: refactor looking for decloak requests This was a little bit intertwingled, and long functions offend me. commit 7ab3e8a878e79a84c3c13d2a03e3bfe4148d2032 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 20:23:05 +0000 PresenceCache: stop using LmMessageHandler commit b76a9f08c6d9b6a410a1fda567ec81316dce47a8 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 19:34:37 +0000 conn-presence: stop using LmMessageHandler commit 8ee8a2027a38b67448eb56720baac842c6d218a1 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 19:21:21 +0000 MucFactory: stop using LmMessageHandler commit f676f5045909587dbf612a19ef35e6188f6308ca Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 18:41:46 +0000 IMFactory: stop using LmMessageHandler. commit 62303c98f15f8e23e3bfa0a03e7ba109de0ac653 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 18:13:51 +0000 Remove lm-message.[ch] commit 89f7b1a1daafe6b9159c5cb42fb0c7fb7acf6871 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 18:08:32 +0000 Delete LmMessage{,Type,SubType} typedefs commit 6e3d12a641453d1a00b5271b3094edb7a6845a6c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 18:04:40 +0000 Remove lm_message_new[_with_subtype] commit 3c0a4208c89e0f2fc2acbf2da8a4563386da7870 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 17:43:07 +0000 Remove lm_message_get_[sub_]type. Wocky is a little less convenient here, but wocky_stanza_extract_errors() comes to the rescue. commit ee42d5f8329229aa8b7ed34cc96b4b888f60f307 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 17:40:48 +0000 Remove lm_connection_send_with_reply This basically inlines the call to wocky_porter_send_iq_async() in _gabble_connection_send_with_reply(), and removes a layer of indirection in calling the callback. commit 6ce72d766d274ab84c00b8533ae7f665067ea2e2 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 17:03:45 +0000 test-parse-message: g_assert_*-ify commit 89f7ea25ae4d0afdfc807747b543392a27a89220 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 17:01:26 +0000 test-parse-message: GTestify commit d89833fb55289705c6791a7a07a9c662b8a85df9 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 16:46:40 +0000 Remove duplicated AMP rules. I noticed this duplication while deleting lm_message_build and thought it might be better moved to some random place. commit 722536a79ae18e6bc060e97a7a520e89a13b371c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 16:20:45 +0000 Remove lm_message_get_node() It's completely unused! commit a615d8380375c3d5266c1b17e58488868fda23fb Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 16:16:35 +0000 Expunge lm_message_node_get_name() commit d1758a79e0f9287fed177574b5c39e324128b15a Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-27 15:55:09 +0000 Remove lm_message_build[_with_subtype] The build specs aren't *quite* compatible. lm_message_build()'s '(' accepted two arguments: tag name, and content (usually ""). So: '(', "foo", "" becomes '(', "foo" '(', "foo", "bar" becomes '(', "foo", '$', "bar" I didn't actually do this with sed as a result. commit af1a389766cad96903932f9231219ca5e80d5f98 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-01-26 16:04:59 -0500 Port google-relay test to call1 commit 89ccb036c015a2988b282198f74ec7ad5fbd51c9 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-01-26 16:04:26 -0500 Move new check_and_accept_offer to callutils commit a6ffa908693db3183a274e133c5cbdb37eb60d58 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-01-26 16:03:38 -0500 Update CALL_STREAM_TRANSPORT enum to new API Add missing and renamed to what is in the spec. commit 84403989062485a3ef0c5e131b8e11f47d964104 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-26 18:56:15 +0000 Correct NODE_DEBUG's first argument type. My previous patch was wrong. I didn't compile it. Sorry. commit bc55f4cd2ccba08642b39dcdb576dd3df05cd901 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-26 18:05:13 +0000 debug: remove leftover reference to LmMessageNode This is only on the --disable-debug path. commit 8cd1fe08bee1f31cd05b7fee5629496e0d2f806e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-26 17:03:26 +0000 Update Wocky submodule Something has gone screwy here. This supposedly only adds a single new commit: commit 44a326f3ab2aafea7a78df6ac75e9b4c014fe0e8 Author: Siraj Razick <siraj.razick@collabora.co.uk> Date: Wed Dec 21 12:29:29 2011 -0500 Build fixes for Windows These changes enables us to cross-compile wocky for windows with mingw32 but the buildbots are confused and are using a ridiculously old snapshot. commit 450c82611c7921c6d0711bfa3170a6f1cc70f336 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-26 14:25:33 +0000 Expunge lm_message_ref and lm_message_unref. And also a couple of uses of lm_message_get_node(). commit c3e951a71acd69f2c3c3196675e2b2979e8a9a4a Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-26 14:14:36 +0000 Jingle*: (mostly) de-Loudmouth-ify The only remaining reference is a reference to LmHandlerResult forced upon us by _gabble_connection_send_with_reply(). I'm sure we can deal with that later. commit e142bebe3e112d715af2b4784b24730eb9c310a0 Merge: a2a603b 035a6b0 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2012-01-26 13:09:47 +0000 Merge branch 'master' into BYE-BYE-LOUDMOUTH Conflicts: src/connection.c src/connection.h src/ft-manager.c src/jingle-content.c src/jingle-factory.c src/jingle-session.c src/message-util.c src/muc-channel.c src/muc-channel.h commit f8e208971a06a1f2b911066014900437559dd758 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-01-25 17:38:42 -0500 call-test: Add advertise_call utility commit debda34210cf48069c08ac8395592ef00f2f0ba6 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-01-25 17:16:08 -0500 call-test: Use callutils check_state instead of a copy commit e5bf54da204ff67396ee77835b25c8aea77c198c Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-01-25 17:15:13 -0500 call-test: Remove unused exec_test import commit 3323f531d06bbaf9494c5b6bc56a8f14d68f3900 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-01-25 16:59:49 -0500 call: Connect signals in sync constructor The sync constructor was not connecting to jingle session "terminate" and "content-removed" signal. This was causing incoming call to not send the ENDED state. commit 4214f06caf4c809958e6cd33cd730f76c52bda49 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-01-25 16:58:12 -0500 call: Add trace on jingle session terminate commit d3beae79aadab2e0adfc206082068fc6689ff290 Author: Siraj Razick <siraj.razick@collabora.co.uk> Date: 2012-01-13 11:32:48 -0500 fd.o#44649 - Gabble plugin API symbols should be factored out to a separate library This patch refactors gabble connection by introducing a new GInterface which the plugins will link agaist. And GabbleConnection implements the new Interface. https://bugs.freedesktop.org/show_bug.cgi?id=44649 commit 93943569220656d2939c96f50515da5ed7877af6 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2012-01-20 20:23:47 -0500 Add the other reason from Jingle to the Call channel termination commit 7a207a7a42a6c6fe9737d9ce0032bab820c4ce58 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-01-20 15:29:55 -0500 Add Call1 version of hold-av test commit 8bf0743da622c2adf7a93f82c9a86dd28d277e3b Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-01-20 15:29:06 -0500 Stream failure brings call to pending_hold state commit 123a0d473ad742c85f6d5242c1009403e7f222ba Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-01-16 15:41:40 -0500 Add no-audio content DTMF call This test simply check that DTMF method does not exist on non-audio content object. commit 9ee76cdc02c550850c8490ddc97dc0c0fa24c38a Author: Siraj Razick <siraj.razick@collabora.co.uk> Date: 2012-01-06 16:32:47 -0500 Change the plugin API to create_sidecar_async and create_sidecar_finish All gabble plugins should implement these two methods hereafter. This patch also updates all the internal plugins to use this new API https://bugs.freedesktop.org/show_bug.cgi?id=44331 commit 026e84f10bbfa52f813d30d95b0efbd2ec7a5228 Author: Siraj Razick <siraj.razick@collabora.co.uk> Date: 2012-01-06 16:32:47 -0500 Change the plugin API to create_sidecar_async and create_sidecar_finish All gabble plugins should implement these two methods hereafter. This patch also updates all the internal plugins to use this new API https://bugs.freedesktop.org/show_bug.cgi?id=44331 commit b642a5dab5535bb3787529de26b6d69be98210e0 Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-01-12 13:56:51 +0100 call-channel: Fix build warning commit 8c9c9fe6e67066a3208371734be54fa1e264af09 Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk> Date: 2012-01-11 17:35:20 -0500 Check that DefferedTones is reset when sending new tones commit 47994713103ae137ca86810e0f032dce3418120c Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk> Date: 2012-01-11 17:34:35 -0500 Check that CurrentlySendingTones is triggered commit 606d64610704dcdbfbc80e56a2c4e5f032350091 Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk> Date: 2012-01-11 16:28:39 -0500 Test deferred tones in Call1 commit 0cb44ec85906f4ea21c55c9ead449a386eacbcd4 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-01-10 13:03:17 -0500 Fix reason when a call is rejected commit 635ee7183038d7bec1b10f2a56b41fbf087dcbef Author: Olivier Crête <olivier.crete@collabora.com> Date: 2012-01-06 20:24:49 -0500 Add fixme to remember to handle rejected codecs commit ca0726474896e546f40f251d4a25ecbbb98bbb0a Author: Olivier Crête <olivier.crete@collabora.com> Date: 2012-01-06 15:51:49 -0500 Set the Call termination reason commit 9aa42222621917e040f778d8ecea7f9f1663de76 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2012-01-05 20:17:55 -0500 Port DTMF test to recent Call commit 25dce42e3b0786d84ef017648ceb31268702b680 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2012-01-05 19:06:17 -0500 Update candidate capitalisation in tests too commit 75826de1194146ddc7c9a3e1677d6fcbe37dcb13 Author: Nicolas Dufresne <nicolas.dufresne@collabora.com> Date: 2012-01-04 16:48:25 -0500 Candidate info names are no longer capitalised commit c253cfd561152df8a7f12459c3787d15a738d823 Author: Xavier Claessens <xavier.claessens@collabora.co.uk> Date: 2012-01-03 17:06:22 +0100 Fix build warning commit c5dea13a289fbaa29068a834252c9b8a29b02193 Author: Xavier Claessens <xclaesse@gmail.com> Date: 2011-12-19 11:48:57 +0100 GabbleMediaFactory: Use TP_PROP_ where appropriate commit dd0f6115ada3ad038f383662e02805f2641cfa9e Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-12-31 02:25:47 -0500 Add test for Hold in Call commit 3a1a8fc0e062ac268ed54a2b56b70062ed4e2195 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-12-30 17:14:15 -0500 Implement local hold for Call commit b555f952361fce1e037e67be2d90770eec5ffd02 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-12-29 22:49:45 -0500 Update to new tp-glib api for setting the local sending state commit 47cc822f25c4100fd91758ee34a49a9edc31f9c2 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-12-28 01:18:13 -0500 Add test for the remote side changing the direction commit 20483522b56a08c5fe01b1012db89c8e7239b850 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-12-27 03:06:59 -0500 Add test for pending states when the other side asks to send commit 8fe2c028aedd1b9daae79546cbb07cb9e1b50759 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-12-27 01:46:21 -0500 Implement per-dialect CanRequestReceiving Also add unit test for it commit db3883574a31350605f03555616be01ef0bfe3b3 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-12-27 00:54:18 -0500 Fix Request receiving Also add tests commit f4c69b786b2c33930f7b6625a161c1b6b4013a2a Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-12-26 23:08:29 -0500 Add test for endpoint state changes caused by reconnection commit b50e272f22ca8c8f94b00ec273beef36ea1c0aa1 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-12-26 21:06:40 -0500 Update codec offer test for updated spec commit 80f2cc4c085c1a7e76150f939f2c65fac06de370 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-12-26 20:59:03 -0500 Update to correctly set the local and remote sending states Also update the unit tests and move some work to the base class commit 3940ed863349a6f1ab6be6764b79c00cf303798a Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-12-23 15:03:39 -0500 Implement request_receiving using the base class commit 6af603c3edcfdcd0f836ec34fc720f50b90a73e4 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-12-23 15:03:01 -0500 Port to BaseMediaCallChannel commit a8c774fcd09e4298ade48982112ac0cc69b89321 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-12-23 11:54:22 -0500 Export the ICE credentials from the transport to the stream commit 10d618e5098ec0b5a8baada8c1dec67428382797 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-12-13 17:55:05 -0500 WIP: Half port DTMF test commit e97ab16a643a7a45c9e2e09d28777218759436b2 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-12-13 17:47:33 -0500 Restore flags for StreamedMedia tests commit 591755cc3fcb5fe257eca33462cddef26aef71a2 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-12-13 17:42:36 -0500 Port the codec offer test commit 395bb80683f5830326db422f9ed9ee3123c30ab1 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-12-13 16:02:24 -0500 Listen to endpoint state change notification commit b25eb1fe6845f72bf2f4fb991c09cbdd8d9ed671 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-12-13 15:47:45 -0500 Update tests to new Call1 spec commit 0009ecf2483e1ddb935266a4a8d03c31ca5ddb36 Author: Xavier Claessens <xclaesse@gmail.com> Date: 2011-12-09 15:30:57 +0100 WIP: port unit tests to Call1 commit e946c179c33cac58de14443ed877cbd829e8ed04 Author: Xavier Claessens <xclaesse@gmail.com> Date: 2011-11-28 14:23:17 +0100 Replace tp-yell with tp-glib's Call1 API commit ab43a9f94d0f304003b581a67c7dff6391917b5b Author: Siraj Razick <siraj.razick@collabora.co.uk> Date: 2011-12-30 17:14:00 -0500 build libgabble-convenience as a .dll for windows when building 3rd part plugins for gabble, all the symbols as to be defined at link time, not at run time. to solve this problem libgabble-convenience has to compiled as libgabble-runtime.dll. also by this patch we avoid static linking telepath-gabble.exe commit 035a6b0a6e8ce1787abf2583bb918436282026fe Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2011-12-22 16:02:51 +0100 telepathy-gabble-xmpp-console: no need to import pygtk In gobject-introspection we trust. https://bugs.freedesktop.org/show_bug.cgi?id=44056 commit 748caada6a36c26e7b8752a39138b4eaf42296db Author: Siraj Razick <siraj.razick@collabora.co.uk> Date: 2012-01-04 05:10:37 -0500 Use ";" as the seperator on windows. With this fix, gabble can locate the plugin directory properly on Windows commit b5bc31a5084e05d7e4251a37f628f7835928ab1c Author: Siraj Razick <siraj.razick@collabora.co.uk> Date: 2012-01-02 13:12:08 -0500 Make gabble cross compile with mingw32 The patch provides the changes required to make gabble compile under mingw32. - Index is replaced with strchr since index is deprecated and not included in mingw32 sdk - D_WIN32_WINNT=0x0501 is defined to make getnameinfo work - And other compile fixes commit 3cdfbe659bbe3a7e217486c2b0a957880b3c24ea Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-12-22 12:04:53 -0200 Update NEWS commit 5df4b3abb3909f4cdac2f88580acba762f7b07d1 Merge: dfb062f e1524fd Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-12-22 12:02:40 -0200 Merge branch 'ft-optional' Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit dfb062f2a580d431713742904791627c2044155d Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2011-12-22 11:48:37 +0000 Start on version 0.15.4 commit bf29681bd6ac87c63b1ce6624d1efc58957af920 Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2011-12-22 10:59:49 +0000 version 0.15.3 commit 3e7bb6cedcca537126422799a33a11d95bc8808a Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2011-12-22 10:43:24 +0000 NEWS: add reference to fd.o#43891 commit 845816e8c451bd18412b4c616ce549863689714a Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2011-12-22 10:33:05 +0000 Update wocky to fix wocky_data_form_set_type() https://bugs.freedesktop.org/show_bug.cgi?id=43891 commit ead4381be6e3ab46d454458d54c86fc98c4fe61d Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-12-21 09:28:06 +0000 start on version 0.15.3 Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit ac5b2184c9b89f527d8ce4ee83484fde084f8499 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-12-21 09:15:53 +0000 version 0.15.2 Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit e1524fd2acb29611f8e9055e227b86c4809b546f Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-12-20 21:40:36 -0200 Add configure option to disable file transfer support. commit 109ae37c08613b9d1b240ab325f993d466a9be55 Author: Xavier Claessens <xclaesse@gmail.com> Date: 2011-12-20 15:09:27 +0100 Update wocky commit to fix build warnings commit 09cae896ad821071e7d1fcfc69503deeefb57534 Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2011-12-16 16:02:01 +0000 Compute the caps verification string correctly with dataforms in plugins https://bugs.freedesktop.org/show_bug.cgi?id=43889 commit a17ea171acb4847ada48782a8b57feff78aee123 Author: Alvaro Soliverez <alvaro.soliverez@collabora.co.uk> Date: 2011-12-14 17:00:11 -0300 Added missing build flag commit 2348d1d320bd99560427875de45351691c018274 Author: Xavier Claessens <xclaesse@gmail.com> Date: 2011-12-14 12:33:48 +0100 Fix the build with glib 2.32 deprecated symbols commit e61ea6b4baa4080e072f69699bc876c762797b5d Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2011-12-07 13:19:22 +0000 Add gabble_connection_add_sidecar_own_caps_full() with dataforms https://bugs.freedesktop.org/show_bug.cgi?id=43588 commit a7740569c39532c1e508ff707ddecadbcd5acd0b Author: Sjoerd Simons <sjoerd.simons@collabora.co.uk> Date: 2011-11-29 12:58:32 +0100 Update wocky snapshot to fix issues with non-character data commit 956da5d8d2df4aad54e44315ae9df4b54a3ec0fc Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-24 16:48:18 +0000 Rhythm is a dancer. commit f7555112d4d9fb17709befd5068a4fdac7365886 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-24 16:17:58 +0000 Version 0.15.1 commit 4284793d64274349ced1d4c0ceb6f69cb136425d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-24 16:14:49 +0000 NEWS for 0.15.1 commit 7d6e1fa81492520fcd020fe6a1ab4b0a8a1e85ef Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-24 15:32:29 +0000 Knock .DRAFT off Conn.I.Addressing. I've taken the executive decision to turn it into a version number, so that we don't force ourselves to break compatibility if we decide the interface is perfect. commit 05e7ea30f2588a098ad52c1969ca3f25795e7dba Merge: f467b8c 9e4bd73 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-24 15:25:21 +0000 Merge remote-tracking branch 'andrunko/fb-addressing' Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=41789> commit f467b8cd4dffca20516be46d6da58f0bb4868df3 Merge: 6a0ed9a 7fa869b Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-24 15:15:58 +0000 Merge remote-tracking branch 'andrunko/conn-addressing' Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=30296> commit 6a0ed9a2f9c49d21060dd0053c8b71864ee59e10 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-24 14:22:23 +0000 extensions: add Make rules for *-gtk-doc.h 3c830e9 fixed `make clean` but in the process it broke building from nothing… since these are now included in nodist_libgabble_extensions_la_SOURCES, we need to tell Make how to build them. commit 210aeb46df44531b1b3c348b5b75e743afe2503c Merge: b775d24 43cbe47 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-24 14:06:42 +0000 Merge remote-tracking branch 'andrunko/protocol-addressing' Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=32692> commit b775d249a13db7a31a0306572f670f6b76b3c804 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-24 13:58:29 +0000 configure: depend on tp-glib 0.17.2 This is needed to support Protocol.Interface.Addressing, coming right up… commit 6554c595fe1fd7684ac8efb2505b589601660c3b Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2011-11-22 17:26:17 +0000 Fix missing capabilities.h and caps-channel-manager.h The problem was introduced by this commit: |commit 587da15932d178ad289e81b039dcabb4e90984c5 |Author: Jonny Lamb <jonny.lamb@collabora.co.uk> |Date: Thu Sep 1 14:19:52 2011 +0100 | | gabble: add capabilities.h and caps-channel-manager.h as public API | | Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit c6e76ac44acd46e8d5a1c9f2cc950548d7a30ead Author: Alvaro Soliverez <alvaro.soliverez@collabora.co.uk> Date: 2011-11-15 13:05:47 -0300 Support building on Android This patch makes it possible to use installed versions of Wocky and Yell, rather than submodules; adds a missing explicit dependency on gio; and adds Androgenizer build targets. Modified from an original patch by Derek Foreman. https://bugs.freedesktop.org/show_bug.cgi?id=42446 commit 9e4bd7355548bc64aeda0c997dbd14e66522193b Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-17 14:36:38 -0200 addressing-util: Properly check if "x-facebook-id" vcard address is a number. commit f3d2d2e95ed23e080e5bd4ec935491916efd7bbf Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-17 13:10:03 -0200 addressing-util: Refactor gabble_parse_vcard_address and make "x-facebook-id" parsing expect a number, not a JID. Refactor gabble_parse_vcard_address in gabble_normalize_vcard_address, gabble_vcard_address_to_jid and gabble_jid_to_vcard_address and and make "x-facebook-id" parsing expect a number, not a JID. commit a3c018452d6e4bf48c6eeb16bfd55b35b70c3aad Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 21:31:18 -0200 Expand tests for Conn.I.Addressing to test normalization of vCard addresses with 'x-facebook-id' field.fb-addressing. commit fdf0b93faa48797b739a4d6275baad0f1069f0ce Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-10 21:33:21 -0200 Expand tests for Protocol.I.Addressing to test normalization of vCard addresses with 'x-facebook-id' field. commit 3f4ce2c1a14aba3c5f0c922e527ff9e648311207 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 20:32:45 -0200 protocol: Add support for normalizing vCard addresses with 'x-facebook-id' field. commit 7fa869b1f319ab42c75d61fdd3b22859f3bb1dfb Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-21 13:25:27 -0200 Update Conn.I.Addressing from tp-spec. commit aa5280ce5e76c65b310379d73671f4bce826a286 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-21 13:11:07 -0200 addressing-util: Rename gabble_normalize_uri to gabble_normalize_contact_uri. commit b203be272d60153eef7d00b5edab30a4f0021759 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-17 13:39:22 -0200 addressing-util: Replace gabble_decode_jid with wocky_decode_jid. commit 25c3d3469e587467008d0f7942125ff9a421a6d9 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-17 13:34:56 -0200 addressing-util: Remove redundant checks when calling g_uri_escape_string. commit 4192c92ae505489050da9f89fcbb756d83f66bb3 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-17 12:00:23 -0200 twisted/addressing.py: Expand tests for normalizing URIs. commit 2d661e26a114dcf91e0461a814072be4c095e0f4 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-17 11:40:05 -0200 addressing-util: Use gabble_parse_xmpp_uri on gabble_uri_to_jid. commit 9f53dc66c3a9b29ba987e5bb1d9a33ad34567beb Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-17 11:39:46 -0200 addressing-util: Add gabble_parse_xmpp_uri helper method. commit 909d5428e4187ffe276587e726a790e7b1653636 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-17 11:10:19 -0200 addressing-util: Refactor gabble_jid_to_uri and gabble_normalize_uri. commit dad62245979ea66a63c4e2ad8ad99386c0007e07 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-17 10:42:07 -0200 conn-addressing: Remove unnecessary cast. commit 26594e8d47c0af050128d9133892f676cde96e55 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-17 10:41:33 -0200 Update docs for Conn.I.Addressing. commit ef5685459b4815aac89d3e0ed4202e277e127705 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 20:36:26 -0200 protocol: Use gabble_get_addressable_uri_schemes/vcard_fields. commit 687adff7ab22e0f2dc5f81b895726372acc28a98 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 21:30:49 -0200 addressing-util: Make gabble_uri/vcard_address_for_handle generic. commit 2e33ef47c7fc2c2630c084b590610f5bf086fdab Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 21:27:39 -0200 addressing-util: Use vcard address as the identifier for tp_handle_inspect in gabble_ensure_handle_from_vcard_address. We need to parse the vcard address to make sure the field/address is supported, but we cannot use the return of it as the identifier to tp_handle_ensure, as the return may be invalid (depending on the vcard field). commit ab6aef86574495c699756f13f7fe3e8e33b48c97 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 20:08:28 -0200 addressing-util: Split gabble_parse_uri in gabble_normalize_uri, gabble_jid_to_uri and gabble_uri_to_jid. Also properly escape URIs. commit 846339c2ad4fe280a1f89ca60ff4bfcd59ed7063 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 17:44:35 -0200 conn-addressing: Use g_str_hash/equal and dup/free the key for the requested hash on conn_addressing_get_contacts_by_uri/vcard_field. commit 1393bc432a2a271e94d528df15b9166c9fa9a8b7 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 17:41:42 -0200 Update docs for Conn.I.Addressing. commit 774995d3b527ced96f236ac7937d8861c9403c03 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 17:37:08 -0200 Fix typo in Conn.I.Addressing. commit f84a9c17a256a17ad0118a9a932cc90650399143 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 17:16:56 -0200 Split requested contacts into a separate argument in Conn.I.Addressing. Remove the contact attributes ".../requested-*" and return the satisfied requested addresses on GetContactsByURI/VCardField. commit a1c71d47685d266be24f3a6deebddb5d184c781d Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 13:27:18 -0200 protocol: Use g_error_matches to properly match for errors and don't crash if error is NULL. commit bee30c01c77fcd76fe046bf962d1568f16149980 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 13:23:49 -0200 conn-addressing: Use g_error_matches to properly match for errors. commit 158fbf5c3987b90f27345cd54ba3885790caddd3 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 13:19:31 -0200 conn-addressing: Add comments for g_hash_table_get_keys usage. commit cd210ac5a6d04fb46d532e1421b11cc9baa34197 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 13:18:25 -0200 conn-addressing: Rename variables starting with "in_". commit 4137aba89752ae3b773c44fa59e238376a2561dc Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 13:14:47 -0200 conn-addressing: Reorder includes. commit 36be157b1edb9776a320d377588b2ec8fd1cce56 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 13:11:50 -0200 conn-addressing: No need to include debug.h and define a debug flag as we don't use them. commit 2a1708b475e527bd2d8662d30777c910d08c5df1 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 13:08:42 -0200 addressing-util: Refactor gabble_vcard_address_for_handle. commit 082f79dbf29e3a11d641b6339000e2bcf639f2c9 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 13:01:22 -0200 addressing-util: Refactor gabble_vcard_addresses_for_handle. commit 24f94aad9af73af03486f0612e4f99a723b30e3e Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 12:32:51 -0200 addressing-util: Refactor gabble_parse_vcard_address. commit 218ae8f0dc091444b34df18f9e79797a9bfdcc37 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 13:06:59 -0200 addressing-util: Refactor gabble_uri_for_handle. commit 44184e6acbcd8cd6cd6baa39811833d39c90e600 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 12:52:44 -0200 addressing-util: Refactor gabble_uris_for_handle. commit 5e74e1d55948636645b654f267398253d329ffdc Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-16 12:24:00 -0200 addressing-util: Refactor gabble_parse_uri. commit 3210556571ef281f2afe6586c35474be0906681b Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-14 16:33:30 -0200 addressing-util: Put includes in alphabetical order. commit 78af6ffac2fccf1f26ad7c38b369e9c493f726f1 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-14 16:31:38 -0200 addressing-util: No need to include debug.h and define a debug flag as we don't use them. commit d977ec1feaf34a19979309ca1a8e2e1808aa3ece Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-14 16:32:22 -0200 addressing-util: No need to include config.h in the header file. commit c07bb73548709f427c4b47b5a0d93c77806d631e Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-11 01:30:05 -0200 addressing-util: Fix some coding style issues. commit dda584a302134223185a36d589e48d8d2a1ec07d Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-11 01:00:34 -0200 addressing-util: Do not fill output uri if input uri cannot be parsed in gabble_parse_uri. commit 33394ec5a4f1acfc3f6235626d98e0267e27fa53 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-11 00:53:31 -0200 twisted/addressing.py: Re-enable Protocol.I.Addressing test. commit f4a87f5d3584d19993206992f768638a0209bdea Author: Eitan Isaacson <eitan@monotonous.org> Date: 2010-09-22 10:32:09 -0700 Synced with latest tp_contacts_mixin_get_contact_attributes. commit b4cc4692ee10fa84f92922bfabb22153232187a5 Author: Eitan Isaacson <eitan@monotonous.org> Date: 2010-09-21 13:07:32 -0700 More centralizing. commit c1610996707159f8c09ed0077df169eadd253d59 Author: Eitan Isaacson <eitan@monotonous.org> Date: 2010-09-21 12:07:35 -0700 Added addressing-utils.[ch] to aide in addressing consistency. commit 3c86293fa5dc2b24447eeaddc5cd8b7a1e3cf9da Author: Eitan Isaacson <eitan@monotonous.org> Date: 2010-09-20 11:54:33 -0700 Added Conn.I.Addressing tests. commit d7618fe18e64c05625d95531c3c918a1c238a5da Author: Eitan Isaacson <eitan@monotonous.org> Date: 2010-09-20 00:05:06 -0700 Implemented getters in Conn.I.Addressing. commit 2524367ba1531d27a1c201651119a44aba0a999a Author: Eitan Isaacson <eitan@monotonous.org> Date: 2010-09-20 00:04:40 -0700 Factored out URI parsing. commit f1b72e248195b25f629bb2042135066c34b482a4 Author: Eitan Isaacson <eitan@monotonous.org> Date: 2010-09-19 16:20:18 -0700 Started work on connection addressing iface. commit 4c0aa45e6a69de77cc9e685edac9213ba34192dd Author: Eitan Isaacson <eitan@monotonous.org> Date: 2010-09-19 09:19:42 -0700 Added Conn.I.Addressing as an extension. commit 43cbe4770f28bc52115bec727edc07a6c9142841 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-21 13:05:55 -0200 protocol: Update to latest changes in Proto.I.Addressing. commit a9608bc48432be0e18441b931c60d6438acc40e9 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-14 15:05:14 -0200 twisted/constants.py: Re-use PROTOCOL definition when defining PROTOCOL_IFACE_ADDRESSING. commit 9c745c78daa57bb374fdcb536ead75ba3d50c9aa Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-14 15:04:34 -0200 write-mgr-file: Use one property per line when calling g_object_get, to emphasize the paired arguments. commit b7504155ef6656ee155439fef7b35b3e6226dcfb Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-14 14:57:45 -0200 protocol: Reorder logic of checking for uri schemes in addressing_normalize_uri. commit be3b8aa3f9b6d8aa5e933d7ee44475ab4356c5c3 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-14 14:56:09 -0200 protocol: Reorder logic of checking for vcard fields in addressing_normalize_vcard_address. commit c02c3f6d08d890627ed19b8513cc3609e4ed8303 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-14 14:53:38 -0200 Remove debug area for protocol as it's not being used. commit f498451348f9053ff3e4b01a854862d00ba57a80 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-14 14:49:52 -0200 protocol: Updated with latest changes in tp-glib to support Protocol.I.Addressing. commit 6cdcedb7faca3d2fa43e01d32d9ae7bade2a0a5b Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-10 21:34:37 -0200 write-mgr-file: Make it comply with ISO C90. commit fb792b824efcc0960db7143ff69bf79ee76ac278 Author: Eitan Isaacson <eitan@monotonous.org> Date: 2011-01-03 16:24:43 -0800 Use new addressing GInterface API. Fix review nitpicks. commit bd20b6a9c8b4ba138a77112efd698af126965afc Author: Eitan Isaacson <eitan@monotonous.org> Date: 2010-12-27 15:56:53 -0800 Update manager file writer for new addressing features. commit 83095016b23bc2096dd7fcd567bde3ac56017ac4 Author: Eitan Isaacson <eitan@monotonous.org> Date: 2010-12-27 15:56:06 -0800 Added tests for Protocol.Interface.Addressing. commit fb0b624a751807821dcaa91196457dc0be70406c Author: Eitan Isaacson <eitan@monotonous.org> Date: 2010-09-15 15:56:54 -0700 Added Addressing support to protocol. commit 3c830e93b65121c2a6450c97b68922b49d85fde3 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-21 14:19:35 +0000 extensions: add generated -gtk-doc.h files to Makefile The updated code generator added in f9332611 puts gtk-doc comments into separate source files. Since these weren't mentioned in extensions/Makefile.am, `make distcheck` failed, protesting about “files left in build directory after distclean”. commit 357aef5d882f461a05037255f3f0dee844d18d6f Merge: cbe05e9 ac3ed72 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-21 13:14:04 +0000 Merge branch 'xmpp-console' Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=xmpp-console> Reviewed-by: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> commit ac3ed729bed7d8c4fb62a11ade54f54b6139c0d0 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-21 10:49:00 +0000 console plugin: add a FIXME re. client dying commit f28d2d99353e91c925986f8ee7abde562384f884 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-18 11:00:46 +0000 console UI: turn off monitoring when we quit commit 936059fedae244ec4ea9cf40d500f9b761639bfb Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-18 11:00:21 +0000 console UI: allow passing account identifiers commit 77f77a88c3a28a68cdbd5656912580cf2e235338 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-17 23:50:33 +0000 console UI: fix handling errors from SendIQ commit 2622e65507e83956a2dd0b7f349135771ec8f335 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-17 17:42:43 +0000 console UI: add a page for sending arbitrary stanzas commit 5bcba4d971ebf48ba827067ff4b1c5d28c36295f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-17 23:49:50 +0000 console UI: factor out spinner wrapper notebook thing commit ff861b9904b4d200c33107fd39178585310918d0 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-17 11:07:32 +0000 console plugin: add SendStanza method commit 0212d45fcddd528cf3f3b66c930b0b57e0788d6e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-16 10:23:42 +0000 console UI: add stanza monitor pane commit 9391ee87e77315f3405722846d6b2bec14736497 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-16 09:38:46 +0000 console UI: split out UI helpers The traffic monitor window will need to show nicely-formatted stanzas, and it will also need a grid with the same spacing. commit bd8c210005270e42b09feb08abf521bd64a1237d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-16 09:29:12 +0000 console UI: pack IQ page into a notebook. commit ace82cb0e39516c6df7b055b5a2219c45578c746 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-16 09:19:29 +0000 console UI: refactor IQ interface into a class This just pulls out the entire Gtk.Grid containing the UI for sending an IQ into its own subclass of Gtk.Grid, paving the way for another page in the UI for watching the stanzas fly past. commit 54dc3ce758b1f47f2a46590297765c5baf5dbd77 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-16 09:18:38 +0000 Add a smoke test for the XMPP console commit 1a6f7fff8022d9f4bf17ded58771c3c7a8582049 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-16 09:09:39 +0000 console plugin: implement received/sent signals Ideally the SpewStanzas property would become False when the client which asked for it falls off the bus. Later... commit 27afc946f679d649d57026ffd7d81bbaae00b4a2 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-16 09:08:18 +0000 Add Sending/Receiving signals to Console API commit f9332611f8c19a0bf96a7c822c7e03da796813f7 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-11 19:45:25 +0000 tools: update to respect EmitsChangedSignal commit 20901a521f66d1106e69ca967c2a60af10b3c486 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-11 19:27:50 +0000 Update Wocky snapshot This new snapshot allows Gabble (specifically, our plugin) to register match-all stanza handlers, and also adds the stanza currently being sent as an argument to the WockyPorter::sending signal. commit 9f3e22edb1b13ff37b124a5fe3a5e9a1522dbebb Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-21 18:07:09 +0100 xmpp-console: add some better error reporting commit f59235111739cde7b746de4b93d9090f039dc494 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-21 17:38:54 +0100 xmpp-console: Readd a crucial feature from 0.12.5. commit 4fd5fd804b45b3b1c8f8de5a71210099663d688c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-21 16:49:39 +0100 xmpp-console: show a spinner while waiting for a reply commit c63263f038c938839e5a3ec5e4809955b877a381 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-21 16:28:13 +0100 xmpp-console: add radio buttons for get vs. set commit 00e1ca483ad07ddcd2a059130e3e186ae12fbd63 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-21 16:17:12 +0100 xmpp-console: split up entry-adding function I'd like to use a combobox or something for the get/set selection. commit 880edbed11b23262afed535ce51dc3e36ebf3698 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-21 10:43:59 +0100 Add XMPP console UI It is only installed if the plugin is installed. commit 59fbf7d5e24859595d230f6249c30370f09a6281 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-21 10:43:50 +0100 test plugin: include version number commit 98ab5aa93c9574187bf47ff7bad10f7a1fe2b935 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-22 14:33:52 +0100 Add an XMPP console sidecar It currently only supports sending an arbitrary IQ and getting the reply. Obviously this is for developer use only. commit cbe05e97476160fab38ba491717f4d5a42c17887 Merge: 7c77196 2f1c385 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-17 14:46:33 -0200 Merge branch 'trivia' commit 2f1c3854ed8860caeb8410d4a9c0882124641e10 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-11-17 14:18:18 -0200 Remove gabble_decode_jid in favour of wocky_decode_jid. commit 7c77196d24c77a31bb51928ee3875f1161b9fd08 Author: Xavier Claessens <xclaesse@gmail.com> Date: 2011-11-16 15:21:04 +0100 Add coding style check for g_hash_table_destroy and g_array_free usage commit 769a97c2ed9e6cbfda656a65483f6142423adc36 Author: Xavier Claessens <xclaesse@gmail.com> Date: 2011-11-16 14:39:30 +0100 Use _unref instead of _free _destroy when possible.unref Replace g_(ptr_)array_free (foo, TRUE) and g_hash_table_destroy with respectively g_(ptr_)array_unref (foo) and g_hash_table_unref. I used this command to generate this patch: for f in `find -name "*.c"`; do sed -i $f -re 's/g_ptr_array_free \(([^ ,]+), TRUE\)/g_ptr_array_unref \(\1\)/'; done See Danielle's blog for explanation of possible bug _free can do: http://blogs.gnome.org/danni/2011/11/16/mistakes-with-g_value_set_boxed/ commit dfccd984ac6c694a689c1f224efb4f4e2b27e01c Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-11-16 11:37:13 +0000 bump nano-version Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 241356cdbd74bca44e8c0c9c583a2d1f4daf903a Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-11-16 10:07:32 +0000 version 0.15.0 Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 65c8b8f3edb446e3a0411a7401d9e3947ba858db Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-11-16 11:24:10 +0000 jingle outgoing test: add MembersChangedDetailed flag to base flags telepathy-glib ≥ 0.16.2 always sets the Members_Changed_Detailed flag in the group mixin, so now that we depend on tp-glib ≥ 0.17.1 we should expect that too. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 9f8e0db4ba039eb78d055a0c04bb8fb283c89751 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-11-16 10:01:14 +0000 NEWS: further updates about Wocky Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 1e61c2ef8d352294f369eebe3493f135c7dca16c Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-11-16 09:48:34 +0000 NEWS: update Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 65628acf0d363f0868d643cffcb01b950d6dcf5f Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-11-16 08:44:02 +0000 file transfer helper: use crazier stock metadata in file transfer tests Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 78af31f043327c194ed4db4c2db2d8b04d57f07f Merge: f903c62 80ffa6e Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-11-16 08:07:09 +0000 Merge branch 'ft-metadata' Conflicts: src/namespaces.h tests/twisted/Makefile.am Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit f903c62e4de60610638931cc14ed3118de2d37c6 Merge: 9309cb4 566c0f7 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-15 15:34:41 +0000 Merge branch 'telepathy-gabble-0.14' commit 566c0f72fe54d44752c3704537e42c3e3640488c Merge: ebcb135 7524ce7 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-15 15:34:27 +0000 Merge branch 'telepathy-gabble-0.12' into telepathy-gabble-0.14 commit 7524ce77ef3989418d2e8b0a2af47e472c7c982d Merge: 9cf653e 6cb2b5d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-15 15:34:11 +0000 Merge branch 'local-pending-flicker2' into telepathy-gabble-0.12 commit 6cb2b5d0f9e4a164537e3861f787e603d02bb8e4 Author: Cosimo Alfarano <cosimo.alfarano@collabora.com> Date: 2011-11-02 13:24:09 +0000 add case for "cancel subscription" to test_local_pending commit 31c2cd55912c72c82cba28202f220a80c8b4faca Author: Cosimo Alfarano <cosimo.alfarano@collabora.com> Date: 2011-11-02 13:20:15 +0000 expect MembersChanged AND ContactsChanged on sub-request We should explicitly expect the relevant state transition on the publish channel; and when forbidding events, we just forbid them from occurring on the publish channel. (fix by Will Thompson, thanks Will) commit 284779859a67e2dfceb4d9930df81e452d5a4b3a Author: Cosimo Alfarano <cosimo.alfarano@collabora.com> Date: 2011-11-02 11:39:46 +0000 fix comment: Alice is just requesting subscription commit 273654bfb07e5ff593b162dd455f739f697b71b8 Author: Cosimo Alfarano <cosimo.alfarano@collabora.com> Date: 2011-11-02 11:39:21 +0000 Remove useless symbol in test_local_pending commit 8fcf944c1afbcd98a5cbf582e33d88d877a6980f Author: Marco Barisione <marco@barisione.org> Date: 2011-08-31 17:31:24 +0100 Roster: don't hide local pending contacts from stored commit 9309cb456645ff7643ebe36c50e3b447641b6c6b Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-15 12:13:46 +0000 Fully expunge HANDLE_LEAK_DEBUG_CFLAGS Sorry, internet. commit 36a50290e5d9324cf55ed7a53cb9c221d7386d95 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-15 11:34:42 +0000 configure: remove --enable-handle-leak-debug. There's no such thing as a handle leak any more, so this is vestigial. Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 5b3105a5a357cdd1f1d098fcc3e2c26a40e5b93f Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-11-15 10:12:55 +0000 wocky: update snapshot for sasl fix again Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 30ff2ae153dfa5b45072df344d129d909429a63e Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-11-15 09:16:56 +0000 wocky: update snapshot to fix sasl build failure Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 80ffa6e731f2ecb5c31bbaec1083d13e6757d912 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-11-15 09:16:05 +0000 ft metadata: use tp-glib generated code rather than using the draft interface Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 13835c53f6e7b0cf1d576ca8ae031282494ed473 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-11-15 09:15:36 +0000 configure: up the tp-glib dependency Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 275667c68ed51ffd4dc988c5916a11e85401f4ac Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-11-11 11:11:14 +0000 metadata test: test for odd metadata with a key but no values Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 631d3beed4585d9c2b1530ab4c9657907234c9fe Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-11-11 11:10:51 +0000 caps-helper: deal with no value nodes in data forms Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 798edc37548cbcea3c4c16edbe65aa62f3ba3ff4 Merge: 585f946 ebcb135 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-10 17:09:40 +0000 Merge branch 'telepathy-gabble-0.14' Conflicts: NEWS configure.ac commit ebcb1350c3b316f8fe510caacacf0b2a59b95458 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-10 16:40:09 +0000 conn-olpc: handle activities with NULL ids. Other places in the code seem to handle GabbleOlpcActivity.id being NULL; and <https://bugs.freedesktop.org/show_bug.cgi?id=32050> is a crash on this strcmp. There are no logs, and the first argument to strcmp is not on record, so this suggests to me that this might be the cause! commit 5677e158d6518e53bc06c131e3b2c8b9c779a74a Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2011-11-09 17:46:04 +0000 Remove double definition gabbletestsdir is defined in configure.ac https://bugs.freedesktop.org/show_bug.cgi?id=42679 commit c5afb4dc7f6ea3a55ca35bbd04e16ce87e57cacc Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-11-09 19:34:03 +0000 metadata: update to new draft Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit a1f943c809232021db6d831f0e9869bb0584dcfc Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-11-09 18:07:37 +0000 extensions: update FT.Metadata draft Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 585f9467b8916b5d3ebc0e06c00019b916099672 Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2011-11-09 17:46:04 +0000 Remove double definition gabbletestsdir is defined in configure.ac https://bugs.freedesktop.org/show_bug.cgi?id=42679 commit dd7cbb323b1ed31f34f2babff8d066f7e88bc3c9 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-11-09 17:33:55 +0000 namespaces: update metadata namespaces Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit bdf5c1535079d7f69e8b0d50def2bf0acd2a7d1a Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-11-09 08:20:31 +0000 connection: fix typo when indexing pointer array using wrong counter D'oh! Fixes: fd.o#42706 Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit b4b5aa0be69a171615801c13626f5221e8b1cb6c Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-11-09 08:20:31 +0000 connection: fix typo when indexing pointer array using wrong counter D'oh! Fixes: fd.o#42706 Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit e5d6c92c9ff74fdba49d751ed1f7b5d87bf17336 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-07 20:34:38 +0000 lay the foundations for 0.15.x commit ed197893f4e303276480649330b9c362c60f6442 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-07 20:34:04 +0000 Nano-version bump to 0.14.0.1 commit 2c134e18d24d1daebba6963f73c1bff9b960b46c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-07 19:59:19 +0000 Version 0.14.0 commit 152c12a2e393e6c135a975df847f55990fc8d0f5 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-07 19:58:40 +0000 Hey, let's call this 0.14.0 commit 0f86ad63a641a780b0e812725f7a7bd24d57a467 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-07 19:20:28 +0000 NEWS for 0.13.8 commit df3882d34528ccb320835fafbad74034a589dc64 Merge: 6ef3ca9 6895340 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-07 17:46:04 +0000 Merge branch 'facebook-own-message' Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 6895340badaff9f97683230848ae8e0f9f6f99d8 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-04 08:58:45 +0000 ImFactory: handle Facebook's own-message extension Facebook's XMPP server sends us IQs containing messages which we send to contacts, whether on this connection or via another connection (such as the web interface). We can expose these as Delivery_Status_Accepted delivery reports, allowing UIs to log them and show them up or whatever. This could help keep things coherent if the user hops between chatting in the browser and/or Empathy, say. https://bugs.freedesktop.org/show_bug.cgi?id=41417 commit 6ef3ca940f0b4a4ae1aedb2c03ddc794fe659582 Author: Danielle Madeley <danielle@madeley.id.au> Date: 2011-11-07 22:18:17 +1100 Use commit ids that actually exist for Wocky What happened here was that git-bz was rewriting my commit ids when I submitted the patch to bugzilla for review, but my Gabble was still pointing to the original commit I had made. SURPRISE! commit e61dc0318e7a7c00c268105599ea3eada2c1491b Author: Danielle Madeley <danielle@madeley.id.au> Date: 2011-11-07 21:45:02 +1100 Return the appropriate value in the case of an unknown timestamp This updates Gabble for the latest spec. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=42652 commit 465b3aef2330ae73c2f643eeec4676da657c2222 Merge: ed09e89 a04b9e5 Author: Danielle Madeley <danielle@madeley.id.au> Date: 2011-11-07 20:54:44 +1100 Merge branch 'wocky-muc-gdatetime' commit 4312e1f6789227e658ee55349b91b0980128ab51 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-04 16:21:04 +0000 IMChannel: reindent receiving/delivery report code This patch just gets rid of the funky formatting mentioned in an earlier patch; there are no code changes. commit 574d1468432bd066dfe7a50fed8c2bbae5d71975 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-04 12:22:09 +0000 IMChannel: split incoming message and report handling As a nice side effect, the new _gabble_im_channel_report_delivery() function can do successful delivery reports if send_error == GABBLE_TEXT_CHANNEL_SEND_NO_ERROR. This will become useful momentarily... The funky formatting is to make clearer that this patch is mostly moving code around unmodified; a subsequent patch will clean it up. commit 46da670d5c0fa51b92a168d454d23e9b119e349a Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-04 12:11:42 +0000 im_channel_receive: split out building basic message This is about the only part of this function which is shared between the delivery report code path and the normal message code path. commit deb5a15cb02344891f5871cd5f8dcf8faa464d4a Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-11 17:01:13 +0100 ImFactory: refactor creating unrequested channels We'll need similar logic for handling incoming facebook:own-message notifications. commit 214c0b08245fc264985e4504309abb7b7e82f68c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-03 23:50:24 +0000 exec-with-log.sh.in: set WOCKY_DEBUG. I'm delighted that 3a1fe026 made us compatible with hypothetical shells, but it also reduced the amount of debug output in gabble-testing.log. commit b34a0207287a3976e1b880c5b958b9215c5930ad Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-11-03 23:27:24 +0000 im_channel_receive: remove redundant 'sender' parameter If we're passing an incoming message to a 1-1 IM channel, we don't need to tell the channel who sent the message: it knows perfectly well. In fact, we were telling it twice: once in handle form (which is redundant), and once in full JID form (which is more useful: it lets the channel update its resource binding). commit 9b81a8da064954b714474208d2fb4e7d5cb2d6b4 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-11 15:54:47 +0100 ImFactory new_im_channel: remove redundant typecheck By the time we get this far we can be sure that the factory really is a factory. commit 54104dac1cbfa6a13e8aba199a2043eb061e9a87 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-11 15:53:26 +0100 ImFactory: remove GET_PRIV anti-idiom commit 34b600adcb8894615fc2b40400ce6e740230f7c2 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-11 15:50:24 +0100 IMChannel: implement get_object_path_suffix I think this is simpler than the factory passing the path in. Though it's actually longer, which offends me on some level. commit b3d5848804b8128b0962f4860efcd758e19d7fc3 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-11 15:42:42 +0100 ImFactory: simplify new_im_channel's arguments We can infer from @request_token whether the channel was requested locally or is being created in response to a incoming event; hence, we don't need a separate @initiator argument. commit 7a9200ca2a426f4f794a4fd43291bcd511a9420f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-11 15:34:57 +0100 ImFactory: document new_im_channel more usefully commit 33cd9527f7c0d1f4a2b72e8cfadc417b69590336 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-04 01:15:32 +0100 Remove unneeded im_channel_closed_cb prototype commit eb0dc2a0694451453c40c0e75da3ba9093837339 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-04 00:24:40 +0100 Document _gabble_im_channel_receive usefully commit 933af070afdc7a3a1df333c318743e0ba115f3a5 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-04 00:20:14 +0100 Remove redundant CHECK_STR_EMPTY macro commit 2941264d571f3bd23739f7bbdbb350c53355398b Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-04 00:08:02 +0100 IMFactory: use constructed, not constructor commit aa4b8472a09fafd5bc8046c01f2163d6d7e4495c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-04 00:05:22 +0100 Remove obsolete DBUS_API_SUBJECT_TO_CHANGE defines commit d3607abee80d237ea1d00aca55e14eadc7ff5bb4 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-05-30 12:16:16 +0100 muc-factory: use a dispatch table for handling requests commit 517cce66448836d6f3de0eef34b9c36d7a4a2bf9 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-05-30 11:45:40 +0100 muc-factory: use fully-qualified property constants commit 45b54e41a49f60b4e0c620546492a91e0c1b1b4c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-05-27 12:09:52 +0100 MucFactory: remove stupid priv anti-idiom commit 616ccbaf5f8b04e1ab1f74f0441490731c1044eb Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-31 17:09:39 +0000 ft-client-caps test: change client name I've no idea why but if caps/tube-caps.py is run before this test (it has the same idea and design as this test was copied from it) then this one fails due to the same client name?! Another day... Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit ed09e896b3c249568192e92b5195462e626918fb Merge: 08da102 f5f7cc6 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-10-31 14:05:12 -0200 Merge branch 'memory-leaks' Reviewed-by: Will Thompson <will.thompson@collabora.co.uk> commit f5f7cc6b3407af00eb594aca4c2ffc797f987846 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-10-31 13:55:18 -0200 roster: Do not leak the roster stanza. commit 1d61ece67ffac336e4beb430cb1da6e2b4f971cb Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-10-31 13:54:40 -0200 connection: Remove unnecessary extra copy of caps when updating capabilities. commit cb97cf5832904d9ce05c93318f43d8b83fb5aa37 Author: Andre Moreira Magalhaes (andrunko) <andre.magalhaes@collabora.co.uk> Date: 2011-10-31 13:48:15 -0200 conn-presence: Properly free priv member. commit 107d1867af1cd827cf41cc202b0f91bace124f20 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-31 14:51:35 +0000 ft-client-caps test: clarify caps dict building Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 8ecdc16893fc2208233252dd5054b88925392601 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-31 14:30:39 +0000 ft-client-caps: remove duplication by using caps_helper.presence_and_disco Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit c5ea43c6c5bac3cc29695df4f2c2889775eb94a4 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-31 13:45:25 +0000 ft-manager: use nicer tp_g_value_slice_new_* functions Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 70d83e788df4acd2218447696e5517b27b416530 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-31 13:43:51 +0000 ft-manager: clarify argument name Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 534678998700786a5bc5c6e66e863fc64e353ee6 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-31 13:43:01 +0000 twisted tests: use conn.Requests isntead of making a dbus.Interface Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 5cdf63160451cb2142eb1915eb369d9c248bd80b Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-31 13:40:31 +0000 ft-channel: simplify adding fields to dataform Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 56086a17c480737973cc28e6c82b7b98d8eb9f6e Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-31 13:29:07 +0000 namespaces: change FT metadata namespace "and… im: is not a URI scheme. http://telepathy.im/..." Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 7560587e9a14e13b1cb6f1ce2b0c5451bfc67c65 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-31 13:01:21 +0000 ft-manager: deal with bad ServiceName fields Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 08da102662f74cf084e4d2bdfc86f2b15e33ca66 Merge: f9529b7 9cf653e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-31 09:38:35 +0000 Merge branch 'telepathy-gabble-0.12' commit 9cf653e93ba9beb8ff2df73627cd2b1f5bedf6bc Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-28 18:34:25 +0100 roster: ignore multiple replies to roster query. The XMPP server running on vk.com is buggy, and replies to our roster query twice. Gabble just blindly assumed that any <iq type='result'> with a roster in it was the singular reply to our singular query. This is a pretty reasonable assumption but this buggy server violates it, and Gabble calls tp_base_contact_list_set_list_received() more than once, which triggers a critical in that function. A more invasive fix would use wocky_porter_send_iq_async() rather than scraping all the roster IQs out of everything using the LM API, but I wanted to quickly fix a bug on a Friday afternoon. Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=42186> Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit abbfb9b9fd90cb9f279449a9b43e3bff66167d87 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-28 18:54:57 +0100 ft metadata test: fix subclass of file receiving test Oops, this was subclassing the wrong FT helper test class. No other changes necessary (like a boss). Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 735bea1282b3299030869d41920d7dbaabaaddce Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-27 17:23:57 +0100 capabilities: only add metadata cap when we have normal FT caps Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit f9529b7d27b0cc9edc9b7c39573c533963d87079 Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2011-10-21 15:20:03 +0100 Update .gitignore with installed tests commit f4b4768caabf44f0c2955e97bf8c8af592ff23b1 Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2011-10-12 18:45:34 +0100 Install the test plugin for the installed tests commit 49925bb583375e19b2d0fa0aeda7902f79fca370 Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2011-09-29 16:55:06 -0400 tests: add --enable-installed-tests This configure option makes it possible to install the twisted tests in ${libdir}/telepathy-gabble-tests and run them without the sources. The dbus configuration is duplicated in tests/twisted/servicedir/ for the installed tests and tests/twisted/servicedir-uninstalled/ for the uninstalled tests. commit 3a1fe026d8a43f9bad8c6820c73310245929fb4c Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2011-10-21 15:36:18 +0100 exec-with-log.sh.in: POSIX shells, avoid "export var=foo" commit eec2603bd4f8644cc165ce5c8ce42d21c4c73f66 Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2011-10-21 15:11:03 +0100 Use autoconf's $(MKDIR_P) commit fa01616db7028029832cb6da6fa898dac0605a82 Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2011-10-21 14:19:01 +0100 tests/twisted/Makefile.am: Move additional tests in the main list commit b1d83dcd017bac58e00461ed5cc2b1c967d426fe Author: Alban Crequy <alban.crequy@collabora.co.uk> Date: 2011-10-21 13:54:06 +0100 tests/twisted/Makefile.am: order lists in alphabetic order commit ade61fe2442ee0787c253b9aff7848216427a71f Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-26 18:55:45 +0100 ft tests: add tests for FT service name caps Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 3107077eaafd32548273e79363fa3dce4ddc3d25 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-26 18:26:25 +0100 ft-manager: advertise file transfer services with capabilities Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit d92500bcd3911dbddad5fff2d40cfbc674663b41 Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2011-10-26 16:19:58 +0200 actually implement ContactBlocking interface https://bugs.freedesktop.org/show_bug.cgi?id=42281 commit a8f305d39ee09748ac258ce577dd9738278f9561 Author: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: 2011-10-26 15:50:31 +0200 Advertise ContactBlocking if supported https://bugs.freedesktop.org/show_bug.cgi?id=42281 commit 16060fa8422c7ba530461732821064c3576136c8 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-26 13:10:15 +0100 ft-channel: fail to create channel if the contact doesn't have the right caps Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit bd6cb214613a95dc5870ac256fd95349576f5fce Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-26 11:50:34 +0100 ft-manager: only advertise Metadata support for those who support it Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 583cb3ae5b8538fa24a882462a453d5865587352 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-26 11:48:11 +0100 capabilities: advertise support for the TP FT metadata extension Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 08599349b9681f588826393b4c8c2debe228a50b Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-26 11:05:58 +0100 metadata test: ensure we get an error with a bad Metadata property Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit b4f1e9b52846826faf4b843cf4c3bdd00f75150c Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-26 09:09:40 +0100 metadata test: test receiving an offer with no dataforms Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 82e7b8a0f7461665e58381e7690e3c0f2ebeacc0 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-26 09:09:33 +0100 ft-helper: test parsing incoming offer metadata Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit fcf41a7e505a2d38cba5a40e82150bb03eb8d9a1 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-26 09:08:00 +0100 caps-helper: split out function to add data forms to a node Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 396e49c5492c8142cfc3fc45054eee0bbba36e23 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-26 08:48:31 +0100 file-transfer tests: add simple Metadata test Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 52e76fbe1a5348eccdda726133e2705a1f78f44d Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-26 08:46:54 +0100 ft-channel: include metadata in file transfer offer Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit c2f0b06cb87a62ca9e15bb9bfa870a9854e0117e Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-26 08:44:40 +0100 caps-helper: allow extract_data_forms to be called with no x nodes Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit b9f1bc49edd64959ff0ea57f216672d3067b1118 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-26 08:35:16 +0100 caps-helper: move data form parsing code into its own function Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 2933e974314887c283276c904832c69d470849b5 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-26 08:33:00 +0100 ft-manager: disallow FORM_TYPE keys in Metadata property Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 30899a8616c660cc0852af003a4ad40609a5b52d Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-26 08:30:25 +0100 ft-channel: make Metadata props immutable and test them Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 7a1da4c951c3bda7793f4511e3b470e7226d8108 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-25 21:13:09 +0100 namespaces: define NSs for Metadata dataforms Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 5472db8eb4a59c6261a36ddcea407489d488c3eb Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-25 21:05:04 +0100 ft-manager: get Metadata props from SI file transfer offer Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 64c9d82af61b25ab06bd74607acf0f336c6c463a Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-25 21:04:33 +0100 ft-manager: set Metadata props from channel request Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit ab38d52b84ddd80f356a3d804eeae0aeb99b1520 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-25 21:03:03 +0100 ft-channel: set Metadata props on construction Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 50e3c855268d9e43f0a2853cc71757f5e88b1ab3 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-25 21:00:28 +0100 ft-manager: add Metadata props to Allowed_Properties Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit a5fd662a8f3a70eccef1a3d943f060513d2658f3 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-25 20:58:42 +0100 ft-channel: implement Metadata properties Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit d903da03658e26e574ed6d8ffdd58cc20023857b Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-10-25 20:57:16 +0100 extensions: add FileTransfer.Metadata draft Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit e1973c15669a6043cd474cb48b89baafc4bb0d45 Merge: bf1c8dd 3cdbae8 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-24 11:15:41 +0100 Merge branch '41743-show-contacts-as-offline-even-after-a-really-early-message' Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 3cdbae82cb09dd8218e1c783b7bad1f84b84498e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-13 11:33:08 +0100 Fix offline contacts showing up as unknown, not offline Due to a weird interaction between the presence cache, IM channels, and scraping nicknames out of <message/>s, receiving a message from an offline contact before the roster is received would cause their status to erroneously show up as unknown, not offline. This fix is a bit of a hack, but it is much smaller than refactoring to make the IM channel store the alias (which would allow us to expunge keep_unavailable). This regressed as a side-effect of e0cda61. Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=41743> commit 3b79e21684aa31b568aeb3969d034e772ac9e610 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-14 12:00:50 +0100 Test grabbing <nick/> from <message/> If a contact is not on your roster, you typically have no idea what their nickname is: no roster, no PEP, no vCard (assuming the server doesn't let random people fetch your vCard). In this situation, contacts who message you out of the blue can include <nick/> in the message itself. This is implemented in a kind of dodgy way in Gabble at the moment: the IM channel forcibly retains an entry for the contact in the presence cache, and then the presence cache stashes the nickname as if it came from presence… It was also previously untested, so I thought it worth adding a test before I even thought about fixing how it's implemented. commit a04b9e505e6a5baec65fbb52522f1b52656ca72e Author: Danielle Madeley <danielle@madeley.id.au> Date: 2011-10-18 13:47:55 +1100 [muc-channel] WockyMuc now signals timestamps as GDateTime instead of time_t Fixes assumptions in the code where timestamp was assumed to be gint64. commit bf1c8dd299d02ad433af2c31c879601d712e8d3b Author: Danielle Madeley <danielle@madeley.id.au> Date: 2011-10-17 23:04:00 +1100 [muc-channel] timestamp is a time_t not a gint64 Cast to the correct type so that Gabble compiles correctly on 32-bit. I propose fixing this properly by using either gint64 or GDateTime in Wocky, but not tonight. commit 009bec00c4d83f401179fd7fb442158875238a34 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-12 17:46:33 +0100 Update Wocky snapshot for glib/gtypes.h fix. commit fca53f10536c4e758c24227c956296534ce2a4a3 Author: Cosimo Cecchi <cosimoc@gnome.org> Date: 2011-10-12 12:33:33 -0400 test-resolver: don't include glib/types.h directly Use the glib.h header instead. commit f065fb6165f18441b00cbfc263acd50c3eb05b38 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-12 16:20:54 +0100 nano version bump to 0.13.8.1 •_________________________• commit 9f1ddd0ae7edf1686dedb7c12d373c99b7444221 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-12 15:55:33 +0100 Version 0.13.7 commit 51f01ab2f802ba5f40a10f5cab207d73d9914dcd Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-12 15:51:16 +0100 Truncate generated ChangeLog at version 0.12.0 It used to be 2.4M, which is almost as big as the entire contents of the 'src' directory! Truncating it trims it down to 68K. commit b109b58411387c2139704f13923453bbeaf15a21 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-12 15:28:08 +0100 NEWS for 0.13.7 commit 3f1091e0f6b576f266472fbf96d271332e7686ad Author: Xavier Claessens <xclaesse@gmail.com> Date: 2011-10-01 20:33:17 +0200 Do not assume we can authenticate with a password If Wocky does not understand any of the authentication mechanisms supported by the server, then we cannot authenticate with just a password; hence, we should not claim to support the X-TELEPATHY-PASSWORD pseudo-mechanism. (This is the case for the Windows Live Messenger XMPP server, for example.) commit 9f64fd21ede78e42396c93c81892738011045404 Merge: e435637 aff2d84 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-12 12:21:28 +0100 Merge branch 'moar-room' Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=32611> commit aff2d8453d577020658ce47d06f07864f6194b1d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-15 18:40:40 +0100 MUC: ref properties_being_updated commit 12e4a9ac245617b43f3fbd3e69ad55ddb1a88fcd Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-12 18:03:08 +0100 MUC: add more error-checking to SetSubject commit d9160a13c236bcf8a1b789c70dee5497ca17ee4b Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-06 17:48:29 +0100 muc/subject: fix obsolete FIXME about discoing MUCs fd.o#21152 was fixed in 2009. We do have to make the test echo back our unavailable presence if we want to re-use the JID, but that's fine, we can do that. commit 92810af8b77c45981ff736050667161085abb099 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-06 14:35:45 +0100 MUC: update for RoomConfig.update_async API change I decided it was clearer for TpBaseRoomConfigClass.update_async to take a TpBaseRoomConfig as its first argument, rather than a TpBaseChannel. This makes it reasonable to implement the update_async vfunc in GabbleRoomConfig! Yay, no more monkey-patching. I think it would be even better to move all the configuration-frobbing code to GabbleRoomConfig. But this branch is already plenty long enough. commit 4cd04e5366889a5cf8be84d9b096023cba999598 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-05 19:51:07 +0100 RoomConfig: move the base class to tp-glib commit 8d298302188f33ab9336c186b3e03b458d56d629 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-05 18:29:35 +0100 muc/room-config: test disconnecting with requests in flight commit 9efe5f730a4ba61f8b28b0350d4b567069e7a7c7 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-05 16:19:05 +0100 muc/room-config: expand test coverage This tests one more field of room configuration, and also checks the transitions to and from being a room owner. commit 1b3e6d52e2f2969ab944460fb5c7e2b8350ec416 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-05 15:21:22 +0100 muc/room-config.py: refactor form building/parsing commit 983d327aa1731781d74334716adcf5baaac15f80 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-05 14:47:56 +0100 muc/subject.py: fix disco reply <feature var='muc_public'/> should be a child of the <query/> element, not of the <x/> element. commit b620985fb445fc7d54a90080232531248f7899dc Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-02 14:27:32 +0100 MUC: emit ConfigurationRetrieved commit dff8ddbc721ef5791bb089ed9aed19b918553a4d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-02 14:27:26 +0100 RoomConfig: implement ConfigurationRetrieved commit 5ef367af72b53e4c7d115be037139410f2c03a3e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-02 11:30:49 +0100 subject: test for PropertiesChanged Removing the Telepathy.Properties interface from GabbleMucChannel miraculously makes this work. \o/ commit 675367323b8617b88f9f156545e0ea63b21d88e6 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-02 11:26:02 +0100 Rename muc/test-muc-properties to muc/room-config This more accurately reflects its current nature! commit e3b9601367429f2272949995c71b8fd425c28e93 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-02 11:16:21 +0100 MUC: emit PropertiesChanged for RoomConfig commit ede43dda5a6fbed9c7a90b735b24f59fc50a1589 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-02 11:15:19 +0100 RoomConfig: track changed properties With this patch, GabbleRoomConfig tracks which properties have changed, and grows a method to emit PropertiesChanged for those properties. I am not very happy with the macroification of the set_property implementation, but it's the best I could come up with. commit 4c05dc0910cc1d58f71047fa53162d750fc8c6fb Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-01 18:48:04 +0100 RoomConfig: refactor validating property types commit 413157a5b3a66343a7b811a3fd72b516ef86bf2e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-01 18:17:02 +0100 MUC: remove Telepathy.Properties \o\ /o/ \o\ /o/ Now I can get stuck into implementing change notification. commit 16a480c39631481c17fd788a197f7445a7b1effe Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-06 17:01:22 +0100 muc/test-muc: neaten up interface assertions commit 59ee55354fee1a9425790886ea98f342340e390b Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-01 14:35:59 +0100 MUC: hook up UpdateConfiguration This simultaneously un-hooks-up SetProperties. I could have refactored to make it possible to keep both, but I don't think it would buy us anything since we're just about to delete old properties anyway. commit 3a7eadb2ce77968034832ce7d0f039d15fdb3256 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-01 13:39:20 +0100 RoomConfig: add a vfunc for updating configuration commit e70dccee1faf596ff8d00613d7651d3ae751c342 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-30 12:57:09 +0100 MUC: mark appropriate properties as mutable This is a *lot* simpler than in the old days. We no longer have to do something per-property on every permission change, because whether or not we are currently an owner of the MUC has no bearing on which properties would be mutable if we were. commit 26dc9c3df3340bb2662a870301f233274d5fdc47 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-30 12:32:18 +0100 RoomConfig: track ostensibly-mutable properties This isn't hooked up in MucChannel yet, so we currently report all properties as immutable. It occurs to me that “immutable” means something else elsewhere in Telepathy so we should probably call this something else. commit 4d5b16af21c1dfde2426456409182603b6063ee0 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-30 11:42:31 +0100 RoomConfig: implement CanUpdateConfiguration commit 757718b7993f17d95184795634519968553ed8eb Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-29 16:39:46 +0100 RoomConfig: hook up reading most fields This doesn't cover emitting PropertiesChanged (impossible until we expunge old-style properties), nor the current room password, nor changing any fields. commit 8d686b421db6a1b7b38ab30b0d3739f768ee3232 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-29 14:09:47 +0100 Add the start of a RoomConfig object. I'm implementing this as a separate object rather than as part of GabbleMucChannel in the hope of sticking it into tp-glib. commit 54dd251e25734eb097e2a4ba278f1d8ff1dde2e6 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-30 12:55:08 +0100 test-muc-properties: make clearer assertions The formatting of these assertions was unhelpful, and using assertEquals gives us nicer messages when the assertions do fail. commit 82c09a7a031ff2726d56a6d28c01d7c911ef3c23 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-30 12:34:08 +0100 MUC: remove half-baked allowinvites support Previously, we allowed the user to configure whether or not occupants should be allowed to invite others to the room, but didn't actually provide any way to retrieve the current setting. This is a pretty useless MUC configuration flag anyway, given that occupants can always send direct (as opposed to mediated) invitations … so I have no qualms about expunging it. commit 59e35681f2762383e05e696d176a21c6c3b81344 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-30 10:32:44 +0100 MUC: wockify submitting configuration form commit 1edd10efc2c7f16025a2de56b34740b37f849bf4 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-30 09:56:29 +0100 MUC: fill in config form using a lookup table Again, this is shorter than the huge chain of ifs, and I think it's more readable. commit a9f7e51872bdf63a421cb4c26b6e61a59c4c992f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-29 17:46:47 +0100 MUC: correctly send default configuration to the MUC Ahem. Previously we were sending it to our own server. Not so useful. commit bd60fe08cb47fd30d5471c08eed8464bf19646a2 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-29 17:42:14 +0100 MUC: remove faux error handling when accepting default config _gabble_connection_send_with_reply always returns TRUE. I guess the only case this doesn't handle is when the channel (and hence the WockyMuc) has somehow miraculously outlived the connection—I don't think this happens. commit 9e2d76bc981fae2b1c309d11c52a6c369c9d0c57 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-29 17:20:16 +0100 MUC: wockify one use of muc#owner. We request this and parse the reply in two-and-a-half places … this is the simpler one of the two places where we actually parse the reply. commit 0d63603fe7835b18cc12b9e3d101dd30e700d8fa Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-29 15:39:06 +0100 MUC: refactor handling forms in disco reply This only works because we only handle one field. As and when we handle more, we should switch to WockyDataForm anyway. commit 772c8df4a54228b08f1d58ccd8de7d688a374a47 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-29 15:18:15 +0100 MUC: simplify feature mapping with a lookup table This is shorter than the previous chain of if-else, and (I believe) much clearer. commit d7e694b31c191bbe9d2dc56922cb171e8ed2dbd8 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-26 17:27:06 +0100 MUC: remove redundant role and affiliation enums Wocky has these. No need to duplicate them. commit f4b4a4b00011c8f40fc7e245d842e09526095d3c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-26 17:08:56 +0100 MUC: Remove subject from old Properties commit b06ab5b631006a512d1d811cb306aaa2f3702edf Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-26 16:49:09 +0100 MUC: Wockify parsing Subject-setting errors commit f53172e06c29586a32989b11cf66aa2d28368ad0 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-06 16:42:08 +0100 MUC: use id='' to catch SetSubject errors Servers don't strictly have to echo the <subject/> element in their reply if they reject our subject change message. But they do have to preserve the id='' attribute. This patch makes Gabble set an id='' attribute on <message/>s sent to change the subject, and look for that ID when it receives a <message type='error'/> from a MUC. (It continues to look for <subject/> errors, too.) Prosody is an example of a server that behaves like this. commit 2f4d98398c24b95b1178871f62cf89a7bf467dd8 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-26 16:38:19 +0100 MUC: return asynchronously from SetSubject commit 23451bbeb0d06f14d5d2726d92b79a1f618baffe Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-26 16:35:05 +0100 MUC: handle errors when setting subject So this hasn't worked since the WockyMUC port. If you tried to set the subject, and got an error back, the SetProperties() call would never terminate (and you wouldn't be able to call it again for the lifetime of the channel). commit 1e94a3c37c1e134dfb0f88bff1cfe4ad5b0628c7 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-26 16:34:46 +0100 MUC: remove unused argument from _handle_subject commit 2f3df38c90f06698a16fa95d6d4c676c07b28efe Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-26 16:04:25 +0100 muc-channel.h: clean up stale prototypes Most of these no longer exist. Those which do are only used in muc-channel.c, and one of those three is a one-liner which I just inlined at the single point it's called. commit a1463a4f488b62a8891dd3d1e98ffb91f1014f1c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-03 14:17:03 +0100 Wockify SetSubject implementation commit f40f170f058fd00a46f74fafca761cbbe6affa14 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-02 18:35:52 +0100 Subject: use tp_svc_dbus_properties_emit_properties_changed commit 5f3afbcb08a3e686ff536dc024aff91a50782549 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-02 18:22:06 +0100 MUCChannel: simplify password flags implementation We only have one flag, so we may as well just store a boolean. commit c7d28425eefc77826d3235647f0370c8813cd180 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-02 12:52:55 +0100 Build against Room & Subject from tp-glib telepathy-glib 0.15.8 was technically the first release that had Room and Subject, but 0.15.9 was released 10 minutes later. :) commit 6f2c9640bb568e6672989cee9ea078661afd541e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-31 23:03:48 +0100 Update to Jonny's last Subject draft I had to comment out the change notification tests because this object implements both Telepathy.Properties and DBus.Properties; both of them have a signal called PropertiesChanged, and dbus-glib does not allow the two to co-exist. commit 082d84aeef688809fe255098bac75cbc40ef30f9 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-04 09:01:45 +0000 muc-{channel,factory}: update to latest draft spec Split the subject stuff from Room into a different interface and rename RoomID to RoomName. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 81bbbae26a884771b0cd7be5da742dc5b7a2b4e7 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-04 08:49:52 +0000 extensions: update to latest Room draft and add Chan.I.Subject Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 5fe7678d2bd0c5af56adc753d7eb97b47b840b1a Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-03 17:09:43 +0000 muc-channel: XMPP always supports room subjects Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 160e92fd1d4987019f63b27d1392e97fb4ec270c Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-03 16:51:33 +0000 muc/subject.py: make more assertions when setting the subject Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 1b934c6f47bdbf5b53f670f9f55794afc65630a9 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-03 16:50:31 +0000 muc/subject.py: replace magic numbers with text Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 636e252a569e231d3ec1db4eeb2ba49a88938428 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-03 16:48:45 +0000 muc-channel: add a convenience emit_subject_changed method Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 0d54d8155d2f02d106dab6f45aa58a05f22fa3e2 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-03 12:45:22 +0000 muc/subject.py: test calling SetSubject Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 9a3b1476583ab2726f40a917924cbdb7164827f2 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-03 12:34:16 +0000 muc-channel: implement SetSubject Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit b4f1b66d4916144c6155653678592318037b0095 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-03 12:33:41 +0000 muc/subject.py: test for subject flags and SubjectChanged signals Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 72b0a0a4dce061c12cbf406a54059c31beb1a6f7 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-03 12:33:19 +0000 muc-channel: emit SubjectChanged where appropriate Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit e785bb839a8d9e0af6314497a28641c1e2a1c615 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-03 11:40:31 +0000 extensions: update to unmerged Room draft Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit e435637b78212c6604489bf031d8bf0c56d549d5 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com> Date: 2011-10-11 20:55:05 +0300 Disable STUN server tests that exercise Google relay, if that is disabled commit 3e3bf4b79322ec5352c21f5e12019decb56ac44f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-10-03 14:47:20 +0100 ServerTLSManager: remove useless DEBUG output Reviewed-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk> commit a64cd72472d48ad8e88bfebe5e6046f02d4b5c93 Merge: 5f1ad2c 9c86f44 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-28 18:58:10 +0100 Merge branch 'moar-caps' commit 5f1ad2c76f43842856fb01a2dc51648a42f24284 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-28 18:45:23 +0100 Nano-version bump to 0.13.6.1 commit 9c86f446c6a00142c373aae1fa357f5c00f0f2c6 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-28 18:45:08 +0100 connection: document why data forms might cause warnings to appear Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 30315eacd21cd322d0b7adaf743fa57b373f6417 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-28 18:26:55 +0100 Version 0.13.6 commit ca01a7df1a6d7efa06021dba1594ca27380a9129 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-28 18:20:46 +0100 More NEWS for 0.13.6 commit 7fb0ccab3ce97fabcb2009faaa50f5c3e7d04019 Merge: 6211097 c3b6d21 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-28 18:10:41 +0100 Merge branch 'telepathy-gabble-0.12' Conflicts: NEWS configure.ac commit c3b6d2101aa5257a6f1ec927f3b0f3b3911cd2a6 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-28 17:53:39 +0100 nano-version bump! 0.12.7.1 commit 8acd2b0e95fa4b732e1b82eacbc85f0fddf05fee Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-28 17:29:32 +0100 Version 0.12.7 commit c48f3da4949aac74b2c455983ca982166ff031db Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-28 17:29:23 +0100 NEWS for 0.12.7 commit 498920f1f69cdccbcc3c5f2146a1b1b9b5cd5976 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-28 14:17:15 +0100 connection: drop invalid or duplicate data forms from channel managers Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit f670d0082e850835b93405eac32da24d94496975 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-28 15:07:02 +0100 Revert "connection: deal with not being able to hash self presence" This reverts commit 9f8f181fd943f1e96f898c736ee4977d310b94a1. commit 6d7811ac1c1e0b7b98431d567626bff1f4161d3b Author: Jussi Kukkonen <jku@linux.intel.com> Date: 2011-09-01 23:48:35 +0300 mail notification: ensure google notification setting is correct Google XMPP server has an (extension) setting that can be used to enable mail notifications, see https://code.google.com/apis/talk/jep_extensions/usersettings.html https://bugs.freedesktop.org/show_bug.cgi?id=40565 commit 5e27d123f8a24509a619010cf2dedbbd632bbf0b Author: Jussi Kukkonen <jku@linux.intel.com> Date: 2011-09-01 23:45:54 +0300 mail notification: recognize "google:setting" namespace commit 55b092e583fd16ac18440c989bfc603176dbd610 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-27 14:59:21 +0100 connection: log what form types clients contribute Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit b9c8a79c4f562a6971eb051848685b69d6b986d9 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-27 14:42:05 +0100 presence-cache: refactor data form replacing into its own function Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 1edf9a4dbc1bbbd24a9141b676eb310d6e4be919 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-27 14:39:20 +0100 dataforms.py: be sure to call UpdateCapabilities with arguments Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit c005728f1cab3ae10aeae2cc51c4691f9aa03593 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-27 14:38:23 +0100 presence-cache: use hash table iters instead of foreach This is nicer and can terminate early. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 084793e6ec80af7d7c6b891a6bdb896ab9f03d1a Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-27 14:34:32 +0100 presence-cache: clean up code to replace data form arrays This was broken in the case of data_forms == NULL as it left info->data_forms pointing to a freed GPtrArray. Good catch, Will! Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 3d42307058b3a1bc31138b53b21e7ed8bf681e1b Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-27 11:58:50 +0100 connection: fix comment placement in an if/else block Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 6211097e8b2df75b79313746b6f7c4e081921eb5 Merge: 060acfb c4bfa12 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-26 16:38:48 +0100 Merge branch 'soup-is-optional' Conflicts: tests/twisted/jingle/google-relay.py commit c4bfa12099858594001c15a2b1750977aaef814d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-26 15:26:21 +0100 tests: when built without soup, don't test google relay commit 060acfb55bdafcafff595eff6e2ed3ae24877c04 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-21 13:47:21 +0100 Rename test-initial-aliases to match Makefile commit c84617178fd951ece907cec4eb5c1da44c2123bb Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-20 15:58:37 +0100 Call: handle google relay reply after channel dies Previously, if the Google relay server replied to our HTTP request after the Call channel had already gone away, we'd crash. Fixes: <http://bugs.freedesktop.org/show_bug.cgi?id=39768> commit e7cc7f9b9b41923ab57b284776911f82102d06b3 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-20 15:58:37 +0100 Call: test google relay reply after channel dies It's kind of funny: the bug fixed by the previous commit repeatedly surfaced for StreamedMedia channels in a variety of situations (you closed the channel, you removed yourself from Members, you disconnected the connection), and hence there's a lovingly-written exhaustive set of test cases for those scenarios for incoming and outgoing channels. But of course they weren't run for Call channels… This patch only makes the bare minimum number of changes to the test to at least slightly exercise the Call code. It's not as exhaustive as it is for StreamedMedia, and works almost by accident, but hey... commit 06d98c31504139136336160aac4b1f094a8ccc88 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-20 15:58:37 +0100 Call: handle google relay reply after channel dies Previously, if the Google relay server replied to our HTTP request after the Call channel had already gone away, we'd crash. Fixes: <http://bugs.freedesktop.org/show_bug.cgi?id=39768> commit f1ece52985d24d734462f96e8a33db8ced771fdb Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-20 15:50:28 +0100 jingle/google-relay: use functools.partial commit 114a25a2cb9a1f57560cca30bddfeaeaeec0e3b6 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-20 15:21:50 +0100 Roster: rename updates_nicknames to updated_nicknames This is a typo! commit b070c914d5f59f2f5b7a5cd1ad476b9c4729eaaf Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-20 15:19:17 +0100 Roster: don't emit nicknames-update with no nicknames. This was triggering an assertion failure in one of the signal handlers, which asserts that the array is non-empty. Reviewed-by: Marco Barisione <marco@barisione.org> commit 2413a026e53c42fa0973b0a861587dff12c1e65e Author: Derek Foreman <derek.foreman@collabora.co.uk> Date: 2011-05-16 12:19:44 -0400 Remove duplicates from source file lists Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit acaf2d4c7f54ecad880450987f716aface11d741 Author: Derek Foreman <derek.foreman@collabora.co.uk> Date: 2011-05-16 12:17:50 -0400 Check for presence of gmodule Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 3967b4ccf908c70be173c1b27617ebdc19fd6c48 Merge: bc40410 40b5b45 Author: Marco Barisione <marco@barisione.org> Date: 2011-09-20 12:44:00 +0100 Merge branch 'grouped-alias-updates' Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=40943 Reviewed-by: Will Thompson <will.thompson@collabora.co.uk> commit 40b5b45203098ce308a51b6c88c4ab31d40e047d Author: Marco Barisione <marco@barisione.org> Date: 2011-09-16 18:57:56 +0100 roster: emit a single signal for all the aliases updated at the same time commit d4cfda9cd64923c81d87b8f875b5f20658023a17 Author: Marco Barisione <marco@barisione.org> Date: 2011-09-16 16:39:02 +0100 conn-aliasing: add a plural version of the nickname-update signal handler commit bc40410024314a700ef70702502f868630e02e8b Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-15 16:05:03 +0100 with-session-bus: import --also-for-system from Salut Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit e829ba1c802f8b06bf678772046833d0a1c6fd0b Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-12 18:03:27 +0100 with-session-bus.sh: retain newline when forking dbus-monitor commit 30a7ac413f66178c3cceae63baab487365ef8845 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-07 17:02:18 +0100 connection: add more public helper functions for getting caps This is useful so in a Gabble plugin you can get the TpBaseContactList and then look at each contact's caps for whatever reason. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 485c9d8ad1365cbee11b8c7769425d5d5c02fc27 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-07 15:25:14 +0100 connection: fix typo when checking whether a client can do anything Naughty Simon. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 9ca541ae76b6dc1838f11eaea21d6e284d5d7965 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-07 15:18:40 +0100 connection: stop trying to print data form titles as debug messages Approximately no data forms in entity capabilities have titles set properly anyway, so outputting: (null) (null) was getting dull. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit c0e658ed4e99555466e5d1c09140f43cb4faf898 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-06 14:21:51 +0100 connection: add pick_best_resource_for_caps function Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit d96a1a927959b43586a888c56d45ab8b23b60de0 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-06 14:21:31 +0100 connection: add get_jid_for_caps utility function Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 70580a776d7b54a950042ea6c08b4949d96f2332 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-06 14:17:44 +0100 connection: add get_session public function Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 003e6186d70640c32b85cdf5bc920cbd94882e43 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-06 14:17:01 +0100 connection: make get_full_jid part of the public API Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 7436f9a3144929ffb10e6c9b1c240d153529a5a3 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-06 14:15:57 +0100 presence: implement WockyXep0115Capabilities interface Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit e34fde96b5e3c5a766f66380e1e09a3f9a9074d2 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-06 14:15:30 +0100 presence-cache: add get_handle utility function Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit d63ca76093a79a630a69fc2d49384004f3f5fe33 Author: Jussi Kukkonen <jku@linux.intel.com> Date: 2011-09-01 23:48:35 +0300 mail notification: ensure google notification setting is correct Google XMPP server has an (extension) setting that can be used to enable mail notifications, see https://code.google.com/apis/talk/jep_extensions/usersettings.html https://bugs.freedesktop.org/show_bug.cgi?id=40565 commit dc7ba1b82823a8e637f1bf3e8257ff44132f44b1 Author: Jussi Kukkonen <jku@linux.intel.com> Date: 2011-09-01 23:45:54 +0300 mail notification: recognize "google:setting" namespace commit 9b3b88ab8a7fdeeeb98faae23e6b53b1051e3415 Merge: 9b3e977 97175d8 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-05 18:53:26 +0100 Merge branch 'telepathy-gabble-0.12' commit 97175d86d43f0d9ebe7fa3f3f0ed96e825ae8094 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-03 08:32:16 +0100 MUC: add password test I left this out of 2d7c9db :( commit 9b3e977b7b08c6cfa055183f1914ab1b1b891c4b Merge: e3d4b85 6c102c0 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-05 18:49:55 +0100 Merge branch 'CAPS-LOCK' https://bugs.freedesktop.org/show_bug.cgi?id=40390 commit 6c102c09557e2988386751ffb1ee7186f0747578 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-26 11:00:49 +0100 Connection: assume all handles have ContactCaps Previously, some places in Gabble which called gabble_connection_get_handle_contact_capabilities() did not assume that it never returns NULL. But (due to the implicit text caps for everyone) it is guaranteed always to return a non-NULL array of capabilities, so we can simplify the places that call it. commit 00de9b2849013d7bc011ef34d3a3cb5a2730a83c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-26 10:56:49 +0100 CapsChannelManager: correct English in a comment commit 29d365c626445bd3f0c30d9cd6a1103cc87c3d96 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-26 10:55:20 +0100 Connection: simplify getting ContactCaps without presence If we don't have presence for a contact, we do not have any capabilities for them. But we always want to ensure that all contacts are capable of IM. So, currently there is a special-case in the caps-gathering code: if we have no presence, we only call _get_contact_capabilities on the IM factory: its implementation of this virtual method, unlike all others, doesn't care if it's passed a NULL set of caps. Otherwise, if we do have a set of capabilities, we call gabble_connection_build_contact_caps(), which is essentially a foreach over all channel managers, including the IM factory. I think it's neater to avoid the special case, and treat "no presence" as equivalent (for capabilities purposes) to "presence with no caps". commit e3d4b85839b465e160b91ac7b581dabd1097fc6e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-03 11:23:33 +0100 Remove support for legacy Presence. This was Olli's idea. He claims that building the old-school signals causes measurable CPU usage on accounts with lots of contacts (think: Facebook). It certainly causes D-Bus spam. Neither Telepathy-GLib nor TelepathyQt4 use this old interface. Empathy doesn't, either. I think this should be safe. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=40598 Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit b16296db19ecbca6cfaf8d669c8997dbedb8e5fc Merge: 8569bab 2d7c9db Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-09-05 18:39:02 +0100 Merge branch 'telepathy-gabble-0.12' commit 2d7c9db4766394d39ff3b3fc42cf7e928e4f4751 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-03 08:32:16 +0100 MUC: don't forget password when handling nick conflicts WockyMuc has a property, :password, representing the current password being used to join the MUC. GabbleMuc previously had a private variable, 'password', which was used for this. In the port to WockyMuc, setting the private variable was removed, but it was still used when re-attempting to join after a nick conflict. (I think the password should be a parameter to a hypothetical wocky_muc_join_async() which does all the nick conflict crap for you. Having this as state that kicks around on the WockyMuc for ever is bizarre—once you're in the room, you usually don't use the password, unless you're the owner, in which case you can retrieve the current password *which may be different*!) This patch expunges the zombie private variable, and ensures WockyMuc:password is only set when the user provides a password, not at every join attempt. It adds a test for this case, and some of the basic functionality of Password (which subsumes some incidental testing of the Password interface in muc/presence-before-closing: the only test that touched Password at all!). Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=39790 Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 25c3f4dd8b9360cb531f0fc3a653094ce1e9b042 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-01 14:30:15 +0100 test plugin: make TestChannelManager implement CapsChannelManager ...and give back a new data form in the represent_client function. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 9f8f181fd943f1e96f898c736ee4977d310b94a1 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-02 16:29:04 +0100 connection: deal with not being able to hash self presence If a data form is bad we might not be able to, so we shouldn't crash. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 00a7c2fb7195374c39f2b9c9be8254822e5484e8 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-02 16:38:43 +0100 caps_helper: give data forms back to disco utility functions Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit adea0ce7c2e48190fcf18c11717380e551432e04 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-02 16:35:48 +0100 jingle-share tests: also consider data forms in disco replies Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 6dfe751e17618a5f29f6611b649e7a1bbe0969d3 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-02 16:31:41 +0100 caps_helper: split out code to read disco replies Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 3968fd5da0e56006fde7bf6832e605ef8f544572 Author: Marco Barisione <marco@barisione.org> Date: 2011-09-02 11:24:30 +0100 Stable Gabble was accidentally using the master branch of wocky commit 587da15932d178ad289e81b039dcabb4e90984c5 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-01 14:19:52 +0100 gabble: add capabilities.h and caps-channel-manager.h as public API Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 1afd2d8e2fab78542467b2f36f08fc6e84523f91 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-09-01 12:13:16 +0100 caps_helper.py: add initial data form parser We want to be able to check that disco replies with data forms still have the correct hash. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 45dc8f926f18be249f24f66deb589907bda47f98 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-08-31 16:29:43 +0100 connection: send data forms in disco query replies Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 7c6971a75a6eb32c77b64a7e9754e1fdb2a694af Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-08-31 11:40:45 +0100 presence-cache: store data forms from disco replies and the caps cache Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit d887fdc2d23bf00322c9923e8eead7c5f0607302 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-08-31 08:58:55 +0100 presence: start holding a list of data forms Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 28b64163e8bbca02de308612f6653ed291e2b1df Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com> Date: 2011-09-01 13:22:42 +0300 Don't allow the stub for GabbleGoogleRelayResolver to be empty g_slice_alloc() behavior for zero-sized blocks is undocumented and leads to obscure code paths taken. commit 39fc20df8c978ebf072998cc1077a48ec6b41593 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com> Date: 2011-09-01 11:32:08 +0300 Ignore the relay info in Jingle stanza if Google relay support is disabled commit d2b3153f84e1f010b02ce4b084f3711ab95060e8 Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com> Date: 2011-08-31 16:14:09 +0300 Make Google proxy support optional The intent is to make optional the dependency on libsoup (fd.o #40537). commit 60b5bc0cf55ee60b0c66384e544a9f35d3b3688d Author: Mikhail Zabaluev <mikhail.zabaluev@nokia.com> Date: 2011-08-31 13:56:10 +0300 Isolated the Google relay resolution code in a separate source file commit 8569bab0c49f88e397aebc9fcf2d045a21b5be75 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-08-29 17:46:58 -0400 Announce the camera-v1 caps bundle so that the Google UIs put a little camera for us https://bugs.freedesktop.org/show_bug.cgi?id=40471 commit 5dcf95eaf432b5af1edf82e87f40f795a3265a35 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-08-30 11:42:50 +0100 connection: save data forms created from UpdateCapabilities These aren't used yet. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit d9ecbbc1bbe573049e8cbb3348c600ec7512c84e Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-08-30 11:18:45 +0100 caps-channel-manager: add data form argument to represent_client Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 81176c13d19530ac37401e7b9e597ebfbd2a2904 Author: Olivier Crête <olivier.crete@collabora.co.uk> Date: 2011-07-19 21:01:10 +0300 presence-cache.c: Add Android presence cache bundle Let's add another "well-known" bundle https://bugs.freedesktop.org/show_bug.cgi?id=36996 commit 78015e5dc12c37d6a99b417d8e1abea9e975e607 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2010-02-05 13:41:29 +0000 Add a summary of options to the end of configure commit 068445479b27c036e01e6e2f7134f7cfd2f48d6f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-17 16:25:07 +0100 nano version bump commit 6c86d9bc863af7504bfafeb1212360cfd0f2b70d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-17 16:22:35 +0100 bump nano-version to 0.13.5.1 commit 6f7803086bdce403b2b32e83d16a083bce9d0ee9 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-17 16:18:11 +0100 0.13.5 commit 881c1802539f5ee4a8d095d0c97abc6088b301bc Merge: 7d56957 45254c4 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-17 16:17:42 +0100 Merge branch 'telepathy-gabble-0.12' Conflicts: NEWS configure.ac commit 45254c4fd2bd13f6ddb7cdf0e26f2d35cb4ba8ff Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-17 16:13:07 +0100 Version 0.12.6 commit 7d569578494b20abd7889bfd7d3fd4defef07568 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-17 15:54:44 +0100 nano version! 0.13.4.1 commit a94dbcdd0d3eed3cecc84e2c825b2002ec61d60f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-17 15:30:41 +0100 version 0.13.4 commit ddea8e83665ae5e5fa9f256091992f3065c77797 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-17 15:30:16 +0100 NEWS for 0.13.4 commit e4590e849801ff4b0f2ddb9ad23a7da210212395 Merge: a89eb63 ac4485a Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-17 13:12:57 +0100 Merge branch 'telepathy-gabble-0.12' Conflicts: NEWS configure.ac commit ac4485aa2b217b622fca2529f456b39ec4a0e0b7 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-17 13:09:20 +0100 nano-version bump! commit 7ae6e69ddc96f5d8fb38208e46a2f44c7daca245 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-17 12:41:09 +0100 Version 0.12.5 commit 1bc901f50cf3d5bb7dec0729e018ba00e24f6f06 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-17 12:40:43 +0100 NEWS for 0.12.5 commit a89eb63f14b55f5e291490c8cbaa114e2a7a2b53 Merge: b183b4f b32a81d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-17 12:27:14 +0100 Merge branch 'old-bugs' commit b183b4f20361f96cc7326da62b1705bb4758f09e Author: Olli Salli <ollisal@gmail.com> Date: 2011-08-10 21:53:26 +0300 Update NEWS commit 5c201dffc0c71d1a0500a341709b4930d6187f97 Merge: df2e4bd 5a62326 Author: Olli Salli <ollisal@gmail.com> Date: 2011-08-10 21:43:13 +0300 Merge branch 'tube-caps' Reviewed-by: Simon McVittie (smcv) <simon.mcvittie@collabora.co.uk> commit 5a62326a6d3e91820d6ccec78635151ec403dd1d Author: Olli Salli <ollisal@gmail.com> Date: 2011-08-10 19:22:02 +0300 tube-caps: Test for a bidirectional (no Requested property) stream tube filter commit bd22f64177ae9532b5dd3f6697355545bccc8625 Author: Olli Salli <ollisal@gmail.com> Date: 2011-08-10 19:20:07 +0300 Drop an extra == TRUE in a conditional commit fb81504e14cbd02ae051f06bf39ed7b9f2e85280 Author: Olli Salli <ollisal@gmail.com> Date: 2011-08-10 19:19:36 +0300 private-tubes-factory.c: Use TP_PROP constants commit c44f4f1c601b2f71d08567c94f349f8c719a1a36 Author: Olli Salli <ollisal@gmail.com> Date: 2011-08-10 18:24:02 +0300 tube-caps test: Test that Requested=True filters don't make tube services advertised commit 8ca532d73b98c828b0620bd2ded172fd90a4b893 Author: Olli Salli <ollisal@gmail.com> Date: 2011-08-10 17:52:48 +0300 Don't advertise being able to receive tubes if we can only initiate them commit df2e4bd487e26bf785dbdc85fe50db7a9d35c989 Author: Marco Barisione <marco@barisione.org> Date: 2011-08-05 15:24:57 +0100 Update wocky to fix PEP when power saving is enabled commit cee0ee6d6a8daa2c32b139e28a88b07e3746853f Author: Marco Barisione <marco@barisione.org> Date: 2011-08-05 15:22:02 +0100 Update wocky to fix PEP when power saving is enabled commit 18b99be3be0c0b3ed31e52c25ac545ad6152e85d Author: Marco Barisione <marco@barisione.org> Date: 2011-08-01 14:20:34 +0100 Update the Wocky snaphost and adapt the changes in WockyPing Reviewed-by: Will Thompson <will.thompson@collabora.co.uk> commit 77155451e3145d0c856d4bd3d2e2ae53923463ad Merge: fbb15c3 82d3fbe Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-03 10:21:10 +0100 Merge branch 'telepathy-gabble-0.12' commit 82d3fbe13b68caa242727ad7cc5d60e53926f7c9 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-03 10:11:36 +0100 Connection: correctly install power-saving property. Previously :power-saving was actually mistakenly implemented as a synonym for :decloak-automatically. This only showed up when (on master) I changed the default for "decloak-automatically" to be TRUE (not FALSE, as is the default for :power-saving). commit fbb15c3cb82e6c8944a8797e6f3b7a4a9c24b427 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-08-02 17:46:05 +0100 Turn on DecloakAutomatically by default There should be UI to turn this off, but since people can (in general) IM you even if they're not subscribed to your presence, they should be able (by default) to call you too. Reviewed-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk> commit d5d3107396225812841078dc8f0e3661b916f506 Merge: 7db8678 d0707d6 Author: Marco Barisione <marco@barisione.org> Date: 2011-08-01 17:38:23 +0100 Merge branch 'telepathy-gabble-0.12' commit d0707d61636e16b6acfbb84c0846b9373681b747 Merge: cbe0592 3b87f9d Author: Marco Barisione <marco@barisione.org> Date: 2011-08-01 17:36:23 +0100 Merge branch 'initial-invisibility' into telepathy-gabble-0.12 Reviewed-by: Will Thompson <will.thompson@collabora.co.uk> Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=38706> commit 3b87f9d655f5ecdaca7fffa7de0394037fbec3df Author: Marco Barisione <marco@barisione.org> Date: 2011-07-26 14:46:32 +0200 presence/shared-status.py: test invisibility works with updated servers commit c2e977cf73bb961d3130428e2b5a68f1d54a42fe Author: Marco Barisione <marco@barisione.org> Date: 2011-07-26 14:39:20 +0200 conn-presence.c: make shared invisibility work after the server update The new version of the Google Talk servers supports a newer version of shared status. Because of an unknown version string we were assuming invisibility was not supported. We now just fall back from "hidden" to "dnd" if another resource doesn't support shared invisibility. Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=38706> commit 7db86780825ed1c3459c380fa5b0b209c6287fd3 Merge: 2ec472c 22f6849 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-29 18:54:28 +0100 Merge branch 'null-caps-39464' Fixes: http://bugs.freedesktop.org/show_bug.cgi?id=39464 commit 2ec472c9deb1bbca578c4f3cb939ef8ae3065bd8 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-28 15:57:31 +0100 test bytestreams: also only listen on localhost commit 885d9cdc175f58c5490c64d38e585678e8e10ebb Author: Paul Seidler <pl.seidler@gmail.com> Date: 2011-04-03 15:16:37 +0200 tests: use localhost https://bugs.freedesktop.org/show_bug.cgi?id=35968 commit 22f684987e53d0043a7739c6c1b1929f639c659f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-28 15:28:53 +0100 Add a regression test for fd.o#39464 commit 147ebf5404c5818aba122e25cf1c7844cbd99a59 Merge: 5b423d6 49606ef Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-27 17:36:27 +0100 Merge branch 'rudolph' Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk> commit 5b423d671523b7f3b28755d0de4a064540d8e814 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-27 16:25:57 +0100 bump nano-version to 0.13.3.1 commit f50a1e625217d528c6a6406d6ce610773910d1d8 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-27 16:22:36 +0100 make-release-mail: detect headers more robustly. I just broke this by having a line beginning 'telepathy-gabble' which was not actually a version header. commit 7f64afa396c7e639e7920a60d46b980a12d5c2ee Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-27 16:01:51 +0100 Version 0.13.3 commit b099c2a269804857cf41a393cca22f8b82704ec6 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-27 15:58:16 +0100 NEWS for 0.13.3 commit b5ec55b7056634a679ce277f3575f09214d5372a Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-27 15:42:41 +0100 Update Wocky submodule to fix fd.o#36077 commit a0ad5e286229d90b79942bf32e29e2874d278a31 Merge: 2b4881b cbe0592 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-27 15:40:16 +0100 Merge branch 'telepathy-gabble-0.12' Conflicts: lib/ext/wocky commit cbe0592fbfbd2706f3c306da860b88e61e33a82e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-27 15:20:01 +0100 bump nano-version commit ecf29e6a17441829bd369bd2d25245c8dcb7aa73 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-27 15:07:59 +0100 Version 0.12.4 commit 3ad658923c085f7ecad5cca06ab0de77fa7eadf4 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-27 14:49:52 +0100 Update Wocky submodule to fix fd.o#36077 No other changes are included: this is the gabble-0.12 branch of Wocky. commit 49606ef2f8637792e0b4fc5cfc77851259867fd5 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-27 14:08:18 +0100 JingleFactory: stop including fake loudmouth! commit 50aa29eceeaa7eefa336a5dee2641a02b2c8e846 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-27 13:40:44 +0100 JingleFactory: wockify google:jingleinfo callback This squashes the spurious "ignoring jingleinfo from '%s', not ourself nor the server" debug messages that showed up on pretty much every incoming IQ set, because some idiot (me) put that check before the check for a <query xmlns='google:jingleinfo'/> element. Using _register_handler_from_server() and pattern-matching makes this a *lot* neater, I think—and objectively, it's half as much code. commit 319c851c095dea4a4425f80c4db67947cb1abdbd Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-27 13:33:32 +0100 JingleFactory: wockify jingle action callback This could be better: we could match dialects up-front. But hey. commit fa61e14c10296b945cbb75585ad87d673b577426 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-26 15:37:54 +0100 JingleFactory: use constructed, not constructor. This also expunges a weird FIXME! commit 138cea6ca12d5a929d52aa2e86b9f0e34919e35a Author: David Laban <david.laban@collabora.co.uk> Date: 2011-07-22 02:28:15 -0400 presence-cache: don't crash if computed_hash == NULL commit 2b4881bb7df570c4840dc4cfdea8ee3ca9176c92 Merge: 4080a24 05faadf Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-13 17:13:09 +0100 Merge branch 'encryption' Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=38719> commit 4080a244d604207bac505073295b7ed1f1556538 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-11 17:30:04 +0100 test-debug: use ProxyWrapper Obsessive? Moi? commit 133c168d3a2838293c2d63b7796a6a942e67ea39 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-11 17:29:35 +0100 ProxyWrapper: add a sensible ‘no other interfaces’ default commit 818528a2f36a74c0a493fe77daa9f12f35de9285 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-11 17:20:45 +0100 Test Debug object's absence with --disable-debug 38a6178 changed test-debug.py to verify that the Debug object is present but non-functional when --disable-debug is passed to configure. Gabble actually doesn't have a Debug object at all in that situation, which I think is reasonable—so this now tests that calling GetMessages fails. The test doesn't make any particular assertions about the error. Right now it happens to be 'org.freedesktop.DBus.Error.UnknownMethod' but it really ought to be some kind of ‘unknown object’ method. So. commit feed269a8d964c61fa6b271591ed2311e6fba75e Merge: ebb6963 1e3b981 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-11 16:19:15 +0100 Merge branch 'debug-stubs' https://bugs.freedesktop.org/show_bug.cgi?id=39046 Reviewed-by: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> commit 1e3b9812fce185efb830b5aec5f5912472e49cd4 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-08 14:13:15 +0100 Update Wocky for corresponding --disable-debug fixes commit 99ee60ef205efa3d6b77134bd2003d373477f9cb Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-08 10:46:36 +0100 Define a static inline no-op DEBUG with --disable-debug commit ebb6963dc788faa9683f2b976b1db19187819351 Merge: 38a6178 74e4699 Author: Marco Barisione <marco@barisione.org> Date: 2011-07-07 14:23:16 +0100 Merge branch 'extra-certificate-identities' Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=38749> Reviewed-by: Will Thompson <will.thompson@collabora.co.uk> commit 74e46998689e8049faa9eb87eca0886ab1f72481 Author: Marco Barisione <marco@barisione.org> Date: 2011-06-28 15:39:33 +0100 server-tls-channel.py: test that gabble verify hostnames Gabble should accept certificates for hostnames if they match the hostname in the JID or one of the hostnames in the extra-certificate-identities parameter. commit 2672b6c7e03a303aed2649f925dac486ab9fb469 Author: Marco Barisione <marco@barisione.org> Date: 2011-06-28 15:39:07 +0100 Move the extra domains to trust from the TLS channel to the manager commit ed99546dc9ee402f42727702305b3125a73724af Author: Marco Barisione <marco@barisione.org> Date: 2011-06-28 15:38:29 +0100 TLSManager: check the connection before the non-interactive verification commit 86726ddce8ad38cfca1a753d3b7b8940bfe5f82b Author: Marco Barisione <marco@barisione.org> Date: 2011-06-28 15:37:45 +0100 ServerTLSChannel: make reference_identities a GStrv and not a GPtrArray In this case the GPtrArray doesn't give us any advantage and doesn't make clear that the content is a NULL terminated array of strings. commit a6c42b97d4e1984451c919048cc04df72b4c454d Author: Marco Barisione <marco@barisione.org> Date: 2011-06-28 15:36:53 +0100 Add an extra_identify argument to the TLS verification functions Update the Wocky snaphost and adapt the TLS manager to the changes. Now the TLS verification functions have an extra argument for the additional hostnames that we have to consider valid. This is useful, for instance, when using Google apps. Rather than providing a certificate for the JID’s domain part, the server provides a certificate for talk.google.com; if the user has explicitly configured a ‘Google Talk’ account, it's reasonable to accept certificates for this domain. commit 38a6178a7529e3b1bf1ab8439185541e01c18dd5 Author: David Laban <david.laban@collabora.co.uk> Date: 2011-05-31 16:10:16 -0400 test-debug.py: actually check that no debugging happens Reviewed-by: Will Thompson <will.thompson@collabora.co.uk> commit f7cd57841f39ca7d007623745ea2c33acaa97c88 Author: Vincent Penquerc'h <vincent.penquerch@collabora.co.uk> Date: 2011-05-23 12:29:52 +0300 Fix tp-yell includes being read from /usr/include instead of the submodule Since tp-yell gets installed in ${PREFIX}/telepathy-1.0, adding include paths for some other telepathy library (such as tp-glib) would automatically make tp-yell headers discoverable. Fixed by moving the tp-yell submodule paths before the ones for any telepathy library, so these will be found first. This fixes the build if you have a version of tp-yell installed which does not have a symbol that tp-gabble needs. https://bugs.freedesktop.org/show_bug.cgi?id=37492 Reviewed-by: Will Thompson <will.thompson@collabora.co.uk> commit c356abc2de2b33cb250b143bb5a8b28068971f4d Author: Vincent Penquerc'h <vincent.penquerch@collabora.co.uk> Date: 2011-05-23 12:29:52 +0300 Fix tp-yell includes being read from /usr/include instead of the submodule Since tp-yell gets installed in ${PREFIX}/telepathy-1.0, adding include paths for some other telepathy library (such as tp-glib) would automatically make tp-yell headers discoverable. Fixed by moving the tp-yell submodule paths before the ones for any telepathy library, so these will be found first. This fixes the build if you have a version of tp-yell installed which does not have a symbol that tp-gabble needs. https://bugs.freedesktop.org/show_bug.cgi?id=37492 Reviewed-by: Will Thompson <will.thompson@collabora.co.uk> commit 5c06d57058f169401449039b7148470ca1784699 Author: Thomas Flueeli <tflueeli@gmail.com> Date: 2011-02-02 22:59:56 +0100 gibber: fix TCP connection establishment on Windows https://bugs.freedesktop.org/show_bug.cgi?id=31621 Reviewed-by: Will Thompson <will.thompson@collabora.co.uk> commit 9086cd4c9be315aa91a6284ffecb65178c89c8c1 Author: Thomas Flueeli <tflueeli@gmail.com> Date: 2011-02-02 21:02:54 +0100 gibber: add workaround for GLib bug on Windows https://bugs.freedesktop.org/show_bug.cgi?id=31621 Reviewed-by: Will Thompson <will.thompson@collabora.co.uk> commit 04763e4bc8ed32c208c75209b66221ab46290005 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-07-06 18:40:13 +0100 Set the DBus_Property flag on DecloakAutomatically Without this, MC won't update the property on running connections. Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 51ddcba7fde8c2f9db5cd01930652318093c0032 Merge: f54614c 0acb80d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-28 14:00:59 +0100 Merge branch 'more-alias-and-vcard-tweaks' Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=11321> Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk> commit 05faadffcce2573f788c979b9d85bf78721f84c4 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-28 13:49:21 +0100 Fix Make dependencies for write-mgr-file All the parameter information lives in protocol.c these days. commit 0acb80d4c7669d26fe543e515473ad3f7dfbe11d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-28 10:59:20 +0100 Correctly clear our own alias when asked to. Previously, Gabble would include an empty <NICKNAME/> node in your vCard, which kind of offends my inner purist: it should just leave it out. En passant, this should also fix clearing the name='' attribute on the roster for yourself (if you're on your own roster) but this is untested. commit 0f30bcdcaab39a2ebcaafb42272056d79f126c11 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-28 10:57:41 +0100 gabbletest: fix expect_and_handle_[sg]et_vcard I wrote these, and they've *always* been broken: • _get_ would include two <vCard/> elements in the reply: the first (from the query) would always be empty. • _set_ tries to update the global 'current_vcard' variable, but because it wasn't declared 'global' it did not update it. Astonishingly all the tests pass... commit 4080addd6c2fa879b69e1e9b4567ccac0cf15697 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-28 10:30:24 +0100 test-set-alias: clean up vCard check. This makes the test more thorough: it actually checks the structure of the vCard… commit 22382935be99e027da46303107926a15cd8f3017 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-28 10:19:12 +0100 Test setting our own alias via PEP Astonishingly, this was untested... commit 17d99f5e7ed7b4837d5367950a99773fb61bf646 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-28 10:11:08 +0100 Aliasing: handle SetAlias({contact: ''}) better Previously, if the user set a contact's alias to '', Gabble would change its alias on your roster to the empty string… this is not really ideal. This patch makes Gabble switch to using a cached remote alias for the contact, if any; if there is none, it simply removes the name='' attribute from the roster entirely, and tries to make a request for a better nickname. commit abd99988770e2fdbd8bd811c8e08662fa21e7d0d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-28 09:57:20 +0100 Aliasing: split out cached remote alias lookup There are no code changes in this patch: it simply moves the middle section of _gabble_connection_get_cached_alias(), which deals with looking for cached aliases that the contact specified for themself (on PEP, in their vCard, in their MUC JID, etc.) into a separate function. It also adds a docstring to _gabble_connection_get_cached_alias(). commit 928ef53affeb52d6ed380078d1acabd7f1b4dfec Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-22 00:27:42 +0100 test-save-alias-to-roster: ack and echo roster pushes I was adding some more stuff to this test and realised that it's technically misbehaving as a server: the server MUST (of course) ack the roster update the client says, but it also MUST send roster pushes to all connected resources, event to the resource who made the change. Gabble relies on this, and only respects changes to the roster when the server pushes them to it. (I think this is fine, it means there's only one code path.) This test happened not to ever update a roster item more than once, so not acking the pushes didn't matter so much. It also never depended on reading back stuff that it added to the roster. But I'm about to add a section which will. commit e4450664ff14d65b76f869aeb0aeb7cc9fe51438 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-22 00:26:25 +0100 Aliasing: remove a hateful g_hash_table_foreach commit 7bea4d961ec7361455258ed01750df28a7207c26 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-22 12:34:42 +0100 ContactInfo: don't claim PHOTO is unknown Previously this code would log “unknown vCard node in XML: PHOTO” for every vCard that flew past. This is misleading: PHOTO is perfectly well-known, it's just handled by a different bit of code. So this patch adds the notion of an ignored field, which the ContactInfo code knows about but does nothing with. I didn't add any of the other fields mentioned in the comment at the end of the field table: they're not handled anywhere, so it may arguably be worth logging something about these. commit b32a81d5436cb6f6d0c6435674fc424cabfed9e3 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-27 18:49:00 +0100 MucChannel: fix coding style violations commit 12ea43016a73e853a1a6ad8227f2a6f109474abf Author: Michael Scherer <misc@mandriva.org> Date: 2011-06-27 18:41:35 +0100 Support XEP-0012: Last Activity Patch largely rewritten by Will, since Gabble has changed a lot in the two years since he rejected it on (in retrospect, shaky and unnecessarily hostile) grounds. Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=11688> Signed-off-by: Will Thompson <will.thompson@collabora.co.uk> commit 901577fd23a6e7f7e639be6c8d8b086a3531a091 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-27 18:03:36 +0100 Remove TpBaseConnection.connected callback. This OLPC-specific function can just be called from the ::status-changed signal handler. I've called it at the end of that function because the 'connected' vfunc is called just after ::status-changed is emitted, so this shouldn't change the order of operations in the OLPC code. Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=12041> commit 0f00b08488ef0459fdb6d8f85d55b049d4dc0245 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-20 12:51:40 +0100 Enable require-encryption by default This seems like a reasonable thing to do in 2011. commit f54614c40756f382d1a608054f1b711ff6390d5c Merge: 7d58d83 11ddfc2 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-24 20:12:12 +0100 Merge remote-tracking branch 'origin/master' commit 7d58d83eee6624c66001582d1f56caadedaf82ab Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-24 20:11:30 +0100 Bump version to 0.13.2.1 commit ea425adba81a2681af4c4ed7184972deae378331 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-24 19:57:18 +0100 Version 0.13.2 commit ac2df5eacd34852d6d6ddf584bd2394812e66ad6 Merge: cf9ed52 fcfbc06 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-24 19:55:03 +0100 Merge branch 'telepathy-gabble-0.12' Conflicts: NEWS configure.ac src/presence-cache.c commit fcfbc06d3f679a8266f13921ff3771bd07cf7f24 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-24 19:50:08 +0100 bump version to 0.12.3.1 commit a1d33d82c8645303e279e20033d8f96bc6f6e567 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-24 18:48:03 +0100 Version 0.12.3 commit 18a8b11833af6b8b2e62e4ee3bd3037a8b5b2c2f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-24 18:47:45 +0100 NEWS for 0.12.3 commit 712bbe2b59ed5746cee50604956b0cb842ea9cc4 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-24 19:35:23 +0100 FTChannel: don't assert about handle-type in setter telepathy-glib's default for TpChannelIface:handle-type has changed in 0.15.2: it used to be NONE, and now it's UNKNOWN. This broke both Salut and Gabble… But as the comment says, it's not meaningfully writeable. It's not at all obviously why this assertion is there. commit 276abd5ff84d635eb5f8cd3eee56978f75631722 Author: Colin Walters <walters@verbum.org> Date: 2011-06-24 18:42:23 +0100 Honor NOCONFIGURE for compatibility with gnome-autogen.sh See also: http://people.gnome.org/~walters/docs/build-api.txt commit 11ddfc2e24bbb2fc5297c714dbea88c377a1911e Merge: cf9ed52 1ff589c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-24 15:48:44 +0100 Merge branch 'telepathy-gabble-0.12' Conflicts: src/presence-cache.c commit 1ff589c1e89cf9bb90f59a961c23f2ffa9c3dff0 Merge: cdff268 f7cdb73 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-24 15:31:29 +0100 Merge branch 'fd.o-38603-initial-contact-presence' into telepathy-gabble-0.12 commit f7cdb735461e81b428f9a5d776e2b2487263c8aa Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-23 16:53:23 +0100 Cite fd.o#38603 (presence-before-roster doesn't work) commit fa0990a9810b9629d32dd53840aa415e2d5dbe7d Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-23 16:39:59 +0100 Roster: don't emit presence updates for available contacts Previously, when we received the roster we would announce that the presence of everyone on it we're subscribed to has changed, just for the side-effect of signalling that offline contacts really are offline, not just unknown. This offended me. :) commit d1f7941c3343b1c498e55543c66ae72fa2b880f5 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-23 16:28:20 +0100 initial-contact-presence: reduce duplication of presences commit e0cda613a166e9c538ccdcd8cf5d5feae72a2596 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-23 16:19:11 +0100 GabblePresence: start in state Unknown This has the effect of ensuring that receiving <presence type='unavailable'/> for a contact not previously in the presence cache will not cause a change from Unknown to Unknown to be signalled. commit 66788076de9fb0062d685346d4bb5c444befd3ea Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-23 15:58:11 +0100 PresenceCache: discard UNKNOWN presences in maybe_remove In various places, gabble_presence_cache_maybe_remove() is called to allow the cache to relinquish its grip on content-free offline presences. It should also be able to drop unknown presences: they're basically equivalent, based on whether or not the contact is on our roster. Specifically, this means that UNKNOWN presences for contacts received before the roster has arrived do not linger in the cache, and hence these contacts are correctly signalled as OFFLINE when the roster arrives. Really, I think a better fix would be to change the presence cache to not have this distinction between Unknown and Offline: it's completely based on whether or not the contact is (known to be) on the roster, and this is reflected in the way that the handler for incoming <presence/> passes a different value into the presence cache based on whether or not the contact is on the roster. But this would be a much more invasive change, so I'm not prepared to make it just yet. commit 01d600f1f9f52ac7f021fed2a75e6aa8e7168274 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-23 15:46:28 +0100 Presence: debug GabblePresenceId names where possible (I may have missed a few places, but these are the two I came across.) commit b2616cbb5e25fcd28dbeaad68055b18a399db8b5 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-23 13:48:27 +0100 Build GEnum/GFlags for enums in connection.h Specifically, I want a GEnum for GabblePresenceId so I can include the stringy versions in debug strings. commit a6c0404419c7c84924e1b98783860f8ad99aa18f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-23 12:51:58 +0100 initial-contact-presence: split expect from assertion I think this makes things clearer: we're expecting some presences to change in response to the roster arriving, and we're expecting the changes to be these. This means that the test failing manifests itself as an assertion failure, not a timeout. commit cf9ed5291015fd97b2121dcf38933e8bf885013d Merge: 0b6f5f5 cdff268 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-21 14:24:00 +0100 Merge branch 'telepathy-gabble-0.12' commit cdff268c3965046baa37aac100cceda3e9aafe37 Merge: 63c4d27 6df83a1 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-21 14:21:26 +0100 Merge branch 'aliases' into telepathy-gabble-0.12 Reviewed-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk> commit 6df83a17ff312dc3ad99c79bb40163eba687449c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-21 12:25:05 +0100 Look for better aliases if roster says name=jid. When we discover that a contact doesn't have an alias at all, we fall back to their JID, and write this to the roster (as we do for any other alias we use, to spare our users' precious bandwidth). This is fine and all, but it means that we ignore any subsequent updates from the contact to say that they have a better alias. For instance, we might get a PEP nickname update, or fetch their vCard for some other reason (getting an avatar, ContactInfo, &c &c). In those cases, we would like to have any better alias obtained passively to replace the JID fallback. This is only ever passive: we still don't query for a better alias if the roster says it's the JID. (Clever users can set the alias to the empty string, which has the effect of forcing a refresh.) Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=27361 commit 7a221f03f2a8796895bd48febe1b04168d1b5a1a Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-20 17:00:56 +0100 servicetest: Stringify events more nicely commit e619592d8bfbba0d0679f918f514fdfc08b829cb Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-20 16:51:08 +0100 gabbletest: make stanza events subclasses of Event This looks neater to me. commit a85a67c99ab9085eafc8afe17437253a082e0e08 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-20 16:13:49 +0100 Ignore empty name='' attributes on the roster. Previously, if a roster item had an empty name='' attribute, Gabble would be content to show this to the user, and never try PEP or their vCard for a better nickname. The empty alias is never useful. commit 6ba62283b7052ff49cc223b65d4ac06937ec1043 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-20 16:09:50 +0100 rostertest: support name='' attrs in roster pushes commit 7ac26b27921b9217066c68c2a3333ff616c69a31 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-20 13:26:58 +0100 test-save-alias-to-roster: use contact list fetching helper commit c033c160dfd91a9253aaaac7804922067116cb4e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-20 13:17:55 +0100 test-save-alias-to-roster: expect AddMembers to return This is an ancient FIXME. I think it's safe to say that we depend on a new enough tp-glib. commit 0b6f5f529ac72a479956663175cb6205c41ea394 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-16 18:02:03 +0100 Bump nano-version to 0.13.1.1 commit 17e3e817f5faa349f08b8b541c1ecd65f83234a4 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-16 17:46:27 +0100 Version 0.13.1 commit bd88fdcc79243df03d3fa31259696e1743bd7b78 Merge: a2d6254 63c4d27 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-16 17:45:23 +0100 Merge branch 'telepathy-gabble-0.12' Conflicts: NEWS configure.ac commit 63c4d275abab3aad53923f556473ee902965e2b6 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-16 17:37:36 +0100 National novel versus ionization commit 5e59111c54577650316749a262d6c891f415e603 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-16 17:22:32 +0100 version 0.12.2 commit 052ca8131c8e145714372db249efd9bd04c70f94 Merge: e8e2d23 a88dd55 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-16 17:07:55 +0100 Merge branch 'gtalk-jingle-workarounds' into telepathy-gabble-0.12 These aren't perfect, but they'll do for now. https://bugs.freedesktop.org/show_bug.cgi?id=38352 commit a88dd5529d038f32b3c01b9eb6109eaa10e88604 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-15 18:08:08 +0100 Add a test for working around GMail commit 714e066f8b566f107cef819d4ae6fb7786c8739f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-15 17:53:17 +0100 JingleSession: special-case that GMail can't modify contents. In theory, it can, because it now speaks modern Jingle which has this concept. But in practice it cannot, at least for now. commit b1e774762806b1e0446aaccd42657437e96b01a2 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-15 17:44:40 +0100 MediaChannel: clean up setting ImmutableStreams commit bbf7da0ca74749cfec6701e9cd16f8d7595c4bb8 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-15 17:38:31 +0100 RTP: use video_rtp/_rtcp component names with GMail commit fcc5df48e59c4141151fe6c9d8348a1b676cc88c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-15 17:13:12 +0100 JingleContent: work around GMail omitting content creators commit a29379f10e8ff96bfcd206cd92a12cff25bc5c72 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-15 16:51:33 +0100 PresenceCache: set Omits Content Creators quirk for GMail commit 519504984f9ec70657fdf0bff0eb580bee253237 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-15 16:50:12 +0100 JingleSession: refactor quirk-checking code. commit cd4a003443ff6f9b6e022e9a21146e59c2c56463 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-13 20:15:09 +0100 TransportIface: correct a contents vs. candidates thinko commit a2d6254646182c10d55290f8b3ce53d7a399ca96 Merge: 0a7c31e e8e2d23 Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-06-13 15:16:07 -0400 Merge branch 'telepathy-gabble-0.12' commit e8e2d23490846ebabb7c640bb905b7549883b3af Author: Olivier Crête <olivier.crete@collabora.com> Date: 2011-06-13 14:20:53 -0400 jingle-media-rtp: Codec encoding names are not case sensitive commit 0a7c31ea51c5096e86111f73f157bb87f0f46d0e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-02 19:46:38 +0100 Post-release nano-version and NEWS bump to 0.13.1 commit c4a118850bcaccd6502b6a19cbb61238de1d157e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-02 19:20:59 +0100 Version 0.13.0 commit 3fbd382bf99ce3584d9e167f60c47b9f973cd8c3 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-02 19:20:36 +0100 NEWS for 0.13.0 commit 9f1fa8b567e7f792013ab8a624ad46aa0735e606 Merge: 8d5a2f5 828f2e7 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-02 17:10:08 +0100 Merge branch 'telepathy-gabble-0.12' Conflicts: configure.ac lib/ext/wocky commit 828f2e79137acfd1079a6d1efcc527d8bec724b1 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-02 17:06:55 +0100 Post-release nano-version and NEWS bump commit fe551853438ca44f6f28e5ce334a53e9b9c6b693 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-02 16:11:37 +0100 Version 0.12.1 commit dbc9a937f335ac403436c6fddbd0129693247e49 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-02 16:08:51 +0100 NEWS for 0.12.1 commit b756564ad0a27e1d210b38bf7583ec41d7007574 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-01 14:54:45 +0100 httptest: chain up from HTTPFactory constructor. This fixes jingle/google-relay.py with recent versions of Twisted Web. commit 8f19db01eac316b81d76f4533399fac2d05d72ac Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-02 14:59:09 +0100 Update Wocky snapshot to fix self avatar in MUCs (That is: fd.o#32017) commit 8d5a2f593c4f6c3b2db161be74a03bb3f05270b9 Merge: 5bfe3ed 34b9066 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-01 18:12:51 +0100 Merge branch 'fd.o-32017-muc-self-avatar' commit 34b90665e4860ff5dc022cc7549f070d1de645de Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-05-31 15:07:24 +0100 Add a regression test for avatars in MUCs. commit ef057a2fb297ce639618e89dae4b6cdbd732ff3c Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-05-31 17:42:51 +0100 Update Wocky snapshot for WockyMuc changes This update changes the signature of various signals to include MUC status codes as bits in a guint rather than in a hash table. It also fixes WockyMuc stealing <presence/> stanzas before Gabble's handlers have a chance to get stuff out of them; test for that to follow. Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=32017> but I am not very happy with the fix. commit 4f80d8e0aa86a0b8759c29f0e9e91aaeb909e76e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-05-31 15:14:46 +0100 mucutil: return event from try_to_join_muc commit 0fb508d1b269069aa25f701f82e14060b90051ef Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-06-01 14:54:45 +0100 httptest: chain up from HTTPFactory constructor. This fixes jingle/google-relay.py with recent versions of Twisted Web. commit 5bfe3ede2c17b7dd10d258e5661892967cabcc60 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-05-24 19:41:00 +0100 Explicitly cast to guint64 when passing varargs Without any additional type information, integers used in varargs lists can get passed as the wrong type. In this call to tp_value_array_build() in gabble_muc_channel_constructed(), we should be passing 0 as a a gint64, but I think in practice we're passing it as a pointer-sized thing. (I'm not a C language lawyer, I'm sure someone could correct me on this.) If the type we're passing it as is not the same size as a gint64, this will cause tp_value_array_build() to read off the end of its varargs, probably crashing in the process (because what it reads will probably not be a valid GType). The other call to tp_value_array_build() added in ec8ca6e (for the Room interface) does cast correctly. Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=37165> Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 9b81db6ba12edb6e5c8f9b901f83b9a92d9e23fa Merge: e27aa6f 04f044f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-05-24 14:17:52 +0100 Merge branch 'telepathy-gabble-0.12' commit 04f044fe0ce68dd73d6bb92477106a09fd43dbdd Merge: 53401b9 487dce0 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-05-24 14:17:17 +0100 Merge remote-tracking branch 'origin/telepathy-gabble-0.12' into telepathy-gabble-0.12 commit e27aa6f6fd58533c22b0a2c30579f969378bad3e Merge: efaebdd 53401b9 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-05-24 14:16:31 +0100 Merge branch 'telepathy-gabble-0.12' commit 53401b9d16dc6ed2c2e15b7af5f7c2ad254aac1f Author: Chandni Verma <chandniverma2112@gmail.com> Date: 2011-05-10 20:25:43 +0530 Filter out google-rbc-announcement messages They are server generated containing no interesting information and appear in clients as if sent by peer Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=36647 commit efaebdd96fdfec40aec3e257176e9d16faf44112 Author: Debarshi Ray <rishi@gnu.org> Date: 2011-05-24 01:49:08 +0530 Update wocky (fixes build failure with GCC 4.6) Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=37518> commit 51fdf722717a5646116b554f5feb860d82a26566 Author: Siraj Razick <siraj.razick@collabora.co.uk> Date: 2011-05-23 19:43:57 +0530 fixes : telepathy gabble build break build breaks due to my previous two patches when doing make check this commit fixes those errors Reviewed-by: Will Thompson <will.thompson@collabora.co.uk> commit 1794df70dd67d70e6c8649e47a4f3719fee268d7 Merge: 987722a 4087b2a Author: Marco Barisione <marco@barisione.org> Date: 2011-05-23 14:18:37 +0100 Merge branch 'error_reports' Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk> commit 4087b2a87a9ceb6553030f3514771e7e8ffaf2f8 Author: Siraj Razick <siraj.razick@collabora.co.uk> Date: 2011-05-20 23:52:14 +0530 gabble_message_util_build_stanza: clearer renaming of variables The commit renames INVALID_ARGUMENT to RETURN_INVALID_ARGUMENT, and msg to stanza renamed msg to stanza, the difference between message (a TpMessagerepresenting an abstract message) and msg (a WockyStanza representing an XMPPXML stanza) would be clearer. (based on the comments by:Simon McVittie on f.d.o BUG#33460) commit 1c86beea6be1cb0b5b946da2345d98139072a3ea Author: Siraj Razick <siraj.razick@collabora.co.uk> Date: 2011-04-28 18:53:23 +0530 Fixes : fd.o#33460 by using wocky_porter_send_async() Bug - 33460 - IM and MUC channels should use wocky_porter_send_async(), and emit failing delivery reports url : https://bugs.freedesktop.org/show_bug.cgi?id=33460 commit 5aa9d93472ba3a90410496f453d861ce16f6bd5a Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-05-19 16:47:11 +0100 Smoke-test MUC delivery report flags Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk> commit 5ba21edcf88ef60be5558acc0b0259b5f29e98e9 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-05-18 16:06:52 +0100 muc-factory: don't use a string after freeing it Uh oh! Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 987722a87f929035c4c6dcbcd069e0ba414b25ee Merge: ba3c764 487dce0 Author: Marco Barisione <marco@barisione.org> Date: 2011-05-17 16:42:29 +0100 Merge branch 'telepathy-gabble-0.12' commit 487dce00f8f54ea30edb807b1e1c8eb3c717a85d Merge: e704ea0 a776a13 Author: Marco Barisione <marco@barisione.org> Date: 2011-05-17 16:33:19 +0100 Merge branch 'shared-presence' into telepathy-gabble-0.12 Reviewed-by: Will Thompson <will.thompson@collabora.co.uk> Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=37283> commit a776a13404c9af8f29a0e52d8645bd66622c27d4 Author: Marco Barisione <marco@barisione.org> Date: 2011-05-17 11:41:47 +0100 presence/shared-status.py: test that remote presence doesn't override away commit ba640e0f9d1fd0ab7aa42e21ec5ad2f2bee5622b Author: Marco Barisione <marco@barisione.org> Date: 2011-05-17 15:51:34 +0100 presence/shared-status.py: don't use a weird and avoidable "or" construct commit ca600286bd3f42771a2b8bd35ca2e5d278644d45 Author: Marco Barisione <marco@barisione.org> Date: 2011-05-17 11:39:40 +0100 conn-presence.c: don't override away when the remote status changes commit ba3c764bf634fad3af4ca0a8f35b180ca9ba221d Merge: 52b2d76 e704ea0 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2011-05-16 10:12:01 +0100 Merge branch 'telepathy-gabble-0.12' commit e704ea03ac1cc6a4e38670e3b8f89386154f8894 Author: Simon McVittie <simon.mcvittie@collabora.co.uk> Date: 2011-05-10 18:52:07 +0100 set_status_to_connected: do nothing if we already disconnected Now that we're making more use of GAsyncResult, we can easily get into this situation: * all but one of the preconditions for being CONNECTED have happened; the remaining one uses GAsyncResult (currently that can only be conn_presence_set_initial_presence_async) * conn_presence_set_initial_presence succeeds, and schedules a call to its callback in an idle; we are now ready to be CONNECTED, but because of GAsyncResult calling conventions, we won't call the callback right now * someone calls Disconnect(), and we do so, synchronously; we are now DISCONNECTED * the idle goes off and connection_initial_presence_cb is called, with success, while DISCONNECTED! Bug: https://bugs.freedesktop.org/show_bug.cgi?id=37078 Reviewed-by: Vivek Dasmohapatra <vivek@collabora.co.uk> commit 52b2d7691404457a559fc3fbb09e6f064d7dc33b Merge: 02ad9c4 8f08873 Author: Marco Barisione <marco@barisione.org> Date: 2011-05-12 16:55:32 +0100 Merge branch 'telepathy-gabble-0.12' commit 8f088732c364f1b77f805d65590e30abaf61a707 Author: Marco Barisione <marco@barisione.org> Date: 2011-05-12 16:40:38 +0100 conn-presence.c: remove a line forgotten when fixing a merge conflict Reviewed-by: Will Thompson <will.thompson@collabora.co.uk> commit 02ad9c4dcb40e047eab8fb8777ddf1ccb5e35dce Author: Debarshi Ray <rishi@gnu.org> Date: 2011-05-12 10:10:23 +0300 Update the release mail automation script to contain the Git URL commit 44c5d0ec3de8014efa79f15d85c630ee120db0c9 Merge: d4ddbf7 f99b6f4 Author: Marco Barisione <marco@barisione.org> Date: 2011-05-12 14:20:11 +0100 Merge branch 'telepathy-gabble-0.12' commit f99b6f43f92299c7eb99ccbfef7b806f5b52c1de Merge: fe15601 d5421d1 Author: Marco Barisione <marco@barisione.org> Date: 2011-05-12 13:07:21 +0100 Merge branch 'shared-presence' into telepathy-gabble-0.12 Reviewed-by: Will Thompson <will.thompson@collabora.co.uk> Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=37069> commit d5421d18d1fcb03a86ecfb81e37029c3f015c791 Author: Marco Barisione <marco@barisione.org> Date: 2011-05-10 18:46:05 +0100 conn-presence.c: handle the transition from hidden to away on GTalk commit d895028ef03577768e19476e263455e7f7cbe4a7 Author: Marco Barisione <marco@barisione.org> Date: 2011-05-10 18:33:12 +0100 conn-presence.c: add a function to know if a GabblePresenceId is away commit c5fc80a4d42c794d43332b3626e9ec50ea03580a Author: Marco Barisione <marco@barisione.org> Date: 2011-05-10 14:33:22 +0100 conn-presence.c: leave an away status using <presence/> too When setting an away status on a server that supports shared status, we need to use <presence/> instead of shared status. When we then leave the away status, we want to use the shared status, but GTalk also expects us to also send a <presence/>. commit 1ee540de1b939c676a76cbcf046a4cfb7b77deab Author: Marco Barisione <marco@barisione.org> Date: 2011-05-10 18:47:06 +0100 presence/shared-status.py: test the transition from hidden to away commit 951991f33fea6525469cb712d205ffd1ba2b1eec Author: Marco Barisione <marco@barisione.org> Date: 2011-05-10 14:29:06 +0100 presence/shared-status.py: test the transition from away to non-away commit d669b203f4c09396b3ff04c6dd392c314211ee59 Author: Marco Barisione <marco@barisione.org> Date: 2011-05-10 14:04:34 +0100 presence/shared-status.py: fix a typo (even → event) commit cb9807eb74a70df762d173b57ee04368572c1113 Author: Marco Barisione <marco@barisione.org> Date: 2011-05-10 13:57:36 +0100 presence/shared-status.py: don't unforbid events too early commit d4ddbf79d3b4b845a01cdfcfb14b024d69105dc4 Merge: 6ad9e1e b85a525 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-05-06 11:34:42 +0100 Merge branch 'room' Conflicts: src/muc-channel.c tests/twisted/constants.py Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 6ad9e1e3d6a553405394032ae7258beff37c6f2a Merge: d467f27 fe15601 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-05-05 15:26:02 +0100 Merge branch 'telepathy-gabble-0.12' commit fe156016db44b3cfd8bb3276d3c5a8944e7ff22f Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-04-15 14:27:07 +0100 Don't assume google:queue support from google:roster Dave Cridland asked the Google Talk server team to advertise a google:queue stream feature, and as of this month some time, they do! So we can stop looking for google:roster as well. Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk> Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=36260> commit 5d2927d9155d2388145406c189fdf9d9f8dfcac6 Merge: cacd814 e4ae0fe Author: Marco Barisione <marco@barisione.org> Date: 2011-05-05 15:01:59 +0100 Merge branch 'shared-presence' into telepathy-gabble-0.12 Reviewed-by: Will Thompson <will.thompson@collabora.co.uk> Fixes: <https://bugs.freedesktop.org/show_bug.cgi?id=36058> commit e4ae0fe527dbbffe403026b25eb4c44b3b325715 Author: Marco Barisione <marco@barisione.org> Date: 2011-05-03 18:43:22 +0100 presence/shared-status.py: test that "chat" falls back to "available" commit d010bb78008681707fc6cd4b4c2393c15affd442 Author: Marco Barisione <marco@barisione.org> Date: 2011-05-03 18:41:05 +0100 conn-presence.c: don't allow the "chat" status when using shared status commit 42ca8dd32fa930c85fcdddc16b64220d45429f4f Author: Marco Barisione <marco@barisione.org> Date: 2011-05-03 16:19:06 +0100 conn-presence.c: simplify the non-connected case in status_available_cb commit 49633baeb861f9798cf87809f7421a087e9c9cff Author: Marco Barisione <marco@barisione.org> Date: 2011-04-18 18:32:39 +0100 presence/shared-status.py: always expect an initial <presence/> commit c2b8e2d64edfec296554f72a2d59cca26cbacfe4 Author: Marco Barisione <marco@barisione.org> Date: 2011-04-18 18:29:20 +0100 conn-presence.c: send an initial <presence/> when using shared status commit c0ff90f6850ff80e682a86d45a4a5bda27e75425 Author: Marco Barisione <marco@barisione.org> Date: 2011-05-04 11:54:25 +0100 presence/invisible_helper.py: don't handle privacy lists in XmppXmlStream commit 6bc9759f7140d0ac544659a4a6776c57e405699f Author: Marco Barisione <marco@barisione.org> Date: 2011-05-04 11:53:14 +0100 presence/shared-status.py: don't allow privacy list stanzas commit d04b628113fb93300f6dc82e88addbcf1e58b80e Author: Marco Barisione <marco@barisione.org> Date: 2011-04-15 17:13:11 +0100 conn-presence.c: don't try privacy lists when using shared status commit 06cc941cbada06c876e922df097d93956d88e00f Author: Marco Barisione <marco@barisione.org> Date: 2011-04-07 18:44:14 +0100 presence/shared-status.py: test the correct behaviour with away and xa commit 2a53547a92ec30a31cf4442e60f3f318269952d6 Author: Marco Barisione <marco@barisione.org> Date: 2011-04-07 18:41:30 +0100 conn-presence.c: don't use shared presence for away statuses Away and extended away are mapped to idle in GTalk and are per connection, so they are not set through shared presence. commit 2fb53a5a09c7dea0eee5bf7f54ab0d6c24e8b246 Author: Marco Barisione <marco@barisione.org> Date: 2011-04-07 18:40:43 +0100 conn-presence.c: fix indentation commit c49ea89ae115ad8a0c537a1a491a79604c819072 Author: Marco Barisione <marco@barisione.org> Date: 2011-04-07 18:38:53 +0100 conn-presence.c: don't send <presence/> if we already used shared status commit d467f276329264be0b24f5af6c854fd7a182b531 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-05-05 12:05:33 +0100 Bump micro version for unstable branch. The next release from master will be 0.13.0 commit a2a603bdfb12bc9aa80726bf1f822cc22c76917e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-05-03 13:15:32 +0100 Request pipeline: remove FIXME I checked everything that uses the request pipeline (directly or indirectly), and nothing checks for error codes outside of those specified in XMPP Core. (Previously this code used gabble_message_get_xmpp_error, which would also fetch Jingle, SI and a couple of other class of error.) commit c1be75d93784a9b1b37b0dd717b1494029a675b8 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-03-07 14:12:22 +0000 Remove GabbleXmppError. There is a FIXME buried in here … but the tests pass. commit ea21cdcd49ba24235f97060c056fe9cd9744e69e Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-03-04 11:09:11 +0000 _gabble_connection_acknowledge_set_iq: use Wocky Really, this function should go away, but this will be much easier when we get rid of LmMessageHandler since then (almost) all the places calling it will have a WockyPorter * already. commit 66c905575590cf30b0c3307de55718a813833a09 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-03-01 10:36:33 +0000 Delete my favourite function. :'( commit f510988de177d4c60ce10cc93ec15e1e85bd29bb Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-03-01 10:36:07 +0000 _gabble_connection_send_iq_error: use Wocky commit b32211ace00f3591d6e77d14313787f8d440a483 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-03-01 10:47:21 +0000 Remove lm_iq_message_make_result() commit e1e754f9440a35a69a3ac6dc15ed5190da184047 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-02-28 21:46:39 +0000 Remove three redundant node functions from util.[ch] lm_message_node_has_namespace(), wocky_node_get_child_any_ns() and lm_message_node_get_namespace() have exact equivalents in Wocky. commit 46410a32d5eef705a48b74a6d5aa4f61aa1c3fef Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-02-04 17:09:04 +0000 loudmouth: Remove LmMessageNode Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 3cd3ffc609f92a534317f006eb4401f39bc4b279 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-02-04 17:06:54 +0000 stop using LmMessageNode wrapper WockyNode is the future. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 0de3d249d69bb99fddbcf72e4dafe36660245eb7 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-02-04 17:05:53 +0000 use the new xmlns and xml:lang build tags Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 36c8f4e67979c60d635d1448b1c2afe15d2a96ec Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-02-04 16:55:45 +0000 util: add xml:lang and xmlns lm_message_build tags Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 160289f855182e9e2d00a91b38541d8e989eee17 Merge: 4722b73 0d865ef Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-05-02 09:32:54 +0100 Merge branch 'caps-hash' commit 0d865efce5ca0840925abdca673a3f171258f767 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-05-02 09:11:57 +0100 caps-hash test: removed This has moved to wocky. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 4722b731516f98a810b97d1be0c5762cb87d9432 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-05-02 09:32:02 +0100 update wocky snapshot Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit cacd8147f3d0c0f4b0b851731b76dcacb4a9fb35 Author: Will Thompson <will.thompson@collabora.co.uk> Date: 2011-04-21 18:48:03 +0100 naaaa nanananano version katamari damacy commit 8b00635e0c048bae7219c06f5e18ac8b33a9dacf Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-02-04 11:16:15 +0000 caps-hash: misc fixes to cleanup code wocky_caps_hash_compute_from_lists allows dataforms to be NULL if there aren't any and will no longer assert on dataforms=NULL. Also, we no longer dup the feature strings as we free the pointer array in the same function so we know what the memory allocation of the array is. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit d34197fb00196aff94142d38216acf4efc36d2af Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-02-04 10:21:09 +0000 caps-hash: use wocky_caps_hash_compute_from_lists Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit c7bba6807c7c236a3a7c7121e1e096f626c56dcb Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-02-04 10:19:31 +0000 connection: clarify add_sidecar_own_caps' identity arg Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 0917818df48202cf979e5911c968966b6384a84a Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-02-04 10:19:14 +0000 presence-cache: don't try and copy a NULL disco identity array Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit c330f99490d65b87698ecc3677cc7a521955a74a Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-02-03 09:32:28 +0000 caps-hash: remove anything to do with dataforms We don't need it for self presence, and we're moving to Wocky. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit bfd15d09556a01079842e5f56b2fb3729f991cf8 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-24 13:05:41 +0000 caps-hash: remove _from_lm_node We're slowly moving this into Wocky. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 969c73f63979dada565e9c36d51d34da0e5a68c3 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-24 13:04:21 +0000 disco-identity: remove Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit df58879f27bced1367fe3c9011cce733952cfae5 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-24 12:48:17 +0000 use WockyDiscoIdentity instead of the gabble version Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 926a07f594b303888ab98fe71735d288dfaf62cf Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-24 12:47:57 +0000 use wocky_caps_hash_ functions Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit b85a52558e9260cf28dba25b60f894aa8075383c Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-13 09:20:14 +0000 muc-factory: remove more assertions with side effects I forgot these last time, whoops. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 0986e22bcbff90cc12d4bef5cf27e42d8bde9853 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-13 09:18:14 +0000 muc-factory: improve debug messages when TargetID and room props conflict Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 9806dea0ec26d3803f6f05e12666296bbfa527b7 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-04 08:47:20 +0000 muc/room.py: fix copy-paste error Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 921f6ee9813814baead9a0672af6b42beab654c9 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-04 08:46:18 +0000 muc-factory: give temporary variables better names Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 558fd89929b0b4dc978f0e02b9f694ab7f93ffb5 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-04 08:42:33 +0000 muc-factory: also note why asserting on decoding a JID Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 86f10810b3f244d34d2cc79ac3f46176fabe1c64 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-04 08:40:58 +0000 muc-channel: re-add comment about valid TargetID Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 9ca2e3f94bd2ddb062d5eed6aff2f64fc929ad2b Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-03 16:45:05 +0000 muc-factory: ensure RoomID and ServerID don't conflict with TargetID Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 35356cd6fda7dd10d223fd99b204c51c7aa3c28c Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-03 16:03:44 +0000 muc-channel: check the result of gabble_decode_jid properly Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 23d4b72664d671374b6eaa48b703d7ea8e936f7d Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2011-01-03 16:01:51 +0000 muc-channel: add newlines when calling g_object_get for clarity Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 4312f26c61c9a61ca007575d23a521500931bc8b Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2010-12-23 17:06:06 +0000 tests: add a test for Room interface Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 637ba03783fff269933a7802728d680f5a8b82e6 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2010-12-23 17:04:55 +0000 muc-factory: allow channel requests with RoomID + Server set Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 51c40a378b1b1434b6ad3705fbd2744216c35bd8 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2010-12-23 12:22:57 +0000 muc/subject.py: test the Room Subject property is correct Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit a8053079c2fafe334684be6ee34b768f89abd8ab Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2010-12-23 12:22:34 +0000 muc-channel: set Room properties as appropriate Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit ec8ca6ea5d945fae643b45cc5fdaa757cb070afa Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2010-12-23 10:30:08 +0000 muc-channel: implement Room properties Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> commit 7c67a8eeac4a65597beb860a9750e4cd639061b1 Author: Jonny Lamb <jonny.lamb@collabora.co.uk> Date: 2010-12-23 09:54:43 +0000 extensions: add Chan_Iface_Room draft Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> ������������������������������������������������������������������������������telepathy-gabble-0.18.3/gabble/���������������������������������������������������������������������0000775�0001750�0001750�00000000000�12332445275�017421� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/gabble/capabilities.h�������������������������������������������������������0000664�0001750�0001750�00000006555�12332440117�022224� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * capabilities.h - Connection.Interface.Capabilities constants and utilities * Copyright (C) 2005 Collabora Ltd. * Copyright (C) 2005 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GABBLE_CAPABILITIES__H__ #define __GABBLE_CAPABILITIES__H__ #include <glib-object.h> #include <gabble/capabilities-set.h> /* Pseudo-capabilities for buggy or strange implementations, represented as * strings starting with a character not allowed in XML (the ASCII beep :-) */ #define QUIRK_PREFIX_CHAR '\x07' #define QUIRK_PREFIX "\x07" /* Gabble 0.7.x with 16 <= x < 29 omits @creator on <content/> */ #define QUIRK_OMITS_CONTENT_CREATORS "\x07omits-content-creators" /* The Google Webmail client doesn't support some features */ #define QUIRK_GOOGLE_WEBMAIL_CLIENT "\x07google-webmail-client" /* The Android GTalk client needs a quirk for component names */ #define QUIRK_ANDROID_GTALK_CLIENT "\x07android-gtalk-client" /* Some useful capability sets for Jingle etc. */ const GabbleCapabilitySet *gabble_capabilities_get_legacy (void); const GabbleCapabilitySet *gabble_capabilities_get_any_audio (void); const GabbleCapabilitySet *gabble_capabilities_get_any_video (void); const GabbleCapabilitySet *gabble_capabilities_get_any_audio_video (void); const GabbleCapabilitySet *gabble_capabilities_get_any_google_av (void); const GabbleCapabilitySet *gabble_capabilities_get_any_jingle_av (void); const GabbleCapabilitySet *gabble_capabilities_get_any_transport (void); const GabbleCapabilitySet *gabble_capabilities_get_geoloc_notify (void); const GabbleCapabilitySet *gabble_capabilities_get_olpc_notify (void); /* XEP-0115 version 1.3: * * "The names of the feature bundles MUST NOT be used for semantic purposes: * they are merely opaque identifiers" * * However, some old Jabber clients (e.g. Gabble 0.2) and various Google * clients require the bundle names "voice-v1" and "video-v1". We keep these * names for compatibility. */ #define BUNDLE_SHARE_V1 "share-v1" #define BUNDLE_VOICE_V1 "voice-v1" #define BUNDLE_VIDEO_V1 "video-v1" #define BUNDLE_CAMERA_V1 "camera-v1" #define BUNDLE_PMUC_V1 "pmuc-v1" const GabbleCapabilitySet *gabble_capabilities_get_bundle_share_v1 (void); const GabbleCapabilitySet *gabble_capabilities_get_bundle_voice_v1 (void); const GabbleCapabilitySet *gabble_capabilities_get_bundle_video_v1 (void); const GabbleCapabilitySet *gabble_capabilities_get_bundle_camera_v1 (void); /* Return the capabilities we always have */ const GabbleCapabilitySet *gabble_capabilities_get_fixed_caps (void); void gabble_capabilities_init (gpointer conn); void gabble_capabilities_finalize (gpointer conn); #endif /* __GABBLE_CAPABILITIES__H__ */ ���������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/gabble/caps-hash.h����������������������������������������������������������0000664�0001750�0001750�00000002503�11674642450�021443� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * caps-hash.h - caps computing string hash (XEP-0115 v1.5) API available to telepathy-gabble plugins * Copyright (C) 2008-2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GABBLE_PLUGINS_CAPS_HASH_H #define GABBLE_PLUGINS_CAPS_HASH_H #include <glib.h> #include <gabble/capabilities-set.h> G_BEGIN_DECLS gchar *gabble_caps_hash_compute_full (const GabbleCapabilitySet *cap_set, const GPtrArray *identities, GPtrArray *data_forms) G_GNUC_WARN_UNUSED_RESULT; gchar *gabble_caps_hash_compute (const GabbleCapabilitySet *cap_set, const GPtrArray *identities) G_GNUC_WARN_UNUSED_RESULT; G_END_DECLS #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/gabble/telepathy-gabble.pc.in�����������������������������������������������0000664�0001750�0001750�00000001034�12332440117�023547� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ libexecdir=@libexecdir@ pluginexecdir=@pluginexecdir@ pluginexeclibdir=@pluginexeclibdir@ gabblepath=${libexecdir}/telepathy-gabble # For plugins' tests Name: Telepathy-Gabble Description: XMPP backend for the Telepathy framework Version: @VERSION@ Requires: pkg-config >= 0.21 Requires.private: glib-2.0 >= 2.32, gobject-2.0, gio-2.0, telepathy-glib >= 0.19.9 Libs: -L${pluginexeclibdir} -lgabble-plugins -lwocky Cflags: -I${includedir}/telepathy-gabble-0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/gabble/caps-channel-manager.h�����������������������������������������������0000664�0001750�0001750�00000006253�12223562023�023532� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * caps-channel-manager.h - interface holding capabilities functions for * channel managers * * Copyright (C) 2008 Collabora Ltd. * Copyright (C) 2008 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GABBLE_CAPS_CHANNEL_MANAGER_H #define GABBLE_CAPS_CHANNEL_MANAGER_H #include <glib-object.h> #include <telepathy-glib/telepathy-glib.h> #include "capabilities.h" G_BEGIN_DECLS #define GABBLE_TYPE_CAPS_CHANNEL_MANAGER \ (gabble_caps_channel_manager_get_type ()) #define GABBLE_CAPS_CHANNEL_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ GABBLE_TYPE_CAPS_CHANNEL_MANAGER, GabbleCapsChannelManager)) #define GABBLE_IS_CAPS_CHANNEL_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ GABBLE_TYPE_CAPS_CHANNEL_MANAGER)) #define GABBLE_CAPS_CHANNEL_MANAGER_GET_INTERFACE(obj) \ (G_TYPE_INSTANCE_GET_INTERFACE ((obj), \ GABBLE_TYPE_CAPS_CHANNEL_MANAGER, GabbleCapsChannelManagerInterface)) typedef struct _GabbleCapsChannelManager GabbleCapsChannelManager; typedef struct _GabbleCapsChannelManagerInterface GabbleCapsChannelManagerInterface; /* virtual methods */ typedef void (*GabbleCapsChannelManagerGetContactCapsFunc) ( GabbleCapsChannelManager *manager, TpHandle handle, const GabbleCapabilitySet *caps, GPtrArray *arr); typedef void (*GabbleCapsChannelManagerResetCapsFunc) ( GabbleCapsChannelManager *manager); typedef void (*GabbleCapsChannelManagerAddCapFunc) ( GabbleCapsChannelManager *manager, GHashTable *cap, GabbleCapabilitySet *cap_set); typedef void (*GabbleCapsChannelManagerRepresentClientFunc) ( GabbleCapsChannelManager *manager, const gchar *client_name, const GPtrArray *filters, const gchar * const *cap_tokens, GabbleCapabilitySet *cap_set, GPtrArray *data_forms); void gabble_caps_channel_manager_get_contact_capabilities ( GabbleCapsChannelManager *caps_manager, TpHandle handle, const GabbleCapabilitySet *caps, GPtrArray *arr); void gabble_caps_channel_manager_represent_client ( GabbleCapsChannelManager *caps_manager, const gchar *client_name, const GPtrArray *filters, const gchar * const *cap_tokens, GabbleCapabilitySet *cap_set, GPtrArray *data_forms); struct _GabbleCapsChannelManagerInterface { GTypeInterface parent; GabbleCapsChannelManagerGetContactCapsFunc get_contact_caps; GabbleCapsChannelManagerRepresentClientFunc represent_client; gpointer priv; }; GType gabble_caps_channel_manager_get_type (void); G_END_DECLS #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/gabble/Makefile.am����������������������������������������������������������0000664�0001750�0001750�00000000702�12332440117�021442� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������if ENABLE_PLUGIN_API pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = telepathy-gabble.pc gabbleincludedir = $(includedir)/telepathy-gabble-0/gabble gabbleinclude_HEADERS = $(headers) else EXTRA_DIST = $(headers) endif headers = \ capabilities.h \ capabilities-set.h \ caps-channel-manager.h \ caps-hash.h \ plugin-connection.h \ error.h \ gabble.h \ namespaces.h \ plugin.h \ sidecar.h \ types.h ��������������������������������������������������������������telepathy-gabble-0.18.3/gabble/error.h��������������������������������������������������������������0000664�0001750�0001750�00000002435�11720700311�020710� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * error.h — error API available to telepathy-gabble plugins (and internals) * Copyright © 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GABBLE_PLUGINS_ERROR_H #define GABBLE_PLUGINS_ERROR_H #include <glib.h> #include <wocky/wocky.h> #include <telepathy-glib/telepathy-glib.h> G_BEGIN_DECLS void gabble_set_tp_error_from_wocky (const GError *wocky_error, GError **error); void gabble_set_tp_conn_error_from_wocky (const GError *wocky_error, TpConnectionStatus previous_status, TpConnectionStatusReason *conn_reason, GError **error); G_END_DECLS #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/gabble/capabilities-set.h���������������������������������������������������0000664�0001750�0001750�00000006777�11720700311�023016� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * capabilities-set.h - capabilities set API available to telepathy-gabble plugins * Copyright (C) 2005-2010 Collabora Ltd. * Copyright (C) 2005-2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GABBLE_PLUGINS_CAPABILITIES_SET_H #define GABBLE_PLUGINS_CAPABILITIES_SET_H #include <glib-object.h> #include <wocky/wocky.h> G_BEGIN_DECLS /** * GabbleCapabilitySet: * * A set of capabilities. */ typedef struct _GabbleCapabilitySet GabbleCapabilitySet; GabbleCapabilitySet *gabble_capability_set_new (void); GabbleCapabilitySet *gabble_capability_set_new_from_stanza ( WockyNode *query_result); GabbleCapabilitySet *gabble_capability_set_copy ( const GabbleCapabilitySet *caps); void gabble_capability_set_update (GabbleCapabilitySet *target, const GabbleCapabilitySet *source); void gabble_capability_set_add (GabbleCapabilitySet *caps, const gchar *cap); gboolean gabble_capability_set_remove (GabbleCapabilitySet *caps, const gchar *cap); void gabble_capability_set_exclude (GabbleCapabilitySet *caps, const GabbleCapabilitySet *removed); void gabble_capability_set_intersect (GabbleCapabilitySet *target, const GabbleCapabilitySet *source); gint gabble_capability_set_size (const GabbleCapabilitySet *caps); gboolean gabble_capability_set_has (const GabbleCapabilitySet *caps, const gchar *cap); gboolean gabble_capability_set_has_one (const GabbleCapabilitySet *caps, const GabbleCapabilitySet *alternatives); gboolean gabble_capability_set_at_least (const GabbleCapabilitySet *caps, const GabbleCapabilitySet *query); gboolean gabble_capability_set_equals (const GabbleCapabilitySet *a, const GabbleCapabilitySet *b); void gabble_capability_set_clear (GabbleCapabilitySet *caps); void gabble_capability_set_free (GabbleCapabilitySet *caps); void gabble_capability_set_foreach (const GabbleCapabilitySet *caps, GFunc func, gpointer user_data); gchar *gabble_capability_set_dump (const GabbleCapabilitySet *caps, const gchar *indent); gchar *gabble_capability_set_dump_diff (const GabbleCapabilitySet *old_caps, const GabbleCapabilitySet *new_caps, const gchar *indent); typedef gboolean (*GabbleCapabilitySetPredicate) ( const GabbleCapabilitySet *set, gconstpointer user_data); /* These functions are compatible with GabbleCapabilitySetPredicate; * pass in the desired capabilities as the user_data */ #define gabble_capability_set_predicate_equals \ ((GabbleCapabilitySetPredicate) gabble_capability_set_equals) #define gabble_capability_set_predicate_has \ ((GabbleCapabilitySetPredicate) gabble_capability_set_has) #define gabble_capability_set_predicate_has_one \ ((GabbleCapabilitySetPredicate) gabble_capability_set_has_one) #define gabble_capability_set_predicate_at_least \ ((GabbleCapabilitySetPredicate) gabble_capability_set_at_least) G_END_DECLS #endif �telepathy-gabble-0.18.3/gabble/types.h��������������������������������������������������������������0000644�0001750�0001750�00000002265�11570651565�020745� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * types.h - type definitions available to telepathy-gabble plugins * Copyright © 2010 Collabora Ltd. * Copyright © 2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GABBLE_PLUGINS_TYPES_H #define GABBLE_PLUGINS_TYPES_H #include <glib.h> G_BEGIN_DECLS typedef struct _GabbleConnection GabbleConnection; typedef struct _GabbleDiscoIdentity GabbleDiscoIdentity; typedef struct _GabblePlugin GabblePlugin; typedef struct _GabbleSidecar GabbleSidecar; G_END_DECLS #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/gabble/plugin.h�������������������������������������������������������������0000664�0001750�0001750�00000011755�12223562023�021067� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * plugin.h — plugin API for telepathy-gabble plugins * Copyright © 2009 Collabora Ltd. * Copyright © 2009 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GABBLE_PLUGINS_PLUGIN_H #define GABBLE_PLUGINS_PLUGIN_H #include <glib-object.h> #include <gio/gio.h> #include <telepathy-glib/telepathy-glib.h> #include <wocky/wocky.h> #include <gabble/plugin-connection.h> #include <gabble/sidecar.h> #include <gabble/types.h> G_BEGIN_DECLS #define GABBLE_TYPE_PLUGIN (gabble_plugin_get_type ()) #define GABBLE_PLUGIN(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GABBLE_TYPE_PLUGIN, GabblePlugin)) #define GABBLE_IS_PLUGIN(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GABBLE_TYPE_PLUGIN)) #define GABBLE_PLUGIN_GET_INTERFACE(obj) \ (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GABBLE_TYPE_PLUGIN, \ GabblePluginInterface)) typedef struct _GabblePluginInterface GabblePluginInterface; typedef void (*GabblePluginCreateSidecarImpl) ( GabblePlugin *plugin, const gchar *sidecar_interface, GabblePluginConnection *plugin_connection, WockySession *session, GAsyncReadyCallback callback, gpointer user_data); /* The return type should be a new GPtrArray* which will be freed * straight after this function is called, so the pointer array must * not have a free function. */ typedef GPtrArray * (*GabblePluginCreateChannelManagersImpl) ( GabblePlugin *plugin, GabblePluginConnection *plugin_connection); typedef GabbleSidecar * (*GabblePluginCreateSidecarFinishImpl) ( GabblePlugin *plugin, GAsyncResult *result, GError **error); struct _GabblePluginPrivacyListMap { const gchar *presence_status_name; const gchar *privacy_list_name; }; typedef struct _GabblePluginPrivacyListMap GabblePluginPrivacyListMap; struct _GabblePluginInterface { GTypeInterface parent; /** * An arbitrary human-readable name identifying this plugin. */ const gchar *name; /** * A %NULL-terminated array of strings listing the sidecar D-Bus interfaces * implemented by this plugin. */ const gchar * const *sidecar_interfaces; /** * An implementation of gabble_plugin_create_sidecar_async(). */ GabblePluginCreateSidecarImpl create_sidecar_async; /** * An implementation of gabble_plugin_create_sidecar_finish(). */ GabblePluginCreateSidecarFinishImpl create_sidecar_finish; /** * The plugin's version, conventionally a "."-separated sequence of * numbers. */ const gchar *version; /** * Additional custom statuses supported by the plugin. */ TpPresenceStatusSpec *presence_statuses; /** * Privacy lists implementing specific statuses */ GabblePluginPrivacyListMap *privacy_list_map; /** * An optional callback to create additional channel managers. */ GabblePluginCreateChannelManagersImpl create_channel_managers; }; GType gabble_plugin_get_type (void); const gchar *gabble_plugin_get_name ( GabblePlugin *plugin); const gchar *gabble_plugin_get_version ( GabblePlugin *plugin); const gchar * const *gabble_plugin_get_sidecar_interfaces ( GabblePlugin *plugin); gboolean gabble_plugin_implements_sidecar ( GabblePlugin *plugin, const gchar *sidecar_interface); void gabble_plugin_create_sidecar_async ( GabblePlugin *plugin, const gchar *sidecar_interface, GabblePluginConnection *plugin_connection, WockySession *session, GAsyncReadyCallback callback, gpointer user_data); GabbleSidecar *gabble_plugin_create_sidecar_finish ( GabblePlugin *plugin, GAsyncResult *result, GError **error); const TpPresenceStatusSpec *gabble_plugin_get_custom_presence_statuses ( GabblePlugin *plugin); gboolean gabble_plugin_implements_presence_status ( GabblePlugin *plugin, const gchar *status); const gchar *gabble_plugin_presence_status_for_privacy_list ( GabblePlugin *plugin, const gchar *list_name); GPtrArray * gabble_plugin_create_channel_managers (GabblePlugin *plugin, GabblePluginConnection *plugin_connection); /** * gabble_plugin_create: * * Prototype for the plugin entry point. * * Returns: a new instance of this plugin, which must not be %NULL. */ GabblePlugin *gabble_plugin_create (void); typedef GabblePlugin *(*GabblePluginCreateImpl) (void); G_END_DECLS #endif �������������������telepathy-gabble-0.18.3/gabble/sidecar.h������������������������������������������������������������0000644�0001750�0001750�00000004076�11423525545�021210� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * sidecar.h — sidecar API available to telepathy-gabble plugins * Copyright © 2009 Collabora Ltd. * Copyright © 2009 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GABBLE_PLUGINS_SIDECAR_H #define GABBLE_PLUGINS_SIDECAR_H #include <glib-object.h> #include <gabble/types.h> G_BEGIN_DECLS #define GABBLE_TYPE_SIDECAR (gabble_sidecar_get_type ()) #define GABBLE_SIDECAR(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GABBLE_TYPE_SIDECAR, GabbleSidecar)) #define GABBLE_IS_SIDECAR(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GABBLE_TYPE_SIDECAR)) #define GABBLE_SIDECAR_GET_INTERFACE(obj) \ (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GABBLE_TYPE_SIDECAR, \ GabbleSidecarInterface)) typedef struct _GabbleSidecarInterface GabbleSidecarInterface; typedef GHashTable * (*GabbleSidecarGetImmutablePropertiesImpl) ( GabbleSidecar *); struct _GabbleSidecarInterface { GTypeInterface parent; /** * The D-Bus interface implemented by this sidecar. */ const gchar *interface; /** * An implementation of gabble_sidecar_get_immutable_properties(). */ GabbleSidecarGetImmutablePropertiesImpl get_immutable_properties; }; GType gabble_sidecar_get_type (void); const gchar *gabble_sidecar_get_interface (GabbleSidecar *sidecar); GHashTable *gabble_sidecar_get_immutable_properties (GabbleSidecar *sidecar); G_END_DECLS #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/gabble/namespaces.h���������������������������������������������������������0000644�0001750�0001750�00000002141�11423525545�021704� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * namespaces.h — namespace constants definitions that can be used by telepathy-gabble plugins * Copyright © 2009 Collabora Ltd. * Copyright © 2009 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GABBLE_PLUGINS_NAMESPACES_H #define GABBLE_PLUGINS_NAMESPACES_H #define NS_CAPS "http://jabber.org/protocol/caps" #define NS_GABBLE_CAPS "http://telepathy.freedesktop.org/caps" #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/gabble/plugin-connection.h��������������������������������������������������0000664�0001750�0001750�00000011374�12223562023�023221� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * plugin-connection.h — Connection API available to telepathy-gabble plugins * Copyright © 2012 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GABBLE_PLUGIN_CONNECTION_H #define GABBLE_PLUGIN_CONNECTION_H #include <glib-object.h> #include <telepathy-glib/telepathy-glib.h> #include <gabble/capabilities-set.h> #include <gabble/types.h> #include <wocky/wocky.h> G_BEGIN_DECLS typedef struct _GabblePluginConnection GabblePluginConnection; typedef struct _GabblePluginConnectionInterface GabblePluginConnectionInterface; #define GABBLE_TYPE_PLUGIN_CONNECTION (gabble_plugin_connection_get_type ()) #define GABBLE_PLUGIN_CONNECTION(o) \ (G_TYPE_CHECK_INSTANCE_CAST ((o), GABBLE_TYPE_PLUGIN_CONNECTION, \ GabblePluginConnection)) #define GABBLE_IS_PLUGIN_CONNECTION(o) \ (G_TYPE_CHECK_INSTANCE_TYPE ((o), GABBLE_TYPE_PLUGIN_CONNECTION)) #define GABBLE_PLUGIN_CONNECTION_GET_IFACE(o) \ (G_TYPE_INSTANCE_GET_INTERFACE ((o), GABBLE_TYPE_PLUGIN_CONNECTION, \ GabblePluginConnectionInterface)) GType gabble_plugin_connection_get_type (void) G_GNUC_CONST; typedef gchar * (*GabblePluginConnectionAddSidecarCapsFunc) ( GabblePluginConnection *connection_service, const GabbleCapabilitySet *cap_set, const GPtrArray *identities); typedef gchar * (*GabblePluginConnectionAddSidecarCapsFullFunc) ( GabblePluginConnection *plugin_connection, const GabbleCapabilitySet *cap_set, const GPtrArray *identities, GPtrArray *data_forms); typedef WockySession * (*GabblePluginConnectionGetSessionFunc) ( GabblePluginConnection *plugin_connection); typedef gchar *(*GabblePluginConnectionGetFullJidFunc) ( GabblePluginConnection *plugin_connection); typedef const gchar * (*GabblePluginConnectionGetJidForCapsFunc) ( GabblePluginConnection *plugin_connection, WockyXep0115Capabilities *caps); typedef const gchar* (*GabblePluginConnectionPickBestResourceForCaps) ( GabblePluginConnection *plugin_connection, const gchar *jid, GabbleCapabilitySetPredicate predicate, gconstpointer user_data); typedef TpBaseContactList * (*GabblePluginConnectionGetContactList) ( GabblePluginConnection *plugin_connection); typedef WockyXep0115Capabilities * (*GabblePluginConnectionGetCaps) ( GabblePluginConnection *plugin_connection, TpHandle handle); struct _GabblePluginConnectionInterface { GTypeInterface parent; GabblePluginConnectionAddSidecarCapsFunc add_sidecar_own_caps; GabblePluginConnectionAddSidecarCapsFullFunc add_sidecar_own_caps_full; GabblePluginConnectionGetSessionFunc get_session; GabblePluginConnectionGetFullJidFunc get_full_jid; GabblePluginConnectionGetJidForCapsFunc get_jid_for_caps; GabblePluginConnectionPickBestResourceForCaps pick_best_resource_for_caps; GabblePluginConnectionGetContactList get_contact_list; GabblePluginConnectionGetCaps get_caps; }; gchar *gabble_plugin_connection_add_sidecar_own_caps ( GabblePluginConnection *plugin_service, const GabbleCapabilitySet *cap_set, const GPtrArray *identities); gchar *gabble_plugin_connection_add_sidecar_own_caps_full ( GabblePluginConnection *plugin_connection, const GabbleCapabilitySet *cap_set, const GPtrArray *identities, GPtrArray *data_forms) G_GNUC_WARN_UNUSED_RESULT; WockySession *gabble_plugin_connection_get_session ( GabblePluginConnection *plugin_connection); gchar *gabble_plugin_connection_get_full_jid (GabblePluginConnection *conn); const gchar *gabble_plugin_connection_get_jid_for_caps ( GabblePluginConnection *plugin_connection, WockyXep0115Capabilities *caps); const gchar *gabble_plugin_connection_pick_best_resource_for_caps ( GabblePluginConnection *plugin_connection, const gchar *jid, GabbleCapabilitySetPredicate predicate, gconstpointer user_data); TpBaseContactList *gabble_plugin_connection_get_contact_list ( GabblePluginConnection *plugin_connection); WockyXep0115Capabilities *gabble_plugin_connection_get_caps ( GabblePluginConnection *plugin_connection, TpHandle handle); G_END_DECLS #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/gabble/Makefile.in����������������������������������������������������������0000664�0001750�0001750�00000046146�12332443655�021501� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = gabble DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/telepathy-gabble-uninstalled.pc.in \ $(srcdir)/telepathy-gabble.pc.in \ $(am__gabbleinclude_HEADERS_DIST) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_config_dir.m4 \ $(top_srcdir)/m4/compiler.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/tp-compiler-flag.m4 \ $(top_srcdir)/m4/tp-compiler-warnings.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = telepathy-gabble-uninstalled.pc \ telepathy-gabble.pc CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(pkgconfigdir)" \ "$(DESTDIR)$(gabbleincludedir)" DATA = $(pkgconfig_DATA) am__gabbleinclude_HEADERS_DIST = capabilities.h capabilities-set.h \ caps-channel-manager.h caps-hash.h plugin-connection.h error.h \ gabble.h namespaces.h plugin.h sidecar.h types.h HEADERS = $(gabbleinclude_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLIENT_TYPE = @CLIENT_TYPE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_CODING_STYLE_CHECKS = @ENABLE_CODING_STYLE_CHECKS@ ENABLE_PLUGINS = @ENABLE_PLUGINS@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NICE_CFLAGS = @NICE_CFLAGS@ NICE_LIBS = @NICE_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOUP_CFLAGS = @SOUP_CFLAGS@ SOUP_LIBS = @SOUP_LIBS@ STRIP = @STRIP@ TEST_PYTHON = @TEST_PYTHON@ TP_GLIB_CFLAGS = @TP_GLIB_CFLAGS@ TP_GLIB_LIBS = @TP_GLIB_LIBS@ VERSION = @VERSION@ WOCKY_CFLAGS = @WOCKY_CFLAGS@ WOCKY_LIBS = @WOCKY_LIBS@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gabbletestsdir = @gabbletestsdir@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ pluginexecdir = @pluginexecdir@ pluginexeclibdir = @pluginexeclibdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @ENABLE_PLUGIN_API_TRUE@pkgconfigdir = $(libdir)/pkgconfig @ENABLE_PLUGIN_API_TRUE@pkgconfig_DATA = telepathy-gabble.pc @ENABLE_PLUGIN_API_TRUE@gabbleincludedir = $(includedir)/telepathy-gabble-0/gabble @ENABLE_PLUGIN_API_TRUE@gabbleinclude_HEADERS = $(headers) @ENABLE_PLUGIN_API_FALSE@EXTRA_DIST = $(headers) headers = \ capabilities.h \ capabilities-set.h \ caps-channel-manager.h \ caps-hash.h \ plugin-connection.h \ error.h \ gabble.h \ namespaces.h \ plugin.h \ sidecar.h \ types.h all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu gabble/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu gabble/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): telepathy-gabble-uninstalled.pc: $(top_builddir)/config.status $(srcdir)/telepathy-gabble-uninstalled.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ telepathy-gabble.pc: $(top_builddir)/config.status $(srcdir)/telepathy-gabble.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ done uninstall-pkgconfigDATA: @$(NORMAL_UNINSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) install-gabbleincludeHEADERS: $(gabbleinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(gabbleinclude_HEADERS)'; test -n "$(gabbleincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(gabbleincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(gabbleincludedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(gabbleincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(gabbleincludedir)" || exit $$?; \ done uninstall-gabbleincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(gabbleinclude_HEADERS)'; test -n "$(gabbleincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(gabbleincludedir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(DATA) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(gabbleincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-gabbleincludeHEADERS install-pkgconfigDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-gabbleincludeHEADERS uninstall-pkgconfigDATA .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool cscopelist-am ctags ctags-am distclean \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-gabbleincludeHEADERS \ install-html install-html-am install-info install-info-am \ install-man install-pdf install-pdf-am install-pkgconfigDATA \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-gabbleincludeHEADERS \ uninstall-pkgconfigDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/gabble/telepathy-gabble-uninstalled.pc.in�����������������������������������0000664�0001750�0001750�00000001066�12332440117�026074� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������prefix= exec_prefix= abs_top_srcdir=@abs_top_srcdir@ abs_top_builddir=@abs_top_builddir@ libdir=@libdir@ pluginexecdir=@pluginexecdir@ pluginexeclibdir=@pluginexeclibdir@ gabblepath=@abs_top_builddir@/src/telepathy-gabble # For plugins' tests Name: Telepathy-Gabble Description: XMPP backend for the Telepathy framework Version: @VERSION@ Requires: pkg-config >= 0.21 Requires.private: glib-2.0 >= 2.32, gobject-2.0, gio-2.0, telepathy-glib >= 0.19.9 Libs: ${abs_top_builddir}/src/libgabble-plugins.la Cflags: -I${abs_top_srcdir} -I${abs_top_srcdir}/lib/ext/wocky ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/gabble/gabble.h�������������������������������������������������������������0000664�0001750�0001750�00000002450�11720700311�020770� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gabble.h — API for telepathy-gabble plugins * Copyright © 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef GABBLE_PLUGINS_GABBLE_H #define GABBLE_PLUGINS_GABBLE_H #define IN_GABBLE_PLUGINS_GABBLE_H #include <glib-object.h> #include <gabble/capabilities.h> #include <gabble/capabilities-set.h> #include <gabble/caps-channel-manager.h> #include <gabble/caps-hash.h> #include <gabble/plugin-connection.h> #include <gabble/error.h> #include <gabble/namespaces.h> #include <gabble/plugin.h> #include <gabble/sidecar.h> #include <gabble/types.h> #undef IN_GABBLE_PLUGINS_GABBLE_H #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/NEWS������������������������������������������������������������������������0000664�0001750�0001750�00000176516�12332443575�016725� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble 0.18.3 (2014-05-07) ==================================== Fixes: • fd.o #76465: fix a crash in Jingle (Guillaume) telepathy-gabble 0.18.2 (2014-03-20) ==================================== The “mithril boxing gloves” release. Fixes: • update Wocky: · don't try to cancel a source ID twice, which issues a critical warning in GLib 2.39 · fix failure to build with recent (Markdown-based) gtk-doc • plugin loader: don't crash if g_dir_open() fails twice (fd.o #66085, Will) • fix a crash in 1-1 Tubes on 64-bit machines (fd.o #70038, Guillaume) • fix enum cast warnings under clang (fd.o #70038, Guillaume) • add a regression test for fd.o #68829 (Simon) telepathy-gabble 0.18.1 (2013-09-06) ==================================== This stable release fixes connection issues with Facebook which have been recently introduced because of a change in their XMPP servers. Fixes: • update Wocky: · fd.o #68829: If we send an IQ to a server allow "from" to be empty (David Edmundson) telepathy-gabble 0.18.0 (2013-08-09) ==================================== The “sea view over the steelworks” release. This is a new stable branch, recommended for use with GNOME 3.10. Summary of changes since 0.16.x: • GLib 2.32 is (directly) required • better interop with Google webmail for audio/video calls • better interop with Google and MSN servers • better interop with iChat • don't claim to support X-TELEPATHY-PASSWORD if the username is unknown • look up a STUN server automatically, using DNS SRV • old-style Tubes channels have been removed • bug fixes Enhancements since 0.17.6: • Check for GLib 2.32 in the top-level configure.ac, and drop fallback paths for older GLib (Simon) Fixes since 0.17.6: • Update Wocky to its new gabble-0.18 branch: · fd.o #67875: make the documentation build successfully (Simon) · fd.o #67900: make the tests pass with GLib 2.36 (Simon) • fd.o #65290: wrap uninstalled regression tests in run-test.sh so they can work under Automake ≥ 1.13 (Simon) • fd.o #67828: fix a test failure with telepathy-glib 0.20.3/0.21.1 or later (Simon) • Debian #714534: avoid naming a function parameter "errno", which is technically a reserved word and might be a macro expanding to an lvalue expression (Samuel Thibault) telepathy-gabble 0.17.5 (2013-06-06) ==================================== The “4.5kg of laptops” release. Dependencies: • GLib 2.32 is now directly required. It was already indirectly required by telepathy-glib 0.19.x. Fixes: • update Wocky: · fd.o #65131: interoperate with non-XMPP-Core-compliant Jingle IQs sent by Google's webmail UI (Simon) · improve reference-counting for better stability (Simon) • fd.o #65296: initialize libdbus for thread-safety (Simon) • fd.o #64285: avoid running the same commands twice in parallel when doing a highly parallel build (Simon) • fd.o #49595: disable an unreliable test-case (Simon) telepathy-gabble 0.17.4 (2013-05-30) ==================================== The “unattainably high curry standards” release. This development release fixes the same man-in-the-middle attack as 0.16.6. If you use an unencrypted connection to a "legacy Jabber" (pre-XMPP) server, this version of Gabble will not connect until you make one of these configuration changes: • upgrade the server software to something that supports XMPP 1.0; or • use an encrypted "old SSL" connection, typically on port 5223 (old-ssl); or • turn off "Encryption required (TLS/SSL)" (require-encryption) Fixes: • update Wocky: · fd.o #61792: fix linking an example program with ld versions that default to --no-copy-dt-needed-entries · fd.o #65036 (CVE-2013-1431): update Wocky to respect the tls-required flag on legacy Jabber servers • fd.o #63119: improve regression tests' isolation from the session bus (Simon) • fd.o #64319: consider the <URL> field to be "supported" on Google servers (it's currently read-only and contains a Google+ URL) (Xavier) • fd.o #64354: don't claim we support X-TELEPATHY-PASSWORD if we don't know the username (Xavier) telepathy-gabble 0.17.3 (2013-03-01) ==================================== The “less resplendent backup ruffs” release. This includes the fixes from telepathy-gabble 0.16.5, including fixing a remotely-triggered denial-of-service bug. You should upgrade. Fixes: • fd.o#57521: don't crash when the server sends back malformed or error replies to privacy list queries. (wjt) • fd.o#61433: don't crash on weirdly-shaped data forms in caps query replies. This issue is tracked as CVE-2013-1769. Unfortunately, this bug can be triggered by any XMPP user who knows your bare JID, not just by people you've authorized to see your presence. Fortunately, it is just a NULL pointer dereference, rather than allowing the attacker to do anything more nefarious like execute code. (wjt) • fd.o#43166: handle rate-limiting by MUCs better, including disabling typing notifications if we get rate-limited, and including the error message from the server in the D-Bus signal so that the user interface could, in principle, show it to the user. (wjt) Enhancements: • fd.o#58198: the Jingle protocol code now lives in Wocky. This should make no functional difference to Gabble. (wjt) telepathy-gabble 0.17.2 (2012-12-07) ==================================== Hooray! Hooray! Hooray! Dependencies: • telepathy-glib 0.19.9 is now required. Enhancements: • fd.o#54760, fd.o#57080: Gabble now uses GLib's base64 implementation rather than including its own. (Heiher, Alban Browaeys) • fd.o#25961, fd.o#25385: Gabble now looks up a STUN server from the _stun._udp SRV record for the user's domain. (Maiku, wjt) • fd.o#47378: XEP-0184 delivery reports are now supported. Note that Empathy neither requests nor displays them. (wjt) Fixes: • fd.o#56181: don't inadvertantly disable creating Call1 channels. (rishi) • fd.o#52362: hopefully, don't crash if we disconnect in the middle of trying to change our Google Talk presence. (wjt) • The Jingle code now sends back unknown-session errors correctly, as mentioned on fd.o#33789. (wjt) • fd.o#57267: File transfer channels now include FileTransfer.FUTURE and FileTransfer.METADATA in their Interfaces property (Daniele Domenichelli) • fd.o#57521: Don't crash when connecting to the League of Legends XMPP server. (wjt) • fd.o#52146: Don't crash in sympathy if the auth channel handler crashes. (wjt) telepathy-gabble 0.17.1 (2012-09-11) ==================================== Dependencies: • telepathy-glib 0.19.7 is now required. (sorry about that) Enhancements: • fd.o#32612: Old-style Tubes channels have been removed. (Jonny) • Tube and Text channels are no longer announced together. (Jonny) Fixes: • Make sure capability discovery works for the camera-v1 capability bundle, avoiding an iChat bug in which it repeats failed capability discovery requests in a rapid loop (fd.o #54634, Simon) • Fix some race conditions and other brokenness in the tests (Sjoerd) • Make sure capability discovery works for the camera-v1 capability bundle, avoiding an iChat bug in which it repeats failed capability discovery requests in a rapid loop (fd.o #54634, Simon) • Fix some race conditions and other brokenness in the tests (Sjoerd) telepathy-gabble 0.17.0 (2012-08-14) ==================================== Dependencies: • telepathy-glib 0.19.2 is now required. Changes since 0.16.2: • Fix calls with android devices (Marcus) • Implement WLM jidlookup. This makes possible to add MSN contacts using XMPP. (Xavier) • Fix google caps parsing (Jonny) telepathy-gabble 0.16.0 (2012-04-02) ==================================== This is the start of a new stable branch. Changes since 0.15.5: • telepathy-glib 0.18.0 is now required. • Install plugins in their own special (versioned) gabble directory so we're not installing unversioned ABI-unstable libraries. (Simon) • The DownloadAtConnection and Download ContactList members have been implemented. (Alban) • Handle errors in IBB bytestreams. (fd.o#47999, Will) Summary of particularly noteworthy changes since 0.14.x: • telepathy-glib 0.18.0 is now required. • Gabble can now be built on Android, using 'androgenizer'. • Add support for the final version of Call1 and remove the telepathy-yell submodule. • Many other miscellanous fixes and small interface implementations. telepathy-gabble 0.15.5 (2012-03-22) ==================================== Requirements: • telepathy-glib 0.17.7 is now required. Enhancements: • fd.o#46513: Refactor Jingle code to remove Telepathy in preparation of moving it to Wocky. (Will) • fd.o#45602: Subclass TpBaseChannel in more channel implemenations. (Jonny) • fd.o#47502: Add a --disable-voip configure flag to disable building gabble with VoIP support. (Marco) Fixes: • Correctly convert between Telepathy and Jingle candidate types. (Olivier) • Start sending automatically on accepting bidirectional calls. (Olivier) telepathy-gabble 0.15.4 (2012-02-21) ==================================== The "disproportionate retribution" release. Requirements: • telepathy-glib 0.17.5 is now required Enhancements: • Add support for the final version of Call1 from telepathy-spec 0.25.2 and remove the telepathy-yell submodule. (Many contributors) • fd.o#41790 - Make file transfer support optional (andrunko) • fd.o#44056 - telepathy-gabble-xmpp-console no longer mixes GIR and pygtk. (Guillaume) • fd.o#33911 - The Loudmouth API compatibility layer has been removed. It's possible this will cause regressions in weird edge cases but it should make the code base more maintainable. (Jonny, Will) • fd.o#45491 - Error messages provided by the server in <presence type='error'/> stanzas are now exposed via the SimplePresence API. This makes it easier for users to distinguish contacts being offline from contacts' servers being broken. (Will) • fd.o#44649 - Gabble now has a gabble-plugins.so library, similarly to mission-control. This enables plugins to link correctly as DLLs on Windows. This also means that plugins don't directly access GabbleConnections anymore, but instead invoke the same functionality through a GabblePluginConnection GInterface. (siraj) API changes to Wocky snapshot: • fd.o#45400 - WockyPepService's API has changed a little bit. wocky_pep_service_get_finish() has grown an extra out argument to give the caller the <item/> element found, if any; similarly, the ::changed signal has grown a similar extra argument. (Will) • fd.o#34975 - WockyPorter is now responsible for sending back error replies for unhandled IQs, whereas previously this was up to Gabble. Plugin authors shouldn't notice this change. (Will) • fd.o#27489 - including <wocky/wocky.h> now includes all public API from Wocky, and including any other header directly is forbidden. (This is similar to how GLib's headers are structured.) Out-of-tree plugins will need to be updated. (Will) Fixes: • fd.o#44331 - Gabble plugin API fails at runtime on Windows : gabble_plugin_create_sidecar function is renamed to gabble_plugin_create_sidecar_async and new virtual function gabble_plugin_create_sidecar_finish is introduced. All gabble plugins should implement these two methods and all internal plugins are updated to use this new API. (siraj) • fd.o #45443 (workaround): avoid testing Credentials access control, since recent Linux has stricter requirements for credentials-passing (it's now opt-in) which we're not yet meeting. (Guillaume) • fd.o #46379: don't raise a GError with domain 0. (Simon) • fd.o #44855: work around Google's unimplemented capability discovery by hard-coding the capabilities of the GTalk echo bot. (Guillaume) • Work around the deprecation of GValueArray. (Guillaume) telepathy-gabble 0.15.3 (2011-12-22) ==================================== Fixes: • fd.o#43891: Update wocky snapshot to fix wocky_data_form_set_type() (Alban) telepathy-gabble 0.15.2 (2011-12-21) ==================================== Enhancements: • fd.o#43588, fd.o#43889: Add public gabble_connection_add_sidecar_own_caps_full() function which includes data forms. (Alban) Fixes: • fd.o#42462: Update wocky snapshot to fix gabble getting kicked from D-Bus when non-character utf-8 is used by remote clients (Sjoerd) • Fix the build when using GLib 2.32. (Xavier) telepathy-gabble 0.15.1 (2011-11-24) ==================================== The “goodbye desolate railyard” release. Dependencies: • telepathy-glib 0.17.2 is now required. Enhancements: • fd.o#38568: Ladies and gentlemen, prepare your angle brackets: Gabble now ships with an XMPP console interface! You can send IQs and get their replies, send arbitrary stanzas, or monitor all incoming and outgoing stanzas, all with beautiful GtkSourceView syntax highlighting. UI love and caring welcome. Anyone want to make a version of the Telepathy “heads” icon with stanzas in place of the thought balloons? (wjt) • fd.o#32692, fd.o#30296, fd.o#41789: Gabble now implements the freshly-undrafted Protocol.Interface.Addressing and the still-unstable Connection.Interface.Addressing1, and uses them to expose Facebook contacts' integer IDs. (andrunko, eeejay) • fd.o#42446: Gabble can now be built on Android, using Androgenizer. (Derek Foreman, Alvaro Soliverez) Fixes: • capabilities.h and caps-channel-manager.h are no longer erroneously omitted. (albanc) telepathy-gabble 0.15.0 (2011-11-16) ==================================== This is the start of a new development branch that will lead to 0.16 in roughly six months. Dependencies: • telepathy-glib 0.17.1 is now required. Enhancements: • fd.o#42288: the Chan.I.FileTransfer.Metadata interface has been implemented. (jonny) • Updated Wocky: · The SASL auth server test now builds with new and old versions of libsasl2. Bug fixes: • fd.o#42706: fix a typo when indexing a pointer array by using the wrong counter! (jonny) • fd.o#32050: fix a crasher when using OLPC activities. (wjt) • Wocky: · fd.o#41719: don't bail on hashing caps if there's no FORM_TYPE. (jonny) · fdo#39057: Accept from="server.com" as stanzas coming from server. (xclaesse) telepathy-gabble 0.14.0 (2011-11-07) ==================================== The “Ironically, downforeveryoneorjustme.com is down.” release. This is the start of a glorious new stable series of Gabble! Major changes since 0.12.x which might disrupt your life: • Gabble implements the new Room, Subject and RoomConfig interfaces, and no longer supports the old, crummy Telepathy.Properties interface. • Gabble no longer supports the legacy Presence interace. • require-encryption is now enabled by default. • The plugin API has been extended; plugins for 0.12.x may need updating to compile and run with 0.14.x. Enhancements since 0.13.7: • It's now possible to install Gabble's test suite. (albanc) • fd.o#41417: when connected to Facebook, text channels now produce 'accepted' delivery reports when the user sends a message to a contact using another device. (wjt) Fixes since 0.13.7: • Compile against unstable GLib, where including glib/gtypes.h directly (instead of glib.h) is forbidden. (cosimoc) • Correct type mismatches for timestamps in muc-channel.c, which lead to Gabble not compiling correctly on 32-bit. (danni) • fd.o#41743: Offline contacts to whom we have a presence subscription and also a channel open at the time the roster arrives are now correctly shown as offline, rather than unknown. (wjt) • fd.o#42281: Actually implement the ContactBlocking interface. (cassidy) • fd.o#42186: Gabble no longer crashes if the server replies to its roster query IQ twice (as vk.com's XMPP server does). (wjt) • Various memory leak fixes. (andrunko) • Gabble now returns MAXINT64 for the subject timestamp when it is unknown, as per the latest spec. (danni) telepathy-gabble 0.13.7 (2011-10-12) ==================================== The “toast the air” release. Dependencies: • telepathy-glib 0.15.9 is now required. Enhancements: • fd.o#32611: Gabble now implements the Room, Subject and RoomConfig interfaces. It no longer implements old-style Telepathy.Properties on text channels. Applications which used those will need to be updated to use Subject and RoomConfig instead; they should be pleasantly surprised at how much easier the new APIs are to use. (Jonny, Will) • Plugins which implement channel managers may now expose capabilities from them, using the GabbleCapsChannelManager interface; other, less dramatic pieces of API for plugins have also been added. (Jonny) Fixes: • fd.o#41388: SASL authentication channels no longer claim that X-TELEPATHY-PASSWORD authentication is supported on servers that don't actually support authenticating with a password (such as the WLM server). (Xavier) • Wocky no longer confuses the realm and the server (which are usually, but not always, the same) when performing DIGEST-MD5 authentication. (Marco) • We now correctly submit the default configuration form to the MUC we have just created, rather than to the user's own server. (Will) telepathy-gabble 0.13.6 (2011-09-28) ==================================== The “grab yourself a bottle” release. Enhancements: • Video-capable Android phones are now considered to be video-capable by Gabble. (fd.o#36996, Olivier Crête) • Gabble now informs Google UIs that we have a camera connected if we have any video-capable user interfaces. While this is not strictly accurate, it's an improvement: they now show a little camera icon for us. (fd.o#40471, Olivier Crête) • Google proxy support—and hence the libsoup dependency—is now optional. (fd.o#40537, Mikhail Zabaluev) • Gabble no longer support the legacy Presence API. This reduces D-Bus traffic, particularly during login. (fd.o#40598, Will Thompson) • Gabble now signals all aliases from the roster in a single AliasesChanged signal. This *dramatically* reduces D-Bus traffic during login on services like Facebook. (fd.o#40943, Marco Barisione) Fixes: • Joining a password-protected chat room where someone else already has the nickname you wanted to use—a pretty obscure scenario—now works again. (fd.o#39790, Will Thompson) • Closing a Call channel immediately after it is created—specifically, before the Google relay server has had a chance to reply—no longer crashes Gabble. (fd.o#39768, Will Thompson) • The Google Talk setting controlling the sending of mail notifications is now explicitly enabled if a client is interested in mail notifications. (fd.o#40565, Jussi Kukkonen) telepathy-gabble 0.13.5 (2011-08-17) ==================================== This is a fixed version of the botched 0.13.4 release. telepathy-gabble 0.13.4 (2011-08-17) ==================================== The “giant iris of the wide blue sky” release. This contains all the fixes from telepathy-gabble 0.12.5, and other exciting things. Enhancements: • XEP-0012 (Last Activity) is implemented at long last. (Michael Scherer, fd.o#11688) • DecloakAutomatically is now enabled by default. This means that any contact who can IM you can also call you (if they're using Gabble). (Will Thompson) Fixes: • StreamTube services are now only advertised to the network, if a Client filter has a channel class with Requested=false (incoming tube) or no Requested property at all (tube with any direction) (Olli Salli, fd.o#39933) • Gabble no longer crashes if a peer advertises malformed capabilities. (David Laban) • The test suite's fake XMPP server now listens exclusively on localhost (Paul Seidler, fd.o#35968) • Invisibility now works on Google Talk again, following a server-side change. (Marco Barisione, fd.o#38706) • The DecloakAutomatically and PowerSavingActive properties are now decoupled, rather than being erroneously linked. (Will Thompson) • Only certain known PEP events are now queued when power saving is active, as opposed to all PEP events. (Siraj Rasick) telepathy-gabble 0.13.3 (2011-07-27) ==================================== The “I got 99 poplars” release. This contains all the fixes from telepathy-gabble 0.12.4, and more. Changes: • 'require-encryption' is now enabled by default. This seems like a reasonable thing to do in 2011. It will obviously cause connection errors if any of the user's configured Jabber servers do not support encryption. It may also cause problems if the user is connecting to servers with untrustworthy SSL certificates. When Gabble encounters a certificate it does not trust, it creates a ServerTLSConnection channel, in the hope that it will be handled by an application which can prompt the user. Empathy has a handler for such channels. On other platforms where no handler is available, if require-encryption is disabled, Gabble falls back to accepting those certificates (on the basis that encryption was being used opportunistically), but if it is enabled, Gabble falls back to rejecting them. • Relatedly, Gabble will itself accept certificates for domains listed in 'extra-certificate-identities' if they have no other problems. Previously it would include these identities in a property on the ServerTLSConnection channel, but do nothing with them itself. (Marco Barisione, fd.o#38749) Fixes: • If telepathy-yell is installed to /usr/include, the included copy will still be used. (Vincent Penquerc'h, fd.o#37492) • With GnuTLS 2.12, sending very large amounts of data will no longer cause the connection to stall. (Sjoerd Simons, fd.o#36077) • File transfer channels should now work on Windows. (Thomas Flüeli, fd.o#31621) telepathy-gabble 0.13.2 (2011-06-24) ==================================== The “Minotaur Shock” release. This includes all of the fixes from the 0.12.3 release (and no other changes since 0.13.1). Enhancements: • autogen.sh now honours the NOCONFIGURE environment variable, for compatibility with gnome-autogen.sh. (Colin Walters) Fixes: • Empty aliases stored on the roster are now ignored. Additionally, if we've cached a contact's JID as their alias on our roster (because we couldn't find a better alias), and we come across a better alias for the contact (via a PEP nickname push, or by fetching their vCard for some other reason), we now replace the JID with that better alias. (fd.o#27361, Will) • We now handle receiving unavailable presence from our contacts before we receive the roster correctly. Previously, this would cause those contacts to be stuck in state 'unknown' rather than 'offline' until they next came online. (fd.o#38603, Will) • Don't make assertions about TpChannelIface:handle-type's value in GabbleFileTransferChannel's set_property implementation. The property's not really writeable—the getter returns a constant value for it anyway—and this fixes a crash with telepathy-glib 0.15.2, in which the default value has changed from NONE to UNKNOWN. (Will) telepathy-gabble 0.13.1 (2011-06-16) ==================================== The “old piano” release. This includes all of the fixes from the 0.12.2 release (and no other changes since 0.13.0). Fixes: • We now interoperate with Google Mail's brand new implementation of Jingle. Some of the workarounds added are temporary, and some are not. (fd.o#38352, Will) • Compare codec names case-insensitively. (fd.o#38264, Olivier) telepathy-gabble 0.13.0 (2011-06-02) ==================================== The “Belgian Wake-Up Drill” release. This is the first release in an all-new unstable series of Gabble. Enhancements: • The draft Channel.Interface.Room is implemented. (Jonny) • IM and MUC channels now signal failure to send messages in some situations. (fd.o#33460, Siraj) telepathy-gabble 0.12.1 (2011-06-02) ==================================== The “Have you seen this cat?” release. Enhancements: • Spurious server-generated messages sent by the Google Mail client's “reply to email over chat” feature are now filtered out. (fd.o#36647, Chandni) Fixes: • No longer crashes if Disconnect() is called just before a connection declares itself Connected. (fd.o#37078, Simon) • No longer assumes Google's Queue extension is supported if Google's Roster extension is supported. (fd.o#36260, Will) • Many corner cases of the transitions to and from Away and Invisible when using Google's Shared Status extension have been fixed. (fd.o#37069, fd.o#36058, fd.o#37283, Marco) • You can now see your own avatar in MUCs. (fd.o#32017, Will) telepathy-gabble 0.12.0 (2011-04-21) ==================================== The “Is that Noam Chomsky on the telephone” release. This is the long-awaited start of the 0.12 stable branch. Dependencies: • telepathy-glib 0.14.5 is now required. Enhancements: • Plugins can now implement channel managers. (Jonny) Fixes: • No longer crashes when joining MUCs fails, or when kicked from a MUC. (Will, fd.o#35120) • Handles MUC nickname conflicts more accurately, resolving an issue triggered by a Google Talk server bug. (Will, fd.o#35619) • No longer gets contacts' client types confused (Jonny, fd.o#32139) • Exposes the status message length limit imposed by Google Talk, and truncates status messages if necessary. (André, fd.o#33054) telepathy-gabble 0.11.10 (2011-03-31) ===================================== The “I am going to bake a cake with beetroot in it” release. Dependencies: • telepathy-glib 0.14.3 is now required! Enhancements: • Non-urgent stanzas are now queued locally if PowerSaving is turned on but the google:queue extension is not available. (Senko) • The ReferenceIdentities property on server TLS channels is now implemented, populated partly from a new 'extra-certificate-identities' parameter. This allows Empathy/Gabble to safely trust the Google Talk server's certificate when using a JID hosted by Google Apps without prompting the user. (fd.o#35410 and fd.o#35415, Stef Walter) • Fatal criticals can now be turned off at configure time (fd.o#35840, Marco Barisione) • The new StreamHandler methods from spec 0.22.1 for rtcp-fb and rtp-hdrext are now implemented. (fd.o#34985, Olivier) Fixes: • `make check -C tests/twisted` now prints a helpful message if Twisted is not available, and the regular tests now pass if Twisted is not available. (Will) • Fix memory leaks in ServerTLSManager (fd.o#35395, Stef Walter) telepathy-gabble 0.11.9 (never) =============================== There is no telepathy-gabble 0.11.9. telepathy-gabble 0.11.8 (2011-03-14) ==================================== Enhancements: • Updated Wocky: · wocky_porter_register_handler() has been split into three functions: wocky_porter_register_handler_from(), wocky_porter_register_handler_from_server(), and wocky_porter_register_handler_from_anyone(). These make it harder to introduce bugs like fd.o#34048. · Since wocky_porter_register_handler() has been removed entirely, out-of-tree plugins may need to be updated to work with this release. Fixes: • fd.o#27693: Gabble no longer polls for contacts' geolocation information; it relies on PEP working properly. (wjt) • fd.o#35137: Gabble now sets the Overwritten_By_Nickname flag for appropriate contact info fields. (jonny) telepathy-gabble 0.11.7 (2011-02-16) ==================================== Dependencies: • telepathy-glib ≥ 0.13.12 is now required. Fixes: • fd.o#32390: Gabble now treats a request for a ContactSearch channel with Server set to the empty string as equivalent to not specifying a server, and rejects requests where the JID specified for Server is invalid. (wjt) • fd.o#32874: Offline contacts are now assumed to support 1–1 text channels. (jonnylamb) • fd.o#34048: Malicious contacts can no longer trick Gabble into relaying audio/video data via a server of their choosing. (wjt, sjoerd) Enhancements: • fd.o#32815: fallback-conference-server now defaults to conference.telepathy.im. Thus, if the user's server doesn't have a conference component configured, upgrading a 1-1 chat into an ad-hoc conference still works. • fd.o#11291: support for xep-0092, Software Version. (Robot101, Michael Scherer) • fd.o#33471: support for the FileTransfer.URI property. (cassidy) telepathy-gabble 0.11.6 (2011-01-27) ==================================== Interesting changes: • Generated code for the Call channel type has been moved to an external submodule called telepathy-yell. This is included in the source tarballs for telepathy-gabble (like how wocky is) so there should be no changes necessary for packagers. Dependencies: Fixes: • fd.o#19930: MUC channels are now only closed properly when the server acknowledges our request to leave. This fixes the case of trying to join a MUC you left only seconds ago before the server had a chance to notice. (jonny) • fd.o#26385: gabble's media stream code now uses TpDBusPropertiesMixin for increased maintainability. (jonny) • Include Protocol.AuthenticationTypes in the manager file. (jonny) Enhancements: • More miscellaneous updates to the Call channel type including: » Update to newest Call spec. (sjoerd) » Base classes have been extracted from Gabble code and moved into telepathy-yell. (wjt, sjoerd, alsuren) » Some test updates to ensure Call works as it should. (sjoerd) • The caps cache has been moved from Gabble to Wocky. (jonny) Test suite changes: • Tests no longer need to call Connect() and wait for the connection to connect but they can choose to do so if they need to. (jonny) • If a test hits an unhandled exception (a timeout, some other python error or perhaps a DBus error?) the queue switches off verbose mode, so users aren't forced to scroll up pages and pages of disconnection logs to find the error. (jonny) • with-session-bus.sh is now as silent as it can be without verbose mode turned on. (jonny) telepathy-gabble 0.11.5 (2011-01-10) ==================================== Fixes: • Support for Google Talk's google:queue extension now works against Google's server again. This regressed in 0.11.1, which changed gabble to send iq gets rather than iq sets. (wjt) • Fix crash caused by timing out items in the iq pipeline before sending them out. (sjoerd) • Correctly parse jingle transport-info message that refer to multiple contents. (sjoerd) • Updated Wocky: » Fix a bug in WockyHeartbeatSource which caused criticals when it was destroyed. (wjt) » Fix parsing of chat state messages in MUCs. (wjt) telepathy-gabble 0.11.4 (2010-12-14) ==================================== Potentially-incompatible changes: • Following telepathy-spec 0.21.5, the message-token field in message headers is no longer guaranteed to be globally-unique. This is known to be problematic for rtcom-event-logger, as used in Maemo 5. Dependencies: • telepathy-glib ≥ 0.13.9 is now required Enhancements: • Implement Protocol.AuthenticationTypes (jonny) • Improve error reporting in Group and StreamedMedia channels (eeejay) Fixes: • fd.o #29147: you will no longer get the scrollback from MUCs hosted by M-Link (and possibly other servers) when you change your presence (wjt) • fd.o #32278: fix an assertion failure when accepting X-TELEPATHY-PASSWORD authentication and immediately closing the channel (jonny) • Make the regression tests pass with telepathy-glib ≥ 0.13.8 (smcv) • Fix the build without system CA certificates (ptlo) telepathy-gabble 0.11.3 (2010-11-30) ==================================== The “Hey, I'm so desperately waiting for telepathy-gablle 0.11 that I can hardly eat.” release. Dependencies: • telepathy-glib >= 0.13.7 is now required. Enhancements: • fd.o #31106: add Protocol.Interface.Presence (vivek) • fd.o #31874: implement and refactor undrafted SASL interface (smcv) Fixes: • fd.o #31998: relax assertions about how fast AddMembers/RemoveMembers succeed (smcv) telepathy-gabble 0.11.2 (2010-11-22) ==================================== The “Please enjoy this refreshing beverage” release. Fixes: • fd.o #31412: fix crashes during disconnection if a PEP alias request is in-flight (smcv) • Loosen an assertion to fix test failure with telepathy-glib >= 0.13.5, which releases connections' object paths sooner (smcv) • fd.o #31772: fix a crash if a contact goes invisible while we're discovering their capabilities (wjt) • Remove accidentally re-added libuuid dependency (jonnylamb) • --with-ca-certificates, formerly known as --with-ca-file, now warns—rather than making configure fail—if the specified path does not exist. This is kinder to buildds which may not actually have the CAs installed. telepathy-gabble 0.11.1 (2010-11-16) ==================================== Enhancements: • Implement Conn.I.PowerSaving (eeejay) • fd.o #31474: replace --with-ca-certificates configure option with --with-ca-file. The default is to use the normal location for either Red Hat or Debian, or fail if neither exists. Use --with-ca-file to force a particular location (e.g. if your build system doesn't guarantee to have the CA certificate bundle installed), or use --without-ca-file if your system doesn't have a standard CA certificate store. (Brian Pepple) Fixes: • Don't generate unused bindings for channel bundles (wjt) • Update wocky snapshot · Add an optional dependency on libiphb and link it up to the main loop to provide non-regular XMPP pings where appropriate. (wjt) · Misc OpenSSL fixes. (wjt) telepathy-gabble 0.11.0 (2010-11-04) ==================================== The "your gmail theme is horrible and offensive" release. Enhancements: • Implement the ContactList, ContactGroups interfaces, refactoring GabbleRoster considerably in the process (smcv) • fd.o #28413: implement DTMF on StreamedMedia and Call channels, up-to-date for spec 0.21.3 (Jack Bates, smcv, jonny) • Implement the ClientTypes interface (jonny) • Make the tests considerably less prone to race conditions (sjoerd) • Adapt GabbleCapsChannelManager to be useful in Salut too (smcv) • fd.o #31216: implement the stable version of MailNotification (smcv) • fd.o #28726: use Google's Shared Status extension to support being invisible/hidden on Google Talk (eeejay) • Add a summary of how Tubes capabilities work (wjt) Fixes: • Poll GMail servers periodically for a short time after each mail notification, to work around the server throttling notifications (stormer) • fd.o #30950: advertise the immutable properties of Messages channels (smcv) • fd.o #28279: don't announce new Tubes channels until ready (sjoerd) telepathy-gabble 0.10.4 (2010-11-02) ==================================== The “Well, this super analysis i made!!!!! could be useful for you!!!!!!!!!!!!” release. There are plenty more bangs where these come from, I assure you. Enhancements: • fd.o #24775: implement local IPv4 address discovery on Windows, allowing out-of-band SOCKS5 bytestreams to work there (Thomas Flueeli) Fixes: • Updated Wocky snapshot: · Added HTTP proxy support. This is not technically a fix, but it's nice to have. ;-) (stormer) · Miscellaneous leak fixes. (stormer) · Miscellaneous other fixes. (wjt) • Prefer XEP-0186 invisibility over privacy list-based invisibility when both are available (eeejay) • fd.o #31197: improve portability to Windows (Thomas Flueeli) telepathy-gabble 0.10.3 (2010-10-06) ==================================== The "we ran out of bangs" release. Fixes: • Emit ActivitiesChanged when the server aknowledges our own update (tomeu) • Removed dependency to libuuid (stormer) • Slacker_message_filter can survive invalid/non-signal/unexpected messages (fledermaus) • Remove support for gadget (tomeu) telepathy-gabble 0.10.2 (2010-09-30) ==================================== The “I guess that you don't want to have a shared library!! because you fear to have a shared library!!!!!!!! yeah!!!” release. Fixes: • Updated Wocky snapshot: · Made it compile when built with OpenSSL (wjt) · Handle the connection being disconnected by the remote side more gracefully (sjoerd) · Make the XML parser more tolerant of recoverable errors in the incoming stream. In particular, this fixes an issue with illegal namespaces in some contacts' PEP nodes (sjoerd) • Fixed a memory allocation error which could cause corruption when using plugins which deal with capabilities (wjt) • Ensure only one OLPC activity is created for a given channel (tomeu) telepathy-gabble 0.10.1 (2010-09-29) ==================================== The “That command worked with no errors!!!!!!!!!!! but i don't know if it works for real!!!!!!!!!!!” release. Fixes: • From updated Wocky snapshot: · Check the return value of wocky_xmpp_connection_send_stanza_finish() in starttls_sent_cb() (wjt; found by Coverity) · Don't retry indefinitely on failed OpenSSL writes (fledermaus) • Don't leak local candidates, stun servers, and remote candidates when getting Stream/Endpoint properties (smcv) • Don't assume privacy list lists are well-formed (wjt; found by Coverity) • When a contact becomes unavailable, check the correct roster subscription attribute to decide whether their status should be Offline or Unknown (smcv) telepathy-gabble 0.10.0 (2010-09-16) ==================================== The "we demand additional lumber" release, starting the 0.10.x stable branch. Highlights since 0.8.x ---------------------- Gabble no longer uses Loudmouth for XMPP; instead, it contains a snapshot of Wocky, a new XMPP library based on GIO. Wocky will be split into a fully independent project when it reaches API stability. New features and significant bugfixes include: • Jingle calls now interoperate with Pidgin, Gajim, and XEP-0100 SIP gateways • file transfers now interoperate with the Google Talk desktop client • support for Google Talk PMUC chatrooms • contact information (vCards) on servers supporting XEP-0054 • searching for contacts on servers supporting XEP-0055 • improved capability-discovery support (ContactCapabilities) • compile-time selection of GNUTLS or OpenSSL for SSL support • support for JIDs with non-ASCII domains • experimental support for plugins • experimental support for multi-user Jingle calls (Muji) • compilation on Unix platforms other than Linux should now work Compatibility notes ------------------- • telepathy-glib 0.11.16, GLib 2.24, libxml 2, SQLite 3, libnice 0.0.11, libsoup and libuuid are required. • libsasl 2 is optional. • Either GNUTLS >= 2.8.2 or OpenSSL >= 0.9.8g is also required. • At the time of release, GNUTLS 2.8 is recommended. For versions 2.10.0 and 2.10.1, some fixes need to be backported from 2.11.1 to fix connection failures with "-59: GNUTLS_E_INTERNAL_ERROR" in the debug log; we're tracking this as <https://bugs.freedesktop.org/show_bug.cgi?id=29364>. • If you use telepathy-mission-control, version 5.5.0 or later is required. A 5.6.x stable branch suitable for this will be released soon. Packagers, please make Gabble conflict with Mission Control < 5.5.0 (e.g. the Breaks or Conflicts relationships in dpkg), or if that's not possible in your packaging system, depend on Mission Control >= 5.5.0. Changes since 0.9.18 -------------------- • Fix a crash if the connection closes while verifying a TLS certificate (wjt) • Allow an in-progress connection to the server to be cancelled with Disconnect (cosimoc) • Add regression tests for TLS certificate verification (cosimoc) telepathy-gabble 0.9.18 (2010-09-13) ==================================== The “What, more work? Off I go then” release. Enhancements: • fd.o #30065: implement the stable API for ContactSearch (wjt) • Implement the stable API for interactive TLS certificate checking (cosimoc) • Implement the stable API for Conference channels (smcv) • Add the fallback-servers parameter, which can be used to make connections to Google Talk on some networks more reliable (stormer) • Prompt the user about unknown TLS certificates if neither require-encryption nor ignore-ssl-errors is set (cosimoc) Fixes: • Make the --with-ca-certificates configure option work (Vincent Untz) • fd.o #30117: always emit PresencesChanged when we change our own presence, and fix a related memory leak (wjt) • update our copy of Wocky: › fd.o#28051: SRV errors on some networks no longer break Facebook logins (wjt) › don't fail on missing CRLs if not in strict TLS verification mode (fledermaus) • fd.o#28990: removed dependency to libuuid (stormer) telepathy-gabble 0.9.17 (2010-08-26) ==================================== The "Mona Lisa overdrive" release. Enhancements: • Implement TLS certificate support (cosimoc) • Use TpBaseChannel instead of GabbleBaseChannel (wjt) • Plugin-provided, privacy-list based presence statuses (ptlo) Fixes: • fd.o #29721: start the presence unsure timeout once we connect (wjt) • fd.o #29000: make CA certificates path configurable (stormer) • Fix several leaks, improve tests in case of connection leaks (wjt) telepathy-gabble 0.9.16 (2010-08-19) ==================================== The “still at it” release. Enhancements: • Implement XEP-0126: Invisibility (wjt and eeejay) • Implement XEP-0186: Invisible Command (wjt and eeejay) • implement org.freedesktop.Telepathy.Protocol (ptlo) • Add a ActivityProperties.GetActivity method for retrieving an activity's room handle from its id (tomeu) • Add a BuddyInfo.AddActivity method so activities can advertise themselves without having to track all the other shared activities (tomeu) Fixes: • fd.o #25533: muc-factory: don't associate a request with tubes if a tube was requested (jonnylamb) • muc-factory: rearrange which NewChannels signals come first (jonnylamb) • Cope if Jingle sharing requests omit <manifest> (wjt) • fd.o #29113: Skip file collection candidates with invalid addresses (wjt) • several improvements to the test suite (smcv) • fixes for building under gcc-4.5 (smcv) • adapt to the new TLS API (sjoerd) telepathy-gabble 0.9.15 (2010-06-30) ==================================== The “wave forlornly through the gates” release. Enhancements: ❖ in Wocky, build enum types for all error domains (smcv) Fixes: ❖ Debian #586936: in Wocky, clear the parser state when resetting, fixing assertion failures if the caps cache gets corrupted (sjoerd) ❖ fd.o #28712: in Wocky, fix SCRAM-SHA1 authentication by initializing state correctly (sjoerd) telepathy-gabble 0.9.14 (2010-06-22) ==================================== The "missing frame" release. Enhancements: • When a call is ended, mention who ended it in the debug log (wjt) Fixes: • fd.o #28599: ignore errors from disco#info query on our own bare JID, fixing connections to older versions of jabberd, jabberd2, Prosody etc., which regressed in 0.9.13 (wjt) • Use the self-handle as actor for changes to the 'deny' list, and improve roster regression tests, in preparation for future ContactList API (smcv) • Update Wocky snapshot: • fd.o #28643: stop applying GNUTLS_VERIFY_DO_NOT_ALLOW_SAME flag, allowing connection to (for instance) jabber.ccc.de (Lars Noschinski) • Apply more workarounds for TLS server misbehaviour (wjt) • fd.o #28647: be more tolerant if servers send an IQ reply without a 'from' attribute (smcv) • fd.o #27488: wocky_connector_connect_finish, _register_finish parameters have been re-ordered (smcv) telepathy-gabble 0.9.13 (2010-06-14) ==================================== The “But today, you ARE the law!” release. Dependencies: • libnice >= 0.0.11 is now required. • telepathy-glib >= 0.11.6 is now required. Enhancements: • Gabble is now able to exchange files with the Google Talk desktop client! (KaKaRoTo) • On Maemo, when connected to Google Talk, suppress presence updates while the device is idle. (wjt) • Plugins may now specify additional capabilities for Gabble to advertise, and add responses to new disco#info queries. (andrunko) • From Wocky: › The SCRAM-SHA-1 SASL mechanism is now supported. (sjoerd) Fixes: • From Wocky: › Messages from JIDs at non-ASCII domains are no longer silently dropped. (wjt) › Whether or not the connection is secure is now correctly propagated from Wocky up to Gabble. (eeejay) telepathy-gabble 0.9.12 (2010-06-03) ==================================== The “Show me the face of you” release. Dependencies: • libuuid is now required. Enhancements: • The capabilities cache now persists on-disk. (daf) • Multi-user calls are now supported, using the Muji protocol! Frabjous day, etc. Empathy does not yet support multi-user calls; there's a test client written in Python, but you'll need bleeding-edge Farsight to run it. (sjoerd, Maiku) • Support the /info contact attribute for ContactInfo. (andrunko) • XMPP keepalives are now sent and acked; this fixes the biggest remaining regression from 0.8! (ptlo) • When making outgoing calls, Gabble now prefers to call resources which claim to be phones. (fd.o#28265, wjt) • The current draft of SASL authentication channels is implemented, allowing channel handlers to support SASL mechanisms like X-GOOGLE-TOKEN. As a result, 'account' and 'password' are now optional connection parameters, since SASL mechanisms such as ANONYMOUS (see XEP-0175) require neither. (eeejay, danni) Fixes: • From Wocky: › Don't treat error replies from PEP nodes as PEP updates. (fd.o#28232, cassidy) › Don't drop backlog messages from former members of MUCs. (fd.o#27913, wjt) • Blocked contacts are no longer accidentally unblocked if you remove them from the 'stored' list. (fd.o#20597, wjt) • Gabble MailNotification.RequestInboxURL no longer returns an empty string in some situations (fd.o#27157, stormer) • Various fixes for issues found by Coverity (wjt) telepathy-gabble 0.9.11 (2010-04-26) ==================================== The “This place is a narrative mess” release. Enhancements: • The ContactInfo interface is now implemented! (andrunko, smcv) • Updated Wocky: · Permit ASCII mnemonics in wocky_stanza_build(), and detect more errors (wjt) · Renamed WockyXmpp{Stanza,Node} to Wocky{Stanza,Node}; add more helper code for building, storing, and serializing trees of nodes (sjoerd) · Refactored PubSub response distillery, and added support for retriving node configuration and modifying affiliates (wjt) Fixes: • fd.o#25775: crash in pep_reply_cb() (cassidy) • fd.o#27694: GetContactAttributes should return {} as location if there is no location for the contact (cassidy) telepathy-gabble 0.9.10 (2010-04-08) ==================================== The “Cartoons and Macramé Wounds” release. Enhancements: • Updated Wocky: - Improve Windows portability (Ole André Vadla Ravnås) - Fix a double-free (KaKaRoTo) - Even more exciting PubSub code (wjt) Fixes: • Properly expose more authentication failure errors from Wocky in Connection.StatusChanged (sjoerd) • Run tests in a temporary D-Bus session, which fixes fd.o#25816 (sjoerd) • Fix tests on machines with no ipv6 (sjoerd) • Avoid doing undefined void-pointer arithmetic (smcv) telepathy-gabble 0.9.9 (2010-03-26) =================================== The “It's release o'clock, quick, say something funny” release. Enhancements: • Update Wocky: - New and exiting Dataforms code! (wjt) • Various portability improvements (smcv) Fixes: • Fix mail notification on GTalk showing at most 30 unread mails (Nicolas) telepathy-gabble 0.9.8 (2010-03-16) =================================== The “Chat Roulette Funny Piano Improv #1” release. Enhancements: • Update Wocky: - Lots of exciting new Pubsub code! (cassidy, wjt) - Plus some crash fixes • Various correctness improvements to the test suite. (KaKaRoTo) Fixes: • No longer crashes on receiving a stanza error without an <error/> node, which was a regression in 0.9.5. (wjt) • We can now spell “received” and “separate”! (smcv, courtesy of Lintian) telepathy-gabble 0.9.7 (2010-03-03) =================================== The "Faraday cake" release. Dependencies: * Gabble now needs telepathy-glib ≥ 0.9.2 Enhancements: * Add support for draft 1 of Connection.Interface.MailNotification (stormer) * Improve regression test coverage (KaKaRoTo) * Update Wocky: - data-form utility code (cassidy) - node iterator utility functions (sjoerd) - better gtk-doc, improve portability (smcv) Fixes: * Implement the 'accuracy' key in Location, not the deprecated XEP-0080 'error' (which is not in telepathy-spec) (cassidy) telepathy-gabble 0.9.6 (2010-02-23) =================================== The "save us from this existential quagmire!" release. Enhancements: • The plugin loader is now built by default, and the gateway-registration plugin is installed by default. Since the API is still experimental and likely to change from one release to the next, the development headers etc. necessary to write third-party plugins are only installed if you configure with --enable-plugin-api (this is not recommended). (smcv) Fixes: • fd.o #26658: queue up any data received on the FileTransfer socket until the channel moves to state OPEN (KaKaRoTo) • Clean up signal connections in GabbleJingleFactory to avoid a possible use-after-free if a Jingle session, or the Connection, outlives the Jingle factory (KaKaRoTo) • Improve the gateway-registration plugin to exchange presence subscriptions and fix a memory leak (smcv) • Don't install the plugin unless the plugin loader has been enabled, and don't compile a useless static-library version of the plugin (smcv) telepathy-gabble 0.9.5 (2010-02-19) =================================== The "eclectic mandate whittling" release. Enhancements: • Update Wocky for improved error-wrangling code (wjt) Fixes: • When delaying a stream request until service discovery has finished in order to interpret capabilities, correctly resume the request after service discovery (smcv) • Calculate capabilities hash correctly when compiled with --enable-is-a-phone (wjt) • Don't emit a potentially-non-UTF-8 Google relay magic_cookie in debug output (Maiku) telepathy-gabble 0.9.4 (2010-01-28) =================================== The “Samuel Clemens had four cats!” release. Enhancements: • Added an --enable-is-a-phone configure switch, which makes Gabble identify itself as a "phone" (rather than a "pc") in XEP-0115 disco replies. (wjt) • Added preliminary support for the Channel.Type.Call draft. By default, incoming Jingle calls are exposed as Channel.Type.Call if a handler is available; pass --disable-channel-type-call to configure to always expose incoming calls as StreamedMedia. (sjoerd, Maiku) • One-to-one text channels can now be upgraded to multi-user conferences using the draft Conference interface. This will use a PMUC room on Google's conference server if at least one participant is using a Google Talk client, or an instant room on your own conference server (XEP-0045 §10.1.2) otherwise. (danni) • Implements XEP-0276, to permit calling contacts whose presence you are not subscribed to (controlled by a simple Gabble-specific connection interface). (smcv) • Plugins may now specify their own version number, for improved debug logs. (wjt) • Added a simple sidecar, implemented as a plugin, to support registering to gateways which require nothing more than a username and password. (smcv) Fixes: • We can now accept calls from, and place calls to, bare JIDs (that is, contacts with no resource). This is required for calling XEP-0100-compliant SIP gateways. (smcv) • We now deal correctly with setting a vCard if there's no existing vCard on the server. (fd.o#25987, wjt) • ignore-ssl-errors is now implied by require-encryption being false. This was a regression from 0.8. (wjt) • ContactCapabilities are now exposed on the Contacts interface with the correct attribute name. (fd.o#26210, wjt) telepathy-gabble 0.9.3 (2009-12-21) =================================== The ``TRANSPORT CHAOS threat level: PANDEMONIUM'' release Highlights: • Various updates to the OpenSSL backend causing it not to stall when reading multiple ssl records at the same time Enhancements: • Gabble now advertises a 'pmuc-v1' capability bundle, telling the Google Mail client that we support being invited to MUCs. (fd.o#22768, jonnylamb) • Rather than hard-coding a list of SOCKS5 proxy servers to use if the user's own XMPP server does not provide one, Gabble now falls back to a list of proxy servers returned by discoing the newly-set-up proxies.telepathy.im. (fd.o#25304, cassidy) • Various leaks fixed as pointed out by valgrind (daf, sjoerd) Fixes: • Do not re-publish our own vCard if nothing's changed (fd.o#25341, andrunko) • The default resource is now unique to the machine Gabble is running on, rather than being randomly generated for each connection. Fixes fd.o#23630: “Per-connection resource randomization increases the window in which you lose messages”. (wjt) • Always assume that MUC servers will let us change the subject, mitigating fd.o #13157; previously we assumed they would only let moderators change the subject. (smcv) • fd.o #21152: allow joining chatrooms on servers that don't respond to disco queries, like talk.google.com (jonny) • fd.o #22456: append fallback conference server if the room name has no @, rather than just failing (if using the Requests API) (jonny) • fd.o #22768 (partial): reassure talk.google.com that we can be invited to chatrooms. This enables us to be invited to private MUCs by the Google client, but doesn't currently support creating them. (jonny) • fd.o #24558: correctly flag the password parameter as secret (smcv) • Use TpDebugSender for debug output, instead of reimplementing it (jonny) • Allow sending chat state to contacts whose capabilities we don't know, such as invisible Google Talk users (wjt) • Only disco SOCKS5 proxies when they're needed for a file transfer or tube. (fd.o#21151, cassidy) • Do not advertise support for file transfers unless a handler is available. (fd.o#25243, smcv) • Do not re-publish our own vCard if nothing's changed (fd.o#25341, andrunko) telepathy-gabble 0.9.2 (2009-10-27) =================================== The ``The photo device is down'' release. Highlights: * Add support for using OpenSSL instead of GNUTLS for SSL support Fixes: * Honour errors that tell us to wait and try again when fetching vCards. This was erroneously claimed to be in 0.9.1. (Alban) * Don't re-fetch our own avatar in a loop when connecting to Google Talk. This should fix #23684 once and for all. (Alban) * Don't trust other people's <message/> IDs to be globally unique: in particular, Google Talk uses simple incrementing integers (wjt) * Use the correct marshaller for the pre-presence signal, fixing a cr 64-bit platforms (wjt) * Make sure the Connection object disappears from the bus when disconnected (Vivek) telepathy-gabble 0.9.1 (2009-09-25) =================================== The “even children are made of atoms” release. Highlights: * Jingle call interoperability with Pidgin and Gajim. Fixes: * When receiving a file, Gabble now closes the local socket once all the data has been written. (Guillaume) * fd.o #24043: Doesn't parse candidates in a Jingle session-accept stanza This fix lets us interoperate with Pidgin's Jingle implementation. (Sjoerd, David) * fd.o #24023: Accepting initial streams for a call is racy. (Sjoerd, Daf) * fd.o #20629: DBus events in tests should contain full path. (Daf) * fd.o #22795: jingle/google-relay.py is secretly made of cheese. (Daf) * fd.o #23903: Gabble crashes in File Transfer. (Guillaume) * fd.o #23685: build Gibber with fno-strict-aliasing so asyncns.c builds with new GCC. (Guillaume) * fd.o #20565: Contacts should be initially offline and not unknown. (Daf) * When members are removed from a call due to a stream error, always indicate so. (Daf) * Fix corner cases in SetLocation()'s language handling. (Daf) * fd.o #24195: Doesn't think clients without google p2p tranport are media capable. This fix lets us interoperate with Gajim's Jingle implementation. (Sjoerd, Daf) * Make stun-server.py not fail if the default STUN server hostname can't be resolved. (David) * fd.o #23684: Gabble advertizes an avatar's sha1 in its presence stanza without following XEP-0153. (Alban) * Honour errors that tell us to wait and try again when fetching vCards. (Alban) telepathy-gabble 0.9.0 (2009-09-16) =================================== The "Use STAPLE REMOVER on TREMENDOUS DANGEROUS-LOOKING YAK" release. This is the first release in the 0.9 development branch. Most users should continue to use the 0.8.x stable branch for now. This release introduces some regressions: proxies and keep-alive aren't supported any more. These features will be back in future releases. Dependencies: * Gabble doesn't depend on loudmouth anymore. Instead, it ships a copy of Wocky, a new XMPP library based on gio. As a side effect of this, gio >= 2.21 and gnutls >= 2.8.2 are now needed to build Gabble. * telepathy-glib >= 0.7.37 is now required Enhancements: * Add the ability to send a message when terminating a VoIP call (wjt) * Add ContactSearch channels using spec draft 2 (wjt, cassidy) * Implement the final ContactCapabilities spec, and refactor Capabilities code to represent capabilities as sets of XML namespaces, rather than bitfields (wjt, smcv) * fd.o#19952: Support requesting channels with InitialAudio/InitialVideo through the final API from telepathy-spec 0.17.28 (smcv) * Gabble now loads certificates from ~/.config/telepathy/certs/ as well as from the system-wide location (/etc/ssl/certs/ca-certificates.crt). Fixes: * Improve pubsub.c test coverage (cassidy) * fd.o #22968: don't try to pass credentials through Unix sockets on non-Linux, since the way we currently do it is known to be non-portable. Patches to implement Credentials on more OSs would be welcomed. (smcv) telepathy-gabble 0.8.5 (2009-10-02) =================================== The “a page out of Remembrance of Things Past and a blowtorch with which to set it on fire” release. Fixes: * Don't re-fetch our own avatar in a loop when connecting to Google Talk. This should fix #23684 once and for all. (Alban) * Fix a crash introduced by the vCard-related fixes in 0.8.4. (Alban) telepathy-gabble 0.8.4 (2009-09-25) =================================== The “bourgeois traditional omelette form” release. Highlights: * Jingle call interoperability with Pidgin and Gajim. Fixes: * When receiving a file, Gabble now closes the local socket once all the data has been written. (Guillaume) * fd.o #24043: Doesn't parse candidates in a Jingle session-accept stanza This fix lets us interoperate with Pidgin's Jingle implementation. (Sjoerd, David) * fd.o #24023: Accepting initial streams for a call is racy. (Sjoerd, Daf) * fd.o #20629: DBus events in tests should contain full path. (Daf) * fd.o #22795: jingle/google-relay.py is secretly made of cheese. (Daf) * fd.o #23903: Gabble crashes in File Transfer. (Guillaume) * fd.o #23685: build Gibber with fno-strict-aliasing so asyncns.c builds with new GCC. (Guillaume) * fd.o #20565: Contacts should be initially offline and not unknown. (Daf) * When members are removed from a call due to a stream error, always indicate so. (Daf) * Fix corner cases in SetLocation()'s language handling. (Daf) * fd.o #24195: Doesn't think clients without google p2p tranport are media capable. This fix lets us interoperate with Gajim's Jingle implementation. (Sjoerd, Daf) * Make stun-server.py not fail if the default STUN server hostname can't be resolved. (David) * fd.o #23684: Gabble advertizes an avatar's sha1 in its presence stanza without following XEP-0153. (Alban) * Honour errors that tell us to wait and try again when fetching vCards. (Alban) telepathy-gabble 0.8.3 (2009-09-10) =================================== The “one cigarette, some coffee, and four tiny stones” release. Enhancements: * fd.o #23681: Allow setting presence on a connection before it goes online. This avoids e.g. going from Available -> Busy immediately when signing on. (daf) Fixes: * fd.o #23684: fix handling of avatar conflict with several resources, and a possible infinite ping-pong of presence stanzas from the server (albanc) * Time out disco requests after 20, not 20,000, seconds! (grundleborg) * Correctly respond to disco requests for video-v1 bundle, avoiding a loop when iChat blindly retries failed disco requests (smcv) * Fix Requested and State properties of muc D-Bus tubes that we previously created and are still present when we re-join the muc. These tubes are now listed in Tubes.ListTubes(). fd.o #23678. (cassidy) * Don't send the same disco request to the same (full) JID more than once. fd.o #23841. (wjt) * Update the Jingle raw-udp and ice-udp namespaces we claim to support to the current version. (wjt) * fd.o #23348, #23349: fix compilation on NetBSD by including more headers (Thomas Klausner) * fd.o #21327: force ISO date format in ChangeLog (wjt) * Reduce the size of the ChangeLog by truncating at version 0.6.0 and not including diffstats (previously, the changelog.gz in our Debian packages was larger than Gabble itself!) (smcv) telepathy-gabble 0.8.2 (2009-09-03) =================================== The “tape two fried eggs over your eyes and walk the streets of Paris for an hour” release. Enhancements: * Improve jid validation, so that obviously-invalid jids are rejected. (daf) Fixes: * Don't crash when a vCard set fails, and there are edits pending. This can happen if you're trying to set your avatar and then disconnect. (daf) * fd.o#23013: ContactCapabilities.SetSelfCapabilities can crash gabble with wrong parms (sjoerd) * Fix parsing of incoming session accept from Google Video Chat. This should make outgoing calls to Google Video Chat users work, as well as incoming calls. Hooray! (wjt, with help from sjoerd and Olivier Crête) telepathy-gabble 0.8.1 (2009-08-20) =================================== The “five pounds of cherries and a live beaver” release. Fixes: * fd.o#22535: Gabble no longer crashes if you disconnect while it's trying to start a Google relay session for a call. This should have been fixed in 0.7.31, but it's really fixed now. :-) (wjt) * Fix an occasional crash when PEP requests time out, or are cancelled when you disconnect. (daf) * Correct an assertion about vCard edits not to fire incorrectly. (daf) * Clarify some correct-but-confusing behaviour in libjingle 0.3 mode, which fixes a Coverity false-positive. (smcv) telepathy-gabble 0.8.0 (2009-08-18) =================================== The “place a chair facing the oven and sit in it forever” release. This is the first release in the 0.8 stable series. Dependencies: * telepathy-glib >= 0.7.34 is now required as Gabble implements the Location API. Enhancements: * Location and Debug are now implemented as stable interfaces. * Timeouts are synchronised to the second where possible, leading to fewer wakeups. Fixes: * Fix race condition introduced by fix for fd.o #22023. * Make vCard request less likely to time out. * Fix a bug where a vCard request failure could cause SetAvatar or SetAliases not to return. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/ltmain.sh�������������������������������������������������������������������0000644�0001750�0001750�00001051522�12332443652�020026� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ # libtool (GNU libtool) 2.4.2 # Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, # 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool 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. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, # or obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Usage: $progname [OPTION]... [MODE-ARG]... # # Provide generalized library-building support services. # # --config show all configuration variables # --debug enable verbose shell tracing # -n, --dry-run display commands without modifying any files # --features display basic configuration information and exit # --mode=MODE use operation mode MODE # --preserve-dup-deps don't remove duplicate dependency libraries # --quiet, --silent don't print informational messages # --no-quiet, --no-silent # print informational messages (default) # --no-warn don't display warning messages # --tag=TAG use configuration variables from tag TAG # -v, --verbose print more informational messages than default # --no-verbose don't print the extra informational messages # --version print version information # -h, --help, --help-all print short, long, or detailed help message # # MODE must be one of the following: # # clean remove files from the build directory # compile compile a source file into a libtool object # execute automatically set library path, then run a program # finish complete the installation of libtool libraries # install install libraries or executables # link create a library or an executable # uninstall remove libraries from an installed directory # # MODE-ARGS vary depending on the MODE. When passed as first option, # `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. # Try `$progname --help --mode=MODE' for a more detailed description of MODE. # # When reporting a bug, please describe a test case to reproduce it and # include the following information: # # host-triplet: $host # shell: $SHELL # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) # $progname: (GNU libtool) 2.4.2 # automake: $automake_version # autoconf: $autoconf_version # # Report bugs to <bug-libtool@gnu.org>. # GNU libtool home page: <http://www.gnu.org/software/libtool/>. # General help using GNU software: <http://www.gnu.org/gethelp/>. PROGRAM=libtool PACKAGE=libtool VERSION=2.4.2 TIMESTAMP="" package_revision=1.3337 # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # NLS nuisances: We save the old values to restore during execute mode. lt_user_locale= lt_safe_locale= for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${$lt_var+set}\" = set; then save_$lt_var=\$$lt_var $lt_var=C export $lt_var lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" fi" done LC_ALL=C LANGUAGE=C export LANGUAGE LC_ALL $lt_unset CDPATH # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath="$0" : ${CP="cp -f"} test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} : ${Xsed="$SED -e 1s/^X//"} # Global variables: EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. exit_status=$EXIT_SUCCESS # Make sure IFS has a sensible default lt_nl=' ' IFS=" $lt_nl" dirname="s,/[^/]*$,," basename="s,^.*/,," # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_dirname may be replaced by extended shell implementation # func_basename file func_basename () { func_basename_result=`$ECHO "${1}" | $SED "$basename"` } # func_basename may be replaced by extended shell implementation # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` } # func_dirname_and_basename may be replaced by extended shell implementation # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # func_strip_suffix prefix name func_stripname () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname may be replaced by extended shell implementation # These SED scripts presuppose an absolute path with a trailing slash. pathcar='s,^/\([^/]*\).*$,\1,' pathcdr='s,^/[^/]*,,' removedotparts=':dotsl s@/\./@/@g t dotsl s,/\.$,/,' collapseslashes='s@/\{1,\}@/@g' finalslash='s,/*$,/,' # func_normal_abspath PATH # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. # value returned in "$func_normal_abspath_result" func_normal_abspath () { # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` while :; do # Processed it all yet? if test "$func_normal_abspath_tpath" = / ; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result" ; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_relative_path SRCDIR DSTDIR # generates a relative path from SRCDIR to DSTDIR, with a trailing # slash if non-empty, suitable for immediately appending a filename # without needing to append a separator. # value returned in "$func_relative_path_result" func_relative_path () { func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=${func_dirname_result} if test "x$func_relative_path_tlibdir" = x ; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test "x$func_stripname_result" != x ; then func_relative_path_result=${func_relative_path_result}/${func_stripname_result} fi # Normalisation. If bindir is libdir, return empty string, # else relative path ending with a slash; either way, target # file name can be directly appended. if test ! -z "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result/" func_relative_path_result=$func_stripname_result fi } # The name of this program: func_dirname_and_basename "$progpath" progname=$func_basename_result # Make sure we have an absolute path for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=$func_dirname_result progdir=`cd "$progdir" && pwd` progpath="$progdir/$progname" ;; *) save_IFS="$IFS" IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS="$save_IFS" test -x "$progdir/$progname" && break done IFS="$save_IFS" test -n "$progdir" || progdir=`pwd` progpath="$progdir/$progname" ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='s/\([`"$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' # Sed substitution that converts a w32 file name or path # which contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-`\' parameter expansions in output of double_quote_subst that were # `\'-ed in input to the same. If an odd number of `\' preceded a '$' # in input to double_quote_subst, that '$' was protected from expansion. # Since each input `\' is now two `\'s, look for any number of runs of # four `\'s followed by two `\'s and then a '$'. `\' that '$'. bs='\\' bs2='\\\\' bs4='\\\\\\\\' dollar='\$' sed_double_backslash="\ s/$bs4/&\\ /g s/^$bs2$dollar/$bs&/ s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g s/\n//g" # Standard options: opt_dry_run=false opt_help=false opt_quiet=false opt_verbose=false opt_warning=: # func_echo arg... # Echo program name prefixed message, along with the current mode # name if it has been set yet. func_echo () { $ECHO "$progname: ${opt_mode+$opt_mode: }$*" } # func_verbose arg... # Echo program name prefixed message in verbose mode only. func_verbose () { $opt_verbose && func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_error arg... # Echo program name prefixed message to standard error. func_error () { $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 } # func_warning arg... # Echo program name prefixed warning message to standard error. func_warning () { $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 # bash bug again: : } # func_fatal_error arg... # Echo program name prefixed message to standard error, and exit. func_fatal_error () { func_error ${1+"$@"} exit $EXIT_FAILURE } # func_fatal_help arg... # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { func_error ${1+"$@"} func_fatal_error "$help" } help="Try \`$progname --help' for more information." ## default # func_grep expression filename # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $GREP "$1" "$2" >/dev/null 2>&1 } # func_mkdir_p directory-path # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { my_directory_path="$1" my_dir_list= if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then # Protect directory names starting with `-' case $my_directory_path in -*) my_directory_path="./$my_directory_path" ;; esac # While some portion of DIR does not yet exist... while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` done my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` save_mkdir_p_IFS="$IFS"; IFS=':' for my_dir in $my_dir_list; do IFS="$save_mkdir_p_IFS" # mkdir can fail with a `File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$my_dir" 2>/dev/null || : done IFS="$save_mkdir_p_IFS" # Bail out if we (or some other process) failed to create a directory. test -d "$my_directory_path" || \ func_fatal_error "Failed to create \`$1'" fi } # func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, STRING is the basename for that directory. func_mktempdir () { my_template="${TMPDIR-/tmp}/${1-$progname}" if test "$opt_dry_run" = ":"; then # Return a directory name, but don't create it in dry-run mode my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` if test ! -d "$my_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race my_tmpdir="${my_template}-${RANDOM-0}$$" save_mktempdir_umask=`umask` umask 0077 $MKDIR "$my_tmpdir" umask $save_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$my_tmpdir" || \ func_fatal_error "cannot create temporary directory \`$my_tmpdir'" fi $ECHO "$my_tmpdir" } # func_quote_for_eval arg # Aesthetically quote ARG to be evaled later. # This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT # is double-quoted, suitable for a subsequent eval, whereas # FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters # which are still active within double quotes backslashified. func_quote_for_eval () { case $1 in *[\\\`\"\$]*) func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; *) func_quote_for_eval_unquoted_result="$1" ;; esac case $func_quote_for_eval_unquoted_result in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and and variable # expansion for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" ;; *) func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" esac } # func_quote_for_expand arg # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { case $1 in *[\\\`\"]*) my_arg=`$ECHO "$1" | $SED \ -e "$double_quote_subst" -e "$sed_double_backslash"` ;; *) my_arg="$1" ;; esac case $my_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") my_arg="\"$my_arg\"" ;; esac func_quote_for_expand_result="$my_arg" } # func_show_eval cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$my_cmd" my_status=$? if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_show_eval_locale cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$lt_user_locale $my_cmd" my_status=$? eval "$lt_safe_locale" if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_tr_sh # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_version # Echo version message to standard output and exit. func_version () { $opt_debug $SED -n '/(C)/!b go :more /\./!{ N s/\n# / / b more } :go /^# '$PROGRAM' (GNU /,/# warranty; / { s/^# // s/^# *$// s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ p }' < "$progpath" exit $? } # func_usage # Echo short help message to standard output and exit. func_usage () { $opt_debug $SED -n '/^# Usage:/,/^# *.*--help/ { s/^# // s/^# *$// s/\$progname/'$progname'/ p }' < "$progpath" echo $ECHO "run \`$progname --help | more' for full usage" exit $? } # func_help [NOEXIT] # Echo long help message to standard output and exit, # unless 'noexit' is passed as argument. func_help () { $opt_debug $SED -n '/^# Usage:/,/# Report bugs to/ { :print s/^# // s/^# *$// s*\$progname*'$progname'* s*\$host*'"$host"'* s*\$SHELL*'"$SHELL"'* s*\$LTCC*'"$LTCC"'* s*\$LTCFLAGS*'"$LTCFLAGS"'* s*\$LD*'"$LD"'* s/\$with_gnu_ld/'"$with_gnu_ld"'/ s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ p d } /^# .* home page:/b print /^# General help using/b print ' < "$progpath" ret=$? if test -z "$1"; then exit $ret fi } # func_missing_arg argname # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $opt_debug func_error "missing argument for $1." exit_cmd=exit } # func_split_short_opt shortopt # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. func_split_short_opt () { my_sed_short_opt='1s/^\(..\).*$/\1/;q' my_sed_short_rest='1s/^..\(.*\)$/\1/;q' func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` } # func_split_short_opt may be replaced by extended shell implementation # func_split_long_opt longopt # Set func_split_long_opt_name and func_split_long_opt_arg shell # variables after splitting LONGOPT at the `=' sign. func_split_long_opt () { my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' my_sed_long_arg='1s/^--[^=]*=//' func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` } # func_split_long_opt may be replaced by extended shell implementation exit_cmd=: magic="%%%MAGIC variable%%%" magic_exe="%%%MAGIC EXE variable%%%" # Global variables. nonopt= preserve_args= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "${1}=\$${1}\${2}" } # func_append may be replaced by extended shell implementation # func_append_quoted var value # Quote VALUE and append to the end of shell variable VAR, separated # by a space. func_append_quoted () { func_quote_for_eval "${2}" eval "${1}=\$${1}\\ \$func_quote_for_eval_result" } # func_append_quoted may be replaced by extended shell implementation # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "${@}"` } # func_arith may be replaced by extended shell implementation # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` } # func_len may be replaced by extended shell implementation # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` } # func_lo2o may be replaced by extended shell implementation # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` } # func_xform may be replaced by extended shell implementation # func_fatal_configuration arg... # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func_error ${1+"$@"} func_error "See the $PACKAGE documentation for more information." func_fatal_error "Fatal configuration error." } # func_config # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # Display the features supported by this script. func_features () { echo "host: $host" if test "$build_libtool_libs" = yes; then echo "enable shared libraries" else echo "disable shared libraries" fi if test "$build_old_libs" = yes; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag tagname # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname="$1" re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf="/$re_begincf/,/$re_endcf/p" # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Option defaults: opt_debug=: opt_dry_run=false opt_config=false opt_preserve_dup_deps=false opt_features=false opt_finish=false opt_help=false opt_help_all=false opt_silent=: opt_warning=: opt_verbose=: opt_silent=false opt_verbose=false # Parse options once, thoroughly. This comes as soon as possible in the # script to make things like `--version' happen as quickly as we can. { # this just eases exit handling while test $# -gt 0; do opt="$1" shift case $opt in --debug|-x) opt_debug='set -x' func_echo "enabling shell trace mode" $opt_debug ;; --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) opt_config=: func_config ;; --dlopen|-dlopen) optarg="$1" opt_dlopen="${opt_dlopen+$opt_dlopen }$optarg" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) opt_features=: func_features ;; --finish) opt_finish=: set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help_all=: opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_mode="$optarg" case $optarg in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_silent=false func_append preserve_args " $opt" ;; --no-warning|--no-warn) opt_warning=false func_append preserve_args " $opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $opt" ;; --silent|--quiet) opt_silent=: func_append preserve_args " $opt" opt_verbose=false ;; --verbose|-v) opt_verbose=: func_append preserve_args " $opt" opt_silent=false ;; --tag) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_tag="$optarg" func_append preserve_args " $opt $optarg" func_enable_tag "$optarg" shift ;; -\?|-h) func_usage ;; --help) func_help ;; --version) func_version ;; # Separate optargs to long options: --*=*) func_split_long_opt "$opt" set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-n*|-v*) func_split_short_opt "$opt" set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) break ;; -*) func_fatal_help "unrecognized option \`$opt'" ;; *) set dummy "$opt" ${1+"$@"}; shift; break ;; esac done # Validate options: # save first non-option argument if test "$#" -gt 0; then nonopt="$opt" shift fi # preserve --debug test "$opt_debug" = : || func_append preserve_args " --debug" case $host in *cygwin* | *mingw* | *pw32* | *cegcc*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then func_fatal_configuration "not configured to build any kind of library" fi # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test "$opt_mode" != execute; then func_error "unrecognized option \`-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$progname --help --mode=$opt_mode' for more information." } # Bail if the options were screwed $exit_cmd $EXIT_FAILURE } ## ----------- ## ## Main. ## ## ----------- ## # func_lalib_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null \ | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_unsafe_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if `file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case "$lalib_p_line" in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test "$lalib_p" = yes } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { func_lalib_p "$1" } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $opt_debug save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$save_ifs eval cmd=\"$cmd\" func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. func_source () { $opt_debug case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case "$lt_sysroot:$1" in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result="=$func_stripname_result" ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $opt_debug if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with \`--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=${1} if test "$build_libtool_libs" = yes; then write_lobj=\'${2}\' else write_lobj=none fi if test "$build_old_libs" = yes; then write_oldobj=\'${3}\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T <<EOF # $write_libobj - a libtool object file # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # Name of the PIC object. pic_object=$write_lobj # Name of the non-PIC object non_pic_object=$write_oldobj EOF $MV "${write_libobj}T" "${write_libobj}" } } ################################################## # FILE NAME AND PATH CONVERSION HELPER FUNCTIONS # ################################################## # func_convert_core_file_wine_to_w32 ARG # Helper function used by file name conversion functions when $build is *nix, # and $host is mingw, cygwin, or some other w32 environment. Relies on a # correctly configured wine environment available, with the winepath program # in $build's $PATH. # # ARG is the $build file name to be converted to w32 format. # Result is available in $func_convert_core_file_wine_to_w32_result, and will # be empty on error (or when ARG is empty) func_convert_core_file_wine_to_w32 () { $opt_debug func_convert_core_file_wine_to_w32_result="$1" if test -n "$1"; then # Unfortunately, winepath does not exit with a non-zero error code, so we # are forced to check the contents of stdout. On the other hand, if the # command is not found, the shell will set an exit code of 127 and print # *an error message* to stdout. So we must check for both error code of # zero AND non-empty stdout, which explains the odd construction: func_convert_core_file_wine_to_w32_tmp=`winepath -w "$1" 2>/dev/null` if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$lt_sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $opt_debug # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result="" if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result" ; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $opt_debug if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $opt_debug # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $opt_debug if test -z "$2" && test -n "$1" ; then func_error "Could not determine host file name corresponding to" func_error " \`$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result="$1" fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $opt_debug if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " \`$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result="$3" fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $opt_debug case $4 in $1 ) func_to_host_path_result="$3$func_to_host_path_result" ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via `$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $opt_debug $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $opt_debug case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result="$1" } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result="$func_convert_core_msys_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via `$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $opt_debug if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd="func_convert_path_${func_stripname_result}" fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $opt_debug func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result="$1" } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_msys_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_mode_compile arg... func_mode_compile () { $opt_debug # Get the compilation command and the source file. base_compile= srcfile="$nonopt" # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg="$arg" arg_mode=normal ;; target ) libobj="$arg" arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify \`-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs="$IFS"; IFS=',' for arg in $args; do IFS="$save_ifs" func_append_quoted lastarg "$arg" done IFS="$save_ifs" func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg="$srcfile" srcfile="$arg" ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with \`-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj="$func_basename_result" } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from \`$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name \`$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname="$func_basename_result" xdir="$func_dirname_result" lobj=${xdir}$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test "$suppress_opt" = yes; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test "$compiler_c_o" = yes; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test "$need_locks" != no; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test "$opt_mode" = compile && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a \`.o' file suitable for static linking -static only build a \`.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode \`$opt_mode'" ;; esac echo $ECHO "Try \`$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test "$opt_help" = :; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | sed -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | sed '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $opt_debug # The first argument is the command name. cmd="$nonopt" test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "\`$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "\`$file' was not linked with \`-export-dynamic'" continue fi func_dirname "$file" "" "." dir="$func_dirname_result" if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir="$func_dirname_result" ;; *) func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file="$progdir/$program" elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if test "X$opt_dry_run" = Xfalse; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS fi } test "$opt_mode" = execute && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $opt_debug libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "\`$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument \`$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and \`=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_silent && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the \`-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the \`$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the \`$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test "$opt_mode" = finish && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $opt_debug # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" func_append install_prog "$func_quote_for_eval_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=yes ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test "x$prev" = x-m && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" func_append install_prog " $func_quote_for_eval_result" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi func_append install_shared_prog " $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the \`$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_for_eval "$install_override_mode" func_append install_shared_prog " -m $func_quote_for_eval_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else func_dirname_and_basename "$dest" "" "." destdir="$func_dirname_result" destname="$func_basename_result" # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "\`$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "\`$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir="$func_dirname_result" func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking \`$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname="$1" shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme="$stripme" case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme="" ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try `ln -sf' first, because the `ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib="$destdir/$realname" func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name="$func_basename_result" instname="$dir/$name"i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest="$destfile" destfile= ;; *) func_fatal_help "cannot copy a libtool object to \`$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script \`$wrapper'" finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then func_warning "\`$lib' has not been installed in \`$libdir'" finalize=no fi done relink_command= func_source "$wrapper" outputname= if test "$fast_install" = no && test -n "$relink_command"; then $opt_dry_run || { if test "$finalize" = yes; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file="$func_basename_result" outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_silent || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink \`$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file="$outputname" else func_warning "cannot relink \`$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name="$func_basename_result" # Set up the ranlib parameters. oldlib="$destdir/$name" func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $tool_oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run \`$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test "$opt_mode" = install && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $opt_debug my_outputname="$1" my_originator="$2" my_pic_p="${3-no}" my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms="${my_outputname}S.c" else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${my_outputname}.nm" func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then func_verbose "generating symbol list for \`$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$outputname.exp" $opt_dry_run || { $RM $export_symbols eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from \`$dlprefile'" func_basename "$dlprefile" name="$func_basename_result" case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename="" if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname" ; then func_basename "$dlprefile_dlname" dlprefile_dlbasename="$func_basename_result" else # no lafile. user explicitly requested -dlpreopen <import library>. $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename" ; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 </dev/null >/dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[]; LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = {\ { \"$my_originator\", (void *) 0 }," case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) if test "X$my_pic_p" != Xno; then pic_flag_for_symtable=" $pic_flag" fi ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' # Transform the symbol file into the correct name. symfileobj="$output_objdir/${my_outputname}S.$objext" case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for \`$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $opt_debug win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s,.*,import, p q } }'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $opt_debug sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $opt_debug match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive which possess that section. Heuristic: eliminate # all those which have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $opt_debug if func_cygming_gnu_implib_p "$1" ; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1" ; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result="" fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $opt_debug f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" if test "$lock_old_archive_extraction" = yes; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test "$lock_old_archive_extraction" = yes; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $opt_debug my_gentop="$1"; shift my_oldlibs=${1+"$@"} my_oldobjs="" my_xlib="" my_xabs="" my_xdir="" for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib="$func_basename_result" my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir="$my_gentop/$my_xlib_u" func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` darwin_base_archive=`basename "$darwin_archive"` darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches ; do func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" func_extract_an_archive "`pwd`" "${darwin_base_archive}" cd "$darwin_curdir" $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result="$my_oldobjs" } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory in which it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=\"$qECHO\" fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ which is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options which match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { case \" \$* \" in *\\ --lt-*) for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done ;; esac func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat <<EOF /* $cwrappersource - temporary wrapper executable for $objdir/$outputname Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION The $output program cannot be directly executed until all the libtool libraries that it depends on are installed. This wrapper executable should never be moved out of the build directory. If it is, it will not operate correctly. */ EOF cat <<"EOF" #ifdef _MSC_VER # define _CRT_SECURE_NO_DEPRECATE 1 #endif #include <stdio.h> #include <stdlib.h> #ifdef _MSC_VER # include <direct.h> # include <process.h> # include <io.h> #else # include <unistd.h> # include <stdint.h> # ifdef __CYGWIN__ # include <io.h> # endif #endif #include <malloc.h> #include <stdarg.h> #include <assert.h> #include <string.h> #include <ctype.h> #include <errno.h> #include <fcntl.h> #include <sys/stat.h> /* declarations of non-ANSI functions */ #if defined(__MINGW32__) # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined(__CYGWIN__) # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined (other platforms) ... */ #endif /* portability defines, excluding path handling macros */ #if defined(_MSC_VER) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC # ifndef _INTPTR_T_DEFINED # define _INTPTR_T_DEFINED # define intptr_t int # endif #elif defined(__MINGW32__) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined(__CYGWIN__) # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined (other platforms) ... */ #endif #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) #if defined(LT_DEBUGWRAPPER) static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <<EOF volatile const char * MAGIC_EXE = "$magic_exe"; const char * LIB_PATH_VARNAME = "$shlibpath_var"; EOF if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then func_to_host_path "$temp_rpath" cat <<EOF const char * LIB_PATH_VALUE = "$func_to_host_path_result"; EOF else cat <<"EOF" const char * LIB_PATH_VALUE = ""; EOF fi if test -n "$dllsearchpath"; then func_to_host_path "$dllsearchpath:" cat <<EOF const char * EXE_PATH_VARNAME = "PATH"; const char * EXE_PATH_VALUE = "$func_to_host_path_result"; EOF else cat <<"EOF" const char * EXE_PATH_VARNAME = ""; const char * EXE_PATH_VALUE = ""; EOF fi if test "$fast_install" = yes; then cat <<EOF const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */ EOF else cat <<EOF const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */ EOF fi cat <<"EOF" #define LTWRAPPER_OPTION_PREFIX "--lt-" static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX; static const char *dumpscript_opt = LTWRAPPER_OPTION_PREFIX "dump-script"; static const char *debug_opt = LTWRAPPER_OPTION_PREFIX "debug"; int main (int argc, char *argv[]) { char **newargz; int newargc; char *tmp_pathspec; char *actual_cwrapper_path; char *actual_cwrapper_name; char *target_name; char *lt_argv_zero; intptr_t rval = 127; int i; program_name = (char *) xstrdup (base_name (argv[0])); newargz = XMALLOC (char *, argc + 1); /* very simple arg parsing; don't want to rely on getopt * also, copy all non cwrapper options to newargz, except * argz[0], which is handled differently */ newargc=0; for (i = 1; i < argc; i++) { if (strcmp (argv[i], dumpscript_opt) == 0) { EOF case "$host" in *mingw* | *cygwin* ) # make stdout use "unix" line endings echo " setmode(1,_O_BINARY);" ;; esac cat <<"EOF" lt_dump_script (stdout); return 0; } if (strcmp (argv[i], debug_opt) == 0) { lt_debug = 1; continue; } if (strcmp (argv[i], ltwrapper_option_prefix) == 0) { /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX namespace, but it is not one of the ones we know about and have already dealt with, above (inluding dump-script), then report an error. Otherwise, targets might begin to believe they are allowed to use options in the LTWRAPPER_OPTION_PREFIX namespace. The first time any user complains about this, we'll need to make LTWRAPPER_OPTION_PREFIX a configure-time option or a configure.ac-settable value. */ lt_fatal (__FILE__, __LINE__, "unrecognized %s option: '%s'", ltwrapper_option_prefix, argv[i]); } /* otherwise ... */ newargz[++newargc] = xstrdup (argv[i]); } newargz[++newargc] = NULL; EOF cat <<EOF /* The GNU banner must be the first non-error debug message */ lt_debugprintf (__FILE__, __LINE__, "libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\n"); EOF cat <<"EOF" lt_debugprintf (__FILE__, __LINE__, "(main) argv[0]: %s\n", argv[0]); lt_debugprintf (__FILE__, __LINE__, "(main) program_name: %s\n", program_name); tmp_pathspec = find_executable (argv[0]); if (tmp_pathspec == NULL) lt_fatal (__FILE__, __LINE__, "couldn't find %s", argv[0]); lt_debugprintf (__FILE__, __LINE__, "(main) found exe (before symlink chase) at: %s\n", tmp_pathspec); actual_cwrapper_path = chase_symlinks (tmp_pathspec); lt_debugprintf (__FILE__, __LINE__, "(main) found exe (after symlink chase) at: %s\n", actual_cwrapper_path); XFREE (tmp_pathspec); actual_cwrapper_name = xstrdup (base_name (actual_cwrapper_path)); strendzap (actual_cwrapper_path, actual_cwrapper_name); /* wrapper name transforms */ strendzap (actual_cwrapper_name, ".exe"); tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1); XFREE (actual_cwrapper_name); actual_cwrapper_name = tmp_pathspec; tmp_pathspec = 0; /* target_name transforms -- use actual target program name; might have lt- prefix */ target_name = xstrdup (base_name (TARGET_PROGRAM_NAME)); strendzap (target_name, ".exe"); tmp_pathspec = lt_extend_str (target_name, ".exe", 1); XFREE (target_name); target_name = tmp_pathspec; tmp_pathspec = 0; lt_debugprintf (__FILE__, __LINE__, "(main) libtool target name: %s\n", target_name); EOF cat <<EOF newargz[0] = XMALLOC (char, (strlen (actual_cwrapper_path) + strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1)); strcpy (newargz[0], actual_cwrapper_path); strcat (newargz[0], "$objdir"); strcat (newargz[0], "/"); EOF cat <<"EOF" /* stop here, and copy so we don't have to do this twice */ tmp_pathspec = xstrdup (newargz[0]); /* do NOT want the lt- prefix here, so use actual_cwrapper_name */ strcat (newargz[0], actual_cwrapper_name); /* DO want the lt- prefix here if it exists, so use target_name */ lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1); XFREE (tmp_pathspec); tmp_pathspec = NULL; EOF case $host_os in mingw*) cat <<"EOF" { char* p; while ((p = strchr (newargz[0], '\\')) != NULL) { *p = '/'; } while ((p = strchr (lt_argv_zero, '\\')) != NULL) { *p = '/'; } } EOF ;; esac cat <<"EOF" XFREE (target_name); XFREE (actual_cwrapper_path); XFREE (actual_cwrapper_name); lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */ lt_setenv ("DUALCASE", "1"); /* for MSK sh */ /* Update the DLL searchpath. EXE_PATH_VALUE ($dllsearchpath) must be prepended before (that is, appear after) LIB_PATH_VALUE ($temp_rpath) because on Windows, both *_VARNAMEs are PATH but uninstalled libraries must come first. */ lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE); lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE); lt_debugprintf (__FILE__, __LINE__, "(main) lt_argv_zero: %s\n", nonnull (lt_argv_zero)); for (i = 0; i < newargc; i++) { lt_debugprintf (__FILE__, __LINE__, "(main) newargz[%d]: %s\n", i, nonnull (newargz[i])); } EOF case $host_os in mingw*) cat <<"EOF" /* execv doesn't actually work on mingw as expected on unix */ newargz = prepare_spawn (newargz); rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz); if (rval == -1) { /* failed to start process */ lt_debugprintf (__FILE__, __LINE__, "(main) failed to launch target \"%s\": %s\n", lt_argv_zero, nonnull (strerror (errno))); return 127; } return rval; EOF ;; *) cat <<"EOF" execv (lt_argv_zero, newargz); return rval; /* =127, but avoids unused variable warning */ EOF ;; esac cat <<"EOF" } void * xmalloc (size_t num) { void *p = (void *) malloc (num); if (!p) lt_fatal (__FILE__, __LINE__, "memory exhausted"); return p; } char * xstrdup (const char *string) { return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL; } const char * base_name (const char *name) { const char *base; #if defined (HAVE_DOS_BASED_FILE_SYSTEM) /* Skip over the disk name in MSDOS pathnames. */ if (isalpha ((unsigned char) name[0]) && name[1] == ':') name += 2; #endif for (base = name; *name; name++) if (IS_DIR_SEPARATOR (*name)) base = name + 1; return base; } int check_executable (const char *path) { struct stat st; lt_debugprintf (__FILE__, __LINE__, "(check_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if ((stat (path, &st) >= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; int tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined (HAVE_DOS_BASED_FILE_SYSTEM) } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = q - p; p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (strcmp (str, pat) == 0) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else int len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { int orig_value_len = strlen (orig_value); int add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ int len = strlen (new_value); while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[len-1] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -n -e ' s/^\(.\{79\}\)\(..*\)/\1\ \2/ h s/\([\\"]\)/\\\1/g s/$/\\n/ s/\([^\n]*\).*/ fputs ("\1", f);/p g D' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $opt_debug case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_mode_link arg... func_mode_link () { $opt_debug case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module="${wl}-single_module" func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir="$arg" prev= continue ;; dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" test -f "$arg" \ || func_fatal_error "symbol file \`$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file \`$arg' does not exist" fi arg=$save_arg prev= continue ;; precious_regex) precious_files_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds="$arg" prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "\`-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between \`-L' and \`$1'" else func_fatal_error "need path for \`-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of \`$dir'" dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test "X$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module="${wl}-multi_module" continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "\`-no-install' is ignored for $host" func_warning "assuming \`-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-flto*|-fwhopr*|-fuse-linker-plugin) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test "$prev" = dlfiles; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the \`$prevarg' option requires an argument" if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname="$func_basename_result" libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" func_dirname "$output" "/" "" output_objdir="$func_dirname_result$objdir" func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps ; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test "$linkmode,$pass" = "lib,link"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs="$tmp_deplibs" fi if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi if test "$linkmode,$pass" = "lib,dlpreopen"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs="$dlprefiles" fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then func_warning "\`-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test "$linkmode" = lib; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no func_dirname "$lib" "" "." ladir="$func_dirname_result" lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l *.ltframework) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "\`-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=no case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi ;; pass_all) valid_a_lib=yes ;; esac if test "$valid_a_lib" != yes; then echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." else echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" fi # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "\`$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir="$func_dirname_result" dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" elif test "$linkmode" != prog && test "$linkmode" != lib; then func_fatal_error "\`$lib' is not a convenience library" fi tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test "$prefer_static_libs" = yes || test "$prefer_static_libs,$installed" = "built,no"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib="$l" done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then func_fatal_error "cannot -dlopen a convenience library: \`$lib'" fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of \`$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir="$ladir" fi ;; esac func_basename "$lib" laname="$func_basename_result" # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library \`$lib' was moved." dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$lt_sysroot$libdir" absdir="$lt_sysroot$libdir" fi test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir="$ladir" absdir="$abs_ladir" # Remove this search path later func_append notinst_path " $abs_ladir" else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir" && test "$linkmode" = prog; then func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" fi case "$host" in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { { test "$prefer_static_libs" = no || test "$prefer_static_libs,$installed" = "built,yes"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. case "$temp_rpath:" in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test "$use_static_libs" = built && test "$installed" = yes; then use_static_libs=no fi if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test "$installed" = no; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule="" for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule="$dlpremoduletest" break fi done if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then echo if test "$linkmode" = prog; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname="$1" shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc*) func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" func_basename "$soroot" soname="$func_basename_result" func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from \`$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for \`$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$opt_mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; *-*-sysv4*uw2*) add_dir="-L$dir" ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we can not # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null ; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library" ; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add="$dir/$old_library" fi elif test -n "$old_library"; then add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$absdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && test "$hardcode_minus_L" != yes && test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$opt_mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system can not link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs="$temp_deplibs" fi func_append newlib_search_path " $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path="$deplib" ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of \`$dir'" absdir="$dir" fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl" ; then depdepl="$absdir/$objdir/$depdepl" darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" path= fi fi ;; *) path="-L$absdir/$objdir" ;; esac else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "\`$deplib' seems to be moved" path="-L$absdir" fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test "$pass" = link; then if test "$linkmode" = "prog"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" fi if test "$linkmode" = prog || test "$linkmode" = lib; then dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "\`-R' is ignored for archives" test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "\`-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "\`-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test "$module" = no && \ func_fatal_help "libtool library \`$output' must begin with \`lib'" if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test "$dlself" != no && \ func_warning "\`-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test "$#" -gt 1 && \ func_warning "ignoring multiple \`-rpath's for a libtool library" install_libdir="$1" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "\`-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 shift IFS="$save_ifs" test -n "$7" && \ func_fatal_help "too many parameters to \`-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$1" number_minor="$2" number_revision="$3" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|qnx|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_minor" lt_irix_increment=no ;; esac ;; no) current="$1" revision="$2" age="$3" ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT \`$current' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION \`$revision' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE \`$age' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE \`$age' is greater than the current interface number \`$current'" func_fatal_error "\`$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current" ;; irix | nonstopux) if test "X$lt_irix_increment" = "Xno"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring:${iface}.0" done # Make executables depend on our current version. func_append verstring ":${current}.0" ;; qnx) major=".$current" versuffix=".$current" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; *) func_fatal_configuration "unknown library version type \`$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then func_warning "undefined symbols not allowed in $host shared libraries" build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi func_generate_dlsyms "$libname" "$libname" "yes" func_append libobjs " $symfileobj" test "X$libobjs" = "X " && libobjs= if test "$opt_mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) if test "X$precious_files_regex" != "X"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c <<EOF int main() { return 0; } EOF $opt_dry_run || $RM conftest if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then ldd_output=`ldd conftest` for i in $deplibs; do case $i in -l*) func_stripname -l '' "$i" name=$func_stripname_result if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $i "*) func_append newdeplibs " $i" i="" ;; esac fi if test -n "$i" ; then libname=`eval "\\$ECHO \"$libname_spec\""` deplib_matches=`eval "\\$ECHO \"$library_names_spec\""` set dummy $deplib_matches; shift deplib_match=$1 if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then func_append newdeplibs " $i" else droppeddeps=yes echo $ECHO "*** Warning: dynamic linker does not accept needed library $i." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which I believe you do not have" echo "*** because a test_compile did reveal that the linker did not use it for" echo "*** its dynamic dependency list that programs get resolved with at runtime." fi fi ;; *) func_append newdeplibs " $i" ;; esac done else # Error occurred in the first compile. Let's try to salvage # the situation: Compile a separate program for each library. for i in $deplibs; do case $i in -l*) func_stripname -l '' "$i" name=$func_stripname_result $opt_dry_run || $RM conftest if $LTCC $LTCFLAGS -o conftest conftest.c $i; then ldd_output=`ldd conftest` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $i "*) func_append newdeplibs " $i" i="" ;; esac fi if test -n "$i" ; then libname=`eval "\\$ECHO \"$libname_spec\""` deplib_matches=`eval "\\$ECHO \"$library_names_spec\""` set dummy $deplib_matches; shift deplib_match=$1 if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then func_append newdeplibs " $i" else droppeddeps=yes echo $ECHO "*** Warning: dynamic linker does not accept needed library $i." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because a test_compile did reveal that the linker did not use this one" echo "*** as a dynamic dependency that programs can get resolved with at runtime." fi fi else droppeddeps=yes echo $ECHO "*** Warning! Library $i is needed by this library but I was not able to" echo "*** make it link in! You will probably need to install it or some" echo "*** library that it depends on before this library will be fully" echo "*** functional. Installing it before continuing would be even better." fi ;; *) func_append newdeplibs " $i" ;; esac done fi ;; file_magic*) set dummy $deplibs_check_method; shift file_magic_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` if test -n "$file_magic_glob"; then libnameglob=`func_echo_all "$libname" | $SED -e $file_magic_glob` else libnameglob=$libname fi test "$want_nocaseglob" = yes && nocaseglob=`shopt -p nocaseglob` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do if test "$want_nocaseglob" = yes; then shopt -s nocaseglob potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test "X$deplibs_check_method" = "Xnone"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs="$new_libs" # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then # Remove ${wl} instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$opt_mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname="$1" shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi lib="$output_objdir/$realname" linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols="$output_objdir/$libname.uexp" func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile if test "x`$SED 1q $export_symbols`" != xEXPORTS; then # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols="$export_symbols" export_symbols= always_export_symbols=yes fi fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs="$IFS"; IFS='~' for cmd1 in $cmds; do IFS="$save_ifs" # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test "$try_normal_branch" = yes \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=${output_objdir}/${output_la}.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS="$save_ifs" if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test "$compiler_needs_object" = yes && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test "X$skipped_export" != "X:" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then output=${output_objdir}/${output_la}.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test "$compiler_needs_object" = yes; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-${k}.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test "X$objlist" = X || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-${k}.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\${concat_cmds}$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi if ${skipped_export-false}; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi fi test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi if ${skipped_export-false}; then if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi fi libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "\`-R' is ignored for objects" test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for objects" test -n "$release" && \ func_warning "\`-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object \`$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec and hope we can get by with # turning comma into space.. wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` else gentop="$output_objdir/${obj}x" func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" # Create the old-style object. reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for programs" test -n "$release" && \ func_warning "\`-release' is ignored for programs" test "$preload" = yes \ && test "$dlopen_support" = unknown \ && test "$dlopen_self" = unknown \ && test "$dlopen_self_static" = unknown && \ func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test "$tagname" = CXX ; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " ${wl}-bind_at_load" func_append finalize_command " ${wl}-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs="$new_libs" func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" "no" # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=yes case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=no ;; *cygwin* | *mingw* ) if test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; *) if test "$need_relink" = no || test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; esac if test "$wrappers_required" = no; then # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.${objext}"; then func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' fi exit $exit_status fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" func_warning "this platform does not like uninstalled shared libraries" func_warning "\`$output' will be relinked during installation" else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource="$output_path/$objdir/lt-$output_name.c" cwrapper="$output_path/$output_name.exe" $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host" ; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save $symfileobj" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" if test "$preload" = yes && test -f "$symfileobj"; then func_append oldobjs " $symfileobj" fi fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase="$func_basename_result" case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name="$func_basename_result" func_resolve_sysroot "$deplib" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles="$newdlprefiles" fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test "x$bindir" != x ; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that can not go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } { test "$opt_mode" = link || test "$opt_mode" = relink; } && func_mode_link ${1+"$@"} # func_mode_uninstall arg... func_mode_uninstall () { $opt_debug RM="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) func_append RM " $arg"; rmforce=yes ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir="$func_dirname_result" if test "X$dir" = X.; then odir="$objdir" else odir="$dir/$objdir" fi func_basename "$file" name="$func_basename_result" test "$opt_mode" = uninstall && odir="$dir" # Remember odir for removal later, being careful to avoid duplicates if test "$opt_mode" = clean; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case "$opt_mode" in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test "$pic_object" != none; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test "$non_pic_object" != none; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test "$opt_mode" = clean ; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name" ; then func_append rmfiles " $odir/lt-${noexename}.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } { test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && func_mode_uninstall ${1+"$@"} test -z "$opt_mode" && { help="$generic_help" func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode \`$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: # vi:sw=2 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/AUTHORS���������������������������������������������������������������������0000644�0001750�0001750�00000000740�11165152371�017247� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������Ross Burton <ross@burtonini.com> Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Dafydd Harries <dafydd.harries@collabora.co.uk> Robert McQueen <robert.mcqueen@collabora.co.uk> Simon McVittie <simon.mcvittie@collabora.co.uk> Mads Chr. Olesen <shiyee@shiyee.dk> Senko Rasic <senko.rasic@collabora.co.uk> Ole André Ravnaas <ole.andre.ravnaas@collabora.co.uk> Olli Salli <olli.salli@collabora.co.uk> Sjoerd Simons <sjoerd@luon.net> Rob Taylor <rob.taylor@collabora.co.uk> ��������������������������������telepathy-gabble-0.18.3/config.h.in�����������������������������������������������������������������0000664�0001750�0001750�00000011512�12332443654�020227� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* config.h.in. Generated from configure.ac by autoheader. */ /* Client type from http://xmpp.org/registrar/disco-categories.html#client */ #undef CLIENT_TYPE /* Enable Channel.Type.Call */ #undef ENABLE_CHANNEL_TYPE_CALL /* Enable debug code */ #undef ENABLE_DEBUG /* Critical warnings will result in an assertion */ #undef ENABLE_FATAL_CRITICALS /* Enable file transfer */ #undef ENABLE_FILE_TRANSFER /* Enable Google Jingle relay support */ #undef ENABLE_GOOGLE_RELAY /* Make tests installable */ #undef ENABLE_INSTALLED_TESTS /* Enable file transfer */ #undef ENABLE_JINGLE_FILE_TRANSFER /* Enable plugins */ #undef ENABLE_PLUGINS /* Enable VoIP */ #undef ENABLE_VOIP /* Prevent post 2.32 APIs */ #undef GLIB_VERSION_MAX_ALLOWED /* Ignore post 2.30 deprecations */ #undef GLIB_VERSION_MIN_REQUIRED /* path to system Certificate Authority list */ #undef GTLS_SYSTEM_CA_CERTIFICATES /* Define to 1 if you have the <arpa/inet.h> header file. */ #undef HAVE_ARPA_INET_H /* Define to 1 if you have the <arpa/nameser.h> header file. */ #undef HAVE_ARPA_NAMESER_H /* Define to 1 if you have the <dlfcn.h> header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the <fcntl.h> header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the `getifaddrs' function. */ #undef HAVE_GETIFADDRS /* Define to 1 if you have the <ifaddrs.h> header file. */ #undef HAVE_IFADDRS_H /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the <memory.h> header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `memset' function. */ #undef HAVE_MEMSET /* Define to 1 if you have the <netdb.h> header file. */ #undef HAVE_NETDB_H /* Define to 1 if you have the <netinet/in.h> header file. */ #undef HAVE_NETINET_IN_H /* Define to 1 if you have the <net/if.h> header file. */ #undef HAVE_NET_IF_H /* Define to 1 if you have the <resolv.h> header file. */ #undef HAVE_RESOLV_H /* Define to 1 if you have the `select' function. */ #undef HAVE_SELECT /* Define to 1 if you have the `setresuid' function. */ #undef HAVE_SETRESUID /* Define to 1 if you have the `setreuid' function. */ #undef HAVE_SETREUID /* Define to 1 if you have the <stdint.h> header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the <stdlib.h> header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR /* Define to 1 if you have the <strings.h> header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the <string.h> header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strndup' function. */ #undef HAVE_STRNDUP /* Define to 1 if you have the <sys/ioctl.h> header file. */ #undef HAVE_SYS_IOCTL_H /* Define to 1 if you have the <sys/socket.h> header file. */ #undef HAVE_SYS_SOCKET_H /* Define to 1 if you have the <sys/stat.h> header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the <sys/types.h> header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the <sys/un.h> header file. */ #undef HAVE_SYS_UN_H /* Define to 1 if you have the <unistd.h> header file. */ #undef HAVE_UNISTD_H /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Disable single header include */ #undef TP_DISABLE_SINGLE_INCLUDE /* Prevent to use sealed variables */ #undef TP_SEAL_ENABLE /* Prevent post 0.20 APIs */ #undef TP_VERSION_MAX_ALLOWED /* Ignore post 0.18 deprecations */ #undef TP_VERSION_MIN_REQUIRED /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # undef _ALL_SOURCE #endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # undef _GNU_SOURCE #endif /* Enable threading extensions on Solaris. */ #ifndef _POSIX_PTHREAD_SEMANTICS # undef _POSIX_PTHREAD_SEMANTICS #endif /* Enable extensions on HP NonStop. */ #ifndef _TANDEM_SOURCE # undef _TANDEM_SOURCE #endif /* Enable general extensions on Solaris. */ #ifndef __EXTENSIONS__ # undef __EXTENSIONS__ #endif /* Version number of package */ #undef VERSION /* Define to 1 if on MINIX. */ #undef _MINIX /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ #undef _POSIX_1_SOURCE /* Define to 1 if you need to in order for `stat' and other things to work. */ #undef _POSIX_SOURCE ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/depcomp���������������������������������������������������������������������0000755�0001750�0001750�00000056016�12332443655�017570� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2013-05-30.07; # UTC # Copyright (C) 1999-2013 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, see <http://www.gnu.org/licenses/>. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>. case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to <bug-automake@gnu.org>. EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/data/�����������������������������������������������������������������������0000775�0001750�0001750�00000000000�12332445274�017115� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/data/Makefile.am������������������������������������������������������������0000664�0001750�0001750�00000001373�12332440117�021144� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������EXTRA_DIST = gabble.service.in managerdir = $(datadir)/telepathy/managers manager_DATA = gabble.manager servicedir = $(datadir)/dbus-1/services service_DATA = org.freedesktop.Telepathy.ConnectionManager.gabble.service # We don't use the full filename for the .in because > 99 character filenames # in tarballs are non-portable (and automake 1.8 doesn't let us build # non-archaic tarballs) org.freedesktop.Telepathy.ConnectionManager.gabble.service: gabble.service.in \ Makefile $(AM_V_GEN)sed -e "s|[@]libexecdir[@]|$(libexecdir)|" $< > $@ CLEANFILES = $(service_DATA) $(manager_DATA) $(manager_DATA): ../src/write-mgr-file.c ../src/protocol.c ../src/protocol.h @$(MAKE) -C ../src write-mgr-file$(EXEEXT) $(AM_V_GEN)../src/write-mgr-file$(EXEEXT) > $@ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/data/gabble.service.in������������������������������������������������������0000664�0001750�0001750�00000000153�12332440117�022306� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������[D-BUS Service] Name=org.freedesktop.Telepathy.ConnectionManager.gabble Exec=@libexecdir@/telepathy-gabble ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/data/Makefile.in������������������������������������������������������������0000664�0001750�0001750�00000040765�12332443655�021177� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = data DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_config_dir.m4 \ $(top_srcdir)/m4/compiler.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/tp-compiler-flag.m4 \ $(top_srcdir)/m4/tp-compiler-warnings.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(managerdir)" "$(DESTDIR)$(servicedir)" DATA = $(manager_DATA) $(service_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLIENT_TYPE = @CLIENT_TYPE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_CODING_STYLE_CHECKS = @ENABLE_CODING_STYLE_CHECKS@ ENABLE_PLUGINS = @ENABLE_PLUGINS@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NICE_CFLAGS = @NICE_CFLAGS@ NICE_LIBS = @NICE_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOUP_CFLAGS = @SOUP_CFLAGS@ SOUP_LIBS = @SOUP_LIBS@ STRIP = @STRIP@ TEST_PYTHON = @TEST_PYTHON@ TP_GLIB_CFLAGS = @TP_GLIB_CFLAGS@ TP_GLIB_LIBS = @TP_GLIB_LIBS@ VERSION = @VERSION@ WOCKY_CFLAGS = @WOCKY_CFLAGS@ WOCKY_LIBS = @WOCKY_LIBS@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gabbletestsdir = @gabbletestsdir@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ pluginexecdir = @pluginexecdir@ pluginexeclibdir = @pluginexeclibdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = gabble.service.in managerdir = $(datadir)/telepathy/managers manager_DATA = gabble.manager servicedir = $(datadir)/dbus-1/services service_DATA = org.freedesktop.Telepathy.ConnectionManager.gabble.service CLEANFILES = $(service_DATA) $(manager_DATA) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu data/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu data/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-managerDATA: $(manager_DATA) @$(NORMAL_INSTALL) @list='$(manager_DATA)'; test -n "$(managerdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(managerdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(managerdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(managerdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(managerdir)" || exit $$?; \ done uninstall-managerDATA: @$(NORMAL_UNINSTALL) @list='$(manager_DATA)'; test -n "$(managerdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(managerdir)'; $(am__uninstall_files_from_dir) install-serviceDATA: $(service_DATA) @$(NORMAL_INSTALL) @list='$(service_DATA)'; test -n "$(servicedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(servicedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(servicedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(servicedir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(servicedir)" || exit $$?; \ done uninstall-serviceDATA: @$(NORMAL_UNINSTALL) @list='$(service_DATA)'; test -n "$(servicedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(servicedir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(DATA) installdirs: for dir in "$(DESTDIR)$(managerdir)" "$(DESTDIR)$(servicedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-managerDATA install-serviceDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-managerDATA uninstall-serviceDATA .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-managerDATA install-pdf install-pdf-am install-ps \ install-ps-am install-serviceDATA install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-managerDATA uninstall-serviceDATA # We don't use the full filename for the .in because > 99 character filenames # in tarballs are non-portable (and automake 1.8 doesn't let us build # non-archaic tarballs) org.freedesktop.Telepathy.ConnectionManager.gabble.service: gabble.service.in \ Makefile $(AM_V_GEN)sed -e "s|[@]libexecdir[@]|$(libexecdir)|" $< > $@ $(manager_DATA): ../src/write-mgr-file.c ../src/protocol.c ../src/protocol.h @$(MAKE) -C ../src write-mgr-file$(EXEEXT) $(AM_V_GEN)../src/write-mgr-file$(EXEEXT) > $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: �����������telepathy-gabble-0.18.3/COPYING���������������������������������������������������������������������0000644�0001750�0001750�00000067152�11423525545�017250� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������Most of Gabble is licensed under the GNU Lesser General Public License, as published by the Free Software Foundation and reproduced below: either version 2.1 of the License, or (at your option) any later version. XEP tools in the the docs/ directory, used to generate HTML documentation for various non-standard XMPP extensions, are copyright 1999-2009 by the XMPP Standards Foundation (XSF) and is released under a MIT-style license, reproduced below. ------------------------------------------------------------------------ GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. <one line to give the library's name and a brief idea of what it does.> Copyright (C) <year> <name of author> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. <signature of Ty Coon>, 1 April 1990 Ty Coon, President of Vice That's all there is to it! ------------------------------------------------------------------------ License of docs/xep.xsl etc. Copyright (c) 1999 - 2009 XMPP Standards Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/������������������������������������������������������������������������0000775�0001750�0001750�00000000000�12332445274�016752� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/gibber/�����������������������������������������������������������������0000775�0001750�0001750�00000000000�12332445274�020204� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/gibber/gibber-unix-transport.h������������������������������������������0000644�0001750�0001750�00000007010�11423525545�024616� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gibber-unix-transport.h - Header for GibberUnixTransport * Copyright (C) 2006, 2008 Collabora Ltd. * @author: Sjoerd Simons <sjoerd@luon.net> * @author: Alban Crequy <alban.crequy@collabora.co.uk> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GIBBER_UNIX_TRANSPORT_H__ #define __GIBBER_UNIX_TRANSPORT_H__ #include <glib-object.h> #ifdef G_OS_UNIX #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #include <sys/un.h> #include "gibber-fd-transport.h" G_BEGIN_DECLS GQuark gibber_unix_transport_error_quark (void); #define GIBBER_UNIX_TRANSPORT_ERROR gibber_unix_transport_error_quark() typedef enum { GIBBER_UNIX_TRANSPORT_ERROR_CONNECT_FAILED, GIBBER_UNIX_TRANSPORT_ERROR_FAILED, GIBBER_UNIX_TRANSPORT_ERROR_NO_CREDENTIALS, } GibberUnixTransportError; typedef struct _GibberUnixTransport GibberUnixTransport; typedef struct _GibberUnixTransportClass GibberUnixTransportClass; struct _GibberUnixTransportClass { GibberFdTransportClass parent_class; }; struct _GibberUnixTransport { GibberFdTransport parent; }; GType gibber_unix_transport_get_type (void); /* TYPE MACROS */ #define GIBBER_TYPE_UNIX_TRANSPORT \ (gibber_unix_transport_get_type ()) #define GIBBER_UNIX_TRANSPORT(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GIBBER_TYPE_UNIX_TRANSPORT, \ GibberUnixTransport)) #define GIBBER_UNIX_TRANSPORT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GIBBER_TYPE_UNIX_TRANSPORT, \ GibberUnixTransportClass)) #define GIBBER_IS_UNIX_TRANSPORT(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GIBBER_TYPE_UNIX_TRANSPORT)) #define GIBBER_IS_UNIX_TRANSPORT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GIBBER_TYPE_UNIX_TRANSPORT)) #define GIBBER_UNIX_TRANSPORT_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GIBBER_TYPE_UNIX_TRANSPORT, \ GibberUnixTransportClass)) gboolean gibber_unix_transport_supports_credentials (void); GibberUnixTransport * gibber_unix_transport_new (void); GibberUnixTransport * gibber_unix_transport_new_from_fd (int fd); gboolean gibber_unix_transport_connect (GibberUnixTransport *transport, const gchar *path, GError **error); gboolean gibber_unix_transport_send_credentials (GibberUnixTransport *transport, const guint8 *data, gsize size); typedef struct { pid_t pid; uid_t uid; gid_t gid; } GibberCredentials; typedef void (*GibberUnixTransportRecvCredentialsCb) ( GibberUnixTransport *transport, GibberBuffer *buffer, GibberCredentials *credentials, GError *error, gpointer user_data); gboolean gibber_unix_transport_recv_credentials (GibberUnixTransport *transport, GibberUnixTransportRecvCredentialsCb callback, gpointer user_data); G_END_DECLS #endif /* G_OS_UNIX */ #endif /* #ifndef __GIBBER_UNIX_TRANSPORT_H__*/ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/gibber/gibber-debug.h���������������������������������������������������0000664�0001750�0001750�00000003240�12332441362�022664� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ #ifndef __DEBUG_H__ #define __DEBUG_H__ #include "config.h" #include <glib.h> #if 0 #include "gibber-xmpp-stanza.h" #endif G_BEGIN_DECLS #ifdef ENABLE_DEBUG typedef enum { DEBUG_TRANSPORT = 1 << 0, DEBUG_NET = 1 << 1, DEBUG_XMPP_READER = 1 << 2, DEBUG_XMPP_WRITER = 1 << 3, DEBUG_SASL = 1 << 4, DEBUG_SSL = 1 << 5, DEBUG_RMULTICAST = 1 << 6, DEBUG_RMULTICAST_SENDER = 1 << 7, DEBUG_MUC_CONNECTION = 1 << 8, DEBUG_BYTESTREAM = 1 << 9, DEBUG_FILE_TRANSFER = 1 << 10, } DebugFlags; #define DEBUG_XMPP (DEBUG_XMPP_READER | DEBUG_XMPP_WRITER) void gibber_debug_set_flags_from_env (void); void gibber_debug_set_flags (DebugFlags flags); gboolean gibber_debug_flag_is_set (DebugFlags flag); void gibber_debug (DebugFlags flag, const gchar *format, ...) G_GNUC_PRINTF (2, 3); #if 0 void gibber_debug_stanza (DebugFlags flag, GibberXmppStanza *stanza, const gchar *format, ...) G_GNUC_PRINTF (3, 4); #endif #ifdef DEBUG_FLAG #define DEBUG(format, ...) \ G_STMT_START { \ gibber_debug (DEBUG_FLAG, "%s: " format, G_STRFUNC, ##__VA_ARGS__); \ } G_STMT_END #define DEBUG_STANZA(stanza, format, ...) \ G_STMT_START { \ gibber_debug_stanza (DEBUG_FLAG, stanza, "%s: " format, G_STRFUNC,\ ##__VA_ARGS__); \ } G_STMT_END #define DEBUGGING (debug_flag_is_set (DEBUG_FLAG)) #endif /* DEBUG_FLAG */ #else /* ENABLE_DEBUG */ #ifdef DEBUG_FLAG #define DEBUG(format, ...) G_STMT_START { } G_STMT_END #define DEBUG_STANZA(stanza, format, ...) G_STMT_START { } G_STMT_END #define DEBUGGING (0) #endif /* DEBUG_FLAG */ #endif /* ENABLE_DEBUG */ G_END_DECLS #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/gibber/gibber-linklocal-transport.h�������������������������������������0000644�0001750�0001750�00000005310�11203243435�025573� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gibber-linklocal-transport.h - Header for GibberLLTransport * Copyright (C) 2006 Collabora Ltd. * @author: Sjoerd Simons <sjoerd@luon.net> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GIBBER_LL_TRANSPORT_H__ #define __GIBBER_LL_TRANSPORT_H__ #include <glib-object.h> #include "gibber-fd-transport.h" G_BEGIN_DECLS GQuark gibber_ll_transport_error_quark (void); #define GIBBER_LL_TRANSPORT_ERROR gibber_ll_transport_error_quark() typedef enum { GIBBER_LL_TRANSPORT_ERROR_CONNECT_FAILED, GIBBER_LL_TRANSPORT_ERROR_FAILED, } GibberLLTransportError; typedef struct _GibberLLTransport GibberLLTransport; typedef struct _GibberLLTransportClass GibberLLTransportClass; struct _GibberLLTransportClass { GibberFdTransportClass parent_class; }; struct _GibberLLTransport { GibberFdTransport parent; }; GType gibber_ll_transport_get_type (void); /* TYPE MACROS */ #define GIBBER_TYPE_LL_TRANSPORT \ (gibber_ll_transport_get_type ()) #define GIBBER_LL_TRANSPORT(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GIBBER_TYPE_LL_TRANSPORT, \ GibberLLTransport)) #define GIBBER_LL_TRANSPORT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GIBBER_TYPE_LL_TRANSPORT, \ GibberLLTransportClass)) #define GIBBER_IS_LL_TRANSPORT(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GIBBER_TYPE_LL_TRANSPORT)) #define GIBBER_IS_LL_TRANSPORT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GIBBER_TYPE_LL_TRANSPORT)) #define GIBBER_LL_TRANSPORT_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GIBBER_TYPE_LL_TRANSPORT, \ GibberLLTransportClass)) GibberLLTransport * gibber_ll_transport_new (void); void gibber_ll_transport_open_fd (GibberLLTransport *connection, int fd); gboolean gibber_ll_transport_open_sockaddr (GibberLLTransport *connection, struct sockaddr_storage *addr, GError **error); gboolean gibber_ll_transport_is_incoming (GibberLLTransport *connection); void gibber_ll_transport_set_incoming (GibberLLTransport *connetion, gboolean incoming); G_END_DECLS #endif /* #ifndef __GIBBER_LL_TRANSPORT_H__*/ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/gibber/Makefile.am������������������������������������������������������0000664�0001750�0001750�00000004657�11711756652�022261� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������noinst_LTLIBRARIES = libgibber.la BUILT_SOURCES = \ gibber-signals-marshal.list \ gibber-signals-marshal.h \ gibber-signals-marshal.c OUR_SOURCES = \ gibber-debug.c \ gibber-debug.h \ gibber-transport.c \ gibber-transport.h \ gibber-fd-transport.c \ gibber-fd-transport.h \ gibber-tcp-transport.c \ gibber-tcp-transport.h \ gibber-unix-transport.c \ gibber-unix-transport.h \ gibber-linklocal-transport.c \ gibber-linklocal-transport.h \ gibber-listener.c \ gibber-listener.h \ gibber-sockets.c \ gibber-sockets.h \ gibber-sockets-unix.h \ gibber-sockets-win32.h \ gibber-util.h \ gibber-util.c libgibber_la_SOURCES = $(OUR_SOURCES) $(BUILT_SOURCES) # Coding style checks check_c_sources = \ $(OUR_SOURCES) include $(top_srcdir)/tools/check-coding-style.mk check-local: check-coding-style CLEANFILES=$(BUILT_SOURCES) dist-hook: $(shell for x in $(BUILT_SOURCES); do rm -f $(distdir)/$$x ; done) gibber-signals-marshal.list: $(OUR_SOURCES) Makefile.am @( cd $(srcdir) && \ sed -n -e 's/.*_gibber_signals_marshal_\([[:upper:][:digit:]]*__[[:upper:][:digit:]_]*\).*/\1/p' \ $(OUR_SOURCES) ) \ | sed -e 's/__/:/' -e 'y/_/,/' | sort -u > $@.tmp @if cmp -s $@.tmp $@; then \ rm $@.tmp; \ touch $@; \ else \ mv $@.tmp $@; \ fi %-signals-marshal.h: %-signals-marshal.list Makefile.am $(AM_V_GEN)glib-genmarshal --header --prefix=_$(subst -,_,$*)_signals_marshal $< > $@ %-signals-marshal.c: %-signals-marshal.list Makefile.am $(AM_V_GEN){ echo '#include "$*-signals-marshal.h"' && \ glib-genmarshal --body --prefix=_$(subst -,_,$*)_signals_marshal $< ; \ } > $@ AM_CFLAGS = $(ERROR_CFLAGS) $(GCOV_CFLAGS) @GLIB_CFLAGS@ @GMODULE_CFLAGS@ -fno-strict-aliasing # following flag is requied to make getnameinfo work if WINDOWS AM_CFLAGS += -D_WIN32_WINNT=0x0501 endif AM_LDFLAGS = $(GCOV_LIBS) @GLIB_LIBS@ Android.mk: Makefile.am $(BUILT_SOURCES) androgenizer -:PROJECT telepathy-gabble -:STATIC gibber -:TAGS eng debug \ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ -:SOURCES $(libgibber_la_SOURCES) \ -:CFLAGS $(DEFS) $(CFLAGS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CFLAGS) \ -:CPPFLAGS $(CPPFLAGS) $(AM_CPPFLAGS) \ -:LDFLAGS $(AM_LDFLAGS) \ > $@ ���������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/gibber/gibber-transport.h�����������������������������������������������0000644�0001750�0001750�00000010652�11423525545�023643� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gibber-transport.h - Header for GibberTransport * Copyright (C) 2006 Collabora Ltd. * @author Sjoerd Simons <sjoerd@luon.net> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GIBBER_TRANSPORT_H__ #define __GIBBER_TRANSPORT_H__ #include <glib-object.h> #include "gibber-sockets.h" G_BEGIN_DECLS typedef enum { GIBBER_TRANSPORT_DISCONNECTED = 0, GIBBER_TRANSPORT_CONNECTING, GIBBER_TRANSPORT_CONNECTED, GIBBER_TRANSPORT_DISCONNECTING, } GibberTransportState; typedef struct _GibberTransport GibberTransport; typedef struct _GibberTransportClass GibberTransportClass; typedef struct _GibberBuffer GibberBuffer; typedef void (*GibberHandlerFunc) (GibberTransport *transport, GibberBuffer *buffer, gpointer user_data); struct _GibberBuffer { const guint8 *data; gsize length; }; struct _GibberTransportClass { GObjectClass parent_class; gboolean (*send) (GibberTransport *transport, const guint8 *data, gsize length, GError **error); void (*disconnect) (GibberTransport *transport); gboolean (*get_peeraddr) (GibberTransport *transport, struct sockaddr_storage *addr, socklen_t *len); gboolean (*get_sockaddr) (GibberTransport *transport, struct sockaddr_storage *addr, socklen_t *len); gboolean (*buffer_is_empty) (GibberTransport *transport); void (*block_receiving) (GibberTransport *transport, gboolean block); }; struct _GibberTransport { GObject parent; GibberTransportState state; /* Maximum packet size for transports where it matters, 0 otherwise */ gsize max_packet_size; /* FIXME Should be private... */ GibberHandlerFunc handler; gpointer user_data; }; GType gibber_transport_get_type (void); /* TYPE MACROS */ #define GIBBER_TYPE_TRANSPORT (gibber_transport_get_type ()) #define GIBBER_TRANSPORT(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GIBBER_TYPE_TRANSPORT, GibberTransport)) #define GIBBER_TRANSPORT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GIBBER_TYPE_TRANSPORT, \ GibberTransportClass)) #define GIBBER_IS_TRANSPORT(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GIBBER_TYPE_TRANSPORT)) #define GIBBER_IS_TRANSPORT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GIBBER_TYPE_TRANSPORT)) #define GIBBER_TRANSPORT_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GIBBER_TYPE_TRANSPORT, \ GibberTransportClass)) /* Utility functions for the classes based on GibberTransport */ void gibber_transport_received_data (GibberTransport *transport, const guint8 *data, gsize length); void gibber_transport_received_data_custom (GibberTransport *transport, GibberBuffer *buffer); void gibber_transport_set_state (GibberTransport *transport, GibberTransportState state); void gibber_transport_emit_error (GibberTransport *transport, GError *error); /* Public api */ GibberTransportState gibber_transport_get_state (GibberTransport *transport); gboolean gibber_transport_send (GibberTransport *transport, const guint8 *data, gsize size, GError **error); void gibber_transport_disconnect (GibberTransport *transport); void gibber_transport_set_handler (GibberTransport *transport, GibberHandlerFunc func, gpointer user_data); gboolean gibber_transport_get_peeraddr (GibberTransport *transport, struct sockaddr_storage *addr, socklen_t *len); gboolean gibber_transport_get_sockaddr (GibberTransport *transport, struct sockaddr_storage *addr, socklen_t *len); gboolean gibber_transport_buffer_is_empty (GibberTransport *transport); void gibber_transport_emit_buffer_empty (GibberTransport *transport); void gibber_transport_block_receiving (GibberTransport *transport, gboolean block); G_END_DECLS #endif /* #ifndef __GIBBER_TRANSPORT_H__*/ ��������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/gibber/gibber-listener.c������������������������������������������������0000664�0001750�0001750�00000032265�11711756652�023442� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gibber-listener.c - Source for GibberListener * Copyright (C) 2007,2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <config.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <sys/types.h> #include <errno.h> #include <stdio.h> #include "gibber-sockets.h" #ifdef HAVE_UNISTD_H # include <unistd.h> #endif #include <glib.h> #include "gibber-listener.h" #include "gibber-fd-transport.h" #include "gibber-unix-transport.h" #include "gibber-util.h" #define DEBUG_FLAG DEBUG_NET #include "gibber-debug.h" #include "gibber-signals-marshal.h" G_DEFINE_TYPE (GibberListener, gibber_listener, \ G_TYPE_OBJECT); /* signals */ enum { NEW_CONNECTION, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; typedef struct { GIOChannel *listener; guint io_watch_in; } Listener; typedef struct _GibberListenerPrivate GibberListenerPrivate; struct _GibberListenerPrivate { GSList *listeners; /* Don't allow to listen again if it is already listening */ gboolean listening; int port; gboolean dispose_has_run; }; #define GIBBER_LISTENER_GET_PRIVATE(obj) \ ((GibberListenerPrivate *) obj->priv) GQuark gibber_listener_error_quark (void) { static GQuark quark = 0; if (!quark) quark = g_quark_from_static_string ( "gibber_listener_error"); return quark; } static gboolean unimplemented (GError **error) { g_set_error (error, GIBBER_LISTENER_ERROR, GIBBER_LISTENER_ERROR_FAILED, "Unimplemented"); return FALSE; } static void gibber_listener_init (GibberListener *self) { GibberListenerPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GIBBER_TYPE_LISTENER, GibberListenerPrivate); self->priv = priv; priv->dispose_has_run = FALSE; } static void gibber_listeners_clean_listeners (GibberListener *self) { GibberListenerPrivate *priv = GIBBER_LISTENER_GET_PRIVATE (self); GSList *t; for (t = priv->listeners ; t != NULL ; t = g_slist_delete_link (t, t)) { Listener *l = (Listener *) t->data; g_io_channel_unref (l->listener); g_source_remove (l->io_watch_in); g_slice_free (Listener, l); } priv->listeners = NULL; priv->listening = FALSE; priv->port = 0; } static void gibber_listener_dispose (GObject *object) { GibberListener *self = GIBBER_LISTENER (object); gibber_listeners_clean_listeners (self); G_OBJECT_CLASS (gibber_listener_parent_class)->dispose ( object); } static void gibber_listener_class_init ( GibberListenerClass *gibber_listener_class) { GObjectClass *object_class = G_OBJECT_CLASS ( gibber_listener_class); g_type_class_add_private (gibber_listener_class, sizeof (GibberListenerPrivate)); object_class->dispose = gibber_listener_dispose; signals[NEW_CONNECTION] = g_signal_new ( "new-connection", G_OBJECT_CLASS_TYPE (gibber_listener_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, _gibber_signals_marshal_VOID__OBJECT_POINTER_UINT, G_TYPE_NONE, 3, GIBBER_TYPE_TRANSPORT, G_TYPE_POINTER, G_TYPE_UINT); } GibberListener * gibber_listener_new (void) { return g_object_new (GIBBER_TYPE_LISTENER, NULL); } static gboolean listener_io_in_cb (GIOChannel *source, GIOCondition condition, gpointer user_data) { GibberListener *self = GIBBER_LISTENER (user_data); GibberFdTransport *transport; int fd, nfd; int ret; char host[NI_MAXHOST]; char port[NI_MAXSERV]; struct sockaddr_storage addr; socklen_t addrlen = sizeof (struct sockaddr_storage); fd = g_io_channel_unix_get_fd (source); nfd = accept (fd, (struct sockaddr *) &addr, &addrlen); gibber_normalize_address (&addr); #ifdef GIBBER_TYPE_UNIX_TRANSPORT if (addr.ss_family == AF_UNIX) { transport = GIBBER_FD_TRANSPORT (gibber_unix_transport_new_from_fd (nfd)); /* UNIX sockets doesn't have port */ ret = getnameinfo ((struct sockaddr *) &addr, addrlen, host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); port[0] = '\0'; } else #endif { transport = g_object_new (GIBBER_TYPE_FD_TRANSPORT, NULL); gibber_fd_transport_set_fd (transport, nfd, TRUE); ret = getnameinfo ((struct sockaddr *) &addr, addrlen, host, NI_MAXHOST, port, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV); } if (ret == 0) { if (port[0] != '\0') DEBUG ("New connection from %s port %s", host, port); else DEBUG ("New connection from %s", host); } else { DEBUG("New connection..."); } g_signal_emit (self, signals[NEW_CONNECTION], 0, transport, &addr, (guint) addrlen); g_object_unref (transport); return TRUE; } static gboolean add_listener (GibberListener *self, int family, int type, int protocol, struct sockaddr *address, socklen_t addrlen, GError **error) { #define BACKLOG 5 int fd = -1, ret, yes = 1; Listener *l; GibberListenerPrivate *priv = GIBBER_LISTENER_GET_PRIVATE (self); char name [NI_MAXHOST], portname[NI_MAXSERV]; union { struct sockaddr addr; struct sockaddr_in in; struct sockaddr_in6 in6; struct sockaddr_storage storage; } baddress; socklen_t baddrlen = sizeof (baddress); fd = socket (family, type, protocol); if (fd == -1) { gibber_socket_set_error (error, "socket failed", GIBBER_LISTENER_ERROR, gibber_socket_errno_is_eafnosupport () ? GIBBER_LISTENER_ERROR_FAMILY_NOT_SUPPORTED : GIBBER_LISTENER_ERROR_FAILED); goto error; } ret = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (char *) &yes, sizeof (int)); if (ret == -1) { gibber_socket_set_error (error, "setsockopt failed", GIBBER_LISTENER_ERROR, GIBBER_LISTENER_ERROR_FAILED); goto error; } #ifdef IPV6_V6ONLY if (family == AF_INET6) { ret = setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof (int)); if (ret == -1) { gibber_socket_set_error (error, "setsockopt failed", GIBBER_LISTENER_ERROR, GIBBER_LISTENER_ERROR_FAILED); goto error; } } #endif ret = bind (fd, address, addrlen); if (ret < 0) { gibber_socket_set_error (error, "bind failed", GIBBER_LISTENER_ERROR, gibber_socket_errno_is_eaddrinuse () ? GIBBER_LISTENER_ERROR_ADDRESS_IN_USE : GIBBER_LISTENER_ERROR_FAILED); goto error; } ret = listen (fd, BACKLOG); if (ret == -1) { gibber_socket_set_error (error, "listen failed", GIBBER_LISTENER_ERROR, gibber_socket_errno_is_eaddrinuse () ? GIBBER_LISTENER_ERROR_ADDRESS_IN_USE : GIBBER_LISTENER_ERROR_FAILED); goto error; } ret = getsockname (fd, &baddress.addr, &baddrlen); if (ret == -1) { gibber_socket_set_error (error, "getsockname failed", GIBBER_LISTENER_ERROR, GIBBER_LISTENER_ERROR_FAILED); goto error; } getnameinfo (&baddress.addr, baddrlen, name, sizeof (name), portname, sizeof (portname), NI_NUMERICHOST | NI_NUMERICSERV); DEBUG ( "Listening on %s port %s...", name, portname); switch (family) { case AF_INET: priv->port = g_ntohs (baddress.in.sin_port); break; case AF_INET6: priv->port = g_ntohs (baddress.in6.sin6_port); break; default: priv->port = 0; break; } l = g_slice_new (Listener); l->listener = gibber_io_channel_new_from_socket (fd); g_io_channel_set_close_on_unref (l->listener, TRUE); l->io_watch_in = g_io_add_watch (l->listener, G_IO_IN, listener_io_in_cb, self); priv->listeners = g_slist_append (priv->listeners, l); return TRUE; error: if (fd > 0) close (fd); return FALSE; } /* port: if 0, choose a random port */ static gboolean listen_tcp_af (GibberListener *listener, int port, GibberAddressFamily family, gboolean loopback, GError **error) { GibberListenerPrivate *priv = GIBBER_LISTENER_GET_PRIVATE (listener); struct addrinfo req, *ans = NULL, *a; int ret; gchar sport[6]; if (priv->listening) { g_set_error (error, GIBBER_LISTENER_ERROR, GIBBER_LISTENER_ERROR_ALREADY_LISTENING, "GibberListener is already listening"); return FALSE; } memset (&req, 0, sizeof (req)); if (!loopback) req.ai_flags = AI_PASSIVE; switch (family) { case GIBBER_AF_IPV4: req.ai_family = AF_INET; break; case GIBBER_AF_IPV6: req.ai_family = AF_INET6; break; case GIBBER_AF_ANY: req.ai_family = AF_UNSPEC; break; } req.ai_socktype = SOCK_STREAM; req.ai_protocol = IPPROTO_TCP; g_snprintf (sport, 6, "%d", port); ret = getaddrinfo (NULL, sport, &req, &ans); if (ret != 0) { DEBUG ("getaddrinfo failed: %s", gai_strerror (ret)); g_set_error (error, GIBBER_LISTENER_ERROR, GIBBER_LISTENER_ERROR_FAILED, "%s", gai_strerror (ret)); goto error; } priv->port = 0; for (a = ans ; a != NULL ; a = a->ai_next) { union { struct sockaddr *addr; struct sockaddr_storage *storage; struct sockaddr_in *in; struct sockaddr_in6 *in6; } addr; gboolean ret_; GError *terror = NULL; addr.addr = a->ai_addr; /* the caller let us choose a port and we are not in the first round */ if (port == 0 && priv->port != 0) { if (a->ai_family == AF_INET) addr.in->sin_port = g_htons (priv->port); else if (a->ai_family == AF_INET6) addr.in6->sin6_port = g_htons (priv->port); else g_assert_not_reached (); } ret_ = add_listener (listener, a->ai_family, a->ai_socktype, a->ai_protocol, a->ai_addr, a->ai_addrlen, &terror); if (ret_ == FALSE) { gboolean fatal = !g_error_matches (terror, GIBBER_LISTENER_ERROR, GIBBER_LISTENER_ERROR_FAMILY_NOT_SUPPORTED); /* let error always point to the last error */ g_clear_error (error); g_propagate_error (error, terror); if (fatal) goto error; } else { /* add_listener succeeded: don't allow to listen again */ priv->listening = TRUE; } } /* If all listeners failed, report the last error */ if (priv->listeners == NULL) goto error; /* There was an error at some point, but it was not fatal. ignore it */ g_clear_error (error); freeaddrinfo (ans); return TRUE; error: gibber_listeners_clean_listeners (listener); if (ans != NULL) freeaddrinfo (ans); return FALSE; } gboolean gibber_listener_listen_tcp (GibberListener *listener, int port, GError **error) { return gibber_listener_listen_tcp_af (listener, port, GIBBER_AF_ANY, error); } gboolean gibber_listener_listen_tcp_af (GibberListener *listener, int port, GibberAddressFamily family, GError **error) { return listen_tcp_af (listener, port, family, FALSE, error); } gboolean gibber_listener_listen_tcp_loopback (GibberListener *listener, int port, GError **error) { return gibber_listener_listen_tcp_loopback_af (listener, port, GIBBER_AF_ANY, error); } gboolean gibber_listener_listen_tcp_loopback_af (GibberListener *listener, int port, GibberAddressFamily family, GError **error) { return listen_tcp_af (listener, port, family, TRUE, error); } gboolean gibber_listener_listen_socket (GibberListener *listener, gchar *path, gboolean abstract, GError **error) { GibberListenerPrivate *priv = GIBBER_LISTENER_GET_PRIVATE (listener); #ifdef GIBBER_TYPE_UNIX_TRANSPORT struct sockaddr_un addr; int ret; #endif if (priv->listening) { g_set_error (error, GIBBER_LISTENER_ERROR, GIBBER_LISTENER_ERROR_ALREADY_LISTENING, "GibberListener is already listening"); return FALSE; } #ifdef GIBBER_TYPE_UNIX_TRANSPORT if (abstract) return unimplemented (error); memset (&addr, 0, sizeof (addr)); addr.sun_family = PF_UNIX; snprintf (addr.sun_path, sizeof (addr.sun_path) - 1, "%s", path); ret = add_listener (listener, AF_UNIX, SOCK_STREAM, 0, (struct sockaddr *) &addr, sizeof (addr), error); if (ret == TRUE) { /* add_listener succeeded: don't allow to listen again */ priv->listening = TRUE; } return ret; #else /* Unix transport not supported */ return unimplemented (error); #endif /* Unix transport not supported */ } int gibber_listener_get_port (GibberListener *listener) { GibberListenerPrivate *priv = GIBBER_LISTENER_GET_PRIVATE (listener); return priv->port; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/gibber/gibber-util.h����������������������������������������������������0000644�0001750�0001750�00000002161�11423525545�022560� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gibber-util.h - Header for Gibber utility functions * Copyright (C) 2007 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GIBBER_UTIL_H__ #define __GIBBER_UTIL_H__ #include "gibber-sockets.h" #include <glib.h> G_BEGIN_DECLS void gibber_normalize_address (struct sockaddr_storage *addr); gboolean gibber_strdiff (const gchar *left, const gchar *right); G_END_DECLS #endif /* #ifndef __GIBBER_UTIL_H__ */ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/gibber/gibber-fd-transport.c��������������������������������������������0000644�0001750�0001750�00000037261�11622757713�024237� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gibber-fd-transport.c - Source for GibberFdTransport * Copyright (C) 2006-2007 Collabora Ltd. * @author: Sjoerd Simons <sjoerd.simons@collabora.co.uk> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <config.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #ifdef HAVE_UNISTD_H # include <unistd.h> #endif #include "gibber-sockets.h" #include "gibber-fd-transport.h" #define DEBUG_FLAG DEBUG_NET #include "gibber-debug.h" static gboolean _channel_io_out (GIOChannel *source, GIOCondition condition, gpointer data); static gboolean gibber_fd_transport_send (GibberTransport *transport, const guint8 *data, gsize size, GError **error); static void gibber_fd_transport_disconnect (GibberTransport *transport); static gboolean gibber_fd_transport_get_peeraddr (GibberTransport *transport, struct sockaddr_storage *addr, socklen_t *len); static gboolean gibber_fd_transport_get_sockaddr (GibberTransport *transport, struct sockaddr_storage *addr, socklen_t *len); static void _do_disconnect (GibberFdTransport *self); static gboolean gibber_fd_transport_buffer_is_empty ( GibberTransport *transport); static void gibber_fd_transport_block_receiving (GibberTransport *transport, gboolean block); G_DEFINE_TYPE(GibberFdTransport, gibber_fd_transport, GIBBER_TYPE_TRANSPORT) GQuark gibber_fd_transport_error_quark (void) { static GQuark quark = 0; if (!quark) quark = g_quark_from_static_string ("gibber_fd_transport_error"); return quark; } /* private structure */ typedef struct _GibberFdTransportPrivate GibberFdTransportPrivate; struct _GibberFdTransportPrivate { GIOChannel *channel; gboolean dispose_has_run; guint watch_in; guint watch_out; guint watch_err; GString *output_buffer; gboolean receiving_blocked; }; #define GIBBER_FD_TRANSPORT_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), GIBBER_TYPE_FD_TRANSPORT, \ GibberFdTransportPrivate)) static void gibber_fd_transport_init (GibberFdTransport *self) { GibberFdTransportPrivate *priv = GIBBER_FD_TRANSPORT_GET_PRIVATE (self); self->fd = -1; priv->channel = NULL; priv->output_buffer = NULL; priv->watch_in = 0; priv->watch_out = 0; priv->watch_err = 0; } static void gibber_fd_transport_dispose (GObject *object); static void gibber_fd_transport_finalize (GObject *object); static GibberFdIOResult gibber_fd_transport_write ( GibberFdTransport *fd_transport, GIOChannel *channel, const guint8 *data, int len, gsize *written, GError **error); static void gibber_fd_transport_class_init ( GibberFdTransportClass *gibber_fd_transport_class) { GObjectClass *object_class = G_OBJECT_CLASS (gibber_fd_transport_class); GibberTransportClass *transport_class = GIBBER_TRANSPORT_CLASS (gibber_fd_transport_class); g_type_class_add_private (gibber_fd_transport_class, sizeof (GibberFdTransportPrivate)); object_class->dispose = gibber_fd_transport_dispose; object_class->finalize = gibber_fd_transport_finalize; transport_class->send = gibber_fd_transport_send; transport_class->disconnect = gibber_fd_transport_disconnect; transport_class->get_peeraddr = gibber_fd_transport_get_peeraddr; transport_class->get_sockaddr = gibber_fd_transport_get_sockaddr; transport_class->buffer_is_empty = gibber_fd_transport_buffer_is_empty; transport_class->block_receiving = gibber_fd_transport_block_receiving; gibber_fd_transport_class->read = gibber_fd_transport_read; gibber_fd_transport_class->write = gibber_fd_transport_write; } void gibber_fd_transport_dispose (GObject *object) { GibberFdTransport *self = GIBBER_FD_TRANSPORT (object); GibberFdTransportPrivate *priv = GIBBER_FD_TRANSPORT_GET_PRIVATE (self); if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; _do_disconnect (self); if (G_OBJECT_CLASS (gibber_fd_transport_parent_class)->dispose) G_OBJECT_CLASS (gibber_fd_transport_parent_class)->dispose (object); } void gibber_fd_transport_finalize (GObject *object) { G_OBJECT_CLASS (gibber_fd_transport_parent_class)->finalize (object); } static void _do_disconnect (GibberFdTransport *self) { GibberFdTransportPrivate *priv = GIBBER_FD_TRANSPORT_GET_PRIVATE (self); if (GIBBER_TRANSPORT(self)->state == GIBBER_TRANSPORT_DISCONNECTED) { return; } DEBUG ("Closing the fd transport"); if (priv->channel != NULL) { if (priv->watch_in != 0) g_source_remove (priv->watch_in); if (priv->watch_out) g_source_remove (priv->watch_out); if (priv->watch_err) g_source_remove (priv->watch_err); g_io_channel_shutdown (priv->channel, FALSE, NULL); g_io_channel_unref (priv->channel); priv->channel = NULL; } else { close (self->fd); } self->fd = -1; if (priv->output_buffer) { g_string_free (priv->output_buffer, TRUE); priv->output_buffer = NULL; } if (!priv->dispose_has_run) /* If we are disposing we don't care about the state anymore */ gibber_transport_set_state (GIBBER_TRANSPORT (self), GIBBER_TRANSPORT_DISCONNECTED); } static gboolean _try_write (GibberFdTransport *self, const guint8 *data, int len, gsize *written, GError **err) { GibberFdTransportPrivate *priv = GIBBER_FD_TRANSPORT_GET_PRIVATE (self); GibberFdTransportClass *cls = GIBBER_FD_TRANSPORT_GET_CLASS (self); GibberFdIOResult result; GError *error = NULL; result = cls->write (self, priv->channel, data, len, written, &error); switch (result) { case GIBBER_FD_IO_RESULT_SUCCESS: case GIBBER_FD_IO_RESULT_AGAIN: break; case GIBBER_FD_IO_RESULT_ERROR: gibber_transport_emit_error (GIBBER_TRANSPORT (self), error); /* fallthrough */ case GIBBER_FD_IO_RESULT_EOF: DEBUG ("Writing data failed, closing the transport"); _do_disconnect (self); g_propagate_error (err, error); return FALSE; break; } return TRUE; } static gboolean _writeout (GibberFdTransport *self, const guint8 *data, gsize len, GError **error) { GibberFdTransportPrivate *priv = GIBBER_FD_TRANSPORT_GET_PRIVATE (self); gsize written = 0; DEBUG ("Writing out %" G_GSIZE_FORMAT " bytes", len); if (priv->output_buffer == NULL || priv->output_buffer->len == 0) { /* We've got nothing buffer yet so try to write out directly */ if (!_try_write (self, data, len, &written, error)) { return FALSE; } } if (written == len) { gibber_transport_emit_buffer_empty (GIBBER_TRANSPORT (self)); return TRUE; } if (priv->output_buffer) { g_string_append_len (priv->output_buffer, (gchar *) data + written, len - written); } else { priv->output_buffer = g_string_new_len ((gchar *) data + written, len - written); } if (!priv->watch_out) { priv->watch_out = g_io_add_watch (priv->channel, G_IO_OUT, _channel_io_out, self); } return TRUE; } static gboolean _channel_io_in (GIOChannel *source, GIOCondition condition, gpointer data) { GibberFdTransport *self = GIBBER_FD_TRANSPORT (data); GibberFdTransportPrivate *priv = GIBBER_FD_TRANSPORT_GET_PRIVATE (self); GibberFdIOResult result; GError *error = NULL; GibberFdTransportClass *cls = GIBBER_FD_TRANSPORT_GET_CLASS(self); result = cls->read (self, priv->channel, &error); switch (result) { case GIBBER_FD_IO_RESULT_SUCCESS: case GIBBER_FD_IO_RESULT_AGAIN: break; case GIBBER_FD_IO_RESULT_ERROR: gibber_transport_emit_error (GIBBER_TRANSPORT(self), error); /* Deliberately falling through */ case GIBBER_FD_IO_RESULT_EOF: DEBUG("Failed to read from the transport, closing.."); _do_disconnect (self); return FALSE; } return TRUE; } static gboolean _channel_io_out (GIOChannel *source, GIOCondition condition, gpointer data) { GibberFdTransport *self = GIBBER_FD_TRANSPORT (data); GibberFdTransportPrivate *priv = GIBBER_FD_TRANSPORT_GET_PRIVATE (self); gsize written; g_assert (priv->output_buffer); if (!_try_write (self, (guint8 *) priv->output_buffer->str, priv->output_buffer->len, &written, NULL)) { return FALSE; } if (written > 0 ) { priv->output_buffer = g_string_erase (priv->output_buffer, 0, written); } if (priv->output_buffer->len == 0) { priv->watch_out = 0; gibber_transport_emit_buffer_empty (GIBBER_TRANSPORT (self)); return FALSE; } return TRUE; } static gboolean _channel_io_err (GIOChannel *source, GIOCondition condition, gpointer data) { GibberFdTransport *self = GIBBER_FD_TRANSPORT (data); GError *error = NULL; gint code; const gchar *msg; if (condition & G_IO_ERR) { DEBUG ("Error on GIOChannel.Closing the transport"); /* We can't use g_io_channel_error_from_errno because it seems errno is * not always set when we got a G_IO_ERR. */ code = GIBBER_FD_TRANSPORT_ERROR_FAILED; msg = "Error on GIOChannel"; } else { g_assert_not_reached (); } error = g_error_new_literal (GIBBER_FD_TRANSPORT_ERROR, code, msg); gibber_transport_emit_error (GIBBER_TRANSPORT (self), error); g_error_free (error); _do_disconnect (self); return FALSE; } #ifdef G_OS_WIN32 /* workaround for GLib bug #338943 */ static gboolean _channel_io_in_dispatcher (GIOChannel *source, GIOCondition condition, gpointer data) { if (condition & G_IO_ERR) { return _channel_io_err (source, condition, data); } if (condition == G_IO_IN) { return _channel_io_in (source, condition, data); } g_assert_not_reached (); } #endif /* Default read and write implementations */ static GibberFdIOResult gibber_fd_transport_write (GibberFdTransport *fd_transport, GIOChannel *channel, const guint8 *data, int len, gsize *written, GError **error) { GIOStatus status; status = g_io_channel_write_chars (channel, (gchar *) data, len, written, error); switch (status) { case G_IO_STATUS_NORMAL: return GIBBER_FD_IO_RESULT_SUCCESS; case G_IO_STATUS_AGAIN: return GIBBER_FD_IO_RESULT_AGAIN; case G_IO_STATUS_ERROR: return GIBBER_FD_IO_RESULT_ERROR; case G_IO_STATUS_EOF: return GIBBER_FD_IO_RESULT_EOF; } g_assert_not_reached (); } #define BUFSIZE 1024 GibberFdIOResult gibber_fd_transport_read (GibberFdTransport *transport, GIOChannel *channel, GError **error) { guint8 buf[BUFSIZE + 1]; GIOStatus status; gsize bytes_read; status = g_io_channel_read_chars (channel, (gchar *) buf, BUFSIZE, &bytes_read, error); switch (status) { case G_IO_STATUS_NORMAL: buf[bytes_read] = '\0'; DEBUG ("Received %" G_GSIZE_FORMAT " bytes", bytes_read); gibber_transport_received_data (GIBBER_TRANSPORT (transport), buf, bytes_read); return GIBBER_FD_IO_RESULT_SUCCESS; case G_IO_STATUS_ERROR: return GIBBER_FD_IO_RESULT_ERROR; case G_IO_STATUS_EOF: return GIBBER_FD_IO_RESULT_EOF; case G_IO_STATUS_AGAIN: return GIBBER_FD_IO_RESULT_AGAIN; } g_assert_not_reached (); } void gibber_fd_transport_set_fd (GibberFdTransport *self, int fd, gboolean is_socket) { GibberFdTransportPrivate *priv = GIBBER_FD_TRANSPORT_GET_PRIVATE (self); g_assert (self->fd == -1 && fd >= 0); self->fd = fd; if (is_socket) { gibber_socket_set_nonblocking (fd); priv->channel = gibber_io_channel_new_from_socket (fd); } else { #ifndef G_OS_WIN32 fcntl (fd, F_SETFL, O_NONBLOCK); #endif priv->channel = g_io_channel_unix_new (fd); } g_io_channel_set_close_on_unref (priv->channel, TRUE); g_io_channel_set_encoding (priv->channel, NULL, NULL); g_io_channel_set_buffered (priv->channel, FALSE); #ifdef G_OS_WIN32 /* workaround for GLib bug #338943 */ if (!priv->receiving_blocked) { priv->watch_in = g_io_add_watch (priv->channel, G_IO_IN | G_IO_ERR, _channel_io_in_dispatcher, self); } else { priv->watch_err = g_io_add_watch (priv->channel, G_IO_ERR, _channel_io_err, self); } #else if (!priv->receiving_blocked) { priv->watch_in = g_io_add_watch (priv->channel, G_IO_IN, _channel_io_in, self); } priv->watch_err = g_io_add_watch (priv->channel, G_IO_ERR, _channel_io_err, self); #endif gibber_transport_set_state (GIBBER_TRANSPORT(self), GIBBER_TRANSPORT_CONNECTED); } gboolean gibber_fd_transport_send (GibberTransport *transport, const guint8 *data, gsize size, GError **error) { return _writeout (GIBBER_FD_TRANSPORT (transport), data, size, error); } void gibber_fd_transport_disconnect (GibberTransport *transport) { DEBUG("Connection close requested"); _do_disconnect (GIBBER_FD_TRANSPORT (transport)); } static gboolean gibber_fd_transport_get_peeraddr (GibberTransport *transport, struct sockaddr_storage *addr, socklen_t *len) { GibberFdTransport *self = GIBBER_FD_TRANSPORT (transport); if (self->fd == -1) { DEBUG ("Someone requested the sockaddr while we're not connected"); return FALSE; } *len = sizeof (struct sockaddr_storage); return (getpeername (self->fd, (struct sockaddr *) addr, len) == 0); } static gboolean gibber_fd_transport_get_sockaddr (GibberTransport *transport, struct sockaddr_storage *addr, socklen_t *len) { GibberFdTransport *self = GIBBER_FD_TRANSPORT (transport); if (self->fd == -1) { DEBUG ("Someone requested the sockaddr while we're not connected"); return FALSE; } *len = sizeof (struct sockaddr_storage); return (getsockname (self->fd, (struct sockaddr *) addr, len) == 0); } static gboolean gibber_fd_transport_buffer_is_empty (GibberTransport *transport) { GibberFdTransport *self = GIBBER_FD_TRANSPORT (transport); GibberFdTransportPrivate *priv = GIBBER_FD_TRANSPORT_GET_PRIVATE (self); return (priv->output_buffer == NULL || priv->output_buffer->len == 0); } static void gibber_fd_transport_block_receiving (GibberTransport *transport, gboolean block) { GibberFdTransport *self = GIBBER_FD_TRANSPORT (transport); GibberFdTransportPrivate *priv = GIBBER_FD_TRANSPORT_GET_PRIVATE (self); if (block && priv->watch_in != 0) { DEBUG ("block receiving from the transport"); g_source_remove (priv->watch_in); priv->watch_in = 0; } else if (!block && priv->watch_in == 0) { DEBUG ("unblock receiving from the transport"); if (priv->channel != NULL) { #ifdef G_OS_WIN32 /* workaround for GLib bug #338943 */ if (priv->watch_err) { g_source_remove (priv->watch_err); priv->watch_err = 0; } priv->watch_in = g_io_add_watch (priv->channel, G_IO_IN | G_IO_ERR, _channel_io_in_dispatcher, self); #else priv->watch_in = g_io_add_watch (priv->channel, G_IO_IN, _channel_io_in, self); #endif } /* else the transport isn't connected yet */ } priv->receiving_blocked = block; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/gibber/gibber-fd-transport.h��������������������������������������������0000644�0001750�0001750�00000006023�11423525545�024227� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gibber-fd-transport.h - Header for GibberFdTransport * Copyright (C) 2006 Collabora Ltd. * @author: Sjoerd Simons <sjoerd@luon.net> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GIBBER_FD_TRANSPORT_H__ #define __GIBBER_FD_TRANSPORT_H__ #include <glib-object.h> #include "gibber-sockets.h" #include "gibber-transport.h" typedef enum { GIBBER_FD_IO_RESULT_SUCCESS, GIBBER_FD_IO_RESULT_AGAIN, GIBBER_FD_IO_RESULT_ERROR, GIBBER_FD_IO_RESULT_EOF, } GibberFdIOResult; G_BEGIN_DECLS GQuark gibber_fd_transport_error_quark (void); #define GIBBER_FD_TRANSPORT_ERROR gibber_fd_transport_error_quark() typedef enum { GIBBER_FD_TRANSPORT_ERROR_PIPE, GIBBER_FD_TRANSPORT_ERROR_FAILED, } GibberFdTransportError; typedef struct _GibberFdTransport GibberFdTransport; typedef struct _GibberFdTransportClass GibberFdTransportClass; struct _GibberFdTransportClass { GibberTransportClass parent_class; /* Called when fd is ready for reading */ GibberFdIOResult (*read) (GibberFdTransport *fd_transport, GIOChannel *channel, GError **error); /* Called when something needs to be written*/ GibberFdIOResult (*write) (GibberFdTransport *fd_transport, GIOChannel *channel, const guint8 *data, int len, gsize *written, GError **error); }; struct _GibberFdTransport { GibberTransport parent; int fd; }; GType gibber_fd_transport_get_type (void); /* TYPE MACROS */ #define GIBBER_TYPE_FD_TRANSPORT \ (gibber_fd_transport_get_type ()) #define GIBBER_FD_TRANSPORT(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GIBBER_TYPE_FD_TRANSPORT, \ GibberFdTransport)) #define GIBBER_FD_TRANSPORT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GIBBER_TYPE_FD_TRANSPORT, \ GibberFdTransportClass)) #define GIBBER_IS_FD_TRANSPORT(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GIBBER_TYPE_FD_TRANSPORT)) #define GIBBER_IS_FD_TRANSPORT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GIBBER_TYPE_FD_TRANSPORT)) #define GIBBER_FD_TRANSPORT_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GIBBER_TYPE_FD_TRANSPORT, \ GibberFdTransportClass)) void gibber_fd_transport_set_fd (GibberFdTransport *fd_transport, int fd, gboolean is_socket); GibberFdIOResult gibber_fd_transport_read (GibberFdTransport *transport, GIOChannel *channel, GError **error); G_END_DECLS #endif /* #ifndef __GIBBER_FD_TRANSPORT_H__*/ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/gibber/gibber-tcp-transport.c�������������������������������������������0000644�0001750�0001750�00000017727�11622757713�024441� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gibber-tcp-transport.c - Source for GibberTCPTransport * Copyright (C) 2006 Collabora Ltd. * @author Sjoerd Simons <sjoerd@luon.net> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <config.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #ifdef HAVE_UNISTD_H # include <unistd.h> #endif #include "gibber-sockets.h" #include "gibber-tcp-transport.h" #define DEBUG_FLAG DEBUG_NET #include "gibber-debug.h" #include <gio/gio.h> #include "errno.h" G_DEFINE_TYPE(GibberTCPTransport, gibber_tcp_transport, GIBBER_TYPE_FD_TRANSPORT) /* private structure */ typedef struct _GibberTCPTransportPrivate GibberTCPTransportPrivate; struct _GibberTCPTransportPrivate { GIOChannel *channel; GList *addresses; guint16 port; guint watch_in; gboolean dispose_has_run; }; #define GIBBER_TCP_TRANSPORT_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), GIBBER_TYPE_TCP_TRANSPORT, \ GibberTCPTransportPrivate)) static void gibber_tcp_transport_init (GibberTCPTransport *obj) { /* GibberTCPTransportPrivate *priv = GIBBER_TCP_TRANSPORT_GET_PRIVATE (obj); */ /* allocate any data required by the object here */ } static void gibber_tcp_transport_dispose (GObject *object); static void gibber_tcp_transport_finalize (GObject *object); static void gibber_tcp_transport_class_init ( GibberTCPTransportClass *gibber_tcp_transport_class) { GObjectClass *object_class = G_OBJECT_CLASS (gibber_tcp_transport_class); g_type_class_add_private (gibber_tcp_transport_class, sizeof (GibberTCPTransportPrivate)); object_class->dispose = gibber_tcp_transport_dispose; object_class->finalize = gibber_tcp_transport_finalize; } static void clean_connect_attempt (GibberTCPTransport *self) { GibberTCPTransportPrivate *priv = GIBBER_TCP_TRANSPORT_GET_PRIVATE ( self); if (priv->watch_in != 0) { g_source_remove (priv->watch_in); priv->watch_in = 0; } if (priv->channel != NULL) { g_io_channel_unref (priv->channel); priv->channel = NULL; } } static void clean_all_connect_attempts (GibberTCPTransport *self) { GibberTCPTransportPrivate *priv = GIBBER_TCP_TRANSPORT_GET_PRIVATE ( self); clean_connect_attempt (self); g_resolver_free_addresses (priv->addresses); priv->addresses = NULL; } void gibber_tcp_transport_dispose (GObject *object) { GibberTCPTransport *self = GIBBER_TCP_TRANSPORT (object); GibberTCPTransportPrivate *priv = GIBBER_TCP_TRANSPORT_GET_PRIVATE (self); if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; clean_all_connect_attempts (self); /* release any references held by the object here */ if (G_OBJECT_CLASS (gibber_tcp_transport_parent_class)->dispose) G_OBJECT_CLASS (gibber_tcp_transport_parent_class)->dispose (object); } void gibber_tcp_transport_finalize (GObject *object) { /* GibberTCPTransport *self = GIBBER_TCP_TRANSPORT (object); GibberTCPTransportPrivate *priv = GIBBER_TCP_TRANSPORT_GET_PRIVATE (self); */ /* free any data held directly by the object here */ G_OBJECT_CLASS (gibber_tcp_transport_parent_class)->finalize (object); } GibberTCPTransport * gibber_tcp_transport_new () { return g_object_new (GIBBER_TYPE_TCP_TRANSPORT, NULL); } static void new_connect_attempt (GibberTCPTransport *self); static gboolean try_to_connect (GibberTCPTransport *self) { GibberTCPTransportPrivate *priv = GIBBER_TCP_TRANSPORT_GET_PRIVATE ( self); GSocketAddress *gaddr; struct sockaddr_storage addr; gssize native_size; gint fd; int ret; int err; gboolean connected = FALSE; g_assert (priv->channel != NULL); fd = g_io_channel_unix_get_fd (priv->channel); gaddr = g_inet_socket_address_new (G_INET_ADDRESS (priv->addresses->data), priv->port); native_size = g_socket_address_get_native_size (gaddr); /* _get_native_size() really shouldn't fail... */ g_return_val_if_fail (native_size > 0, FALSE); /* ...and if sockaddr_storage isn't big enough, we're basically screwed. */ g_return_val_if_fail ((gsize) native_size <= sizeof (addr), FALSE); g_socket_address_to_native (gaddr, &addr, sizeof (addr), NULL); ret = connect (fd, (struct sockaddr *)&addr, (gsize) native_size); #ifdef G_OS_WIN32 err = WSAGetLastError (); connected = (ret == 0 || err == WSAEISCONN); #else err = errno; connected = (ret == 0); #endif g_object_unref (gaddr); if (connected) { DEBUG ("connect succeeded"); clean_all_connect_attempts (self); gibber_fd_transport_set_fd (GIBBER_FD_TRANSPORT (self), fd, TRUE); return FALSE; } if (gibber_connect_errno_requires_retry (err)) { /* We have to wait longer */ return TRUE; } clean_connect_attempt (self); g_object_unref (priv->addresses->data); priv->addresses = g_list_remove_link (priv->addresses, priv->addresses); new_connect_attempt (self); return FALSE; } static gboolean _channel_io (GIOChannel *source, GIOCondition condition, gpointer data) { GibberTCPTransport *self = GIBBER_TCP_TRANSPORT (data); return try_to_connect (self); } static void new_connect_attempt (GibberTCPTransport *self) { GibberTCPTransportPrivate *priv = GIBBER_TCP_TRANSPORT_GET_PRIVATE ( self); int fd; GSocketAddress *gaddr; gchar *tmpstr; if (priv->addresses == NULL) { /* no more candidate to try */ DEBUG ("connection failed"); goto failed; } tmpstr = g_inet_address_to_string (G_INET_ADDRESS (priv->addresses->data)); DEBUG ("Trying %s port %d...", tmpstr, priv->port); g_free (tmpstr); gaddr = g_inet_socket_address_new (G_INET_ADDRESS (priv->addresses->data), priv->port); fd = socket (g_socket_address_get_family (gaddr), SOCK_STREAM, IPPROTO_TCP); g_object_unref (gaddr); if (fd < 0) { DEBUG("socket failed: #%d %s", gibber_socket_errno (), gibber_socket_strerror ()); goto failed; } gibber_socket_set_nonblocking (fd); priv->channel = gibber_io_channel_new_from_socket (fd); g_io_channel_set_close_on_unref (priv->channel, FALSE); g_io_channel_set_encoding (priv->channel, NULL, NULL); g_io_channel_set_buffered (priv->channel, FALSE); priv->watch_in = g_io_add_watch (priv->channel, G_IO_IN | G_IO_PRI | G_IO_OUT, _channel_io, self); try_to_connect (self); return; failed: clean_all_connect_attempts (self); gibber_transport_set_state (GIBBER_TRANSPORT (self), GIBBER_TRANSPORT_DISCONNECTED); } void gibber_tcp_transport_connect (GibberTCPTransport *tcp_transport, const gchar *host, guint16 port) { GibberTCPTransportPrivate *priv = GIBBER_TCP_TRANSPORT_GET_PRIVATE ( tcp_transport); GResolver *resolver = g_resolver_get_default (); GError *error = NULL; gibber_transport_set_state (GIBBER_TRANSPORT (tcp_transport), GIBBER_TRANSPORT_CONNECTING); priv->port = port; g_assert (priv->addresses == NULL); g_assert (priv->channel == NULL); priv->addresses = g_resolver_lookup_by_name (resolver, host, NULL, &error); if (priv->addresses == NULL) { DEBUG("Address lookup failed: %s", error->message); gibber_transport_set_state (GIBBER_TRANSPORT (tcp_transport), GIBBER_TRANSPORT_DISCONNECTED); g_error_free (error); goto out; } new_connect_attempt (tcp_transport); out: g_object_unref (resolver); } �����������������������������������������telepathy-gabble-0.18.3/lib/gibber/gibber-sockets.h�������������������������������������������������0000644�0001750�0001750�00000003003�11622757713�023257� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gibber-sockets.h - meta-header for assorted semi-portable socket code * Copyright (C) 2009 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <config.h> #ifndef GIBBER_SOCKETS_H #define GIBBER_SOCKETS_H #include <glib.h> #ifdef G_OS_WIN32 # include "gibber-sockets-win32.h" #else # include "gibber-sockets-unix.h" #endif G_BEGIN_DECLS gboolean gibber_connect_errno_requires_retry (int err); gboolean gibber_socket_errno_is_eafnosupport (void); gboolean gibber_socket_errno_is_eaddrinuse (void); void gibber_socket_set_error (GError **error, const gchar *context, GQuark domain, gint code); gint gibber_socket_errno (void); const gchar *gibber_socket_strerror (void); GIOChannel *gibber_io_channel_new_from_socket (gint sockfd); void gibber_socket_set_nonblocking (gint sockfd); G_END_DECLS #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/gibber/gibber-debug.c���������������������������������������������������0000664�0001750�0001750�00000004440�12332441362�022662� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "config.h" #include <stdarg.h> #include <glib.h> #include "gibber-debug.h" #ifdef ENABLE_DEBUG static DebugFlags flags = 0; static gboolean initialized = FALSE; static GDebugKey keys[] = { { "transport", DEBUG_TRANSPORT }, { "net", DEBUG_NET }, { "xmpp", DEBUG_XMPP }, { "xmpp-reader", DEBUG_XMPP_READER }, { "xmpp-writer", DEBUG_XMPP_WRITER }, { "sasl", DEBUG_SASL }, { "ssl", DEBUG_SSL }, { "rmulticast", DEBUG_RMULTICAST }, { "rmulticast-sender", DEBUG_RMULTICAST_SENDER }, { "muc-connection", DEBUG_MUC_CONNECTION }, { "bytestream", DEBUG_BYTESTREAM }, { "ft", DEBUG_FILE_TRANSFER }, { "all", ~0 }, { 0, }, }; void gibber_debug_set_flags_from_env () { guint nkeys; const gchar *flags_string; for (nkeys = 0; keys[nkeys].value; nkeys++); flags_string = g_getenv ("GIBBER_DEBUG"); if (flags_string) gibber_debug_set_flags (g_parse_debug_string (flags_string, keys, nkeys)); initialized = TRUE; } void gibber_debug_set_flags (DebugFlags new_flags) { flags |= new_flags; initialized = TRUE; } gboolean gibber_debug_flag_is_set (DebugFlags flag) { return flag & flags; } void gibber_debug (DebugFlags flag, const gchar *format, ...) { if (G_UNLIKELY(!initialized)) gibber_debug_set_flags_from_env (); if (flag & flags) { va_list args; va_start (args, format); g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format, args); va_end (args); } } #if 0 void gibber_debug_stanza (DebugFlags flag, GibberXmppStanza *stanza, const gchar *format, ...) { if (G_UNLIKELY(!initialized)) gibber_debug_set_flags_from_env (); if (flag & flags) { va_list args; gchar *msg, *node_str; va_start (args, format); msg = g_strdup_vprintf (format, args); va_end (args); node_str = gibber_xmpp_node_to_string (stanza->node); g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "%s\n%s", msg, node_str); g_free (msg); g_free (node_str); } } #endif #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/gibber/gibber-transport.c�����������������������������������������������0000664�0001750�0001750�00000020073�12223562023�023625� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gibber-transport.c - Source for GibberTransport * Copyright (C) 2006 Collabora Ltd. * @author Sjoerd Simons <sjoerd@luon.net> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include <stdio.h> #include <stdlib.h> #include "gibber-transport.h" #include "gibber-signals-marshal.h" #define DEBUG_FLAG DEBUG_TRANSPORT #include "gibber-debug.h" G_DEFINE_TYPE(GibberTransport, gibber_transport, G_TYPE_OBJECT) /* signal enum */ enum { CONNECTED, CONNECTING, DISCONNECTED, DISCONNECTING, ERROR, BUFFER_EMPTY, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; /* private structure */ typedef struct _GibberTransportPrivate GibberTransportPrivate; struct _GibberTransportPrivate { gboolean dispose_has_run; }; #define GIBBER_TRANSPORT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GIBBER_TYPE_TRANSPORT, GibberTransportPrivate)) static void gibber_transport_init (GibberTransport *obj) { obj->state = GIBBER_TRANSPORT_DISCONNECTED; obj->handler = NULL; } static void gibber_transport_dispose (GObject *object); static void gibber_transport_finalize (GObject *object); static void gibber_transport_class_init (GibberTransportClass *gibber_transport_class) { GObjectClass *object_class = G_OBJECT_CLASS (gibber_transport_class); g_type_class_add_private (gibber_transport_class, sizeof (GibberTransportPrivate)); object_class->dispose = gibber_transport_dispose; object_class->finalize = gibber_transport_finalize; signals[BUFFER_EMPTY] = g_signal_new ("buffer-empty", G_OBJECT_CLASS_TYPE (gibber_transport_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[CONNECTED] = g_signal_new ("connected", G_OBJECT_CLASS_TYPE (gibber_transport_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[CONNECTING] = g_signal_new ("connecting", G_OBJECT_CLASS_TYPE (gibber_transport_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[DISCONNECTING] = g_signal_new ("disconnecting", G_OBJECT_CLASS_TYPE (gibber_transport_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[DISCONNECTED] = g_signal_new ("disconnected", G_OBJECT_CLASS_TYPE (gibber_transport_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[ERROR] = g_signal_new ("error", G_OBJECT_CLASS_TYPE (gibber_transport_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, _gibber_signals_marshal_VOID__UINT_INT_STRING, G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_INT, G_TYPE_STRING); } void gibber_transport_dispose (GObject *object) { GibberTransport *self = GIBBER_TRANSPORT (object); GibberTransportPrivate *priv = GIBBER_TRANSPORT_GET_PRIVATE (self); if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; /* release any references held by the object here */ if (G_OBJECT_CLASS (gibber_transport_parent_class)->dispose) G_OBJECT_CLASS (gibber_transport_parent_class)->dispose (object); } void gibber_transport_finalize (GObject *object) { G_OBJECT_CLASS (gibber_transport_parent_class)->finalize (object); } void gibber_transport_received_data (GibberTransport *transport, const guint8 *data, gsize length) { GibberBuffer buffer; buffer.length = length; buffer.data = data; gibber_transport_received_data_custom (transport, &buffer); } void gibber_transport_received_data_custom (GibberTransport *transport, GibberBuffer *buffer) { if (G_UNLIKELY (transport->handler == NULL)) { DEBUG("No handler for transport, dropping data!"); } else { transport->handler (transport, buffer, transport->user_data); } } void gibber_transport_set_state (GibberTransport *transport, GibberTransportState state) { if (state != transport->state) { transport->state = state; switch (state) { case GIBBER_TRANSPORT_DISCONNECTED: g_signal_emit (transport, signals[DISCONNECTED], 0); break; case GIBBER_TRANSPORT_CONNECTING: g_signal_emit (transport, signals[CONNECTING], 0); break; case GIBBER_TRANSPORT_CONNECTED: g_signal_emit (transport, signals[CONNECTED], 0); break; case GIBBER_TRANSPORT_DISCONNECTING: g_signal_emit (transport, signals[DISCONNECTING], 0); break; } } } GibberTransportState gibber_transport_get_state (GibberTransport *transport) { return transport->state; } void gibber_transport_emit_error (GibberTransport *transport, GError *error) { DEBUG ("Transport error: %s", error->message); g_signal_emit (transport, signals[ERROR], 0, error->domain, error->code, error->message); } gboolean gibber_transport_send (GibberTransport *transport, const guint8 *data, gsize size, GError **error) { GibberTransportClass *cls = GIBBER_TRANSPORT_GET_CLASS (transport); g_assert (transport->state == GIBBER_TRANSPORT_CONNECTED); return cls->send (transport, data, size, error); } void gibber_transport_disconnect (GibberTransport *transport) { GibberTransportClass *cls = GIBBER_TRANSPORT_GET_CLASS (transport); return cls->disconnect (transport); } void gibber_transport_set_handler (GibberTransport *transport, GibberHandlerFunc func, gpointer user_data) { g_assert (transport->handler == NULL || func == NULL); transport->handler = func; transport->user_data = user_data; } gboolean gibber_transport_get_peeraddr (GibberTransport *transport, struct sockaddr_storage *addr, socklen_t *len) { GibberTransportClass *cls = GIBBER_TRANSPORT_GET_CLASS (transport); if (cls->get_peeraddr != NULL) return cls->get_peeraddr (transport, addr, len); return FALSE; } gboolean gibber_transport_get_sockaddr (GibberTransport *transport, struct sockaddr_storage *addr, socklen_t *len) { GibberTransportClass *cls = GIBBER_TRANSPORT_GET_CLASS (transport); if (cls->get_sockaddr != NULL) return cls->get_sockaddr (transport, addr, len); return FALSE; } gboolean gibber_transport_buffer_is_empty (GibberTransport *transport) { GibberTransportClass *cls = GIBBER_TRANSPORT_GET_CLASS (transport); g_assert (cls->buffer_is_empty != NULL); return cls->buffer_is_empty (transport); } void gibber_transport_emit_buffer_empty (GibberTransport *transport) { g_signal_emit (transport, signals[BUFFER_EMPTY], 0); } void gibber_transport_block_receiving (GibberTransport *transport, gboolean block) { GibberTransportClass *cls = GIBBER_TRANSPORT_GET_CLASS (transport); g_assert (cls->block_receiving != NULL); cls->block_receiving (transport, block); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/gibber/gibber-listener.h������������������������������������������������0000644�0001750�0001750�00000005755�11203243435�023433� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gibber-listener.h - Header for GibberListener * Copyright (C) 2007, 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _GIBBER_LISTENER_H_ #define _GIBBER_LISTENER_H_ #include <glib-object.h> G_BEGIN_DECLS GQuark gibber_listener_error_quark (void); #define GIBBER_LISTENER_ERROR \ gibber_listener_error_quark () typedef enum { GIBBER_LISTENER_ERROR_ALREADY_LISTENING, GIBBER_LISTENER_ERROR_ADDRESS_IN_USE, GIBBER_LISTENER_ERROR_FAMILY_NOT_SUPPORTED, GIBBER_LISTENER_ERROR_FAILED, } GibberListenerError; typedef enum { GIBBER_AF_IPV4, GIBBER_AF_IPV6, GIBBER_AF_ANY } GibberAddressFamily; typedef struct _GibberListener GibberListener; typedef struct _GibberListenerClass GibberListenerClass; struct _GibberListenerClass { GObjectClass parent_class; }; struct _GibberListener { GObject parent; gpointer priv; }; GType gibber_listener_get_type (void); /* TYPE MACROS */ #define GIBBER_TYPE_LISTENER \ (gibber_listener_get_type ()) #define GIBBER_LISTENER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GIBBER_TYPE_LISTENER,\ GibberListener)) #define GIBBER_LISTENER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GIBBER_TYPE_LISTENER,\ GibberListenerClass)) #define GIBBER_IS_LISTENER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GIBBER_TYPE_LISTENER)) #define GIBBER_IS_LISTENER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GIBBER_TYPE_LISTENER)) #define GIBBER_LISTENER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GIBBER_TYPE_LISTENER,\ GibberListenerClass)) GibberListener *gibber_listener_new (void); gboolean gibber_listener_listen_tcp (GibberListener *listener, int port, GError **error); gboolean gibber_listener_listen_tcp_af (GibberListener *listener, int port, GibberAddressFamily family, GError **error); gboolean gibber_listener_listen_tcp_loopback (GibberListener *listener, int port, GError **error); gboolean gibber_listener_listen_tcp_loopback_af (GibberListener *listener, int port, GibberAddressFamily family, GError **error); gboolean gibber_listener_listen_socket (GibberListener *listener, gchar *path, gboolean abstract, GError **error); int gibber_listener_get_port (GibberListener *listener); G_END_DECLS #endif /* #ifndef _GIBBER_LISTENER_H_ */ �������������������telepathy-gabble-0.18.3/lib/gibber/gibber-util.c����������������������������������������������������0000644�0001750�0001750�00000004240�11570651565�022560� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gibber-util.c - Code for Gibber utility functions * Copyright (C) 2007 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <config.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef HAVE_UNISTD_H # include <unistd.h> #endif #include "gibber-util.h" void gibber_normalize_address (struct sockaddr_storage *addr) { struct sockaddr_in *s4 = (struct sockaddr_in *) addr; struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) addr; if (s6->sin6_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED (&(s6->sin6_addr))) { /* Normalize to ipv4 address */ guint32 addr_big_endian; guint16 port; memcpy (&addr_big_endian, s6->sin6_addr.s6_addr + 12, 4); port = s6->sin6_port; s4->sin_family = AF_INET; s4->sin_addr.s_addr = addr_big_endian; s4->sin_port = port; } } /** * gibber_strdiff: * @left: The first string to compare (may be NULL) * @right: The second string to compare (may be NULL) * * Return %TRUE if the given strings are different. Unlike #strcmp this * function will handle null pointers, treating them as distinct from any * string. * * Returns: %FALSE if @left and @right are both %NULL, or if * neither is %NULL and both have the same contents; %TRUE otherwise */ gboolean gibber_strdiff (const gchar *left, const gchar *right) { if ((NULL == left) != (NULL == right)) return TRUE; else if (left == right) return FALSE; else return (0 != strcmp (left, right)); } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/gibber/gibber-sockets-unix.h��������������������������������������������0000644�0001750�0001750�00000003552�11423525545�024244� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* To be included by gibber-sockets.h only. * Do not include this header directly. */ /* * gibber-sockets-unix.h - meta-header for assorted semi-portable socket code * Copyright (C) 2009 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <config.h> /* prerequisite for stdlib.h on Darwin etc., according to autoconf.info */ #include <stdio.h> /* prerequisite for sys/socket.h on Darwin, according to autoconf.info */ #include <stdlib.h> /* prerequisite for all sorts of things */ #include <sys/types.h> #ifdef HAVE_ARPA_INET_H # include <arpa/inet.h> #endif #ifdef HAVE_ARPA_NAMESER_H # include <arpa/nameser.h> #endif #ifdef HAVE_FCNTL_H # include <fcntl.h> #endif #ifdef HAVE_NETDB_H # include <netdb.h> #endif #ifdef HAVE_NETINET_IN_H # include <netinet/in.h> #endif #ifdef HAVE_RESOLV_H /* autoconf.info recommends putting sys/types.h, netinet/in.h, * arpa/nameser.h, netdb.h before this one; if you re-order this header, * please keep that true */ # include <resolv.h> #endif #ifdef HAVE_SYS_IOCTL_H # include <sys/ioctl.h> #endif #ifdef HAVE_SYS_UN_H # include <sys/un.h> #endif #ifdef HAVE_SYS_SOCKET_H # include <sys/socket.h> #endif ������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/gibber/gibber-sockets-win32.h�������������������������������������������0000664�0001750�0001750�00000002154�11711756652�024227� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* To be included by gibber-sockets.h only. * Do not include this header directly. */ /* * gibber-sockets-win32.h - meta-header for assorted semi-portable socket code * Copyright (C) 2009 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <winsock2.h> #include <ws2tcpip.h> #include <windows.h> #include <winbase.h> /* Winsock makes some inappropriately-namespaced definitions */ #undef ERROR #undef interface ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/gibber/gibber-sockets.c�������������������������������������������������0000644�0001750�0001750�00000004751�11622757713�023265� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gibber-sockets.c - basic portability wrappers for BSD/Winsock differences * * Copyright (C) 2009 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <config.h> #include "gibber-sockets.h" #include <errno.h> #define DEBUG_FLAG DEBUG_NET #include "gibber-debug.h" gboolean gibber_connect_errno_requires_retry (int err) { #ifdef G_OS_WIN32 return (err == WSAEINPROGRESS || err == WSAEALREADY || err == WSAEWOULDBLOCK || err == WSAEINVAL); #else return (err == EINPROGRESS || err == EALREADY); #endif } gint gibber_socket_errno (void) { #ifdef G_OS_WIN32 return WSAGetLastError (); #else return errno; #endif } const gchar * gibber_socket_strerror (void) { #ifdef G_OS_WIN32 return "[no strerror() in winsock :-(]"; #else return g_strerror (errno); #endif } gboolean gibber_socket_errno_is_eafnosupport (void) { #ifdef G_OS_WIN32 return (WSAGetLastError () == WSAEAFNOSUPPORT); #else return (errno == EAFNOSUPPORT); #endif } gboolean gibber_socket_errno_is_eaddrinuse (void) { #ifdef G_OS_WIN32 return (WSAGetLastError () == WSAEADDRINUSE); #else return (errno == EADDRINUSE); #endif } void gibber_socket_set_error (GError **error, const gchar *context, GQuark domain, gint code) { gint err = gibber_socket_errno (); const gchar *str = gibber_socket_strerror (); DEBUG ("%s: #%d %s", context, err, str); g_set_error (error, domain, code, "%s: #%d %s", context, err, str); } GIOChannel * gibber_io_channel_new_from_socket (gint sockfd) { #ifdef G_OS_WIN32 return g_io_channel_win32_new_socket (sockfd); #else return g_io_channel_unix_new (sockfd); #endif } void gibber_socket_set_nonblocking (gint sockfd) { #ifdef G_OS_WIN32 u_long please_dont_block = 1; ioctlsocket (sockfd, FIONBIO, &please_dont_block); #else fcntl (sockfd, F_SETFL, O_NONBLOCK); #endif } �����������������������telepathy-gabble-0.18.3/lib/gibber/Makefile.in������������������������������������������������������0000664�0001750�0001750�00000054456�12332443655�022270� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(top_srcdir)/tools/check-coding-style.mk \ $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp # following flag is requied to make getnameinfo work @WINDOWS_TRUE@am__append_1 = -D_WIN32_WINNT=0x0501 subdir = lib/gibber ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_config_dir.m4 \ $(top_srcdir)/m4/compiler.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/tp-compiler-flag.m4 \ $(top_srcdir)/m4/tp-compiler-warnings.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libgibber_la_LIBADD = am__objects_1 = gibber-debug.lo gibber-transport.lo \ gibber-fd-transport.lo gibber-tcp-transport.lo \ gibber-unix-transport.lo gibber-linklocal-transport.lo \ gibber-listener.lo gibber-sockets.lo gibber-util.lo am__objects_2 = gibber-signals-marshal.lo am_libgibber_la_OBJECTS = $(am__objects_1) $(am__objects_2) libgibber_la_OBJECTS = $(am_libgibber_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgibber_la_SOURCES) DIST_SOURCES = $(libgibber_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLIENT_TYPE = @CLIENT_TYPE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_CODING_STYLE_CHECKS = @ENABLE_CODING_STYLE_CHECKS@ ENABLE_PLUGINS = @ENABLE_PLUGINS@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NICE_CFLAGS = @NICE_CFLAGS@ NICE_LIBS = @NICE_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOUP_CFLAGS = @SOUP_CFLAGS@ SOUP_LIBS = @SOUP_LIBS@ STRIP = @STRIP@ TEST_PYTHON = @TEST_PYTHON@ TP_GLIB_CFLAGS = @TP_GLIB_CFLAGS@ TP_GLIB_LIBS = @TP_GLIB_LIBS@ VERSION = @VERSION@ WOCKY_CFLAGS = @WOCKY_CFLAGS@ WOCKY_LIBS = @WOCKY_LIBS@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gabbletestsdir = @gabbletestsdir@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ pluginexecdir = @pluginexecdir@ pluginexeclibdir = @pluginexeclibdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ noinst_LTLIBRARIES = libgibber.la BUILT_SOURCES = \ gibber-signals-marshal.list \ gibber-signals-marshal.h \ gibber-signals-marshal.c OUR_SOURCES = \ gibber-debug.c \ gibber-debug.h \ gibber-transport.c \ gibber-transport.h \ gibber-fd-transport.c \ gibber-fd-transport.h \ gibber-tcp-transport.c \ gibber-tcp-transport.h \ gibber-unix-transport.c \ gibber-unix-transport.h \ gibber-linklocal-transport.c \ gibber-linklocal-transport.h \ gibber-listener.c \ gibber-listener.h \ gibber-sockets.c \ gibber-sockets.h \ gibber-sockets-unix.h \ gibber-sockets-win32.h \ gibber-util.h \ gibber-util.c libgibber_la_SOURCES = $(OUR_SOURCES) $(BUILT_SOURCES) # Coding style checks check_c_sources = \ $(OUR_SOURCES) CLEANFILES = $(BUILT_SOURCES) AM_CFLAGS = $(ERROR_CFLAGS) $(GCOV_CFLAGS) @GLIB_CFLAGS@ \ @GMODULE_CFLAGS@ -fno-strict-aliasing $(am__append_1) AM_LDFLAGS = $(GCOV_LIBS) @GLIB_LIBS@ all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/tools/check-coding-style.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/gibber/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu lib/gibber/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/tools/check-coding-style.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libgibber.la: $(libgibber_la_OBJECTS) $(libgibber_la_DEPENDENCIES) $(EXTRA_libgibber_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libgibber_la_OBJECTS) $(libgibber_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gibber-debug.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gibber-fd-transport.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gibber-linklocal-transport.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gibber-listener.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gibber-signals-marshal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gibber-sockets.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gibber-tcp-transport.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gibber-transport.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gibber-unix-transport.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gibber-util.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: all check check-am install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am check-local clean \ clean-generic clean-libtool clean-noinstLTLIBRARIES \ cscopelist-am ctags ctags-am dist-hook distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am check-coding-style: @fail=0; \ if test -n "$(check_misc_sources)"; then \ tools_dir=$(top_srcdir)/tools \ sh $(top_srcdir)/tools/check-misc.sh \ $(addprefix $(srcdir)/,$(check_misc_sources)) || fail=1; \ fi; \ if test -n "$(check_c_sources)"; then \ tools_dir=$(top_srcdir)/tools \ sh $(top_srcdir)/tools/check-c-style.sh \ $(addprefix $(srcdir)/,$(check_c_sources)) || fail=1; \ fi;\ if test yes = "$(ENABLE_CODING_STYLE_CHECKS)"; then \ exit "$$fail";\ else \ exit 0;\ fi check-local: check-coding-style dist-hook: $(shell for x in $(BUILT_SOURCES); do rm -f $(distdir)/$$x ; done) gibber-signals-marshal.list: $(OUR_SOURCES) Makefile.am @( cd $(srcdir) && \ sed -n -e 's/.*_gibber_signals_marshal_\([[:upper:][:digit:]]*__[[:upper:][:digit:]_]*\).*/\1/p' \ $(OUR_SOURCES) ) \ | sed -e 's/__/:/' -e 'y/_/,/' | sort -u > $@.tmp @if cmp -s $@.tmp $@; then \ rm $@.tmp; \ touch $@; \ else \ mv $@.tmp $@; \ fi %-signals-marshal.h: %-signals-marshal.list Makefile.am $(AM_V_GEN)glib-genmarshal --header --prefix=_$(subst -,_,$*)_signals_marshal $< > $@ %-signals-marshal.c: %-signals-marshal.list Makefile.am $(AM_V_GEN){ echo '#include "$*-signals-marshal.h"' && \ glib-genmarshal --body --prefix=_$(subst -,_,$*)_signals_marshal $< ; \ } > $@ Android.mk: Makefile.am $(BUILT_SOURCES) androgenizer -:PROJECT telepathy-gabble -:STATIC gibber -:TAGS eng debug \ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ -:SOURCES $(libgibber_la_SOURCES) \ -:CFLAGS $(DEFS) $(CFLAGS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CFLAGS) \ -:CPPFLAGS $(CPPFLAGS) $(AM_CPPFLAGS) \ -:LDFLAGS $(AM_LDFLAGS) \ > $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/gibber/gibber-linklocal-transport.c�������������������������������������0000644�0001750�0001750�00000012745�11423525545�025611� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gibber-linklocal-transport.c - Source for GibberLLTransport * Copyright (C) 2006 Collabora Ltd. * @author: Sjoerd Simons <sjoerd@luon.net> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <config.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #ifdef HAVE_UNISTD_H # include <unistd.h> #endif #include "gibber-sockets.h" #include "gibber-linklocal-transport.h" #include "gibber-util.h" #define DEBUG_FLAG DEBUG_NET #include "gibber-debug.h" /* Buffer size used for reading input */ #define BUFSIZE 1024 G_DEFINE_TYPE(GibberLLTransport, gibber_ll_transport, GIBBER_TYPE_FD_TRANSPORT) GQuark gibber_ll_transport_error_quark (void) { static GQuark quark = 0; if (!quark) quark = g_quark_from_static_string ("gibber_linklocal_transport_error"); return quark; } /* private structure */ typedef struct _GibberLLTransportPrivate GibberLLTransportPrivate; struct _GibberLLTransportPrivate { gboolean incoming; gboolean dispose_has_run; }; #define GIBBER_LL_TRANSPORT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GIBBER_TYPE_LL_TRANSPORT, GibberLLTransportPrivate)) static void gibber_ll_transport_finalize (GObject *object); static void gibber_ll_transport_init (GibberLLTransport *self) { GibberLLTransportPrivate *priv = GIBBER_LL_TRANSPORT_GET_PRIVATE (self); priv->incoming = FALSE; } static void gibber_ll_transport_dispose (GObject *object); static void gibber_ll_transport_class_init (GibberLLTransportClass *gibber_ll_transport_class) { GObjectClass *object_class = G_OBJECT_CLASS (gibber_ll_transport_class); g_type_class_add_private (gibber_ll_transport_class, sizeof (GibberLLTransportPrivate)); object_class->dispose = gibber_ll_transport_dispose; object_class->finalize = gibber_ll_transport_finalize; } void gibber_ll_transport_dispose (GObject *object) { GibberLLTransport *self = GIBBER_LL_TRANSPORT (object); GibberLLTransportPrivate *priv = GIBBER_LL_TRANSPORT_GET_PRIVATE (self); if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; if (G_OBJECT_CLASS (gibber_ll_transport_parent_class)->dispose) G_OBJECT_CLASS (gibber_ll_transport_parent_class)->dispose (object); } void gibber_ll_transport_finalize (GObject *object) { G_OBJECT_CLASS (gibber_ll_transport_parent_class)->finalize (object); } GibberLLTransport * gibber_ll_transport_new (void) { return g_object_new (GIBBER_TYPE_LL_TRANSPORT, NULL); } void gibber_ll_transport_open_fd (GibberLLTransport *transport, int fd) { GibberLLTransportPrivate *priv = GIBBER_LL_TRANSPORT_GET_PRIVATE (transport); priv->incoming = TRUE; gibber_transport_set_state (GIBBER_TRANSPORT (transport), GIBBER_TRANSPORT_CONNECTING); gibber_fd_transport_set_fd (GIBBER_FD_TRANSPORT (transport), fd, TRUE); } gboolean gibber_ll_transport_open_sockaddr (GibberLLTransport *transport, struct sockaddr_storage *addr, GError **error) { GibberLLTransportPrivate *priv = GIBBER_LL_TRANSPORT_GET_PRIVATE (transport); char host[NI_MAXHOST]; char port[NI_MAXSERV]; int fd; int ret; g_assert (!priv->incoming); gibber_transport_set_state (GIBBER_TRANSPORT(transport), GIBBER_TRANSPORT_CONNECTING); if (getnameinfo ((struct sockaddr *)addr, sizeof (struct sockaddr_storage), host, NI_MAXHOST, port, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV) == 0) { DEBUG("Trying to connect to %s port %s", host, port); } else { DEBUG("Connecting.."); } fd = socket (addr->ss_family, SOCK_STREAM, 0); if (fd < 0) { g_set_error (error, GIBBER_LL_TRANSPORT_ERROR, GIBBER_LL_TRANSPORT_ERROR_FAILED, "Getting socket failed: %s", g_strerror (errno)); DEBUG("Getting socket failed: %s", strerror(errno)); goto failed; } ret = connect (fd, (struct sockaddr *)addr, sizeof (struct sockaddr_storage)); if (ret < 0) { g_set_error (error, GIBBER_LL_TRANSPORT_ERROR, GIBBER_LL_TRANSPORT_ERROR_CONNECT_FAILED, "Connect failed: %s", g_strerror (errno)); DEBUG("Connecting failed: %s", strerror (errno)); goto failed; } gibber_fd_transport_set_fd (GIBBER_FD_TRANSPORT (transport), fd, TRUE); return TRUE; failed: gibber_transport_set_state (GIBBER_TRANSPORT (transport), GIBBER_TRANSPORT_DISCONNECTED); if (fd >= 0) { close (fd); } return FALSE; } gboolean gibber_ll_transport_is_incoming (GibberLLTransport *transport) { GibberLLTransportPrivate *priv = GIBBER_LL_TRANSPORT_GET_PRIVATE (transport); return priv->incoming; } void gibber_ll_transport_set_incoming (GibberLLTransport *transport, gboolean incoming) { GibberLLTransportPrivate *priv = GIBBER_LL_TRANSPORT_GET_PRIVATE (transport); g_assert ( GIBBER_TRANSPORT (transport)->state == GIBBER_TRANSPORT_DISCONNECTED); priv->incoming = incoming; } ���������������������������telepathy-gabble-0.18.3/lib/gibber/gibber-tcp-transport.h�������������������������������������������0000644�0001750�0001750�00000004343�11423525545�024427� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gibber-tcp-transport.h - Header for GibberTCPTransport * Copyright (C) 2006 Collabora Ltd. * @author Sjoerd Simons <sjoerd@luon.net> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __GIBBER_TCP_TRANSPORT_H__ #define __GIBBER_TCP_TRANSPORT_H__ #include <glib-object.h> #include "gibber-fd-transport.h" G_BEGIN_DECLS typedef struct _GibberTCPTransport GibberTCPTransport; typedef struct _GibberTCPTransportClass GibberTCPTransportClass; struct _GibberTCPTransportClass { GibberFdTransportClass parent_class; }; struct _GibberTCPTransport { GibberFdTransport parent; }; GType gibber_tcp_transport_get_type (void); /* TYPE MACROS */ #define GIBBER_TYPE_TCP_TRANSPORT \ (gibber_tcp_transport_get_type ()) #define GIBBER_TCP_TRANSPORT(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), GIBBER_TYPE_TCP_TRANSPORT, \ GibberTCPTransport)) #define GIBBER_TCP_TRANSPORT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), GIBBER_TYPE_TCP_TRANSPORT, \ GibberTCPTransportClass)) #define GIBBER_IS_TCP_TRANSPORT(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GIBBER_TYPE_TCP_TRANSPORT)) #define GIBBER_IS_TCP_TRANSPORT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), GIBBER_TYPE_TCP_TRANSPORT)) #define GIBBER_TCP_TRANSPORT_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GIBBER_TYPE_TCP_TRANSPORT, \ GibberTCPTransportClass)) GibberTCPTransport * gibber_tcp_transport_new (void); void gibber_tcp_transport_connect (GibberTCPTransport *tcp_transport, const gchar *host, guint16 port); G_END_DECLS #endif /* #ifndef __GIBBER_TCP_TRANSPORT_H__*/ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/gibber/gibber-unix-transport.c������������������������������������������0000664�0001750�0001750�00000024676�12223562023�024623� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * gibber-linklocal-transport.c - Source for GibberLLTransport * Copyright (C) 2006, 2008 Collabora Ltd. * @author: Sjoerd Simons <sjoerd@luon.net> * @author: Alban Crequy <alban.crequy@collabora.co.uk> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include <glib.h> #ifdef G_OS_UNIX /* If you claim to be Unix but you don't have these headers, you may have * already lost. */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include "gibber-unix-transport.h" #include "gibber-util.h" #define DEBUG_FLAG DEBUG_NET #include "gibber-debug.h" G_DEFINE_TYPE(GibberUnixTransport, gibber_unix_transport, \ GIBBER_TYPE_FD_TRANSPORT) GQuark gibber_unix_transport_error_quark (void) { static GQuark quark = 0; if (!quark) quark = g_quark_from_static_string ("gibber_unix_transport_error"); return quark; } /* private structure */ typedef struct _GibberUnixTransportPrivate GibberUnixTransportPrivate; struct _GibberUnixTransportPrivate { gboolean incoming; GibberUnixTransportRecvCredentialsCb recv_creds_cb; gpointer recv_creds_data; gboolean dispose_has_run; }; #define GIBBER_UNIX_TRANSPORT_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), GIBBER_TYPE_UNIX_TRANSPORT, \ GibberUnixTransportPrivate)) static void gibber_unix_transport_finalize (GObject *object); static void gibber_unix_transport_init (GibberUnixTransport *self) { GibberUnixTransportPrivate *priv = GIBBER_UNIX_TRANSPORT_GET_PRIVATE (self); priv->incoming = FALSE; } static void gibber_unix_transport_dispose (GObject *object); static GibberFdIOResult gibber_unix_transport_read ( GibberFdTransport *transport, GIOChannel *channel, GError **error); static void gibber_unix_transport_class_init ( GibberUnixTransportClass *gibber_unix_transport_class) { GObjectClass *object_class = G_OBJECT_CLASS (gibber_unix_transport_class); GibberFdTransportClass *fd_class = GIBBER_FD_TRANSPORT_CLASS ( gibber_unix_transport_class); g_type_class_add_private (gibber_unix_transport_class, sizeof (GibberUnixTransportPrivate)); object_class->dispose = gibber_unix_transport_dispose; object_class->finalize = gibber_unix_transport_finalize; /* override GibberFdTransport's read */ fd_class->read = gibber_unix_transport_read; } void gibber_unix_transport_dispose (GObject *object) { GibberUnixTransport *self = GIBBER_UNIX_TRANSPORT (object); GibberUnixTransportPrivate *priv = GIBBER_UNIX_TRANSPORT_GET_PRIVATE (self); if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; priv->recv_creds_cb = NULL; priv->recv_creds_data = NULL; if (G_OBJECT_CLASS (gibber_unix_transport_parent_class)->dispose) G_OBJECT_CLASS (gibber_unix_transport_parent_class)->dispose (object); } void gibber_unix_transport_finalize (GObject *object) { G_OBJECT_CLASS (gibber_unix_transport_parent_class)->finalize (object); } GibberUnixTransport * gibber_unix_transport_new (void) { return g_object_new (GIBBER_TYPE_UNIX_TRANSPORT, NULL); } gboolean gibber_unix_transport_connect (GibberUnixTransport *transport, const gchar *path, GError **error) { union { struct sockaddr_un un; struct sockaddr addr; } addr; int fd; gibber_transport_set_state (GIBBER_TRANSPORT (transport), GIBBER_TRANSPORT_CONNECTING); memset (&addr, 0, sizeof (addr)); fd = socket (PF_UNIX, SOCK_STREAM, 0); if (fd == -1) { DEBUG ("Error creating socket: %s", g_strerror (errno)); g_set_error (error, GIBBER_UNIX_TRANSPORT_ERROR, GIBBER_UNIX_TRANSPORT_ERROR_CONNECT_FAILED, "Error creating socket: %s", g_strerror (errno)); goto failed; } addr.un.sun_family = PF_UNIX; g_strlcpy (addr.un.sun_path, path, sizeof (addr.un.sun_path)); if (connect (fd, &addr.addr, sizeof (addr.un)) == -1) { g_set_error (error, GIBBER_UNIX_TRANSPORT_ERROR, GIBBER_UNIX_TRANSPORT_ERROR_CONNECT_FAILED, "Error connecting socket: %s", g_strerror (errno)); DEBUG ("Error connecting socket: %s", g_strerror (errno)); goto failed; } DEBUG ("Connected to socket"); gibber_fd_transport_set_fd (GIBBER_FD_TRANSPORT (transport), fd, TRUE); return TRUE; failed: g_assert (error != NULL); gibber_transport_emit_error (GIBBER_TRANSPORT(transport), *error); gibber_transport_set_state (GIBBER_TRANSPORT (transport), GIBBER_TRANSPORT_DISCONNECTED); return FALSE; } GibberUnixTransport * gibber_unix_transport_new_from_fd (int fd) { GibberUnixTransport *transport; transport = gibber_unix_transport_new (); gibber_fd_transport_set_fd (GIBBER_FD_TRANSPORT (transport), fd, TRUE); return transport; } /* Patches that reimplement these functions for non-Linux would be welcome * (please file a bug) */ #if defined(__linux__) gboolean gibber_unix_transport_supports_credentials (void) { return TRUE; } gboolean gibber_unix_transport_send_credentials (GibberUnixTransport *transport, const guint8 *data, gsize size) { int fd, ret; struct ucred *cred; struct msghdr msg; struct cmsghdr *ch; struct iovec iov; char buffer[CMSG_SPACE (sizeof (struct ucred))]; DEBUG ("send credentials"); fd = GIBBER_FD_TRANSPORT (transport)->fd; /* Set the message payload */ memset (&iov, 0, sizeof (iov)); iov.iov_base = (void *) data; iov.iov_len = size; memset (&msg, 0, sizeof (msg)); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = buffer; msg.msg_controllen = sizeof (buffer); memset (buffer, 0, sizeof (buffer)); /* Set the credentials */ ch = CMSG_FIRSTHDR (&msg); ch->cmsg_len = CMSG_LEN (sizeof (struct ucred)); ch->cmsg_level = SOL_SOCKET; ch->cmsg_type = SCM_CREDENTIALS; cred = (struct ucred *) CMSG_DATA (ch); cred->pid = getpid (); cred->uid = getuid (); cred->gid = getgid (); ret = sendmsg (fd, &msg, 0); if (ret == -1) { DEBUG ("sendmsg failed: %s", g_strerror (errno)); return FALSE; } return TRUE; } #define BUFSIZE 1024 static GibberFdIOResult gibber_unix_transport_read (GibberFdTransport *transport, GIOChannel *channel, GError **error) { GibberUnixTransport *self = GIBBER_UNIX_TRANSPORT (transport); GibberUnixTransportPrivate *priv = GIBBER_UNIX_TRANSPORT_GET_PRIVATE (self); int fd; guint8 buffer[BUFSIZE]; ssize_t bytes_read; GibberBuffer buf; struct iovec iov; struct msghdr msg; char control[CMSG_SPACE (sizeof (struct ucred))]; struct cmsghdr *ch; struct ucred *cred; int opt; if (priv->recv_creds_cb == NULL) return gibber_fd_transport_read (transport, channel, error); /* We are waiting for credentials */ fd = transport->fd; /* set SO_PASSCRED flag */ opt = 1; setsockopt (fd, SOL_SOCKET, SO_PASSCRED, &opt, sizeof (opt)); memset (buffer, 0, sizeof (buffer)); memset (&iov, 0, sizeof (iov)); iov.iov_base = buffer; iov.iov_len = sizeof (buffer); memset (&msg, 0, sizeof (msg)); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = control; msg.msg_controllen = sizeof (control); bytes_read = recvmsg (fd, &msg, 0); if (bytes_read == -1) { GError *err = NULL; g_set_error_literal (&err, G_IO_CHANNEL_ERROR, g_io_channel_error_from_errno (errno), "recvmsg failed"); priv->recv_creds_cb (self, NULL, NULL, err, priv->recv_creds_data); g_propagate_error (error, err); priv->recv_creds_cb = NULL; priv->recv_creds_data = NULL; return GIBBER_FD_IO_RESULT_ERROR; } /* unset SO_PASSCRED flag */ opt = 0; setsockopt (fd, SOL_SOCKET, SO_PASSCRED, &opt, sizeof (opt)); buf.data = buffer; buf.length = bytes_read; /* extract the credentials */ ch = CMSG_FIRSTHDR (&msg); if (ch == NULL) { GError *err = NULL; DEBUG ("Message doesn't contain credentials"); g_set_error_literal (&err, GIBBER_UNIX_TRANSPORT_ERROR, GIBBER_UNIX_TRANSPORT_ERROR_NO_CREDENTIALS, "no credentials received"); priv->recv_creds_cb (self, &buf, NULL, err, priv->recv_creds_data); g_error_free (err); } else { GibberCredentials credentials; cred = (struct ucred *) CMSG_DATA (ch); credentials.pid = cred->pid; credentials.uid = cred->uid; credentials.gid = cred->gid; priv->recv_creds_cb (self, &buf, &credentials, NULL, priv->recv_creds_data); } priv->recv_creds_cb = NULL; priv->recv_creds_data = NULL; return GIBBER_FD_IO_RESULT_SUCCESS; } gboolean gibber_unix_transport_recv_credentials (GibberUnixTransport *self, GibberUnixTransportRecvCredentialsCb callback, gpointer user_data) { GibberUnixTransportPrivate *priv = GIBBER_UNIX_TRANSPORT_GET_PRIVATE (self); if (priv->recv_creds_cb != NULL) { DEBUG ("already waiting for credentials"); return FALSE; } priv->recv_creds_cb = callback; priv->recv_creds_data = user_data; return TRUE; } #else /* OSs where we have no implementation */ gboolean gibber_unix_transport_supports_credentials (void) { return FALSE; } gboolean gibber_unix_transport_recv_credentials (GibberUnixTransport *self, GibberUnixTransportRecvCredentialsCb callback, gpointer user_data) { DEBUG ("stub implementation, failing"); return FALSE; } gboolean gibber_unix_transport_send_credentials (GibberUnixTransport *transport, const guint8 *data, gsize size) { DEBUG ("stub implementation, failing"); return FALSE; } static GibberFdIOResult gibber_unix_transport_read (GibberFdTransport *transport, GIOChannel *channel, GError **error) { return gibber_fd_transport_read (transport, channel, error); } #endif /* OSs where we have no implementation of credentials */ #endif /* G_OS_UNIX */ ������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/��������������������������������������������������������������������0000775�0001750�0001750�00000000000�12332445272�017550� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/Makefile.am���������������������������������������������������������0000664�0001750�0001750�00000000410�12223562020�021565� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������SUBDIRS = DIST_SUBDIRS = wocky all-local: @cd wocky && $(MAKE) clean-local: if test -e wocky/Makefile ; then \ cd wocky && $(MAKE) clean ; \ fi uninstall-local: @cd wocky/wocky && $(MAKE) uninstall install-data-local: @cd wocky/wocky && $(MAKE) install ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/��������������������������������������������������������������0000775�0001750�0001750�00000000000�12332445273�020705� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/configure.ac��������������������������������������������������0000664�0001750�0001750�00000024120�12332440453�023165� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������AC_PREREQ([2.59]) # Making releases: # set the new version number: # odd minor -> development series # even minor -> stable series # increment micro for each release within a series # set wockynano_version to 0. m4_define([wocky_major_version], [0]) m4_define([wocky_minor_version], [0]) m4_define([wocky_micro_version], [0]) m4_define([wocky_nano_version], [1]) # Some magic m4_define([wocky_base_version], [wocky_major_version.wocky_minor_version.wocky_micro_version]) m4_define([wocky_version], [m4_if(wocky_nano_version, 0, [wocky_base_version], [wocky_base_version].[wocky_nano_version])])dnl AC_INIT([Wocky], [wocky_version]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([1.9 -Wno-portability tar-ustar]) AM_PROG_LIBTOOL AM_CONFIG_HEADER(config.h) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES]) dnl check for tools AC_PROG_CC AC_PROG_CC_STDC AM_PROG_AS AM_PROG_MKDIR_P dnl decide error flags dnl ifelse(wocky_nano_version, 0, dnl [ official_release=yes ], dnl [ official_release=no ]) official_release=no TP_COMPILER_WARNINGS([ERROR_CFLAGS], [test "x$official_release" = xno], [all \ extra \ declaration-after-statement \ shadow \ strict-prototypes \ missing-prototypes \ sign-compare \ nested-externs \ pointer-arith \ format-security \ init-self], [missing-field-initializers \ unused-parameter]) AC_SUBST([ERROR_CFLAGS]) ifelse(wocky_nano_version, 0, [ # Wocky is version x.y.z - disable coding style checks by default AC_ARG_ENABLE(coding-style-checks, AC_HELP_STRING([--enable-coding-style-checks], [check coding style using grep]), [ENABLE_CODING_STYLE_CHECKS=$enableval], [ENABLE_CODING_STYLE_CHECKS=no] ) ], [ # Wocky is version x.y.z.1 - enable coding style checks by default AC_ARG_ENABLE(coding-style-checks, AC_HELP_STRING([--disable-coding-style-checks], [do not check coding style using grep]), [ENABLE_CODING_STYLE_CHECKS=$enableval], [ENABLE_CODING_STYLE_CHECKS=yes]) ]) AC_SUBST([ENABLE_CODING_STYLE_CHECKS]) dnl debugging stuff AC_ARG_ENABLE(debug, AC_HELP_STRING([--disable-debug],[compile without debug code]), [ case "${enableval}" in yes|no) enable_debug="${enableval}" ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;; esac ], [enable_debug=yes]) if test "$enable_debug" = yes; then AC_DEFINE(ENABLE_DEBUG, [], [Enable debug code]) else enable_debug=no fi AC_ARG_WITH(installed-headers, AC_HELP_STRING([--with-installed-headers=DIR], [install development headers to DIR @<:@default=nowhere@:>@]), [], [with_installed_headers=]) AM_CONDITIONAL(INSTALL_HEADERS, test x$with_installed_headers != x) HEADER_DIR=$with_installed_headers AC_SUBST(HEADER_DIR) dnl Build a shared library even though Wocky isn't stable yet? AC_ARG_ENABLE([shared-suffix], AC_HELP_STRING([--enable-shared-suffix=], [install a shared library with a version-specific suffix]), [], [enable_shared_suffix=]) AM_CONDITIONAL([ENABLE_SHARED_SUFFIX], [test x$enable_shared_suffix != x]) SHARED_SUFFIX="$enable_shared_suffix" AC_SUBST([SHARED_SUFFIX]) dnl Check for code generation tools AC_HEADER_STDC([]) AC_CHECK_HEADERS_ONCE([unistd.h]) AC_C_INLINE dnl Check endianness (Needed for the sha1 implementation) AC_C_BIGENDIAN dnl Check for Glib PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.32, gobject-2.0 >= 2.32, gthread-2.0 >= 2.32, gio-2.0 >= 2.32]) AC_DEFINE([GLIB_VERSION_MIN_REQUIRED], [GLIB_VERSION_2_32], [Ignore post 2.32 deprecations]) AC_DEFINE([GLIB_VERSION_MAX_ALLOWED], [GLIB_VERSION_2_32], [Prevent post 2.32 APIs]) AC_SUBST(GLIB_CFLAGS) AC_SUBST(GLIB_LIBS) dnl Check GIO proxy support PKG_CHECK_EXISTS([gio-2.0 >= 2.25.15], [HAVE_GIO_PROXY=yes AC_DEFINE(HAVE_GIO_PROXY, [1], [Defined if GIO supports proxy])], [HAVE_GIO_PROXY=no]) AM_CONDITIONAL(HAVE_GIO_PROXY, [test "x${HAVE_GIO_PROXY}" = "xyes"]) dnl Choose an SSL/TLS backend (default gnutls) AC_ARG_WITH([tls], AC_HELP_STRING([--with-tls=BACKEND], [which TLS backend to use (gnutls, openssl, or auto) @<:@default=auto@:>@]), [], [with_tls=auto]) AS_CASE([$with_tls], [gnutls], [PKG_CHECK_MODULES(TLS, [gnutls >= 2.8.2 ])], [openssl], [USING_OPENSSL=yes AC_DEFINE(USING_OPENSSL, 1, [Define if using openssl]) PKG_CHECK_MODULES(TLS, [openssl >= 0.9.8g])], [auto], [PKG_CHECK_MODULES(TLS, [gnutls >= 2.8.2 ], [with_tls=gnutls], [USING_OPENSSL=yes AC_DEFINE(USING_OPENSSL, 1, [Define if using openssl]) PKG_CHECK_MODULES(TLS, [openssl >= 0.9.8g],[with_tls=openssl], AC_MSG_ERROR([Neither gnutls nor openssl found]))])], [*], AC_MSG_ERROR([Must have a TLS backend (gnutls or openssl)])) AC_SUBST(TLS_CFLAGS) AC_SUBST(TLS_LIBS) AM_CONDITIONAL(USING_OPENSSL, test x$USING_OPENSSL = xyes) AC_ARG_ENABLE([prefer-stream-ciphers], AC_HELP_STRING([--enable-prefer-stream-ciphers], [prefer stream ciphers over block ciphers to save bandwidth (at the possible expense of security)]), [prefer_stream_ciphers=$enableval], [prefer_stream_ciphers=no]) if test x$prefer_stream_ciphers = xyes; then AC_DEFINE(ENABLE_PREFER_STREAM_CIPHERS, [], [Prefer stream ciphers over block ones to save bandwidth]) if test $with_tls = gnutls; then # The *-ALL priority strings require gnutls 2.12.0. # We do this check here and not earlier to avoid accidentally falling # back to openssl because of the use of --enable-prefer-stream-ciphers. PKG_CHECK_MODULES(GNUTLS_FOR_STREAM_CIPHERS, [gnutls >= 2.12.0],[], AC_MSG_ERROR([gnutls 2.12.0 is needed to use --enable-prefer-stream-cihpers])) fi fi # ----------------------------------------------------------- # Make CA certificates path configurable # Stolen from GIO's TLS # ----------------------------------------------------------- AC_MSG_CHECKING([location of system Certificate Authority list]) AC_ARG_WITH(ca-certificates, [AC_HELP_STRING([--with-ca-certificates=@<:@path@:>@], [path to system Certificate Authority list])]) if test "$with_ca_certificates" = "no"; then AC_MSG_RESULT([disabled]) else if test -z "$with_ca_certificates"; then for f in /etc/pki/tls/certs/ca-bundle.crt \ /etc/ssl/certs/ca-certificates.crt; do if test -f "$f"; then with_ca_certificates="$f" fi done if test -z "$with_ca_certificates"; then AC_MSG_ERROR([could not find. Use --with-ca-certificates=path to set, or --without-ca-certificates to disable]) fi fi AC_MSG_RESULT($with_ca_certificates) AC_DEFINE_UNQUOTED([GTLS_SYSTEM_CA_CERTIFICATES], ["$with_ca_certificates"], [path to system Certificate Authority list]) fi if test -n "$with_ca_certificates"; then if ! test -f "$with_ca_certificates"; then AC_MSG_WARN([Specified certificate authority file '$with_ca_certificates' does not exist]) fi fi GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` AC_SUBST(GLIB_GENMARSHAL) dnl Check for libxml2 PKG_CHECK_MODULES(LIBXML2, [libxml-2.0]) AC_SUBST(LIBXML2_CFLAGS) AC_SUBST(LIBXML2_LIBS) dnl Check for sqlite PKG_CHECK_MODULES(SQLITE, [sqlite3]) AC_SUBST(SQLITE_CFLAGS) AC_SUBST(SQLITE_LIBS) dnl check for libsasl2 (for sasl test) dnl must check for headers as well as library (no .pc so can't use pkg-config) AC_CHECK_LIB(sasl2, sasl_server_new, [ AC_CHECK_HEADER(sasl/sasl.h, [ LIBSASL2_LIBS="-lsasl2" LIBSASL2_CFLAGS="" HAVE_LIBSASL2=yes AC_DEFINE(HAVE_LIBSASL2, 1, [Define if libsasl2 is available]) ], [ AC_MSG_WARN(libsasl2 headers missing: skipping sasl tests)]) ], [ AC_MSG_WARN(libsasl2 not found: skipping sasl tests) HAVE_LIBSASL2=no ]) AC_SUBST(LIBSASL2_LIBS) AC_SUBST(LIBSASL2_CFLAGS) AM_CONDITIONAL(HAVE_LIBSASL2, test "x$HAVE_LIBSASL2" = "xyes") PKG_CHECK_MODULES(LIBIPHB, [libiphb >= 0.61.31], [AC_DEFINE(HAVE_IPHB, 1, [libiphb is available]) have_iphb=yes ], [have_iphb=no]) AC_SUBST(LIBIPHB_CFLAGS) AC_SUBST(LIBIPHB_LIBS) AC_ARG_ENABLE(google-relay, AC_HELP_STRING([--disable-google-relay], [disable Google Jingle relay support]), [enable_google_relay=$enableval], [enable_google_relay=yes]) if test x$enable_google_relay = xyes; then AC_DEFINE(ENABLE_GOOGLE_RELAY, [], [Enable Google Jingle relay support]) dnl Check for libsoup PKG_CHECK_MODULES(SOUP, libsoup-2.4) fi AM_CONDITIONAL([ENABLE_GOOGLE_RELAY], [test "x$enable_google_relay" = xyes]) AC_ARG_ENABLE(coverage, AC_HELP_STRING([--enable-coverage], [compile with coverage profiling instrumentation (gcc only)]), [ case "${enableval}" in "yes"|"no") enable_coverage="${enableval}" ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-coverage) ;; esac ] ) WOCKY_GCOV(${enable_coverage}) WOCKY_LCOV(${enable_coverage}) if test "x$enable_coverage" = "x"; then enable_coverage=no fi AC_SUBST(PACKAGE_STRING) dnl To be used by tests and examples WOCKY_CFLAGS='-I${top_builddir} -I${top_srcdir}' AC_SUBST(WOCKY_CFLAGS) GTK_DOC_CHECK([1.17],[--flavour no-tmpl]) AC_OUTPUT( Makefile \ wocky/Makefile \ wocky/wocky-uninstalled.pc \ wocky/wocky.pc \ m4/Makefile \ tools/Makefile \ examples/Makefile \ tests/Makefile \ docs/Makefile \ docs/reference/Makefile ) echo " Configure summary: Compiler Flags.......: ${CFLAGS} Prefix...............: ${prefix} Coverage profiling...: ${enable_coverage} Coding style checks..: ${ENABLE_CODING_STYLE_CHECKS} Debug................: ${enable_debug} Features: TLS Backend..........: ${with_tls} Prefer stream ciphers: ${prefer_stream_ciphers} System CA certs......: ${with_ca_certificates} SASL2 Tests..........: ${HAVE_LIBSASL2} gtk-doc documentation: ${enable_gtk_doc} libiphb integration..: ${have_iphb} Google relay support.: ${enable_google_relay} " ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/README��������������������������������������������������������0000644�0001750�0001750�00000000024�11544576223�021563� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������Wocky XMPP Library! ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/aclocal.m4����������������������������������������������������0000664�0001750�0001750�00000140747�12332443663�022563� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# generated automatically by aclocal 1.13.4 -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # serial 1 (pkg-config-0.24) # # Copyright © 2004 Scott James Remnant <scott@netsplit.com>. # # 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. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # PKG_PROG_PKG_CONFIG([MIN-VERSION]) # ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])# PKG_PROG_PKG_CONFIG # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # # Check to see whether a particular set of modules exists. Similar # to PKG_CHECK_MODULES(), but does not set variables or print errors. # # Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) # only at the first occurence in configure.ac, so if the first place # it's called might be skipped (such as if it is within an "if", you # have to call PKG_CHECK_EXISTS manually # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) # --------------------------------------------- m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])# _PKG_CONFIG # _PKG_SHORT_ERRORS_SUPPORTED # ----------------------------- AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])# _PKG_SHORT_ERRORS_SUPPORTED # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], # [ACTION-IF-NOT-FOUND]) # # # Note that if there is a possibility the first call to # PKG_CHECK_MODULES might not happen, you should be sure to include an # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac # # # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])# PKG_CHECK_MODULES # PKG_INSTALLDIR(DIRECTORY) # ------------------------- # Substitutes the variable pkgconfigdir as the location where a module # should install pkg-config .pc files. By default the directory is # $libdir/pkgconfig, but the default can be changed by passing # DIRECTORY. The user can override through the --with-pkgconfigdir # parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ]) dnl PKG_INSTALLDIR # PKG_NOARCH_INSTALLDIR(DIRECTORY) # ------------------------- # Substitutes the variable noarch_pkgconfigdir as the location where a # module should install arch-independent pkg-config .pc files. By # default the directory is $datadir/pkgconfig, but the default can be # changed by passing DIRECTORY. The user can override through the # --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ]) dnl PKG_NOARCH_INSTALLDIR # PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, # [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # ------------------------------------------- # Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])# PKG_CHECK_VAR # Copyright (C) 2002-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # 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. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.13' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.13.4], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.13.4])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # Figure out how to run the assembler. -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_AS # ---------- AC_DEFUN([AM_PROG_AS], [# By default we simply use the C compiler to build assembly code. AC_REQUIRE([AC_PROG_CC]) test "${CCAS+set}" = set || CCAS=$CC test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS AC_ARG_VAR([CCAS], [assembler compiler command (defaults to CC)]) AC_ARG_VAR([CCASFLAGS], [assembler compiler flags (defaults to CFLAGS)]) _AM_IF_OPTION([no-dependencies],, [_AM_DEPENDENCIES([CCAS])])dnl ]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each '.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # 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. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> # <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Copyright (C) 2003-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_MKDIR_P # --------------- # Check for 'mkdir -p'. AC_DEFUN([AM_PROG_MKDIR_P], [AC_PREREQ([2.60])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl dnl FIXME we are no longer going to remove this! adjust warning dnl FIXME message accordingly. AC_DIAGNOSE([obsolete], [$0: this macro is deprecated, and will soon be removed. You should use the Autoconf-provided 'AC][_PROG_MKDIR_P' macro instead, and use '$(MKDIR_P)' instead of '$(mkdir_p)'in your Makefile.am files.]) dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, dnl while keeping a definition of mkdir_p for backward compatibility. dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of dnl Makefile.ins that do not define MKDIR_P, so we do our own dnl adjustment using top_builddir (which is defined more often than dnl MKDIR_P). AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl case $mkdir_p in [[\\/$]]* | ?:[[\\/]]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac ]) # -*- Autoconf -*- # Obsolete and "removed" macros, that must however still report explicit # error messages when used, to smooth transition. # # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. AC_DEFUN([AM_CONFIG_HEADER], [AC_DIAGNOSE([obsolete], ['$0': this macro is obsolete. You should use the 'AC][_CONFIG_HEADERS' macro instead.])dnl AC_CONFIG_HEADERS($@)]) AC_DEFUN([AM_PROG_CC_STDC], [AC_PROG_CC am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc AC_DIAGNOSE([obsolete], ['$0': this macro is obsolete. You should simply use the 'AC][_PROG_CC' macro instead. Also, your code should no longer depend upon 'am_cv_prog_cc_stdc', but upon 'ac_cv_prog_cc_stdc'.])]) AC_DEFUN([AM_C_PROTOTYPES], [AC_FATAL([automatic de-ANSI-fication support has been removed])]) AU_DEFUN([fp_C_PROTOTYPES], [AM_C_PROTOTYPES]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # 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 ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $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 if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2013 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar <conftest.tar]) AM_RUN_LOG([cat conftest.dir/file]) grep GrepMe conftest.dir/file >/dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/as-compiler-flag.m4]) m4_include([m4/gtk-doc.m4]) m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) m4_include([m4/tp-compiler-flag.m4]) m4_include([m4/tp-compiler-warnings.m4]) m4_include([m4/wocky-gcov.m4]) m4_include([m4/wocky-lcov.m4]) �������������������������telepathy-gabble-0.18.3/lib/ext/wocky/Makefile.am���������������������������������������������������0000664�0001750�0001750�00000001402�12332440453�022731� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = autogen.sh SUBDIRS = wocky tools m4 examples tests docs DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc dist-hook: chmod u+w ${distdir}/ChangeLog if test -d ${top_srcdir}/.git; then \ git log --stat > ${distdir}/ChangeLog || \ git log > ${distdir}/ChangeLog; \ fi include $(top_srcdir)/rules/lcov.mak CLEANFILES = FIXME.out check-local:: egrep -A 5 '[F]IXME|[T]ODO|[X]XX' \ $(srcdir)/wocky/*.[ch] \ $(srcdir)/tests/*.[ch] \ $(srcdir)/examples/*.[ch] \ > FIXME.out || true # one day we'll have a wocky.freedesktop.org but today is not that day maintainer-upload-docs: rsync -rvzPp --chmod=Dg+s,ug+rwX,o=rX $(srcdir)/docs/reference/html/ \ telepathy.freedesktop.org:/srv/telepathy.freedesktop.org/www/doc/wocky/ ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/missing�������������������������������������������������������0000755�0001750�0001750�00000015331�12332443664�022307� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2012-06-26.16; # UTC # Copyright (C) 1996-2013 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996. # 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, see <http://www.gnu.org/licenses/>. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to <bug-automake@gnu.org>." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=http://www.perl.org/ flex_URL=http://flex.sourceforge.net/ gnu_software_URL=http://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'automa4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/INSTALL�������������������������������������������������������0000644�0001750�0001750�00000036605�12332443664�021750� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������Installation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX `make' updates targets which have the same time stamps as their prerequisites, which makes it generally unusable when shipped generated files such as `configure' are involved. Use GNU `make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `<wchar.h>' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf limitation. Until the limitation is lifted, you can use this workaround: CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. ���������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/autogen.sh����������������������������������������������������0000755�0001750�0001750�00000001360�11544576223�022710� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/bin/sh set -e gtkdocize || exit 1 if test -n "$AUTOMAKE"; then : # don't override an explicit user request elif automake-1.11 --version >/dev/null 2>/dev/null && \ aclocal-1.11 --version >/dev/null 2>/dev/null; then # If we have automake-1.11, use it. This is the oldest version (=> least # likely to introduce undeclared dependencies) that will give us # --enable-silent-rules support. AUTOMAKE=automake-1.11 export AUTOMAKE ACLOCAL=aclocal-1.11 export ACLOCAL fi autoreconf -i -f run_configure=true for arg in $*; do case $arg in --no-configure) run_configure=false ;; *) ;; esac done if test $run_configure = true; then ./configure "$@" fi ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/configure�����������������������������������������������������0000755�0001750�0001750�00002004655�12332443663�022627� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for Wocky 0.0.0.1. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 </dev/null exec 6>&1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='Wocky' PACKAGE_TARNAME='wocky' PACKAGE_VERSION='0.0.0.1' PACKAGE_STRING='Wocky 0.0.0.1' PACKAGE_BUGREPORT='' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include <stdio.h> #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> #endif #ifdef HAVE_SYS_STAT_H # include <sys/stat.h> #endif #ifdef STDC_HEADERS # include <stdlib.h> # include <stddef.h> #else # ifdef HAVE_STDLIB_H # include <stdlib.h> # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include <memory.h> # endif # include <string.h> #endif #ifdef HAVE_STRINGS_H # include <strings.h> #endif #ifdef HAVE_INTTYPES_H # include <inttypes.h> #endif #ifdef HAVE_STDINT_H # include <stdint.h> #endif #ifdef HAVE_UNISTD_H # include <unistd.h> #endif" ac_header_list= ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS GTK_DOC_USE_REBASE_FALSE GTK_DOC_USE_REBASE_TRUE GTK_DOC_USE_LIBTOOL_FALSE GTK_DOC_USE_LIBTOOL_TRUE GTK_DOC_BUILD_PDF_FALSE GTK_DOC_BUILD_PDF_TRUE GTK_DOC_BUILD_HTML_FALSE GTK_DOC_BUILD_HTML_TRUE ENABLE_GTK_DOC_FALSE ENABLE_GTK_DOC_TRUE GTKDOC_DEPS_LIBS GTKDOC_DEPS_CFLAGS HTML_DIR GTKDOC_MKPDF GTKDOC_REBASE GTKDOC_CHECK WOCKY_CFLAGS HAVE_LCOV_FALSE HAVE_LCOV_TRUE LCOV_PATH HAVE_GCOV_FALSE HAVE_GCOV_TRUE GCOV GCOV_LIBS GCOV_CFLAGS FFLAGS CXXFLAGS MOSTLYCLEANFILES have_gcov ENABLE_GOOGLE_RELAY_FALSE ENABLE_GOOGLE_RELAY_TRUE SOUP_LIBS SOUP_CFLAGS LIBIPHB_LIBS LIBIPHB_CFLAGS HAVE_LIBSASL2_FALSE HAVE_LIBSASL2_TRUE LIBSASL2_CFLAGS LIBSASL2_LIBS SQLITE_LIBS SQLITE_CFLAGS LIBXML2_LIBS LIBXML2_CFLAGS GLIB_GENMARSHAL GNUTLS_FOR_STREAM_CIPHERS_LIBS GNUTLS_FOR_STREAM_CIPHERS_CFLAGS USING_OPENSSL_FALSE USING_OPENSSL_TRUE TLS_LIBS TLS_CFLAGS HAVE_GIO_PROXY_FALSE HAVE_GIO_PROXY_TRUE GLIB_LIBS GLIB_CFLAGS PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG SHARED_SUFFIX ENABLE_SHARED_SUFFIX_FALSE ENABLE_SHARED_SUFFIX_TRUE HEADER_DIR INSTALL_HEADERS_FALSE INSTALL_HEADERS_TRUE ENABLE_CODING_STYLE_CHECKS ERROR_CFLAGS am__fastdepCCAS_FALSE am__fastdepCCAS_TRUE CCASDEPMODE CCASFLAGS CCAS CPP OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB ac_ct_AR AR DLLTOOL OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC host_os host_vendor host_cpu host build_os build_vendor build_cpu build LIBTOOL AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_shared enable_static with_pic enable_fast_install enable_dependency_tracking with_gnu_ld with_sysroot enable_libtool_lock enable_Werror enable_coding_style_checks enable_debug with_installed_headers enable_shared_suffix with_tls enable_prefer_stream_ciphers with_ca_certificates enable_google_relay enable_coverage with_html_dir enable_gtk_doc enable_gtk_doc_html enable_gtk_doc_pdf ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP CCAS CCASFLAGS PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR GLIB_CFLAGS GLIB_LIBS TLS_CFLAGS TLS_LIBS GNUTLS_FOR_STREAM_CIPHERS_CFLAGS GNUTLS_FOR_STREAM_CIPHERS_LIBS LIBXML2_CFLAGS LIBXML2_LIBS SQLITE_CFLAGS SQLITE_LIBS LIBIPHB_CFLAGS LIBIPHB_LIBS SOUP_CFLAGS SOUP_LIBS GTKDOC_DEPS_CFLAGS GTKDOC_DEPS_LIBS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= 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=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -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_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$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 ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$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 | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$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 ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) 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 | -n) 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 ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$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_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=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 ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # 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 the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` 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 test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # 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 <<_ACEOF \`configure' configures Wocky 0.0.0.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/wocky] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --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 System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of Wocky 0.0.0.1:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --disable-libtool-lock avoid locking (might break parallel builds) --disable-Werror compile without -Werror (normally enabled in development builds) --disable-coding-style-checks do not check coding style using grep --disable-debug compile without debug code --enable-shared-suffix= install a shared library with a version-specific suffix --enable-prefer-stream-ciphers prefer stream ciphers over block ciphers to save bandwidth (at the possible expense of security) --disable-google-relay disable Google Jingle relay support --enable-coverage compile with coverage profiling instrumentation (gcc only) --enable-gtk-doc use gtk-doc to build documentation [[default=no]] --enable-gtk-doc-html build documentation in html format [[default=yes]] --enable-gtk-doc-pdf build documentation in pdf format [[default=no]] Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot=DIR Search for dependent libraries within DIR (or the compiler's sysroot if not specified). --with-installed-headers=DIR install development headers to DIR [default=nowhere] --with-tls=BACKEND which TLS backend to use (gnutls, openssl, or auto) [default=auto] --with-ca-certificates=[path] path to system Certificate Authority list --with-html-dir=PATH path to installed docs Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a nonstandard directory <lib dir> LIBS libraries to pass to the linker, e.g. -l<library> CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if you have headers in a nonstandard directory <include dir> CPP C preprocessor CCAS assembler compiler command (defaults to CC) CCASFLAGS assembler compiler flags (defaults to CFLAGS) PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path GLIB_CFLAGS C compiler flags for GLIB, overriding pkg-config GLIB_LIBS linker flags for GLIB, overriding pkg-config TLS_CFLAGS C compiler flags for TLS, overriding pkg-config TLS_LIBS linker flags for TLS, overriding pkg-config GNUTLS_FOR_STREAM_CIPHERS_CFLAGS C compiler flags for GNUTLS_FOR_STREAM_CIPHERS, overriding pkg-config GNUTLS_FOR_STREAM_CIPHERS_LIBS linker flags for GNUTLS_FOR_STREAM_CIPHERS, overriding pkg-config LIBXML2_CFLAGS C compiler flags for LIBXML2, overriding pkg-config LIBXML2_LIBS linker flags for LIBXML2, overriding pkg-config SQLITE_CFLAGS C compiler flags for SQLITE, overriding pkg-config SQLITE_LIBS linker flags for SQLITE, overriding pkg-config LIBIPHB_CFLAGS C compiler flags for LIBIPHB, overriding pkg-config LIBIPHB_LIBS linker flags for LIBIPHB, overriding pkg-config SOUP_CFLAGS C compiler flags for SOUP, overriding pkg-config SOUP_LIBS linker flags for SOUP, overriding pkg-config GTKDOC_DEPS_CFLAGS C compiler flags for GTKDOC_DEPS, overriding pkg-config GTKDOC_DEPS_LIBS linker flags for GTKDOC_DEPS, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF Wocky configure 0.0.0.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case <limits.h> declares $2. For example, HP-UX 11i <limits.h> declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer <limits.h> to <assert.h> if __STDC__ is defined, since <limits.h> exists even on freestanding compilers. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by Wocky $as_me 0.0.0.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi as_fn_append ac_header_list " unistd.h" # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu am__api_version='1.13' 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 elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # 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 # AmigaOS /C/install, which installs bootblocks on floppy discs # 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" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /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 for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir 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. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&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}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # 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 ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $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". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file 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" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='wocky' VERSION='0.0.0.1' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> # <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> mkdir_p='$(MKDIR_P)' # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar plaintar pax cpio none' # The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether UID '$am_uid' is supported by ustar format" >&5 $as_echo_n "checking whether UID '$am_uid' is supported by ustar format... " >&6; } if test $am_uid -le $am_max_uid; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } _am_tools=none fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GID '$am_gid' is supported by ustar format" >&5 $as_echo_n "checking whether GID '$am_gid' is supported by ustar format... " >&6; } if test $am_gid -le $am_max_gid; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } _am_tools=none fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a ustar tar archive" >&5 $as_echo_n "checking how to create a ustar tar archive... " >&6; } # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_ustar-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do { echo "$as_me:$LINENO: $_am_tar --version" >&5 ($_am_tar --version) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && break done am__tar="$_am_tar --format=ustar -chf - "'"$$tardir"' am__tar_="$_am_tar --format=ustar -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x ustar -w "$$tardir"' am__tar_='pax -L -x ustar -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H ustar -L' am__tar_='find "$tardir" -print | cpio -o -H ustar -L' am__untar='cpio -i -H ustar -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_ustar}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5 (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } rm -rf conftest.dir if test -s conftest.tar; then { echo "$as_me:$LINENO: $am__untar <conftest.tar" >&5 ($am__untar <conftest.tar) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { echo "$as_me:$LINENO: cat conftest.dir/file" >&5 (cat conftest.dir/file) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } grep GrepMe conftest.dir/file >/dev/null 2>&1 && break fi done rm -rf conftest.dir if ${am_cv_prog_tar_ustar+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_prog_tar_ustar=$_am_tool fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_ustar" >&5 $as_echo "$am_cv_prog_tar_ustar" >&6; } case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.2' macro_revision='1.3337' ltmain="$ac_aux_dir/ltmain.sh" # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case "$ECHO" in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_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 $# != 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 ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdio.h> int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdarg.h> #include <stdio.h> struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in *GNU* | *'with BFD'*) test "$with_gnu_ld" != no && break ;; *) test "$with_gnu_ld" != yes && break ;; esac fi done IFS="$lt_save_ifs" else lt_cv_path_LD="$LD" # Let the user override the test with a path. fi fi LD="$lt_cv_path_LD" if test -n "$LD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 </dev/null` in *GNU* | *'with BFD'*) lt_cv_prog_gnu_ld=yes ;; *) lt_cv_prog_gnu_ld=no ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n $lt_cv_sys_max_cmd_len ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 $as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 $as_echo "$xsi_shell" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 $as_echo_n "checking whether the shell understands \"+=\"... " >&6; } lt_shell_append=no ( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 $as_echo "$lt_shell_append" >&6; } if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test "$GCC" != yes; then reload_cmds=false fi ;; darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} : ${AR_FLAGS=cru} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 $as_echo "${with_sysroot}" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD="${LD-ld}_sol2" fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR cru libconftest.a conftest.o" >&5 $AR cru libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[012]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since # <limits.h> exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <ac_nonexistent.h> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since # <limits.h> exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include <limits.h> #else # include <assert.h> #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <ac_nonexistent.h> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <float.h> int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <string.h> _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdlib.h> _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <ctype.h> #include <stdlib.h> #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done # Set options enable_dlopen=no enable_win32_dll=no # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac else enable_shared=yes fi # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for lt_pkg in $withval; do IFS="$lt_save_ifs" if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS="$lt_save_ifs" ;; esac else pic_mode=default fi test -z "$pic_mode" && pic_mode=default # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac else enable_fast_install=yes fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' if test -n "$lt_prog_compiler_pic"; then lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ F* | *Sun*Fortran*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Intel*\ [CF]*Compiler*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; *Portland\ Group*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test x"$lt_cv_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach <jrb3@best.com> says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='${wl}--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' link_all_deplibs=yes ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi export_dynamic_flag_spec='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test "$lt_cv_ld_force_load" = "yes"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test x"$lt_cv_prog_compiler__b" = xyes; then archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_irix_exported_symbol=yes else lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test "$lt_cv_irix_exported_symbol" = yes; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='${wl}-z,text' allow_undefined_flag='${wl}-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='${wl}-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test "$ld_shlibs" = no && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([A-Za-z]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib<name>.so # instead of lib<name>.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Add ABI-specific directories to the system library path. sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test "$hardcode_action" = relink || test "$inherit_rpath" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen="shl_load" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen="dlopen" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include <dlfcn.h> #endif #include <stdio.h> #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include <dlfcn.h> #endif #include <stdio.h> #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report which library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" ac_config_commands="$ac_config_commands libtool" # Only expand once: ac_config_headers="$ac_config_headers config.h" # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_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 $# != 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 ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdarg.h> #include <stdio.h> struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi case $ac_cv_prog_cc_stdc in #( no) : ac_cv_prog_cc_c99=no; ac_cv_prog_cc_c89=no ;; #( *) : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 $as_echo_n "checking for $CC option to accept ISO C99... " >&6; } if ${ac_cv_prog_cc_c99+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdarg.h> #include <stdbool.h> #include <stdlib.h> #include <wchar.h> #include <stdio.h> // Check varargs macros. These examples are taken from C99 6.10.3.5. #define debug(...) fprintf (stderr, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK your preprocessor is broken; #endif #if BIG_OK #else your preprocessor is broken; #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // See if C++-style comments work. // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\0'; ++i) continue; return 0; } // Check varargs and va_copy. static void test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str; int number; float fnumber; while (*format) { switch (*format++) { case 's': // string str = va_arg (args_copy, const char *); break; case 'd': // int number = va_arg (args_copy, int); break; case 'f': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); } int main () { // Check bool. _Bool success = false; // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. test_varargs ("s, d' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' || dynamic_array[ni.number - 1] != 543); ; return 0; } _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c99" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c99" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 $as_echo "$ac_cv_prog_cc_c99" >&6; } ;; esac if test "x$ac_cv_prog_cc_c99" != xno; then : ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdarg.h> #include <stdio.h> struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 else ac_cv_prog_cc_stdc=no fi fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO Standard C" >&5 $as_echo_n "checking for $CC option to accept ISO Standard C... " >&6; } if ${ac_cv_prog_cc_stdc+:} false; then : $as_echo_n "(cached) " >&6 fi case $ac_cv_prog_cc_stdc in #( no) : { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; #( '') : { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; #( *) : { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_stdc" >&5 $as_echo "$ac_cv_prog_cc_stdc" >&6; } ;; esac # By default we simply use the C compiler to build assembly code. test "${CCAS+set}" = set || CCAS=$CC test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS depcc="$CCAS" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CCAS_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CCAS_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CCAS_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CCAS_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CCAS_dependencies_compiler_type" >&5 $as_echo "$am_cv_CCAS_dependencies_compiler_type" >&6; } CCASDEPMODE=depmode=$am_cv_CCAS_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CCAS_dependencies_compiler_type" = gcc3; then am__fastdepCCAS_TRUE= am__fastdepCCAS_FALSE='#' else am__fastdepCCAS_TRUE='#' am__fastdepCCAS_FALSE= fi mkdir_p="$MKDIR_P" case $mkdir_p in [\\/$]* | ?:[\\/]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac official_release=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands " >&5 $as_echo_n "checking to see if compiler understands ... " >&6; } save_CFLAGS="$CFLAGS" save_CXXFLAGS="$CXXFLAGS" CFLAGS="$CFLAGS " CXXFLAGS="$CXXFLAGS " cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : flag_ok=yes else flag_ok=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" CXXFLAGS="$save_CXXFLAGS" if test "X$flag_ok" = Xyes ; then true else true fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 $as_echo "$flag_ok" >&6; } tp_warnings="" for tp_flag in all \ extra \ declaration-after-statement \ shadow \ strict-prototypes \ missing-prototypes \ sign-compare \ nested-externs \ pointer-arith \ format-security \ init-self; do { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -W$tp_flag" >&5 $as_echo_n "checking to see if compiler understands -W$tp_flag... " >&6; } save_CFLAGS="$CFLAGS" save_CXXFLAGS="$CXXFLAGS" CFLAGS="$CFLAGS -W$tp_flag" CXXFLAGS="$CXXFLAGS -W$tp_flag" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : flag_ok=yes else flag_ok=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" CXXFLAGS="$save_CXXFLAGS" if test "X$flag_ok" = Xyes ; then tp_warnings="$tp_warnings -W$tp_flag" true else true fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 $as_echo "$flag_ok" >&6; } done tp_error_flags="-Werror" { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror" >&5 $as_echo_n "checking to see if compiler understands -Werror... " >&6; } save_CFLAGS="$CFLAGS" save_CXXFLAGS="$CXXFLAGS" CFLAGS="$CFLAGS -Werror" CXXFLAGS="$CXXFLAGS -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : flag_ok=yes else flag_ok=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" CXXFLAGS="$save_CXXFLAGS" if test "X$flag_ok" = Xyes ; then tp_werror=yes true else tp_werror=no true fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 $as_echo "$flag_ok" >&6; } for tp_flag in missing-field-initializers \ unused-parameter; do { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Wno-$tp_flag" >&5 $as_echo_n "checking to see if compiler understands -Wno-$tp_flag... " >&6; } save_CFLAGS="$CFLAGS" save_CXXFLAGS="$CXXFLAGS" CFLAGS="$CFLAGS -Wno-$tp_flag" CXXFLAGS="$CXXFLAGS -Wno-$tp_flag" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : flag_ok=yes else flag_ok=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" CXXFLAGS="$save_CXXFLAGS" if test "X$flag_ok" = Xyes ; then tp_warnings="$tp_warnings -Wno-$tp_flag" true else true fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 $as_echo "$flag_ok" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Wno-error=$tp_flag" >&5 $as_echo_n "checking to see if compiler understands -Wno-error=$tp_flag... " >&6; } save_CFLAGS="$CFLAGS" save_CXXFLAGS="$CXXFLAGS" CFLAGS="$CFLAGS -Wno-error=$tp_flag" CXXFLAGS="$CXXFLAGS -Wno-error=$tp_flag" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : flag_ok=yes else flag_ok=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" CXXFLAGS="$save_CXXFLAGS" if test "X$flag_ok" = Xyes ; then tp_error_flags="$tp_error_flags -Wno-error=$tp_flag" true else tp_werror=no true fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 $as_echo "$flag_ok" >&6; } done # Check whether --enable-Werror was given. if test "${enable_Werror+set}" = set; then : enableval=$enable_Werror; tp_werror=$enableval else : fi if test "x$tp_werror" = xyes && test "x$official_release" = xno; then ERROR_CFLAGS="$tp_warnings $tp_error_flags" else ERROR_CFLAGS="$tp_warnings" fi # Wocky is version x.y.z.1 - enable coding style checks by default # Check whether --enable-coding-style-checks was given. if test "${enable_coding_style_checks+set}" = set; then : enableval=$enable_coding_style_checks; ENABLE_CODING_STYLE_CHECKS=$enableval else ENABLE_CODING_STYLE_CHECKS=yes fi # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then : enableval=$enable_debug; case "${enableval}" in yes|no) enable_debug="${enableval}" ;; *) as_fn_error $? "bad value ${enableval} for --enable-debug" "$LINENO" 5 ;; esac else enable_debug=yes fi if test "$enable_debug" = yes; then $as_echo "#define ENABLE_DEBUG /**/" >>confdefs.h else enable_debug=no fi # Check whether --with-installed-headers was given. if test "${with_installed_headers+set}" = set; then : withval=$with_installed_headers; else with_installed_headers= fi if test x$with_installed_headers != x; then INSTALL_HEADERS_TRUE= INSTALL_HEADERS_FALSE='#' else INSTALL_HEADERS_TRUE='#' INSTALL_HEADERS_FALSE= fi HEADER_DIR=$with_installed_headers # Check whether --enable-shared-suffix was given. if test "${enable_shared_suffix+set}" = set; then : enableval=$enable_shared_suffix; else enable_shared_suffix= fi if test x$enable_shared_suffix != x; then ENABLE_SHARED_SUFFIX_TRUE= ENABLE_SHARED_SUFFIX_FALSE='#' else ENABLE_SHARED_SUFFIX_TRUE='#' ENABLE_SHARED_SUFFIX_FALSE= fi SHARED_SUFFIX="$enable_shared_suffix" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <float.h> int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <string.h> _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdlib.h> _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <ctype.h> #include <stdlib.h> #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi for ac_header in $ac_header_list do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 $as_echo_n "checking for inline... " >&6; } if ${ac_cv_c_inline+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 $as_echo "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 $as_echo_n "checking whether byte ordering is bigendian... " >&6; } if ${ac_cv_c_bigendian+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __APPLE_CC__ not a universal capable compiler #endif typedef int dummy; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. ac_arch= ac_prev= for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do if test -n "$ac_prev"; then case $ac_word in i?86 | x86_64 | ppc | ppc64) if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ac_arch=$ac_word else ac_cv_c_bigendian=universal break fi ;; esac ac_prev= elif test "x$ac_word" = "x-arch"; then ac_prev=arch fi done fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <sys/types.h> #include <sys/param.h> int main () { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <sys/types.h> #include <sys/param.h> int main () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <limits.h> int main () { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <limits.h> int main () { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # Compile a test program. if test "$cross_compiling" = yes; then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; int main () { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* Are we little or big endian? From Harbison&Steele. */ union { long int l; char c[sizeof (long int)]; } u; u.l = 1; return u.c[sizeof (long int) - 1] == 1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_bigendian=no else ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 $as_echo "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) as_fn_error $? "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 $as_echo "$ac_pt_PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 $as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } PKG_CONFIG="" fi fi pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB" >&5 $as_echo_n "checking for GLIB... " >&6; } if test -n "$GLIB_CFLAGS"; then pkg_cv_GLIB_CFLAGS="$GLIB_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.32, gobject-2.0 >= 2.32, gthread-2.0 >= 2.32, gio-2.0 >= 2.32\""; } >&5 ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.32, gobject-2.0 >= 2.32, gthread-2.0 >= 2.32, gio-2.0 >= 2.32") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GLIB_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 >= 2.32, gobject-2.0 >= 2.32, gthread-2.0 >= 2.32, gio-2.0 >= 2.32" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$GLIB_LIBS"; then pkg_cv_GLIB_LIBS="$GLIB_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.32, gobject-2.0 >= 2.32, gthread-2.0 >= 2.32, gio-2.0 >= 2.32\""; } >&5 ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.32, gobject-2.0 >= 2.32, gthread-2.0 >= 2.32, gio-2.0 >= 2.32") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GLIB_LIBS=`$PKG_CONFIG --libs "glib-2.0 >= 2.32, gobject-2.0 >= 2.32, gthread-2.0 >= 2.32, gio-2.0 >= 2.32" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0 >= 2.32, gobject-2.0 >= 2.32, gthread-2.0 >= 2.32, gio-2.0 >= 2.32" 2>&1` else GLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0 >= 2.32, gobject-2.0 >= 2.32, gthread-2.0 >= 2.32, gio-2.0 >= 2.32" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$GLIB_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (glib-2.0 >= 2.32, gobject-2.0 >= 2.32, gthread-2.0 >= 2.32, gio-2.0 >= 2.32) were not met: $GLIB_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables GLIB_CFLAGS and GLIB_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables GLIB_CFLAGS and GLIB_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see <http://pkg-config.freedesktop.org/>. See \`config.log' for more details" "$LINENO" 5; } else GLIB_CFLAGS=$pkg_cv_GLIB_CFLAGS GLIB_LIBS=$pkg_cv_GLIB_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi $as_echo "#define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_32" >>confdefs.h $as_echo "#define GLIB_VERSION_MAX_ALLOWED GLIB_VERSION_2_32" >>confdefs.h if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gio-2.0 >= 2.25.15\""; } >&5 ($PKG_CONFIG --exists --print-errors "gio-2.0 >= 2.25.15") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then HAVE_GIO_PROXY=yes $as_echo "#define HAVE_GIO_PROXY 1" >>confdefs.h else HAVE_GIO_PROXY=no fi if test "x${HAVE_GIO_PROXY}" = "xyes"; then HAVE_GIO_PROXY_TRUE= HAVE_GIO_PROXY_FALSE='#' else HAVE_GIO_PROXY_TRUE='#' HAVE_GIO_PROXY_FALSE= fi # Check whether --with-tls was given. if test "${with_tls+set}" = set; then : withval=$with_tls; else with_tls=auto fi case $with_tls in #( gnutls) : pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TLS" >&5 $as_echo_n "checking for TLS... " >&6; } if test -n "$TLS_CFLAGS"; then pkg_cv_TLS_CFLAGS="$TLS_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls >= 2.8.2 \""; } >&5 ($PKG_CONFIG --exists --print-errors "gnutls >= 2.8.2 ") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_TLS_CFLAGS=`$PKG_CONFIG --cflags "gnutls >= 2.8.2 " 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$TLS_LIBS"; then pkg_cv_TLS_LIBS="$TLS_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls >= 2.8.2 \""; } >&5 ($PKG_CONFIG --exists --print-errors "gnutls >= 2.8.2 ") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_TLS_LIBS=`$PKG_CONFIG --libs "gnutls >= 2.8.2 " 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then TLS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gnutls >= 2.8.2 " 2>&1` else TLS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gnutls >= 2.8.2 " 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$TLS_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (gnutls >= 2.8.2 ) were not met: $TLS_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables TLS_CFLAGS and TLS_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables TLS_CFLAGS and TLS_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see <http://pkg-config.freedesktop.org/>. See \`config.log' for more details" "$LINENO" 5; } else TLS_CFLAGS=$pkg_cv_TLS_CFLAGS TLS_LIBS=$pkg_cv_TLS_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi ;; #( openssl) : USING_OPENSSL=yes $as_echo "#define USING_OPENSSL 1" >>confdefs.h pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TLS" >&5 $as_echo_n "checking for TLS... " >&6; } if test -n "$TLS_CFLAGS"; then pkg_cv_TLS_CFLAGS="$TLS_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl >= 0.9.8g\""; } >&5 ($PKG_CONFIG --exists --print-errors "openssl >= 0.9.8g") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_TLS_CFLAGS=`$PKG_CONFIG --cflags "openssl >= 0.9.8g" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$TLS_LIBS"; then pkg_cv_TLS_LIBS="$TLS_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl >= 0.9.8g\""; } >&5 ($PKG_CONFIG --exists --print-errors "openssl >= 0.9.8g") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_TLS_LIBS=`$PKG_CONFIG --libs "openssl >= 0.9.8g" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then TLS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "openssl >= 0.9.8g" 2>&1` else TLS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "openssl >= 0.9.8g" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$TLS_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (openssl >= 0.9.8g) were not met: $TLS_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables TLS_CFLAGS and TLS_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables TLS_CFLAGS and TLS_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see <http://pkg-config.freedesktop.org/>. See \`config.log' for more details" "$LINENO" 5; } else TLS_CFLAGS=$pkg_cv_TLS_CFLAGS TLS_LIBS=$pkg_cv_TLS_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi ;; #( auto) : pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TLS" >&5 $as_echo_n "checking for TLS... " >&6; } if test -n "$TLS_CFLAGS"; then pkg_cv_TLS_CFLAGS="$TLS_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls >= 2.8.2 \""; } >&5 ($PKG_CONFIG --exists --print-errors "gnutls >= 2.8.2 ") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_TLS_CFLAGS=`$PKG_CONFIG --cflags "gnutls >= 2.8.2 " 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$TLS_LIBS"; then pkg_cv_TLS_LIBS="$TLS_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls >= 2.8.2 \""; } >&5 ($PKG_CONFIG --exists --print-errors "gnutls >= 2.8.2 ") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_TLS_LIBS=`$PKG_CONFIG --libs "gnutls >= 2.8.2 " 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then TLS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gnutls >= 2.8.2 " 2>&1` else TLS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gnutls >= 2.8.2 " 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$TLS_PKG_ERRORS" >&5 USING_OPENSSL=yes $as_echo "#define USING_OPENSSL 1" >>confdefs.h pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TLS" >&5 $as_echo_n "checking for TLS... " >&6; } if test -n "$TLS_CFLAGS"; then pkg_cv_TLS_CFLAGS="$TLS_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl >= 0.9.8g\""; } >&5 ($PKG_CONFIG --exists --print-errors "openssl >= 0.9.8g") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_TLS_CFLAGS=`$PKG_CONFIG --cflags "openssl >= 0.9.8g" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$TLS_LIBS"; then pkg_cv_TLS_LIBS="$TLS_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl >= 0.9.8g\""; } >&5 ($PKG_CONFIG --exists --print-errors "openssl >= 0.9.8g") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_TLS_LIBS=`$PKG_CONFIG --libs "openssl >= 0.9.8g" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then TLS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "openssl >= 0.9.8g" 2>&1` else TLS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "openssl >= 0.9.8g" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$TLS_PKG_ERRORS" >&5 as_fn_error $? "Neither gnutls nor openssl found" "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "Neither gnutls nor openssl found" "$LINENO" 5 else TLS_CFLAGS=$pkg_cv_TLS_CFLAGS TLS_LIBS=$pkg_cv_TLS_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } with_tls=openssl fi elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } USING_OPENSSL=yes $as_echo "#define USING_OPENSSL 1" >>confdefs.h pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TLS" >&5 $as_echo_n "checking for TLS... " >&6; } if test -n "$TLS_CFLAGS"; then pkg_cv_TLS_CFLAGS="$TLS_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl >= 0.9.8g\""; } >&5 ($PKG_CONFIG --exists --print-errors "openssl >= 0.9.8g") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_TLS_CFLAGS=`$PKG_CONFIG --cflags "openssl >= 0.9.8g" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$TLS_LIBS"; then pkg_cv_TLS_LIBS="$TLS_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl >= 0.9.8g\""; } >&5 ($PKG_CONFIG --exists --print-errors "openssl >= 0.9.8g") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_TLS_LIBS=`$PKG_CONFIG --libs "openssl >= 0.9.8g" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then TLS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "openssl >= 0.9.8g" 2>&1` else TLS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "openssl >= 0.9.8g" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$TLS_PKG_ERRORS" >&5 as_fn_error $? "Neither gnutls nor openssl found" "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "Neither gnutls nor openssl found" "$LINENO" 5 else TLS_CFLAGS=$pkg_cv_TLS_CFLAGS TLS_LIBS=$pkg_cv_TLS_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } with_tls=openssl fi else TLS_CFLAGS=$pkg_cv_TLS_CFLAGS TLS_LIBS=$pkg_cv_TLS_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } with_tls=gnutls fi ;; #( *) : as_fn_error $? "Must have a TLS backend (gnutls or openssl)" "$LINENO" 5 ;; #( *) : ;; esac if test x$USING_OPENSSL = xyes; then USING_OPENSSL_TRUE= USING_OPENSSL_FALSE='#' else USING_OPENSSL_TRUE='#' USING_OPENSSL_FALSE= fi # Check whether --enable-prefer-stream-ciphers was given. if test "${enable_prefer_stream_ciphers+set}" = set; then : enableval=$enable_prefer_stream_ciphers; prefer_stream_ciphers=$enableval else prefer_stream_ciphers=no fi if test x$prefer_stream_ciphers = xyes; then $as_echo "#define ENABLE_PREFER_STREAM_CIPHERS /**/" >>confdefs.h if test $with_tls = gnutls; then # The *-ALL priority strings require gnutls 2.12.0. # We do this check here and not earlier to avoid accidentally falling # back to openssl because of the use of --enable-prefer-stream-ciphers. pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNUTLS_FOR_STREAM_CIPHERS" >&5 $as_echo_n "checking for GNUTLS_FOR_STREAM_CIPHERS... " >&6; } if test -n "$GNUTLS_FOR_STREAM_CIPHERS_CFLAGS"; then pkg_cv_GNUTLS_FOR_STREAM_CIPHERS_CFLAGS="$GNUTLS_FOR_STREAM_CIPHERS_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls >= 2.12.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "gnutls >= 2.12.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GNUTLS_FOR_STREAM_CIPHERS_CFLAGS=`$PKG_CONFIG --cflags "gnutls >= 2.12.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$GNUTLS_FOR_STREAM_CIPHERS_LIBS"; then pkg_cv_GNUTLS_FOR_STREAM_CIPHERS_LIBS="$GNUTLS_FOR_STREAM_CIPHERS_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls >= 2.12.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "gnutls >= 2.12.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GNUTLS_FOR_STREAM_CIPHERS_LIBS=`$PKG_CONFIG --libs "gnutls >= 2.12.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then GNUTLS_FOR_STREAM_CIPHERS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gnutls >= 2.12.0" 2>&1` else GNUTLS_FOR_STREAM_CIPHERS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gnutls >= 2.12.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$GNUTLS_FOR_STREAM_CIPHERS_PKG_ERRORS" >&5 as_fn_error $? "gnutls 2.12.0 is needed to use --enable-prefer-stream-cihpers" "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "gnutls 2.12.0 is needed to use --enable-prefer-stream-cihpers" "$LINENO" 5 else GNUTLS_FOR_STREAM_CIPHERS_CFLAGS=$pkg_cv_GNUTLS_FOR_STREAM_CIPHERS_CFLAGS GNUTLS_FOR_STREAM_CIPHERS_LIBS=$pkg_cv_GNUTLS_FOR_STREAM_CIPHERS_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi fi fi # ----------------------------------------------------------- # Make CA certificates path configurable # Stolen from GIO's TLS # ----------------------------------------------------------- { $as_echo "$as_me:${as_lineno-$LINENO}: checking location of system Certificate Authority list" >&5 $as_echo_n "checking location of system Certificate Authority list... " >&6; } # Check whether --with-ca-certificates was given. if test "${with_ca_certificates+set}" = set; then : withval=$with_ca_certificates; fi if test "$with_ca_certificates" = "no"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 $as_echo "disabled" >&6; } else if test -z "$with_ca_certificates"; then for f in /etc/pki/tls/certs/ca-bundle.crt \ /etc/ssl/certs/ca-certificates.crt; do if test -f "$f"; then with_ca_certificates="$f" fi done if test -z "$with_ca_certificates"; then as_fn_error $? "could not find. Use --with-ca-certificates=path to set, or --without-ca-certificates to disable" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_ca_certificates" >&5 $as_echo "$with_ca_certificates" >&6; } cat >>confdefs.h <<_ACEOF #define GTLS_SYSTEM_CA_CERTIFICATES "$with_ca_certificates" _ACEOF fi if test -n "$with_ca_certificates"; then if ! test -f "$with_ca_certificates"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Specified certificate authority file '$with_ca_certificates' does not exist" >&5 $as_echo "$as_me: WARNING: Specified certificate authority file '$with_ca_certificates' does not exist" >&2;} fi fi GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0` pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBXML2" >&5 $as_echo_n "checking for LIBXML2... " >&6; } if test -n "$LIBXML2_CFLAGS"; then pkg_cv_LIBXML2_CFLAGS="$LIBXML2_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libxml-2.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "libxml-2.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBXML2_CFLAGS=`$PKG_CONFIG --cflags "libxml-2.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$LIBXML2_LIBS"; then pkg_cv_LIBXML2_LIBS="$LIBXML2_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libxml-2.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "libxml-2.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBXML2_LIBS=`$PKG_CONFIG --libs "libxml-2.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then LIBXML2_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libxml-2.0" 2>&1` else LIBXML2_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libxml-2.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBXML2_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (libxml-2.0) were not met: $LIBXML2_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables LIBXML2_CFLAGS and LIBXML2_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables LIBXML2_CFLAGS and LIBXML2_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see <http://pkg-config.freedesktop.org/>. See \`config.log' for more details" "$LINENO" 5; } else LIBXML2_CFLAGS=$pkg_cv_LIBXML2_CFLAGS LIBXML2_LIBS=$pkg_cv_LIBXML2_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLITE" >&5 $as_echo_n "checking for SQLITE... " >&6; } if test -n "$SQLITE_CFLAGS"; then pkg_cv_SQLITE_CFLAGS="$SQLITE_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sqlite3\""; } >&5 ($PKG_CONFIG --exists --print-errors "sqlite3") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_SQLITE_CFLAGS=`$PKG_CONFIG --cflags "sqlite3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$SQLITE_LIBS"; then pkg_cv_SQLITE_LIBS="$SQLITE_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sqlite3\""; } >&5 ($PKG_CONFIG --exists --print-errors "sqlite3") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_SQLITE_LIBS=`$PKG_CONFIG --libs "sqlite3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then SQLITE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "sqlite3" 2>&1` else SQLITE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "sqlite3" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$SQLITE_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (sqlite3) were not met: $SQLITE_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables SQLITE_CFLAGS and SQLITE_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables SQLITE_CFLAGS and SQLITE_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see <http://pkg-config.freedesktop.org/>. See \`config.log' for more details" "$LINENO" 5; } else SQLITE_CFLAGS=$pkg_cv_SQLITE_CFLAGS SQLITE_LIBS=$pkg_cv_SQLITE_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sasl_server_new in -lsasl2" >&5 $as_echo_n "checking for sasl_server_new in -lsasl2... " >&6; } if ${ac_cv_lib_sasl2_sasl_server_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsasl2 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char sasl_server_new (); int main () { return sasl_server_new (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_sasl2_sasl_server_new=yes else ac_cv_lib_sasl2_sasl_server_new=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sasl2_sasl_server_new" >&5 $as_echo "$ac_cv_lib_sasl2_sasl_server_new" >&6; } if test "x$ac_cv_lib_sasl2_sasl_server_new" = xyes; then : ac_fn_c_check_header_mongrel "$LINENO" "sasl/sasl.h" "ac_cv_header_sasl_sasl_h" "$ac_includes_default" if test "x$ac_cv_header_sasl_sasl_h" = xyes; then : LIBSASL2_LIBS="-lsasl2" LIBSASL2_CFLAGS="" HAVE_LIBSASL2=yes $as_echo "#define HAVE_LIBSASL2 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libsasl2 headers missing: skipping sasl tests" >&5 $as_echo "$as_me: WARNING: libsasl2 headers missing: skipping sasl tests" >&2;} fi else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libsasl2 not found: skipping sasl tests" >&5 $as_echo "$as_me: WARNING: libsasl2 not found: skipping sasl tests" >&2;} HAVE_LIBSASL2=no fi if test "x$HAVE_LIBSASL2" = "xyes"; then HAVE_LIBSASL2_TRUE= HAVE_LIBSASL2_FALSE='#' else HAVE_LIBSASL2_TRUE='#' HAVE_LIBSASL2_FALSE= fi pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBIPHB" >&5 $as_echo_n "checking for LIBIPHB... " >&6; } if test -n "$LIBIPHB_CFLAGS"; then pkg_cv_LIBIPHB_CFLAGS="$LIBIPHB_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libiphb >= 0.61.31\""; } >&5 ($PKG_CONFIG --exists --print-errors "libiphb >= 0.61.31") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBIPHB_CFLAGS=`$PKG_CONFIG --cflags "libiphb >= 0.61.31" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$LIBIPHB_LIBS"; then pkg_cv_LIBIPHB_LIBS="$LIBIPHB_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libiphb >= 0.61.31\""; } >&5 ($PKG_CONFIG --exists --print-errors "libiphb >= 0.61.31") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBIPHB_LIBS=`$PKG_CONFIG --libs "libiphb >= 0.61.31" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then LIBIPHB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libiphb >= 0.61.31" 2>&1` else LIBIPHB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libiphb >= 0.61.31" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBIPHB_PKG_ERRORS" >&5 have_iphb=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } have_iphb=no else LIBIPHB_CFLAGS=$pkg_cv_LIBIPHB_CFLAGS LIBIPHB_LIBS=$pkg_cv_LIBIPHB_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_IPHB 1" >>confdefs.h have_iphb=yes fi # Check whether --enable-google-relay was given. if test "${enable_google_relay+set}" = set; then : enableval=$enable_google_relay; enable_google_relay=$enableval else enable_google_relay=yes fi if test x$enable_google_relay = xyes; then $as_echo "#define ENABLE_GOOGLE_RELAY /**/" >>confdefs.h pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SOUP" >&5 $as_echo_n "checking for SOUP... " >&6; } if test -n "$SOUP_CFLAGS"; then pkg_cv_SOUP_CFLAGS="$SOUP_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsoup-2.4\""; } >&5 ($PKG_CONFIG --exists --print-errors "libsoup-2.4") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_SOUP_CFLAGS=`$PKG_CONFIG --cflags "libsoup-2.4" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$SOUP_LIBS"; then pkg_cv_SOUP_LIBS="$SOUP_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libsoup-2.4\""; } >&5 ($PKG_CONFIG --exists --print-errors "libsoup-2.4") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_SOUP_LIBS=`$PKG_CONFIG --libs "libsoup-2.4" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then SOUP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libsoup-2.4" 2>&1` else SOUP_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libsoup-2.4" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$SOUP_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (libsoup-2.4) were not met: $SOUP_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables SOUP_CFLAGS and SOUP_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables SOUP_CFLAGS and SOUP_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see <http://pkg-config.freedesktop.org/>. See \`config.log' for more details" "$LINENO" 5; } else SOUP_CFLAGS=$pkg_cv_SOUP_CFLAGS SOUP_LIBS=$pkg_cv_SOUP_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi fi if test "x$enable_google_relay" = xyes; then ENABLE_GOOGLE_RELAY_TRUE= ENABLE_GOOGLE_RELAY_FALSE='#' else ENABLE_GOOGLE_RELAY_TRUE='#' ENABLE_GOOGLE_RELAY_FALSE= fi # Check whether --enable-coverage was given. if test "${enable_coverage+set}" = set; then : enableval=$enable_coverage; case "${enableval}" in "yes"|"no") enable_coverage="${enableval}" ;; *) as_fn_error $? "bad value ${enableval} for --enable-coverage" "$LINENO" 5 ;; esac fi enable=${enable_coverage} GCOV=`echo $CC | sed s/gcc/gcov/g` # Extract the first word of "$GCOV", so it can be a program name with args. set dummy $GCOV; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_have_gcov+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$have_gcov"; then ac_cv_prog_have_gcov="$have_gcov" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_have_gcov="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_have_gcov" && ac_cv_prog_have_gcov="no" fi fi have_gcov=$ac_cv_prog_have_gcov if test -n "$have_gcov"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_gcov" >&5 $as_echo "$have_gcov" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands \"-fprofile-arcs\"" >&5 $as_echo_n "checking to see if compiler understands \"-fprofile-arcs\"... " >&6; } save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS "-fprofile-arcs"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : flag_ok=yes else flag_ok=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" if test "X$flag_ok" = Xyes ; then flag_profile_arcs=yes true else flag_profile_arcs=no true fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 $as_echo "$flag_ok" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands \"-ftest-coverage\"" >&5 $as_echo_n "checking to see if compiler understands \"-ftest-coverage\"... " >&6; } save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS "-ftest-coverage"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : flag_ok=yes else flag_ok=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" if test "X$flag_ok" = Xyes ; then flag_test_coverage=yes true else flag_test_coverage=no true fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 $as_echo "$flag_ok" >&6; } if test "x$enable" = xyes && test "x$GCC" = "xyes" && test "$flag_profile_arcs" = yes && test "$flag_test_coverage" = yes ; then GCOV_CFLAGS="$GCOV_CFLAGS -fprofile-arcs -ftest-coverage" GCOV_CFLAGS=`echo "$GCOV_CFLAGS" | sed -e 's/-O[0-9]*//g'` GCOV_LIBS=-lgcov MOSTLYCLEANFILES="*.bb *.bbg *.da *.gcov *.gcda *.gcno" cat >>confdefs.h <<_ACEOF #define HAVE_GCOV 1 _ACEOF CFLAGS="-O0" CXXFLAGS="-O0" FFLAGS="-O0" CCASFLAGS="-O0" { $as_echo "$as_me:${as_lineno-$LINENO}: gcov enabled, setting CFLAGS and friends to $CFLAGS" >&5 $as_echo "$as_me: gcov enabled, setting CFLAGS and friends to $CFLAGS" >&6;} fi if test x$have_gcov = xyes; then HAVE_GCOV_TRUE= HAVE_GCOV_FALSE='#' else HAVE_GCOV_TRUE='#' HAVE_GCOV_FALSE= fi enable=${enable_coverage} for ac_prog in lcov do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LCOV_PATH+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LCOV_PATH"; then ac_cv_prog_LCOV_PATH="$LCOV_PATH" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LCOV_PATH="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LCOV_PATH=$ac_cv_prog_LCOV_PATH if test -n "$LCOV_PATH"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LCOV_PATH" >&5 $as_echo "$LCOV_PATH" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$LCOV_PATH" && break done if test -n "$LCOV_PATH" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether lcov accepts --compat-libtool" >&5 $as_echo_n "checking whether lcov accepts --compat-libtool... " >&6; } if $LCOV_PATH --compat-libtool --help > /dev/null 2>&1 ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: lcov option --compat-libtool is not supported" >&5 $as_echo "$as_me: WARNING: lcov option --compat-libtool is not supported" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: update lcov to version > 1.5" >&5 $as_echo "$as_me: WARNING: update lcov to version > 1.5" >&2;} LCOV_PATH="" fi fi if test -n "$LCOV_PATH" && test "x$enable" = xyes; then HAVE_LCOV_TRUE= HAVE_LCOV_FALSE='#' else HAVE_LCOV_TRUE='#' HAVE_LCOV_FALSE= fi if test "x$enable_coverage" = "x"; then enable_coverage=no fi WOCKY_CFLAGS='-I${top_builddir} -I${top_srcdir}' # Extract the first word of "gtkdoc-check", so it can be a program name with args. set dummy gtkdoc-check; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_GTKDOC_CHECK+:} false; then : $as_echo_n "(cached) " >&6 else case $GTKDOC_CHECK in [\\/]* | ?:[\\/]*) ac_cv_path_GTKDOC_CHECK="$GTKDOC_CHECK" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_GTKDOC_CHECK="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi GTKDOC_CHECK=$ac_cv_path_GTKDOC_CHECK if test -n "$GTKDOC_CHECK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_CHECK" >&5 $as_echo "$GTKDOC_CHECK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi for ac_prog in gtkdoc-rebase do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_GTKDOC_REBASE+:} false; then : $as_echo_n "(cached) " >&6 else case $GTKDOC_REBASE in [\\/]* | ?:[\\/]*) ac_cv_path_GTKDOC_REBASE="$GTKDOC_REBASE" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_GTKDOC_REBASE="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi GTKDOC_REBASE=$ac_cv_path_GTKDOC_REBASE if test -n "$GTKDOC_REBASE"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_REBASE" >&5 $as_echo "$GTKDOC_REBASE" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$GTKDOC_REBASE" && break done test -n "$GTKDOC_REBASE" || GTKDOC_REBASE="true" # Extract the first word of "gtkdoc-mkpdf", so it can be a program name with args. set dummy gtkdoc-mkpdf; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_GTKDOC_MKPDF+:} false; then : $as_echo_n "(cached) " >&6 else case $GTKDOC_MKPDF in [\\/]* | ?:[\\/]*) ac_cv_path_GTKDOC_MKPDF="$GTKDOC_MKPDF" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_GTKDOC_MKPDF="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi GTKDOC_MKPDF=$ac_cv_path_GTKDOC_MKPDF if test -n "$GTKDOC_MKPDF"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_MKPDF" >&5 $as_echo "$GTKDOC_MKPDF" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Check whether --with-html-dir was given. if test "${with_html_dir+set}" = set; then : withval=$with_html_dir; else with_html_dir='${datadir}/gtk-doc/html' fi HTML_DIR="$with_html_dir" # Check whether --enable-gtk-doc was given. if test "${enable_gtk_doc+set}" = set; then : enableval=$enable_gtk_doc; else enable_gtk_doc=no fi if test x$enable_gtk_doc = xyes; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk-doc >= 1.17\""; } >&5 ($PKG_CONFIG --exists --print-errors "gtk-doc >= 1.17") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : else as_fn_error $? "You need to have gtk-doc >= 1.17 installed to build $PACKAGE_NAME" "$LINENO" 5 fi if test "x$PACKAGE_NAME" != "xglib"; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTKDOC_DEPS" >&5 $as_echo_n "checking for GTKDOC_DEPS... " >&6; } if test -n "$GTKDOC_DEPS_CFLAGS"; then pkg_cv_GTKDOC_DEPS_CFLAGS="$GTKDOC_DEPS_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GTKDOC_DEPS_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$GTKDOC_DEPS_LIBS"; then pkg_cv_GTKDOC_DEPS_LIBS="$GTKDOC_DEPS_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GTKDOC_DEPS_LIBS=`$PKG_CONFIG --libs "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then GTKDOC_DEPS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>&1` else GTKDOC_DEPS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$GTKDOC_DEPS_PKG_ERRORS" >&5 : elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } : else GTKDOC_DEPS_CFLAGS=$pkg_cv_GTKDOC_DEPS_CFLAGS GTKDOC_DEPS_LIBS=$pkg_cv_GTKDOC_DEPS_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build gtk-doc documentation" >&5 $as_echo_n "checking whether to build gtk-doc documentation... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_gtk_doc" >&5 $as_echo "$enable_gtk_doc" >&6; } # Check whether --enable-gtk-doc-html was given. if test "${enable_gtk_doc_html+set}" = set; then : enableval=$enable_gtk_doc_html; else enable_gtk_doc_html=yes fi # Check whether --enable-gtk-doc-pdf was given. if test "${enable_gtk_doc_pdf+set}" = set; then : enableval=$enable_gtk_doc_pdf; else enable_gtk_doc_pdf=no fi if test -z "$GTKDOC_MKPDF"; then enable_gtk_doc_pdf=no fi if test -z "$AM_DEFAULT_VERBOSITY"; then AM_DEFAULT_VERBOSITY=1 fi if test x$enable_gtk_doc = xyes; then ENABLE_GTK_DOC_TRUE= ENABLE_GTK_DOC_FALSE='#' else ENABLE_GTK_DOC_TRUE='#' ENABLE_GTK_DOC_FALSE= fi if test x$enable_gtk_doc_html = xyes; then GTK_DOC_BUILD_HTML_TRUE= GTK_DOC_BUILD_HTML_FALSE='#' else GTK_DOC_BUILD_HTML_TRUE='#' GTK_DOC_BUILD_HTML_FALSE= fi if test x$enable_gtk_doc_pdf = xyes; then GTK_DOC_BUILD_PDF_TRUE= GTK_DOC_BUILD_PDF_FALSE='#' else GTK_DOC_BUILD_PDF_TRUE='#' GTK_DOC_BUILD_PDF_FALSE= fi if test -n "$LIBTOOL"; then GTK_DOC_USE_LIBTOOL_TRUE= GTK_DOC_USE_LIBTOOL_FALSE='#' else GTK_DOC_USE_LIBTOOL_TRUE='#' GTK_DOC_USE_LIBTOOL_FALSE= fi if test -n "$GTKDOC_REBASE"; then GTK_DOC_USE_REBASE_TRUE= GTK_DOC_USE_REBASE_FALSE='#' else GTK_DOC_USE_REBASE_TRUE='#' GTK_DOC_USE_REBASE_FALSE= fi ac_config_files="$ac_config_files Makefile wocky/Makefile wocky/wocky-uninstalled.pc wocky/wocky.pc m4/Makefile tools/Makefile examples/Makefile tests/Makefile docs/Makefile docs/reference/Makefile" cat >confcache <<\_ACEOF # 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, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # 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. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCCAS_TRUE}" && test -z "${am__fastdepCCAS_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCCAS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${INSTALL_HEADERS_TRUE}" && test -z "${INSTALL_HEADERS_FALSE}"; then as_fn_error $? "conditional \"INSTALL_HEADERS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_SHARED_SUFFIX_TRUE}" && test -z "${ENABLE_SHARED_SUFFIX_FALSE}"; then as_fn_error $? "conditional \"ENABLE_SHARED_SUFFIX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_GIO_PROXY_TRUE}" && test -z "${HAVE_GIO_PROXY_FALSE}"; then as_fn_error $? "conditional \"HAVE_GIO_PROXY\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USING_OPENSSL_TRUE}" && test -z "${USING_OPENSSL_FALSE}"; then as_fn_error $? "conditional \"USING_OPENSSL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_LIBSASL2_TRUE}" && test -z "${HAVE_LIBSASL2_FALSE}"; then as_fn_error $? "conditional \"HAVE_LIBSASL2\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_GOOGLE_RELAY_TRUE}" && test -z "${ENABLE_GOOGLE_RELAY_FALSE}"; then as_fn_error $? "conditional \"ENABLE_GOOGLE_RELAY\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_GCOV_TRUE}" && test -z "${HAVE_GCOV_FALSE}"; then as_fn_error $? "conditional \"HAVE_GCOV\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_LCOV_TRUE}" && test -z "${HAVE_LCOV_FALSE}"; then as_fn_error $? "conditional \"HAVE_LCOV\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_GTK_DOC_TRUE}" && test -z "${ENABLE_GTK_DOC_FALSE}"; then as_fn_error $? "conditional \"ENABLE_GTK_DOC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${GTK_DOC_BUILD_HTML_TRUE}" && test -z "${GTK_DOC_BUILD_HTML_FALSE}"; then as_fn_error $? "conditional \"GTK_DOC_BUILD_HTML\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${GTK_DOC_BUILD_PDF_TRUE}" && test -z "${GTK_DOC_BUILD_PDF_FALSE}"; then as_fn_error $? "conditional \"GTK_DOC_BUILD_PDF\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${GTK_DOC_USE_LIBTOOL_TRUE}" && test -z "${GTK_DOC_USE_LIBTOOL_FALSE}"; then as_fn_error $? "conditional \"GTK_DOC_USE_LIBTOOL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${GTK_DOC_USE_REBASE_TRUE}" && test -z "${GTK_DOC_USE_REBASE_FALSE}"; then as_fn_error $? "conditional \"GTK_DOC_USE_REBASE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by Wocky $as_me 0.0.0.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ Wocky config.status 0.0.0.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in SHELL \ ECHO \ PATH_SEPARATOR \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ nm_file_list_spec \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ sys_lib_dlsearch_path_spec; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' xsi_shell='$xsi_shell' lt_shell_append='$lt_shell_append' # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "wocky/Makefile") CONFIG_FILES="$CONFIG_FILES wocky/Makefile" ;; "wocky/wocky-uninstalled.pc") CONFIG_FILES="$CONFIG_FILES wocky/wocky-uninstalled.pc" ;; "wocky/wocky.pc") CONFIG_FILES="$CONFIG_FILES wocky/wocky.pc" ;; "m4/Makefile") CONFIG_FILES="$CONFIG_FILES m4/Makefile" ;; "tools/Makefile") CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;; "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;; "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; "docs/Makefile") CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;; "docs/reference/Makefile") CONFIG_FILES="$CONFIG_FILES docs/reference/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' <conf$$subs.awk | sed ' /^[^""]/{ N s/\n// } ' >>$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' <confdefs.h | sed ' s/'"$ac_delim"'/"\\\ "/g' >>$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; "libtool":C) # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool 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. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # The names of the tagged configurations supported by this script. available_tags="" # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The PATH separator for the build system. PATH_SEPARATOR=$lt_PATH_SEPARATOR # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # DLL creation program. DLLTOOL=$lt_DLLTOOL # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and in which our libraries should be installed. lt_sysroot=$lt_sysroot # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain="$ac_aux_dir/ltmain.sh" # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) if test x"$xsi_shell" = xyes; then sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ func_dirname ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ } # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_basename ()$/,/^} # func_basename /c\ func_basename ()\ {\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ func_dirname_and_basename ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ func_stripname ()\ {\ \ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ \ # positional parameters, so assign one to ordinary parameter first.\ \ func_stripname_result=${3}\ \ func_stripname_result=${func_stripname_result#"${1}"}\ \ func_stripname_result=${func_stripname_result%"${2}"}\ } # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ func_split_long_opt ()\ {\ \ func_split_long_opt_name=${1%%=*}\ \ func_split_long_opt_arg=${1#*=}\ } # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ func_split_short_opt ()\ {\ \ func_split_short_opt_arg=${1#??}\ \ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ } # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ func_lo2o ()\ {\ \ case ${1} in\ \ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ \ *) func_lo2o_result=${1} ;;\ \ esac\ } # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_xform ()$/,/^} # func_xform /c\ func_xform ()\ {\ func_xform_result=${1%.*}.lo\ } # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_arith ()$/,/^} # func_arith /c\ func_arith ()\ {\ func_arith_result=$(( $* ))\ } # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_len ()$/,/^} # func_len /c\ func_len ()\ {\ func_len_result=${#1}\ } # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$lt_shell_append" = xyes; then sed -e '/^func_append ()$/,/^} # func_append /c\ func_append ()\ {\ eval "${1}+=\\${2}"\ } # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ func_append_quoted ()\ {\ \ func_quote_for_eval "${2}"\ \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ } # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 $as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} fi mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi echo " Configure summary: Compiler Flags.......: ${CFLAGS} Prefix...............: ${prefix} Coverage profiling...: ${enable_coverage} Coding style checks..: ${ENABLE_CODING_STYLE_CHECKS} Debug................: ${enable_debug} Features: TLS Backend..........: ${with_tls} Prefer stream ciphers: ${prefer_stream_ciphers} System CA certs......: ${with_ca_certificates} SASL2 Tests..........: ${HAVE_LIBSASL2} gtk-doc documentation: ${enable_gtk_doc} libiphb integration..: ${have_iphb} Google relay support.: ${enable_google_relay} " �����������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/��������������������������������������������������������0000775�0001750�0001750�00000000000�12332445273�022047� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-session-test.c������������������������������������0000664�0001750�0001750�00000003300�12005516162�025772� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifdef HAVE_CONFIG_H #include "config.h" #endif #include <stdio.h> #include <unistd.h> #include <string.h> #include <glib.h> #include <wocky/wocky.h> #include "wocky-test-helper.h" static void test_instantiation (void) { WockyTestStream *stream; WockyXmppConnection *connection; WockySession *session; stream = g_object_new (WOCKY_TYPE_TEST_STREAM, NULL); connection = wocky_xmpp_connection_new (stream->stream0); session = wocky_session_new_with_connection (connection, "example.com"); g_assert (session != NULL); g_assert (WOCKY_IS_SESSION (session)); g_object_unref (stream); g_object_unref (connection); g_object_unref (session); } static void test_get_porter (void) { test_data_t *test = setup_test (); WockySession *session; WockyPorter *porter; session = wocky_session_new_with_connection (test->in, "example.com"); porter = wocky_session_get_porter (session); g_assert (WOCKY_IS_PORTER (porter)); g_object_unref (session); teardown_test (test); } static void test_get_contact_factory (void) { test_data_t *test = setup_test (); WockySession *session; WockyContactFactory *factory; session = wocky_session_new_with_connection (test->in, "example.com"); factory = wocky_session_get_contact_factory (session); g_assert (WOCKY_IS_CONTACT_FACTORY (factory)); g_object_unref (session); teardown_test (test); } int main (int argc, char **argv) { int result; test_init (argc, argv); g_test_add_func ("/session/instantiation", test_instantiation); g_test_add_func ("/session/get-porter", test_get_porter); g_test_add_func ("/session/get-contact-factory", test_get_contact_factory); result = g_test_run (); test_deinit (); return result; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-tls-test.c����������������������������������������0000664�0001750�0001750�00000022022�11720661341�025116� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> #include <unistd.h> #include <string.h> #include "config.h" #include <glib.h> #include <wocky/wocky.h> #include "wocky-test-stream.h" #include "wocky-test-helper.h" #define BUF_SIZE 8192 #define TEST_SSL_DATA_A "badgerbadgerbadger" #define TEST_SSL_DATA_B "mushroom, mushroom" #define TEST_SSL_DATA_LEN sizeof (TEST_SSL_DATA_A) static const gchar *test_data[] = { TEST_SSL_DATA_A, TEST_SSL_DATA_B, NULL }; typedef struct { test_data_t *test; char cli_buf[BUF_SIZE]; char srv_buf[BUF_SIZE]; char *cli_send; gsize cli_send_len; gsize cli_sent; WockyTLSConnection *client; WockyTLSConnection *server; GString *cli_data; GString *srv_data; guint read_op_count; guint write_op_count; gboolean in_read; } ssl_test_t; /* ************************************************************************ */ /* client callbacks */ static void client_write_cb (GObject *source, GAsyncResult *result, gpointer data) { GOutputStream *output = G_OUTPUT_STREAM (source); ssl_test_t *ssl_test = data; GError *error = NULL; gsize ret; ret = g_output_stream_write_finish (output, result, &error); g_assert_cmpint (ret, <=, ssl_test->cli_send_len - ssl_test->cli_sent); g_assert_no_error (error); ssl_test->cli_sent += ret; if (ssl_test->cli_sent == ssl_test->cli_send_len) { ssl_test->test->outstanding--; g_main_loop_quit (ssl_test->test->loop); return; } g_output_stream_write_async (output, ssl_test->cli_send + ssl_test->cli_sent, ssl_test->cli_send_len - ssl_test->cli_sent, G_PRIORITY_DEFAULT, ssl_test->test->cancellable, client_write_cb, data); } static void client_read_cb (GObject *source, GAsyncResult *result, gpointer data) { GInputStream *input = G_INPUT_STREAM (source); ssl_test_t *ssl_test = data; GError *error = NULL; gssize count = g_input_stream_read_finish (input, result, &error); g_assert (!ssl_test->in_read); g_assert_no_error (error); g_assert_cmpint (count, ==, TEST_SSL_DATA_LEN); ssl_test->read_op_count++; g_string_append_len (ssl_test->cli_data, ssl_test->cli_buf, count); switch (ssl_test->read_op_count) { case 1: /* we've read at least one ssl record at this point, combine the others */ wocky_test_stream_set_mode (ssl_test->test->stream->stream0_input, WOCK_TEST_STREAM_READ_COMBINE); break; case 2: #ifdef USING_OPENSSL /* Our openssl backend should have read all ssl records by now and * thus shouldn't request more data from the input stream. The GnuTLS * backend requests more granularily what it needs so will still read * from the input stream */ wocky_test_input_stream_set_read_error ( ssl_test->test->stream->stream0_input); #endif /* USING_OPENSSL */ break; case 3: case 4: break; case 5: { GIOStream *io = G_IO_STREAM (ssl_test->client); GOutputStream *output = g_io_stream_get_output_stream (io); g_output_stream_write_async (output, ssl_test->cli_send, ssl_test->cli_send_len, G_PRIORITY_DEFAULT, ssl_test->test->cancellable, client_write_cb, data); return; } default: g_error ("Read too many records: test broken?"); } ssl_test->in_read = TRUE; g_input_stream_read_async (input, ssl_test->cli_buf, BUF_SIZE, G_PRIORITY_DEFAULT, ssl_test->test->cancellable, client_read_cb, data); ssl_test->in_read = FALSE; } static void client_handshake_cb (GObject *source, GAsyncResult *result, gpointer data) { GInputStream *input; WockyTLSSession *session = WOCKY_TLS_SESSION (source); ssl_test_t *ssl_test = data; ssl_test->client = wocky_tls_session_handshake_finish (session, result, NULL); input = g_io_stream_get_input_stream (G_IO_STREAM (ssl_test->client)); ssl_test->in_read = TRUE; g_input_stream_read_async (input, ssl_test->cli_buf, BUF_SIZE, G_PRIORITY_DEFAULT, ssl_test->test->cancellable, client_read_cb, data); ssl_test->in_read = FALSE; } /* ************************************************************************ */ /* server callbacks */ static void server_read_cb (GObject *source, GAsyncResult *result, gpointer data) { GInputStream *input = G_INPUT_STREAM (source); ssl_test_t *ssl_test = data; gssize count = g_input_stream_read_finish (input, result, NULL); g_string_append_len (ssl_test->srv_data, ssl_test->srv_buf, count); if (ssl_test->srv_data->len < ssl_test->cli_send_len) { g_input_stream_read_async (input, ssl_test->srv_buf, BUF_SIZE, G_PRIORITY_DEFAULT, ssl_test->test->cancellable, server_read_cb, data); } else { ssl_test->test->outstanding--; g_main_loop_quit (ssl_test->test->loop); } } static void server_write_cb (GObject *source, GAsyncResult *result, gpointer data) { ssl_test_t *ssl_test = data; gsize written; GOutputStream *output = G_OUTPUT_STREAM (source); GIOStream *io = G_IO_STREAM (ssl_test->server); GInputStream *input = g_io_stream_get_input_stream (io); written = g_output_stream_write_finish (output, result, NULL); g_assert_cmpint (written, ==, TEST_SSL_DATA_LEN); ssl_test->write_op_count++; if (ssl_test->write_op_count < 5) { const char *payload = test_data[ssl_test->write_op_count & 1]; g_output_stream_write_async (output, payload, TEST_SSL_DATA_LEN, G_PRIORITY_LOW, ssl_test->test->cancellable, server_write_cb, data); } else { wocky_test_stream_cork (ssl_test->test->stream->stream0_input, FALSE); g_input_stream_read_async (input, ssl_test->srv_buf, BUF_SIZE, G_PRIORITY_DEFAULT, ssl_test->test->cancellable, server_read_cb, data); } } static void server_handshake_cb (GObject *source, GAsyncResult *result, gpointer data) { GOutputStream *output; WockyTLSSession *session = WOCKY_TLS_SESSION (source); ssl_test_t *ssl_test = data; GError *error = NULL; ssl_test->server = wocky_tls_session_handshake_finish (session, result, &error); g_assert_no_error (error); g_assert (ssl_test->server != NULL); output = g_io_stream_get_output_stream (G_IO_STREAM (ssl_test->server)); /* cork the client reading stream */ wocky_test_stream_cork (ssl_test->test->stream->stream0_input, TRUE); g_output_stream_write_async (output, TEST_SSL_DATA_A, TEST_SSL_DATA_LEN, G_PRIORITY_LOW, ssl_test->test->cancellable, server_write_cb, data); } /* ************************************************************************ */ /* test(s) */ static void setup_ssl_test (ssl_test_t *ssl_test, test_data_t *test) { guint x; /* the tests currently rely on all the chunks being the same size */ /* note that we include the terminating \0 in the payload */ for (x = 0; test_data[x] != NULL; x++) g_assert (strlen (test_data[x]) == (TEST_SSL_DATA_LEN - 1)); ssl_test->test = test; ssl_test->cli_data = g_string_new (""); ssl_test->srv_data = g_string_new (""); } static void teardown_ssl_test (ssl_test_t *ssl_test) { g_free (ssl_test->cli_send); g_string_free (ssl_test->cli_data, TRUE); g_string_free (ssl_test->srv_data, TRUE); g_io_stream_close (G_IO_STREAM (ssl_test->server), NULL, NULL); g_io_stream_close (G_IO_STREAM (ssl_test->client), NULL, NULL); g_object_unref (ssl_test->server); g_object_unref (ssl_test->client); } static void test_tls_handshake_rw (void) { ssl_test_t ssl_test = { NULL, } ; test_data_t *test = setup_test (); WockyTLSSession *client = wocky_tls_session_new (test->stream->stream0); WockyTLSSession *server = wocky_tls_session_server_new ( test->stream->stream1, 1024, TLS_SERVER_KEY_FILE, TLS_SERVER_CRT_FILE); gsize expected = TEST_SSL_DATA_LEN * 5; gchar *target = TEST_SSL_DATA_A "\0" TEST_SSL_DATA_B "\0" TEST_SSL_DATA_A "\0" TEST_SSL_DATA_B "\0" TEST_SSL_DATA_A; ssl_test.cli_send = g_malloc0 (32 * 1024); while (ssl_test.cli_send_len + 4 < 32 * 1024) { guint32 r = g_random_int (); memcpy (ssl_test.cli_send + ssl_test.cli_send_len, &r, 4); ssl_test.cli_send_len += 4; } setup_ssl_test (&ssl_test, test); wocky_tls_session_handshake_async (client, G_PRIORITY_DEFAULT, test->cancellable, client_handshake_cb, &ssl_test); test->outstanding += 1; wocky_tls_session_handshake_async (server, G_PRIORITY_DEFAULT, test->cancellable, server_handshake_cb, &ssl_test); test->outstanding += 1; test_wait_pending (test); g_assert_cmpint (test->outstanding, ==, 0); g_assert_cmpint (ssl_test.cli_data->len, ==, expected); g_assert_cmpint (ssl_test.srv_data->len, ==, ssl_test.cli_send_len); g_assert (!memcmp (ssl_test.cli_data->str, target, expected)); g_assert (!memcmp (ssl_test.srv_data->str, ssl_test.cli_send, ssl_test.cli_send_len)); teardown_test (test); teardown_ssl_test (&ssl_test); g_object_unref (client); g_object_unref (server); } int main (int argc, char **argv) { int result; test_init (argc, argv); g_test_add_func ("/tls/handshake+rw", test_tls_handshake_rw); result = g_test_run (); test_deinit (); return result; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-test-sasl-auth-server.h���������������������������0000664�0001750�0001750�00000006564�11720661341�027543� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * wocky-test-sasl-auth-server.h - Header for TestSaslAuthServer * Copyright (C) 2006 Collabora Ltd. * @author Sjoerd Simons <sjoerd@luon.net> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_SASL_AUTH_SERVER_H__ #define __TEST_SASL_AUTH_SERVER_H__ #include <glib-object.h> #include <gio/gio.h> #include <wocky/wocky.h> G_BEGIN_DECLS typedef enum { SERVER_PROBLEM_NO_PROBLEM, SERVER_PROBLEM_NO_SASL, SERVER_PROBLEM_NO_MECHANISMS, SERVER_PROBLEM_INVALID_USERNAME, SERVER_PROBLEM_INVALID_PASSWORD, SERVER_PROBLEM_REQUIRE_GOOGLE_JDD, SERVER_PROBLEM_DISLIKE_GOOGLE_JDD, SERVER_PROBLEM_SPACE_CHALLENGE, SERVER_PROBLEM_SLASH_CHALLENGE, /* Not actually a problem, but let the server choose to put * ``additional data with success'' in a success stanza. */ SERVER_PROBLEM_FINAL_DATA_IN_SUCCESS, } ServerProblem; typedef struct _TestSaslAuthServer TestSaslAuthServer; typedef struct _TestSaslAuthServerClass TestSaslAuthServerClass; typedef struct _TestSaslAuthServerPrivate TestSaslAuthServerPrivate; struct _TestSaslAuthServerClass { GObjectClass parent_class; }; struct _TestSaslAuthServer { GObject parent; TestSaslAuthServerPrivate *priv; }; GType test_sasl_auth_server_get_type (void); /* TYPE MACROS */ #define TEST_TYPE_SASL_AUTH_SERVER \ (test_sasl_auth_server_get_type ()) #define TEST_SASL_AUTH_SERVER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), TEST_TYPE_SASL_AUTH_SERVER, \ TestSaslAuthServer)) #define TEST_SASL_AUTH_SERVER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), TEST_TYPE_SASL_AUTH_SERVER, \ TestSaslAuthServerClass)) #define TEST_IS_SASL_AUTH_SERVER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), TEST_TYPE_SASL_AUTH_SERVER)) #define TEST_IS_SASL_AUTH_SERVER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), TEST_TYPE_SASL_AUTH_SERVER)) #define TEST_SASL_AUTH_SERVER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_SASL_AUTH_SERVER, \ TestSaslAuthServerClass)) void test_sasl_auth_server_auth_async (GObject *obj, WockyXmppConnection *conn, WockyStanza *auth, GAsyncReadyCallback cb, GCancellable *cancellable, gpointer data); gboolean test_sasl_auth_server_auth_finish (TestSaslAuthServer *self, GAsyncResult *res, GError **error); const gchar *test_sasl_auth_server_get_selected_mech (TestSaslAuthServer *self); TestSaslAuthServer * test_sasl_auth_server_new (GIOStream *stream, gchar *mech, const gchar *user, const gchar *password, const gchar *servername, ServerProblem problem, gboolean start); void test_sasl_auth_server_stop (TestSaslAuthServer *self); gint test_sasl_auth_server_set_mechs (GObject *obj, WockyStanza *feat); G_END_DECLS #endif /* #ifndef __TEST_SASL_AUTH_SERVER_H__*/ ��������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-pubsub-test-helpers.h�����������������������������0000664�0001750�0001750�00000001064�11720661341�027264� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifndef WOCKY_PUBSUB_TEST_HELPERS_H #define WOCKY_PUBSUB_TEST_HELPERS_H #include <glib.h> #include <wocky/wocky.h> typedef struct { const gchar *node; const gchar *jid; const gchar *subscription; WockyPubsubSubscriptionState state; const gchar *subid; } CannedSubscriptions; void test_pubsub_add_subscription_nodes ( WockyNode *subscriptions_node, CannedSubscriptions *subs, gboolean include_node); void test_pubsub_check_and_free_subscriptions ( GList *subscriptions, const CannedSubscriptions *expected_subs); #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/README��������������������������������������������������0000644�0001750�0001750�00000000655�11544576223�022737� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������You can valgrind all the tests by running: % make valgrind To valgrind an individual test binary (wocky-porter-test, say), run: % make wocky-porter-test.valgrind If you want to pass arguments to the tests when valgrinding (perhaps you've narrowed the leaky test down to one test case, /xmpp-porter/cancel-iq-closing say), run: % make wocky-porter-test.valgrind \ TEST_ARGS='-p /xmpp-porter/cancel-iq-closing' �����������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-pubsub-node-test.c��������������������������������0000664�0001750�0001750�00000107274�12005516162�026551� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifdef HAVE_CONFIG_H #include "config.h" #endif #include <stdio.h> #include <unistd.h> #include <string.h> #include <glib.h> #include <wocky/wocky.h> #include "wocky-pubsub-test-helpers.h" #include "wocky-test-helper.h" #include "wocky-test-stream.h" /* Test instantiating a WockyPubsubNode object */ static void test_instantiation (void) { WockyPubsubService *pubsub; WockyXmppConnection *connection; WockyTestStream *stream; WockySession *session; WockyPubsubNode *node; stream = g_object_new (WOCKY_TYPE_TEST_STREAM, NULL); connection = wocky_xmpp_connection_new (stream->stream0); session = wocky_session_new_with_connection (connection, "example.com"); pubsub = wocky_pubsub_service_new (session, "pubsub.localhost"); g_assert (pubsub != NULL); node = wocky_pubsub_service_ensure_node (pubsub, "node1"); g_assert (node != NULL); g_assert (!wocky_strdiff (wocky_pubsub_node_get_name (node), "node1")); g_object_unref (node); g_object_unref (pubsub); g_object_unref (session); g_object_unref (connection); g_object_unref (stream); } /* test wocky_pubsub_node_make_publish_stanza() */ static void test_make_publish_stanza (void) { WockyPubsubService *pubsub; WockyXmppConnection *connection; WockyTestStream *stream; WockySession *session; WockyPubsubNode *node; WockyStanza *stanza, *expected; WockyNode *pubsub_node, *publish, *item; stream = g_object_new (WOCKY_TYPE_TEST_STREAM, NULL); connection = wocky_xmpp_connection_new (stream->stream0); session = wocky_session_new_with_connection (connection, "example.com"); pubsub = wocky_pubsub_service_new (session, "pubsub.localhost"); node = wocky_pubsub_service_ensure_node (pubsub, "track1"); stanza = wocky_pubsub_node_make_publish_stanza (node, &pubsub_node, &publish, &item); g_assert (stanza != NULL); g_assert (pubsub_node != NULL); g_assert (publish != NULL); g_assert (item != NULL); /* I've embraced and extended pubsub, and want to put stuff on the <pubsub> * and <publish> nodes... */ wocky_node_set_attribute (pubsub_node, "gig", "tomorrow"); wocky_node_set_attribute (publish, "kaki", "king"); /* Oh, and I should probably publish something. */ wocky_node_add_child_with_content_ns (item, "castle", "bone chaos", "urn:example:songs"); expected = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, "pubsub.localhost", '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB, '@', "gig", "tomorrow", '(', "publish", '@', "kaki", "king", '@', "node", "track1", '(', "item", '(', "castle", ':', "urn:example:songs", '$', "bone chaos", ')', ')', ')', ')', NULL); test_assert_stanzas_equal (stanza, expected); g_object_unref (expected); g_object_unref (stanza); g_object_unref (node); g_object_unref (pubsub); g_object_unref (session); g_object_unref (connection); g_object_unref (stream); } /* Test subscribing to a node. */ static gboolean test_subscribe_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; reply = wocky_stanza_build_iq_result (stanza, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB, '(', "subscription", '@', "node", "node1", '@', "jid", "mighty@pirate.lit", '@', "subscription", "subscribed", ')', ')', NULL); wocky_porter_send (porter, reply); g_object_unref (reply); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void test_subscribe_cb (GObject *source, GAsyncResult *res, gpointer user_data) { WockyPubsubNode *node = WOCKY_PUBSUB_NODE (source); test_data_t *test = (test_data_t *) user_data; WockyPubsubSubscription *sub; sub = wocky_pubsub_node_subscribe_finish (WOCKY_PUBSUB_NODE (source), res, NULL); g_assert (sub != NULL); /* the node name should be the same. */ g_assert_cmpstr (wocky_pubsub_node_get_name (sub->node), ==, wocky_pubsub_node_get_name (node)); /* in fact, they should be the same node. */ g_assert (sub->node == node); wocky_pubsub_subscription_free (sub); test->outstanding--; g_main_loop_quit (test->loop); } static void test_subscribe (void) { test_data_t *test = setup_test (); WockyPubsubService *pubsub; WockyPubsubNode *node; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_session_start (test->session_in); pubsub = wocky_pubsub_service_new (test->session_in, "pubsub.localhost"); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, test_subscribe_iq_cb, test, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB, '(', "subscribe", '@', "node", "node1", '@', "jid", "mighty@pirate.lit", ')', ')', NULL); node = wocky_pubsub_service_ensure_node (pubsub, "node1"); g_assert (node != NULL); wocky_pubsub_node_subscribe_async (node, "mighty@pirate.lit", NULL, test_subscribe_cb, test); test->outstanding += 2; test_wait_pending (test); g_object_unref (node); g_object_unref (pubsub); test_close_both_porters (test); teardown_test (test); } /* Test unsubscribing from a node. */ typedef struct { test_data_t *test; gboolean expect_subid; } TestUnsubscribeCtx; #define EXPECTED_SUBID "⚞♥⚟" static gboolean test_unsubscribe_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { TestUnsubscribeCtx *ctx = user_data; test_data_t *test = ctx->test; WockyNode *unsubscribe; const gchar *subid; WockyStanza *reply; unsubscribe = wocky_node_get_child ( wocky_node_get_child_ns (wocky_stanza_get_top_node (stanza), "pubsub", WOCKY_XMPP_NS_PUBSUB), "unsubscribe"); g_assert (unsubscribe != NULL); subid = wocky_node_get_attribute (unsubscribe, "subid"); if (ctx->expect_subid) g_assert_cmpstr (EXPECTED_SUBID, ==, subid); else g_assert_cmpstr (NULL, ==, subid); reply = wocky_stanza_build_iq_result (stanza, NULL); wocky_porter_send (porter, reply); g_object_unref (reply); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void test_unsubscribe_cb (GObject *source, GAsyncResult *res, gpointer user_data) { TestUnsubscribeCtx *ctx = user_data; test_data_t *test = ctx->test; gboolean ret; ret = wocky_pubsub_node_unsubscribe_finish (WOCKY_PUBSUB_NODE (source), res, NULL); g_assert (ret); test->outstanding--; g_main_loop_quit (test->loop); } static void test_unsubscribe (void) { test_data_t *test = setup_test (); TestUnsubscribeCtx ctx = { test, }; WockyPubsubService *pubsub; WockyPubsubNode *node; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_session_start (test->session_in); pubsub = wocky_pubsub_service_new (test->session_in, "pubsub.localhost"); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, test_unsubscribe_iq_cb, &ctx, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB, '(', "unsubscribe", '@', "node", "node1", '@', "jid", "mighty@pirate.lit", ')', ')', NULL); node = wocky_pubsub_service_ensure_node (pubsub, "node1"); g_assert (node != NULL); /* first, test unsubscribing with no subid */ ctx.expect_subid = FALSE; wocky_pubsub_node_unsubscribe_async (node, "mighty@pirate.lit", NULL, NULL, test_unsubscribe_cb, &ctx); test->outstanding += 2; test_wait_pending (test); /* then test unsubscribing with a subid */ ctx.expect_subid = TRUE; wocky_pubsub_node_unsubscribe_async (node, "mighty@pirate.lit", EXPECTED_SUBID, NULL, test_unsubscribe_cb, &ctx); test->outstanding += 2; test_wait_pending (test); g_object_unref (node); g_object_unref (pubsub); test_close_both_porters (test); teardown_test (test); } /* test wocky_pubsub_node_delete_async */ static gboolean test_delete_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; reply = wocky_stanza_build_iq_result (stanza, NULL); wocky_porter_send (porter, reply); g_object_unref (reply); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void test_delete_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; g_assert (wocky_pubsub_node_delete_finish (WOCKY_PUBSUB_NODE (source), res, NULL)); test->outstanding--; g_main_loop_quit (test->loop); } static void test_delete (void) { test_data_t *test = setup_test (); WockyPubsubService *pubsub; WockyPubsubNode *node; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_session_start (test->session_in); pubsub = wocky_pubsub_service_new (test->session_in, "pubsub.localhost"); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, test_delete_iq_cb, test, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB_OWNER, '(', "delete", '@', "node", "node1", ')', ')', NULL); node = wocky_pubsub_service_ensure_node (pubsub, "node1"); g_assert (node != NULL); wocky_pubsub_node_delete_async (node, NULL, test_delete_cb, test); test->outstanding += 2; test_wait_pending (test); g_object_unref (node); g_object_unref (pubsub); test_close_both_porters (test); teardown_test (test); } /* Test retrieving a list of subscribers. See XEP-0060 §8.8.1 Retrieve * Subscriptions List * <http://xmpp.org/extensions/xep-0060.html#owner-subscriptions-retrieve> */ static CannedSubscriptions example_183[] = { { "princely_musings", "hamlet@denmark.lit", "subscribed", WOCKY_PUBSUB_SUBSCRIPTION_SUBSCRIBED, NULL }, { "princely_musings", "polonius@denmark.lit", "unconfigured", WOCKY_PUBSUB_SUBSCRIPTION_UNCONFIGURED, NULL }, { "princely_musings", "bernardo@denmark.lit", "subscribed", WOCKY_PUBSUB_SUBSCRIPTION_SUBSCRIBED, "123-abc" }, { "princely_musings", "bernardo@denmark.lit", "subscribed", WOCKY_PUBSUB_SUBSCRIPTION_SUBSCRIBED, "004-yyy" }, { NULL, } }; static gboolean test_list_subscribers_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *expected, *reply; WockyNode *subscriptions; expected = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, "pubsub.localhost", '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB_OWNER, '(', "subscriptions", '@', "node", "princely_musings", ')', ')', NULL); test_assert_stanzas_equal_no_id (stanza, expected); g_object_unref (expected); reply = wocky_stanza_build_iq_result (stanza, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB_OWNER, '(', "subscriptions", '@', "node", "princely_musings", '*', &subscriptions, ')', ')', NULL); test_pubsub_add_subscription_nodes (subscriptions, example_183, FALSE); wocky_porter_send (porter, reply); g_object_unref (reply); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void test_list_subscribers_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GList *subscribers; g_assert (wocky_pubsub_node_list_subscribers_finish ( WOCKY_PUBSUB_NODE (source), res, &subscribers, NULL)); test_pubsub_check_and_free_subscriptions (subscribers, example_183); test->outstanding--; g_main_loop_quit (test->loop); } static void test_list_subscribers (void) { test_data_t *test = setup_test (); WockyPubsubService *pubsub; WockyPubsubNode *node; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_session_start (test->session_in); pubsub = wocky_pubsub_service_new (test->session_in, "pubsub.localhost"); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, test_list_subscribers_iq_cb, test, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB_OWNER, '(', "subscriptions", '@', "node", "princely_musings", ')', ')', NULL); node = wocky_pubsub_service_ensure_node (pubsub, "princely_musings"); g_assert (node != NULL); wocky_pubsub_node_list_subscribers_async (node, NULL, test_list_subscribers_cb, test); test->outstanding += 2; test_wait_pending (test); g_object_unref (node); g_object_unref (pubsub); test_close_both_porters (test); teardown_test (test); } /* Test retrieving a list of entities affiliated to a node you own. See * XEP-0060 §8.9.1 Retrieve Affiliations List * <http://xmpp.org/extensions/xep-0060.html#owner-affiliations-retrieve> */ static gboolean test_list_affiliates_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *expected, *reply; expected = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, "pubsub.localhost", '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB_OWNER, '(', "affiliations", '@', "node", "princely_musings", ')', ')', NULL); test_assert_stanzas_equal_no_id (stanza, expected); g_object_unref (expected); reply = wocky_stanza_build_iq_result (stanza, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB_OWNER, '(', "affiliations", '@', "node", "princely_musings", '(', "affiliation", '@', "jid", "hamlet@denmark.lit", '@', "affiliation", "owner", ')', '(', "affiliation", '@', "jid", "polonius@denmark.lit", '@', "affiliation", "outcast", ')', ')', ')', NULL); wocky_porter_send (porter, reply); g_object_unref (reply); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void test_list_affiliates_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GList *affiliates; WockyPubsubAffiliation *aff; g_assert (wocky_pubsub_node_list_affiliates_finish ( WOCKY_PUBSUB_NODE (source), res, &affiliates, NULL)); g_assert_cmpuint (2, ==, g_list_length (affiliates)); aff = affiliates->data; g_assert_cmpstr ("princely_musings", ==, wocky_pubsub_node_get_name (aff->node)); g_assert_cmpstr ("hamlet@denmark.lit", ==, aff->jid); g_assert_cmpuint (WOCKY_PUBSUB_AFFILIATION_OWNER, ==, aff->state); aff = affiliates->next->data; g_assert_cmpstr ("princely_musings", ==, wocky_pubsub_node_get_name (aff->node)); g_assert_cmpstr ("polonius@denmark.lit", ==, aff->jid); g_assert_cmpuint (WOCKY_PUBSUB_AFFILIATION_OUTCAST, ==, aff->state); wocky_pubsub_affiliation_list_free (affiliates); test->outstanding--; g_main_loop_quit (test->loop); } static void test_list_affiliates (void) { test_data_t *test = setup_test (); WockyPubsubService *pubsub; WockyPubsubNode *node; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_session_start (test->session_in); pubsub = wocky_pubsub_service_new (test->session_in, "pubsub.localhost"); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, test_list_affiliates_iq_cb, test, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB_OWNER, '(', "affiliations", '@', "node", "princely_musings", ')', ')', NULL); node = wocky_pubsub_service_ensure_node (pubsub, "princely_musings"); g_assert (node != NULL); wocky_pubsub_node_list_affiliates_async (node, NULL, test_list_affiliates_cb, test); test->outstanding += 2; test_wait_pending (test); g_object_unref (node); g_object_unref (pubsub); test_close_both_porters (test); teardown_test (test); } /* Test modifying the entities affiliated to a node that you own. See §8.9.2 * Modify Affiliation. */ static gboolean test_modify_affiliates_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *expected, *reply; expected = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, "pubsub.localhost", '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB_OWNER, '(', "affiliations", '@', "node", "princely_musings", '(', "affiliation", '@', "jid", "hamlet@denmark.lit", '@', "affiliation", "none", ')', '(', "affiliation", '@', "jid", "polonius@denmark.lit", '@', "affiliation", "none", ')', '(', "affiliation", '@', "jid", "bard@shakespeare.lit", '@', "affiliation", "publisher", ')', ')', ')', NULL); test_assert_stanzas_equal_no_id (stanza, expected); g_object_unref (expected); reply = wocky_stanza_build_iq_result (stanza, NULL); wocky_porter_send (porter, reply); g_object_unref (reply); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void test_modify_affiliates_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; g_assert (wocky_pubsub_node_modify_affiliates_finish ( WOCKY_PUBSUB_NODE (source), res, NULL)); test->outstanding--; g_main_loop_quit (test->loop); } static void test_modify_affiliates (void) { test_data_t *test = setup_test (); WockyPubsubService *pubsub; WockyPubsubNode *node; GList *snakes = NULL; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_session_start (test->session_in); pubsub = wocky_pubsub_service_new (test->session_in, "pubsub.localhost"); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, test_modify_affiliates_iq_cb, test, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB_OWNER, '(', "affiliations", '@', "node", "princely_musings", ')', ')', NULL); node = wocky_pubsub_service_ensure_node (pubsub, "princely_musings"); g_assert (node != NULL); snakes = g_list_append (snakes, wocky_pubsub_affiliation_new (node, "hamlet@denmark.lit", WOCKY_PUBSUB_AFFILIATION_NONE)); snakes = g_list_append (snakes, wocky_pubsub_affiliation_new (node, "polonius@denmark.lit", WOCKY_PUBSUB_AFFILIATION_NONE)); snakes = g_list_append (snakes, wocky_pubsub_affiliation_new (node, "bard@shakespeare.lit", WOCKY_PUBSUB_AFFILIATION_PUBLISHER)); wocky_pubsub_node_modify_affiliates_async (node, snakes, NULL, test_modify_affiliates_cb, test); wocky_pubsub_affiliation_list_free (snakes); snakes = NULL; test->outstanding += 2; test_wait_pending (test); g_object_unref (node); g_object_unref (pubsub); test_close_both_porters (test); teardown_test (test); } /* Tests retrieving a node's current configuration. * * Since data forms are reasonably exhaustively tested elsewhere, this test * uses a very simple configuration form. */ static gboolean test_get_configuration_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *expected, *reply; expected = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, "pubsub.localhost", '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB_OWNER, '(', "configure", '@', "node", "princely_musings", ')', ')', NULL); test_assert_stanzas_equal_no_id (stanza, expected); g_object_unref (expected); reply = wocky_stanza_build_iq_result (stanza, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB_OWNER, '(', "configure", '(', "x", ':', WOCKY_XMPP_NS_DATA, '@', "type", "form", '(', "field", '@', "type", "hidden", '@', "var", "FORM_TYPE", '(', "value", '$', WOCKY_XMPP_NS_PUBSUB_NODE_CONFIG, ')', ')', '(', "field", '@', "var", "pubsub#title", '@', "type", "text-single", '(', "value", '$', "Hello thar", ')', ')', '(', "field", '@', "var", "pubsub#deliver_notifications", '@', "type", "boolean", '@', "label", "Deliver event notifications", '(', "value", '$', "1", ')', ')', ')', ')', ')', NULL); wocky_porter_send (porter, reply); g_object_unref (reply); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void test_get_configuration_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyDataForm *form; GError *error = NULL; form = wocky_pubsub_node_get_configuration_finish ( WOCKY_PUBSUB_NODE (source), res, &error); g_assert_no_error (error); g_assert (form != NULL); /* Don't bother testing too much, it's tested elsewhere. */ g_assert_cmpuint (3, ==, g_hash_table_size (form->fields)); g_object_unref (form); test->outstanding--; g_main_loop_quit (test->loop); } static void test_get_configuration (void) { test_data_t *test = setup_test (); WockyPubsubService *pubsub; WockyPubsubNode *node; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_session_start (test->session_in); pubsub = wocky_pubsub_service_new (test->session_in, "pubsub.localhost"); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, test_get_configuration_iq_cb, test, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB_OWNER, '(', "configure", '@', "node", "princely_musings", ')', ')', NULL); node = wocky_pubsub_service_ensure_node (pubsub, "princely_musings"); g_assert (node != NULL); wocky_pubsub_node_get_configuration_async (node, NULL, test_get_configuration_cb, test); test->outstanding += 2; test_wait_pending (test); g_object_unref (node); g_object_unref (pubsub); test_close_both_porters (test); teardown_test (test); } /* Test that the 'event-received' signals are fired when we expect them to be. */ gboolean service_event_received; gboolean node_event_received; WockyPubsubNode *expected_node; static void service_event_received_cb (WockyPubsubService *service, WockyPubsubNode *node, WockyStanza *event_stanza, WockyNode *event_node, WockyNode *items_node, GList *items, test_data_t *test) { WockyNode *item; /* Check that we're not winding up with multiple nodes for the same thing. */ if (expected_node != NULL) g_assert (node == expected_node); g_assert_cmpstr ("event", ==, event_node->name); g_assert_cmpstr ("items", ==, items_node->name); g_assert_cmpuint (2, ==, g_list_length (items)); item = g_list_nth_data (items, 0); g_assert_cmpstr ("item", ==, item->name); g_assert_cmpstr ("1", ==, wocky_node_get_attribute (item, "id")); item = g_list_nth_data (items, 1); g_assert_cmpstr ("item", ==, item->name); g_assert_cmpstr ("snakes", ==, wocky_node_get_attribute (item, "id")); test->outstanding--; g_main_loop_quit (test->loop); service_event_received = TRUE; } static void node_event_received_cb (WockyPubsubNode *node, WockyStanza *event_stanza, WockyNode *event_node, WockyNode *items_node, GList *items, test_data_t *test) { WockyNode *item; g_assert_cmpstr ("event", ==, event_node->name); g_assert_cmpstr ("items", ==, items_node->name); g_assert_cmpuint (2, ==, g_list_length (items)); item = g_list_nth_data (items, 0); g_assert_cmpstr ("item", ==, item->name); g_assert_cmpstr ("1", ==, wocky_node_get_attribute (item, "id")); item = g_list_nth_data (items, 1); g_assert_cmpstr ("item", ==, item->name); g_assert_cmpstr ("snakes", ==, wocky_node_get_attribute (item, "id")); test->outstanding--; g_main_loop_quit (test->loop); node_event_received = TRUE; } static void send_pubsub_event (WockyPorter *porter, const gchar *service, const gchar *node) { WockyStanza *stanza; stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, service, NULL, '(', "event", ':', WOCKY_XMPP_NS_PUBSUB_EVENT, '(', "items", '@', "node", node, '(', "item", '@', "id", "1", '(', "payload", ')', ')', '(', "item", '@', "id", "snakes", '(', "payload", ')', ')', ')', ')', NULL); wocky_porter_send (porter, stanza); g_object_unref (stanza); } static void test_receive_event (void) { test_data_t *test = setup_test (); WockyPubsubService *pubsub; WockyPubsubNode *node; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_porter_start (test->sched_in); pubsub = wocky_pubsub_service_new (test->session_out, "pubsub.localhost"); node = wocky_pubsub_service_ensure_node (pubsub, "lol"); g_signal_connect (pubsub, "event-received", (GCallback) service_event_received_cb, test); g_signal_connect (node, "event-received", (GCallback) node_event_received_cb, test); /* send event from the right service for that node */ node_event_received = FALSE; service_event_received = FALSE; expected_node = node; send_pubsub_event (test->sched_in, "pubsub.localhost", "lol"); test->outstanding += 2; test_wait_pending (test); g_assert (node_event_received); g_assert (service_event_received); node_event_received = FALSE; service_event_received = FALSE; /* send event from the right service on a different node */ expected_node = NULL; send_pubsub_event (test->sched_in, "pubsub.localhost", "whut"); test->outstanding += 1; test_wait_pending (test); g_assert (!node_event_received); g_assert (service_event_received); service_event_received = FALSE; /* send event from a different service, on a node with the same name */ send_pubsub_event (test->sched_in, "pubsub.elsewhere", "lol"); g_object_unref (node); g_object_unref (pubsub); /* send event from the right service and node, after we dropped our ref to * the node and service. nothing else should be keeping it hanging around, so * our signal handlers should have been disconnected. */ send_pubsub_event (test->sched_in, "pubsub.localhost", "lol"); test_close_both_porters (test); teardown_test (test); /* None of the subsequent events should have triggered event-received. */ g_assert (!node_event_received); g_assert (!service_event_received); } /* /pubsub-node/subscription-state-changed */ typedef struct { test_data_t *test; const gchar *expecting_service_ssc_received_for; gboolean expecting_node_ssc_received; WockyPubsubSubscriptionState expected_state; } TestSSCCtx; static void send_subscription_state_change (WockyPorter *porter, const gchar *service, const gchar *node, const gchar *state) { WockyStanza *stanza; stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, service, NULL, '(', "event", ':', WOCKY_XMPP_NS_PUBSUB_EVENT, '(', "subscription", '@', "node", node, '@', "jid", "mighty@pirate.lit", '@', "subscription", state, ')', ')', NULL); wocky_porter_send (porter, stanza); g_object_unref (stanza); } static void service_subscription_state_changed_cb ( WockyPubsubService *service, WockyPubsubNode *node, WockyStanza *stanza, WockyNode *event_node, WockyNode *subscription_node, WockyPubsubSubscription *subscription, TestSSCCtx *ctx) { g_assert (ctx->expecting_service_ssc_received_for != NULL); g_assert_cmpstr (wocky_pubsub_node_get_name (node), ==, ctx->expecting_service_ssc_received_for); g_assert_cmpstr (event_node->name, ==, "event"); g_assert_cmpstr (wocky_node_get_ns (event_node), ==, WOCKY_XMPP_NS_PUBSUB_EVENT); g_assert_cmpstr (subscription_node->name, ==, "subscription"); g_assert (subscription->node == node); g_assert_cmpstr (subscription->jid, ==, "mighty@pirate.lit"); g_assert_cmpuint (subscription->state, ==, ctx->expected_state); g_assert (subscription->subid == NULL); ctx->expecting_service_ssc_received_for = NULL; ctx->test->outstanding--; g_main_loop_quit (ctx->test->loop); } static void node_subscription_state_changed_cb ( WockyPubsubNode *node, WockyStanza *stanza, WockyNode *event_node, WockyNode *subscription_node, WockyPubsubSubscription *subscription, TestSSCCtx *ctx) { g_assert (ctx->expecting_node_ssc_received); ctx->expecting_node_ssc_received = FALSE; g_assert_cmpstr (wocky_pubsub_node_get_name (node), ==, "dairy-farmer"); g_assert_cmpstr (event_node->name, ==, "event"); g_assert_cmpstr (wocky_node_get_ns (event_node), ==, WOCKY_XMPP_NS_PUBSUB_EVENT); g_assert_cmpstr (subscription_node->name, ==, "subscription"); g_assert (subscription->node == node); g_assert_cmpstr (subscription->jid, ==, "mighty@pirate.lit"); g_assert_cmpuint (subscription->state, ==, ctx->expected_state); g_assert (subscription->subid == NULL); ctx->test->outstanding--; g_main_loop_quit (ctx->test->loop); } static void test_subscription_state_changed (void) { test_data_t *test = setup_test (); TestSSCCtx ctx = { test, FALSE, FALSE, WOCKY_PUBSUB_SUBSCRIPTION_NONE }; WockyPubsubService *pubsub; WockyPubsubNode *node; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_porter_start (test->sched_in); pubsub = wocky_pubsub_service_new (test->session_out, "pubsub.localhost"); g_signal_connect (pubsub, "subscription-state-changed", (GCallback) service_subscription_state_changed_cb, &ctx); node = wocky_pubsub_service_ensure_node (pubsub, "dairy-farmer"); g_signal_connect (node, "subscription-state-changed", (GCallback) node_subscription_state_changed_cb, &ctx); /* Send a subscription change notification for a different node. */ send_subscription_state_change (test->sched_in, "pubsub.localhost", "cow", "pending"); ctx.expecting_service_ssc_received_for = "cow"; ctx.expecting_node_ssc_received = FALSE; ctx.expected_state = WOCKY_PUBSUB_SUBSCRIPTION_PENDING; test->outstanding += 1; test_wait_pending (test); /* Send a subscription change notification for @node. */ send_subscription_state_change (test->sched_in, "pubsub.localhost", "dairy-farmer", "unconfigured"); ctx.expecting_service_ssc_received_for = "dairy-farmer"; ctx.expecting_node_ssc_received = TRUE; ctx.expected_state = WOCKY_PUBSUB_SUBSCRIPTION_UNCONFIGURED; test->outstanding += 2; test_wait_pending (test); g_assert (!ctx.expecting_node_ssc_received); test_close_both_porters (test); teardown_test (test); g_object_unref (node); g_object_unref (pubsub); } /* /pubsub-node/deleted */ typedef struct { test_data_t *test; const gchar *expecting_service_node_deleted_for; gboolean expecting_node_deleted; } TestDeletedCtx; static void send_deleted (WockyPorter *porter, const gchar *service, const gchar *node) { WockyStanza *stanza; stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, service, NULL, '(', "event", ':', WOCKY_XMPP_NS_PUBSUB_EVENT, '(', "delete", '@', "node", node, ')', ')', NULL); wocky_porter_send (porter, stanza); g_object_unref (stanza); } static void service_node_deleted_cb ( WockyPubsubService *service, WockyPubsubNode *node, WockyStanza *stanza, WockyNode *event_node, WockyNode *delete_node, TestDeletedCtx *ctx) { g_assert (ctx->expecting_service_node_deleted_for != NULL); g_assert_cmpstr (wocky_pubsub_node_get_name (node), ==, ctx->expecting_service_node_deleted_for); g_assert_cmpstr (event_node->name, ==, "event"); g_assert_cmpstr (wocky_node_get_ns (event_node), ==, WOCKY_XMPP_NS_PUBSUB_EVENT); g_assert_cmpstr (delete_node->name, ==, "delete"); ctx->expecting_service_node_deleted_for = NULL; ctx->test->outstanding--; g_main_loop_quit (ctx->test->loop); } static void node_deleted_cb ( WockyPubsubNode *node, WockyStanza *stanza, WockyNode *event_node, WockyNode *delete_node, TestDeletedCtx *ctx) { g_assert (ctx->expecting_node_deleted); ctx->expecting_node_deleted = FALSE; g_assert_cmpstr (wocky_pubsub_node_get_name (node), ==, "dairy-farmer"); g_assert_cmpstr (event_node->name, ==, "event"); g_assert_cmpstr (wocky_node_get_ns (event_node), ==, WOCKY_XMPP_NS_PUBSUB_EVENT); g_assert_cmpstr (delete_node->name, ==, "delete"); ctx->test->outstanding--; g_main_loop_quit (ctx->test->loop); } static void test_deleted (void) { test_data_t *test = setup_test (); TestDeletedCtx ctx = { test, FALSE, FALSE }; WockyPubsubService *pubsub; WockyPubsubNode *node; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_porter_start (test->sched_in); pubsub = wocky_pubsub_service_new (test->session_out, "pubsub.localhost"); g_signal_connect (pubsub, "node-deleted", (GCallback) service_node_deleted_cb, &ctx); node = wocky_pubsub_service_ensure_node (pubsub, "dairy-farmer"); g_signal_connect (node, "deleted", (GCallback) node_deleted_cb, &ctx); /* Send a deletion notification for a different node. */ send_deleted (test->sched_in, "pubsub.localhost", "cow"); ctx.expecting_service_node_deleted_for = "cow"; ctx.expecting_node_deleted = FALSE; test->outstanding += 1; test_wait_pending (test); g_assert (ctx.expecting_service_node_deleted_for == NULL); /* Send a subscription change notification for @node. */ send_deleted (test->sched_in, "pubsub.localhost", "dairy-farmer"); ctx.expecting_service_node_deleted_for = "dairy-farmer"; ctx.expecting_node_deleted = TRUE; test->outstanding += 2; test_wait_pending (test); g_assert (ctx.expecting_service_node_deleted_for == NULL); g_assert (!ctx.expecting_node_deleted); test_close_both_porters (test); teardown_test (test); g_object_unref (node); g_object_unref (pubsub); } int main (int argc, char **argv) { int result; test_init (argc, argv); g_test_add_func ("/pubsub-node/instantiation", test_instantiation); g_test_add_func ("/pubsub-node/make-publish-stanza", test_make_publish_stanza); g_test_add_func ("/pubsub-node/subscribe", test_subscribe); g_test_add_func ("/pubsub-node/unsubscribe", test_unsubscribe); g_test_add_func ("/pubsub-node/delete", test_delete); g_test_add_func ("/pubsub-node/list-subscribers", test_list_subscribers); g_test_add_func ("/pubsub-node/list-affiliates", test_list_affiliates); g_test_add_func ("/pubsub-node/modify-affiliates", test_modify_affiliates); g_test_add_func ("/pubsub-node/get-configuration", test_get_configuration); g_test_add_func ("/pubsub-node/receive-event", test_receive_event); g_test_add_func ("/pubsub-node/subscription-state-changed", test_subscription_state_changed); g_test_add_func ("/pubsub-node/deleted", test_deleted); result = g_test_run (); test_deinit (); return result; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-ping-test.c���������������������������������������0000664�0001750�0001750�00000007725�12005516162�025263� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifdef HAVE_CONFIG_H #include "config.h" #endif #include <stdio.h> #include <unistd.h> #include <string.h> #include <glib.h> #include <wocky/wocky.h> #include "wocky-test-stream.h" #include "wocky-test-helper.h" #define PING_COUNT 2 #define PING_INTERVAL 1 /* We expect PING_COUNT pings, followed by disabling pings and waiting for * PING_COUNT * PING_INTERVAL to see if we get any pings we didn't want, * followed by turning pings back on again and testing if we get any. The +1 is * a fudge factor. ;-) */ #define TOTAL_TIMEOUT (PING_COUNT * PING_INTERVAL + 1) * 3 static void ping_recv_cb (const gchar *buff, gsize len, gpointer user_data) { test_data_t *data = user_data; gchar *tmp_buff; /* There is no g_assert_cmpnstr */ tmp_buff = g_strndup (buff, len); g_assert_cmpstr (tmp_buff, ==, " "); g_free (tmp_buff); g_assert_cmpuint (data->outstanding, >, 0); data->outstanding--; g_main_loop_quit (data->loop); } static gboolean we_have_waited_long_enough (gpointer user_data) { test_data_t *test = user_data; g_assert_cmpuint (test->outstanding, ==, 1); test->outstanding--; g_main_loop_quit (test->loop); return FALSE; } static void test_periodic_ping (void) { WockyPing *ping; test_data_t *test = setup_test_with_timeout (TOTAL_TIMEOUT); WockyXmppConnection *connection; GIOStream *stream; GInputStream *stream_in; g_assert (WOCKY_IS_C2S_PORTER (test->sched_in)); /* First, we ping every n seconds */ ping = wocky_ping_new (WOCKY_C2S_PORTER (test->sched_in), PING_INTERVAL); test_open_both_connections (test); wocky_porter_start (test->sched_in); wocky_porter_start (test->sched_out); g_object_get (test->sched_out, "connection", &connection, NULL); g_object_get (connection, "base-stream", &stream, NULL); stream_in = g_io_stream_get_input_stream (stream); g_object_unref (stream); g_object_unref (connection); wocky_test_stream_set_direct_read_callback (stream_in, ping_recv_cb, test); test->outstanding += PING_COUNT; test_wait_pending (test); /* Now, we disable pings, and wait briefly to see if we get any pings. */ g_object_set (ping, "ping-interval", 0, NULL); g_timeout_add_seconds (PING_INTERVAL * PING_COUNT, we_have_waited_long_enough, test); test->outstanding = 1; test_wait_pending (test); /* And then we enable pings again, and wait for one more. */ g_object_set (ping, "ping-interval", PING_INTERVAL, NULL); test->outstanding += 1; test_wait_pending (test); wocky_test_stream_set_direct_read_callback (stream_in, NULL, NULL); test_close_both_porters (test); g_object_unref (ping); teardown_test (test); } static void send_ping_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *data = (test_data_t *) user_data; WockyStanza *reply; reply = wocky_porter_send_iq_finish (WOCKY_PORTER (source), res, NULL); g_assert (reply != NULL); g_object_unref (reply); data->outstanding--; g_main_loop_quit (data->loop); } static void test_pong (void) { WockyStanza *s; WockyPing *ping; test_data_t *test = setup_test (); g_assert (WOCKY_IS_C2S_PORTER (test->sched_in)); ping = wocky_ping_new (WOCKY_C2S_PORTER (test->sched_in), 0); test_open_both_connections (test); wocky_porter_start (test->sched_in); wocky_porter_start (test->sched_out); /* Server pings us */ s = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "capulet.lit", "juliet@capulet.lit/balcony", '(', "ping", ':', WOCKY_XMPP_NS_PING, ')', NULL); wocky_porter_send_iq_async (test->sched_out, s, NULL, send_ping_cb, test); g_object_unref (s); test->outstanding++; test_wait_pending (test); test_close_both_porters (test); g_object_unref (ping); teardown_test (test); } int main (int argc, char **argv) { int result; test_init (argc, argv); g_test_add_func ("/xmpp-ping/pong", test_pong); g_test_add_func ("/xmpp-ping/periodic", test_periodic_ping); result = g_test_run (); test_deinit (); return result; } �������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/��������������������������������������������������0000775�0001750�0001750�00000000000�12332445273�023167� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/wild-cert.cfg�������������������������������������0000664�0001750�0001750�00000004154�12212322440�025531� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# X.509 Certificate options # # DN options # The organization of the subject. organization = "Collabora" # The organizational unit of the subject. unit = "Wocky Test Suite" # The locality of the subject. # locality = # The state of the certificate owner. state = "Dazed" # The country of the subject. Two letter code. country = UK # The common name of the certificate owner. cn = "Wocky XMPP Library" # A user id of the certificate owner. #uid = "clauper" # If the supported DN OIDs are not adequate you can set # any OID here. # For example set the X.520 Title and the X.520 Pseudonym # by using OID and string pairs. #dn_oid = "2.5.4.12" "Dr." "2.5.4.65" "jackal" # This is deprecated and should not be used in new # certificates. # pkcs9_email = "none@none.org" # The serial number of the certificate serial = 002 # In how many days, counting from today, this certificate will expire. expiration_days = 10220 # X.509 v3 extensions # A dnsname in case of a WWW server. dns_name = "*.weasel-juice.org" #dns_name = "www.morethanone.org" # An IP address in case of a server. ip_address = "127.0.0.1" # An email in case of a person #email = "postmaster@collabora.co.uk" # An URL that has CRLs (certificate revocation lists) # available. Needed in CA certificates. #crl_dist_points = "file:///tmp/wocky-tests/crl" # Whether this is a CA certificate or not #ca # Whether this certificate will be used for a TLS client tls_www_client # Whether this certificate will be used for a TLS server tls_www_server # Whether this certificate will be used to sign data (needed # in TLS DHE ciphersuites). #signing_key # Whether this certificate will be used to encrypt data (needed # in TLS RSA ciphersuites). Note that it is prefered to use different # keys for encryption and signing. encryption_key # Whether this key will be used to sign other certificates. #cert_signing_key # Whether this key will be used to sign CRLs. #crl_signing_key # Whether this key will be used to sign code. #code_signing_key # Whether this key will be used to sign OCSP data. #ocsp_signing_key # Whether this key will be used for time stamping. time_stamping_key ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/ss-cert.cfg���������������������������������������0000664�0001750�0001750�00000004150�12212322440�025213� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# X.509 Certificate options # # DN options # The organization of the subject. organization = "Collabora" # The organizational unit of the subject. unit = "Wocky Test Suite" # The locality of the subject. # locality = # The state of the certificate owner. state = "Confused" # The country of the subject. Two letter code. country = UK # The common name of the certificate owner. cn = "Wocky XMPP Library" # A user id of the certificate owner. #uid = "clauper" # If the supported DN OIDs are not adequate you can set # any OID here. # For example set the X.520 Title and the X.520 Pseudonym # by using OID and string pairs. #dn_oid = "2.5.4.12" "Dr." "2.5.4.65" "jackal" # This is deprecated and should not be used in new # certificates. # pkcs9_email = "none@none.org" # The serial number of the certificate serial = 001 # In how many days, counting from today, this certificate will expire. expiration_days = 10220 # X.509 v3 extensions # A dnsname in case of a WWW server. dns_name = "weasel-juice.org" #dns_name = "www.morethanone.org" # An IP address in case of a server. ip_address = "127.0.0.1" # An email in case of a person email = "postmaster@collabora.co.uk" # An URL that has CRLs (certificate revocation lists) # available. Needed in CA certificates. crl_dist_points = "file:///tmp/wocky-tests/crl" # Whether this is a CA certificate or not ca # Whether this certificate will be used for a TLS client tls_www_client # Whether this certificate will be used for a TLS server tls_www_server # Whether this certificate will be used to sign data (needed # in TLS DHE ciphersuites). signing_key # Whether this certificate will be used to encrypt data (needed # in TLS RSA ciphersuites). Note that it is prefered to use different # keys for encryption and signing. encryption_key # Whether this key will be used to sign other certificates. cert_signing_key # Whether this key will be used to sign CRLs. crl_signing_key # Whether this key will be used to sign code. #code_signing_key # Whether this key will be used to sign OCSP data. #ocsp_signing_key # Whether this key will be used for time stamping. #time_stamping_key ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/rev-key.pem���������������������������������������0000644�0001750�0001750�00000003213�11544576223�025255� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAp8maSrexTHpBTvTk8yGc0D081R9xQgY4aFYgYUrQvaFnAha+ vkRzaYt1FBvsrYJcuwpWq93M/g97Tylln3jKNOPPeYevwdcFAb7aYzWcVbXNsr6J inKAslmslp7rnE0W9cGwAdPrIbLgShwQ+C9lrO6B5J9MJlXdB2KGsq11ATJkLou2 OZGIdC2gfoHMZrv0aIUsLwb6UrpDpfDjpAep4B36CbV90q43UxyAmNv1Gtnzsb/p 4eoTsuccu32qWDBTbXbzQpYn6i7yu1a4plajcbYkmSjRk1aEzwVmoKPjVdmmzWI0 rLRpFFoauGSODZpMg3B03gLX8f9eNlVz6hrtCwIDAQABAoIBAAH0S9hu8fZiviao nOS6vCmDbRVLu8qkaT0d3lwDvmasXezHowpy9afXDf1hTeJqJaEFankEqQHp4D/N yvc5NZxkGDiMJ18/R+RQpW6JDfxu6lRt+mAjG/NNLsDFB8LW9bDVxAe2wNha+Fh5 9zX3fLGvnX0Hi0rZroIK2GggXmqDIj+Ce3k6wcJLhZ7h6bext18lPKXigvTAFqVZ eJ7sucBrn+ww0qhBACpZ4RT2aBk991/Vrberw9OnJg+ipvjKnn+c+MoyftMj9Ih4 YMh87gRkdObukX5AiEYyYf0VGi7ejDMIygmQzpuup3jUYjNbpwwZZdoz4mwKqmvm Tvr7xdECgYEAzGxPHANCPkl4typwmEYEDRFKPtcoYKr9DJAQL9zqtqb3wEzbbSmN x5HzQqeX/hHND93OdCLKCzcHoF6KgglAmMIwu0ihagHT5Vul1VCoGItGWorL4XIW GTm8kKZXcDCgb6UWSG48fDj5eO5y+ZAxYjof97OmX6D9eleptKfZPe8CgYEA0h8A Wl1b7Qcsx26bLOGih5UuedKsda7EWUIbg5M86zy2UfJC3Rl6n17+gS55ffjuRrek eYrB2bomAnjhvPPaR6us7j/z87BsJ2PbZSsS/AkoCGqn6yjYR1eUWA65zbSEbWd2 RHB9rhcY7DDW2hwzkSkxbWzaXCuHNme0ZStsHqUCgYBNIbDXyQL9rYs20XSagBCX Pabd/yDlGJ9SVilFZf3J3UYt8NH6ZmtwmclHpSTcYKsXCYIUn+vMP39JK2LnncYZ 3Wu1vrno3beuGt5/lmdWm3Z4Q1aaQgnEitxzV9A2LKLcfVXjDnUUCgtXbeFD+Pwp K/VT6R0liAEcYGdQGuUFUQKBgHhCYAxYJJXLpnhaOJv+Y+xfmKMGzcfpB93iNScg LRyhueO62UP8Ii92ygkblVNhFtcIoi0iGoLHxJtjnidsFcExY59UoQYXMj91KouD lLEFeJEgogy4atiiKngfrX4rVCPdtFXFYFk0RQJhjYZ135m0TuLHC073ZsLfpeLF cHM1AoGBAKru0XcmVES6ieGAPtKm4IBgT4kXoBdAfYcans9DCRqJqqqcnALgHyo2 P2iP+/5u20XOb56bu15ko0fGkq7ibsdrsl9tZbXVyo3/Q0WesN4lOfVEB3tCmS2r D7alla/Fs5HrQEiCYUQGHisEuLqxt6LoHMv8vOqR8jGHiwX98cbe -----END RSA PRIVATE KEY----- �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/ca-2-cert.cfg�������������������������������������0000644�0001750�0001750�00000004153�11544576223�025332� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# X.509 Certificate options # # DN options # The organization of the subject. organization = "Collabora" # The organizational unit of the subject. unit = "Wocky Test Suite" # The locality of the subject. # locality = # The state of the certificate owner. state = "Spindled" # The country of the subject. Two letter code. country = UK # The common name of the certificate owner. cn = "Wocky XMPP Library" # A user id of the certificate owner. #uid = "clauper" # If the supported DN OIDs are not adequate you can set # any OID here. # For example set the X.520 Title and the X.520 Pseudonym # by using OID and string pairs. #dn_oid = "2.5.4.12" "Dr." "2.5.4.65" "jackal" # This is deprecated and should not be used in new # certificates. # pkcs9_email = "none@none.org" # The serial number of the certificate serial = 001 # In how many days, counting from today, this certificate will expire. expiration_days = 10220 # X.509 v3 extensions # A dnsname in case of a WWW server. #dns_name = "www.none.org" #dns_name = "www.morethanone.org" # An IP address in case of a server. #ip_address = "192.168.1.1" # An email in case of a person email = "postmaster@collabora.co.uk" # An URL that has CRLs (certificate revocation lists) # available. Needed in CA certificates. crl_dist_points = "file:///tmp/wocky-tests/crl" # Whether this is a CA certificate or not ca # Whether this certificate will be used for a TLS client #tls_www_client # Whether this certificate will be used for a TLS server #tls_www_server # Whether this certificate will be used to sign data (needed # in TLS DHE ciphersuites). signing_key # Whether this certificate will be used to encrypt data (needed # in TLS RSA ciphersuites). Note that it is prefered to use different # keys for encryption and signing. #encryption_key # Whether this key will be used to sign other certificates. cert_signing_key # Whether this key will be used to sign CRLs. crl_signing_key # Whether this key will be used to sign code. #code_signing_key # Whether this key will be used to sign OCSP data. #ocsp_signing_key # Whether this key will be used for time stamping. #time_stamping_key ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/ca-0-key.pem��������������������������������������0000644�0001750�0001750�00000003213�11544576223�025201� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEA35q0WVGuFFgy4JhzUVGlyBMIcEkEREkxdX1nfjT+cTDuuThN CQJs5OK3Tx/MYrm2t1p1VbwPp6Ked5Qu3pk0zFc1i1iyRFd39tcTXhwkVsZJswMA BfsfcvcxleJkYDFpNuoNAtHZmmDyC3E3ImEcI72sBHXe/M9PcAUhnWMdWGvjK/QQ ZdrU4Q+HJYleg1XZcIZ77u3mpq0Py3Xkv5+Gfl/DGFvhuPWvG76h76aezEvKSMBD H4JM37hviv/vgr8+Vnzn5w2B9d2oU5LO5NEQdeq7dalJ7xeuq82CW86iUnOJm4XD ibhVEV3omSmNn+/FtW+kUU7xDSEnZxiiT8DMWQIDAQABAoIBACYUQcXbPd7LlWB/ vdW5ppafvSZoHOCnKVPVlyAcVL+AgosK7j2MSvCgtnB0XRlsAJSRhF1lITJeZIe/ NcslQqNQ77arFHLEhZLFFlCG0N5xNsBUULb0COtKcwiQLSFfkMgwDCawh5L9kwLF VUsWyBTDGo4I58Bcaq4MRaj4pdj2dxNlpsdf1Nd/FlDVYksD/bBRHBXW//eUYrEc oCYGh65JQKOeCBXL3O8imgcq5nbC0On5O1t2YfqIdmk67iFubn3IkLLm2/hvnSNl m4JvcDzq+uJA4T760s6CSayTd4tHfHS23IXQyluhqsRPd2mZaDkM45oNKBXMNIaN /EU2500CgYEA7QVO6McEq9uWlx/QrWIpMWTdHH0EUqwFEd7wDoWskdyUPX/QDYJb E088O9c1TrNpVcAIQgWy/2EEOMYmUhjrM9q5jiX2m9P745g+ij+cta4GhW+B2sfd ODiY0b7y2Z2bzUuew7UtZ3H5BAuzWcMGz558xh2J8x8DLM0YHtjgNMUCgYEA8YJf cY8ZUPz8tlYXB/NPYRBlqGMwt6x//nxnElYfquXXOMIWf7WsXNjMHcRsksF1IA3i jTLi7s+N6lBR0QO4b/ohXzbSGcxPwJF/OIcQ1+WYpdywO84Y531whKrkn6jopYlK XXChkEZAqNjCoYx19ORi1vpv3KSixK/K2u6Z+oUCgYEAl64R9X2HS8PW9xdxH8P1 wJpftd97aLyU8f7NeT2qVh3m8ARfTIXjatQGI/VxM9A01J9zqWykRDH91adY1qkD u8d5f7Jjww1B4UCIpUhYLRwVKEdXvn6w30243mFoYEMwdYyzKWNEjzKsvR4PxJ2+ OheemdpFccSi74TArtzzflECgYA4dYsMiDCZ71rA4aVmtWnUPjoVwIKOHeSaQMjz z3B9ylejLDSITJdr6T7mopnjQRi5kqVo7wGAZMM/iOFnpKAEhYwxryY047+tPBZq x6CXaFRkShBlGsxVqcyZJz5lWN5yfIMHDyKmENZi4rG1hJm6032L1mY6Rb7LjnE0 91zF5QKBgBFQqqhH1I/2hrJ9knPTYjK+e4iN/zLsE3PliL9IxFrrnc6dZ/qkQ3qL l70zC2GKJf9lVoG6T3uoS2BKz504onusYvAKTKgF/J7giEmzJE2/Eol2+ffZ1uKR jsDx84YYvFZhiPNBfSbsB6IRiH+EEl7SSasTmL/l3TgE1gfaw5S7 -----END RSA PRIVATE KEY----- �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/unknown-cert.cfg����������������������������������0000644�0001750�0001750�00000004152�11544576223�026306� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# X.509 Certificate options # # DN options # The organization of the subject. organization = "Collabora" # The organizational unit of the subject. unit = "Wocky Test Suite" # The locality of the subject. # locality = # The state of the certificate owner. state = "Dazed" # The country of the subject. Two letter code. country = UK # The common name of the certificate owner. cn = "Wocky XMPP Library" # A user id of the certificate owner. #uid = "clauper" # If the supported DN OIDs are not adequate you can set # any OID here. # For example set the X.520 Title and the X.520 Pseudonym # by using OID and string pairs. #dn_oid = "2.5.4.12" "Dr." "2.5.4.65" "jackal" # This is deprecated and should not be used in new # certificates. # pkcs9_email = "none@none.org" # The serial number of the certificate serial = 002 # In how many days, counting from today, this certificate will expire. expiration_days = 10220 # X.509 v3 extensions # A dnsname in case of a WWW server. dns_name = "weasel-juice.org" #dns_name = "www.morethanone.org" # An IP address in case of a server. ip_address = "127.0.0.1" # An email in case of a person #email = "postmaster@collabora.co.uk" # An URL that has CRLs (certificate revocation lists) # available. Needed in CA certificates. #crl_dist_points = "file:///tmp/wocky-tests/crl" # Whether this is a CA certificate or not #ca # Whether this certificate will be used for a TLS client tls_www_client # Whether this certificate will be used for a TLS server tls_www_server # Whether this certificate will be used to sign data (needed # in TLS DHE ciphersuites). #signing_key # Whether this certificate will be used to encrypt data (needed # in TLS RSA ciphersuites). Note that it is prefered to use different # keys for encryption and signing. encryption_key # Whether this key will be used to sign other certificates. #cert_signing_key # Whether this key will be used to sign CRLs. #crl_signing_key # Whether this key will be used to sign code. #code_signing_key # Whether this key will be used to sign OCSP data. #ocsp_signing_key # Whether this key will be used for time stamping. time_stamping_key ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/badwild-cert.cfg����������������������������������0000664�0001750�0001750�00000004152�12212322440�026176� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# X.509 Certificate options # # DN options # The organization of the subject. organization = "Collabora" # The organizational unit of the subject. unit = "Wocky Test Suite" # The locality of the subject. # locality = # The state of the certificate owner. state = "Dazed" # The country of the subject. Two letter code. country = UK # The common name of the certificate owner. cn = "Wocky XMPP Library" # A user id of the certificate owner. #uid = "clauper" # If the supported DN OIDs are not adequate you can set # any OID here. # For example set the X.520 Title and the X.520 Pseudonym # by using OID and string pairs. #dn_oid = "2.5.4.12" "Dr." "2.5.4.65" "jackal" # This is deprecated and should not be used in new # certificates. # pkcs9_email = "none@none.org" # The serial number of the certificate serial = 002 # In how many days, counting from today, this certificate will expire. expiration_days = 10220 # X.509 v3 extensions # A dnsname in case of a WWW server. dns_name = "*easel-juice.org" #dns_name = "www.morethanone.org" # An IP address in case of a server. ip_address = "127.0.0.1" # An email in case of a person #email = "postmaster@collabora.co.uk" # An URL that has CRLs (certificate revocation lists) # available. Needed in CA certificates. #crl_dist_points = "file:///tmp/wocky-tests/crl" # Whether this is a CA certificate or not #ca # Whether this certificate will be used for a TLS client tls_www_client # Whether this certificate will be used for a TLS server tls_www_server # Whether this certificate will be used to sign data (needed # in TLS DHE ciphersuites). #signing_key # Whether this certificate will be used to encrypt data (needed # in TLS RSA ciphersuites). Note that it is prefered to use different # keys for encryption and signing. encryption_key # Whether this key will be used to sign other certificates. #cert_signing_key # Whether this key will be used to sign CRLs. #crl_signing_key # Whether this key will be used to sign code. #code_signing_key # Whether this key will be used to sign OCSP data. #ocsp_signing_key # Whether this key will be used for time stamping. time_stamping_key ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/new-key.pem���������������������������������������0000644�0001750�0001750�00000003213�11544576223�025252� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEAuZZqCSGB8MHUsUeeN/B/VEJSH2kqfE/4q8UBtbQw6o5L9+x+ SVCMBiGF8UbjOJNbQ2I/pxCAo+3S8xRmOjQh6zj0iC78UX72EOCM+1UlE5x40pK5 UOiC82VnaK5NiiqQBOjtHwCfpocuH8LY5yIVw1GqSMqDp4nnuEmXxOy2cfGYyDuo Yb+CQkXijc9bG+847lZeV4Ia/tS2DuzpopgXo5uC8TSD7baZJGYduksq/lLRNVIT eTo4optqynXpGH90uVoopbTsP91hQ9SiZoMi8uVy4Q/OzOfsCfuwKpb+KGwIGCiT 4N63MuVF/9YkY0+/wBm1pQYtO3ucymvlQNcWRwIDAQABAoIBAEy55UuyGS0GjZ7f S4e3+4RDyPzodyKe02F8WMkc3m5SdxDgKpO347PzLxOBqZXtwfjZSRSSK4TaYXCS mfLtM6qySNJ2jmVI9oUiuNZ9rI7vjToNY+URw3XKEhcCnNcG4rTM8Z90HAz2bTi/ Tvo7qsCt5hci9owQ5QZZEpBdBs6TDXYdbHlFEBVOFs8tHQHZ7AhsP46k8QJ+XwC3 nBh01M6aV4jjJw6nJLCJ+Ow2y2xXlySMHwi7XG/r/L8vHTsBDDtTtumtj4u4fpg9 NkM0SrkjiaSigAdGbO7DYSxZtPaw0+PmVXSosHy65lnlxjf8su9pAwi+PyHUerz2 Q3mDRlkCgYEAzSbdglm8Pfo1ONtb43wkzcn8mtheyiGlG4tpOa9PQl60vKOUEe2V Ou3h095kFArZV+l9f1YFQFqMWYCKD8rFm8fcNKgXyeOZaz/xZlPk6tNohGWOv2jv uC6ihAMiiWPRxxP3T2ls9nW+BNq23WKkrxBwdWoqGMRRJavV2FT+sokCgYEA55Ys J/sGi/VaIL/RCbOiDlYgfzzTBGAAFmjwjvN9A6De8zWZACAXqUiZd61kDZTo8kIZ ys/pI9huaiKhoeM3UyjjeCMemVY94ffaKNFRzk5gxcvDJ6pkyow6pmU/p8pVwcb1 u/+eQ1JIjfxzRwE+z4w8HOGJVi7mDa4ztRAGjk8CgYBdRvyUVgS3EVq9nU9sYXfC ccJ/DT4cHawamAqiBcm93Z3D34RlmmatwpdZY9aRHlWwGSPMj+oXVpRV5ZHgmEu9 BuRitMMMMoYBM7Oo2SBOfQ0alaqP8UB9uAaAi4Raf55ULAnYe5Dlhqd9QYy/oChM yOa5HCpD1I8o17aFhC/CMQKBgCy0XYO+Pm5IB4To4kZYKcFQuOc265kdmwa4bS97 KzfHFyKlxwoyJ78i55UloHnKtAkH34i6B8xGnFHaq47fmK9x5i8rwF1jO4DiYnec qIkFskKcaei/SMOcvDmgs+AE+/bzHD6VQozGVoEqKWqcf+56qKP+mY9McFZVuV+L X2ibAoGALs+PgMHw1LkzwfA4n9jB4L48FN5TdpdL5P6VckujqCZaZyjoJ6cVq9gw lFf5lCpHmqIOzxDTzR2Mj8b7mT1q+a7az1BqDwpXG8rwNmhyx22RdyJSY4hiUHAx 0QL3ZcIXOyqneMXU+a2Qoj3aMAr2ZUS2OEpWEtmPfXcxf5DHaB4= -----END RSA PRIVATE KEY----- �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/exp-cert.pem��������������������������������������0000644�0001750�0001750�00000002714�11544576223�025427� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIIEHDCCAwagAwIBAgIBAjALBgkqhkiG9w0BAQUwbDELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTERMA8G A1UECBMIQ29uZnVzZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTAeFw0w OTA5MTExMjU0MDBaFw0wOTA5MTIxMjU0MDBaMGkxCzAJBgNVBAYTAlVLMRIwEAYD VQQKEwlDb2xsYWJvcmExGTAXBgNVBAsTEFdvY2t5IFRlc3QgU3VpdGUxDjAMBgNV BAgTBURhemVkMRswGQYDVQQDExJXb2NreSBYTVBQIExpYnJhcnkwggEfMAsGCSqG SIb3DQEBAQOCAQ4AMIIBCQKCAQCeUF/jv6V1BGXNb+epimCBLHRqVXpOQud/uC3R YgG/hcagM4kUqavAyQSIa83Oc9L01SY38QNENbs4YdLBH0Gvxo4Sc3A/X8IZp23l g6mSwxZzWoRO/D0g5bxDAkCXY+hh+ed4HnfHo+a1J/bVnyNwd6ssagQfyCXX0hCm D4sNk4DFmWr30oEVMRo5jaTcRoyXf5ATuBa8D0bluwOaqccaosFLS6m6B0c8o6OO uT7SM+9VvzG1BU+TzttZrKJmLh2vrKV09+InixDFMfemWGUCHf183xn9Sb1blNyj M++ZgTs98dbJXStzxYLMNkeJFZtroMi6wzgt1Kbfe9XrcaChAgMBAAGjgdIwgc8w DAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwIQYD VR0RBBowGIIQd2Vhc2VsLWp1aWNlLm9yZ4cEfwAAATAPBgNVHQ8BAf8EBQMDByAA MB0GA1UdDgQWBBSp54s9nx3wWAR/8iKl1XGPyKC/VTAfBgNVHSMEGDAWgBRJMCYI jJrWac2LwMwOXAKOSh+mjDAsBgNVHR8EJTAjMCGgH6AdhhtmaWxlOi8vL3RtcC93 b2NreS10ZXN0cy9jcmwwCwYJKoZIhvcNAQEFA4IBAQCzzxwwXOB5xnaKoDerB6fq QbUmyi5Xj/c1kNgN5WnICUJc8bgXWlhLtvXyEE+/2Gshv6rOwpeH7pO4wtACaiHH NmR78Z1OPKlf4+Bxo5/wQhx228gCOsRpFK+qab5s5/OhmJe4r4AyWoF4CPYfyE0v Z5PkOeFiYc5VSJdI7y360zPV8FBYcASU90aCjREDAi+FK0r+Bp2OdxiTRL9N+mEM blgInz/adg74oDjPmrwENkEZbaKyVwL9WBUD7OABIA42exK8nvCwPRiu1//8ALSR wXTAhJ3lOIG4FOoOKBu9sIY/iRL/mJa39YJHG+gVFx+taJKB95tHthGuPraGJjch -----END CERTIFICATE----- ����������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/cas/����������������������������������������������0000775�0001750�0001750�00000000000�12332445273�023735� 5����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/cas/ae5bb84e.0������������������������������������0000644�0001750�0001750�00000002603�11544576223�025320� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIID5jCCAtCgAwIBAgIBATALBgkqhkiG9w0BAQUwbDELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTERMA8G A1UECBMIU3BpbmRsZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTAeFw0w OTA5MTgxMjU1MDVaFw0zNzA5MTExMjU1MDVaMGwxCzAJBgNVBAYTAlVLMRIwEAYD VQQKEwlDb2xsYWJvcmExGTAXBgNVBAsTEFdvY2t5IFRlc3QgU3VpdGUxETAPBgNV BAgTCFNwaW5kbGVkMRswGQYDVQQDExJXb2NreSBYTVBQIExpYnJhcnkwggEfMAsG CSqGSIb3DQEBAQOCAQ4AMIIBCQKCAQC+YAQjeUbAlnnvhQ4imQbL4aU8sJjM/M7g gm51NdXev3WwvOdDDU8LgvaKIoMQyQaS5XAt4Q/hAeHZJW0Nx3zZW9XWiqmHlqsU LdQKvxIz9xnvLRR74gHddMXqsPCHieSNvXm4cnnNPIwmWNiBIo5NdI/Te+tNmGqz pO4t1G9jYlhGNhc2vUIpDo4bO2vWqeRyqnQlrAykfZsScjryZtMBDSc9xZdjJlJt 2nbLlQJVUgi1bEwazP3SWEijfZTKhnXn0bvhFGUSEssHb5CUVr6ILRzWJtAVp/us YAaQLZLhMhcA94YvFB0dlVltsdtvwBPidEC4NMPJcitN/3s1fQbPAgMBAAGjgZkw gZYwDwYDVR0TAQH/BAUwAwEB/zAlBgNVHREEHjAcgRpwb3N0bWFzdGVyQGNvbGxh Ym9yYS5jby51azAPBgNVHQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBTeKryla1ofuyCr Gg3ugeTEymWLhzAsBgNVHR8EJTAjMCGgH6AdhhtmaWxlOi8vL3RtcC93b2NreS10 ZXN0cy9jcmwwCwYJKoZIhvcNAQEFA4IBAQC2RqDYK3xPnMGnlzJBVJI4cPH/iRLi 9ZUWmBzpjHpo0d/in6lAF0UirmjpgllXpCUhJMfP5fxOsZYk1eE/leqTyTory7Xj K6zdHmkFGPU3b5ibFPX65iGFpqZdjCAplFZ9HI7au1b0SpbsMKesE7ZXzBF0+ki3 GrKgQF+e7cMktJf07I4xoVVYimSpADFOHo9Pk1sceK/zSKGzob7TziD4Tpnc8Rhq dOj7J8EbzhqjBVciPYzXvlLjyAqdYRg5RHV1xSIvYKeK0PwVzmNY9Xu30+VShJHc 3Hf/VLl2T1ll8tXUj3hc1Jd2+ZMthTF1PIX3bunTnNUm2PENoxa8pDG3 -----END CERTIFICATE----- �����������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/cas/ca-0-cert.pem���������������������������������0000644�0001750�0001750�00000002603�11544576223�026116� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIID5jCCAtCgAwIBAgIBATALBgkqhkiG9w0BAQUwbDELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTERMA8G A1UECBMIQ29uZnVzZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTAeFw0w OTA5MTgxMjE3MDZaFw0zNzA5MTExMjE3MDZaMGwxCzAJBgNVBAYTAlVLMRIwEAYD VQQKEwlDb2xsYWJvcmExGTAXBgNVBAsTEFdvY2t5IFRlc3QgU3VpdGUxETAPBgNV BAgTCENvbmZ1c2VkMRswGQYDVQQDExJXb2NreSBYTVBQIExpYnJhcnkwggEfMAsG CSqGSIb3DQEBAQOCAQ4AMIIBCQKCAQDfmrRZUa4UWDLgmHNRUaXIEwhwSQRESTF1 fWd+NP5xMO65OE0JAmzk4rdPH8xiuba3WnVVvA+nop53lC7emTTMVzWLWLJEV3f2 1xNeHCRWxkmzAwAF+x9y9zGV4mRgMWk26g0C0dmaYPILcTciYRwjvawEdd78z09w BSGdYx1Ya+Mr9BBl2tThD4cliV6DVdlwhnvu7eamrQ/LdeS/n4Z+X8MYW+G49a8b vqHvpp7MS8pIwEMfgkzfuG+K/++Cvz5WfOfnDYH13ahTks7k0RB16rt1qUnvF66r zYJbzqJSc4mbhcOJuFURXeiZKY2f78W1b6RRTvENISdnGKJPwMxZAgMBAAGjgZkw gZYwDwYDVR0TAQH/BAUwAwEB/zAlBgNVHREEHjAcgRpwb3N0bWFzdGVyQGNvbGxh Ym9yYS5jby51azAPBgNVHQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBRJMCYIjJrWac2L wMwOXAKOSh+mjDAsBgNVHR8EJTAjMCGgH6AdhhtmaWxlOi8vL3RtcC93b2NreS10 ZXN0cy9jcmwwCwYJKoZIhvcNAQEFA4IBAQCL+FK+IzN9Z88ePw/MU2Y1Yd2oigeb /02d7DrzQQXpSN1y3t0LKpi3MM7QbGDVUmC6WI7Tpe9wf0G6ZTfZ6jMeS/4OpeG+ QNRWxAWtAv1+QDEtHf9rVFKjl9SUbKhbsLHePggS52LV/YTwD1PxbCsl75jpaCvU W22tTJL0K1lFBYLM0IxiOkn+vrWNsOYfVpXZbjB4ExLeNp1li2tetXJLluMgeGr5 bKYmWfYyze6FOcp1zQh13e6I0DqIh7F6hb/nKaWcJKSNsq8JsgLWTba8iDF24X5C 2l+SJE0iNtg08tC6XdZ9v1DQUHKIKSX7L5MEVgHbLiOKroriqVeQu8zK -----END CERTIFICATE----- �����������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/cas/c5d5c0da.0������������������������������������0000644�0001750�0001750�00000002603�11544576223�025311� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIID5jCCAtCgAwIBAgIBATALBgkqhkiG9w0BAQUwbDELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTERMA8G A1UECBMIQ29uZnVzZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTAeFw0w OTA5MTgxMjE3MDZaFw0zNzA5MTExMjE3MDZaMGwxCzAJBgNVBAYTAlVLMRIwEAYD VQQKEwlDb2xsYWJvcmExGTAXBgNVBAsTEFdvY2t5IFRlc3QgU3VpdGUxETAPBgNV BAgTCENvbmZ1c2VkMRswGQYDVQQDExJXb2NreSBYTVBQIExpYnJhcnkwggEfMAsG CSqGSIb3DQEBAQOCAQ4AMIIBCQKCAQDfmrRZUa4UWDLgmHNRUaXIEwhwSQRESTF1 fWd+NP5xMO65OE0JAmzk4rdPH8xiuba3WnVVvA+nop53lC7emTTMVzWLWLJEV3f2 1xNeHCRWxkmzAwAF+x9y9zGV4mRgMWk26g0C0dmaYPILcTciYRwjvawEdd78z09w BSGdYx1Ya+Mr9BBl2tThD4cliV6DVdlwhnvu7eamrQ/LdeS/n4Z+X8MYW+G49a8b vqHvpp7MS8pIwEMfgkzfuG+K/++Cvz5WfOfnDYH13ahTks7k0RB16rt1qUnvF66r zYJbzqJSc4mbhcOJuFURXeiZKY2f78W1b6RRTvENISdnGKJPwMxZAgMBAAGjgZkw gZYwDwYDVR0TAQH/BAUwAwEB/zAlBgNVHREEHjAcgRpwb3N0bWFzdGVyQGNvbGxh Ym9yYS5jby51azAPBgNVHQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBRJMCYIjJrWac2L wMwOXAKOSh+mjDAsBgNVHR8EJTAjMCGgH6AdhhtmaWxlOi8vL3RtcC93b2NreS10 ZXN0cy9jcmwwCwYJKoZIhvcNAQEFA4IBAQCL+FK+IzN9Z88ePw/MU2Y1Yd2oigeb /02d7DrzQQXpSN1y3t0LKpi3MM7QbGDVUmC6WI7Tpe9wf0G6ZTfZ6jMeS/4OpeG+ QNRWxAWtAv1+QDEtHf9rVFKjl9SUbKhbsLHePggS52LV/YTwD1PxbCsl75jpaCvU W22tTJL0K1lFBYLM0IxiOkn+vrWNsOYfVpXZbjB4ExLeNp1li2tetXJLluMgeGr5 bKYmWfYyze6FOcp1zQh13e6I0DqIh7F6hb/nKaWcJKSNsq8JsgLWTba8iDF24X5C 2l+SJE0iNtg08tC6XdZ9v1DQUHKIKSX7L5MEVgHbLiOKroriqVeQu8zK -----END CERTIFICATE----- �����������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/cas/8a76ade9.0������������������������������������0000644�0001750�0001750�00000002577�11544576223�025263� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIID4jCCAsygAwIBAgIBATALBgkqhkiG9w0BAQUwajELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTEPMA0G A1UECBMGRm9sZGVkMRswGQYDVQQDExJXb2NreSBYTVBQIExpYnJhcnkwHhcNMDkw OTE4MTI1NTAzWhcNMzcwOTExMTI1NTAzWjBqMQswCQYDVQQGEwJVSzESMBAGA1UE ChMJQ29sbGFib3JhMRkwFwYDVQQLExBXb2NreSBUZXN0IFN1aXRlMQ8wDQYDVQQI EwZGb2xkZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTCCAR8wCwYJKoZI hvcNAQEBA4IBDgAwggEJAoIBANRkYbvqWdla+zNLsftXYnaAD0agDbNl70y4yxNj V1DriZnNgjgWM8ZIgUdvFx+sA8wMoRFBLnXWYfzI+fHYFak+JqysvQmqTifXjKOs Q8Qdhb3hc2z10X7pobRK+oxE7VXDKKp5ou4f3wx1mvSTjB1oTr5o2ZnA5K/dLCM7 OmJ2C/Vj8z6l6HV41esPEYEZv+wfP/9z3xmNhNHcRWIeipEdDZDfXc0n22SeEnGS ZrSJDP9CZaJWAcLUhD5OEh+B3P/gfO9KDAN8PicSFFXj2X0t8incmz5fs6JosgEF o40D/R4xUIU562HEY/4uOM6N2nHM+MKgiDHEUh9s3lLmSB8CAwEAAaOBmTCBljAP BgNVHRMBAf8EBTADAQH/MCUGA1UdEQQeMByBGnBvc3RtYXN0ZXJAY29sbGFib3Jh LmNvLnVrMA8GA1UdDwEB/wQFAwMHBgAwHQYDVR0OBBYEFJdQenuGG7TS4L2av7+3 HHWC+uO7MCwGA1UdHwQlMCMwIaAfoB2GG2ZpbGU6Ly8vdG1wL3dvY2t5LXRlc3Rz L2NybDALBgkqhkiG9w0BAQUDggEBAI2E2XcrxGbK+e9CdIxnrVWsh8HgcvBB/F4M 9jRUSjc3+w3E1zxlyfqGgSrzCJIpZbq7TQ7tTd1AV8j9hP4bP1r3BX6lhiXRtRKC thobgl1gXQtHkFhRpZrWe4vECqucHlznel9nhtLeY50ykt8ajvqxhthe/uabKNlo wC87Aq1ykigR1imLAY8UdvdXfvnfS1d5bF/k3TSw2YOZE4u8KToQf1LVPIG12OPi uStuIX9UYzSe8qOurrbjX+qehoubmrgLPGRKyNfIHsp7Arr/yUnjK5WtojTjcF85 nuP8FceVT5cvKYYPcBP6+YpAeeBJBiK95kzZGqgVewoLpKJht+0= -----END CERTIFICATE----- ���������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/cas/a7481a9e.0������������������������������������0000644�0001750�0001750�00000002603�11544576223�025164� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIID5jCCAtCgAwIBAgIBATALBgkqhkiG9w0BAQUwbDELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTERMA8G A1UECBMIU3BpbmRsZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTAeFw0w OTA5MTgxMjU1MDVaFw0zNzA5MTExMjU1MDVaMGwxCzAJBgNVBAYTAlVLMRIwEAYD VQQKEwlDb2xsYWJvcmExGTAXBgNVBAsTEFdvY2t5IFRlc3QgU3VpdGUxETAPBgNV BAgTCFNwaW5kbGVkMRswGQYDVQQDExJXb2NreSBYTVBQIExpYnJhcnkwggEfMAsG CSqGSIb3DQEBAQOCAQ4AMIIBCQKCAQC+YAQjeUbAlnnvhQ4imQbL4aU8sJjM/M7g gm51NdXev3WwvOdDDU8LgvaKIoMQyQaS5XAt4Q/hAeHZJW0Nx3zZW9XWiqmHlqsU LdQKvxIz9xnvLRR74gHddMXqsPCHieSNvXm4cnnNPIwmWNiBIo5NdI/Te+tNmGqz pO4t1G9jYlhGNhc2vUIpDo4bO2vWqeRyqnQlrAykfZsScjryZtMBDSc9xZdjJlJt 2nbLlQJVUgi1bEwazP3SWEijfZTKhnXn0bvhFGUSEssHb5CUVr6ILRzWJtAVp/us YAaQLZLhMhcA94YvFB0dlVltsdtvwBPidEC4NMPJcitN/3s1fQbPAgMBAAGjgZkw gZYwDwYDVR0TAQH/BAUwAwEB/zAlBgNVHREEHjAcgRpwb3N0bWFzdGVyQGNvbGxh Ym9yYS5jby51azAPBgNVHQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBTeKryla1ofuyCr Gg3ugeTEymWLhzAsBgNVHR8EJTAjMCGgH6AdhhtmaWxlOi8vL3RtcC93b2NreS10 ZXN0cy9jcmwwCwYJKoZIhvcNAQEFA4IBAQC2RqDYK3xPnMGnlzJBVJI4cPH/iRLi 9ZUWmBzpjHpo0d/in6lAF0UirmjpgllXpCUhJMfP5fxOsZYk1eE/leqTyTory7Xj K6zdHmkFGPU3b5ibFPX65iGFpqZdjCAplFZ9HI7au1b0SpbsMKesE7ZXzBF0+ki3 GrKgQF+e7cMktJf07I4xoVVYimSpADFOHo9Pk1sceK/zSKGzob7TziD4Tpnc8Rhq dOj7J8EbzhqjBVciPYzXvlLjyAqdYRg5RHV1xSIvYKeK0PwVzmNY9Xu30+VShJHc 3Hf/VLl2T1ll8tXUj3hc1Jd2+ZMthTF1PIX3bunTnNUm2PENoxa8pDG3 -----END CERTIFICATE----- �����������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/cas/bb7d74ae.0������������������������������������0000644�0001750�0001750�00000002577�11544576223�025332� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIID4jCCAsygAwIBAgIBATALBgkqhkiG9w0BAQUwajELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTEPMA0G A1UECBMGRm9sZGVkMRswGQYDVQQDExJXb2NreSBYTVBQIExpYnJhcnkwHhcNMDkw OTE4MTI1NTAzWhcNMzcwOTExMTI1NTAzWjBqMQswCQYDVQQGEwJVSzESMBAGA1UE ChMJQ29sbGFib3JhMRkwFwYDVQQLExBXb2NreSBUZXN0IFN1aXRlMQ8wDQYDVQQI EwZGb2xkZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTCCAR8wCwYJKoZI hvcNAQEBA4IBDgAwggEJAoIBANRkYbvqWdla+zNLsftXYnaAD0agDbNl70y4yxNj V1DriZnNgjgWM8ZIgUdvFx+sA8wMoRFBLnXWYfzI+fHYFak+JqysvQmqTifXjKOs Q8Qdhb3hc2z10X7pobRK+oxE7VXDKKp5ou4f3wx1mvSTjB1oTr5o2ZnA5K/dLCM7 OmJ2C/Vj8z6l6HV41esPEYEZv+wfP/9z3xmNhNHcRWIeipEdDZDfXc0n22SeEnGS ZrSJDP9CZaJWAcLUhD5OEh+B3P/gfO9KDAN8PicSFFXj2X0t8incmz5fs6JosgEF o40D/R4xUIU562HEY/4uOM6N2nHM+MKgiDHEUh9s3lLmSB8CAwEAAaOBmTCBljAP BgNVHRMBAf8EBTADAQH/MCUGA1UdEQQeMByBGnBvc3RtYXN0ZXJAY29sbGFib3Jh LmNvLnVrMA8GA1UdDwEB/wQFAwMHBgAwHQYDVR0OBBYEFJdQenuGG7TS4L2av7+3 HHWC+uO7MCwGA1UdHwQlMCMwIaAfoB2GG2ZpbGU6Ly8vdG1wL3dvY2t5LXRlc3Rz L2NybDALBgkqhkiG9w0BAQUDggEBAI2E2XcrxGbK+e9CdIxnrVWsh8HgcvBB/F4M 9jRUSjc3+w3E1zxlyfqGgSrzCJIpZbq7TQ7tTd1AV8j9hP4bP1r3BX6lhiXRtRKC thobgl1gXQtHkFhRpZrWe4vECqucHlznel9nhtLeY50ykt8ajvqxhthe/uabKNlo wC87Aq1ykigR1imLAY8UdvdXfvnfS1d5bF/k3TSw2YOZE4u8KToQf1LVPIG12OPi uStuIX9UYzSe8qOurrbjX+qehoubmrgLPGRKyNfIHsp7Arr/yUnjK5WtojTjcF85 nuP8FceVT5cvKYYPcBP6+YpAeeBJBiK95kzZGqgVewoLpKJht+0= -----END CERTIFICATE----- ���������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/cas/ca-2-cert.pem���������������������������������0000644�0001750�0001750�00000002603�11544576223�026120� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIID5jCCAtCgAwIBAgIBATALBgkqhkiG9w0BAQUwbDELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTERMA8G A1UECBMIU3BpbmRsZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTAeFw0w OTA5MTgxMjU1MDVaFw0zNzA5MTExMjU1MDVaMGwxCzAJBgNVBAYTAlVLMRIwEAYD VQQKEwlDb2xsYWJvcmExGTAXBgNVBAsTEFdvY2t5IFRlc3QgU3VpdGUxETAPBgNV BAgTCFNwaW5kbGVkMRswGQYDVQQDExJXb2NreSBYTVBQIExpYnJhcnkwggEfMAsG CSqGSIb3DQEBAQOCAQ4AMIIBCQKCAQC+YAQjeUbAlnnvhQ4imQbL4aU8sJjM/M7g gm51NdXev3WwvOdDDU8LgvaKIoMQyQaS5XAt4Q/hAeHZJW0Nx3zZW9XWiqmHlqsU LdQKvxIz9xnvLRR74gHddMXqsPCHieSNvXm4cnnNPIwmWNiBIo5NdI/Te+tNmGqz pO4t1G9jYlhGNhc2vUIpDo4bO2vWqeRyqnQlrAykfZsScjryZtMBDSc9xZdjJlJt 2nbLlQJVUgi1bEwazP3SWEijfZTKhnXn0bvhFGUSEssHb5CUVr6ILRzWJtAVp/us YAaQLZLhMhcA94YvFB0dlVltsdtvwBPidEC4NMPJcitN/3s1fQbPAgMBAAGjgZkw gZYwDwYDVR0TAQH/BAUwAwEB/zAlBgNVHREEHjAcgRpwb3N0bWFzdGVyQGNvbGxh Ym9yYS5jby51azAPBgNVHQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBTeKryla1ofuyCr Gg3ugeTEymWLhzAsBgNVHR8EJTAjMCGgH6AdhhtmaWxlOi8vL3RtcC93b2NreS10 ZXN0cy9jcmwwCwYJKoZIhvcNAQEFA4IBAQC2RqDYK3xPnMGnlzJBVJI4cPH/iRLi 9ZUWmBzpjHpo0d/in6lAF0UirmjpgllXpCUhJMfP5fxOsZYk1eE/leqTyTory7Xj K6zdHmkFGPU3b5ibFPX65iGFpqZdjCAplFZ9HI7au1b0SpbsMKesE7ZXzBF0+ki3 GrKgQF+e7cMktJf07I4xoVVYimSpADFOHo9Pk1sceK/zSKGzob7TziD4Tpnc8Rhq dOj7J8EbzhqjBVciPYzXvlLjyAqdYRg5RHV1xSIvYKeK0PwVzmNY9Xu30+VShJHc 3Hf/VLl2T1ll8tXUj3hc1Jd2+ZMthTF1PIX3bunTnNUm2PENoxa8pDG3 -----END CERTIFICATE----- �����������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/cas/ca-1-cert.pem���������������������������������0000644�0001750�0001750�00000002577�11544576223�026131� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIID4jCCAsygAwIBAgIBATALBgkqhkiG9w0BAQUwajELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTEPMA0G A1UECBMGRm9sZGVkMRswGQYDVQQDExJXb2NreSBYTVBQIExpYnJhcnkwHhcNMDkw OTE4MTI1NTAzWhcNMzcwOTExMTI1NTAzWjBqMQswCQYDVQQGEwJVSzESMBAGA1UE ChMJQ29sbGFib3JhMRkwFwYDVQQLExBXb2NreSBUZXN0IFN1aXRlMQ8wDQYDVQQI EwZGb2xkZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTCCAR8wCwYJKoZI hvcNAQEBA4IBDgAwggEJAoIBANRkYbvqWdla+zNLsftXYnaAD0agDbNl70y4yxNj V1DriZnNgjgWM8ZIgUdvFx+sA8wMoRFBLnXWYfzI+fHYFak+JqysvQmqTifXjKOs Q8Qdhb3hc2z10X7pobRK+oxE7VXDKKp5ou4f3wx1mvSTjB1oTr5o2ZnA5K/dLCM7 OmJ2C/Vj8z6l6HV41esPEYEZv+wfP/9z3xmNhNHcRWIeipEdDZDfXc0n22SeEnGS ZrSJDP9CZaJWAcLUhD5OEh+B3P/gfO9KDAN8PicSFFXj2X0t8incmz5fs6JosgEF o40D/R4xUIU562HEY/4uOM6N2nHM+MKgiDHEUh9s3lLmSB8CAwEAAaOBmTCBljAP BgNVHRMBAf8EBTADAQH/MCUGA1UdEQQeMByBGnBvc3RtYXN0ZXJAY29sbGFib3Jh LmNvLnVrMA8GA1UdDwEB/wQFAwMHBgAwHQYDVR0OBBYEFJdQenuGG7TS4L2av7+3 HHWC+uO7MCwGA1UdHwQlMCMwIaAfoB2GG2ZpbGU6Ly8vdG1wL3dvY2t5LXRlc3Rz L2NybDALBgkqhkiG9w0BAQUDggEBAI2E2XcrxGbK+e9CdIxnrVWsh8HgcvBB/F4M 9jRUSjc3+w3E1zxlyfqGgSrzCJIpZbq7TQ7tTd1AV8j9hP4bP1r3BX6lhiXRtRKC thobgl1gXQtHkFhRpZrWe4vECqucHlznel9nhtLeY50ykt8ajvqxhthe/uabKNlo wC87Aq1ykigR1imLAY8UdvdXfvnfS1d5bF/k3TSw2YOZE4u8KToQf1LVPIG12OPi uStuIX9UYzSe8qOurrbjX+qehoubmrgLPGRKyNfIHsp7Arr/yUnjK5WtojTjcF85 nuP8FceVT5cvKYYPcBP6+YpAeeBJBiK95kzZGqgVewoLpKJht+0= -----END CERTIFICATE----- ���������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/cas/e7df1717.0������������������������������������0000644�0001750�0001750�00000002603�11544576223�025166� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIID5jCCAtCgAwIBAgIBATALBgkqhkiG9w0BAQUwbDELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTERMA8G A1UECBMIQ29uZnVzZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTAeFw0w OTA5MTgxMjE3MDZaFw0zNzA5MTExMjE3MDZaMGwxCzAJBgNVBAYTAlVLMRIwEAYD VQQKEwlDb2xsYWJvcmExGTAXBgNVBAsTEFdvY2t5IFRlc3QgU3VpdGUxETAPBgNV BAgTCENvbmZ1c2VkMRswGQYDVQQDExJXb2NreSBYTVBQIExpYnJhcnkwggEfMAsG CSqGSIb3DQEBAQOCAQ4AMIIBCQKCAQDfmrRZUa4UWDLgmHNRUaXIEwhwSQRESTF1 fWd+NP5xMO65OE0JAmzk4rdPH8xiuba3WnVVvA+nop53lC7emTTMVzWLWLJEV3f2 1xNeHCRWxkmzAwAF+x9y9zGV4mRgMWk26g0C0dmaYPILcTciYRwjvawEdd78z09w BSGdYx1Ya+Mr9BBl2tThD4cliV6DVdlwhnvu7eamrQ/LdeS/n4Z+X8MYW+G49a8b vqHvpp7MS8pIwEMfgkzfuG+K/++Cvz5WfOfnDYH13ahTks7k0RB16rt1qUnvF66r zYJbzqJSc4mbhcOJuFURXeiZKY2f78W1b6RRTvENISdnGKJPwMxZAgMBAAGjgZkw gZYwDwYDVR0TAQH/BAUwAwEB/zAlBgNVHREEHjAcgRpwb3N0bWFzdGVyQGNvbGxh Ym9yYS5jby51azAPBgNVHQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBRJMCYIjJrWac2L wMwOXAKOSh+mjDAsBgNVHR8EJTAjMCGgH6AdhhtmaWxlOi8vL3RtcC93b2NreS10 ZXN0cy9jcmwwCwYJKoZIhvcNAQEFA4IBAQCL+FK+IzN9Z88ePw/MU2Y1Yd2oigeb /02d7DrzQQXpSN1y3t0LKpi3MM7QbGDVUmC6WI7Tpe9wf0G6ZTfZ6jMeS/4OpeG+ QNRWxAWtAv1+QDEtHf9rVFKjl9SUbKhbsLHePggS52LV/YTwD1PxbCsl75jpaCvU W22tTJL0K1lFBYLM0IxiOkn+vrWNsOYfVpXZbjB4ExLeNp1li2tetXJLluMgeGr5 bKYmWfYyze6FOcp1zQh13e6I0DqIh7F6hb/nKaWcJKSNsq8JsgLWTba8iDF24X5C 2l+SJE0iNtg08tC6XdZ9v1DQUHKIKSX7L5MEVgHbLiOKroriqVeQu8zK -----END CERTIFICATE----- �����������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/unknown-key.pem�����������������������������������0000644�0001750�0001750�00000003217�11544576223�026164� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN RSA PRIVATE KEY----- MIIEpQIBAAKCAQEAvpcNcJNSz2GrNEEWNMaXDqNFZaEcBJ0Tx4QTVA66HaKPXSm7 sS3oYikt9bzeLp1lJqtJqJ8bJiRD6rH3vKMJjunw1BphOPsIAOtNcu0slWR5WKGK DfZfj0+KF7QSbKJ5cx03tV3IFMOg8SCW/HnIDT+yt0OWTo2qtF0BpnFbBUGUgCgO 15Mwo1tqRA02NUJ/Hr87oppVF1/o8qxDf1r5u/icW7C+czLvLOaYCrYwJFjno7IS 5RlkqjhSvNt3whaZfGCS8qriWb+mdTzKEguBawbn0lyFp/R7RfkyDRHKjrl5b2jE L430TvQx8epfGzoQpyoQWQk2IcMZTukCkJIZKQIDAQABAoIBABKIZDNr8/u7+tam NJdVr0cqW7tt7uhI8O0v++Qq2XC7x7aOshRgyy3OZMx2POGqBvW7Zrp5nD15fcwy 2YzziqClwXgSh50vld/nAZ05EGKHhmA2txK0ACdSm/JBnaAILYii0PG3KJdSTZJc 8amj2u7k4Ic/EHzbfDu1Jo2tjKUGSEhECOKsl3I+yrnjlRl8rla7ck8KFY7OJmkp +N4+byV+o+9fz5rxWw9A3yZYa5V3vOMc0tAIQGh0TcDqkRsMONJesFf418W9fqE+ ZZos8qw7Si6sXS1Xge7I/+3SbdzxpI8Wf3HmyEpKIuqAFFtCFd7mvF8UjgNNW8hF Ga8Qkr0CgYEA2Sq4lADOwJt6p1g03Gy4AbS+4hcEKjJ4fEoJuQs6OauDgc1Sp2OM Ee1560XaJK95ccZyFrO6uNO0A9cwCtTTqUkmYFzwtUXzMGa4eQcUjS2aYWIS/yw+ HwCEkQKuzWy0mDeDgWvAjEczgj9ZzVDJoucA51PlmBBuv4Hn0OWz2lUCgYEA4Ku4 XTblxlWzJfnNXUkWSsguUuroH2O8V6WOds0igxuLDMwFLBxROsL1EcpZod8XoBcM MATwJJ0smK65DXnOibMzqUYXOPRfyy360TnIMOaqgKKo6t9ZZMQJiNWq+liZ6gli n43QOxDibojbeWIjLLRGooPFcVfOAWER3eoL/4UCgYEAmKIsJOoEZt9gb6nRTXOk SJ6u4t1mcfoTMNggyUwY2luwDFUxWLDgy+DrJe9siQhEBTGDEm20OR+ikGh4PcSk F4FwVZ49GEtXx5cK5RWS3j9FGFkEHRENgGCuy/Tkw0E6FRo/dYE0TePlUhAQn/u+ HJ7bxbrzzdMO4878DZjEthkCgYEAuCusPyVQaCw6ZggHU9Ak6Pp+FtSfoZOlggeh 6Dsybl02uC/KkaVI5S2JraK9pRb3C/G4uOhjXvBE7YhVA/n02CZBVCKzyKlymWDA uaBvPb7ox/gPFjIu2o5k7nmQ5hWZXiOBaB/dMX4ez9N6bl+HTA8f0/rG8Km0oqbK +anxWe0CgYEAvTT09MGFC8jELxU7vD95euAvdeC4wCOhmNTk99kx2QLvOLqFo6GN wtzu2j1bTO29uX7DQ8iVcqQTuVO9nz6APhSwnkXvtN7tHHUiAKSJewXrBIgsVvY7 E0Ilhz/ILcmuigxe9tB682x9V6NuUhMZnhPvyZFxSM+JCTAfkwmPbj8= -----END RSA PRIVATE KEY----- ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/exp-cert.cfg��������������������������������������0000644�0001750�0001750�00000004146�11544576223�025406� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# X.509 Certificate options # # DN options # The organization of the subject. organization = "Collabora" # The organizational unit of the subject. unit = "Wocky Test Suite" # The locality of the subject. # locality = # The state of the certificate owner. state = "Dazed" # The country of the subject. Two letter code. country = UK # The common name of the certificate owner. cn = "Wocky XMPP Library" # A user id of the certificate owner. #uid = "clauper" # If the supported DN OIDs are not adequate you can set # any OID here. # For example set the X.520 Title and the X.520 Pseudonym # by using OID and string pairs. #dn_oid = "2.5.4.12" "Dr." "2.5.4.65" "jackal" # This is deprecated and should not be used in new # certificates. # pkcs9_email = "none@none.org" # The serial number of the certificate serial = 002 # In how many days, counting from today, this certificate will expire. expiration_days = 1 # X.509 v3 extensions # A dnsname in case of a WWW server. dns_name = "weasel-juice.org" #dns_name = "www.morethanone.org" # An IP address in case of a server. ip_address = "127.0.0.1" # An email in case of a person #email = "postmaster@collabora.co.uk" # An URL that has CRLs (certificate revocation lists) # available. Needed in CA certificates. #crl_dist_points = "file:///tmp/wocky-tests/crl" # Whether this is a CA certificate or not #ca # Whether this certificate will be used for a TLS client tls_www_client # Whether this certificate will be used for a TLS server tls_www_server # Whether this certificate will be used to sign data (needed # in TLS DHE ciphersuites). #signing_key # Whether this certificate will be used to encrypt data (needed # in TLS RSA ciphersuites). Note that it is prefered to use different # keys for encryption and signing. encryption_key # Whether this key will be used to sign other certificates. #cert_signing_key # Whether this key will be used to sign CRLs. #crl_signing_key # Whether this key will be used to sign code. #code_signing_key # Whether this key will be used to sign OCSP data. #ocsp_signing_key # Whether this key will be used for time stamping. time_stamping_key ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/rev-cert.pem��������������������������������������0000644�0001750�0001750�00000002714�11544576223�025427� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIIEHDCCAwagAwIBAgIBCzALBgkqhkiG9w0BAQUwbDELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTERMA8G A1UECBMIQ29uZnVzZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTAeFw0w OTA5MTgxMjU0MTJaFw0zNzA5MTExMjU0MTJaMGkxCzAJBgNVBAYTAlVLMRIwEAYD VQQKEwlDb2xsYWJvcmExGTAXBgNVBAsTEFdvY2t5IFRlc3QgU3VpdGUxDjAMBgNV BAgTBURhemVkMRswGQYDVQQDExJXb2NreSBYTVBQIExpYnJhcnkwggEfMAsGCSqG SIb3DQEBAQOCAQ4AMIIBCQKCAQCnyZpKt7FMekFO9OTzIZzQPTzVH3FCBjhoViBh StC9oWcCFr6+RHNpi3UUG+ytgly7Clar3cz+D3tPKWWfeMo04895h6/B1wUBvtpj NZxVtc2yvomKcoCyWayWnuucTRb1wbAB0+shsuBKHBD4L2Ws7oHkn0wmVd0HYoay rXUBMmQui7Y5kYh0LaB+gcxmu/RohSwvBvpSukOl8OOkB6ngHfoJtX3SrjdTHICY 2/Ua2fOxv+nh6hOy5xy7fapYMFNtdvNClifqLvK7VrimVqNxtiSZKNGTVoTPBWag o+NV2abNYjSstGkUWhq4ZI4NmkyDcHTeAtfx/142VXPqGu0LAgMBAAGjgdIwgc8w DAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwIQYD VR0RBBowGIIQd2Vhc2VsLWp1aWNlLm9yZ4cEfwAAATAPBgNVHQ8BAf8EBQMDByAA MB0GA1UdDgQWBBR2DyOQu6Qw1sh+lkkmX7HGJ1scGjAfBgNVHSMEGDAWgBRJMCYI jJrWac2LwMwOXAKOSh+mjDAsBgNVHR8EJTAjMCGgH6AdhhtmaWxlOi8vL3RtcC93 b2NreS10ZXN0cy9jcmwwCwYJKoZIhvcNAQEFA4IBAQDAvd60gplt/Yl/On9Ucht/ rhYfyUzW4pioSLVmiRKhKbDo8ujmhT3vgxdj2nW+uhPMxMbUsgMqj7tOBxIFqXaW Silo+A9iTr3Xxp/oPT+6u0FurGpu50/vPf/TMNhm+ucwYOfvpXVCJgu52c3WXp8R N4jvBOn8+MSlcetBUkmwRoUApNIEp+BglxDDdOB9IWhEZPvgbNokzAPrsoKflpXp pwkUFBuvn6/ffBBHb2I6rF4a4DC6yoK6DCYONzfHUjKMec7ex7CCWKubN31CogvH sb7ugiIFom/dMqjtGtWzG4ilVAQjjV5HJN+RscVp/6c/VY4WEYPfegUReGR0E47h -----END CERTIFICATE----- ����������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/ca-0-cert.pem�������������������������������������0000644�0001750�0001750�00000002603�11544576223�025350� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIID5jCCAtCgAwIBAgIBATALBgkqhkiG9w0BAQUwbDELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTERMA8G A1UECBMIQ29uZnVzZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTAeFw0w OTA5MTgxMjE3MDZaFw0zNzA5MTExMjE3MDZaMGwxCzAJBgNVBAYTAlVLMRIwEAYD VQQKEwlDb2xsYWJvcmExGTAXBgNVBAsTEFdvY2t5IFRlc3QgU3VpdGUxETAPBgNV BAgTCENvbmZ1c2VkMRswGQYDVQQDExJXb2NreSBYTVBQIExpYnJhcnkwggEfMAsG CSqGSIb3DQEBAQOCAQ4AMIIBCQKCAQDfmrRZUa4UWDLgmHNRUaXIEwhwSQRESTF1 fWd+NP5xMO65OE0JAmzk4rdPH8xiuba3WnVVvA+nop53lC7emTTMVzWLWLJEV3f2 1xNeHCRWxkmzAwAF+x9y9zGV4mRgMWk26g0C0dmaYPILcTciYRwjvawEdd78z09w BSGdYx1Ya+Mr9BBl2tThD4cliV6DVdlwhnvu7eamrQ/LdeS/n4Z+X8MYW+G49a8b vqHvpp7MS8pIwEMfgkzfuG+K/++Cvz5WfOfnDYH13ahTks7k0RB16rt1qUnvF66r zYJbzqJSc4mbhcOJuFURXeiZKY2f78W1b6RRTvENISdnGKJPwMxZAgMBAAGjgZkw gZYwDwYDVR0TAQH/BAUwAwEB/zAlBgNVHREEHjAcgRpwb3N0bWFzdGVyQGNvbGxh Ym9yYS5jby51azAPBgNVHQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBRJMCYIjJrWac2L wMwOXAKOSh+mjDAsBgNVHR8EJTAjMCGgH6AdhhtmaWxlOi8vL3RtcC93b2NreS10 ZXN0cy9jcmwwCwYJKoZIhvcNAQEFA4IBAQCL+FK+IzN9Z88ePw/MU2Y1Yd2oigeb /02d7DrzQQXpSN1y3t0LKpi3MM7QbGDVUmC6WI7Tpe9wf0G6ZTfZ6jMeS/4OpeG+ QNRWxAWtAv1+QDEtHf9rVFKjl9SUbKhbsLHePggS52LV/YTwD1PxbCsl75jpaCvU W22tTJL0K1lFBYLM0IxiOkn+vrWNsOYfVpXZbjB4ExLeNp1li2tetXJLluMgeGr5 bKYmWfYyze6FOcp1zQh13e6I0DqIh7F6hb/nKaWcJKSNsq8JsgLWTba8iDF24X5C 2l+SJE0iNtg08tC6XdZ9v1DQUHKIKSX7L5MEVgHbLiOKroriqVeQu8zK -----END CERTIFICATE----- �����������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/ss-key.pem����������������������������������������0000644�0001750�0001750�00000003213�11544576223�025106� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEAuEDq6imjA3Glai3qXE7nmiHpj18fQthP+JShwyyIcTFfGh7+ DWE5RH63nasAQYYwfYxSKfB1TNdFLTOlwvm6qkZxfpCuzQQpu159+bzHuwvpns1S Q7ZXVbCLzi0OfYkIyovXr8oIFGfsaIYlyd0YSP4/5dal5boZfsAI9mNMv8LtP85B wUUZmkVopQhGGtaFXZ0ew+kbpvPiTJy4HyKjkGT9d83l0snZHqba7phGxZtH19Gc TXGkz3wOq1pViIZNAE676B6F+0YdlpztcLb3uEIB4LEOQhuquzT8FKLd3ThwjV5I CKNj0P6tOHmNw0mpJqZsWZcKA2XuvMekq8mAeQIDAQABAoIBAFnOUnG1v52jG9Pn 803wq5QFqXhXDb6f/kKT91BQ+WPqg4cQyhUtaSNIfCieO260gBgBd963NAUy+6Wv gcDJxcDOuuzMilalC84mnVJHQDab9M+RFeKpEmJSvaHNdj2buCw5AvTMjSmdCa5c jDiaygZx3iUhfRS+o0STRwsIlVT1UZDaDD0+FP7zUYr6D/zXSUBM8i9euOo8Od0b T908CGTJTO2M2DlOqzUUv7wcs2mb7kBTOwH8v6k56/It1F/rSif8tyGBDshna50c 42CUSZdVDEBOJFV+JkhqG5Da63is9bqT5teAb18CrqeNqKhKG5kcvaWG8QdrHfOQ MQlpHS0CgYEAwzyFSud8B71QMcnaJw0R5wB7cKNZx2X+nn+YrSGqCYhvfJFfzmx9 zV28u5k1ZtipXmpKgHRQR1+uo8lymnG9+d9pmd8M5j/rjnOYZpZCLfWSMXGeHih2 UiM1zFwDQJsu5JlCmGP1NInHep4rhAbU5mE2BBassJAb2bfqX8GTjXcCgYEA8ZlW 4mNQ2o5saBn9v1cOb/bmXuM0DWA2bZnDWhg7SZXSd6cgigClFJRMpsB6PXlFrZt0 JwCWKOtcoZhYDfFNbNojVrxMcDxNQ2fXGx8oQil5BiBvTBtjnWI98DdjsF4C/N7R MrScTkxBlC7ES4SK2VyaBPJDV+7Jx1K62eEhHY8CgYBpwWLCjFnXJ2lFTv3ooV/N Lamv/gwnwswFt0BQqCefOlSJuYWYH5SVpe0SAY+3wi0cg58PrfG+d8n11q1Jk8tA ixB81SH7pyxF4b/v8fyvQJKMTetEks5k98WwiTcJzAW+tnYobhzo9KkldoBD6B9z G71SwaWRjr5HVSST8hunSQKBgDa0+i+ZPZ2/0lxgRk0lcWd5CQFDgW3l820t/EZS ZlprSpU9iui07KyUSCcaPpPc+iItqUeLonTxlrAgxw+hLF8Rph7l1Ik1nmk9AkBp 9bvFmFoCzjD1osDolg3m/PPa1eJcshJBQ4OXUOI1FM3k3WwKw/WKxiULNTWlTho4 GD+RAoGAdhDUfixx/mOlPKNz08EaiqvH5abdbvDNTvi4UgCBAxfZAYnyL/fFB53H thKpHO2vKS1WtPZIiGBKffYVg1fJjmEeRof2lFhC7aoyBzcfyjjp9OmXII7mdFQn x3b6EUM92+LliP8D/joXjFOHABuJQBMcCb1Cr2t59MQHtlLWUrc= -----END RSA PRIVATE KEY----- �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/tls-key.pem���������������������������������������0000644�0001750�0001750�00000003213�11544576223�025263� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAwt9AF1py3GpF66t6xyH8vtLu8zQJnUWMPPDCAO8KWWeC8TBz KruGJ58srKETSPcG5Qj5CdvV8gZoXy3PRpp55eqYc39OJ/cfd2fLfSR558Kqic3b cX7h7AFmv/th3t7jcVjC/nVMvzgeYmsz3gsCrasJoee6CxSx5Bfg4Ya8HlJKEAw5 yf9cU9Gx5nbJUPapzCMYYw1KGfU5AJPvD6bKB2z3JX6+srZwoxnyzqAPb1noT6JE w70D0Jl3OdryBTafAN4dOY3qdwwWM5BvliXCUTYcsQtHcxasqxSVtlzLQrNKdXD2 h4F1TwnuInFy2OPHoVWhbwUdNit41UO1pHrc8QIDAQABAoIBAC0rgHipT4yF2bU5 51i3KRW2YQrgmgXpdAtAJ0f+IKD+nFx5xYg3NW6Dt+A/6e90yxVV0hwV5+6Uy6ac QLp13iGMElBbRut+nb2YwpM8XEF7XvpYTDBvn8CLxpxjkZkOgxvn3jMLT4HXaTuY 68nhNXq59Z6gzv/4iQ989XRxPbOtKWI1m96ZTFstkG8TJjaO9AnDxR2sEGHQ+rhP IRMbHLagY1qA0OxMhHCHMTwq/oVBR7xtgraLzeHnSg+Q4Z+hY+TSNmlmJxZINHTK c4kxVhAv2iGJaLDC7XviyKs/AMmoVfcSuG+BGDDOxhpOjx/G4ZzKmp2VVwNOEYk1 E2z7JH0CgYEAy+zMzpdgNIYIcKRAYqQITInsNnfGY+y2tOhUeNA558ZVoqt7Gf1Z TWegqyxtP71ZYkLqidNlJasgX2cU6aAkAHfO1EnpZiaX6WKSXGIfukLhH9Jwc6MW Xnnv0dZ9i83IL5sLIkAVb0TqqIIBvbxZjEYFSQVwpfG8BCvxNwQJ2U8CgYEA9KKh /DkoULrC8SIQ1TroOFcqLZPUFcCPHEfxHC+urWkYpRCrQ43jiZMCegPnKuUEQ9Nu 7UZqOrP0WYyEqQ3P+jC4I4xBozJigGttMTBnC2rm40PCPZcUz28Ja/Tos4oiEN6q qVG5/IlfcjuZZGsFIKbTCxM2uXwykmJDeAC91b8CgYAvbIWAsfF8pYMG9xvGFNGd QyH81MP9bwpabgFfC0W8IgK+TtTVCXcgKi5SQIWzogxMbrVukgvew7pGlYlmf4h/ 11zxP7MYv3bqnrLc6zDnty/1n5HpQo8sL31XNmOCBLw+Xfcr4u1ZMBTGVV2kS04j 8hC+l5ZH8TzBV5rEKZtEvwKBgQCtltmqyEQ7RMsfoDShmfM+R1u+i69q4ACs6L/G aG9izbiXKITeoshazt5rBmn6nhewqU+FPvoSPa+d+4AHFa4Gspt3XgcVbqNGzPPm e5ojF/BOQ76JRbOWngvpdxfIjrQtlFM1YrC+6hu4S2JFR0uUJ8yJh1DFvcOE7AVE GgKasQKBgET77FdaEiiajroe0CE8Ulmge4mpok7QQ81ag6gV6X3R7Ru20pg9iqGo U9OS2VgpqhoWz9PSoI/ZZghRYq0oQz9XDNLtZeGswFJgl4A/TrVs6gWcRxbVfAtg 9EmaJucDIxXNHqoD2yXj7XJPqDkNuD7rV7IOnrsg4La1N7SQpQk2 -----END RSA PRIVATE KEY----- �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/ca-1-cert.cfg�������������������������������������0000644�0001750�0001750�00000004151�11544576223�025327� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# X.509 Certificate options # # DN options # The organization of the subject. organization = "Collabora" # The organizational unit of the subject. unit = "Wocky Test Suite" # The locality of the subject. # locality = # The state of the certificate owner. state = "Folded" # The country of the subject. Two letter code. country = UK # The common name of the certificate owner. cn = "Wocky XMPP Library" # A user id of the certificate owner. #uid = "clauper" # If the supported DN OIDs are not adequate you can set # any OID here. # For example set the X.520 Title and the X.520 Pseudonym # by using OID and string pairs. #dn_oid = "2.5.4.12" "Dr." "2.5.4.65" "jackal" # This is deprecated and should not be used in new # certificates. # pkcs9_email = "none@none.org" # The serial number of the certificate serial = 001 # In how many days, counting from today, this certificate will expire. expiration_days = 10220 # X.509 v3 extensions # A dnsname in case of a WWW server. #dns_name = "www.none.org" #dns_name = "www.morethanone.org" # An IP address in case of a server. #ip_address = "192.168.1.1" # An email in case of a person email = "postmaster@collabora.co.uk" # An URL that has CRLs (certificate revocation lists) # available. Needed in CA certificates. crl_dist_points = "file:///tmp/wocky-tests/crl" # Whether this is a CA certificate or not ca # Whether this certificate will be used for a TLS client #tls_www_client # Whether this certificate will be used for a TLS server #tls_www_server # Whether this certificate will be used to sign data (needed # in TLS DHE ciphersuites). signing_key # Whether this certificate will be used to encrypt data (needed # in TLS RSA ciphersuites). Note that it is prefered to use different # keys for encryption and signing. #encryption_key # Whether this key will be used to sign other certificates. cert_signing_key # Whether this key will be used to sign CRLs. crl_signing_key # Whether this key will be used to sign code. #code_signing_key # Whether this key will be used to sign OCSP data. #ocsp_signing_key # Whether this key will be used for time stamping. #time_stamping_key �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/tls-cert.pem��������������������������������������0000644�0001750�0001750�00000002714�11544576223�025435� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIIEHDCCAwagAwIBAgIBAjALBgkqhkiG9w0BAQUwbDELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTERMA8G A1UECBMIQ29uZnVzZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTAeFw0w OTA5MTgxMjU0MDdaFw0zNzA5MTExMjU0MDdaMGkxCzAJBgNVBAYTAlVLMRIwEAYD VQQKEwlDb2xsYWJvcmExGTAXBgNVBAsTEFdvY2t5IFRlc3QgU3VpdGUxDjAMBgNV BAgTBURhemVkMRswGQYDVQQDExJXb2NreSBYTVBQIExpYnJhcnkwggEfMAsGCSqG SIb3DQEBAQOCAQ4AMIIBCQKCAQDC30AXWnLcakXrq3rHIfy+0u7zNAmdRYw88MIA 7wpZZ4LxMHMqu4YnnyysoRNI9wblCPkJ29XyBmhfLc9Gmnnl6phzf04n9x93Z8t9 JHnnwqqJzdtxfuHsAWa/+2He3uNxWML+dUy/OB5iazPeCwKtqwmh57oLFLHkF+Dh hrweUkoQDDnJ/1xT0bHmdslQ9qnMIxhjDUoZ9TkAk+8PpsoHbPclfr6ytnCjGfLO oA9vWehPokTDvQPQmXc52vIFNp8A3h05jep3DBYzkG+WJcJRNhyxC0dzFqyrFJW2 XMtCs0p1cPaHgXVPCe4icXLY48ehVaFvBR02K3jVQ7WketzxAgMBAAGjgdIwgc8w DAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwIQYD VR0RBBowGIIQd2Vhc2VsLWp1aWNlLm9yZ4cEfwAAATAPBgNVHQ8BAf8EBQMDByAA MB0GA1UdDgQWBBRDAfw/7QRZO5a0qmJ75Oeo3hA01zAfBgNVHSMEGDAWgBRJMCYI jJrWac2LwMwOXAKOSh+mjDAsBgNVHR8EJTAjMCGgH6AdhhtmaWxlOi8vL3RtcC93 b2NreS10ZXN0cy9jcmwwCwYJKoZIhvcNAQEFA4IBAQAIcwQ8FN7lnnQPm4al6y5v zrGzVSxkUuN+I8457E9ZAoFpItMGqWWKjjbOgjS3d95yJWmEW2eBVC3/LMEAvv4z Q6HkTRhafkiLWmXNa8DtbUq1cZ2hNrR1lNTOL4zXwg9JQbtFw0EAM7LfSgqHhTzs xO0AbXaO0TlbYkn9/amPCNQcFjg6Dgdm3x0T3g/tLQjtzjro/hdgYZqPng0MYBpG AUj99FwahI5D8cAPoUjtpxZOlsexz4r8UVGNRvL0Wqg57w8KKF7GVr15b2ZAeQwo pNJkMSXAyPpKW24Q06zwYFnC+Cp32udf2wIB9FEC3zNQugUbtFitHzPjzhum13iR -----END CERTIFICATE----- ����������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/badwild-cert.pem����������������������������������0000664�0001750�0001750�00000003032�12212322440�026214� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIIEUzCCAzugAwIBAgIBAjANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQGEwJVSzES MBAGA1UEChMJQ29sbGFib3JhMRkwFwYDVQQLExBXb2NreSBUZXN0IFN1aXRlMREw DwYDVQQIEwhDb25mdXNlZDEbMBkGA1UEAxMSV29ja3kgWE1QUCBMaWJyYXJ5MB4X DTEyMDUwODE3MjMxNFoXDTQwMDUwMTE3MjMxNFowaTELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTEOMAwG A1UECBMFRGF6ZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTCCAVIwDQYJ KoZIhvcNAQEBBQADggE/ADCCAToCggExAKqugc6RDo23Xf4k7c6ZcWAcennYpZ56 DN4onsqvL7fu5oqorMSWuZnHB6YV74q+Fu0UDLXS9TE4+Vvn3eJrEh4VkcKLqoFs gflGhQS4eul4G1JERPQmux3JkyRNrsJECTncyqW5A82YpFh9SaHWaifxb6Y24G9u /kxf3G8QdqKjXNI3JH8bTKzAJWfs+lSYOarwzkGPnnOZCKU5rKXiKOyP+0tG1KnH G9FH/4eX1JfmNT4VyoAwFjVTBw1228z2bnyt/MSFCVnbnYcNU381rYFjq6O9bzf9 Cfglb58AbwJnKIoaCn2AzavpMXYmEjt9vplZ3DQFBcC5/ysUWW22C2HjqSz0BcQ0 a3+qpql2gdr+tKAAactY7yC1HI095eMLRxMLN5aedImfAW8o/aVOBsUCAwEAAaOB 0jCBzzAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD ATAhBgNVHREEGjAYghAqZWFzZWwtanVpY2Uub3JnhwR/AAABMA8GA1UdDwEB/wQF AwMHIAAwHQYDVR0OBBYEFAOsVIF450rphWkweqxR8bnRaBnmMB8GA1UdIwQYMBaA FEkwJgiMmtZpzYvAzA5cAo5KH6aMMCwGA1UdHwQlMCMwIaAfoB2GG2ZpbGU6Ly8v dG1wL3dvY2t5LXRlc3RzL2NybDANBgkqhkiG9w0BAQsFAAOCAQEAeJIQ1SZS3UQZ 1aBh3901WZhYozH38i7I7JclEQO0Kla2et289IAc2IiocEoeMjwE3bO+1xO4EF2N zEgGzodaIsVGol9zlrRm9CXeYgRBPkgorebFWfEigIsLY3VjrhBhV3UnDTY7Hebr tqdOX7Xa0DLud1AqGzNia2aon28qY05qu5RPgxfvpRUYnJJlT5tidSkbXJIuvbb0 roFd+es4qgQU+ZiAc6DHpREcShxd+20JJVR9zvqeM7egP3tZPiFf8u6n3CsYKQ0p be3NygY35lwc1VYxX/PMecslbsHQoa+ZWgd2+lcZ/81QD2JrmRo7nG3clsCbXodj 1c8cuflfhw== -----END CERTIFICATE----- ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/ca-1-key.pem��������������������������������������0000644�0001750�0001750�00000003213�11544576223�025202� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEA1GRhu+pZ2Vr7M0ux+1didoAPRqANs2XvTLjLE2NXUOuJmc2C OBYzxkiBR28XH6wDzAyhEUEuddZh/Mj58dgVqT4mrKy9CapOJ9eMo6xDxB2FveFz bPXRfumhtEr6jETtVcMoqnmi7h/fDHWa9JOMHWhOvmjZmcDkr90sIzs6YnYL9WPz PqXodXjV6w8RgRm/7B8//3PfGY2E0dxFYh6KkR0NkN9dzSfbZJ4ScZJmtIkM/0Jl olYBwtSEPk4SH4Hc/+B870oMA3w+JxIUVePZfS3yKdybPl+zomiyAQWjjQP9HjFQ hTnrYcRj/i44zo3accz4wqCIMcRSH2zeUuZIHwIDAQABAoIBADF4hC9CAdWX1IT5 L6asjvmtEGHR6/8KUjfbnymP7QmjIzTY4mjv+vVHdB1QaeFtrqC7nFSpiwnVepNn uJg1Ta5TFK0JuypiKbwr/80r1cj7W2iD99+8TiSyhIC7Kiq771AXmgRDOskeUVTU m9g1+d/rqNO/FlgyztGLwbkfFZVTHpQ6QP3j5zaUcQzu0JS4RDCusuBZKcIMaXll u0xs9kwk8+yD7BNEoZqXsOHA36AzftdRTgxSmXGYN66pHNEU/f+QjcksOdO7L2ya sphrEweSALSH15okw8f+O1cMwPV/BVPkzhhS5ERvRbqVq/YWPS12gy8YXjSwNE17 HQlRfckCgYEA1I39mbambVPX4TaYzZygbDzLbfMCdmtLMht+LaHNbe7FQnALsxR8 jt0LIHfAo8pztDlJfe/Zppfsz+JBlpRFRUUB+S/NXEk59EX8HN+tAL93L1nZVmjU qOSdwPHxkGlfuuQG7gP0zjSTwQBGbMmdC+S0PXa1SubbOSCw1AXiDEUCgYEA/83i 7uthjW/AQXCgxP+tlb6KP3Dp6009URa+V9hT4jRO523FnsLJXtKEFCV+Wxq7dO8X QNrXWy5dj+tnzl6dJ76maWxORBiPArFFeUvTAUfzogR6Z0wrtBwPEvsNkVUMK8Xp NxndLY5DxNqHrTugIwdTDFZxAwO66YGwAddhUxMCgYB+t9QL8t9PaF/YbXM1iX3+ aVQiTXEXZinjSo6z57WQJ3xEeoYPElSb214J0jrvqv/F3y1YPkj0z7gny0ys1+Jg RJ7Dj2MP9LvvTFXcZOFAA+WrPhabNE4sDneaEuOf46JlyhHzjjpBQQkhU+eobZ4J /CQUTJQSfoUNjta84HD+PQKBgCzXClCXMiJ41FqkQ4pEx0jYfaNhR5/XikgMlJER eqLMSIiI1Xte6a2VeVGOwPd3WCTHRGw58EYrensf6LJkI2g0IzeXpKCLLYZrTKJW iEZRNoPQBSTWVVLdGEdbeqVfIyMJLjhacErsBTUcmWvkZ828GvKutGCy5rDH6vJn rsfBAoGAOGcl22yaS2ngXM1/l0tNTuZSdjiF7mtD73Gmv/VAae0sDqLgwr64F1at f0ppTACSM8uVA0d2EgvcmpBGNMi/ApvqVnpcDd2HZ6BFJAW+hk6QBB8GGpKPUSt+ F0Q3LJmmMz6Ct9spGu4Kach6k0DapGKBFUkaor3xOj1Lgi34yV0= -----END RSA PRIVATE KEY----- �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/ss-cert.pem���������������������������������������0000664�0001750�0001750�00000002664�12212322440�025245� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIIECDCCAvCgAwIBAgIBATANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQGEwJVSzES MBAGA1UEChMJQ29sbGFib3JhMRkwFwYDVQQLExBXb2NreSBUZXN0IFN1aXRlMREw DwYDVQQIEwhDb25mdXNlZDEbMBkGA1UEAxMSV29ja3kgWE1QUCBMaWJyYXJ5MB4X DTEyMDUwOTIxMTkwNFoXDTQwMDUwMjIxMTkwNFowbDELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTERMA8G A1UECBMIQ29uZnVzZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALhA6uopowNxpWot6lxO55oh6Y9f H0LYT/iUocMsiHExXxoe/g1hOUR+t52rAEGGMH2MUinwdUzXRS0zpcL5uqpGcX6Q rs0EKbteffm8x7sL6Z7NUkO2V1Wwi84tDn2JCMqL16/KCBRn7GiGJcndGEj+P+XW peW6GX7ACPZjTL/C7T/OQcFFGZpFaKUIRhrWhV2dHsPpG6bz4kycuB8io5Bk/XfN 5dLJ2R6m2u6YRsWbR9fRnE1xpM98DqtaVYiGTQBOu+gehftGHZac7XC297hCAeCx DkIbqrs0/BSi3d04cI1eSAijY9D+rTh5jcNJqSambFmXCgNl7rzHpKvJgHkCAwEA AaOBtDCBsTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdJQQWMBQGCCsGAQUFBwMCBggr BgEFBQcDATAhBgNVHREEGjAYghB3ZWFzZWwtanVpY2Uub3JnhwR/AAABMA8GA1Ud DwEB/wQFAwMHpgAwHQYDVR0OBBYEFJSBitgIFe+DDoAc7lAGk5+gbReHMCwGA1Ud HwQlMCMwIaAfoB2GG2ZpbGU6Ly8vdG1wL3dvY2t5LXRlc3RzL2NybDANBgkqhkiG 9w0BAQsFAAOCAQEArMZFCHoZHZGpT7XrsWHJALVIixkwtWePte9iiznKbl4ywrlZ fRAOoPUl+ZrspDU0lA5299V67M2WMIMs9uAjW5jgCPswylkO1RaJBTHcHmiGm2Ev R/8h4PCDo/LJvQjQs3B7Wev5zQEE25h8DUxvqA499wRWPxVmiLt4n/yFuVMNUDAF eQvCDv2YQu8EZ/A++kQjbjujTHT3okSXoPEcOZj+C1Eqp8cWXRrrh8xkE9ptRWIS Q+MhjvgVPrniGBBK1Mh0DbQhlriLD++XYI3bDwlg/Hnc0o9bWv0sfyvtOI45g5QG SDeBQ8L0KFUfu03ZBwATpd9pHUngpWbVXGqLhg== -----END CERTIFICATE----- ����������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/rev-cert.cfg��������������������������������������0000644�0001750�0001750�00000004152�11544576223�025403� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# X.509 Certificate options # # DN options # The organization of the subject. organization = "Collabora" # The organizational unit of the subject. unit = "Wocky Test Suite" # The locality of the subject. # locality = # The state of the certificate owner. state = "Dazed" # The country of the subject. Two letter code. country = UK # The common name of the certificate owner. cn = "Wocky XMPP Library" # A user id of the certificate owner. #uid = "clauper" # If the supported DN OIDs are not adequate you can set # any OID here. # For example set the X.520 Title and the X.520 Pseudonym # by using OID and string pairs. #dn_oid = "2.5.4.12" "Dr." "2.5.4.65" "jackal" # This is deprecated and should not be used in new # certificates. # pkcs9_email = "none@none.org" # The serial number of the certificate serial = 013 # In how many days, counting from today, this certificate will expire. expiration_days = 10220 # X.509 v3 extensions # A dnsname in case of a WWW server. dns_name = "weasel-juice.org" #dns_name = "www.morethanone.org" # An IP address in case of a server. ip_address = "127.0.0.1" # An email in case of a person #email = "postmaster@collabora.co.uk" # An URL that has CRLs (certificate revocation lists) # available. Needed in CA certificates. #crl_dist_points = "file:///tmp/wocky-tests/crl" # Whether this is a CA certificate or not #ca # Whether this certificate will be used for a TLS client tls_www_client # Whether this certificate will be used for a TLS server tls_www_server # Whether this certificate will be used to sign data (needed # in TLS DHE ciphersuites). #signing_key # Whether this certificate will be used to encrypt data (needed # in TLS RSA ciphersuites). Note that it is prefered to use different # keys for encryption and signing. encryption_key # Whether this key will be used to sign other certificates. #cert_signing_key # Whether this key will be used to sign CRLs. #crl_signing_key # Whether this key will be used to sign code. #code_signing_key # Whether this key will be used to sign OCSP data. #ocsp_signing_key # Whether this key will be used for time stamping. time_stamping_key ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/ca-0-cert.cfg�������������������������������������0000644�0001750�0001750�00000004153�11544576223�025330� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# X.509 Certificate options # # DN options # The organization of the subject. organization = "Collabora" # The organizational unit of the subject. unit = "Wocky Test Suite" # The locality of the subject. # locality = # The state of the certificate owner. state = "Confused" # The country of the subject. Two letter code. country = UK # The common name of the certificate owner. cn = "Wocky XMPP Library" # A user id of the certificate owner. #uid = "clauper" # If the supported DN OIDs are not adequate you can set # any OID here. # For example set the X.520 Title and the X.520 Pseudonym # by using OID and string pairs. #dn_oid = "2.5.4.12" "Dr." "2.5.4.65" "jackal" # This is deprecated and should not be used in new # certificates. # pkcs9_email = "none@none.org" # The serial number of the certificate serial = 001 # In how many days, counting from today, this certificate will expire. expiration_days = 10220 # X.509 v3 extensions # A dnsname in case of a WWW server. #dns_name = "www.none.org" #dns_name = "www.morethanone.org" # An IP address in case of a server. #ip_address = "192.168.1.1" # An email in case of a person email = "postmaster@collabora.co.uk" # An URL that has CRLs (certificate revocation lists) # available. Needed in CA certificates. crl_dist_points = "file:///tmp/wocky-tests/crl" # Whether this is a CA certificate or not ca # Whether this certificate will be used for a TLS client #tls_www_client # Whether this certificate will be used for a TLS server #tls_www_server # Whether this certificate will be used to sign data (needed # in TLS DHE ciphersuites). signing_key # Whether this certificate will be used to encrypt data (needed # in TLS RSA ciphersuites). Note that it is prefered to use different # keys for encryption and signing. #encryption_key # Whether this key will be used to sign other certificates. cert_signing_key # Whether this key will be used to sign CRLs. crl_signing_key # Whether this key will be used to sign code. #code_signing_key # Whether this key will be used to sign OCSP data. #ocsp_signing_key # Whether this key will be used for time stamping. #time_stamping_key ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/unknown-cert.pem����������������������������������0000644�0001750�0001750�00000002725�11544576223�026334� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIIEITCCAwugAwIBAgIBAjALBgkqhkiG9w0BAQUwcTELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTEWMBQG A1UECBMNTG9zdC1pbi1TcGFjZTEbMBkGA1UEAxMSV29ja3kgWE1QUCBMaWJyYXJ5 MB4XDTA5MDkxODEyNTQxM1oXDTM3MDkxMTEyNTQxM1owaTELMAkGA1UEBhMCVUsx EjAQBgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTEO MAwGA1UECBMFRGF6ZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTCCAR8w CwYJKoZIhvcNAQEBA4IBDgAwggEJAoIBAL6XDXCTUs9hqzRBFjTGlw6jRWWhHASd E8eEE1QOuh2ij10pu7Et6GIpLfW83i6dZSarSaifGyYkQ+qx97yjCY7p8NQaYTj7 CADrTXLtLJVkeVihig32X49Pihe0EmyieXMdN7VdyBTDoPEglvx5yA0/srdDlk6N qrRdAaZxWwVBlIAoDteTMKNbakQNNjVCfx6/O6KaVRdf6PKsQ39a+bv4nFuwvnMy 7yzmmAq2MCRY56OyEuUZZKo4Urzbd8IWmXxgkvKq4lm/pnU8yhILgWsG59Jchaf0 e0X5Mg0Ryo65eW9oxC+N9E70MfHqXxs6EKcqEFkJNiHDGU7pApCSGSkCAwEAAaOB 0jCBzzAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD ATAhBgNVHREEGjAYghB3ZWFzZWwtanVpY2Uub3JnhwR/AAABMA8GA1UdDwEB/wQF AwMHIAAwHQYDVR0OBBYEFKH0v7AWPAzbSGYbG+h0kTcRaf+RMB8GA1UdIwQYMBaA FK5MjvmEOvzqUkos/bUV40sy5ngKMCwGA1UdHwQlMCMwIaAfoB2GG2ZpbGU6Ly8v dG1wL3dvY2t5LXRlc3RzL2NybDALBgkqhkiG9w0BAQUDggEBAAH4rfEh9rrTpzz7 I4rLAmKyKpp9FHiPkA/ZSH/U4ffbILrych0SvpHxusNWRo3rjcUOBAq5Xt+2Oqvl 0gVqcFF8GuGhiXYSV3k40bQHxv3MO5HanPbCIw0BDjERC0Ii+8BkDEMXRdQdyYmP q+D1PKjev0bQtjai2L8/R6WOWTJtZeQAMwvtEqdwSLXDxyQSEJc4NIvWWijqq3hP Ld+wozE/+Ajx4A4qeab9Vyj1Ul/zGYF/JDPgPLwOoBXeBJxJ+cB5HP4OOt/dpTWu L1ratvrGEubystJ05fPewqHhwyBDuqnCI/gIyRXEcbHA6sIJ5RpaKFWbOF1SQO4P 30nZOag= -----END CERTIFICATE----- �������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/ca-2-key.pem��������������������������������������0000644�0001750�0001750�00000003217�11544576223�025207� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN RSA PRIVATE KEY----- MIIEpQIBAAKCAQEAvmAEI3lGwJZ574UOIpkGy+GlPLCYzPzO4IJudTXV3r91sLzn Qw1PC4L2iiKDEMkGkuVwLeEP4QHh2SVtDcd82VvV1oqph5arFC3UCr8SM/cZ7y0U e+IB3XTF6rDwh4nkjb15uHJ5zTyMJljYgSKOTXSP03vrTZhqs6TuLdRvY2JYRjYX Nr1CKQ6OGztr1qnkcqp0JawMpH2bEnI68mbTAQ0nPcWXYyZSbdp2y5UCVVIItWxM Gsz90lhIo32UyoZ159G74RRlEhLLB2+QlFa+iC0c1ibQFaf7rGAGkC2S4TIXAPeG LxQdHZVZbbHbb8AT4nRAuDTDyXIrTf97NX0GzwIDAQABAoIBACH44mQuLSkK8UGD 3ezgn+zcHG+DGBFkf8pinDGAZOT2B5t9akt14YgtW690zyy8otat6OHXCs1dV583 ZYmS8r2a/MLnRa9zfJ4CO5ebVzU8wD0FL2WYBDsvrm3eG14khkug50q56vBsAJqL Oj95GinKRiw4LdpP+6KJKRO2mBYE1Mkm+Ma2YD36/40zuDGKyp47oFNbZOHgwI/l U5Oi10/HWFXZ7J8qFWX06prQVymWW/eZdgEtjrVqzRXCdea85UdlbPYZ2DoIjO2e TFJ2ApjVY8uCZtd1PdTAmIK+RWHPbRY3e1fGji+1W5PT6FkVzS9DoYUTsA8GFche /bqvDUECgYEAz5N9iaAGISlGjSU+iW2WHD/+WIru1u6hjXjKyI1kAW42h6C9rLnS U+fRl34p+chR9pI+RM8lQjqa1Pfl+kQEu4hQertgSbbdy8FJ6UK1nV+ianl+rdYB HXup2a7EDZGYsWMKLE0hSZ/Y6aVrO4mrrvGX//aDHsB5qSGEIAnzP6ECgYEA6slF yXbGYxOK2qvioUhrDYAMCcPEOy1Gn9pcyurV4Vetk+uFjZs80pcO1fu6GXkc7mR3 pveFUx0f7C7D5NYq9PckK/JPj3CkVDlm/uIHSZeRDYjkPDaAB38Lphkl7DDTlP54 XD22XhziV+WIIvly4t7vziBtkJMR1s+sq+JucG8CgYEAxpJLl6qT8okvyrqEVqeU 4DV/tWhDDy19Mn8JTk2kC5JJa/mjOWcSA95SLGAu+5pcfkpscxrOg8rYbz8uq/kB pfzDMIWrmRjsmIyxjgmY/5GLJ9xOCTIeIvw4AdwkBO7xaVBbXQH0BCB8OxdZu7z5 lgPb6qsByBtMxzUe1h9uqcECgYEAxiI4nH15id7SDRuE02qTvP7UKeFlVjMtKHVU XYG0IMinGO9m80uQFn+X64jVUe3dNmjeeK7lenBXoi8M7a627acqhVOlRH1gkBsp CeuhDr+zj2J4iT/M54aVRARw9lN2GoRs+hqyLdXeRSLUsf8krsRIRwEitSEHquny 49LgNE0CgYEAhATwToe64ujjjADzacdQ17Jxlxjp6Ko8afuKMRixY+gIwhLhRv/i FUHq3uOxVuPK4P2m2Euc0UUQyWhXsgOzSFcwwlnfLbTBoe1TNsBYPgf/Lm/MqgYi GG/QIM1GkaheDwCrn4QIAgzvHLFNJC8ouwA3Uj9dkaYvXjoW65ftwcE= -----END RSA PRIVATE KEY----- ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/new-cert.pem��������������������������������������0000644�0001750�0001750�00000002714�11544576223�025424� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIIEHDCCAwagAwIBAgIBAzALBgkqhkiG9w0BAQUwbDELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTERMA8G A1UECBMIQ29uZnVzZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTAeFw0z NzA5MTExMjU0MDBaFw0zNzA5MTgxMjU0MDBaMGkxCzAJBgNVBAYTAlVLMRIwEAYD VQQKEwlDb2xsYWJvcmExGTAXBgNVBAsTEFdvY2t5IFRlc3QgU3VpdGUxDjAMBgNV BAgTBURhemVkMRswGQYDVQQDExJXb2NreSBYTVBQIExpYnJhcnkwggEfMAsGCSqG SIb3DQEBAQOCAQ4AMIIBCQKCAQC5lmoJIYHwwdSxR5438H9UQlIfaSp8T/irxQG1 tDDqjkv37H5JUIwGIYXxRuM4k1tDYj+nEICj7dLzFGY6NCHrOPSILvxRfvYQ4Iz7 VSUTnHjSkrlQ6ILzZWdork2KKpAE6O0fAJ+mhy4fwtjnIhXDUapIyoOniee4SZfE 7LZx8ZjIO6hhv4JCReKNz1sb7zjuVl5Xghr+1LYO7OmimBejm4LxNIPttpkkZh26 Syr+UtE1UhN5Ojiim2rKdekYf3S5WiiltOw/3WFD1KJmgyLy5XLhD87M5+wJ+7Aq lv4obAgYKJPg3rcy5UX/1iRjT7/AGbWlBi07e5zKa+VA1xZHAgMBAAGjgdIwgc8w DAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwIQYD VR0RBBowGIIQd2Vhc2VsLWp1aWNlLm9yZ4cEfwAAATAPBgNVHQ8BAf8EBQMDByAA MB0GA1UdDgQWBBTQlqg773FSODizSAmYG7bIV06GuzAfBgNVHSMEGDAWgBRJMCYI jJrWac2LwMwOXAKOSh+mjDAsBgNVHR8EJTAjMCGgH6AdhhtmaWxlOi8vL3RtcC93 b2NreS10ZXN0cy9jcmwwCwYJKoZIhvcNAQEFA4IBAQBTok7jC9jwZeiPmGgiktNe kkAwKJuJpa9O9lgeiZywlaR3vWIEuQpi7P/VpkWca7pjmu0kVJk7AupW6s6RfeW6 OALA7Zn9SC0w1zj2aSDmjI0DWosvkvoO+jkNS6HIozkMkWa6IX7veL7sTUP6cZ7f twMPExDhdNrmyOOLjxiW7Bvz6HVfAvcgCah6JjNSxL4QAdFiz0VJOInWXtp7/2rc YMeBsg4YFkV51YBVts7gCL4lDLxE79Rkj7YwhP6f84tTy+NjFmjBYKS9tyKJViOd 9L82PfXhHFUcYP/8wqhk+nE5PF4mLhroUq9DZpGU8ICEIzGburysoQi64IoPDCGM -----END CERTIFICATE----- ����������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/ca-0-crl.pem��������������������������������������0000664�0001750�0001750�00000001347�12212322440�025160� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN X509 CRL----- MIIB/DCB5QIBATANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQGEwJVSzESMBAGA1UE ChMJQ29sbGFib3JhMRkwFwYDVQQLExBXb2NreSBUZXN0IFN1aXRlMREwDwYDVQQI EwhDb25mdXNlZDEbMBkGA1UEAxMSV29ja3kgWE1QUCBMaWJyYXJ5Fw0xMjA1MTAx NjQzNTBaFw0xMzA1MTAxNjQzNTBaMBQwEgIBCxcNMTIwNTEwMTY0MzUwWqAvMC0w HwYDVR0jBBgwFoAUSTAmCIya1mnNi8DMDlwCjkofpowwCgYDVR0UBAMCAQAwDQYJ KoZIhvcNAQELBQADggEBACFaj/M6g+fP0RQEiB7kvoocdM7XGUemkl9Ns/chc9zH yLgq1891jIO5GoKoCuMGEFfYat/VZutNOLFHkJ0AeqrvOSPVZ8atcZTJR/lgjR6I PN/UMFpHMEVa7cUtLPx47UvGDolrOo1d4ciLVUUPoZMRGxTitVz8KtEk+O9s6NjS W25uTGoNT58OQS51dXq4N97gNMSeggWGN1Y9swv0s992G/Y93t/uQvsRsSEMe7kj ddChE3Gb4I+7TkjL+e64RlYsAtvMePM3k3+Zk95wFGWqlwRow46Nv3F02C8Af5JV zp+tsq2foM0lIADnOTjUs2XgNGqx0Gm/hTAfBMsIgkM= -----END X509 CRL----- �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/unknown-ca-key.pem��������������������������������0000644�0001750�0001750�00000003213�11544576223�026541� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEA3OnZj1DlQPIDzJ15thqOY8IAIUCAL7zKbCwC1b60WGQasDF4 5DVD/WGBFfRLQlWRIlfj57bCdmc+1SrXjJCJGFGzr0QLZsqoOEi8V8goW57Eqdzu HW7e37oY9zd5zScnnftUnt6+2fl/lKR6Vit3AhNsCSZg8v5glccBuq27XlzSDc9K tSBeleUV71tF1K+n9RC8oKrixlB9KLgY6ppfBn7N4m5Awoqozhk+85snrlWZZELb S6ov5MEVJ8BoVsCejZWCPxHIG8fX8zccgZ/Ktll6Qx2RUTsPlsETXteYBEh7zWoc DZi6Qnr7qqHZoq8nlgi8Q+LeT9z00uItD4RH0QIDAQABAoIBAArnr83Jb2Gw+LNK cEJHJhGCV32MuK8ylXb4xrSMrwwgd+lL7eTtBLPOsv+1kRv/i5QrjMRo0wljgBhn fp+xmFTnHpS3qgzrUtnBbGu0ZZqdOCXO8kGpcg7O+dHFTynLhaMAr70Ob5Mkw/Gf W2sixuOHOCls97LzD+tA2ULg9dt658QqtSO4UhJjQz7aV4oz625NBlV6C0GYSo+5 vtxIey2jO4mzg0uTdDMbk+x0D0+Y5KfVGTZfKv4c3Ekk56m0IZfDA6hi3/16DY7X Th2f6Y6gmrxcyz6BvaV05LMXeYgcxSnp6np3PoH7cD9PSmlBYWuW0yx7KfQjFdr/ pdJl2EkCgYEA5OHifkfJa6toFbSF82E5u/l8u0JsjLYlVGJMdpD62tFPMRlpE4mQ HN45JF6uHbkCd00xqZ+z0WBw6gpk84BKW8Qk5luU0PPc2giLn6WlD0GBCi7TV5Cw lhf5CL/Dz9tsfnoJ2SRfr948h2Gc7c/XmeTub8BnN2F7cqwkmfLKcwkCgYEA9xZD zI+5s5qv/ZRkqs697kKVEqX51FsVHmNDp/dVq4vkMjrqfWfD5PwRwZ2kPyvwXfb/ s9NR58IJkkqxwSvSTAOfZtlJmWMVxP/6GStOcuPI6MHcwjXQmkKCgx6z00VLB1TG OIjNqU8hSTpd9Mqecj7Y5U/aTGQTbRNxLXbc+IkCgYAeQFTFSAuxNWh+ZevGbTVK SQFZZsAeIPzyGEPu796YCU4kOS2QLYBksGJxEiqFNyzCQ+uqdbc4lzyVUmZhYLVz R4tw/u2+aFzqXHLH2Qbl60x44hOA4VjVnbmGlIH2+RNv7AVdM9eJ0R/C7P3m2K+w YXe6QX3i7fl5AJOd3V8wsQKBgFGdAhH8WztO2dipfkLI/QVI6tJ5DjctSqF56iv9 z0dVcq+AtFltv8/PztGkD09qZP+0iStNnp0tg1nV4DbNEa5X9/vRw7StfNBQOLy9 iDD8uizfc9qWSevaEh/bMUyUc77dKogb78p/v5/fbo9fqcxUo/HCWXmoCJ6bsGNz AnP5AoGBAKVK8otu7a2z4uxhVySOhaJ6GvWZZ6TkM8SZUFxW8H2EPLyxaIeSnMZF G217tfER+hiP+nviCwGYxU88mo5Pn2OXlhWTAEJv/TccM6G4eWo06SDz3cqWYfNh B7rT3jiBfNwbpjokwcbIbzvyx7jjFjsas1b9Fdk+XdFV2pyXB9JA -----END RSA PRIVATE KEY----- �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/ca-0-crl.cfg��������������������������������������0000664�0001750�0001750�00000004154�12212322440�025135� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# X.509 Certificate options # # DN options # The organization of the subject. organization = "Collabora" # The organizational unit of the subject. unit = "Wocky Test Suite" # The locality of the subject. # locality = # The state of the certificate owner. state = "Confused" # The country of the subject. Two letter code. country = UK # The common name of the certificate owner. cn = "Wocky XMPP Library" # A user id of the certificate owner. #uid = "clauper" # If the supported DN OIDs are not adequate you can set # any OID here. # For example set the X.520 Title and the X.520 Pseudonym # by using OID and string pairs. #dn_oid = "2.5.4.12" "Dr." "2.5.4.65" "jackal" # This is deprecated and should not be used in new # certificates. # pkcs9_email = "none@none.org" # The serial number of the certificate serial = 001 # In how many days, counting from today, this certificate will expire. expiration_days = 10220 # X.509 v3 extensions # A dnsname in case of a WWW server. #dns_name = "www.none.org" #dns_name = "www.morethanone.org" # An IP address in case of a server. #ip_address = "192.168.1.1" # An email in case of a person email = "postmaster@collabora.co.uk" # An URL that has CRLs (certificate revocation lists) # available. Needed in CA certificates. crl_dist_points = "file:///tmp/wocky-tests/crl" # Whether this is a CA certificate or not #ca # Whether this certificate will be used for a TLS client #tls_www_client # Whether this certificate will be used for a TLS server #tls_www_server # Whether this certificate will be used to sign data (needed # in TLS DHE ciphersuites). signing_key # Whether this certificate will be used to encrypt data (needed # in TLS RSA ciphersuites). Note that it is prefered to use different # keys for encryption and signing. #encryption_key # Whether this key will be used to sign other certificates. cert_signing_key # Whether this key will be used to sign CRLs. crl_signing_key # Whether this key will be used to sign code. #code_signing_key # Whether this key will be used to sign OCSP data. #ocsp_signing_key # Whether this key will be used for time stamping. #time_stamping_key ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/badwild-key.pem�����������������������������������0000664�0001750�0001750�00000014571�12212322440�026061� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������Public Key Info: Public Key Algorithm: RSA Key Security Level: Normal modulus: 00:aa:ae:81:ce:91:0e:8d:b7:5d:fe:24:ed:ce:99: 71:60:1c:7a:79:d8:a5:9e:7a:0c:de:28:9e:ca:af: 2f:b7:ee:e6:8a:a8:ac:c4:96:b9:99:c7:07:a6:15: ef:8a:be:16:ed:14:0c:b5:d2:f5:31:38:f9:5b:e7: dd:e2:6b:12:1e:15:91:c2:8b:aa:81:6c:81:f9:46: 85:04:b8:7a:e9:78:1b:52:44:44:f4:26:bb:1d:c9: 93:24:4d:ae:c2:44:09:39:dc:ca:a5:b9:03:cd:98: a4:58:7d:49:a1:d6:6a:27:f1:6f:a6:36:e0:6f:6e: fe:4c:5f:dc:6f:10:76:a2:a3:5c:d2:37:24:7f:1b: 4c:ac:c0:25:67:ec:fa:54:98:39:aa:f0:ce:41:8f: 9e:73:99:08:a5:39:ac:a5:e2:28:ec:8f:fb:4b:46: d4:a9:c7:1b:d1:47:ff:87:97:d4:97:e6:35:3e:15: ca:80:30:16:35:53:07:0d:76:db:cc:f6:6e:7c:ad: fc:c4:85:09:59:db:9d:87:0d:53:7f:35:ad:81:63: ab:a3:bd:6f:37:fd:09:f8:25:6f:9f:00:6f:02:67: 28:8a:1a:0a:7d:80:cd:ab:e9:31:76:26:12:3b:7d: be:99:59:dc:34:05:05:c0:b9:ff:2b:14:59:6d:b6: 0b:61:e3:a9:2c:f4:05:c4:34:6b:7f:aa:a6:a9:76: 81:da:fe:b4:a0:00:69:cb:58:ef:20:b5:1c:8d:3d: e5:e3:0b:47:13:0b:37:96:9e:74:89:9f:01:6f:28: fd:a5:4e:06:c5: public exponent: 01:00:01: private exponent: 30:f2:e9:01:3f:b2:87:cb:fd:a5:c4:1b:7b:33:a0: 43:2b:07:a8:e8:0b:df:5e:2b:50:8f:1f:b3:0a:f8: c9:6c:37:2b:ae:e2:15:63:10:89:5c:7e:02:10:aa: 69:04:c8:f8:66:d6:9a:52:8c:c4:f8:0c:f3:61:94: cd:b9:5d:31:c9:87:ca:de:59:20:d2:e8:97:7f:b4: e8:3c:ab:eb:46:e9:b6:f7:23:3b:4d:dc:3d:d7:b0: 5e:29:f5:23:7b:75:95:e5:8f:2c:65:da:04:5d:71: 4c:7b:69:e1:82:e7:60:db:29:e4:e6:3a:09:5b:30: 8c:e0:b5:0c:19:11:9c:e4:f2:da:ca:bb:a9:c4:3f: 82:0f:7c:ea:c8:18:a6:a8:1d:69:bb:b3:bb:33:a0: 02:90:79:e1:78:fc:56:ca:a6:fa:fc:42:59:2f:43: c2:d6:66:88:d7:9f:83:01:60:25:bb:31:f3:67:90: 51:6f:8f:9b:54:e6:54:a3:6a:b9:e7:15:21:8f:03: bb:31:b4:63:77:c8:b6:88:b6:f2:ee:88:c7:c8:e6: 7a:3e:05:25:5f:fe:6a:54:11:0f:44:57:18:4c:34: a4:fe:01:07:65:68:bb:6c:b2:f4:df:a3:74:94:65: ba:84:37:26:6a:75:4f:38:81:46:43:51:43:21:3e: 1e:1b:8c:cd:28:41:d9:23:8b:c3:7b:b1:31:21:8e: 51:cc:7d:a7:4b:bd:ec:f7:34:45:df:e3:b1:4b:5e: 86:4d:03:3e:ea:b5:21:4c:7b:e2:08:a2:6e:94:df: 6c:c8:0d:65: prime1: 00:c9:35:da:a7:66:35:95:86:65:2d:87:e9:c4:34: c8:af:6d:8b:d7:2a:ab:cd:f5:db:52:27:f6:3b:07: 15:2c:f1:ce:e9:01:87:69:c7:50:7d:48:fc:86:ac: ac:c6:27:f3:e4:94:fd:03:dd:1a:10:dd:c4:9c:28: d6:eb:52:42:3a:32:d2:83:14:73:1a:75:a8:a5:ac: 86:76:1b:4f:84:67:4f:a7:9a:4b:d2:11:fc:0d:8f: 45:46:e1:cc:ce:a7:01:b8:eb:c5:0b:f0:90:56:0d: b1:04:a6:3f:06:a0:d8:03:be:df:7c:51:6f:14:f1: dc:3e:08:0d:a5:6c:cc:6b:68:ec:c6:d3:d2:35:cf: 28:c5:d7:36:f6:7e:71:6c:7e:1e:12:a3:e3:64:8b: 1e:94:83: prime2: 00:d9:28:88:32:c2:21:fd:24:1e:10:5c:ae:c9:f4: 85:8f:f6:a1:a9:23:39:f9:8a:c6:17:f0:a1:db:fa: f0:51:a0:66:e7:db:3b:39:c7:2f:c1:62:7d:e3:bc: 8a:27:5d:99:0c:11:69:a0:f0:8e:62:22:56:a9:c5: d5:9e:ce:6f:c0:47:9c:c8:90:86:ad:b0:2e:56:64: 35:2c:b6:1d:f1:71:bf:0e:e5:bf:24:1d:40:02:34: ba:37:00:d3:f5:19:65:3c:78:89:20:f8:72:b7:50: 0f:c9:e7:bd:5c:10:fe:b5:d0:07:66:7b:3d:e6:e0: f3:81:b9:7a:19:48:ce:fe:5e:e7:d8:65:f3:d7:9b: f9:95:98:f7:bc:44:0d:a2:24:50:3b:8e:99:f3:5b: 7d:65:17: coefficient: 24:63:2a:2a:91:68:87:30:89:7f:df:a4:22:1f:b2: 22:db:e9:4f:c3:00:87:da:7c:62:d3:ff:19:cb:6d: 01:a9:71:9e:03:4f:66:a2:92:ea:5b:e4:d6:6e:d9: 71:a9:25:49:41:a9:aa:e3:1b:ef:7f:1b:57:83:c4: 78:cd:39:47:d0:af:79:3a:a5:e1:fb:48:4a:f4:d9: 02:db:96:f0:3a:d1:3b:7b:b6:f8:28:1e:2c:1d:a2: 4c:f9:19:29:52:6c:6f:70:19:49:37:59:9d:fd:6c: 36:3e:c8:e0:50:6b:49:ff:2b:d9:31:72:c7:38:67: cc:30:49:40:06:ba:70:63:36:bd:11:19:1a:f2:d1: 2b:f3:09:cc:ed:b6:23:11:4c:9d:9d:d5:56:25:06: bc:9b: exp1: 2d:cb:78:0c:89:92:c0:89:6a:15:c6:cd:49:be:c9: be:43:ac:84:38:4e:09:fe:5f:00:7f:df:e6:e7:61: c6:6c:f2:ae:cd:8e:48:60:f8:cc:cb:03:ce:93:16: 6f:b3:40:2b:52:4d:93:c7:8a:db:33:de:3f:bc:7b: cd:eb:56:ef:70:09:c1:93:b1:ee:df:c0:96:94:81: b5:f7:d9:4d:45:46:37:db:42:4e:79:91:68:74:a7: 4b:ce:b0:92:88:28:38:32:51:12:ba:99:df:3c:16: 81:fc:64:73:d9:bf:d0:7a:6c:db:1a:9d:b1:a2:aa: 81:e3:cb:57:4f:3f:e7:62:66:21:8a:ac:59:5a:e0: e8:c6:66:d8:0b:47:3d:6e:26:e2:0f:32:fd:fb:3b: e6:89: exp2: 77:5c:ef:18:2f:5b:2d:60:87:e1:e8:7f:ee:e4:27: f2:0c:d7:a9:37:82:ab:66:9b:22:17:93:70:6e:0b: 60:62:b1:8d:aa:14:70:da:ca:a6:1a:74:26:14:c1: 3f:88:14:12:ed:13:49:72:50:61:22:8c:ce:3e:be: ff:ce:6a:e0:9e:bc:50:06:18:f1:29:91:1e:cd:6f: e9:06:a5:88:cc:43:ff:75:4b:4e:17:81:d2:74:97: 12:9a:b2:e6:db:31:a9:3e:7b:e9:92:86:c3:ba:0f: 23:a4:ec:91:c9:89:a7:f8:13:c9:41:de:b1:a4:5e: 54:a4:d5:b7:46:2c:f8:e6:c3:bb:4f:b6:eb:81:81: 7b:b8:1c:1b:f0:b0:29:ba:9a:1b:52:73:ce:af:30: 4a:bb: Public Key ID: 03:AC:54:81:78:E7:4A:E9:85:69:30:7A:AC:51:F1:B9:D1:68:19:E6 -----BEGIN RSA PRIVATE KEY----- MIIFegIBAAKCATEAqq6BzpEOjbdd/iTtzplxYBx6edilnnoM3iieyq8vt+7miqis xJa5mccHphXvir4W7RQMtdL1MTj5W+fd4msSHhWRwouqgWyB+UaFBLh66XgbUkRE 9Ca7HcmTJE2uwkQJOdzKpbkDzZikWH1JodZqJ/Fvpjbgb27+TF/cbxB2oqNc0jck fxtMrMAlZ+z6VJg5qvDOQY+ec5kIpTmspeIo7I/7S0bUqccb0Uf/h5fUl+Y1PhXK gDAWNVMHDXbbzPZufK38xIUJWdudhw1TfzWtgWOro71vN/0J+CVvnwBvAmcoihoK fYDNq+kxdiYSO32+mVncNAUFwLn/KxRZbbYLYeOpLPQFxDRrf6qmqXaB2v60oABp y1jvILUcjT3l4wtHEws3lp50iZ8Bbyj9pU4GxQIDAQABAoIBMDDy6QE/sofL/aXE G3szoEMrB6joC99eK1CPH7MK+MlsNyuu4hVjEIlcfgIQqmkEyPhm1ppSjMT4DPNh lM25XTHJh8reWSDS6Jd/tOg8q+tG6bb3IztN3D3XsF4p9SN7dZXljyxl2gRdcUx7 aeGC52DbKeTmOglbMIzgtQwZEZzk8trKu6nEP4IPfOrIGKaoHWm7s7szoAKQeeF4 /FbKpvr8QlkvQ8LWZojXn4MBYCW7MfNnkFFvj5tU5lSjarnnFSGPA7sxtGN3yLaI tvLuiMfI5no+BSVf/mpUEQ9EVxhMNKT+AQdlaLtssvTfo3SUZbqENyZqdU84gUZD UUMhPh4bjM0oQdkji8N7sTEhjlHMfadLvez3NEXf47FLXoZNAz7qtSFMe+IIom6U 32zIDWUCgZkAyTXap2Y1lYZlLYfpxDTIr22L1yqrzfXbUif2OwcVLPHO6QGHacdQ fUj8hqysxifz5JT9A90aEN3EnCjW61JCOjLSgxRzGnWopayGdhtPhGdPp5pL0hH8 DY9FRuHMzqcBuOvFC/CQVg2xBKY/BqDYA77ffFFvFPHcPggNpWzMa2jsxtPSNc8o xdc29n5xbH4eEqPjZIselIMCgZkA2SiIMsIh/SQeEFyuyfSFj/ahqSM5+YrGF/Ch 2/rwUaBm59s7OccvwWJ947yKJ12ZDBFpoPCOYiJWqcXVns5vwEecyJCGrbAuVmQ1 LLYd8XG/DuW/JB1AAjS6NwDT9RllPHiJIPhyt1APyee9XBD+tdAHZns95uDzgbl6 GUjO/l7n2GXz15v5lZj3vEQNoiRQO46Z81t9ZRcCgZgty3gMiZLAiWoVxs1Jvsm+ Q6yEOE4J/l8Af9/m52HGbPKuzY5IYPjMywPOkxZvs0ArUk2Tx4rbM94/vHvN61bv cAnBk7Hu38CWlIG199lNRUY320JOeZFodKdLzrCSiCg4MlESupnfPBaB/GRz2b/Q emzbGp2xoqqB48tXTz/nYmYhiqxZWuDoxmbYC0c9bibiDzL9+zvmiQKBmHdc7xgv Wy1gh+Hof+7kJ/IM16k3gqtmmyIXk3BuC2BisY2qFHDayqYadCYUwT+IFBLtE0ly UGEijM4+vv/OauCevFAGGPEpkR7Nb+kGpYjMQ/91S04XgdJ0lxKasubbMak+e+mS hsO6DyOk7JHJiaf4E8lB3rGkXlSk1bdGLPjmw7tPtuuBgXu4HBvwsCm6mhtSc86v MEq7AoGYJGMqKpFohzCJf9+kIh+yItvpT8MAh9p8YtP/GcttAalxngNPZqKS6lvk 1m7ZcaklSUGpquMb738bV4PEeM05R9CveTql4ftISvTZAtuW8DrRO3u2+CgeLB2i TPkZKVJsb3AZSTdZnf1sNj7I4FBrSf8r2TFyxzhnzDBJQAa6cGM2vREZGvLRK/MJ zO22IxFMnZ3VViUGvJs= -----END RSA PRIVATE KEY----- ���������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/wild-key.pem��������������������������������������0000664�0001750�0001750�00000014603�12212322440�025406� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������Public Key Info: Public Key Algorithm: RSA Key Security Level: Normal modulus: 00:e2:d3:86:c4:99:5f:f3:a8:9a:c9:66:85:f6:cb: 43:84:0b:fa:b2:d7:7c:05:4d:ff:5e:c9:65:1e:16: 45:85:9e:5f:a2:59:50:73:52:31:82:76:07:df:09: 66:d5:3f:69:11:dd:35:5e:3a:a2:be:b2:fb:45:03: d4:01:42:e7:8d:f0:a7:d2:9e:b5:c2:db:61:a5:f6: 2e:cc:5c:ef:4b:28:06:d7:db:e8:bd:36:4d:06:da: 31:fd:aa:f3:8f:d8:5b:1c:0e:e7:10:84:1b:5d:0a: 18:b4:6b:80:06:f1:aa:d3:2f:60:87:46:5e:cb:47: f5:30:c2:af:a2:da:e8:8a:9e:a2:ae:d1:ff:87:41: 80:5d:f4:85:54:ec:3a:76:a2:ed:6f:98:42:e3:d3: d7:c4:25:5f:53:bb:1d:d6:9f:7d:70:c6:64:f0:bf: fb:43:d8:cc:f7:6b:da:f1:e5:4b:38:9f:34:e9:ed: b4:f6:6e:a3:80:0b:04:4d:e1:85:fe:31:9f:18:79: df:5c:1d:55:08:6c:4b:a5:93:5f:94:61:15:4f:68: c7:85:ac:1b:b4:37:cb:9b:50:25:0e:f6:01:13:d6: a9:56:62:2b:55:89:20:3b:84:56:5a:56:3a:eb:44: 77:53:1c:23:71:95:32:e6:6d:f3:43:d9:68:90:b7: b8:9b:3b:7f:a9:79:5e:ec:7d:c9:4a:c4:e7:3b:73: 83:7e:fc:c3:91:e2:e9:1b:77:0b:4a:cb:8c:7c:e7: ef:c3:22:0b:a0:c6:95:c1:b9:28:c3:81:f8:ee:30: 80:5c:c7:09:27: public exponent: 01:00:01: private exponent: 55:09:ac:8a:e4:5d:7e:c2:05:55:e0:63:f5:04:7b: 89:73:dc:47:54:56:20:be:ff:30:90:1c:a2:cd:02: bf:77:82:af:21:00:f2:5b:2c:48:96:eb:98:88:b3: ce:da:f9:0f:43:79:90:9c:37:0b:7b:9a:8c:63:45: 06:3c:09:07:c3:e3:87:29:0d:47:c2:6b:b7:86:b6: 40:d3:ce:ba:c4:84:dc:44:8b:da:f4:12:a8:b1:00: f0:f3:38:61:03:62:15:00:d9:4b:ed:db:3c:64:5e: a2:b5:72:c8:27:ae:3d:82:93:93:e3:a4:02:5e:35: e4:53:f8:f8:fb:4d:17:3b:26:0e:98:98:4e:23:16: 77:23:07:21:b1:76:b1:a7:9f:90:a8:ea:da:f3:3e: ff:3f:b6:be:19:7e:15:b0:3c:7d:75:f6:7d:58:bc: cd:da:ba:4a:ac:b5:ab:91:a9:71:b7:bf:db:0c:ca: ff:7a:72:0e:98:64:78:af:26:fc:07:df:8a:2e:9f: 51:3f:b3:d7:14:9f:1e:5a:0d:73:58:3c:37:67:5e: 4e:6c:f4:bd:e4:58:ae:aa:bd:eb:68:e3:ed:9c:78: af:de:80:9b:6a:93:01:ce:8e:b9:1b:ea:c4:cc:a8: df:55:8c:fb:27:6b:c1:64:9b:ed:48:c8:80:86:e3: 2d:a9:67:0a:7e:be:83:c4:aa:33:24:a1:c4:b4:2d: 17:72:6e:45:9f:81:b3:61:34:03:38:a2:6e:48:84: c3:aa:4b:9b:ba:0f:af:c2:2d:e0:b8:55:bb:01:3b: 6e:bb:77:81: prime1: 00:e6:06:0c:d6:72:1a:a9:3e:91:2f:5c:ca:a4:36: 2a:0e:1c:b8:e8:86:e8:c8:8d:f3:01:da:58:1c:5a: fb:71:23:84:66:0f:ec:00:f7:0a:ce:f4:0b:bb:93: 29:fe:50:ce:39:03:ed:0f:67:3e:a2:2d:3e:fa:c3: 1b:bd:cd:59:22:b8:57:35:f3:14:e9:4a:a6:62:22: 99:9b:a3:1a:b4:2b:d3:be:d0:7b:0b:8a:fb:5c:3c: 6e:05:45:58:c4:13:e0:96:33:b7:da:b0:14:dc:fa: 07:57:68:33:ab:a8:ab:1f:26:f6:96:ea:f2:5c:02: ee:99:28:ec:2a:65:f6:6f:6f:4e:5e:65:87:95:b3: 65:70:05:f2:15:37:6f:f7:94:67:19:98:b9:94:f1: 68:d5:47: prime2: 00:fc:71:0a:87:55:5d:b1:46:2a:95:0b:c4:38:ea: 38:71:bc:ce:68:8c:4b:0a:34:cc:50:df:50:d9:84: 1d:e3:9a:29:45:90:36:54:a0:f8:ce:69:82:06:5c: c9:db:e3:2f:90:86:ec:2f:bc:b6:ed:95:72:1c:b8: 1c:58:de:f5:ee:24:99:3c:e5:ab:8b:89:c0:94:c2: 63:a2:c9:2c:b1:7d:ad:f5:f5:fa:e7:04:84:e5:08: a6:c7:8a:46:92:5d:45:0f:b0:e9:b5:9f:a0:6c:43: 72:14:eb:00:e1:9a:af:9d:5e:2f:be:a3:d6:82:b2: c2:db:c9:3d:5a:42:31:a8:8b:26:6e:ee:50:96:48: 57:fc:96:2a:6c:ce:dd:d6:1c:59:22:06:0f:63:c8: 51:9d:21: coefficient: 00:8b:25:6f:8d:58:ca:17:d7:66:73:7d:c1:22:b3: fa:f6:09:b7:2c:b6:95:47:66:d5:17:97:51:cd:21: df:aa:d6:29:41:6d:c2:22:7e:dc:28:8a:a8:ab:fa: ba:c8:84:d3:45:be:9b:1f:8d:b6:c2:c6:17:88:65: 39:19:f4:1f:fc:98:a3:27:ae:4b:c1:3b:b3:b4:d8: 76:89:ec:51:c2:56:bc:53:e7:6c:1f:39:ab:37:97: 03:32:67:c8:15:0c:67:9f:6f:7c:92:3f:b3:12:b1: ec:ef:98:11:65:fd:96:20:5a:27:5d:fc:3b:cb:f0: 7a:c8:be:dd:02:c0:52:36:da:7e:9a:99:32:3f:44: 8e:fe:84:29:5b:44:8c:ea:42:22:18:4b:a9:00:e7: 63:e1:3a: exp1: 00:ae:50:cd:6f:c1:de:e4:7d:2e:c7:46:b9:a6:82: 09:92:d2:3f:6a:af:ba:3f:2a:1b:8b:3e:ed:60:e7: ad:ff:0a:5c:6e:80:08:68:9e:ce:89:11:36:c6:fa: 7a:6b:68:cf:2f:34:03:75:95:d7:48:4d:a3:99:a3: 3c:25:b5:35:a4:73:30:5c:09:0f:c2:cf:b8:91:4c: 09:3e:81:f7:5d:ac:8c:f5:e0:c6:2e:74:2f:92:b1: 94:ea:d7:a7:b2:48:21:fd:91:c9:f5:a7:54:d8:35: 7e:54:c5:f9:ca:4f:b3:06:93:9f:71:b5:30:df:7b: b5:57:4a:44:d6:c8:98:5d:d0:6b:02:6c:4c:b8:ac: cf:e5:7a:0b:ff:fa:18:16:f6:56:bf:76:16:c5:81: c0:e1:47: exp2: 39:1a:b5:20:02:0e:8c:b0:6b:a7:85:9e:e0:a5:13: 19:9f:75:2d:af:36:b6:5b:55:30:a2:23:9e:e0:c5: 06:1c:74:63:99:08:c1:42:1c:a6:4c:b5:ae:0c:c5: 58:e9:5e:74:1a:21:49:77:2e:06:36:7d:36:c3:eb: 1d:ab:6a:04:71:e0:fc:26:94:14:9f:97:a1:cf:0b: 4c:e2:a7:2a:8b:5c:93:bc:0e:02:be:41:f5:b1:6c: 50:cd:15:c3:bc:37:88:22:23:ec:02:ec:fe:30:8f: 98:ed:c4:28:44:9e:9f:41:94:19:52:e4:8e:72:33: a4:16:34:bb:bb:27:92:91:cf:a2:de:63:fa:6a:e9: 04:69:4f:b5:87:62:25:32:0a:73:a8:dd:48:5c:23: 22:21: Public Key ID: 76:93:58:59:EE:CC:7C:85:34:97:25:10:BE:DB:72:40:CC:57:4D:EC -----BEGIN RSA PRIVATE KEY----- MIIFfAIBAAKCATEA4tOGxJlf86iayWaF9stDhAv6std8BU3/XsllHhZFhZ5follQ c1IxgnYH3wlm1T9pEd01XjqivrL7RQPUAULnjfCn0p61wtthpfYuzFzvSygG19vo vTZNBtox/arzj9hbHA7nEIQbXQoYtGuABvGq0y9gh0Zey0f1MMKvotroip6irtH/ h0GAXfSFVOw6dqLtb5hC49PXxCVfU7sd1p99cMZk8L/7Q9jM92va8eVLOJ806e20 9m6jgAsETeGF/jGfGHnfXB1VCGxLpZNflGEVT2jHhawbtDfLm1AlDvYBE9apVmIr VYkgO4RWWlY660R3UxwjcZUy5m3zQ9lokLe4mzt/qXle7H3JSsTnO3ODfvzDkeLp G3cLSsuMfOfvwyILoMaVwbkow4H47jCAXMcJJwIDAQABAoIBMFUJrIrkXX7CBVXg Y/UEe4lz3EdUViC+/zCQHKLNAr93gq8hAPJbLEiW65iIs87a+Q9DeZCcNwt7moxj RQY8CQfD44cpDUfCa7eGtkDTzrrEhNxEi9r0EqixAPDzOGEDYhUA2Uvt2zxkXqK1 csgnrj2Ck5PjpAJeNeRT+Pj7TRc7Jg6YmE4jFncjByGxdrGnn5Co6trzPv8/tr4Z fhWwPH119n1YvM3aukqstauRqXG3v9sMyv96cg6YZHivJvwH34oun1E/s9cUnx5a DXNYPDdnXk5s9L3kWK6qveto4+2ceK/egJtqkwHOjrkb6sTMqN9VjPsna8Fkm+1I yICG4y2pZwp+voPEqjMkocS0LRdybkWfgbNhNAM4om5IhMOqS5u6D6/CLeC4VbsB O267d4ECgZkA5gYM1nIaqT6RL1zKpDYqDhy46IboyI3zAdpYHFr7cSOEZg/sAPcK zvQLu5Mp/lDOOQPtD2c+oi0++sMbvc1ZIrhXNfMU6UqmYiKZm6MatCvTvtB7C4r7 XDxuBUVYxBPgljO32rAU3PoHV2gzq6irHyb2luryXALumSjsKmX2b29OXmWHlbNl cAXyFTdv95RnGZi5lPFo1UcCgZkA/HEKh1VdsUYqlQvEOOo4cbzOaIxLCjTMUN9Q 2YQd45opRZA2VKD4zmmCBlzJ2+MvkIbsL7y27ZVyHLgcWN717iSZPOWri4nAlMJj oskssX2t9fX65wSE5Qimx4pGkl1FD7DptZ+gbENyFOsA4ZqvnV4vvqPWgrLC28k9 WkIxqIsmbu5QlkhX/JYqbM7d1hxZIgYPY8hRnSECgZkArlDNb8He5H0ux0a5poIJ ktI/aq+6Pyobiz7tYOet/wpcboAIaJ7OiRE2xvp6a2jPLzQDdZXXSE2jmaM8JbU1 pHMwXAkPws+4kUwJPoH3XayM9eDGLnQvkrGU6tenskgh/ZHJ9adU2DV+VMX5yk+z BpOfcbUw33u1V0pE1siYXdBrAmxMuKzP5XoL//oYFvZWv3YWxYHA4UcCgZg5GrUg Ag6MsGunhZ7gpRMZn3Utrza2W1UwoiOe4MUGHHRjmQjBQhymTLWuDMVY6V50GiFJ dy4GNn02w+sdq2oEceD8JpQUn5ehzwtM4qcqi1yTvA4CvkH1sWxQzRXDvDeIIiPs Auz+MI+Y7cQoRJ6fQZQZUuSOcjOkFjS7uyeSkc+i3mP6aukEaU+1h2IlMgpzqN1I XCMiIQKBmQCLJW+NWMoX12ZzfcEis/r2CbcstpVHZtUXl1HNId+q1ilBbcIiftwo iqir+rrIhNNFvpsfjbbCxheIZTkZ9B/8mKMnrkvBO7O02HaJ7FHCVrxT52wfOas3 lwMyZ8gVDGefb3ySP7MSsezvmBFl/ZYgWidd/DvL8HrIvt0CwFI22n6amTI/RI7+ hClbRIzqQiIYS6kA52PhOg== -----END RSA PRIVATE KEY----- �����������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/unknown-ca-cert.cfg�������������������������������0000644�0001750�0001750�00000004160�11544576223�026666� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# X.509 Certificate options # # DN options # The organization of the subject. organization = "Collabora" # The organizational unit of the subject. unit = "Wocky Test Suite" # The locality of the subject. # locality = # The state of the certificate owner. state = "Lost-in-Space" # The country of the subject. Two letter code. country = UK # The common name of the certificate owner. cn = "Wocky XMPP Library" # A user id of the certificate owner. #uid = "clauper" # If the supported DN OIDs are not adequate you can set # any OID here. # For example set the X.520 Title and the X.520 Pseudonym # by using OID and string pairs. #dn_oid = "2.5.4.12" "Dr." "2.5.4.65" "jackal" # This is deprecated and should not be used in new # certificates. # pkcs9_email = "none@none.org" # The serial number of the certificate serial = 001 # In how many days, counting from today, this certificate will expire. expiration_days = 10220 # X.509 v3 extensions # A dnsname in case of a WWW server. #dns_name = "www.none.org" #dns_name = "www.morethanone.org" # An IP address in case of a server. #ip_address = "192.168.1.1" # An email in case of a person email = "postmaster@collabora.co.uk" # An URL that has CRLs (certificate revocation lists) # available. Needed in CA certificates. crl_dist_points = "file:///tmp/wocky-tests/crl" # Whether this is a CA certificate or not ca # Whether this certificate will be used for a TLS client #tls_www_client # Whether this certificate will be used for a TLS server #tls_www_server # Whether this certificate will be used to sign data (needed # in TLS DHE ciphersuites). signing_key # Whether this certificate will be used to encrypt data (needed # in TLS RSA ciphersuites). Note that it is prefered to use different # keys for encryption and signing. #encryption_key # Whether this key will be used to sign other certificates. cert_signing_key # Whether this key will be used to sign CRLs. crl_signing_key # Whether this key will be used to sign code. #code_signing_key # Whether this key will be used to sign OCSP data. #ocsp_signing_key # Whether this key will be used for time stamping. #time_stamping_key ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/new-cert.cfg��������������������������������������0000644�0001750�0001750�00000004146�11544576223�025403� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# X.509 Certificate options # # DN options # The organization of the subject. organization = "Collabora" # The organizational unit of the subject. unit = "Wocky Test Suite" # The locality of the subject. # locality = # The state of the certificate owner. state = "Dazed" # The country of the subject. Two letter code. country = UK # The common name of the certificate owner. cn = "Wocky XMPP Library" # A user id of the certificate owner. #uid = "clauper" # If the supported DN OIDs are not adequate you can set # any OID here. # For example set the X.520 Title and the X.520 Pseudonym # by using OID and string pairs. #dn_oid = "2.5.4.12" "Dr." "2.5.4.65" "jackal" # This is deprecated and should not be used in new # certificates. # pkcs9_email = "none@none.org" # The serial number of the certificate serial = 003 # In how many days, counting from today, this certificate will expire. expiration_days = 7 # X.509 v3 extensions # A dnsname in case of a WWW server. dns_name = "weasel-juice.org" #dns_name = "www.morethanone.org" # An IP address in case of a server. ip_address = "127.0.0.1" # An email in case of a person #email = "postmaster@collabora.co.uk" # An URL that has CRLs (certificate revocation lists) # available. Needed in CA certificates. #crl_dist_points = "file:///tmp/wocky-tests/crl" # Whether this is a CA certificate or not #ca # Whether this certificate will be used for a TLS client tls_www_client # Whether this certificate will be used for a TLS server tls_www_server # Whether this certificate will be used to sign data (needed # in TLS DHE ciphersuites). #signing_key # Whether this certificate will be used to encrypt data (needed # in TLS RSA ciphersuites). Note that it is prefered to use different # keys for encryption and signing. encryption_key # Whether this key will be used to sign other certificates. #cert_signing_key # Whether this key will be used to sign CRLs. #crl_signing_key # Whether this key will be used to sign code. #code_signing_key # Whether this key will be used to sign OCSP data. #ocsp_signing_key # Whether this key will be used for time stamping. time_stamping_key ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/ca-2-cert.pem�������������������������������������0000644�0001750�0001750�00000002603�11544576223�025352� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIID5jCCAtCgAwIBAgIBATALBgkqhkiG9w0BAQUwbDELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTERMA8G A1UECBMIU3BpbmRsZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTAeFw0w OTA5MTgxMjU1MDVaFw0zNzA5MTExMjU1MDVaMGwxCzAJBgNVBAYTAlVLMRIwEAYD VQQKEwlDb2xsYWJvcmExGTAXBgNVBAsTEFdvY2t5IFRlc3QgU3VpdGUxETAPBgNV BAgTCFNwaW5kbGVkMRswGQYDVQQDExJXb2NreSBYTVBQIExpYnJhcnkwggEfMAsG CSqGSIb3DQEBAQOCAQ4AMIIBCQKCAQC+YAQjeUbAlnnvhQ4imQbL4aU8sJjM/M7g gm51NdXev3WwvOdDDU8LgvaKIoMQyQaS5XAt4Q/hAeHZJW0Nx3zZW9XWiqmHlqsU LdQKvxIz9xnvLRR74gHddMXqsPCHieSNvXm4cnnNPIwmWNiBIo5NdI/Te+tNmGqz pO4t1G9jYlhGNhc2vUIpDo4bO2vWqeRyqnQlrAykfZsScjryZtMBDSc9xZdjJlJt 2nbLlQJVUgi1bEwazP3SWEijfZTKhnXn0bvhFGUSEssHb5CUVr6ILRzWJtAVp/us YAaQLZLhMhcA94YvFB0dlVltsdtvwBPidEC4NMPJcitN/3s1fQbPAgMBAAGjgZkw gZYwDwYDVR0TAQH/BAUwAwEB/zAlBgNVHREEHjAcgRpwb3N0bWFzdGVyQGNvbGxh Ym9yYS5jby51azAPBgNVHQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBTeKryla1ofuyCr Gg3ugeTEymWLhzAsBgNVHR8EJTAjMCGgH6AdhhtmaWxlOi8vL3RtcC93b2NreS10 ZXN0cy9jcmwwCwYJKoZIhvcNAQEFA4IBAQC2RqDYK3xPnMGnlzJBVJI4cPH/iRLi 9ZUWmBzpjHpo0d/in6lAF0UirmjpgllXpCUhJMfP5fxOsZYk1eE/leqTyTory7Xj K6zdHmkFGPU3b5ibFPX65iGFpqZdjCAplFZ9HI7au1b0SpbsMKesE7ZXzBF0+ki3 GrKgQF+e7cMktJf07I4xoVVYimSpADFOHo9Pk1sceK/zSKGzob7TziD4Tpnc8Rhq dOj7J8EbzhqjBVciPYzXvlLjyAqdYRg5RHV1xSIvYKeK0PwVzmNY9Xu30+VShJHc 3Hf/VLl2T1ll8tXUj3hc1Jd2+ZMthTF1PIX3bunTnNUm2PENoxa8pDG3 -----END CERTIFICATE----- �����������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/ca-1-cert.pem�������������������������������������0000644�0001750�0001750�00000002577�11544576223�025363� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIID4jCCAsygAwIBAgIBATALBgkqhkiG9w0BAQUwajELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTEPMA0G A1UECBMGRm9sZGVkMRswGQYDVQQDExJXb2NreSBYTVBQIExpYnJhcnkwHhcNMDkw OTE4MTI1NTAzWhcNMzcwOTExMTI1NTAzWjBqMQswCQYDVQQGEwJVSzESMBAGA1UE ChMJQ29sbGFib3JhMRkwFwYDVQQLExBXb2NreSBUZXN0IFN1aXRlMQ8wDQYDVQQI EwZGb2xkZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTCCAR8wCwYJKoZI hvcNAQEBA4IBDgAwggEJAoIBANRkYbvqWdla+zNLsftXYnaAD0agDbNl70y4yxNj V1DriZnNgjgWM8ZIgUdvFx+sA8wMoRFBLnXWYfzI+fHYFak+JqysvQmqTifXjKOs Q8Qdhb3hc2z10X7pobRK+oxE7VXDKKp5ou4f3wx1mvSTjB1oTr5o2ZnA5K/dLCM7 OmJ2C/Vj8z6l6HV41esPEYEZv+wfP/9z3xmNhNHcRWIeipEdDZDfXc0n22SeEnGS ZrSJDP9CZaJWAcLUhD5OEh+B3P/gfO9KDAN8PicSFFXj2X0t8incmz5fs6JosgEF o40D/R4xUIU562HEY/4uOM6N2nHM+MKgiDHEUh9s3lLmSB8CAwEAAaOBmTCBljAP BgNVHRMBAf8EBTADAQH/MCUGA1UdEQQeMByBGnBvc3RtYXN0ZXJAY29sbGFib3Jh LmNvLnVrMA8GA1UdDwEB/wQFAwMHBgAwHQYDVR0OBBYEFJdQenuGG7TS4L2av7+3 HHWC+uO7MCwGA1UdHwQlMCMwIaAfoB2GG2ZpbGU6Ly8vdG1wL3dvY2t5LXRlc3Rz L2NybDALBgkqhkiG9w0BAQUDggEBAI2E2XcrxGbK+e9CdIxnrVWsh8HgcvBB/F4M 9jRUSjc3+w3E1zxlyfqGgSrzCJIpZbq7TQ7tTd1AV8j9hP4bP1r3BX6lhiXRtRKC thobgl1gXQtHkFhRpZrWe4vECqucHlznel9nhtLeY50ykt8ajvqxhthe/uabKNlo wC87Aq1ykigR1imLAY8UdvdXfvnfS1d5bF/k3TSw2YOZE4u8KToQf1LVPIG12OPi uStuIX9UYzSe8qOurrbjX+qehoubmrgLPGRKyNfIHsp7Arr/yUnjK5WtojTjcF85 nuP8FceVT5cvKYYPcBP6+YpAeeBJBiK95kzZGqgVewoLpKJht+0= -----END CERTIFICATE----- ���������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/wild-cert.pem�������������������������������������0000664�0001750�0001750�00000003032�12212322440�025545� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN CERTIFICATE----- MIIEVTCCAz2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQGEwJVSzES MBAGA1UEChMJQ29sbGFib3JhMRkwFwYDVQQLExBXb2NreSBUZXN0IFN1aXRlMREw DwYDVQQIEwhDb25mdXNlZDEbMBkGA1UEAxMSV29ja3kgWE1QUCBMaWJyYXJ5MB4X DTEyMDUwODE3MjMxNFoXDTQwMDUwMTE3MjMxNFowaTELMAkGA1UEBhMCVUsxEjAQ BgNVBAoTCUNvbGxhYm9yYTEZMBcGA1UECxMQV29ja3kgVGVzdCBTdWl0ZTEOMAwG A1UECBMFRGF6ZWQxGzAZBgNVBAMTEldvY2t5IFhNUFAgTGlicmFyeTCCAVIwDQYJ KoZIhvcNAQEBBQADggE/ADCCAToCggExAOLThsSZX/OomslmhfbLQ4QL+rLXfAVN /17JZR4WRYWeX6JZUHNSMYJ2B98JZtU/aRHdNV46or6y+0UD1AFC543wp9KetcLb YaX2Lsxc70soBtfb6L02TQbaMf2q84/YWxwO5xCEG10KGLRrgAbxqtMvYIdGXstH 9TDCr6La6Iqeoq7R/4dBgF30hVTsOnai7W+YQuPT18QlX1O7HdaffXDGZPC/+0PY zPdr2vHlSzifNOnttPZuo4ALBE3hhf4xnxh531wdVQhsS6WTX5RhFU9ox4WsG7Q3 y5tQJQ72ARPWqVZiK1WJIDuEVlpWOutEd1McI3GVMuZt80PZaJC3uJs7f6l5Xux9 yUrE5ztzg378w5Hi6Rt3C0rLjHzn78MiC6DGlcG5KMOB+O4wgFzHCScCAwEAAaOB 1DCB0TAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD ATAjBgNVHREEHDAaghIqLndlYXNlbC1qdWljZS5vcmeHBH8AAAEwDwYDVR0PAQH/ BAUDAwcgADAdBgNVHQ4EFgQUdpNYWe7MfIU0lyUQvttyQMxXTewwHwYDVR0jBBgw FoAUSTAmCIya1mnNi8DMDlwCjkofpowwLAYDVR0fBCUwIzAhoB+gHYYbZmlsZTov Ly90bXAvd29ja3ktdGVzdHMvY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQBd0wScKbZR +VhPij0/MWoQCwo7SpXyOCc1oTH5Cj2FKg70Al2fyfNXeQ94QybK2IFUuhuj6QuC 2kr11a8yUaYj5GfbMP0JHjJn8EKeRlxsv7q37nGkFcN4hweR3UfrY4dhEh195ZlM f3odQaKfyE4ST/SmVzGrzxwVupcuHcxCD4VowYMjO2xl2XeMjTMmkRhuW/kTcVHb xdhkLekyD5AEI3XndFKDRufFXg5nGmV7t5A/i1gKxGi/Co2YeTYd1XDspK0GSyX7 hl6RoZrGPkYF3mUmv6E/SiL8inCMfvt56aSQttX9zqB7zXOTXFnFOho+EYb6ZxvL liKZJQZ39OX7 -----END CERTIFICATE----- ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/tls-cert.cfg��������������������������������������0000644�0001750�0001750�00000004152�11544576223�025411� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# X.509 Certificate options # # DN options # The organization of the subject. organization = "Collabora" # The organizational unit of the subject. unit = "Wocky Test Suite" # The locality of the subject. # locality = # The state of the certificate owner. state = "Dazed" # The country of the subject. Two letter code. country = UK # The common name of the certificate owner. cn = "Wocky XMPP Library" # A user id of the certificate owner. #uid = "clauper" # If the supported DN OIDs are not adequate you can set # any OID here. # For example set the X.520 Title and the X.520 Pseudonym # by using OID and string pairs. #dn_oid = "2.5.4.12" "Dr." "2.5.4.65" "jackal" # This is deprecated and should not be used in new # certificates. # pkcs9_email = "none@none.org" # The serial number of the certificate serial = 002 # In how many days, counting from today, this certificate will expire. expiration_days = 10220 # X.509 v3 extensions # A dnsname in case of a WWW server. dns_name = "weasel-juice.org" #dns_name = "www.morethanone.org" # An IP address in case of a server. ip_address = "127.0.0.1" # An email in case of a person #email = "postmaster@collabora.co.uk" # An URL that has CRLs (certificate revocation lists) # available. Needed in CA certificates. #crl_dist_points = "file:///tmp/wocky-tests/crl" # Whether this is a CA certificate or not #ca # Whether this certificate will be used for a TLS client tls_www_client # Whether this certificate will be used for a TLS server tls_www_server # Whether this certificate will be used to sign data (needed # in TLS DHE ciphersuites). #signing_key # Whether this certificate will be used to encrypt data (needed # in TLS RSA ciphersuites). Note that it is prefered to use different # keys for encryption and signing. encryption_key # Whether this key will be used to sign other certificates. #cert_signing_key # Whether this key will be used to sign CRLs. #crl_signing_key # Whether this key will be used to sign code. #code_signing_key # Whether this key will be used to sign OCSP data. #ocsp_signing_key # Whether this key will be used for time stamping. time_stamping_key ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/certs/exp-key.pem���������������������������������������0000644�0001750�0001750�00000003217�11544576223�025261� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAnlBf47+ldQRlzW/nqYpggSx0alV6TkLnf7gt0WIBv4XGoDOJ FKmrwMkEiGvNznPS9NUmN/EDRDW7OGHSwR9Br8aOEnNwP1/CGadt5YOpksMWc1qE Tvw9IOW8QwJAl2PoYfnneB53x6PmtSf21Z8jcHerLGoEH8gl19IQpg+LDZOAxZlq 99KBFTEaOY2k3EaMl3+QE7gWvA9G5bsDmqnHGqLBS0upugdHPKOjjrk+0jPvVb8x tQVPk87bWayiZi4dr6yldPfiJ4sQxTH3plhlAh39fN8Z/Um9W5TcozPvmYE7PfHW yV0rc8WCzDZHiRWba6DIusM4LdSm33vV63GgoQIDAQABAoIBAEe1Vkm9w/8l98q/ FmrIAABil3SWtSh/y4Yhcbd2sh4DRT3JOh0+4UoYg1IbqoQKGJLHfWE3bOhXgi7+ uEy7kLBCupWG7l/2St/945xjL8sHTMMBTA7O2A1vof+kJIeuPFMss/jHrC+kgNqr eHW4eH/35HPgrW+L5ABG6T2eqriB0fxRLHH1QwsOqIoIG2YRe04PdEsjcNgtSA7d pqcUQU21zbfk2ELUTE8SrlMeDv+ybQTrUJeM44i50R7S6nX5z/KceLO69Hgbgy0Z CXLsmwCgQl1s7Sg0Ur5TSgSKmqVbyyVtJxln3LBMYpO4JxM6LTMT2klxtpZcGbkW rRbLtRUCgYEAwX1LrXcQWm1m6mkni5NVxXxM70hySKuchcDustLxjlnuGuE/IkXI 937fFmXoI8XMGdsBna/WA+CfngKOZK+w0LhOp5aZHGl74r0v/fkS2fz+qzctekQ1 XZ0/QY1hzquZWiczlxkT/lbe0hD4t0GnQom9tJdmLfqxU/ovqKItQO8CgYEA0XXc vljS32koN2oUWWkeBijO7tXHYze2MyiqA447zTaVqSaP69j3LjVa8tHMbADCe2Qx 4CCPuizbGzf8T++hA0e4jGKcnwd96HUHbfP4Q9qNdzg88kUIT0QrDXccMF3MAKRI zd/YzmMDPr+mTWxkDiMQ3kvyixDaJAyTbzzTF28CgYEAgF220lt2bve72nJu+OuD cOR5Shp/L3Ui/52y/tJxzWYeUJj1QLCZlpEGQh7Ttr/oG5MvbEUWsDXaz4KUo3nn zWEpVYfVBoN43EF1UIJpHlP5RO/zbPVJjlTffYblx64SrDvrvye1GvzZEPaPe0zE QaGOSPxUntZ9xN/rtG37peMCgYAfBwKH/8hc58rZSpFxHS0hZHIi1vAONnZ65Y8p r6wUHf3VbKztFtqmsaijR4ishwBIHvN0a95eib57LbPmc2y6e6lOwlzJAecYxB0x oG4qPvmtq1r72FX+x+5ItFgsofhSMAPI21vWVrxoUyNjXKcFoRQimcV37CskI+jD FZN/aQKBgQCQ0pGix/pOA5SJ6ZgwsovK97h/F2VvVx2NhzR2hKkp1ifFzZYmYCLf sm7bzuzcb322ahb+bCoVTUpD6U1QXpeuJnqCx+VBI6J3WfBMerKSzxQQ6ksGfANS 3OOYYAtZOMN72utKg6UPd7zVtTx8gC1peRogQEfELDT8INPOv/RG9g== -----END RSA PRIVATE KEY----- ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-xmpp-reader-test.c��������������������������������0000664�0001750�0001750�00000036660�12212322440�026544� 0����������������������������������������������������������������������������������������������������ustar�00cassidy�������������������������cassidy�������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#ifdef HAVE_CONFIG_H #include "config.h" #endif #include <stdio.h> #include <unistd.h> #include <string.h> #include <glib.h> #include <wocky/wocky.h> #include "wocky-test-helper.h" #define HEADER \ "<?xml version='1.0' encoding='UTF-8'?> " \ "<stream:stream xmlns='jabber:client' " \ " xmlns:stream='http://etherx.jabber.org/streams'> " #define FOOTER "</stream:stream> " #define BROKEN_HEADER \ "<?xml version='1.0' encoding='UTF-8'?> " \ "<stream:streamsss xmlns='jabber:client' " \ " xmlns:stream='http://etherx.jabber.org/streams'> " #define HEADER_WITH_UNQUALIFIED_LANG \ "<?xml version='1.0' encoding='UTF-8'?> " \ "<stream:stream xmlns='jabber:client' " \ " xmlns:stream='http://etherx.jabber.org/streams' " \ " lang='fi'> " #define BROKEN_MESSAGE \ " <message to='juliet@example.com' from='romeo@example.net' xml:lang='en' " \ " id=\"0\"> " \ " <body>Art thou not Romeo, and a Montague?</ody> " \ " </essage> " #define MESSAGE_CHUNK0 \ " <message to='juliet@example.com' from='romeo@example.net' xml:lang='en' " \ " id=\"0\"> " \ " <body>Art thou not Romeo, " #define MESSAGE_CHUNK1 \ " and a Montague?</body> " \ " </message> " #define VCARD_MESSAGE \ " <iq id='v1' " \ " to='stpeter@jabber.org/roundabout' " \ " type='result'> " \ " <vCard xmlns='vcard-temp'> " \ " <FN>Peter Saint-Andre</FN> " \ " <N> " \ " <FAMILY>Saint-Andre</FAMILY> " \ " <GIVEN>Peter</GIVEN> " \ " <MIDDLE/> " \ " </N> " \ " <NICKNAME>stpeter</NICKNAME> " \ " <URL>http://www.xmpp.org/xsf/people/stpeter.shtml</URL> " \ " <BDAY>1966-08-06</BDAY> " \ " <ORG> " \ " <ORGNAME>XMPP Standards Foundation</ORGNAME> " \ " <ORGUNIT/> " \ " </ORG> " \ " <TITLE>Executive Director " \ " Patron Saint " \ " stpeter@jabber.org " \ " " \ " " #define VALID_NAMESPACE "http://garden.with.spaces" #define INVALID_NAMESPACE_MESSAGE \ " "\ " " \ " " \ " " \ " " #define WHITESPACE_PADDED_BODY " The Wench is Dead! " #define MESSAGE_WITH_WHITESPACE_PADDED_BODY \ " " \ " " WHITESPACE_PADDED_BODY "" \ " " #define WHITESPACE_ONLY_BODY " " #define MESSAGE_WITH_WHITESPACE_ONLY_BODY \ " " \ " " WHITESPACE_ONLY_BODY "" \ " " #define U_FDEF "\xe7\xb7\xaf" /* a non-character */ #define REPLACE "\xef\xbf\xbd" /* U+FFFD REPLACEMENT CHARACTER */ #define MONKEY "\xf0\x9f\x99\x88" /* U+1F648 SEE-NO-EVIL MONKEY */ #define NON_CHARACTER_CODEPOINTS U_FDEF MONKEY U_FDEF #define NON_CHARACTER_CODEPOINTS_REPLACEMENT REPLACE MONKEY REPLACE #define MESSAGE_WITH_NON_CHARACTER_CODEPOINTS \ " " \ " " NON_CHARACTER_CODEPOINTS "" \ " " static void test_stream_no_stanzas (void) { WockyXmppReader *reader; GError *error = NULL; reader = wocky_xmpp_reader_new (); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_INITIAL); wocky_xmpp_reader_push (reader, (guint8 *) HEADER FOOTER, strlen (HEADER FOOTER)); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_CLOSED); g_assert (wocky_xmpp_reader_peek_stanza (reader) == NULL); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_CLOSED); g_assert (wocky_xmpp_reader_pop_stanza (reader) == NULL); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_CLOSED); error = wocky_xmpp_reader_get_error (reader); g_assert_no_error (error); g_object_unref (reader); } static void test_stream_open_error (void) { WockyXmppReader *reader; GError *error = NULL; reader = wocky_xmpp_reader_new (); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_INITIAL); wocky_xmpp_reader_push (reader, (guint8 *) BROKEN_HEADER, strlen (BROKEN_HEADER)); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_ERROR); error = wocky_xmpp_reader_get_error (reader); g_assert_error (error, WOCKY_XMPP_READER_ERROR, WOCKY_XMPP_READER_ERROR_INVALID_STREAM_START); g_error_free (error); g_object_unref (reader); } static void test_stream_open_unqualified_lang (void) { WockyXmppReader *reader = wocky_xmpp_reader_new (); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_INITIAL); wocky_xmpp_reader_push (reader, (guint8 *) HEADER_WITH_UNQUALIFIED_LANG, strlen (HEADER_WITH_UNQUALIFIED_LANG)); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_OPENED); g_object_unref (reader); } static void test_parse_error (void) { WockyXmppReader *reader; GError *error = NULL; reader = wocky_xmpp_reader_new (); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_INITIAL); wocky_xmpp_reader_push (reader, (guint8 *) HEADER, strlen (HEADER)); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_OPENED); wocky_xmpp_reader_push (reader, (guint8 *) BROKEN_MESSAGE, strlen (BROKEN_MESSAGE)); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_ERROR); g_assert (wocky_xmpp_reader_peek_stanza (reader) == NULL); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_ERROR); g_assert (wocky_xmpp_reader_pop_stanza (reader) == NULL); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_ERROR); error = wocky_xmpp_reader_get_error (reader); g_assert_error (error, WOCKY_XMPP_READER_ERROR, WOCKY_XMPP_READER_ERROR_PARSE_ERROR); g_error_free (error); g_object_unref (reader); } static void test_no_stream_parse_message (WockyXmppReader *reader) { WockyStanza *stanza; g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_OPENED); wocky_xmpp_reader_push (reader, (guint8 *) MESSAGE_CHUNK0, strlen (MESSAGE_CHUNK0)); g_assert (wocky_xmpp_reader_pop_stanza (reader) == NULL); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_OPENED); wocky_xmpp_reader_push (reader, (guint8 *) MESSAGE_CHUNK1, strlen (MESSAGE_CHUNK1)); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_OPENED); g_assert ((stanza = wocky_xmpp_reader_peek_stanza (reader)) != NULL); g_assert ((stanza = wocky_xmpp_reader_pop_stanza (reader)) != NULL); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_CLOSED); g_object_unref (stanza); } static void test_no_stream_hunks (void) { WockyXmppReader *reader; reader = wocky_xmpp_reader_new_no_stream (); test_no_stream_parse_message (reader); g_object_unref (reader); } static void test_no_stream_reset (void) { WockyXmppReader *reader; reader = wocky_xmpp_reader_new_no_stream (); /* whole message, reset, whole message, reset */ test_no_stream_parse_message (reader); wocky_xmpp_reader_reset (reader); test_no_stream_parse_message (reader); wocky_xmpp_reader_reset (reader); /* push half a message and reset the parser*/ g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_OPENED); wocky_xmpp_reader_push (reader, (guint8 *) MESSAGE_CHUNK0, strlen (MESSAGE_CHUNK0)); wocky_xmpp_reader_reset (reader); /* And push a whole message through again */ test_no_stream_parse_message (reader); g_object_unref (reader); } /* libXML2 doesn't like the vcard-temp namespace test if we can still correctly parse it */ static void test_vcard_namespace (void) { WockyXmppReader *reader; WockyStanza *stanza; reader = wocky_xmpp_reader_new_no_stream (); wocky_xmpp_reader_push (reader, (guint8 *) VCARD_MESSAGE, strlen (VCARD_MESSAGE)); g_assert ((stanza = wocky_xmpp_reader_pop_stanza (reader)) != NULL); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_CLOSED); g_object_unref (stanza); g_object_unref (reader); } static void test_invalid_namespace (void) { WockyXmppReader *reader; WockyStanza *stanza; reader = wocky_xmpp_reader_new_no_stream (); wocky_xmpp_reader_push (reader, (guint8 *) INVALID_NAMESPACE_MESSAGE, strlen (INVALID_NAMESPACE_MESSAGE)); g_assert ((stanza = wocky_xmpp_reader_pop_stanza (reader)) != NULL); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_CLOSED); g_assert_cmpstr (VALID_NAMESPACE, ==, wocky_node_get_ns ( wocky_node_get_child (wocky_stanza_get_top_node (stanza), "branch"))); g_object_unref (stanza); g_object_unref (reader); } /* Helper function for the whitespace body tests */ static void test_body_with_alternative ( const gchar *xml, const gchar *expected_body_text, const gchar *alt_body_text) { WockyXmppReader *reader = wocky_xmpp_reader_new_no_stream (); WockyStanza *stanza; WockyNode *body; wocky_xmpp_reader_push (reader, (guint8 *) xml, strlen (xml)); stanza = wocky_xmpp_reader_pop_stanza (reader); g_assert (stanza != NULL); body = wocky_node_get_child (wocky_stanza_get_top_node (stanza), "body"); g_assert (body != NULL); g_assert (g_utf8_validate (body->content, -1, NULL)); if (alt_body_text == NULL) { g_assert_cmpstr (body->content, ==, expected_body_text); } else { if (wocky_strdiff (body->content, expected_body_text) && wocky_strdiff (body->content, alt_body_text)) { g_error ("Body text «%s» was neither «%s» nor «%s»", body->content, expected_body_text, alt_body_text); } } g_object_unref (stanza); g_object_unref (reader); } static void test_body (const gchar *xml, const gchar *exp) { test_body_with_alternative (xml, exp, NULL); } /* Test that whitespace around the text contents of a message isn't ignored */ static void test_whitespace_padding (void) { test_body (MESSAGE_WITH_WHITESPACE_PADDED_BODY, WHITESPACE_PADDED_BODY); } /* Test that a message body consisting entirely of whitespace isn't ignored */ static void test_whitespace_only (void) { test_body (MESSAGE_WITH_WHITESPACE_ONLY_BODY, WHITESPACE_ONLY_BODY); } /* Test that a message body containing non-character codepoints is * handled "appropriately". Older GLib replaces them with U+FFFD, * newer GLib keeps them as-is. */ static void test_non_character_codepoints (void) { test_body_with_alternative (MESSAGE_WITH_NON_CHARACTER_CODEPOINTS, NON_CHARACTER_CODEPOINTS, NON_CHARACTER_CODEPOINTS_REPLACEMENT); } static void check_namespaces ( WockyXmppReader *reader, const gchar *xml, const gchar *expected_namespace) { WockyStanza *stanza; WockyNode *top_node, *body_node; wocky_xmpp_reader_push (reader, (const guint8 *) xml, strlen (xml)); stanza = wocky_xmpp_reader_pop_stanza (reader); g_assert (stanza != NULL); top_node = wocky_stanza_get_top_node (stanza); g_assert (top_node != NULL); g_assert_cmpstr (expected_namespace, ==, wocky_node_get_ns (top_node)); body_node = wocky_node_get_first_child (top_node); g_assert (body_node != NULL); g_assert_cmpstr (expected_namespace, ==, wocky_node_get_ns (body_node)); g_object_unref (stanza); wocky_xmpp_reader_reset (reader); } static void test_no_stream_default_namespace ( WockyXmppReader *reader, const gchar *expected_default_namespace) { /* Regardless of the reader's default namespace, a root node with an * explicitly-specified namespace should get that namespace. */ check_namespaces (reader, "" "hai", WOCKY_XMPP_NS_JABBER_CLIENT); /* What namespace the nodes here end up in depends on the reader's default. */ check_namespaces (reader, "hai", expected_default_namespace); } static void test_no_stream_default_default_namespace (void) { WockyXmppReader *reader = wocky_xmpp_reader_new_no_stream (); /* WockyXmppReader defaults to the empty namespace. */ test_no_stream_default_namespace (reader, ""); g_object_unref (reader); } static void test_no_stream_specified_default_namespace (void) { #define WEIRD "wocky:weird:namespace" WockyXmppReader *reader = wocky_xmpp_reader_new_no_stream_ns (WEIRD); test_no_stream_default_namespace (reader, WEIRD); g_object_unref (reader); #undef WEIRD } int main (int argc, char **argv) { int result; test_init (argc, argv); g_test_add_func ("/xmpp-reader/stream-no-stanzas", test_stream_no_stanzas); g_test_add_func ("/xmpp-reader/stream-open-error", test_stream_open_error); g_test_add_func ("/xmpp-reader/stream-open-unqualified-lang", test_stream_open_unqualified_lang); g_test_add_func ("/xmpp-reader/parse-error", test_parse_error); g_test_add_func ("/xmpp-reader/no-stream-hunks", test_no_stream_hunks); g_test_add_func ("/xmpp-reader/no-stream-resetting", test_no_stream_reset); g_test_add_func ("/xmpp-reader/vcard-namespace", test_vcard_namespace); g_test_add_func ("/xmpp-reader/invalid-namespace", test_invalid_namespace); g_test_add_func ("/xmpp-reader/whitespace-padding", test_whitespace_padding); g_test_add_func ("/xmpp-reader/whitespace-only", test_whitespace_only); g_test_add_func ("/xmpp-reader/utf-non-character-codepoints", test_non_character_codepoints); g_test_add_func ("/xmpp-reader/no-stream-default-default-namespace", test_no_stream_default_default_namespace); g_test_add_func ("/xmpp-reader/no-stream-specified-default-namespace", test_no_stream_specified_default_namespace); result = g_test_run (); test_deinit (); return result; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/Makefile.am0000664000175000017500000002454612332440453024111 0ustar00cassidycassidy00000000000000############################################################################ # x509 certificates: TEST_DIR := @abs_top_srcdir@/tests SUMMARY := $(TEST_DIR)/summarise-tests.py CERT_DIR := $(TEST_DIR)/certs CA_KEY := $(CERT_DIR)/ca-0-key.pem CA_CERT := $(CERT_DIR)/ca-0-cert.pem SS_KEY := $(CERT_DIR)/ss-key.pem SS_CERT := $(CERT_DIR)/ss-cert.pem REV_KEY := $(CERT_DIR)/rev-key.pem REV_CERT := $(CERT_DIR)/rev-cert.pem EXP_KEY := $(CERT_DIR)/exp-key.pem EXP_CERT := $(CERT_DIR)/exp-cert.pem NEW_KEY := $(CERT_DIR)/new-key.pem NEW_CERT := $(CERT_DIR)/new-cert.pem TLS_KEY := $(CERT_DIR)/tls-key.pem TLS_CERT := $(CERT_DIR)/tls-cert.pem WILD_KEY := $(CERT_DIR)/wild-key.pem WILD_CERT:= $(CERT_DIR)/wild-cert.pem BADWILD_KEY := $(CERT_DIR)/badwild-key.pem BADWILD_CERT := $(CERT_DIR)/badwild-cert.pem CA_DIR := $(CERT_DIR)/cas CRL_DIR := $(CERT_DIR)/crl UNKNOWN_KEY := $(CERT_DIR)/unknown-key.pem UNKNOWN_CERT := $(CERT_DIR)/unknown-cert.pem INCLUDES := -I$(top_builddir)/wocky TLSDEFS := -DTLS_CA_KEY_FILE='"$(CA_KEY)"' \ -DTLS_CA_CRT_FILE='"$(CA_CERT)"' \ -DTLS_SS_KEY_FILE='"$(SS_KEY)"' \ -DTLS_SS_CRT_FILE='"$(SS_CERT)"' \ -DTLS_EXP_KEY_FILE='"$(EXP_KEY)"' \ -DTLS_EXP_CRT_FILE='"$(EXP_CERT)"' \ -DTLS_NEW_KEY_FILE='"$(NEW_KEY)"' \ -DTLS_NEW_CRT_FILE='"$(NEW_CERT)"' \ -DTLS_REV_KEY_FILE='"$(REV_KEY)"' \ -DTLS_REV_CRT_FILE='"$(REV_CERT)"' \ -DTLS_UNKNOWN_KEY_FILE='"$(UNKNOWN_KEY)"' \ -DTLS_UNKNOWN_CRT_FILE='"$(UNKNOWN_CERT)"' \ -DTLS_SERVER_KEY_FILE='"$(TLS_KEY)"' \ -DTLS_SERVER_CRT_FILE='"$(TLS_CERT)"'\ -DTLS_WILD_KEY_FILE='"$(WILD_KEY)"' \ -DTLS_WILD_CRT_FILE='"$(WILD_CERT)"' \ -DTLS_BADWILD_CRT_FILE='"$(BADWILD_CERT)"' \ -DTLS_BADWILD_KEY_FILE='"$(BADWILD_KEY)"' \ -DTLS_CRL_DIR='"$(CRL_DIR)"' \ -DTLS_CA_DIR='"$(CA_DIR)"' ############################################################################ TEST_PROGS = \ wocky-bare-contact-test \ wocky-caps-hash-test \ wocky-connector-test \ wocky-contact-factory-test \ wocky-data-form-test \ wocky-jid-validation-test \ wocky-loopback-test \ wocky-node-tree-test \ wocky-pep-service-test \ wocky-ping-test \ wocky-porter-test \ wocky-pubsub-node-test \ wocky-pubsub-service-test \ wocky-resource-contact-test \ wocky-roster-test \ wocky-sasl-utils-test \ wocky-scram-sha1-test \ wocky-session-test \ wocky-stanza-test \ wocky-tls-test \ wocky-utils-test \ wocky-xmpp-connection-test \ wocky-xmpp-node-test \ wocky-xmpp-reader-test \ wocky-xmpp-readwrite-test \ $(NULL) noinst_PROGRAMS = if HAVE_LIBSASL2 TEST_PROGS += wocky-test-sasl-auth noinst_PROGRAMS += wocky-dummy-xmpp-server endif if HAVE_GIO_PROXY TEST_PROGS += wocky-http-proxy-test endif wocky_bare_contact_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-bare-contact-test.c wocky_caps_hash_test_SOURCES = wocky-caps-hash-test.c \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h EXTRA_wocky_connector_test_DEPENDENCIES = $(CA_DIR) certs wocky_connector_test_SOURCES = \ wocky-connector-test.c \ wocky-test-sasl-auth-server.c \ wocky-test-sasl-auth-server.h \ wocky-test-connector-server.c \ wocky-test-connector-server.h \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ test-resolver.c test-resolver.h wocky_connector_test_LDADD = $(LDADD) @LIBSASL2_LIBS@ wocky_connector_test_CFLAGS = $(AM_CFLAGS) @LIBSASL2_CFLAGS@ $(TLSDEFS) wocky_contact_factory_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-contact-factory-test.c wocky_data_form_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-data-form-test.c wocky_dummy_xmpp_server_SOURCES = wocky-dummy-xmpp-server.c \ wocky-test-connector-server.c wocky-test-connector-server.h \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-test-sasl-auth-server.c wocky-test-sasl-auth-server.h wocky_dummy_xmpp_server_LDADD = $(LDADD) @LIBSASL2_LIBS@ wocky_dummy_xmpp_server_CFLAGS = $(AM_CFLAGS) @LIBSASL2_CFLAGS@ $(TLSDEFS) wocky_http_proxy_test_SOURCES = wocky-http-proxy-test.c \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h wocky_jid_validation_test_SOURCES = \ wocky-jid-validation-test.c \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h wocky_loopback_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-loopback-test.c wocky_node_tree_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-node-tree-test.c wocky_pep_service_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-pep-service-test.c wocky_ping_test_SOURCES = \ wocky-ping-test.c \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h wocky_porter_test_SOURCES = \ wocky-porter-test.c \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h wocky_pubsub_node_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-pubsub-test-helpers.c wocky-pubsub-test-helpers.h \ wocky-pubsub-node-test.c wocky_pubsub_service_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-pubsub-test-helpers.c wocky-pubsub-test-helpers.h \ wocky-pubsub-service-test.c wocky_resource_contact_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-resource-contact-test.c wocky_roster_test_SOURCES = \ wocky-roster-test.c \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h wocky_sasl_utils_test_SOURCES = wocky-sasl-utils-test.c wocky_scram_sha1_test_SOURCES = wocky-scram-sha1-test.c \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h wocky_session_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-session-test.c wocky_stanza_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-stanza-test.c wocky_test_sasl_auth_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-sasl-auth.c \ wocky-test-sasl-handler.c \ wocky-test-sasl-handler.h \ wocky-test-sasl-auth-server.c \ wocky-test-sasl-auth-server.h \ wocky-test-stream.c \ wocky-test-stream.h wocky_test_sasl_auth_LDADD = $(LDADD) @LIBSASL2_LIBS@ wocky_test_sasl_auth_CFLAGS = $(AM_CFLAGS) @LIBSASL2_CFLAGS@ wocky_tls_test_SOURCES = \ wocky-tls-test.c \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h wocky_tls_test_CFLAGS = $(AM_CFLAGS) $(TLSDEFS) wocky_utils_test_SOURCES = wocky-utils-test.c wocky_xmpp_connection_test_SOURCES = \ wocky-xmpp-connection-test.c \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h wocky_xmpp_node_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-xmpp-node-test.c wocky_xmpp_reader_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-xmpp-reader-test.c wocky_xmpp_readwrite_test_SOURCES = \ wocky-test-stream.c wocky-test-stream.h \ wocky-test-helper.c wocky-test-helper.h \ wocky-xmpp-readwrite-test.c AM_CFLAGS = $(ERROR_CFLAGS) $(GCOV_CFLAGS) @GLIB_CFLAGS@ \ @LIBXML2_CFLAGS@ @TLS_CFLAGS@ @WOCKY_CFLAGS@ AM_LDFLAGS = $(GCOV_LIBS) @GLIB_LIBS@ @LIBXML2_LIBS@ @TLS_LIBS@ LDADD = $(top_builddir)/wocky/libwocky.la check_PROGRAMS = $(TEST_PROGS) check_c_sources = $(notdir $(wildcard $(srcdir)/*.c) $(wildcard $(srcdir)/*.h)) noinst_PROGRAMS += $(TEST_PROGS) test-report: test-report.xml gtester-report $(top_builddir)/tests/$@.xml > \ $(top_builddir)/tests/$@.html test-report.xml: ${TEST_PROGS} test test: ${TEST_PROGS} gtester -o test-report.xml -k --verbose ${TEST_PROGS} @if [ -x $(which python) ] ; then \ $(SUMMARY) $@-report.xml ; \ else \ echo "No python available, not summarizing test results" ; \ fi test-%: wocky-%-test gtester -o $@-report.xml -k --verbose $< @if [ -x $(which python) ] ; then \ $(SUMMARY) $@-report.xml ; \ else \ echo "No python available, not summarizing test results" ; \ fi .PHONY: test test-report include $(top_srcdir)/tools/check-coding-style.mk check-local: test check-coding-style ############################################################################ SUPPRESSIONS = \ threadlocal.supp \ gabble.supp \ tp-glib.supp CLEANFILES = test-report.xml \ sasl-test.db # valgrind any given test by running make test.valgrind %.valgrind: % G_SLICE=always-malloc \ G_DEBUG=gc-friendly \ valgrind -q \ $(foreach s,$(SUPPRESSIONS),--suppressions=$(srcdir)/$(s)) \ --tool=memcheck --leak-check=full --trace-children=yes \ --leak-resolution=high --num-callers=20 \ ./$* $(TEST_ARGS) 2>&1 | tee "valgrind.$*.log" @if grep "==" "valgrind.$*.log" > /dev/null 2>&1; then \ exit 1; \ fi valgrind: $(TEST_PROGS) @echo "Valgrinding tests ..." @failed=0; \ for t in $(filter-out $(VALGRIND_TESTS_DISABLE),$(TEST_PROGS)); do \ $(MAKE) $$t.valgrind; \ if test "$$?" -ne 0; then \ echo "Valgrind error for test $$t"; \ failed=`expr $$failed + 1`; \ whicht="$$whicht $$t"; \ fi; \ done; \ if test "$$failed" -ne 0; then \ echo "$$failed tests had leaks or errors under valgrind:"; \ echo "$$whicht"; \ false; \ fi EXTRA_DIST = $(SUPPRESSIONS) \ README \ connector-test-plan.txt \ summarise-tests.py \ wocky-dummy-xmpp-server.c \ $(wildcard $(srcdir)/certs/*.cfg) \ $(wildcard $(srcdir)/certs/*.pem) \ $(wildcard $(srcdir)/certs/cas/*.pem) \ $(wildcard $(srcdir)/certs/cas/*.0) telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-pep-service-test.c0000664000175000017500000001765412005516162026552 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "wocky-test-stream.h" #include "wocky-test-helper.h" #define TEST_NODE1 "http://test.com/node1" #define TEST_NODE2 "http://test.com/node2" /* Test to instantiate a WockyPepService object */ static void test_instantiation (void) { WockyPepService *pep; pep = wocky_pep_service_new ("http://test.com/badger", FALSE); g_assert (pep != NULL); g_object_unref (pep); } /* Test that the 'changed' signal is properly fired */ gboolean event_received; static void test_changed_signal_cb (WockyPepService *pep, WockyBareContact *contact, WockyStanza *stanza, WockyNode *item, test_data_t *test) { const gchar *id = wocky_node_get_attribute ( wocky_stanza_get_top_node (stanza), "id"); g_assert_cmpstr (wocky_bare_contact_get_jid (contact), ==, "alice@example.org"); /* the id happens to hold the number of children; we expect to get the * first one if there is more than one. */ if (wocky_strdiff (id, "0")) { g_assert (item != NULL); g_assert_cmpstr (item->name, ==, "item"); g_assert_cmpstr (wocky_node_get_attribute (item, "id"), ==, "1"); } else { g_assert (item == NULL); } test->outstanding--; g_main_loop_quit (test->loop); event_received = TRUE; } static void send_pep_event (WockyPorter *porter, const gchar *node, guint n_items) { WockyStanza *stanza; WockyNode *items; gchar *n_items_str = g_strdup_printf ("%d", n_items); guint i; stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, "alice@example.org", NULL, /* This is a hint for test_changed_signal_cb. */ '@', "id", n_items_str, '(', "event", ':', WOCKY_XMPP_NS_PUBSUB_EVENT, '(', "items", '@', "node", node, '*', &items, ')', ')', NULL); for (i = 1; i <= n_items; i++) { gchar *i_str = g_strdup_printf ("%d", i); wocky_node_add_build (items, '(', "item", '@', "id", i_str, '(', "payload", ')', ')', NULL); g_free (i_str); } wocky_porter_send (porter, stanza); g_object_unref (stanza); g_free (n_items_str); } static void test_changed_signal (void) { test_data_t *test = setup_test (); WockyPepService *pep; pep = wocky_pep_service_new (TEST_NODE1, FALSE); test_open_both_connections (test); g_signal_connect (pep, "changed", G_CALLBACK (test_changed_signal_cb), test); wocky_pep_service_start (pep, test->session_out); wocky_porter_start (test->sched_out); wocky_porter_start (test->sched_in); /* send events on the right node */ event_received = FALSE; send_pep_event (test->sched_in, TEST_NODE1, 0); send_pep_event (test->sched_in, TEST_NODE1, 1); send_pep_event (test->sched_in, TEST_NODE1, 2); test->outstanding += 3; test_wait_pending (test); g_assert (event_received); event_received = FALSE; /* send event on the wrong node */ send_pep_event (test->sched_in, TEST_NODE2, 1); g_object_unref (pep); /* send event to the right node after the PEP service has been destroyed */ send_pep_event (test->sched_in, TEST_NODE1, 1); test_close_both_porters (test); teardown_test (test); g_assert (!event_received); } /* Test wocky_pep_service_get_async */ static void test_send_query_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; WockyNode *item; WockyStanzaType type; WockyStanzaSubType sub_type; reply = wocky_pep_service_get_finish (WOCKY_PEP_SERVICE (source_object), res, &item, NULL); g_assert (reply != NULL); wocky_stanza_get_type_info (reply, &type, &sub_type); g_assert (type == WOCKY_STANZA_TYPE_IQ); g_assert (sub_type == WOCKY_STANZA_SUB_TYPE_RESULT); g_assert (item != NULL); g_assert_cmpstr (item->name, ==, "item"); g_assert_cmpstr (wocky_node_get_attribute (item, "id"), ==, "1"); g_object_unref (reply); test->outstanding--; g_main_loop_quit (test->loop); } static gboolean test_send_query_stanza_received_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; reply = wocky_stanza_build_iq_result (stanza, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB, '(', "items", '@', "node", "node1", '(', "item", '@', "id", "1", '(', "payload", ')', ')', ')', ')', NULL); wocky_porter_send (porter, reply); g_object_unref (reply); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void test_send_query_failed_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; GError *error = NULL; reply = wocky_pep_service_get_finish (WOCKY_PEP_SERVICE (source_object), res, NULL, &error); g_assert (reply == NULL); g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_CLOSED); g_clear_error (&error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_get (void) { test_data_t *test = setup_test (); WockyPepService *pep; WockyContactFactory *contact_factory; WockyBareContact *contact; guint handler_id; pep = wocky_pep_service_new (TEST_NODE1, FALSE); test_open_both_connections (test); wocky_pep_service_start (pep, test->session_in); wocky_porter_start (test->sched_out); wocky_porter_start (test->sched_in); handler_id = wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, test_send_query_stanza_received_cb, test, NULL); contact_factory = wocky_session_get_contact_factory (test->session_in); contact = wocky_contact_factory_ensure_bare_contact (contact_factory, "juliet@example.org"); wocky_pep_service_get_async (pep, contact, NULL, test_send_query_cb, test); test->outstanding += 2; test_wait_pending (test); /* Regression test for a bug where wocky_pep_service_get_async's callback * would crash if sending the IQ failed. */ wocky_porter_unregister_handler (test->sched_out, handler_id); wocky_pep_service_get_async (pep, contact, NULL, test_send_query_failed_cb, test); test->outstanding += 1; test_close_both_porters (test); g_object_unref (contact); g_object_unref (pep); teardown_test (test); } /* Test wocky_pep_service_make_publish_stanza */ static void test_make_publish_stanza (void) { WockyPepService *pep; WockyStanza *stanza; WockyNode *item = NULL, *n; WockyStanzaType type; WockyStanzaSubType sub_type; pep = wocky_pep_service_new (TEST_NODE1, FALSE); stanza = wocky_pep_service_make_publish_stanza (pep, &item); g_assert (stanza != NULL); wocky_stanza_get_type_info (stanza, &type, &sub_type); g_assert (type == WOCKY_STANZA_TYPE_IQ); g_assert (sub_type == WOCKY_STANZA_SUB_TYPE_SET); n = wocky_node_get_child_ns (wocky_stanza_get_top_node (stanza), "pubsub", WOCKY_XMPP_NS_PUBSUB); g_assert (n != NULL); n = wocky_node_get_child (n, "publish"); g_assert (n != NULL); g_assert (!wocky_strdiff (wocky_node_get_attribute (n, "node"), TEST_NODE1)); n = wocky_node_get_child (n, "item"); g_assert (n != NULL); g_assert (n == item); g_object_unref (stanza); g_object_unref (pep); } int main (int argc, char **argv) { int result; test_init (argc, argv); g_test_add_func ("/pep-service/instantiation", test_instantiation); g_test_add_func ("/pep-service/changed-signal", test_changed_signal); g_test_add_func ("/pep-service/get", test_get); g_test_add_func ("/pep-service/make-publish-stanza", test_make_publish_stanza); result = g_test_run (); test_deinit (); return result; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-test-sasl-auth-server.c0000664000175000017500000007251112332440453027530 0ustar00cassidycassidy00000000000000/* * wocky-test-sasl-auth-server.c - Source for TestSaslAuthServer * Copyright (C) 2006 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "wocky-test-sasl-auth-server.h" #include "wocky-test-helper.h" #ifdef HAVE_LIBSASL2 #include #include #define CHECK_SASL_RETURN(x) \ G_STMT_START { \ if (x < SASL_OK) { \ fprintf (stderr, "sasl error (%d): %s\n", \ ret, sasl_errdetail (priv->sasl_conn)); \ g_assert_not_reached (); \ } \ } G_STMT_END /* Apparently, we're allowed to typedef the same thing *again* if it's * the same signature, so this allows for backwards compatiblity with * older libsasl2s and also works with newer ones too. This'll only * break if libsasl2 change the type of sasl_callback_ft. I sure hope * they don't! */ typedef int (*sasl_callback_ft)(void); #else #define SASL_OK 0 #define SASL_BADAUTH -13 #define SASL_NOUSER -20 #define CHECK_SASL_RETURN(x) \ G_STMT_START { \ if (x < SASL_OK) { \ fprintf (stderr, "sasl error (%d): ???\n", ret); \ g_assert_not_reached (); \ } \ } G_STMT_END #endif G_DEFINE_TYPE(TestSaslAuthServer, test_sasl_auth_server, G_TYPE_OBJECT) #if 0 /* signal enum */ enum { LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; #endif typedef enum { AUTH_STATE_STARTED, AUTH_STATE_CHALLENGE, AUTH_STATE_FINAL_CHALLENGE, AUTH_STATE_AUTHENTICATED, } AuthState; /* private structure */ struct _TestSaslAuthServerPrivate { gboolean dispose_has_run; WockyXmppConnection *conn; GIOStream *stream; #ifdef HAVE_LIBSASL2 sasl_conn_t *sasl_conn; #endif gchar *username; gchar *password; gchar *mech; gchar *selected_mech; AuthState state; ServerProblem problem; GSimpleAsyncResult *result; GCancellable *cancellable; }; static void received_stanza (GObject *source, GAsyncResult *result, gpointer user_data); static void test_sasl_auth_server_init (TestSaslAuthServer *self) { TestSaslAuthServerPrivate *priv; self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TEST_TYPE_SASL_AUTH_SERVER, TestSaslAuthServerPrivate); priv = self->priv; priv->username = NULL; priv->password = NULL; priv->mech = NULL; priv->state = AUTH_STATE_STARTED; } static void test_sasl_auth_server_dispose (GObject *object); static void test_sasl_auth_server_finalize (GObject *object); static void test_sasl_auth_server_class_init ( TestSaslAuthServerClass *test_sasl_auth_server_class) { GObjectClass *object_class = G_OBJECT_CLASS (test_sasl_auth_server_class); g_type_class_add_private (test_sasl_auth_server_class, sizeof (TestSaslAuthServerPrivate)); object_class->dispose = test_sasl_auth_server_dispose; object_class->finalize = test_sasl_auth_server_finalize; } void test_sasl_auth_server_dispose (GObject *object) { TestSaslAuthServer *self = TEST_SASL_AUTH_SERVER (object); TestSaslAuthServerPrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; /* release any references held by the object here */ if (priv->conn != NULL) g_object_unref (priv->conn); priv->conn = NULL; if (priv->stream != NULL) g_object_unref (priv->stream); priv->stream = NULL; #ifdef HAVE_LIBSASL2 if (&priv->sasl_conn != NULL) sasl_dispose (&priv->sasl_conn); priv->sasl_conn = NULL; #endif g_warn_if_fail (priv->result == NULL); g_warn_if_fail (priv->cancellable == NULL); if (G_OBJECT_CLASS (test_sasl_auth_server_parent_class)->dispose) G_OBJECT_CLASS (test_sasl_auth_server_parent_class)->dispose (object); } void test_sasl_auth_server_finalize (GObject *object) { TestSaslAuthServer *self = TEST_SASL_AUTH_SERVER (object); TestSaslAuthServerPrivate *priv = self->priv; /* free any data held directly by the object here */ g_free (priv->username); g_free (priv->password); g_free (priv->mech); g_free (priv->selected_mech); G_OBJECT_CLASS (test_sasl_auth_server_parent_class)->finalize (object); } static void features_sent (GObject *source, GAsyncResult *res, gpointer user_data) { TestSaslAuthServer *self = TEST_SASL_AUTH_SERVER (user_data); TestSaslAuthServerPrivate *priv = self->priv; g_assert (wocky_xmpp_connection_send_stanza_finish ( WOCKY_XMPP_CONNECTION (source), res, NULL)); wocky_xmpp_connection_recv_stanza_async (WOCKY_XMPP_CONNECTION (source), priv->cancellable, received_stanza, user_data); } static void stream_open_sent (GObject *source, GAsyncResult *res, gpointer user_data) { TestSaslAuthServer *self = TEST_SASL_AUTH_SERVER(user_data); TestSaslAuthServerPrivate * priv = self->priv; WockyStanza *stanza; g_assert (wocky_xmpp_connection_send_open_finish ( WOCKY_XMPP_CONNECTION (source), res, NULL)); /* Send stream features */ stanza = wocky_stanza_new ("features", WOCKY_XMPP_NS_STREAM); test_sasl_auth_server_set_mechs (G_OBJECT (self), stanza); wocky_xmpp_connection_send_stanza_async (priv->conn, stanza, priv->cancellable, features_sent, user_data); g_object_unref (stanza); } static void stream_open_received (GObject *source, GAsyncResult *res, gpointer user_data) { TestSaslAuthServer *self = TEST_SASL_AUTH_SERVER(user_data); TestSaslAuthServerPrivate * priv = self->priv; g_assert (wocky_xmpp_connection_recv_open_finish ( WOCKY_XMPP_CONNECTION (source), res, NULL, NULL, NULL, NULL, NULL, NULL)); wocky_xmpp_connection_send_open_async (priv->conn, NULL, "testserver", "1.0", NULL, "0-HA2", NULL, stream_open_sent, self); } static void post_auth_close_sent (GObject *source, GAsyncResult *result, gpointer user_data) { g_assert (wocky_xmpp_connection_send_close_finish ( WOCKY_XMPP_CONNECTION (source), result, NULL)); } static void post_auth_recv_stanza (GObject *source, GAsyncResult *result, gpointer user_data) { TestSaslAuthServer *self = TEST_SASL_AUTH_SERVER(user_data); TestSaslAuthServerPrivate * priv = self->priv; WockyStanza *stanza; GError *error = NULL; /* ignore all stanza until close */ stanza = wocky_xmpp_connection_recv_stanza_finish ( WOCKY_XMPP_CONNECTION (source), result, &error); if (stanza != NULL) { g_object_unref (stanza); wocky_xmpp_connection_recv_stanza_async ( WOCKY_XMPP_CONNECTION (source), priv->cancellable, post_auth_recv_stanza, user_data); } else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { GSimpleAsyncResult *r = priv->result; priv->result = NULL; if (priv->cancellable != NULL) g_object_unref (priv->cancellable); priv->cancellable = NULL; g_simple_async_result_set_from_error (r, error); g_simple_async_result_complete (r); g_object_unref (r); g_error_free (error); } else { g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_CLOSED); wocky_xmpp_connection_send_close_async (WOCKY_XMPP_CONNECTION (source), priv->cancellable, post_auth_close_sent, user_data); g_error_free (error); } } static void post_auth_features_sent (GObject *source, GAsyncResult *result, gpointer user_data) { TestSaslAuthServer *self = TEST_SASL_AUTH_SERVER(user_data); TestSaslAuthServerPrivate * priv = self->priv; g_assert (wocky_xmpp_connection_send_stanza_finish ( WOCKY_XMPP_CONNECTION (source), result, NULL)); wocky_xmpp_connection_recv_stanza_async (WOCKY_XMPP_CONNECTION (source), priv->cancellable, post_auth_recv_stanza, user_data); } static void post_auth_open_sent (GObject *source, GAsyncResult *result, gpointer user_data) { TestSaslAuthServer *tsas = TEST_SASL_AUTH_SERVER (user_data); TestSaslAuthServerPrivate *priv = tsas->priv; g_assert (wocky_xmpp_connection_send_open_finish ( WOCKY_XMPP_CONNECTION (source), result, NULL)); /* if our caller wanted control back, hand it back here: */ if (priv->result != NULL) { GSimpleAsyncResult *r = priv->result; priv->result = NULL; if (priv->cancellable != NULL) g_object_unref (priv->cancellable); priv->cancellable = NULL; g_simple_async_result_complete (r); g_object_unref (r); } else { WockyStanza *s = wocky_stanza_new ("features", WOCKY_XMPP_NS_STREAM); wocky_xmpp_connection_send_stanza_async (WOCKY_XMPP_CONNECTION (source), s, NULL, post_auth_features_sent, user_data); g_object_unref (s); } } static void post_auth_open_received (GObject *source, GAsyncResult *result, gpointer user_data) { g_assert (wocky_xmpp_connection_recv_open_finish ( WOCKY_XMPP_CONNECTION (source), result, NULL, NULL, NULL, NULL, NULL, user_data)); wocky_xmpp_connection_send_open_async ( WOCKY_XMPP_CONNECTION (source), NULL, "testserver", "1.0", NULL, "0-HA1", NULL, post_auth_open_sent, user_data); } static void success_sent (GObject *source, GAsyncResult *result, gpointer user_data) { g_assert (wocky_xmpp_connection_send_stanza_finish ( WOCKY_XMPP_CONNECTION (source), result, NULL)); wocky_xmpp_connection_reset (WOCKY_XMPP_CONNECTION (source)); wocky_xmpp_connection_recv_open_async (WOCKY_XMPP_CONNECTION (source), NULL, post_auth_open_received, user_data); } static void auth_succeeded (TestSaslAuthServer *self, const gchar *challenge) { TestSaslAuthServerPrivate *priv = self->priv; WockyStanza *s; g_assert (priv->state < AUTH_STATE_AUTHENTICATED); priv->state = AUTH_STATE_AUTHENTICATED; s = wocky_stanza_new ("success", WOCKY_XMPP_NS_SASL_AUTH); wocky_node_set_content (wocky_stanza_get_top_node (s), challenge); wocky_xmpp_connection_send_stanza_async (priv->conn, s, NULL, success_sent, self); g_object_unref (s); } static void failure_sent (GObject *source, GAsyncResult *result, gpointer user_data) { TestSaslAuthServer *tsas = TEST_SASL_AUTH_SERVER (user_data); TestSaslAuthServerPrivate *priv = tsas->priv; GSimpleAsyncResult *r = priv->result; priv->result = NULL; g_assert (wocky_xmpp_connection_send_stanza_finish ( WOCKY_XMPP_CONNECTION (source), result, NULL)); if (r != NULL) { if (priv->cancellable != NULL) g_object_unref (priv->cancellable); priv->cancellable = NULL; g_simple_async_result_complete (r); g_object_unref (r); } } static void not_authorized (TestSaslAuthServer *self) { TestSaslAuthServerPrivate *priv = self->priv; WockyStanza *s; g_assert (priv->state < AUTH_STATE_AUTHENTICATED); priv->state = AUTH_STATE_AUTHENTICATED; s = wocky_stanza_build (WOCKY_STANZA_TYPE_FAILURE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, '(', "not-authorized", ')', NULL); wocky_xmpp_connection_send_stanza_async (priv->conn, s, NULL, failure_sent, self); g_object_unref (s); } /* check if the return of the sasl function was as expected, if not FALSE is * returned and the call function should stop processing */ static gboolean check_sasl_return (TestSaslAuthServer *self, int ret) { TestSaslAuthServerPrivate * priv = self->priv; switch (ret) { case SASL_BADAUTH: /* Bad password provided */ g_assert (priv->problem == SERVER_PROBLEM_INVALID_PASSWORD); not_authorized (self); return FALSE; case SASL_NOUSER: /* Unknown user */ g_assert (priv->problem == SERVER_PROBLEM_INVALID_USERNAME); not_authorized (self); return FALSE; default: /* sasl auth should be ok */ CHECK_SASL_RETURN (ret); break; } return TRUE; } enum { BEFORE_KEY, INSIDE_KEY, AFTER_KEY, AFTER_EQ, INSIDE_VALUE, AFTER_VALUE, }; /* insert space, CRLF, TAB etc at strategic locations in the challenge * * to make sure our challenge parser is sufficently robust */ static gchar * space_challenge (const gchar *challenge, unsigned *len) { GString *spaced = g_string_new_len (challenge, (gssize) *len); gchar *c = spaced->str; gchar q = '\0'; gsize pos; gulong state = BEFORE_KEY; gchar spc[] = { ' ', '\t', '\r', '\n' }; for (pos = 0; pos < spaced->len; pos++) { c = spaced->str + pos; switch (state) { case BEFORE_KEY: if (!g_ascii_isspace (*c) && *c != '\0' && *c != '=') state = INSIDE_KEY; break; case INSIDE_KEY: if (*c != '=') break; g_string_insert_c (spaced, pos++, spc [rand () % sizeof (spc)]); state = AFTER_EQ; break; case AFTER_KEY: if (*c != '=') break; state = AFTER_EQ; break; case AFTER_EQ: if (g_ascii_isspace (*c)) break; q = *c; g_string_insert_c (spaced, pos++, spc [rand () % sizeof (spc)]); state = INSIDE_VALUE; break; case INSIDE_VALUE: if (q == '"' && *c != '"') break; if (q != '"' && !g_ascii_isspace (*c) && *c != ',') break; if (q != '"') { g_string_insert_c (spaced, pos++, spc [rand () % sizeof (spc)]); g_string_insert_c (spaced, ++pos, spc [rand () % sizeof (spc)]); } state = AFTER_VALUE; break; case AFTER_VALUE: if (*c == ',') { g_string_insert_c (spaced, pos++, spc [rand () % sizeof (spc)]); g_string_insert_c (spaced, ++pos, spc [rand () % sizeof (spc)]); } state = BEFORE_KEY; break; default: g_assert_not_reached (); } } *len = spaced->len; return g_string_free (spaced, FALSE); } /* insert a bogus parameter with a \" and a \\ sequence in it * scatter some \ characters through the " quoted challenge values */ static gchar * slash_challenge (const gchar *challenge, unsigned *len) { GString *slashed = g_string_new_len (challenge, (gssize) *len); gchar *c = slashed->str; gchar q = '\0'; gsize pos; gulong state = BEFORE_KEY; for (pos = 0; pos < slashed->len; pos++) { c = slashed->str + pos; switch (state) { case BEFORE_KEY: if (!g_ascii_isspace (*c) && *c != '\0' && *c != '=') state = INSIDE_KEY; break; case INSIDE_KEY: if (*c != '=') break; state = AFTER_EQ; break; case AFTER_EQ: if (g_ascii_isspace (*c)) break; q = *c; state = INSIDE_VALUE; break; case INSIDE_VALUE: if (q == '"' && *c != '"') { if ((rand () % 3) == 0) g_string_insert_c (slashed, pos++, '\\'); break; } if (q != '"' && !g_ascii_isspace (*c) && *c != ',') break; state = AFTER_VALUE; break; case AFTER_VALUE: state = BEFORE_KEY; break; default: g_assert_not_reached (); } } g_string_prepend (slashed, "ignore-me = \"(a slash \\\\ a quote \\\")\", "); *len = slashed->len; return g_string_free (slashed, FALSE); } static void handle_auth (TestSaslAuthServer *self, WockyStanza *stanza) { TestSaslAuthServerPrivate *priv = self->priv; guchar *response = NULL; const gchar *challenge; unsigned challenge_len; gsize response_len = 0; int ret; WockyNode *auth = wocky_stanza_get_top_node (stanza); const gchar *gjdd = NULL; g_free (priv->selected_mech); priv->selected_mech = g_strdup (wocky_node_get_attribute ( wocky_stanza_get_top_node (stanza), "mechanism")); if (wocky_stanza_get_top_node (stanza)->content != NULL) { response = g_base64_decode (wocky_stanza_get_top_node (stanza)->content, &response_len); } g_assert (priv->state == AUTH_STATE_STARTED); gjdd = wocky_node_get_attribute_ns (auth, "client-uses-full-bind-result", WOCKY_GOOGLE_NS_AUTH); switch (priv->problem) { case SERVER_PROBLEM_REQUIRE_GOOGLE_JDD: if ((gjdd == NULL) || wocky_strdiff ("true", gjdd)) { not_authorized (self); goto out; } break; case SERVER_PROBLEM_DISLIKE_GOOGLE_JDD: if (gjdd && !wocky_strdiff ("true", gjdd)) { not_authorized (self); goto out; } break; default: break; } priv->state = AUTH_STATE_CHALLENGE; if (!wocky_strdiff ("X-TEST", priv->selected_mech)) { challenge = ""; challenge_len = 0; ret = wocky_strdiff ((gchar *) response, priv->password) ? SASL_BADAUTH : SASL_OK; } else { #if HAVE_LIBSASL2 ret = sasl_server_start (priv->sasl_conn, priv->selected_mech, (gchar *) response, (unsigned) response_len, &challenge, &challenge_len); #else challenge = ""; challenge_len = 0; g_assert (!wocky_strdiff ("PLAIN", priv->selected_mech)); /* response format: ^@ u s e r ^@ p a s s */ /* require at least 1 char user and password */ if (response_len >= 4) { const gchar *user = ((gchar *) response) + 1; int ulen = strlen (user); gchar *pass = g_strndup (user + ulen + 1, response_len - ulen - 2); ret = ( wocky_strdiff (user, priv->username) ? SASL_NOUSER : wocky_strdiff (pass, priv->password) ? SASL_BADAUTH : SASL_OK ); g_free (pass); } else ret = SASL_BADAUTH; #endif } if (!check_sasl_return (self, ret)) goto out; if (challenge_len > 0) { WockyStanza *c; gchar *challenge64; if (ret == SASL_OK) { priv->state = AUTH_STATE_FINAL_CHALLENGE; } if (priv->problem == SERVER_PROBLEM_SPACE_CHALLENGE) { unsigned slen = challenge_len; gchar *spaced = space_challenge (challenge, &slen); challenge64 = g_base64_encode ((guchar *) spaced, slen); g_free (spaced); } else if (priv->problem == SERVER_PROBLEM_SLASH_CHALLENGE) { unsigned slen = challenge_len; gchar *slashc = slash_challenge (challenge, &slen); challenge64 = g_base64_encode ((guchar *) slashc, slen); g_free (slashc); } else { challenge64 = g_base64_encode ((guchar *) challenge, challenge_len); } c = wocky_stanza_new ("challenge", WOCKY_XMPP_NS_SASL_AUTH); wocky_node_set_content (wocky_stanza_get_top_node (c), challenge64); wocky_xmpp_connection_send_stanza_async (priv->conn, c, NULL, NULL, NULL); g_object_unref (c); g_free (challenge64); } else if (ret == SASL_OK) { auth_succeeded (self, NULL); } else { g_assert_not_reached (); } out: g_free (response); } static void handle_response (TestSaslAuthServer *self, WockyStanza *stanza) { TestSaslAuthServerPrivate * priv = self->priv; guchar *response = NULL; const gchar *challenge; unsigned challenge_len; gsize response_len = 0; int ret; if (priv->state == AUTH_STATE_FINAL_CHALLENGE) { g_assert (wocky_stanza_get_top_node (stanza)->content == NULL); auth_succeeded (self, NULL); return; } g_assert (priv->state == AUTH_STATE_CHALLENGE); if (wocky_stanza_get_top_node (stanza)->content != NULL) { response = g_base64_decode (wocky_stanza_get_top_node (stanza)->content, &response_len); } #ifdef HAVE_LIBSASL2 ret = sasl_server_step (priv->sasl_conn, (gchar *) response, (unsigned) response_len, &challenge, &challenge_len); #else ret = SASL_OK; challenge_len = 0; challenge = ""; #endif if (!check_sasl_return (self, ret)) goto out; if (challenge_len > 0) { WockyStanza *c; gchar *challenge64; if (ret == SASL_OK) { priv->state = AUTH_STATE_FINAL_CHALLENGE; } if (priv->problem == SERVER_PROBLEM_SPACE_CHALLENGE) { unsigned slen = challenge_len; gchar *spaced = space_challenge (challenge, &slen); challenge64 = g_base64_encode ((guchar *) spaced, slen); g_free (spaced); } else if (priv->problem == SERVER_PROBLEM_SLASH_CHALLENGE) { unsigned slen = challenge_len; gchar *slashc = slash_challenge (challenge, &slen); challenge64 = g_base64_encode ((guchar *) slashc, slen); g_free (slashc); } else { challenge64 = g_base64_encode ((guchar *) challenge, challenge_len); } if (priv->state == AUTH_STATE_FINAL_CHALLENGE && priv->problem == SERVER_PROBLEM_FINAL_DATA_IN_SUCCESS) { auth_succeeded (self, challenge64); } else { c = wocky_stanza_new ("challenge", WOCKY_XMPP_NS_SASL_AUTH); wocky_node_set_content (wocky_stanza_get_top_node (c), challenge64); wocky_xmpp_connection_send_stanza_async (priv->conn, c, NULL, NULL, NULL); g_object_unref (c); } g_free (challenge64); } else if (ret == SASL_OK) { auth_succeeded (self, NULL); } else { g_assert_not_reached (); } out: g_free (response); } #define HANDLE(x) { #x, handle_##x } static void received_stanza (GObject *source, GAsyncResult *result, gpointer user_data) { TestSaslAuthServer *self; TestSaslAuthServerPrivate *priv; int i; WockyStanza *stanza; GError *error = NULL; struct { const gchar *name; void (*func)(TestSaslAuthServer *self, WockyStanza *stanza); } handlers[] = { HANDLE(auth), HANDLE(response) }; stanza = wocky_xmpp_connection_recv_stanza_finish ( WOCKY_XMPP_CONNECTION (source), result, &error); if (stanza == NULL && (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) || g_error_matches (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_EOS))) { g_error_free (error); return; } self = TEST_SASL_AUTH_SERVER (user_data); priv = self->priv; g_assert (stanza != NULL); if (wocky_strdiff (wocky_node_get_ns ( wocky_stanza_get_top_node (stanza)), WOCKY_XMPP_NS_SASL_AUTH)) { g_assert_not_reached (); } for (i = 0 ; handlers[i].name != NULL; i++) { if (!wocky_strdiff (wocky_stanza_get_top_node (stanza)->name, handlers[i].name)) { handlers[i].func (self, stanza); if (priv->state < AUTH_STATE_AUTHENTICATED) { wocky_xmpp_connection_recv_stanza_async (priv->conn, NULL, received_stanza, user_data); } g_object_unref (stanza); return; } } g_assert_not_reached (); } #ifdef HAVE_LIBSASL2 static int test_sasl_server_auth_log (void *context, int level, const gchar *message) { return SASL_OK; } static int test_sasl_server_auth_getopt (void *context, const char *plugin_name, const gchar *option, const gchar **result, guint *len) { int i; static const struct { const gchar *name; const gchar *value; } options[] = { { "auxprop_plugin", "sasldb"}, { "sasldb_path", "./sasl-test.db"}, { NULL, NULL }, }; for (i = 0; options[i].name != NULL; i++) { if (!wocky_strdiff (option, options[i].name)) { *result = options[i].value; if (len != NULL) *len = strlen (options[i].value); } } return SASL_OK; } #endif TestSaslAuthServer * test_sasl_auth_server_new (GIOStream *stream, gchar *mech, const gchar *user, const gchar *password, const gchar *servername, ServerProblem problem, gboolean start) { TestSaslAuthServer *server; TestSaslAuthServerPrivate *priv; #ifdef HAVE_LIBSASL2 static gboolean sasl_initialized = FALSE; int ret; static sasl_callback_t callbacks[] = { { SASL_CB_LOG, (sasl_callback_ft) test_sasl_server_auth_log, NULL }, { SASL_CB_GETOPT, (sasl_callback_ft) test_sasl_server_auth_getopt, NULL }, { SASL_CB_LIST_END, NULL, NULL }, }; if (!sasl_initialized) { sasl_server_init (NULL, NULL); sasl_initialized = TRUE; } #endif server = g_object_new (TEST_TYPE_SASL_AUTH_SERVER, NULL); priv = server->priv; priv->state = AUTH_STATE_STARTED; #ifdef HAVE_LIBSASL2 ret = sasl_server_new ("xmpp", servername, NULL, NULL, NULL, callbacks, SASL_SUCCESS_DATA, &(priv->sasl_conn)); CHECK_SASL_RETURN (ret); ret = sasl_setpass (priv->sasl_conn, user, password, strlen (password), NULL, 0, SASL_SET_CREATE); CHECK_SASL_RETURN (ret); #endif priv->username = g_strdup (user); priv->password = g_strdup (password); priv->mech = g_strdup (mech); priv->problem = problem; if (start) { priv->stream = g_object_ref (stream); priv->conn = wocky_xmpp_connection_new (stream); priv->cancellable = g_cancellable_new (); wocky_xmpp_connection_recv_open_async (priv->conn, priv->cancellable, stream_open_received, server); } return server; } void test_sasl_auth_server_stop (TestSaslAuthServer *self) { TestSaslAuthServerPrivate *priv = self->priv; if (priv->cancellable != NULL) { test_cancel_in_idle (priv->cancellable); g_object_unref (priv->cancellable); priv->cancellable = NULL; } if (priv->conn != NULL) g_object_unref (priv->conn); priv->conn = NULL; } gboolean test_sasl_auth_server_auth_finish (TestSaslAuthServer *self, GAsyncResult *res, GError **error) { gboolean ok = FALSE; TestSaslAuthServerPrivate *priv = self->priv; if (g_simple_async_result_propagate_error ( G_SIMPLE_ASYNC_RESULT (res), error)) return FALSE; ok = g_simple_async_result_is_valid (G_ASYNC_RESULT (res), G_OBJECT (self), test_sasl_auth_server_auth_async); g_return_val_if_fail (ok, FALSE); return (priv->state == AUTH_STATE_AUTHENTICATED); } void test_sasl_auth_server_auth_async (GObject *obj, WockyXmppConnection *conn, WockyStanza *auth, GAsyncReadyCallback cb, GCancellable *cancellable, gpointer data) { TestSaslAuthServer *self = TEST_SASL_AUTH_SERVER (obj); TestSaslAuthServerPrivate *priv = self->priv; /* We expect the server to not be started but just in case */ test_sasl_auth_server_stop (TEST_SASL_AUTH_SERVER (obj)); priv->state = AUTH_STATE_STARTED; priv->conn = g_object_ref (conn); /* save the details of the point ot which we will hand back control */ if (cb != NULL) { if (cancellable != NULL) priv->cancellable = g_object_ref (cancellable); priv->result = g_simple_async_result_new (obj, cb, data, test_sasl_auth_server_auth_async); } handle_auth (self, auth); if (priv->state < AUTH_STATE_AUTHENTICATED) { wocky_xmpp_connection_recv_stanza_async (priv->conn, priv->cancellable, received_stanza, self); } g_object_unref (auth); } gint test_sasl_auth_server_set_mechs (GObject *obj, WockyStanza *feat) { int ret = 0; TestSaslAuthServer *self = TEST_SASL_AUTH_SERVER (obj); TestSaslAuthServerPrivate *priv = self->priv; WockyNode *mechnode = NULL; if (priv->problem != SERVER_PROBLEM_NO_SASL) { mechnode = wocky_node_add_child_ns ( wocky_stanza_get_top_node (feat), "mechanisms", WOCKY_XMPP_NS_SASL_AUTH); if (priv->problem == SERVER_PROBLEM_NO_MECHANISMS) { /* lalala */ } else if (priv->mech != NULL) { wocky_node_add_child_with_content (mechnode, "mechanism", priv->mech); } else { const gchar *mechs; gchar **mechlist; gchar **tmp; #ifdef HAVE_LIBSASL2 ret = sasl_listmech (priv->sasl_conn, NULL, "","\n","", &mechs, NULL,NULL); CHECK_SASL_RETURN (ret); #else mechs = "PLAIN"; #endif mechlist = g_strsplit (mechs, "\n", -1); for (tmp = mechlist; *tmp != NULL; tmp++) { wocky_node_add_child_with_content (mechnode, "mechanism", *tmp); } g_strfreev (mechlist); } } return ret; } const gchar * test_sasl_auth_server_get_selected_mech (TestSaslAuthServer *self) { TestSaslAuthServerPrivate *priv = self->priv; return priv->selected_mech; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-test-connector-server.c0000664000175000017500000014111212212322440027603 0ustar00cassidycassidy00000000000000/* * wocky-test-connector-server.c - Source for TestConnectorServer * Copyright © 2009 Collabora Ltd. * @author Vivek Dasmohapatra * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include #include #include #include #include #include #include "wocky-test-connector-server.h" #include #define INITIAL_STREAM_ID "0-HAI" /* We're being a bit naughty here by including wocky-debug.h, but we're * internal *enough*. */ #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_CONNECTOR #define WOCKY_COMPILATION #include #undef WOCKY_COMPILATION G_DEFINE_TYPE (TestConnectorServer, test_connector_server, G_TYPE_OBJECT); typedef void (*stanza_func)(TestConnectorServer *self, WockyStanza *xml); typedef struct _stanza_handler stanza_handler; struct _stanza_handler { const gchar *ns; const gchar *name; stanza_func func; }; typedef struct _iq_handler iq_handler; struct _iq_handler { WockyStanzaSubType subtype; const gchar *payload; const gchar *ns; stanza_func func; }; static void xmpp_init (GObject *source, GAsyncResult *result, gpointer data); static void starttls (GObject *source, GAsyncResult *result, gpointer data); static void finished (GObject *source, GAsyncResult *, gpointer data); static void quit (GObject *source, GAsyncResult *result, gpointer data); static void server_enc_outstanding (TestConnectorServer *self); static gboolean server_dec_outstanding (TestConnectorServer *self); /* ************************************************************************* */ /* test connector server object definition */ typedef enum { SERVER_STATE_START, SERVER_STATE_CLIENT_OPENED, SERVER_STATE_SERVER_OPENED, SERVER_STATE_FEATURES_SENT } server_state; static struct { CertSet set; const gchar *key; const gchar *crt; } certs[] = { { CERT_STANDARD, TLS_SERVER_KEY_FILE, TLS_SERVER_CRT_FILE }, { CERT_EXPIRED, TLS_EXP_KEY_FILE, TLS_EXP_CRT_FILE }, { CERT_NOT_YET, TLS_NEW_KEY_FILE, TLS_NEW_CRT_FILE }, { CERT_UNKNOWN, TLS_UNKNOWN_KEY_FILE, TLS_UNKNOWN_CRT_FILE }, { CERT_SELFSIGN, TLS_SS_KEY_FILE, TLS_SS_CRT_FILE }, { CERT_REVOKED, TLS_REV_KEY_FILE, TLS_REV_CRT_FILE }, { CERT_WILDCARD, TLS_WILD_KEY_FILE, TLS_WILD_CRT_FILE }, { CERT_BADWILD, TLS_BADWILD_KEY_FILE, TLS_BADWILD_CRT_FILE }, { CERT_NONE, NULL, NULL } }; struct _TestConnectorServerPrivate { gboolean dispose_has_run; WockyXmppConnection *conn; GIOStream *stream; server_state state; gboolean tls_started; gboolean authed; TestSaslAuthServer *sasl; gchar *mech; gchar *user; gchar *pass; gchar *version; gchar *used_mech; CertSet cert; WockyTLSSession *tls_sess; GCancellable *cancellable; gint outstanding; GSimpleAsyncResult *teardown_result; struct { ServerProblem sasl; ConnectorProblem *connector; } problem; gchar *other_host; guint other_port; }; static void test_connector_server_dispose (GObject *object) { TestConnectorServer *self = TEST_CONNECTOR_SERVER (object); TestConnectorServerPrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; /* release any references held by the object here */ if (priv->conn != NULL) g_object_unref (priv->conn); priv->conn = NULL; if (priv->stream != NULL) g_object_unref (priv->stream); priv->stream = NULL; if (priv->sasl != NULL) g_object_unref (priv->sasl); priv->sasl = NULL; if (priv->tls_sess != NULL) g_object_unref (priv->tls_sess); priv->tls_sess = NULL; if (G_OBJECT_CLASS (test_connector_server_parent_class)->dispose) G_OBJECT_CLASS (test_connector_server_parent_class)->dispose (object); } static void test_connector_server_finalise (GObject *object) { TestConnectorServer *self = TEST_CONNECTOR_SERVER (object); TestConnectorServerPrivate *priv = self->priv; /* free any data held directly by the object here */ g_free (priv->mech); g_free (priv->user); g_free (priv->pass); g_free (priv->version); g_free (priv->used_mech); G_OBJECT_CLASS (test_connector_server_parent_class)->finalize (object); } static void test_connector_server_init (TestConnectorServer *self) { TestConnectorServerPrivate *priv; self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TEST_TYPE_CONNECTOR_SERVER, TestConnectorServerPrivate); priv = self->priv; priv->tls_started = FALSE; priv->authed = FALSE; priv->cancellable = g_cancellable_new (); } static void test_connector_server_class_init (TestConnectorServerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (TestConnectorServerPrivate)); object_class->dispose = test_connector_server_dispose; object_class->finalize = test_connector_server_finalise; } /* ************************************************************************* */ /* xmpp stanza handling: */ static void xmpp_handler (GObject *source, GAsyncResult *result, gpointer user_data); static void handle_auth (TestConnectorServer *self, WockyStanza *xml); static void handle_starttls (TestConnectorServer *self, WockyStanza *xml); static void after_auth (GObject *source, GAsyncResult *res, gpointer data); static void xmpp_close (GObject *source, GAsyncResult *result, gpointer data); static void xmpp_closed (GObject *source, GAsyncResult *result, gpointer data); static void iq_get_query_JABBER_AUTH (TestConnectorServer *self, WockyStanza *xml); static void iq_set_query_JABBER_AUTH (TestConnectorServer *self, WockyStanza *xml); static void iq_set_bind_XMPP_BIND (TestConnectorServer *self, WockyStanza *xml); static void iq_set_session_XMPP_SESSION (TestConnectorServer *self, WockyStanza *xml); static void iq_get_query_XEP77_REGISTER (TestConnectorServer *self, WockyStanza *xml); static void iq_set_query_XEP77_REGISTER (TestConnectorServer *self, WockyStanza *xml); static void iq_sent (GObject *source, GAsyncResult *result, gpointer data); static void iq_sent_unregistered (GObject *source, GAsyncResult *result, gpointer data); #define HANDLER(ns,x) { WOCKY_XMPP_NS_##ns, #x, handle_##x } static stanza_handler handlers[] = { HANDLER (SASL_AUTH, auth), HANDLER (TLS, starttls), { NULL, NULL, NULL } }; #define IQH(S,s,name,nsp,ns) \ { WOCKY_STANZA_SUB_TYPE_##S, #name, WOCKY_##nsp##_NS_##ns, \ iq_##s##_##name##_##nsp##_##ns } static iq_handler iq_handlers[] = { IQH (SET, set, bind, XMPP, BIND), IQH (SET, set, session, XMPP, SESSION), IQH (GET, get, query, JABBER, AUTH), IQH (SET, set, query, JABBER, AUTH), IQH (GET, get, query, XEP77, REGISTER), IQH (SET, set, query, XEP77, REGISTER), { WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, NULL } }; /* ************************************************************************* */ /* error stanza */ static WockyStanza * error_stanza (const gchar *cond, const gchar *msg, gboolean extended) { WockyStanza *error = wocky_stanza_new ("error", WOCKY_XMPP_NS_STREAM); WockyNode *node = wocky_stanza_get_top_node (error); wocky_node_add_child_ns (node, cond, WOCKY_XMPP_NS_STREAMS); if ((msg != NULL) && (*msg != '\0')) wocky_node_add_child_with_content_ns (node, "text", msg, WOCKY_XMPP_NS_STREAMS); if (extended) wocky_node_add_child_with_content_ns (node, "something", "blah", "urn:ietf:a:namespace:I:made:up"); return error; } /* ************************************************************************* */ static void iq_set_query_XEP77_REGISTER (TestConnectorServer *self, WockyStanza *xml) { TestConnectorServerPrivate *priv = self->priv; WockyXmppConnection *conn = priv->conn; WockyStanza *iq = NULL; WockyNode *env = wocky_stanza_get_top_node (xml); WockyNode *query = wocky_node_get_child (env, "query"); const gchar *id = wocky_node_get_attribute (env, "id"); gpointer cb = iq_sent; DEBUG (""); if (priv->problem.connector->xep77 & XEP77_PROBLEM_ALREADY) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '@', "id", id, '(', "query", ':', WOCKY_XEP77_NS_REGISTER, '(', "registered", ')', '(', "username", '$', "foo", ')', '(', "password", '$', "bar", ')', ')', NULL); } else if (priv->problem.connector->xep77 & XEP77_PROBLEM_FAIL_CONFLICT) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, NULL, NULL, '@', "id", id, '(', "error", '@', "type", "cancel", '(', "conflict", ':', WOCKY_XMPP_NS_STANZAS, ')', ')', NULL); } else if (priv->problem.connector->xep77 & XEP77_PROBLEM_FAIL_REJECTED) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, NULL, NULL, '@', "id", id, '(', "error", '@', "type", "modify", '(', "not-acceptable", ':', WOCKY_XMPP_NS_STANZAS, ')', ')', NULL); } else { if (wocky_node_get_child (query, "remove") == NULL) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '@', "id", id, NULL); } else { XEP77Problem problem = priv->problem.connector->xep77; XEP77Problem p = XEP77_PROBLEM_NONE; DEBUG ("handling CANCEL"); if ((p = problem & XEP77_PROBLEM_CANCEL_REJECTED) || (p = problem & XEP77_PROBLEM_CANCEL_DISABLED) || (p = problem & XEP77_PROBLEM_CANCEL_FAILED)) { const gchar *error = NULL; const gchar *etype = NULL; const gchar *ecode = NULL; switch (p) { case XEP77_PROBLEM_CANCEL_REJECTED: error = "bad-request"; etype = "modify"; ecode = "400"; break; case XEP77_PROBLEM_CANCEL_DISABLED: error = "not-allowed"; etype = "cancel"; ecode = "405"; break; default: error = "forbidden"; etype = "cancel"; ecode = "401"; } DEBUG ("error: %s/%s", error, etype); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, NULL, NULL, '@', "id", id, '(', "error", '@', "type", etype, '@', "code", ecode, '(', error, ':', WOCKY_XMPP_NS_STANZAS, ')', ')', NULL); } else { if (priv->problem.connector->xep77 & XEP77_PROBLEM_CANCEL_STREAM) { iq = error_stanza ("not-authorized", NULL, FALSE); cb = finished; } else { cb = iq_sent_unregistered; iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '@', "id", id, NULL); } } } } server_enc_outstanding (self); wocky_xmpp_connection_send_stanza_async (conn, iq, priv->cancellable, cb, self); g_object_unref (xml); g_object_unref (iq); } static void iq_get_query_XEP77_REGISTER (TestConnectorServer *self, WockyStanza *xml) { TestConnectorServerPrivate *priv = self->priv; WockyXmppConnection *conn = priv->conn; WockyStanza *iq = NULL; WockyNode *env = wocky_stanza_get_top_node (xml); WockyNode *query = NULL; const gchar *id = wocky_node_get_attribute (env, "id"); DEBUG (""); if (priv->problem.connector->xep77 & XEP77_PROBLEM_NOT_AVAILABLE) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, NULL, NULL, '@', "id", id, '(', "error", '@', "type", "cancel", '(', "service-unavailable", ':', WOCKY_XMPP_NS_STANZAS, ')', ')', NULL); } else if (priv->problem.connector->xep77 & XEP77_PROBLEM_QUERY_NONSENSE) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, '@', "id", id, '(', "plankton", ':', WOCKY_XEP77_NS_REGISTER, ')', NULL); } else if (priv->problem.connector->xep77 & XEP77_PROBLEM_QUERY_ALREADY) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '@', "id", id, '(', "query", ':', WOCKY_XEP77_NS_REGISTER, '(', "registered", ')', '(', "username", '$', "foo", ')', '(', "password", '$', "bar", ')', ')', NULL); } else { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '@', "id", id, '(', "query", ':', WOCKY_XEP77_NS_REGISTER, '*', &query, ')', NULL); if (!(priv->problem.connector->xep77 & XEP77_PROBLEM_NO_ARGS)) { wocky_node_add_child (query, "username"); wocky_node_add_child (query, "password"); if (priv->problem.connector->xep77 & XEP77_PROBLEM_EMAIL_ARG) wocky_node_add_child (query, "email"); if (priv->problem.connector->xep77 & XEP77_PROBLEM_STRANGE_ARG) wocky_node_add_child (query, "wildebeest"); } } server_enc_outstanding (self); wocky_xmpp_connection_send_stanza_async (conn, iq, NULL, iq_sent, self); g_object_unref (xml); g_object_unref (iq); } static void iq_get_query_JABBER_AUTH (TestConnectorServer *self, WockyStanza *xml) { TestConnectorServerPrivate *priv = self->priv; WockyXmppConnection *conn = priv->conn; WockyStanza *iq = NULL; WockyNode *env = wocky_stanza_get_top_node (xml); const gchar *id = wocky_node_get_attribute (env, "id"); WockyNode *query = wocky_node_get_child (env, "query"); WockyNode *user = (query != NULL) ? wocky_node_get_child (query, "username") : NULL; const gchar *name = (user != NULL) ? user->content : NULL; DEBUG (""); if (priv->problem.connector->jabber & JABBER_PROBLEM_AUTH_NIH) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, NULL, NULL, '@', "id", id, '(', "error", '@', "type", "cancel", '(', "service-unavailable", ':', WOCKY_XMPP_NS_STANZAS, ')', ')', NULL); } else if (name == NULL || *name == '\0') { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, NULL, NULL, '@', "id", id, '(', "error", '@', "type", "modify", '(', "not-acceptable", ':', WOCKY_XMPP_NS_STANZAS, ')', '(', "text", ':', WOCKY_XMPP_NS_STANZAS, '$', "You must include the username in the initial IQ get to work " "around a bug in jabberd 1.4. See " "https://bugs.freedesktop.org/show_bug.cgi?id=24013", ')', ')', NULL); } else if (priv->mech != NULL) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '@', "id", id, '(', "query", ':', WOCKY_JABBER_NS_AUTH, '(', "username", ')', '(', priv->mech, ')', '(', "resource", ')', ')', NULL); } else { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '@', "id", id, '(', "query", ':', WOCKY_JABBER_NS_AUTH, '(', "username", ')', '(', "password", ')', '(', "resource", ')', '(', "digest", ')', ')', NULL); } DEBUG ("responding to iq get"); server_enc_outstanding (self); wocky_xmpp_connection_send_stanza_async (conn, iq, priv->cancellable, iq_sent, self); DEBUG ("sent iq get response"); g_object_unref (xml); g_object_unref (iq); } static void iq_set_query_JABBER_AUTH (TestConnectorServer *self, WockyStanza *xml) { TestConnectorServerPrivate *priv = self->priv; WockyXmppConnection *conn = priv->conn; WockyStanza *iq = NULL; WockyNode *env = wocky_stanza_get_top_node (xml); WockyNode *qry = wocky_node_get_child (env, "query"); JabberProblem problems = priv->problem.connector->jabber; JabberProblem jp = JABBER_PROBLEM_NONE; WockyNode *username = wocky_node_get_child (qry, "username"); WockyNode *password = wocky_node_get_child (qry, "password"); WockyNode *resource = wocky_node_get_child (qry, "resource"); WockyNode *sha1hash = wocky_node_get_child (qry, "digest"); const gchar *id = wocky_node_get_attribute (env, "id"); DEBUG (""); if (username == NULL || resource == NULL) problems |= JABBER_PROBLEM_AUTH_PARTIAL; else if (password != NULL) { if (wocky_strdiff (priv->user, username->content) || wocky_strdiff (priv->pass, password->content)) problems |= JABBER_PROBLEM_AUTH_REJECT; } else if (sha1hash != NULL) { gchar *hsrc = g_strconcat (INITIAL_STREAM_ID, priv->pass, NULL); gchar *sha1 = g_compute_checksum_for_string (G_CHECKSUM_SHA1, hsrc, -1); DEBUG ("checksum: %s vs %s", sha1, sha1hash->content); if (wocky_strdiff (priv->user, username->content) || wocky_strdiff (sha1, sha1hash->content)) problems |= JABBER_PROBLEM_AUTH_REJECT; g_free (hsrc); g_free (sha1); } else problems |= JABBER_PROBLEM_AUTH_PARTIAL; if ((jp = problems & JABBER_PROBLEM_AUTH_REJECT) || (jp = problems & JABBER_PROBLEM_AUTH_BIND) || (jp = problems & JABBER_PROBLEM_AUTH_PARTIAL) || (jp = problems & JABBER_PROBLEM_AUTH_FAILED)) { const gchar *error = NULL; const gchar *etype = NULL; const gchar *ecode = NULL; switch (jp) { case JABBER_PROBLEM_AUTH_REJECT: error = "not-authorized"; etype = "auth"; ecode = "401"; break; case JABBER_PROBLEM_AUTH_BIND: error = "conflict"; etype = "cancel"; ecode = "409"; break; case JABBER_PROBLEM_AUTH_PARTIAL: error = "not-acceptable"; etype = "modify"; ecode = "406"; break; default: error = "bad-request"; etype = "modify"; ecode = "500"; break; } DEBUG ("error: %s/%s", error, etype); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, NULL, NULL, '@', "id", id, '(', "error", '@', "type", etype, '@', "code", ecode, '(', error, ':', WOCKY_XMPP_NS_STANZAS, ')', ')', NULL); } else if (problems & JABBER_PROBLEM_AUTH_STRANGE) { DEBUG ("auth WEIRD"); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL, '@', "id", id, '(', "surstromming", ':', WOCKY_XMPP_NS_BIND, ')', NULL); } else if (problems & JABBER_PROBLEM_AUTH_NONSENSE) { DEBUG ("auth NONSENSE"); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, '@', "id", id, '(', "surstromming", ':', WOCKY_XMPP_NS_BIND, ')', NULL); } else { DEBUG ("auth OK"); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '@', "id", id, NULL); } server_enc_outstanding (self); wocky_xmpp_connection_send_stanza_async (conn, iq, priv->cancellable, iq_sent, self); g_object_unref (iq); g_object_unref (xml); } static void iq_set_bind_XMPP_BIND (TestConnectorServer *self, WockyStanza *xml) { TestConnectorServerPrivate *priv = self->priv; WockyXmppConnection *conn = priv->conn; WockyStanza *iq = NULL; BindProblem problems = priv->problem.connector->bind; BindProblem bp = BIND_PROBLEM_NONE; DEBUG(""); if ((bp = problems & BIND_PROBLEM_INVALID) || (bp = problems & BIND_PROBLEM_DENIED) || (bp = problems & BIND_PROBLEM_CONFLICT) || (bp = problems & BIND_PROBLEM_REJECTED)) { const gchar *error = NULL; const gchar *etype = NULL; switch (bp) { case BIND_PROBLEM_INVALID: error = "bad-request"; etype = "modify"; break; case BIND_PROBLEM_DENIED: error = "not-allowed"; etype = "cancel"; break; case BIND_PROBLEM_CONFLICT: error = "conflict"; etype = "cancel"; break; default: error = "badger-badger-badger-mushroom"; etype = "moomins"; } iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, NULL, NULL, '(', "bind", ':', WOCKY_XMPP_NS_BIND, ')', '(', "error", '@', "type", etype, '(', error, ':', WOCKY_XMPP_NS_STANZAS, ')', ')', NULL); } else if (problems & BIND_PROBLEM_FAILED) { /* deliberately nonsensical response */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL, '(', "bind", ':', WOCKY_XMPP_NS_BIND, ')', NULL); } else if (problems & BIND_PROBLEM_NONSENSE) { /* deliberately nonsensical response */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, '(', "bind", ':', WOCKY_XMPP_NS_BIND, ')', NULL); } else if (problems & BIND_PROBLEM_CLASH) { iq = error_stanza ("conflict", NULL, FALSE); } else { WockyNode *ciq = wocky_stanza_get_top_node (xml); WockyNode *bind = wocky_node_get_child_ns (ciq, "bind", WOCKY_XMPP_NS_BIND); WockyNode *res = wocky_node_get_child (bind, "resource"); const gchar *uniq = NULL; gchar *jid = NULL; if (res != NULL) uniq = res->content; if (uniq == NULL) uniq = "a-made-up-resource"; if (problems & BIND_PROBLEM_NO_JID) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '(', "bind", ':', WOCKY_XMPP_NS_BIND, ')', NULL); } else { jid = g_strdup_printf ("user@some.doma.in/%s", uniq); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '(', "bind", ':', WOCKY_XMPP_NS_BIND, '(', "jid", '$', jid, ')', ')', NULL); g_free (jid); } } server_enc_outstanding (self); wocky_xmpp_connection_send_stanza_async (conn, iq, priv->cancellable, iq_sent, self); g_object_unref (xml); g_object_unref (iq); } static void iq_set_session_XMPP_SESSION (TestConnectorServer *self, WockyStanza *xml) { TestConnectorServerPrivate *priv = self->priv; WockyXmppConnection *conn = priv->conn; WockyStanza *iq = NULL; SessionProblem problems = priv->problem.connector->session; SessionProblem sp = SESSION_PROBLEM_NONE; DEBUG (""); if ((sp = problems & SESSION_PROBLEM_FAILED) || (sp = problems & SESSION_PROBLEM_DENIED) || (sp = problems & SESSION_PROBLEM_CONFLICT) || (sp = problems & SESSION_PROBLEM_REJECTED)) { const gchar *error = NULL; const gchar *etype = NULL; switch (sp) { case SESSION_PROBLEM_FAILED: error = "internal-server-error"; etype = "wait"; break; case SESSION_PROBLEM_DENIED: error = "forbidden"; etype = "auth"; break; case SESSION_PROBLEM_CONFLICT: error = "conflict"; etype = "cancel"; break; default: error = "snaaaaake"; etype = "mushroom"; break; } iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, NULL, NULL, '(', "session", ':', WOCKY_XMPP_NS_SESSION, ')', '(', "error", '@', "type", etype, '(', error, ':', WOCKY_XMPP_NS_STANZAS, ')', ')', NULL); } else if (problems & SESSION_PROBLEM_NO_SESSION) { iq = error_stanza ("resource-constraint", "Out of Cheese Error", FALSE); } else if (problems & SESSION_PROBLEM_NONSENSE) { /* deliberately nonsensical response */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, '(', "surstromming", ':', WOCKY_XMPP_NS_BIND, ')', NULL); } else { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '(', "session", ':', WOCKY_XMPP_NS_SESSION, ')', NULL); } server_enc_outstanding (self); wocky_xmpp_connection_send_stanza_async (conn, iq, NULL, iq_sent, self); g_object_unref (xml); g_object_unref (iq); } static void iq_sent_unregistered (GObject *source, GAsyncResult *result, gpointer data) { GError *error = NULL; TestConnectorServer *self = TEST_CONNECTOR_SERVER (data); TestConnectorServerPrivate *priv = self->priv; WockyXmppConnection *conn = priv->conn; WockyStanza *es = NULL; DEBUG(""); if (!wocky_xmpp_connection_send_stanza_finish (conn, result, &error)) { DEBUG ("send iq response failed: %s", error->message); g_error_free (error); server_dec_outstanding (self); return; } if (server_dec_outstanding (self)) return; es = error_stanza ("not-authorized", NULL, FALSE); server_enc_outstanding (self); wocky_xmpp_connection_send_stanza_async (conn, es, priv->cancellable, finished, self); g_object_unref (es); } static void iq_sent (GObject *source, GAsyncResult *result, gpointer data) { GError *error = NULL; TestConnectorServer *self = TEST_CONNECTOR_SERVER (data); TestConnectorServerPrivate *priv = self->priv; WockyXmppConnection *conn = priv->conn; DEBUG(""); if (!wocky_xmpp_connection_send_stanza_finish (conn, result, &error)) { DEBUG ("send iq response failed: %s", error->message); g_error_free (error); server_dec_outstanding (self); return; } if (server_dec_outstanding (self)) return; server_enc_outstanding (self); DEBUG ("waiting for next stanza from client"); wocky_xmpp_connection_recv_stanza_async (conn, priv->cancellable, xmpp_handler, data); } static void handle_auth (TestConnectorServer *self, WockyStanza *xml) { TestConnectorServerPrivate *priv = self->priv; GObject *sasl = G_OBJECT (priv->sasl); DEBUG (""); /* after this the sasl auth server object is in charge: control should return to us after the auth stages, at the point when we need to send our final feature stanza: the stream does not return to us */ /* this will also unref *xml when it has finished with it */ server_enc_outstanding (self); test_sasl_auth_server_auth_async (sasl, priv->conn, xml, after_auth, priv->cancellable, self); } static void handle_starttls (TestConnectorServer *self, WockyStanza *xml) { TestConnectorServerPrivate *priv = self->priv; DEBUG (""); if (!priv->tls_started) { WockyXmppConnection *conn = priv->conn; ConnectorProblem *problem = priv->problem.connector; WockyStanza *reply = NULL; GAsyncReadyCallback cb = finished; if (problem->xmpp & XMPP_PROBLEM_TLS_LOAD) { reply = error_stanza ("resource-constraint", "Load Too High", FALSE); } else if (problem->xmpp & XMPP_PROBLEM_TLS_REFUSED) { reply = wocky_stanza_new ("failure", WOCKY_XMPP_NS_TLS); } else { reply = wocky_stanza_new ("proceed", WOCKY_XMPP_NS_TLS); cb = starttls; /* set up the tls server session */ /* gnutls_global_set_log_function ((gnutls_log_func)debug_gnutls); * gnutls_global_set_log_level (10); */ if (problem->death & SERVER_DEATH_TLS_NEG) priv->tls_sess = wocky_tls_session_server_new (priv->stream, 1024, NULL, NULL); else { int x; const gchar *key = TLS_SERVER_KEY_FILE; const gchar *crt = TLS_SERVER_CRT_FILE; for (x = 0; certs[x].set != CERT_NONE; x++) { if (certs[x].set == priv->cert) { key = certs[x].key; crt = certs[x].crt; break; } } DEBUG ("cert file: %s", crt); priv->tls_sess = wocky_tls_session_server_new (priv->stream, 1024, key, crt); } } server_enc_outstanding (self); wocky_xmpp_connection_send_stanza_async (conn, reply, NULL, cb, self); g_object_unref (reply); } g_object_unref (xml); } static void finished (GObject *source, GAsyncResult *result, gpointer data) { TestConnectorServer *self = TEST_CONNECTOR_SERVER (data); TestConnectorServerPrivate *priv = self->priv; DEBUG (""); if (server_dec_outstanding (self)) return; server_enc_outstanding (self); wocky_xmpp_connection_send_close_async (priv->conn, priv->cancellable, quit, data); } static void quit (GObject *source, GAsyncResult *result, gpointer data) { TestConnectorServer *self = TEST_CONNECTOR_SERVER (data); TestConnectorServerPrivate *priv = self->priv; DEBUG (""); wocky_xmpp_connection_send_close_finish (priv->conn, result, NULL); server_dec_outstanding (self); } static void handshake_cb (GObject *source, GAsyncResult *result, gpointer user_data) { TestConnectorServer *self = TEST_CONNECTOR_SERVER (user_data); TestConnectorServerPrivate *priv = self->priv; WockyTLSConnection *tls_conn; GError *error = NULL; DEBUG ("TLS/SSL handshake finished"); tls_conn = wocky_tls_session_handshake_finish ( WOCKY_TLS_SESSION (source), result, &error); if (server_dec_outstanding (self)) goto out; if (tls_conn == NULL) { DEBUG ("SSL or TLS Server Setup failed: %s", error->message); g_io_stream_close (priv->stream, NULL, NULL); goto out; } if (priv->conn != NULL) g_object_unref (priv->conn); priv->state = SERVER_STATE_START; priv->conn = wocky_xmpp_connection_new (G_IO_STREAM (tls_conn)); g_object_unref (tls_conn); priv->tls_started = TRUE; xmpp_init (NULL,NULL,self); out: if (error != NULL) g_error_free (error); } static void starttls (GObject *source, GAsyncResult *result, gpointer data) { TestConnectorServer *self = TEST_CONNECTOR_SERVER (data); TestConnectorServerPrivate *priv = self->priv; WockyXmppConnection *conn = WOCKY_XMPP_CONNECTION (source); GError *error = NULL; DEBUG (""); if (!wocky_xmpp_connection_send_stanza_finish (conn, result, &error)) { DEBUG ("Sending starttls '' failed: %s", error->message); g_error_free (error); server_dec_outstanding (self); return; } if (server_dec_outstanding (self)) return; server_enc_outstanding (self); wocky_tls_session_handshake_async (priv->tls_sess, G_PRIORITY_DEFAULT, NULL, handshake_cb, self); } static void xmpp_handler (GObject *source, GAsyncResult *result, gpointer user_data) { TestConnectorServer *self; TestConnectorServerPrivate *priv; WockyStanza *xml = NULL; WockyXmppConnection *conn = NULL; const gchar *ns = NULL; const gchar *name = NULL; gboolean handled = FALSE; GError *error = NULL; WockyStanzaType type = WOCKY_STANZA_TYPE_NONE; WockyStanzaSubType subtype = WOCKY_STANZA_SUB_TYPE_NONE; int i; DEBUG (""); self = TEST_CONNECTOR_SERVER (user_data); priv = self->priv; conn = priv->conn; xml = wocky_xmpp_connection_recv_stanza_finish (conn, result, &error); /* A real XMPP server would need to do some error handling here, but if * we got this far, we can just exit: The client (ie the test) will * report any error that actually needs reporting - we don't need to */ if (error != NULL) { if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { g_error_free (error); server_dec_outstanding (self); return; } g_assert_not_reached (); } if (server_dec_outstanding (self)) return; ns = wocky_node_get_ns (wocky_stanza_get_top_node (xml)); name = wocky_stanza_get_top_node (xml)->name; wocky_stanza_get_type_info (xml, &type, &subtype); /* if we find a handler, the handler is responsible for listening for the next stanza and setting up the next callback in the chain: */ if (type == WOCKY_STANZA_TYPE_IQ) for (i = 0; iq_handlers[i].payload != NULL; i++) { iq_handler *iq = &iq_handlers[i]; WockyNode *payload = wocky_node_get_child_ns (wocky_stanza_get_top_node (xml), iq->payload, iq->ns); /* namespace, stanza subtype and payload tag name must match: */ if ((payload == NULL) || (subtype != iq->subtype)) continue; DEBUG ("test_connector_server:invoking iq handler %s", iq->payload); (iq->func) (self, xml); handled = TRUE; break; } else for (i = 0; handlers[i].ns != NULL; i++) { if (!strcmp (ns, handlers[i].ns) && !strcmp (name, handlers[i].name)) { DEBUG ("test_connector_server:invoking handler %s.%s", ns, name); (handlers[i].func) (self, xml); handled = TRUE; break; } } /* no handler found: just complain and sit waiting for the next stanza */ if (!handled) { DEBUG ("<%s xmlns=\"%s\"… not handled", name, ns); server_enc_outstanding (self); wocky_xmpp_connection_recv_stanza_async (conn, priv->cancellable, xmpp_handler, self); g_object_unref (xml); } } /* ************************************************************************* */ /* resume control after the sasl auth server is done: */ static void after_auth (GObject *source, GAsyncResult *res, gpointer data) { GError *error = NULL; WockyStanza *feat = NULL; WockyNode *node = NULL; TestSaslAuthServer *tsas = TEST_SASL_AUTH_SERVER (source); TestConnectorServer *tcs = TEST_CONNECTOR_SERVER (data); TestConnectorServerPrivate *priv = tcs->priv; WockyXmppConnection *conn = priv->conn; DEBUG ("Auth finished: %d", priv->outstanding); if (!test_sasl_auth_server_auth_finish (tsas, res, &error)) { g_object_unref (priv->sasl); priv->sasl = NULL; if (server_dec_outstanding (tcs)) return; server_enc_outstanding (tcs); wocky_xmpp_connection_send_close_async (conn, priv->cancellable, xmpp_close, data); return; } priv->used_mech = g_strdup (test_sasl_auth_server_get_selected_mech (priv->sasl)); g_object_unref (priv->sasl); priv->sasl = NULL; if (server_dec_outstanding (tcs)) return; feat = wocky_stanza_build (WOCKY_STANZA_TYPE_STREAM_FEATURES, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, NULL); node = wocky_stanza_get_top_node (feat); if (!(priv->problem.connector->xmpp & XMPP_PROBLEM_NO_SESSION)) wocky_node_add_child_ns (node, "session", WOCKY_XMPP_NS_SESSION); if (!(priv->problem.connector->xmpp & XMPP_PROBLEM_CANNOT_BIND)) wocky_node_add_child_ns (node, "bind", WOCKY_XMPP_NS_BIND); priv->state = SERVER_STATE_FEATURES_SENT; server_enc_outstanding (tcs); wocky_xmpp_connection_send_stanza_async (conn, feat, priv->cancellable, xmpp_init, data); g_object_unref (feat); } /* ************************************************************************* */ /* initial XMPP stream setup, up to sending features stanza */ static WockyStanza * feature_stanza (TestConnectorServer *self) { TestConnectorServerPrivate *priv = self->priv; XmppProblem problem = priv->problem.connector->xmpp; const gchar *name = NULL; WockyStanza *feat = NULL; WockyNode *node = NULL; DEBUG (""); if (problem & XMPP_PROBLEM_OTHER_HOST) return error_stanza ("host-unknown", "some sort of DNS error", TRUE); name = (problem & XMPP_PROBLEM_FEATURES) ? "badger" : "features"; feat = wocky_stanza_new (name, WOCKY_XMPP_NS_STREAM); node = wocky_stanza_get_top_node (feat); DEBUG ("constructing <%s...>... stanza", name); if (priv->problem.sasl != SERVER_PROBLEM_NO_SASL) { if (priv->sasl == NULL) priv->sasl = test_sasl_auth_server_new (NULL, priv->mech, priv->user, priv->pass, NULL, priv->problem.sasl, FALSE); test_sasl_auth_server_set_mechs (G_OBJECT (priv->sasl), feat); } if (problem & XMPP_PROBLEM_OLD_AUTH_FEATURE) wocky_node_add_child_ns (node, "auth", WOCKY_JABBER_NS_AUTH_FEATURE); if (!(problem & XMPP_PROBLEM_NO_TLS) && !priv->tls_started) wocky_node_add_child_ns (node, "starttls", WOCKY_XMPP_NS_TLS); return feat; } static void xmpp_close (GObject *source, GAsyncResult *result, gpointer data) { TestConnectorServer *self = TEST_CONNECTOR_SERVER (data); TestConnectorServerPrivate *priv = self->priv; DEBUG ("Closing connection"); wocky_xmpp_connection_send_close_async (priv->conn, NULL, xmpp_closed, self); } static void xmpp_closed (GObject *source, GAsyncResult *result, gpointer data) { TestConnectorServer *self = TEST_CONNECTOR_SERVER (data); TestConnectorServerPrivate *priv = self->priv; DEBUG ("Connection closed"); wocky_xmpp_connection_send_close_finish (priv->conn, result, NULL); } static void startssl (TestConnectorServer *self) { TestConnectorServerPrivate *priv = self->priv; ConnectorProblem *problem = priv->problem.connector; g_assert (!priv->tls_started); DEBUG ("creating SSL Session [server]"); if (problem->death & SERVER_DEATH_TLS_NEG) priv->tls_sess = wocky_tls_session_server_new (priv->stream, 1024, NULL, NULL); else { int x; const gchar *key = TLS_SERVER_KEY_FILE; const gchar *crt = TLS_SERVER_CRT_FILE; for (x = 0; certs[x].set != CERT_NONE; x++) { if (certs[x].set == priv->cert) { key = certs[x].key; crt = certs[x].crt; break; } } priv->tls_sess = wocky_tls_session_server_new (priv->stream, 1024, key, crt); } DEBUG ("starting server SSL handshake"); server_enc_outstanding (self); wocky_tls_session_handshake_async (priv->tls_sess, G_PRIORITY_DEFAULT, priv->cancellable, handshake_cb, self); } static void force_closed_cb (GObject *source, GAsyncResult *result, gpointer user_data) { TestConnectorServer *self = TEST_CONNECTOR_SERVER (user_data); DEBUG ("Connection force closed"); g_assert (wocky_xmpp_connection_force_close_finish ( WOCKY_XMPP_CONNECTION (source), result, NULL)); server_dec_outstanding (self); } static void see_other_host_cb (GObject *source, GAsyncResult *result, gpointer user_data) { TestConnectorServer *self = user_data; g_assert (wocky_xmpp_connection_send_stanza_finish (self->priv->conn, result, NULL)); if (server_dec_outstanding (self)) return; server_enc_outstanding (self); wocky_xmpp_connection_force_close_async (self->priv->conn, self->priv->cancellable, force_closed_cb, self); } static void xmpp_init (GObject *source, GAsyncResult *result, gpointer data) { TestConnectorServer *self; TestConnectorServerPrivate *priv; WockyStanza *xml; WockyXmppConnection *conn; self = TEST_CONNECTOR_SERVER (data); priv = self->priv; conn = priv->conn; DEBUG ("test_connector_server:xmpp_init %d", priv->state); DEBUG ("connection: %p", conn); switch (priv->state) { /* wait for state = SERVER_STATE_CLIENT_OPENED; server_enc_outstanding (self); if (priv->problem.connector->death & SERVER_DEATH_SERVER_START) { wocky_xmpp_connection_force_close_async (conn, priv->cancellable, force_closed_cb, self); } else { wocky_xmpp_connection_recv_open_async (conn, priv->cancellable, xmpp_init, self); } break; /* send our own state = SERVER_STATE_SERVER_OPENED; wocky_xmpp_connection_recv_open_finish (conn, result, NULL, NULL, NULL, NULL, NULL, NULL); if (server_dec_outstanding (self)) return; server_enc_outstanding (self); if (priv->problem.connector->death & SERVER_DEATH_CLIENT_OPEN) { wocky_xmpp_connection_force_close_async (conn, priv->cancellable, force_closed_cb, self); } else { wocky_xmpp_connection_send_open_async (conn, NULL, "testserver", priv->version, NULL, INITIAL_STREAM_ID, priv->cancellable, xmpp_init, self); } break; /* send our feature set */ case SERVER_STATE_SERVER_OPENED: DEBUG ("SERVER_STATE_SERVER_OPENED"); priv->state = SERVER_STATE_FEATURES_SENT; wocky_xmpp_connection_send_open_finish (conn, result, NULL); if (server_dec_outstanding (self)) return; if (priv->problem.connector->death & SERVER_DEATH_SERVER_OPEN) { server_enc_outstanding (self); wocky_xmpp_connection_force_close_async (conn, priv->cancellable, force_closed_cb, self); } else if (priv->problem.connector->xmpp & XMPP_PROBLEM_OLD_SERVER) { DEBUG ("diverting to old-jabber-auth"); server_enc_outstanding (self); wocky_xmpp_connection_recv_stanza_async (priv->conn, priv->cancellable, xmpp_handler, self); } else if (priv->problem.connector->xmpp & XMPP_PROBLEM_SEE_OTHER_HOST) { WockyStanza *stanza; WockyNode *node; gchar *host_and_port; host_and_port = g_strdup_printf ("%s:%u", self->priv->other_host, self->priv->other_port); DEBUG ("Redirect to another host: %s", host_and_port); stanza = wocky_stanza_new ("error", WOCKY_XMPP_NS_STREAM); node = wocky_stanza_get_top_node (stanza); wocky_node_add_child_with_content_ns (node, "see-other-host", host_and_port, WOCKY_XMPP_NS_STREAMS); server_enc_outstanding (self); wocky_xmpp_connection_send_stanza_async (self->priv->conn, stanza, self->priv->cancellable, see_other_host_cb, self); g_object_unref (stanza); } else { xml = feature_stanza (self); server_enc_outstanding (self); wocky_xmpp_connection_send_stanza_async (conn, xml, priv->cancellable, xmpp_init, self); g_object_unref (xml); } break; /* ok, we're done with initial stream setup */ case SERVER_STATE_FEATURES_SENT: DEBUG ("SERVER_STATE_FEATURES_SENT"); wocky_xmpp_connection_send_stanza_finish (conn, result, NULL); if (server_dec_outstanding (self)) return; server_enc_outstanding (self); if (priv->problem.connector->death & SERVER_DEATH_FEATURES) { wocky_xmpp_connection_force_close_async (conn, priv->cancellable, force_closed_cb, self); } else { wocky_xmpp_connection_recv_stanza_async (conn, priv->cancellable, xmpp_handler, self); } break; default: DEBUG ("Unknown Server state. Broken code flow."); } } /* ************************************************************************* */ /* exposed methods */ TestConnectorServer * test_connector_server_new (GIOStream *stream, gchar *mech, const gchar *user, const gchar *pass, const gchar *version, ConnectorProblem *problem, ServerProblem sasl_problem, CertSet cert) { TestConnectorServer *self; TestConnectorServerPrivate *priv; DEBUG ("test_connector_server_new"); self = g_object_new (TEST_TYPE_CONNECTOR_SERVER, NULL); priv = self->priv; priv->stream = g_object_ref (stream); priv->mech = g_strdup (mech); priv->user = g_strdup (user); priv->pass = g_strdup (pass); priv->problem.sasl = sasl_problem; priv->problem.connector = problem; priv->conn = wocky_xmpp_connection_new (stream); priv->cert = cert; DEBUG ("connection: %p", priv->conn); if (problem->xmpp & XMPP_PROBLEM_OLD_SERVER) priv->version = g_strdup ((version == NULL) ? "0.9" : version); else priv->version = g_strdup ((version == NULL) ? "1.0" : version); return self; } static void server_enc_outstanding (TestConnectorServer *self) { TestConnectorServerPrivate *priv = self->priv; priv->outstanding++; DEBUG ("Upped outstanding to %d", priv->outstanding); } static gboolean server_dec_outstanding (TestConnectorServer *self) { TestConnectorServerPrivate *priv = self->priv; priv->outstanding--; g_assert (priv->outstanding >= 0); if (priv->teardown_result != NULL && priv->outstanding == 0) { GSimpleAsyncResult *r = priv->teardown_result; priv->teardown_result = NULL; DEBUG ("Tearing down, bye bye"); g_simple_async_result_complete (r); g_object_unref (r); DEBUG ("Unreffed!"); return TRUE; } DEBUG ("Outstanding: %d", priv->outstanding); return FALSE; } void test_connector_server_teardown (TestConnectorServer *self, GAsyncReadyCallback callback, gpointer user_data) { TestConnectorServerPrivate *priv = self->priv; GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, test_connector_server_teardown); /* For now, we'll assert if this gets called twice */ g_assert (priv->cancellable != NULL); DEBUG ("Requested to stop: %d", priv->outstanding); g_cancellable_cancel (priv->cancellable); g_object_unref (priv->cancellable); priv->cancellable = NULL; if (priv->outstanding == 0) { g_simple_async_result_complete_in_idle (result); g_object_unref (result); } else { priv->teardown_result = result; } } gboolean test_connector_server_teardown_finish (TestConnectorServer *self, GAsyncResult *result, GError *error) { return TRUE; } void test_connector_server_start (TestConnectorServer *self) { TestConnectorServerPrivate *priv; DEBUG("test_connector_server_start"); priv = self->priv; priv->state = SERVER_STATE_START; DEBUG ("connection: %p", priv->conn); if (priv->problem.connector->xmpp & XMPP_PROBLEM_OLD_SSL) { startssl (self); } else { xmpp_init (NULL,NULL,self); } } const gchar * test_connector_server_get_used_mech (TestConnectorServer *self) { TestConnectorServerPrivate *priv = self->priv; return priv->used_mech; } void test_connector_server_set_other_host (TestConnectorServer *self, const gchar *host, guint port) { g_return_if_fail (TEST_IS_CONNECTOR_SERVER (self)); g_return_if_fail (self->priv->other_host == NULL); g_return_if_fail (self->priv->other_port == 0); self->priv->other_host = g_strdup (host); self->priv->other_port = port; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-roster-test.c0000664000175000017500000016733212005516162025645 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "wocky-test-stream.h" #include "wocky-test-helper.h" /* Test to instantiate a WockyRoster object */ static void test_instantiation (void) { WockyRoster *roster; WockyXmppConnection *connection; WockyTestStream *stream; WockySession *session; stream = g_object_new (WOCKY_TYPE_TEST_STREAM, NULL); connection = wocky_xmpp_connection_new (stream->stream0); session = wocky_session_new_with_connection (connection, "example.com"); roster = wocky_roster_new (session); g_assert (roster != NULL); g_object_unref (roster); g_object_unref (session); g_object_unref (connection); g_object_unref (stream); } /* Test if the Roster sends the right IQ query when fetching the roster */ static gboolean fetch_roster_send_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanzaType type; WockyStanzaSubType sub_type; WockyNode *node; WockyStanza *reply; const char *id; /* Make sure stanza is as expected. */ wocky_stanza_get_type_info (stanza, &type, &sub_type); g_assert (type == WOCKY_STANZA_TYPE_IQ); g_assert (sub_type == WOCKY_STANZA_SUB_TYPE_GET); node = wocky_node_get_child (wocky_stanza_get_top_node (stanza), "query"); g_assert (wocky_stanza_get_top_node (stanza) != NULL); g_assert (!wocky_strdiff (wocky_node_get_ns (node), "jabber:iq:roster")); id = wocky_node_get_attribute (wocky_stanza_get_top_node (stanza), "id"); g_assert (id != NULL); reply = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '@', "id", id, '(', "query", ':', "jabber:iq:roster", '(', "item", '@', "jid", "romeo@example.net", '@', "name", "Romeo", '@', "subscription", "both", '(', "group", '$', "Friends", ')', ')', ')', NULL); wocky_porter_send (porter, reply); g_object_unref (reply); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void fetch_roster_fetched_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; g_return_if_fail (wocky_roster_fetch_roster_finish ( WOCKY_ROSTER (source_object), res, NULL)); test->outstanding--; g_main_loop_quit (test->loop); } static void test_fetch_roster_send_iq (void) { WockyRoster *roster; test_data_t *test = setup_test (); test_open_both_connections (test); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, fetch_roster_send_iq_cb, test, NULL); wocky_porter_start (test->sched_out); wocky_session_start (test->session_in); roster = wocky_roster_new (test->session_in); wocky_roster_fetch_roster_async (roster, NULL, fetch_roster_fetched_cb, test); test->outstanding += 2; test_wait_pending (test); test_close_both_porters (test); g_object_unref (roster); teardown_test (test); } /* Test if the Roster object is properly populated when receiving its fetch * reply */ static WockyBareContact * create_romeo (void) { const gchar *groups[] = { "Friends", NULL }; return g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "name", "Romeo", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH, "groups", groups, NULL); } static WockyBareContact * create_juliet (void) { const gchar *groups[] = { "Friends", "Girlz", NULL }; return g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "juliet@example.net", "name", "Juliet", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_TO, "groups", groups, NULL); } static int find_contact (gconstpointer a, gconstpointer b) { if (wocky_bare_contact_equal (WOCKY_BARE_CONTACT (a), WOCKY_BARE_CONTACT (b))) return 0; return 1; } static void fetch_roster_reply_roster_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyBareContact *contact; WockyRoster *roster = WOCKY_ROSTER (source_object); WockyBareContact *romeo, *juliet; GSList *contacts; g_return_if_fail (wocky_roster_fetch_roster_finish (roster, res, NULL)); contacts = wocky_roster_get_all_contacts (roster); g_assert_cmpuint (g_slist_length (contacts), ==, 2); contact = wocky_roster_get_contact (roster, "romeo@example.net"); romeo = create_romeo (); g_assert (wocky_bare_contact_equal (contact, romeo)); g_assert (g_slist_find_custom (contacts, romeo, find_contact) != NULL); g_object_unref (romeo); contact = wocky_roster_get_contact (roster, "juliet@example.net"); juliet = create_juliet (); g_assert (wocky_bare_contact_equal (contact, juliet)); g_assert (g_slist_find_custom (contacts, juliet, find_contact) != NULL); g_object_unref (juliet); g_slist_foreach (contacts, (GFunc) g_object_unref, NULL); g_slist_free (contacts); test->outstanding--; g_main_loop_quit (test->loop); } static gboolean fetch_roster_reply_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { WockyStanza *reply; /* We're acting like the server here. The client doesn't need to send a * "from" attribute, and in fact it doesn't when fetch_roster is called. It * is left up to the server to know which client is the user and then throw * in a correct to attribute. Here we're just adding a from attribute so the * IQ result builder doesn't complain. */ if (wocky_stanza_get_from (stanza) == NULL) wocky_node_set_attribute (wocky_stanza_get_top_node (stanza), "from", "juliet@example.com/balcony"); reply = wocky_stanza_build_iq_result (stanza, '(', "query", ':', "jabber:iq:roster", /* Romeo */ '(', "item", '@', "jid", "romeo@example.net", '@', "name", "Romeo", '@', "subscription", "both", '(', "group", '$', "Friends", ')', /* Juliet */ ')', '(', "item", '@', "jid", "juliet@example.net", '@', "name", "Juliet", '@', "subscription", "to", '(', "group", '$', "Friends", ')', '(', "group", '$', "Girlz", ')', ')', ')', NULL); wocky_porter_send (porter, reply); g_object_unref (reply); return TRUE; } static WockyRoster * create_initial_roster (test_data_t *test) { WockyRoster *roster; wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, fetch_roster_reply_cb, test, NULL); wocky_porter_start (test->sched_out); wocky_session_start (test->session_in); roster = wocky_roster_new (test->session_in); wocky_roster_fetch_roster_async (roster, NULL, fetch_roster_reply_roster_cb, test); test->outstanding++; test_wait_pending (test); return roster; } static void test_fetch_roster_reply (void) { WockyRoster *roster; test_data_t *test = setup_test (); test_open_both_connections (test); roster = create_initial_roster (test); test_close_both_porters (test); g_object_unref (roster); teardown_test (test); } /* Test if roster is properly upgraded when a contact is added to it */ static WockyBareContact * create_nurse (void) { const gchar *groups[] = { NULL }; return g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "nurse@example.net", "name", "Nurse", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_NONE, "groups", groups, NULL); } static void roster_added_cb (WockyRoster *roster, WockyBareContact *contact, test_data_t *test) { WockyBareContact *nurse; GSList *contacts; /* Is that the right contact? */ nurse = create_nurse (); g_assert (wocky_bare_contact_equal (contact, nurse)); /* Check if the contact has been added to the roster */ g_assert (wocky_roster_get_contact (roster, "nurse@example.net") == contact); contacts = wocky_roster_get_all_contacts (roster); g_assert (g_slist_find_custom (contacts, nurse, (GCompareFunc) find_contact)); g_object_unref (nurse); g_slist_foreach (contacts, (GFunc) g_object_unref, NULL); g_slist_free (contacts); test->outstanding--; g_main_loop_quit (test->loop); } static void roster_update_reply_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; WockyStanzaType type; WockyStanzaSubType sub_type; reply = wocky_porter_send_iq_finish (WOCKY_PORTER (source), res, NULL); g_assert (reply != NULL); wocky_stanza_get_type_info (reply, &type, &sub_type); g_assert (type == WOCKY_STANZA_TYPE_IQ); g_assert (sub_type == WOCKY_STANZA_SUB_TYPE_RESULT); g_object_unref (reply); test->outstanding--; g_main_loop_quit (test->loop); } static void send_roster_update (test_data_t *test, const gchar *jid, const gchar *name, const gchar *subscription, const gchar **groups) { WockyStanza *iq; WockyNode *item; guint i; iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, '(', "item", '*', &item, ')', ')', NULL); if (jid != NULL) wocky_node_set_attribute (item, "jid", jid); if (name != NULL) wocky_node_set_attribute (item, "name", name); if (subscription != NULL) wocky_node_set_attribute (item, "subscription", subscription); for (i = 0; groups != NULL && groups[i] != NULL; i++) { WockyNode *node; node = wocky_node_add_child (item, "group"); wocky_node_set_content (node, groups[i]); } wocky_porter_send_iq_async (test->sched_out, iq, NULL, roster_update_reply_cb, test); g_object_unref (iq); test->outstanding++; } static void test_roster_upgrade_add (void) { WockyRoster *roster; test_data_t *test = setup_test (); const gchar *no_group[] = { NULL }; test_open_both_connections (test); roster = create_initial_roster (test); g_signal_connect (roster, "added", G_CALLBACK (roster_added_cb), test); test->outstanding++; send_roster_update (test, "nurse@example.net", "Nurse", "none", no_group); test_wait_pending (test); test_close_both_porters (test); g_object_unref (roster); teardown_test (test); } /* Test if roster is properly upgraded when a contact is removed from it */ static void roster_removed_cb (WockyRoster *roster, WockyBareContact *contact, test_data_t *test) { WockyBareContact *romeo; GSList *contacts; /* Is that the right contact? */ romeo = create_romeo (); g_assert (wocky_bare_contact_equal (contact, romeo)); /* Check if the contact has been removed from the roster */ g_assert (wocky_roster_get_contact (roster, "romeo@example.net") == NULL); contacts = wocky_roster_get_all_contacts (roster); g_assert (g_slist_find_custom (contacts, romeo, (GCompareFunc) find_contact) == NULL); g_object_unref (romeo); g_slist_foreach (contacts, (GFunc) g_object_unref, NULL); g_slist_free (contacts); test->outstanding--; g_main_loop_quit (test->loop); } static void test_roster_upgrade_remove (void) { WockyRoster *roster; test_data_t *test = setup_test (); const gchar *no_group[] = { NULL }; test_open_both_connections (test); roster = create_initial_roster (test); g_signal_connect (roster, "removed", G_CALLBACK (roster_removed_cb), test); test->outstanding++; send_roster_update (test, "romeo@example.net", NULL, "remove", no_group); test_wait_pending (test); test_close_both_porters (test); g_object_unref (roster); teardown_test (test); } /* Test if WockyBareContact objects are properly upgraded */ static void contact_notify_cb (WockyBareContact *contact, GParamSpec *pspec, test_data_t *test) { test->outstanding--; g_main_loop_quit (test->loop); } static void test_roster_upgrade_change (void) { WockyRoster *roster; test_data_t *test = setup_test (); GSList *contacts, *l; WockyBareContact *romeo, *contact; const gchar *groups_init[] = { "Friends", NULL }; const gchar *groups[] = { "Badger", NULL }; test_open_both_connections (test); roster = create_initial_roster (test); contact = wocky_roster_get_contact (roster, "romeo@example.net"); g_assert (contact != NULL); romeo = create_romeo (); contacts = wocky_roster_get_all_contacts (roster); for (l = contacts; l != NULL; l = g_slist_next (l)) { g_signal_connect (l->data, "notify", G_CALLBACK (contact_notify_cb), test); } g_slist_foreach (contacts, (GFunc) g_object_unref, NULL); g_slist_free (contacts); /* change name */ test->outstanding++; send_roster_update (test, "romeo@example.net", "Romeooo", "both", groups_init); test_wait_pending (test); /* Name has been changed */ wocky_bare_contact_set_name (romeo, "Romeooo"); g_assert (wocky_bare_contact_equal (contact, romeo)); /* change subscription */ test->outstanding++; send_roster_update (test, "romeo@example.net", "Romeooo", "to", groups_init); test_wait_pending (test); /* Subscription has been changed */ wocky_bare_contact_set_subscription (romeo, WOCKY_ROSTER_SUBSCRIPTION_TYPE_TO); g_assert (wocky_bare_contact_equal (contact, romeo)); /* change groups */ test->outstanding++; send_roster_update (test, "romeo@example.net", "Romeooo", "to", groups); test_wait_pending (test); /* Groups have been changed */ wocky_bare_contact_set_groups (romeo, (gchar **) groups); g_assert (wocky_bare_contact_equal (contact, romeo)); g_object_unref (romeo); test_close_both_porters (test); g_object_unref (roster); teardown_test (test); } static void ack_iq (WockyPorter *porter, WockyStanza *stanza) { WockyStanza *reply; const gchar *id; id = wocky_node_get_attribute (wocky_stanza_get_top_node (stanza), "id"); g_assert (id != NULL); reply = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '@', "id", id, NULL); wocky_porter_send (porter, reply); g_object_unref (reply); } /* Test adding a contact to the roster */ static void check_edit_roster_stanza (WockyStanza *stanza, const gchar *jid, const gchar *name, const gchar *subscription, const gchar **groups) { WockyStanzaType type; WockyStanzaSubType sub_type; WockyNode *node; GSList *l; guint i; GHashTable *expected_groups; wocky_stanza_get_type_info (stanza, &type, &sub_type); g_assert (type == WOCKY_STANZA_TYPE_IQ); g_assert (sub_type == WOCKY_STANZA_SUB_TYPE_SET); node = wocky_node_get_child_ns (wocky_stanza_get_top_node (stanza), "query", WOCKY_XMPP_NS_ROSTER); g_assert (node != NULL); node = wocky_node_get_child (node, "item"); g_assert (node != NULL); g_assert (!wocky_strdiff (wocky_node_get_attribute (node, "jid"), jid)); if (name != NULL) g_assert (!wocky_strdiff (wocky_node_get_attribute (node, "name"), name)); else g_assert (wocky_node_get_attribute (node, "name") == NULL); if (subscription != NULL) g_assert (!wocky_strdiff (wocky_node_get_attribute (node, "subscription"), subscription)); else g_assert (wocky_node_get_attribute (node, "subscription") == NULL); if (groups == NULL) { /* No group children */ g_assert_cmpuint (g_slist_length (node->children), == , 0); return; } expected_groups = g_hash_table_new (g_str_hash, g_str_equal); for (i = 0; groups[i] != NULL; i++) { g_hash_table_insert (expected_groups, (gchar *) groups[i], GUINT_TO_POINTER (TRUE)); } for (l = node->children; l != NULL; l = g_slist_next (l)) { WockyNode *group = (WockyNode *) l->data; g_assert (!wocky_strdiff (group->name, "group")); g_assert (g_hash_table_remove (expected_groups, group->content)); } g_assert (g_hash_table_size (expected_groups) == 0); g_hash_table_unref (expected_groups); } static void check_add_contact_stanza (WockyStanza *stanza, const gchar *jid, const gchar *name, const gchar **groups) { check_edit_roster_stanza (stanza, jid, name, NULL, groups); } static gboolean first_add = TRUE; static gboolean add_contact_send_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; const gchar *groups[] = { "Friends", "Badger", NULL }; if (first_add) { check_add_contact_stanza (stanza, "mercutio@example.net", "Mercutio", groups); send_roster_update (test, "mercutio@example.net", "Mercutio", "none", groups); first_add = FALSE; } else { /* the second time the name is changed */ check_add_contact_stanza (stanza, "mercutio@example.net", "Badger", groups); send_roster_update (test, "mercutio@example.net", "Badger", "none", groups); } /* Ack the IQ */ ack_iq (porter, stanza); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void contact_added_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyRoster *roster = WOCKY_ROSTER (source); g_assert (wocky_roster_add_contact_finish (roster, res, NULL)); test->outstanding--; g_main_loop_quit (test->loop); } static WockyBareContact * create_mercutio (void) { const gchar *groups[] = { "Friends", "Badger", NULL }; return g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "mercutio@example.net", "name", "Mercutio", "groups", groups, NULL); } static void test_roster_add_contact (void) { WockyRoster *roster; test_data_t *test = setup_test (); WockyBareContact *mercutio, *contact; const gchar *groups[] = { "Friends", "Badger", NULL }; test_open_both_connections (test); roster = create_initial_roster (test); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, add_contact_send_iq_cb, test, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, ')', NULL); mercutio = create_mercutio (); /* Add the Mercutio to our roster */ wocky_roster_add_contact_async (roster, "mercutio@example.net", "Mercutio", groups, NULL, contact_added_cb, test); test->outstanding += 2; test_wait_pending (test); /* check if the contact has been actually added */ contact = wocky_roster_get_contact (roster, "mercutio@example.net"); g_assert (wocky_bare_contact_equal (contact, mercutio)); /* try to re-add the same contact. Operation succeeds immediately */ wocky_roster_add_contact_async (roster, "mercutio@example.net", "Mercutio", groups, NULL, contact_added_cb, test); test->outstanding += 1; test_wait_pending (test); /* try to re-add the same contact but with a different name. The name is * changed */ wocky_roster_add_contact_async (roster, "mercutio@example.net", "Badger", groups, NULL, contact_added_cb, test); test->outstanding += 2; test_wait_pending (test); /* check if the contact has been updated */ contact = wocky_roster_get_contact (roster, "mercutio@example.net"); wocky_bare_contact_set_name (mercutio, "Badger"); g_assert (wocky_bare_contact_equal (contact, mercutio)); test_close_both_porters (test); g_object_unref (mercutio); g_object_unref (roster); teardown_test (test); } static void check_remove_contact_stanza (WockyStanza *stanza, const gchar *jid) { check_edit_roster_stanza (stanza, jid, NULL, "remove", NULL); } /* Test removing a contact from the roster */ static gboolean remove_contact_send_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; const gchar *no_group[] = { NULL }; check_remove_contact_stanza (stanza, "romeo@example.net"); send_roster_update (test, "romeo@example.net", NULL, "remove", no_group); /* Ack the IQ */ ack_iq (porter, stanza); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void contact_removed_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyRoster *roster = WOCKY_ROSTER (source); g_assert (wocky_roster_remove_contact_finish (roster, res, NULL)); test->outstanding--; g_main_loop_quit (test->loop); } static void test_roster_remove_contact (void) { WockyRoster *roster; test_data_t *test = setup_test (); WockyBareContact *contact; test_open_both_connections (test); roster = create_initial_roster (test); contact = wocky_roster_get_contact (roster, "romeo@example.net"); g_assert (contact != NULL); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, remove_contact_send_iq_cb, test, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, ')', NULL); /* Keep a ref on the contact as the roster will release its ref when * removing it */ g_object_ref (contact); wocky_roster_remove_contact_async (roster, contact, NULL, contact_removed_cb, test); test->outstanding += 2; test_wait_pending (test); /* check if the contact has actually been removed */ g_assert (wocky_roster_get_contact (roster, "romeo@example.net") == NULL); /* try to re-remove the same contact. Operation succeeds immediately */ wocky_roster_remove_contact_async (roster, contact, NULL, contact_removed_cb, test); test->outstanding += 1; test_wait_pending (test); test_close_both_porters (test); g_object_unref (roster); g_object_unref (contact); teardown_test (test); } /* test changing the name of a roster item */ static gboolean change_name_send_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanzaType type; WockyStanzaSubType sub_type; WockyNode *node; const gchar *group[] = { "Friends", NULL }; /* Make sure stanza is as expected. */ wocky_stanza_get_type_info (stanza, &type, &sub_type); g_assert (type == WOCKY_STANZA_TYPE_IQ); g_assert (sub_type == WOCKY_STANZA_SUB_TYPE_SET); node = wocky_node_get_child_ns (wocky_stanza_get_top_node (stanza), "query", WOCKY_XMPP_NS_ROSTER); g_assert (node != NULL); node = wocky_node_get_child (node, "item"); g_assert (node != NULL); g_assert (!wocky_strdiff (wocky_node_get_attribute (node, "jid"), "romeo@example.net")); g_assert (!wocky_strdiff (wocky_node_get_attribute (node, "name"), "Badger")); g_assert (!wocky_strdiff (wocky_node_get_attribute (node, "subscription"), "both")); g_assert_cmpuint (g_slist_length (node->children), ==, 1); node = wocky_node_get_child (node, "group"); g_assert (node != NULL); g_assert (!wocky_strdiff (node->content, "Friends")); send_roster_update (test, "romeo@example.net", "Badger", "both", group); /* Ack the IQ */ ack_iq (porter, stanza); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void contact_name_changed_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyRoster *roster = WOCKY_ROSTER (source); g_assert (wocky_roster_change_contact_name_finish (roster, res, NULL)); test->outstanding--; g_main_loop_quit (test->loop); } static void contact_name_changed_not_in_roster_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyRoster *roster = WOCKY_ROSTER (source); GError *error = NULL; g_assert (!wocky_roster_change_contact_name_finish (roster, res, &error)); g_assert_error (error, WOCKY_ROSTER_ERROR, WOCKY_ROSTER_ERROR_NOT_IN_ROSTER); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_roster_change_name (void) { WockyRoster *roster; test_data_t *test = setup_test (); WockyBareContact *contact, *romeo, *mercutio; test_open_both_connections (test); roster = create_initial_roster (test); romeo = create_romeo (); contact = wocky_roster_get_contact (roster, "romeo@example.net"); g_assert (contact != NULL); g_assert (wocky_bare_contact_equal (contact, romeo)); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, change_name_send_iq_cb, test, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, ')', NULL); wocky_roster_change_contact_name_async (roster, contact, "Badger", NULL, contact_name_changed_cb, test); test->outstanding += 2; test_wait_pending (test); /* check if the contact name has actually been change */ wocky_bare_contact_set_name (romeo, "Badger"); g_assert (wocky_bare_contact_equal (contact, romeo)); /* Retry to do the same change; operation succeeds immediately */ wocky_roster_change_contact_name_async (roster, contact, "Badger", NULL, contact_name_changed_cb, test); test->outstanding += 1; test_wait_pending (test); /* try to change name of a contact which is not in the roster */ mercutio = create_mercutio (); wocky_roster_change_contact_name_async (roster, mercutio, "Badger", NULL, contact_name_changed_not_in_roster_cb, test); test->outstanding += 1; test_wait_pending (test); test_close_both_porters (test); g_object_unref (roster); g_object_unref (romeo); g_object_unref (mercutio); teardown_test (test); } /* test adding a group to a contact */ static gboolean add_group_send_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanzaType type; WockyStanzaSubType sub_type; WockyNode *node; const gchar *groups[] = { "Friends", "Badger", NULL }; GSList *l; gboolean group_friend = FALSE, group_badger = FALSE; /* Make sure stanza is as expected. */ wocky_stanza_get_type_info (stanza, &type, &sub_type); g_assert (type == WOCKY_STANZA_TYPE_IQ); g_assert (sub_type == WOCKY_STANZA_SUB_TYPE_SET); node = wocky_node_get_child_ns (wocky_stanza_get_top_node (stanza), "query", WOCKY_XMPP_NS_ROSTER); g_assert (node != NULL); node = wocky_node_get_child (node, "item"); g_assert (node != NULL); g_assert (!wocky_strdiff (wocky_node_get_attribute (node, "jid"), "romeo@example.net")); g_assert (!wocky_strdiff (wocky_node_get_attribute (node, "name"), "Romeo")); g_assert (!wocky_strdiff (wocky_node_get_attribute (node, "subscription"), "both")); g_assert_cmpuint (g_slist_length (node->children), ==, 2); for (l = node->children; l != NULL; l = g_slist_next (l)) { WockyNode *group = (WockyNode *) l->data; g_assert (!wocky_strdiff (group->name, "group")); if (!wocky_strdiff (group->content, "Friends")) group_friend = TRUE; else if (!wocky_strdiff (group->content, "Badger")) group_badger = TRUE; else g_assert_not_reached (); } g_assert (group_friend && group_badger); send_roster_update (test, "romeo@example.net", "Romeo", "both", groups); /* Ack the IQ */ ack_iq (porter, stanza); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void contact_group_added_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyRoster *roster = WOCKY_ROSTER (source); g_assert (wocky_roster_contact_add_group_finish (roster, res, NULL)); test->outstanding--; g_main_loop_quit (test->loop); } static void contact_group_added_not_in_roster_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyRoster *roster = WOCKY_ROSTER (source); GError *error = NULL; g_assert (!wocky_roster_contact_add_group_finish (roster, res, &error)); g_assert_error (error, WOCKY_ROSTER_ERROR, WOCKY_ROSTER_ERROR_NOT_IN_ROSTER); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_contact_add_group (void) { WockyRoster *roster; test_data_t *test = setup_test (); WockyBareContact *contact, *romeo, *mercutio; test_open_both_connections (test); roster = create_initial_roster (test); romeo = create_romeo (); contact = wocky_roster_get_contact (roster, "romeo@example.net"); g_assert (contact != NULL); g_assert (wocky_bare_contact_equal (contact, romeo)); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, add_group_send_iq_cb, test, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, ')', NULL); wocky_roster_contact_add_group_async (roster, contact, "Badger", NULL, contact_group_added_cb, test); test->outstanding += 2; test_wait_pending (test); /* check if the group has actually been added */ wocky_bare_contact_add_group (romeo, "Badger"); g_assert (wocky_bare_contact_equal (contact, romeo)); /* Retry to do the same change; operation succeeds immediately */ wocky_roster_contact_add_group_async (roster, contact, "Badger", NULL, contact_group_added_cb, test); test->outstanding += 1; test_wait_pending (test); /* try to add a group to a contact which is not in the roster */ mercutio = create_mercutio (); wocky_roster_contact_add_group_async (roster, mercutio, "Badger", NULL, contact_group_added_not_in_roster_cb, test); test->outstanding += 1; test_wait_pending (test); test_close_both_porters (test); g_object_unref (roster); g_object_unref (romeo); g_object_unref (mercutio); teardown_test (test); } /* test removing a group from a contact */ static gboolean remove_group_send_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanzaType type; WockyStanzaSubType sub_type; WockyNode *node; const gchar *groups[] = { NULL }; /* Make sure stanza is as expected. */ wocky_stanza_get_type_info (stanza, &type, &sub_type); g_assert (type == WOCKY_STANZA_TYPE_IQ); g_assert (sub_type == WOCKY_STANZA_SUB_TYPE_SET); node = wocky_node_get_child_ns (wocky_stanza_get_top_node (stanza), "query", WOCKY_XMPP_NS_ROSTER); g_assert (node != NULL); node = wocky_node_get_child (node, "item"); g_assert (node != NULL); g_assert (!wocky_strdiff (wocky_node_get_attribute (node, "jid"), "romeo@example.net")); g_assert (!wocky_strdiff (wocky_node_get_attribute (node, "name"), "Romeo")); g_assert (!wocky_strdiff (wocky_node_get_attribute (node, "subscription"), "both")); g_assert_cmpuint (g_slist_length (node->children), ==, 0); send_roster_update (test, "romeo@example.net", "Romeo", "both", groups); /* Ack the IQ */ ack_iq (porter, stanza); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void contact_group_removed_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyRoster *roster = WOCKY_ROSTER (source); g_assert (wocky_roster_contact_remove_group_finish (roster, res, NULL)); test->outstanding--; g_main_loop_quit (test->loop); } static void contact_group_removed_not_in_roster_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyRoster *roster = WOCKY_ROSTER (source); GError *error = NULL; g_assert (!wocky_roster_contact_remove_group_finish (roster, res, &error)); g_assert_error (error, WOCKY_ROSTER_ERROR, WOCKY_ROSTER_ERROR_NOT_IN_ROSTER); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_contact_remove_group (void) { WockyRoster *roster; test_data_t *test = setup_test (); WockyBareContact *contact, *romeo, *mercutio; test_open_both_connections (test); roster = create_initial_roster (test); romeo = create_romeo (); contact = wocky_roster_get_contact (roster, "romeo@example.net"); g_assert (contact != NULL); g_assert (wocky_bare_contact_equal (contact, romeo)); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, remove_group_send_iq_cb, test, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, ')', NULL); wocky_roster_contact_remove_group_async (roster, contact, "Friends", NULL, contact_group_removed_cb, test); test->outstanding += 2; test_wait_pending (test); /* check if the group has actually been added */ wocky_bare_contact_remove_group (romeo, "Friends"); g_assert (wocky_bare_contact_equal (contact, romeo)); /* Retry to do the same change; operation succeeds immediately */ wocky_roster_contact_remove_group_async (roster, contact, "Friends", NULL, contact_group_removed_cb, test); test->outstanding += 1; test_wait_pending (test); /* try to remove a group from a contact which is not in the roster */ mercutio = create_mercutio (); wocky_roster_contact_remove_group_async (roster, mercutio, "Friends", NULL, contact_group_removed_not_in_roster_cb, test); test->outstanding += 1; test_wait_pending (test); test_close_both_porters (test); g_object_unref (roster); g_object_unref (romeo); g_object_unref (mercutio); teardown_test (test); } /* Remove a contact and re-add it before the remove operation is completed */ static WockyStanza *received_iq = NULL; static gboolean iq_set_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; g_assert (received_iq == NULL); received_iq = g_object_ref (stanza); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void test_remove_contact_re_add (void) { WockyRoster *roster; test_data_t *test = setup_test (); WockyBareContact *contact, *romeo; const gchar *groups[] = { "Friends", NULL }; const gchar *no_group[] = { NULL }; test_open_both_connections (test); roster = create_initial_roster (test); contact = wocky_roster_get_contact (roster, "romeo@example.net"); g_assert (contact != NULL); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, iq_set_cb, test, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, ')', NULL); wocky_roster_remove_contact_async (roster, contact, NULL, contact_removed_cb, test); test->outstanding += 1; test_wait_pending (test); g_assert (received_iq != NULL); /* The IQ has been sent but the server didn't send the upgrade and the reply * yet. * Now try to re-add the contact */ check_remove_contact_stanza (received_iq, "romeo@example.net"); wocky_roster_add_contact_async (roster, "romeo@example.net", "Romeo", groups, NULL, contact_added_cb, test); /* Now the server send the roster upgrade and reply to the remove IQ */ send_roster_update (test, "romeo@example.net", NULL, "remove", no_group); ack_iq (test->sched_out, received_iq); g_object_unref (received_iq); received_iq = NULL; /* Wait for: * - completion of the remove_contact operation * - server receives the "add contact" IQ */ test->outstanding += 2; test_wait_pending (test); /* At this point, the contact has been removed */ g_assert (wocky_roster_get_contact (roster, "romeo@example.net") == NULL); check_add_contact_stanza (received_iq, "romeo@example.net", "Romeo", groups); /* Now the server send the roster upgrade and reply to the add IQ */ send_roster_update (test, "romeo@example.net", "Romeo", "none", groups); ack_iq (test->sched_out, received_iq); g_object_unref (received_iq); received_iq = NULL; /* Wait for completion of the add_contact operation */ test->outstanding += 1; test_wait_pending (test); /* Check that the contact is back */ contact = wocky_roster_get_contact (roster, "romeo@example.net"); g_assert (contact != NULL); romeo = create_romeo (); wocky_bare_contact_set_subscription (romeo, WOCKY_ROSTER_SUBSCRIPTION_TYPE_NONE); g_assert (wocky_bare_contact_equal (contact, romeo)); test_close_both_porters (test); g_object_unref (romeo); g_object_unref (roster); teardown_test (test); } /* Remove a contact and then try to edit it before the remove operation is * completed */ static void test_remove_contact_edit (void) { WockyRoster *roster; test_data_t *test = setup_test (); WockyBareContact *contact; const gchar *no_group[] = { NULL }; test_open_both_connections (test); roster = create_initial_roster (test); contact = wocky_roster_get_contact (roster, "romeo@example.net"); g_assert (contact != NULL); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, iq_set_cb, test, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, ')', NULL); /* Keep a ref on the contact as the roster will release its ref when * removing it */ g_object_ref (contact); wocky_roster_remove_contact_async (roster, contact, NULL, contact_removed_cb, test); test->outstanding += 1; test_wait_pending (test); g_assert (received_iq != NULL); /* The IQ has been sent but the server didn't send the upgrade and the reply * yet. * Now try to re-add the contact */ check_remove_contact_stanza (received_iq, "romeo@example.net"); /* Try to change the name of the contact we are removing */ wocky_roster_change_contact_name_async (roster, contact, "Badger", NULL, contact_name_changed_not_in_roster_cb, test); /* Now the server send the roster upgrade and reply to the remove IQ */ send_roster_update (test, "romeo@example.net", NULL, "remove", no_group); ack_iq (test->sched_out, received_iq); g_object_unref (received_iq); received_iq = NULL; /* Wait for: * - completion of the remove_contact operation * - completion (with an error) for the change_name operation */ test->outstanding += 2; test_wait_pending (test); /* At this point, the contact has been removed */ g_assert (wocky_roster_get_contact (roster, "romeo@example.net") == NULL); test_close_both_porters (test); g_object_unref (contact); g_object_unref (roster); teardown_test (test); } /* Queue some edit operations on the same contact */ static void test_multi_contact_edit (void) { WockyRoster *roster; test_data_t *test = setup_test (); WockyBareContact *contact, *juliet; const gchar *groups[] = { "Friends", "Girlz", NULL }; const gchar *groups_changed[] = { "Friends", "School", NULL }; test_open_both_connections (test); roster = create_initial_roster (test); contact = wocky_roster_get_contact (roster, "juliet@example.net"); g_assert (contact != NULL); juliet = create_juliet (); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, iq_set_cb, test, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, ')', NULL); /* Change's Romeo's name */ wocky_roster_change_contact_name_async (roster, contact, "Badger", NULL, contact_name_changed_cb, test); test->outstanding += 1; test_wait_pending (test); g_assert (received_iq != NULL); /* The IQ has been sent but the server didn't send the upgrade and the reply * yet */ g_assert (wocky_bare_contact_equal (contact, juliet)); check_edit_roster_stanza (received_iq, "juliet@example.net", "Badger", "to", groups); /* Try to re-change the name of the contact */ wocky_roster_change_contact_name_async (roster, contact, "Snake", NULL, contact_name_changed_cb, test); /* Add two groups */ wocky_roster_contact_add_group_async (roster, contact, "Hacker", NULL, contact_group_added_cb, test); wocky_roster_contact_add_group_async (roster, contact, "School", NULL, contact_group_added_cb, test); /* Remove a group we just added */ wocky_roster_contact_remove_group_async (roster, contact, "Hacker", NULL, contact_group_removed_cb, test); /* Remove the 2 default groups */ wocky_roster_contact_remove_group_async (roster, contact, "Friends", NULL, contact_group_removed_cb, test); wocky_roster_contact_remove_group_async (roster, contact, "Girlz", NULL, contact_group_removed_cb, test); /* Re-add a removed group */ wocky_roster_contact_add_group_async (roster, contact, "Friends", NULL, contact_group_added_cb, test); /* Now the server sends the roster upgrade and reply to the remove IQ */ send_roster_update (test, "juliet@example.net", "Badger", "to", groups); ack_iq (test->sched_out, received_iq); g_object_unref (received_iq); received_iq = NULL; /* Wait for: * - completion of the first change_name operation * - server receives the second edit IQ */ test->outstanding += 2; test_wait_pending (test); /* At this point, the contact has still his initial name */ wocky_bare_contact_set_name (juliet, "Badger"); g_assert (wocky_bare_contact_equal (contact, juliet)); check_edit_roster_stanza (received_iq, "juliet@example.net", "Snake", "to", groups_changed); /* Now the server send the roster upgrade and reply to the add IQ */ send_roster_update (test, "juliet@example.net", "Snake", "to", groups_changed); ack_iq (test->sched_out, received_iq); g_object_unref (received_iq); received_iq = NULL; /* Wait for completion of: * - the second change_name (Snake) * - the first add_group (Hacker) * - the second add_group (School) * - the first remove_group (Hacker) * - the second remove_group (Friends) * - the third remove_group (Girlz) * - the third add_group (Friends) */ test->outstanding += 7; test_wait_pending (test); /* Check that the contact is back */ wocky_bare_contact_set_name (juliet, "Snake"); wocky_bare_contact_set_groups (juliet, (gchar **) groups_changed); g_assert (wocky_bare_contact_equal (contact, juliet)); test_close_both_porters (test); g_object_unref (roster); g_object_unref (juliet); teardown_test (test); } /* test editing a contact and then remove it from the roster */ static void test_edit_contact_remove (void) { WockyRoster *roster; test_data_t *test = setup_test (); WockyBareContact *contact; const gchar *groups[] = { "Friends", NULL }; test_open_both_connections (test); roster = create_initial_roster (test); contact = wocky_roster_get_contact (roster, "romeo@example.net"); g_assert (contact != NULL); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, iq_set_cb, test, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, ')', NULL); /* change contact's name */ wocky_roster_change_contact_name_async (roster, contact, "Badger", NULL, contact_name_changed_cb, test); test->outstanding += 1; test_wait_pending (test); g_assert (received_iq != NULL); /* The IQ has been sent but the server didn't send the upgrade and the reply * yet. * Now try to re-add the contact */ check_edit_roster_stanza (received_iq, "romeo@example.net", "Badger", "both", groups); /* remove the contact */ wocky_roster_remove_contact_async (roster, contact, NULL, contact_removed_cb, test); /* Now the server send the roster upgrade and reply to the change name IQ */ send_roster_update (test, "romeo@example.net", "Badger", "both", groups); ack_iq (test->sched_out, received_iq); g_object_unref (received_iq); received_iq = NULL; /* Wait for: * - completion of the change name operation * - server receives the "remove contact" IQ */ test->outstanding += 2; test_wait_pending (test); /* At this point, the contact has not been removed yet */ g_assert (wocky_roster_get_contact (roster, "romeo@example.net") != NULL); check_remove_contact_stanza (received_iq, "romeo@example.net"); /* Now the server send the roster upgrade and reply to the remove IQ */ send_roster_update (test, "romeo@example.net", NULL, "remove", NULL); ack_iq (test->sched_out, received_iq); g_object_unref (received_iq); received_iq = NULL; /* Wait for completion of the remove_contact operation */ test->outstanding += 1; test_wait_pending (test); /* Contact is now removed */ g_assert (wocky_roster_get_contact (roster, "romeo@example.net") == NULL); test_close_both_porters (test); g_object_unref (roster); teardown_test (test); } /* Change twice to the same name */ static void test_change_name_twice (void) { WockyRoster *roster; test_data_t *test = setup_test (); WockyBareContact *contact, *romeo; const gchar *groups[] = { "Friends", NULL }; test_open_both_connections (test); roster = create_initial_roster (test); contact = wocky_roster_get_contact (roster, "romeo@example.net"); g_assert (contact != NULL); romeo = create_romeo (); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, iq_set_cb, test, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, ')', NULL); /* Change's Romeo's name */ wocky_roster_change_contact_name_async (roster, contact, "Badger", NULL, contact_name_changed_cb, test); test->outstanding += 1; test_wait_pending (test); g_assert (received_iq != NULL); /* The IQ has been sent but the server didn't send the upgrade and the reply * yet */ g_assert (wocky_bare_contact_equal (contact, romeo)); check_edit_roster_stanza (received_iq, "romeo@example.net", "Badger", "both", groups); /* Try to reset the same name */ wocky_roster_change_contact_name_async (roster, contact, "Badger", NULL, contact_name_changed_cb, test); /* Now the server sends the roster upgrade and reply to the first IQ */ send_roster_update (test, "romeo@example.net", "Badger", "both", groups); ack_iq (test->sched_out, received_iq); g_object_unref (received_iq); received_iq = NULL; /* Wait for completion of the 2 change_name operations. * No IQ has been sent for the second as no change was needed. */ test->outstanding += 2; test_wait_pending (test); g_assert (received_iq == NULL); /* Name has been changed */ wocky_bare_contact_set_name (romeo, "Badger"); g_assert (wocky_bare_contact_equal (contact, romeo)); test_close_both_porters (test); g_object_unref (roster); g_object_unref (romeo); teardown_test (test); } /* Remove twice the same contact */ static void test_remove_contact_twice (void) { WockyRoster *roster; test_data_t *test = setup_test (); WockyBareContact *contact; const gchar *no_group[] = { NULL }; test_open_both_connections (test); roster = create_initial_roster (test); contact = wocky_roster_get_contact (roster, "romeo@example.net"); g_assert (contact != NULL); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, iq_set_cb, test, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, ')', NULL); /* Keep a ref on the contact as the roster will release its ref when * removing it */ g_object_ref (contact); wocky_roster_remove_contact_async (roster, contact, NULL, contact_removed_cb, test); test->outstanding += 1; test_wait_pending (test); g_assert (received_iq != NULL); /* The IQ has been sent but the server didn't send the upgrade and the reply * yet */ check_remove_contact_stanza (received_iq, "romeo@example.net"); /* Re-ask to remove the contact */ wocky_roster_remove_contact_async (roster, contact, NULL, contact_removed_cb, test); /* Now the server send the roster upgrade and reply to the remove IQ */ send_roster_update (test, "romeo@example.net", NULL, "remove", no_group); ack_iq (test->sched_out, received_iq); g_object_unref (received_iq); received_iq = NULL; /* Wait for completion of the 2 remove operations. No IQ has been sent for * the second as no change was needed. */ test->outstanding += 2; test_wait_pending (test); g_assert (received_iq == NULL); /* At this point, the contact has been removed */ g_assert (wocky_roster_get_contact (roster, "romeo@example.net") == NULL); test_close_both_porters (test); g_object_unref (contact); g_object_unref (roster); teardown_test (test); } /* Change name of a contact and try to remove and re-add it while change * operation is running */ static void test_change_name_remove_add (void) { WockyRoster *roster; test_data_t *test = setup_test (); WockyBareContact *contact, *romeo; const gchar *groups[] = { "Friends", NULL }; test_open_both_connections (test); roster = create_initial_roster (test); contact = wocky_roster_get_contact (roster, "romeo@example.net"); g_assert (contact != NULL); romeo = create_romeo (); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, iq_set_cb, test, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, ')', NULL); /* Change's Romeo's name */ wocky_roster_change_contact_name_async (roster, contact, "Badger", NULL, contact_name_changed_cb, test); test->outstanding += 1; test_wait_pending (test); g_assert (received_iq != NULL); /* The IQ has been sent but the server didn't send the upgrade and the reply * yet */ g_assert (wocky_bare_contact_equal (contact, romeo)); check_edit_roster_stanza (received_iq, "romeo@example.net", "Badger", "both", groups); /* Remove the contact */ wocky_roster_remove_contact_async (roster, contact, NULL, contact_removed_cb, test); /* Change our mind and re-add it */ wocky_roster_add_contact_async (roster, "romeo@example.net", "Badger", groups, NULL, contact_added_cb, test); /* Now the server sends the roster upgrade and reply to the first IQ */ send_roster_update (test, "romeo@example.net", "Badger", "both", groups); ack_iq (test->sched_out, received_iq); g_object_unref (received_iq); received_iq = NULL; /* Wait for completion of: * - the change name operation * - the remove operation * - the add operation * No IQ has been sent for the add and remove as no change was needed. */ test->outstanding += 3; test_wait_pending (test); g_assert (received_iq == NULL); /* Name has been changed */ wocky_bare_contact_set_name (romeo, "Badger"); g_assert (wocky_bare_contact_equal (contact, romeo)); test_close_both_porters (test); g_object_unref (roster); g_object_unref (romeo); teardown_test (test); } /* add 2 groups to the same contact */ static void test_add_two_groups (void) { WockyRoster *roster; test_data_t *test = setup_test (); WockyBareContact *contact, *romeo; const gchar *groups2[] = { "Friends", "School", NULL }; const gchar *groups3[] = { "Friends", "School", "Hackers", NULL }; test_open_both_connections (test); roster = create_initial_roster (test); contact = wocky_roster_get_contact (roster, "romeo@example.net"); g_assert (contact != NULL); romeo = create_romeo (); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, iq_set_cb, test, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, ')', NULL); /* Add a group to Romeo */ wocky_roster_contact_add_group_async (roster, contact, "School", NULL, contact_group_added_cb, test); test->outstanding += 1; test_wait_pending (test); g_assert (received_iq != NULL); /* The IQ has been sent but the server didn't send the upgrade and the reply * yet */ g_assert (wocky_bare_contact_equal (contact, romeo)); check_edit_roster_stanza (received_iq, "romeo@example.net", "Romeo", "both", groups2); /* Add another group */ wocky_roster_contact_add_group_async (roster, contact, "Hackers", NULL, contact_group_added_cb, test); /* Now the server sends the roster upgrade and reply to the first IQ */ send_roster_update (test, "romeo@example.net", "Romeo", "both", groups2); ack_iq (test->sched_out, received_iq); g_object_unref (received_iq); received_iq = NULL; /* Wait that: * - the first add_group operation is completed * - the server receives the IQ for the second add_group */ test->outstanding += 2; test_wait_pending (test); wocky_bare_contact_set_groups (romeo, (gchar **) groups2); g_assert (wocky_bare_contact_equal (contact, romeo)); check_edit_roster_stanza (received_iq, "romeo@example.net", "Romeo", "both", groups3); /* Server sends the roster upgrade and reply to the first IQ */ send_roster_update (test, "romeo@example.net", "Romeo", "both", groups3); ack_iq (test->sched_out, received_iq); g_object_unref (received_iq); received_iq = NULL; /* Wait second add_group operation is completed */ test->outstanding += 1; test_wait_pending (test); wocky_bare_contact_set_groups (romeo, (gchar **) groups3); g_assert (wocky_bare_contact_equal (contact, romeo)); test_close_both_porters (test); g_object_unref (roster); g_object_unref (romeo); teardown_test (test); } /* remove 2 groups from the same contact */ static void test_remove_two_groups (void) { WockyRoster *roster; test_data_t *test = setup_test (); WockyBareContact *contact, *juliet; const gchar *groups[] = { "Friends", NULL }; const gchar *no_group[] = { NULL }; test_open_both_connections (test); roster = create_initial_roster (test); contact = wocky_roster_get_contact (roster, "juliet@example.net"); g_assert (contact != NULL); juliet = create_juliet (); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, iq_set_cb, test, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, ')', NULL); /* Remove a group from Juliet */ wocky_roster_contact_remove_group_async (roster, contact, "Girlz", NULL, contact_group_removed_cb, test); test->outstanding += 1; test_wait_pending (test); g_assert (received_iq != NULL); /* The IQ has been sent but the server didn't send the upgrade and the reply * yet */ g_assert (wocky_bare_contact_equal (contact, juliet)); check_edit_roster_stanza (received_iq, "juliet@example.net", "Juliet", "to", groups); /* remove another group */ wocky_roster_contact_remove_group_async (roster, contact, "Friends", NULL, contact_group_removed_cb, test); /* Now the server sends the roster upgrade and reply to the first IQ */ send_roster_update (test, "juliet@example.net", "Juliet", "to", groups); ack_iq (test->sched_out, received_iq); g_object_unref (received_iq); received_iq = NULL; /* Wait that: * - the first remove_group operation is completed * - the server receives the IQ for the second remove_group */ test->outstanding += 2; test_wait_pending (test); wocky_bare_contact_set_groups (juliet, (gchar **) groups); g_assert (wocky_bare_contact_equal (contact, juliet)); check_edit_roster_stanza (received_iq, "juliet@example.net", "Juliet", "to", no_group); /* Server sends the roster upgrade and reply to the first IQ */ send_roster_update (test, "juliet@example.net", "Juliet", "to", no_group); ack_iq (test->sched_out, received_iq); g_object_unref (received_iq); received_iq = NULL; /* Wait second remove_group operation is completed */ test->outstanding += 1; test_wait_pending (test); wocky_bare_contact_set_groups (juliet, (gchar **) no_group); g_assert (wocky_bare_contact_equal (contact, juliet)); test_close_both_porters (test); g_object_unref (roster); g_object_unref (juliet); teardown_test (test); } /* Try to add twice the same contact */ static void test_add_contact_twice (void) { WockyRoster *roster; test_data_t *test = setup_test (); WockyBareContact *mercutio, *contact; const gchar *groups[] = { "Friends", "Badger", NULL }; test_open_both_connections (test); roster = create_initial_roster (test); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, iq_set_cb, test, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, ')', NULL); mercutio = create_mercutio (); /* Add the Mercutio to our roster */ wocky_roster_add_contact_async (roster, "mercutio@example.net", "Mercutio", groups, NULL, contact_added_cb, test); test->outstanding += 1; test_wait_pending (test); g_assert (received_iq != NULL); /* The IQ has been sent but the server didn't send the upgrade and the reply * yet */ /* contact is not added yet */ g_assert (wocky_roster_get_contact (roster, "mercutio@example.net") == NULL); check_add_contact_stanza (received_iq, "mercutio@example.net", "Mercutio", groups); /* Try to re-add the same contact */ wocky_roster_add_contact_async (roster, "mercutio@example.net", "Mercutio", groups, NULL, contact_added_cb, test); /* Now the server sends the roster upgrade and reply to the first IQ */ send_roster_update (test, "mercutio@example.net", "Mercutio", "none", groups); ack_iq (test->sched_out, received_iq); g_object_unref (received_iq); received_iq = NULL; /* Wait that the 2 add_contact operation are completed. No IQ is sent for * the second as nothing has changed. */ test->outstanding += 2; test_wait_pending (test); /* check if the contact has been actually added */ contact = wocky_roster_get_contact (roster, "mercutio@example.net"); g_assert (wocky_bare_contact_equal (contact, mercutio)); test_close_both_porters (test); g_object_unref (mercutio); g_object_unref (roster); teardown_test (test); } int main (int argc, char **argv) { int result; test_init (argc, argv); /* basic */ g_test_add_func ("/xmpp-roster/instantiation", test_instantiation); /* roster fetching */ g_test_add_func ("/xmpp-roster/fetch-roster-send-iq", test_fetch_roster_send_iq); g_test_add_func ("/xmpp-roster/fetch-roster-reply", test_fetch_roster_reply); /* receive upgrade from server */ g_test_add_func ("/xmpp-roster/roster-upgrade-add", test_roster_upgrade_add); g_test_add_func ("/xmpp-roster/roster-upgrade-remove", test_roster_upgrade_remove); g_test_add_func ("/xmpp-roster/roster-upgrade-change", test_roster_upgrade_change); /* edit roster */ g_test_add_func ("/xmpp-roster/roster-add-contact", test_roster_add_contact); g_test_add_func ("/xmpp-roster/roster-remove-contact", test_roster_remove_contact); g_test_add_func ("/xmpp-roster/roster-change-name", test_roster_change_name); g_test_add_func ("/xmpp-roster/contact-add-group", test_contact_add_group); g_test_add_func ("/xmpp-roster/contact-remove-group", test_contact_remove_group); /* start a edit operation while another edit operation is running */ g_test_add_func ("/xmpp-roster/remove-contact-re-add", test_remove_contact_re_add); g_test_add_func ("/xmpp-roster/remove-contact-edit", test_remove_contact_edit); g_test_add_func ("/xmpp-roster/multi-contact-edit", test_multi_contact_edit); g_test_add_func ("/xmpp-roster/edit-contact-remove", test_edit_contact_remove); g_test_add_func ("/xmpp-roster/change-name-twice", test_change_name_twice); g_test_add_func ("/xmpp-roster/remove-contact-twice", test_remove_contact_twice); g_test_add_func ("/xmpp-roster/change-name-add-remove", test_change_name_remove_add); g_test_add_func ("/xmpp-roster/add-two-groups", test_add_two_groups); g_test_add_func ("/xmpp-roster/remove-two-groups", test_remove_two_groups); g_test_add_func ("/xmpp-roster/add-contact-twice", test_add_contact_twice); result = g_test_run (); test_deinit (); return result; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-http-proxy-test.c0000664000175000017500000002334412212322440026451 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-test-stream.h" #include "wocky-test-helper.h" #include #include /* WockyHttpProxy isn't public API, so we need to be a bit sneaky to get the * header. */ #define WOCKY_COMPILATION #include #undef WOCKY_COMPILATION typedef enum { DOMAIN_NONE = 0, DOMAIN_G_IO_ERROR } HttpErrorDomain; typedef struct { const gchar *path; const gchar *reply; HttpErrorDomain domain; gint code; const gchar *username; const gchar *password; } HttpTestCase; typedef struct { GMainLoop *mainloop; GMainLoop *thread_mainloop; GCancellable *cancellable; GCancellable *thread_cancellable; GThread *thread; GSocketListener *listener; guint16 port; const HttpTestCase *test_case; } HttpTestData; static HttpTestCase test_cases[] = { { "/http-proxy/close-by-peer", "", DOMAIN_G_IO_ERROR, G_IO_ERROR_PROXY_FAILED }, { "/http-proxy/bad-reply", "BAD REPLY", DOMAIN_G_IO_ERROR, G_IO_ERROR_PROXY_FAILED }, { "/http-proxy/very-short-reply", "HTTP/1.\r\n\r\n", DOMAIN_G_IO_ERROR, G_IO_ERROR_PROXY_FAILED }, { "/http-proxy/short-reply", "HTTP/1.0\r\n\r\n", DOMAIN_G_IO_ERROR, G_IO_ERROR_PROXY_FAILED }, { "/http-proxy/http-404", "HTTP/1.0 404 Not Found\r\n" "Content-Type: text/html; charset=UTF-8\r\n" "Content-Length: 27\r\n" "\r\n" "

Hello

", DOMAIN_G_IO_ERROR, G_IO_ERROR_PROXY_FAILED }, { "/http-proxy/need-authentication", "HTTP/1.0 407 Proxy Authentication Required\r\n" "Content-Type: text/html; charset=UTF-8\r\n" "Content-Length: 27\r\n" "\r\n" "

Hello

", DOMAIN_G_IO_ERROR, G_IO_ERROR_PROXY_NEED_AUTH }, { "/http-proxy/success", "HTTP/1.0 200 OK\r\n" "\r\n", DOMAIN_NONE, 0 }, { "/http-proxy/authentication-failed", "HTTP/1.0 407 Proxy Authentication Required\r\n" "Content-Type: text/html; charset=UTF-8\r\n" "Content-Length: 27\r\n" "\r\n" "

Hello

", DOMAIN_G_IO_ERROR, G_IO_ERROR_PROXY_AUTH_FAILED, "username", "bad-password" }, { "/http-proxy/authenticated", "HTTP/1.0 200 OK\r\n" "\r\n", DOMAIN_NONE, 0, "Aladdin", "open sesame"}, }; static HttpTestData * tearup (const HttpTestCase *test_case) { HttpTestData *data; data = g_new0 (HttpTestData, 1); data->mainloop = g_main_loop_new (NULL, FALSE); data->cancellable = g_cancellable_new (); data->thread_cancellable = g_cancellable_new (); data->listener = g_socket_listener_new (); data->port = g_socket_listener_add_any_inet_port (data->listener, NULL, NULL); g_assert_cmpuint (data->port, !=, 0); data->test_case = test_case; return data; } static void run_in_thread (HttpTestData *data, GThreadFunc func) { data->thread = g_thread_new ("server_thread", func, data); g_assert (data->thread != NULL); } static gboolean tear_down_idle_cb (gpointer user_data) { HttpTestData *data = user_data; g_main_loop_quit (data->mainloop); return FALSE; } static void teardown (HttpTestData *data) { if (!g_cancellable_is_cancelled (data->cancellable)) g_cancellable_cancel (data->cancellable); if (!g_cancellable_is_cancelled (data->thread_cancellable)) g_cancellable_cancel (data->thread_cancellable); if (data->thread) g_thread_join (data->thread); if (g_main_loop_is_running (data->mainloop)) g_main_loop_quit (data->mainloop); g_idle_add_full (G_PRIORITY_LOW, tear_down_idle_cb, data, NULL); g_main_loop_run (data->mainloop); g_object_unref (data->cancellable); g_object_unref (data->thread_cancellable); g_object_unref (data->listener); g_main_loop_unref (data->mainloop); g_free (data); } static gboolean str_has_prefix_case (const gchar *str, const gchar *prefix) { return g_ascii_strncasecmp (prefix, str, strlen (prefix)) == 0; } static void test_http_proxy_instantiation (void) { GProxy *proxy; proxy = g_proxy_get_default_for_protocol ("http"); g_assert (G_IS_PROXY (proxy)); g_assert (WOCKY_IS_HTTP_PROXY (proxy)); g_object_unref (proxy); } static gpointer server_thread (gpointer user_data) { HttpTestData *data = user_data; GSocketConnection *conn; GDataInputStream *data_in; GOutputStream *out; gchar *buffer; gint has_host = 0; gint has_user_agent = 0; gint has_cred = 0; conn = g_socket_listener_accept (data->listener, NULL, data->thread_cancellable, NULL); g_assert (conn != NULL); data_in = g_data_input_stream_new ( g_io_stream_get_input_stream (G_IO_STREAM (conn))); g_data_input_stream_set_newline_type (data_in, G_DATA_STREAM_NEWLINE_TYPE_CR_LF); buffer = g_data_input_stream_read_line (data_in, NULL, data->thread_cancellable, NULL); g_assert_cmpstr (buffer, ==, "CONNECT to:443 HTTP/1.0"); do { g_free (buffer); buffer = g_data_input_stream_read_line (data_in, NULL, data->thread_cancellable, NULL); g_assert (buffer != NULL); if (str_has_prefix_case (buffer, "Host:")) { has_host++; g_assert_cmpstr (buffer, ==, "Host: to:443"); } else if (str_has_prefix_case (buffer, "User-Agent:")) has_user_agent++; else if (str_has_prefix_case (buffer, "Proxy-Authorization:")) { gchar *cred; gchar *base64_cred; const gchar *received_cred; has_cred++; g_assert (data->test_case->username != NULL); g_assert (data->test_case->password != NULL); cred = g_strdup_printf ("%s:%s", data->test_case->username, data->test_case->password); base64_cred = g_base64_encode ((guchar *) cred, strlen (cred)); g_free (cred); received_cred = buffer + 20; while (*received_cred == ' ') received_cred++; g_assert_cmpstr (base64_cred, ==, received_cred); g_free (base64_cred); } } while (buffer[0] != '\0'); g_assert_cmpuint (has_host, ==, 1); g_assert_cmpuint (has_user_agent, ==, 1); if (data->test_case->username != NULL) g_assert_cmpuint (has_cred, ==, 1); else g_assert_cmpuint (has_cred, ==, 0); g_free (buffer); out = g_io_stream_get_output_stream (G_IO_STREAM (conn)); g_assert (g_output_stream_write_all (out, data->test_case->reply, strlen (data->test_case->reply), NULL, data->thread_cancellable, NULL)); g_object_unref (data_in); g_object_unref (conn); return NULL; } static GQuark get_error_domain (HttpErrorDomain id) { GQuark domain = 0; switch (id) { case DOMAIN_G_IO_ERROR: domain = G_IO_ERROR; break; default: g_assert_not_reached (); } return domain; } static GSocketAddress * create_proxy_address (HttpTestData *data) { GSocketAddress *proxy_address; GInetAddress *inet_address; inet_address = g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4); proxy_address = g_proxy_address_new (inet_address, data->port, "http", "to", 443, data->test_case->username, data->test_case->password); g_object_unref (inet_address); return proxy_address; } static void check_result (const HttpTestCase *test_case, GSocketConnection *connection, GError *error) { if (test_case->domain != DOMAIN_NONE) { g_assert_error (error, get_error_domain (test_case->domain), test_case->code); g_error_free (error); } else { g_assert_no_error (error); g_object_unref (connection); } } static void test_http_proxy_with_data (gconstpointer user_data) { const HttpTestCase *test_case = user_data; HttpTestData *data; GSocketClient *client; GSocketAddress *proxy_address; GSocketConnection *connection; GError *error = NULL; data = tearup (test_case); run_in_thread (data, server_thread); client = g_socket_client_new (); proxy_address = create_proxy_address (data); connection = g_socket_client_connect (client, G_SOCKET_CONNECTABLE (proxy_address), data->cancellable, &error); g_object_unref (proxy_address); g_object_unref (client); check_result (test_case, connection, error); teardown (data); } static void connect_cb (GObject *source, GAsyncResult *result, gpointer user_data) { HttpTestData *data = user_data; GSocketConnection *connection; GError *error = NULL; connection = g_socket_client_connect_finish (G_SOCKET_CLIENT (source), result, &error); check_result (data->test_case, connection, error); g_main_loop_quit (data->mainloop); } static void test_http_proxy_with_data_async (gconstpointer user_data) { const HttpTestCase *test_case = user_data; HttpTestData *data; GSocketClient *client; GSocketAddress *proxy_address; data = tearup (test_case); run_in_thread (data, server_thread); client = g_socket_client_new (); proxy_address = create_proxy_address (data); g_socket_client_connect_async (client, G_SOCKET_CONNECTABLE (proxy_address), data->cancellable, connect_cb, data); g_object_unref (client); g_object_unref (proxy_address); g_main_loop_run (data->mainloop); teardown (data); } int main (int argc, char **argv) { int result; guint i; test_init (argc, argv); _wocky_http_proxy_get_type (); g_test_add_func ("/http-proxy/instantiation", test_http_proxy_instantiation); for (i = 0; i < G_N_ELEMENTS (test_cases); i++) { gchar *async_path; g_test_add_data_func (test_cases[i].path, test_cases + i, test_http_proxy_with_data); async_path = g_strdup_printf ("%s-async", test_cases[i].path); g_test_add_data_func (async_path, test_cases + i, test_http_proxy_with_data_async); g_free (async_path); } result = g_test_run (); test_deinit (); return result; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-utils-test.c0000664000175000017500000000317412005516162025460 0ustar00cassidycassidy00000000000000/* * wocky-utils-test.c - Tests for utility code * * Copyright © 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include static void test_compose_jid (void) { gchar *s = NULL; g_assert_cmpstr ((s = wocky_compose_jid ("juliet", "example.com", "Balcony")), ==, "juliet@example.com/Balcony"); g_free (s); g_assert_cmpstr ((s = wocky_compose_jid ("juliet", "example.com", NULL)), ==, "juliet@example.com"); g_free (s); g_assert_cmpstr ((s = wocky_compose_jid (NULL, "example.com", NULL)), ==, "example.com"); g_free (s); g_assert_cmpstr ((s = wocky_compose_jid (NULL, "example.com", "Server")), ==, "example.com/Server"); g_free (s); } int main (int argc, char **argv) { g_test_init (&argc, &argv, NULL); g_test_add_func ("/utils/compose-jid", test_compose_jid); return g_test_run (); } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-test-sasl-handler.c0000664000175000017500000000216012005516162026667 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-test-sasl-handler.h" #include static void auth_handler_iface_init (gpointer g_iface); G_DEFINE_TYPE_WITH_CODE (WockyTestSaslHandler, wocky_test_sasl_handler, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (WOCKY_TYPE_AUTH_HANDLER, auth_handler_iface_init)) static void wocky_test_sasl_handler_class_init (WockyTestSaslHandlerClass *klass) { } static void wocky_test_sasl_handler_init (WockyTestSaslHandler *self) { } static gboolean test_initial_response (WockyAuthHandler *handler, GString **initial_data, GError **error); static void auth_handler_iface_init (gpointer g_iface) { WockyAuthHandlerIface *iface = g_iface; iface->mechanism = "X-TEST"; iface->plain = FALSE; iface->initial_response_func = test_initial_response; } WockyTestSaslHandler * wocky_test_sasl_handler_new (void) { return g_object_new (WOCKY_TYPE_TEST_SASL_HANDLER, NULL); } static gboolean test_initial_response (WockyAuthHandler *handler, GString **initial_data, GError **error) { *initial_data = g_string_new ("open sesame"); return TRUE; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-test-sasl-handler.h0000644000175000017500000000222311544576223026705 0ustar00cassidycassidy00000000000000#ifndef _WOCKY_TEST_SASL_HANDLER_H #define _WOCKY_TEST_SASL_HANDLER_H #include G_BEGIN_DECLS #define WOCKY_TYPE_TEST_SASL_HANDLER wocky_test_sasl_handler_get_type() #define WOCKY_TEST_SASL_HANDLER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), WOCKY_TYPE_TEST_SASL_HANDLER, \ WockyTestSaslHandler)) #define WOCKY_TEST_SASL_HANDLER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), WOCKY_TYPE_TEST_SASL_HANDLER, \ WockyTestSaslHandlerClass)) #define WOCKY_IS_TEST_SASL_HANDLER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WOCKY_TYPE_TEST_SASL_HANDLER)) #define WOCKY_IS_TEST_SASL_HANDLER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), WOCKY_TYPE_TEST_SASL_HANDLER)) #define WOCKY_TEST_SASL_HANDLER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_TEST_SASL_HANDLER, \ WockyTestSaslHandlerClass)) typedef struct { GObject parent; } WockyTestSaslHandler; typedef struct { GObjectClass parent_class; } WockyTestSaslHandlerClass; GType wocky_test_sasl_handler_get_type (void); WockyTestSaslHandler* wocky_test_sasl_handler_new (void); G_END_DECLS #endif /* _WOCKY_TEST_SASL_HANDLER_H */ telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-scram-sha1-test.c0000664000175000017500000000742212005516162026257 0ustar00cassidycassidy00000000000000/* * wocky-scram-sha1-test.c - Test for wocky scram-sha1 * Copyright (C) 2010 Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "wocky-test-helper.h" typedef struct { guint32 seed; gchar *server; gchar *user; gchar *password; gchar *client_initial_response; gchar *server_initial_response; gchar *client_final_response; gchar *server_final_response; } testcase; static void test_scram_sha1 (testcase *test) { WockyAuthHandler *scram; GString *out, *in; GError *error = NULL; g_random_set_seed (test->seed); scram = WOCKY_AUTH_HANDLER (wocky_sasl_scram_new ( test->server, test->user, test->password)); g_assert (wocky_auth_handler_get_initial_response (scram, &out, &error)); g_assert_no_error (error); g_assert_cmpstr (test->client_initial_response, ==, out->str); g_string_free (out, TRUE); /* Initial challenge, response */ in = g_string_new (test->server_initial_response); (wocky_auth_handler_handle_auth_data (scram, in, &out, &error)); g_assert_no_error (error); g_assert_cmpstr (test->client_final_response, ==, out->str); g_string_free (in, TRUE); g_string_free (out, TRUE); in = g_string_new (test->server_final_response); out = NULL; g_assert (wocky_auth_handler_handle_auth_data (scram, in, &out, &error)); g_assert_no_error (error); g_assert (out == NULL); g_string_free (in, TRUE); g_assert (wocky_auth_handler_handle_success (scram, &error)); g_assert_no_error (error); g_object_unref (scram); } /* Some static tests as generated by trail of our current implementation, which * has been tested against real servers. These testcases are mostly here * because to prevent regressions and differences of output on different * platforms */ static testcase tests[] = { { 42, "example.com", "harry", "blaat", /* client first */ "n,,n=harry,r=ZtzhX7M96stcA2LzDpX1Lmr0Y7tH1JnHvK5BmRQsy5g=", /* server first */ "r=ZtzhX7M96stcA2LzDpX1Lmr0Y7tH1JnHvK5BmRQsy5g=deadfish," "s=snakes==,i=128", /* client final */ "c=biws,r=ZtzhX7M96stcA2LzDpX1Lmr0Y7tH1JnHvK5BmRQsy5g=deadfish," "p=0933cKmf/GHBIh+GYTROuRT78zM=", /* server final */ "v=zW58Ag+pg9C8lGkof3wb7/jvQQQ=" }, { 0xcafe, "eagle.co.uk", "watson", "dna", /* client first */ "n,,n=watson,r=xHkPPK3a6sJZYzbEJVq965vi70Mt9ZaFPI3PdSj8SEU=", /* server first */ "r=xHkPPK3a6sJZYzbEJVq965vi70Mt9ZaFPI3PdSj8SEU=doublehelix," "s=francis=,i=4096", /* client final */ "c=biws," "r=xHkPPK3a6sJZYzbEJVq965vi70Mt9ZaFPI3PdSj8SEU=doublehelix," "p=V4VHXC1JL++UDZWRg82mcP16Hdc=", /* server final */ "v=LYJrt3+nDh0XOEjKZC6DRccsnG0=" }, { 0, } }; int main (int argc, char **argv) { int i; test_init (argc, argv); for (i = 0; tests[i].seed != 0; i++) { gchar *name = g_strdup_printf ("/scram-sha1/test-%d", i); g_test_add_data_func (name, tests + i, (void (*)(const void *)) test_scram_sha1); g_free (name); } return g_test_run (); } telepathy-gabble-0.18.3/lib/ext/wocky/tests/threadlocal.supp0000644000175000017500000000013611544576223025244 0ustar00cassidycassidy00000000000000{ Memcheck:Leak fun:calloc fun:_dl_allocate_tls fun:pthread_create@@* } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-connector-test.c0000664000175000017500000041560012212322440026305 0ustar00cassidycassidy00000000000000#include #include #include #include #include #include #include #include #include #ifdef G_OS_WIN32 #include #include #else #include #include #include #include #include #endif #ifdef G_OS_UNIX #include #endif #include #include "wocky-test-connector-server.h" #include "test-resolver.h" #include "wocky-test-helper.h" #include "config.h" #ifdef G_LOG_DOMAIN #undef G_LOG_DOMAIN #endif #define G_LOG_DOMAIN "wocky-connector-test" #define SASL_DB_NAME "sasl-test.db" #define INVISIBLE_HOST "unreachable.host" #define VISIBLE_HOST "reachable.host" #define REACHABLE "127.0.0.1" #define UNREACHABLE "127.255.255.255" #define DUFF_H0ST "no_such_host.at.all" #define OLD_SSL TRUE #define OLD_JABBER TRUE #define XMPP_V1 FALSE #define STARTTLS FALSE #define CERT_CHECK_STRICT FALSE #define CERT_CHECK_LENIENT TRUE #define TLS_REQUIRED TRUE #define PLAINTEXT_OK FALSE #define QUIET TRUE #define NOISY FALSE #define TLS TRUE #define NOTLS FALSE #define PLAIN FALSE #define DIGEST TRUE #define PORT_XMPP 5222 #define PORT_NONE 0 #define CONNECTOR_INTERNALS_TEST "/connector/basic/internals" #define OK 0 #define CONNECTOR_OK { OK, OK, OK, OK, OK, OK } static GError *error = NULL; static GResolver *original; static GResolver *kludged; static GMainLoop *mainloop; enum { OP_CONNECT = 0, OP_REGISTER, OP_CANCEL, }; enum { S_NO_ERROR = 0, S_WOCKY_AUTH_ERROR, S_WOCKY_CONNECTOR_ERROR, S_WOCKY_XMPP_CONNECTION_ERROR, S_WOCKY_TLS_CERT_ERROR, S_WOCKY_XMPP_STREAM_ERROR, S_G_IO_ERROR, S_G_RESOLVER_ERROR, S_ANY_ERROR = 0xff }; #define MAP(x) case S_##x: return x static GQuark map_static_domain (gint domain) { switch (domain) { MAP (WOCKY_AUTH_ERROR); MAP (WOCKY_CONNECTOR_ERROR); MAP (WOCKY_XMPP_CONNECTION_ERROR); MAP (WOCKY_TLS_CERT_ERROR); MAP (WOCKY_XMPP_STREAM_ERROR); MAP (G_IO_ERROR); MAP (G_RESOLVER_ERROR); default: g_assert_not_reached (); } } #undef MAP typedef void (*test_setup) (gpointer); typedef struct _ServerParameters ServerParameters; struct _ServerParameters { struct { gboolean tls; gchar *auth_mech; gchar *version; } features; struct { ServerProblem sasl; ConnectorProblem conn; } problem; struct { gchar *user; gchar *pass; } auth; guint port; CertSet cert; /* Extra server for see-other-host problem */ ServerParameters *extra_server; /* Runtime */ TestConnectorServer *server; GIOChannel *channel; guint watch; }; typedef struct { gchar *desc; gboolean quiet; struct { int domain; int code; int fallback_code; gchar *mech; gchar *used_mech; gpointer xmpp; gchar *jid; gchar *sid; } result; ServerParameters server_parameters; struct { char *srv; guint port; char *host; char *addr; char *srvhost; } dns; struct { gboolean require_tls; struct { gchar *jid; gchar *pass; gboolean secure; gboolean tls; } auth; struct { gchar *host; guint port; gboolean jabber; gboolean ssl; gboolean lax_ssl; const gchar *ca; } options; int op; test_setup setup; } client; /* Runtime */ WockyConnector *connector; gboolean ok; } test_t; static void _set_connector_email_prop (test_t *test) { g_object_set (G_OBJECT (test->connector), "email", "foo@bar.org", NULL); } ServerParameters see_other_host_extra_server = { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, 8222 }; test_t tests[] = { /* basic connection test, no SRV record, no host or port supplied: */ /* { "/name/of/test", SUPPRESS_STDERR, // result of test: { DOMAIN, CODE, FALLBACK_CODE, AUTH_MECH_USED, XMPP_CONNECTION_PLACEHOLDER }, // When an error is expected it should match the domain and either // the given CODE or the FALLBACK_CODE (GIO over time became more // specific about the error codes it gave in certain conditions) // Server Details: { { TLS_SUPPORT, AUTH_MECH_OR_NULL_FOR_ALL }, { SERVER_PROBLEM..., CONNECTOR_PROBLEM... }, { USERNAME, PASSWORD }, SERVER_LISTEN_PORT, SERVER_CERT }, // Fake DNS Record: // SRV_HOSTs SRV record → { HOSTNAME, PORT } // HOSTs A record → IP_ADDRESS // SRV_HOSTs A record → IP_ADDR_OF_SRV_HOST { SRV_HOST, PORT, HOSTNAME, IP_ADDRESS, IP_ADDR_OF_SRV_HOST }, // Client Details { TLS_REQUIRED, { BARE_JID, PASSWORD, MUST_BE_DIGEST_AUTH, MUST_BE_SECURE }, { XMPP_HOSTNAME_OR_NULL, XMPP_PORT_OR_ZERO, OLD_JABBER, OLD_SSL } } SERVER_PROCESS_ID }, */ /* simple connection, followed by checks on all the internal state * * and get/set property methods to make sure they work */ { CONNECTOR_INTERNALS_TEST, NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", FALSE, NOTLS }, { NULL, 0 } } }, { "/connector/see-other-host", NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_SEE_OTHER_HOST, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP, CERT_STANDARD, &see_other_host_extra_server }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* No SRV or connect host specified */ { "/connector/basic/noserv/nohost/noport", NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* No SRV or connect host specified, connect port specified */ { "/connector/basic/noserv/nohost/port", NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, 8222 }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 8222 } } }, /* No SRV or connect host specified, bad port specified: FAIL */ { "/connector/basic/noserv/nohost/duffport", NOISY, { S_G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED, G_IO_ERROR_FAILED }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, 8222 }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 8221 } } }, /* No SRV record, connect host specified */ { "/connector/basic/noserv/host/noport", NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "schadenfreude.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { "schadenfreude.org", 0 } } }, /* No SRV record, connect host and port specified */ { "/connector/basic/noserv/host/port", NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, 5555 }, { NULL, 0, "meerkats.net", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { "meerkats.net", 5555 } } }, /* No SRV record, connect host and bad port specified: FAIL */ { "/connector/basic/noserv/host/duffport", NOISY, { S_G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED, G_IO_ERROR_FAILED }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, 5555 }, { NULL, 0, "meerkats.net", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { "meerkats.net", 5554 } } }, /* No SRV record, bad connect host: FAIL */ { "/connector/basic/noserv/duffhost/noport", NOISY, { S_G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { NULL, NULL }, PORT_NONE }, { NULL, 0, NULL, NULL, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { DUFF_H0ST, 0 } } }, /* No SRV record, bad connect host, port specified: FAIL */ { "/connector/basic/noserv/duffhost/port", NOISY, { S_G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { NULL, NULL }, PORT_NONE }, { NULL, 0, NULL, NULL, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { "still.no_such_host.at.all", 23 } } }, /* SRV record specified */ { "/connector/basic/serv/nohost/noport", NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, 5050 }, { "weasel-juice.org", 5050, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* SRV record specified, port specified: ignore SRV and connect */ { "/connector/basic/serv/nohost/port", NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, 5051 }, { "weasel-juice.org", 5050, "thud.org", UNREACHABLE, REACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 5051 } } }, /* SRV record specified, bad port: ignore SRV and FAIL */ { "/connector/basic/serv/nohost/duffport", NOISY, { S_G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED, G_IO_ERROR_FAILED }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, 5051 }, { "weasel-juice.org", 5050, "thud.org", UNREACHABLE, REACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 5050 } } }, /* SRV record, connect host specified: use connect host */ { "/connector/basic/serv/host/noport", NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", 5050, "thud.org", UNREACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { VISIBLE_HOST, 0 } } }, /* SRV, connect host and port specified: use host and port */ { "/connector/basic/serv/host/port", NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, 5656 }, { "weasel-juice.org", 5050, "thud.org", UNREACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { VISIBLE_HOST, 5656 } } }, /* SRV record, connect host, bad port: ignore SRV, FAIL */ { "/connector/basic/serv/host/duffport", NOISY, { S_G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED, G_IO_ERROR_FAILED }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, 5656 }, { "weasel-juice.org", 5050, "thud.org", UNREACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { VISIBLE_HOST, 5655 } } }, /* SRV record, bad connect host: use bad host and FAIL */ { "/connector/basic/serv/duffhost/noport", NOISY, { S_G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, REACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { DUFF_H0ST, 0 } } }, /* SRV record, bad connect host, connect port: use bad host and FAIL */ { "/connector/basic/serv/duffhost/port", NOISY, { S_G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, REACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { DUFF_H0ST, PORT_XMPP } } }, /* Facebook Chat has a broken SRV record: you ask for * _xmpp-client._tcp.chat.facebook.com, and it gives you back a CNAME! So * g_socket_client_connect_to_service() fails. But as it happens the real * result should have just been chat.facebook.com anyway, so Wocky tries to * fall back to that. * * So this test has a fake SRV record for an unreachable server, but * expects to succeed because it's listening on the default XMPP port on * our hypothetical 'weasel-juice.org'. */ { "/connector/basic/facebook-chat-srv-workaround", NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", UNREACHABLE, REACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* Further to the above test, this one tests the case where the fallback * doesn't work either. The server isn't listening anywhere (that's the * PORT_NONE in the server_parameters sub-struct), and thud.org (the result * of the SRV lookup) is unreachable. So the connection should fail. */ { "/connector/basic/duffserv/nohost/noport", NOISY, { S_G_IO_ERROR, G_IO_ERROR_NETWORK_UNREACHABLE, G_IO_ERROR_FAILED }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_NONE }, { "not.an.xmpp.server", PORT_XMPP, "thud.org", UNREACHABLE, REACHABLE }, { PLAINTEXT_OK, { "moose@not.an.xmpp.server", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* Bad SRV record, port specified, ignore SRV and connect to domain host */ { "/connector/basic/duffserv/nohost/port", NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, 5050 }, { "weasel-juice.org", PORT_XMPP, "thud.org", UNREACHABLE, REACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 5050 } } }, /* Bad SRV record, bad port specified, ignore SRV and FAIL */ { "/connector/basic/duffserv/nohost/duffport", NOISY, { S_G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED, G_IO_ERROR_FAILED }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, 5050 }, { "weasel-juice.org", PORT_XMPP, "thud.org", UNREACHABLE, REACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 5049 } } }, /* Bad SRV record, connect host specified, ignore SRV */ { "/connector/basic/duffserv/host/noport", NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", 5050, "thud.org", UNREACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { VISIBLE_HOST, 0 } } }, /* Bad SRV record, connect host and port given: ignore SRV */ { "/connector/basic/duffserv/host/port", NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, 5151 }, { "weasel-juice.org", 5050, "thud.org", UNREACHABLE, REACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { VISIBLE_HOST, 5151 } } }, /* Bad SRV record, connect host and bad port, ignore SRV and FAIL */ { "/connector/basic/duffserv/host/duffport", NOISY, { S_G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED, G_IO_ERROR_FAILED }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, 5151 }, { "weasel-juice.org", 5050, "thud.org", UNREACHABLE, REACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { VISIBLE_HOST, 5149 } } }, /* Bad SRV record, bad host and bad port: Just FAIL */ { "/connector/basic/duffserv/duffhost/noport", NOISY, { S_G_IO_ERROR, G_IO_ERROR_NETWORK_UNREACHABLE, G_IO_ERROR_FAILED }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", 5050, "thud.org", UNREACHABLE, REACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { INVISIBLE_HOST, 0 } } }, /*Bad SRV and connect host, ignore SRV and FAIL */ { "/connector/basic/duffserv/duffhost/port", NOISY, { S_G_IO_ERROR, G_IO_ERROR_NETWORK_UNREACHABLE, G_IO_ERROR_FAILED }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, 5151 }, { "weasel-juice.org", 5050, "thud.org", UNREACHABLE, REACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { INVISIBLE_HOST, 5151 } } }, /* ******************************************************************* * * that's it for the basic DNS/connection-logic tests * * now onto the post-tcp-connect stages: */ { "/connector/auth/secure/no-tlsplain/notls/nodigest", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NO_SUPPORTED_MECHANISMS, -1 }, { { NOTLS, "PLAIN" }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", DIGEST, TLS }, { NULL, 0 } } }, { "/connector/auth/secure/no-tlsplain/notls/digest", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { NOTLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", DIGEST, TLS }, { NULL, 0 } } }, { "/connector/auth/insecure/no-tlsplain/notls/nodigest", NOISY, { S_NO_ERROR, 0, 0, "PLAIN" }, { { NOTLS, "PLAIN" }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/auth/insecure/no-tlsplain/notls/digest", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { NOTLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* *************************************************************** * * This block of tests will fail as we don't advertise TLS support */ { "/connector/auth/insecure/no-tlsplain/notls/any", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_TLS_UNAVAILABLE, -1 }, { { NOTLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { TLS_REQUIRED, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0 } } }, { "/connector/auth/insecure/tlsplain/notls/any", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_TLS_UNAVAILABLE, -1 }, { { NOTLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { TLS_REQUIRED, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/auth/secure/no-tlsplain/notls/any", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_TLS_UNAVAILABLE, -1 }, { { NOTLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { TLS_REQUIRED, { "moose@weasel-juice.org", "something", TRUE, TLS }, { NULL, 0 } } }, { "/connector/auth/secure/tlsplain/notls/any", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_TLS_UNAVAILABLE, -1 }, { { NOTLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { TLS_REQUIRED, { "moose@weasel-juice.org", "something", TRUE, NOTLS }, { NULL, 0 } } }, /* **************************************************************** * * this will be a mix of failures and sucesses depending on whether * * we allow plain auth or not */ { "/connector/auth/secure/no-tlsplain/tls/plain", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NO_SUPPORTED_MECHANISMS, -1 }, { { TLS, "PLAIN" }, { SERVER_PROBLEM_INVALID_PASSWORD, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", DIGEST, TLS }, { NULL, 0 } } }, { "/connector/auth/secure/tlsplain/tls/plain", NOISY, { S_NO_ERROR, 0, 0, "PLAIN" }, { { TLS, "PLAIN" }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0 } } }, { "/connector/auth/insecure/no-tlsplain/tls/plain", NOISY, { S_NO_ERROR, 0, 0, "PLAIN" }, { { TLS, "PLAIN" }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", DIGEST, NOTLS }, { NULL, 0 } } }, { "/connector/auth/insecure/tlsplain/tls/plain", NOISY, { S_NO_ERROR, 0, 0, "PLAIN" }, { { TLS, "PLAIN" }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/tls+auth/secure/no-tlsplain/tls/plain", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NO_SUPPORTED_MECHANISMS, -1 }, { { TLS, "PLAIN" }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", DIGEST, TLS }, { NULL, 0 } } }, { "/connector/tls+auth/secure/tlsplain/tls/plain", NOISY, { S_NO_ERROR, 0, 0, "PLAIN" }, { { TLS, "PLAIN" }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0 } } }, { "/connector/tls+auth/insecure/no-tlsplain/tls/plain", NOISY, { S_NO_ERROR, 0, 0, "PLAIN" }, { { TLS, "PLAIN" }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", DIGEST, NOTLS }, { NULL, 0 } } }, { "/connector/tls+auth/insecure/tlsplain/tls/plain", NOISY, { S_NO_ERROR, 0, 0, "PLAIN" }, { { TLS, "PLAIN" }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* **************************************************************** * * these should all be digest auth successes */ { "/connector/auth/secure/no-tlsplain/tls/digest", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", DIGEST, TLS }, { NULL, 0 } } }, { "/connector/auth/secure/tlsplain/tls/digest", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0 } } }, { "/connector/auth/insecure/no-tlsplain/tls/digest", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", DIGEST, NOTLS }, { NULL, 0 } } }, { "/connector/auth/insecure/tlsplain/tls/digest", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/tls+auth/secure/no-tlsplain/tls/digest", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", DIGEST, TLS }, { NULL, 0 } } }, { "/connector/tls+auth/secure/tlsplain/tls/digest", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0 } } }, { "/connector/tls+auth/insecure/no-tlsplain/tls/digest", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", DIGEST, NOTLS }, { NULL, 0 } } }, { "/connector/tls+auth/insecure/tlsplain/tls/digest", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* ***************************************************************** * * SASL problems */ { "/connector/problem/sasl/bad-pass", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_FAILURE, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_INVALID_PASSWORD, CONNECTOR_OK }, { "foo", "bar" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "foo@weasel-juice.org", "notbar", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/problem/sasl/bad-user", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_FAILURE, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_INVALID_USERNAME, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "caribou@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/problem/sasl/no-sasl", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NOT_SUPPORTED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_SASL, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/problem/sasl/no-mechanisms", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NOT_SUPPORTED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_MECHANISMS, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/problem/sasl/bad-mechanism", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NO_SUPPORTED_MECHANISMS, -1 }, { { TLS, "omg-poniez" }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* ********************************************************************* */ /* TLS error conditions */ { "/connector/problem/tls/refused", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_TLS_REFUSED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_TLS_REFUSED, OK, OK, OK, OK} }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* ********************************************************************* * * Invalid JID */ { "/connector/problem/jid/invalid", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_BAD_JID, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_NONE }, { NULL, 0, "thud.org", REACHABLE }, { PLAINTEXT_OK, { "bla@h@_b&la<>h", "something", PLAIN, NOTLS }, { "weasel-juice.org", PORT_XMPP } } }, { "/connector/problem/jid/domainless", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_BAD_JID, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_NONE }, { "weasel-juice.org", 5001, "thud.org", REACHABLE, REACHABLE }, { PLAINTEXT_OK, { "moose@", "something", PLAIN, NOTLS }, { "weasel-juice.org", 0 } } }, /* ********************************************************************* * * XMPP errors */ { "/connector/problem/xmpp/version/0.x", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_NON_XMPP_V1_SERVER, -1 }, { { TLS, NULL, "0.9" }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* we actually tolerate > 1.0 versions */ { "/connector/problem/xmpp/version/1.x", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL, "1.1" }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/problem/xmpp/error/host-unknown", NOISY, { S_WOCKY_XMPP_STREAM_ERROR, WOCKY_XMPP_STREAM_ERROR_HOST_UNKNOWN, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OTHER_HOST, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/problem/xmpp/error/tls-load", NOISY, { S_WOCKY_XMPP_STREAM_ERROR, WOCKY_XMPP_STREAM_ERROR_RESOURCE_CONSTRAINT, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_TLS_LOAD, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/problem/xmpp/error/bind-conflict", NOISY, { S_WOCKY_XMPP_STREAM_ERROR, WOCKY_XMPP_STREAM_ERROR_CONFLICT, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, BIND_PROBLEM_CLASH, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/problem/xmpp/error/session-fail", NOISY, { S_WOCKY_XMPP_STREAM_ERROR, WOCKY_XMPP_STREAM_ERROR_RESOURCE_CONSTRAINT, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, SESSION_PROBLEM_NO_SESSION, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/problem/xmpp/features", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_BAD_FEATURES, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_FEATURES, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* WOCKY_CONNECTOR_ERROR_BIND_UNAVAILABLE */ { "/connector/problem/xmpp/no-bind", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_BIND_UNAVAILABLE, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_CANNOT_BIND, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* WOCKY_CONNECTOR_ERROR_BIND_INVALID */ { "/connector/problem/xmpp/bind/invalid", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_BIND_INVALID, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, BIND_PROBLEM_INVALID, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* WOCKY_CONNECTOR_ERROR_BIND_DENIED */ { "/connector/problem/xmpp/bind/denied", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_BIND_DENIED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, BIND_PROBLEM_DENIED, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* WOCKY_CONNECTOR_ERROR_BIND_CONFLICT */ { "/connector/problem/xmpp/bind/conflict", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_BIND_CONFLICT, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, BIND_PROBLEM_CONFLICT, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* WOCKY_CONNECTOR_ERROR_BIND_REJECTED */ { "/connector/problem/xmpp/bind/rejected", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_BIND_REJECTED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, BIND_PROBLEM_REJECTED, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* WOCKY_CONNECTOR_ERROR_BIND_FAILED */ { "/connector/problem/xmpp/bind/failed", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_BIND_FAILED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, BIND_PROBLEM_FAILED, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/problem/xmpp/bind/nonsense", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_BIND_FAILED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, BIND_PROBLEM_NONSENSE, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/problem/xmpp/bind/no-jid", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, BIND_PROBLEM_NO_JID, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/problem/xmpp/session/none", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_NO_SESSION, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* WOCKY_CONNECTOR_ERROR_SESSION_FAILED */ { "/connector/problem/xmpp/session/failed", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_SESSION_FAILED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, SESSION_PROBLEM_FAILED, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* WOCKY_CONNECTOR_ERROR_SESSION_DENIED */ { "/connector/problem/xmpp/session/denied", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_SESSION_DENIED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, SESSION_PROBLEM_DENIED, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* WOCKY_CONNECTOR_ERROR_SESSION_CONFLICT */ { "/connector/problem/xmpp/session/conflict", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_SESSION_CONFLICT, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, SESSION_PROBLEM_CONFLICT, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* WOCKY_CONNECTOR_ERROR_SESSION_REJECTED */ { "/connector/problem/xmpp/session/rejected", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_SESSION_REJECTED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, SESSION_PROBLEM_REJECTED, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/problem/xmpp/session/nonsense", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_SESSION_FAILED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, SESSION_PROBLEM_NONSENSE, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/econnreset/server-start", NOISY, { S_ANY_ERROR, 0 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, SERVER_DEATH_SERVER_START, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/econnreset/client-open", NOISY, { S_ANY_ERROR, 0 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, SERVER_DEATH_CLIENT_OPEN, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/econnreset/server-open", NOISY, { S_ANY_ERROR, 0 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, SERVER_DEATH_SERVER_OPEN, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/econnreset/features", NOISY, { S_ANY_ERROR, 0 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, SERVER_DEATH_FEATURES, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/econnreset/tls-negotiate", QUIET, { S_ANY_ERROR, 0 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, SERVER_DEATH_TLS_NEG, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* ******************************************************************** */ /* quirks */ { "/connector/google/domain-discovery/require", QUIET, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_REQUIRE_GOOGLE_JDD, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, { "/connector/google/domain-discovery/dislike", QUIET, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_FAILURE, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_DISLIKE_GOOGLE_JDD, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 } } }, /* ******************************************************************** */ /* XEP 0077 */ { "/connector/xep77/register/ok", NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 }, OP_REGISTER } }, { "/connector/xep77/register/no-args", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_REGISTRATION_EMPTY, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, OK, OK, XEP77_PROBLEM_NO_ARGS } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 }, OP_REGISTER } }, { "/connector/xep77/register/email-missing", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_REGISTRATION_REJECTED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, OK, OK, XEP77_PROBLEM_EMAIL_ARG } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 }, OP_REGISTER } }, { "/connector/xep77/register/unknown-arg", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_REGISTRATION_UNSUPPORTED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, OK, OK, XEP77_PROBLEM_STRANGE_ARG } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 }, OP_REGISTER } }, { "/connector/xep77/register/unknown+email-args", NOISY, { S_ANY_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, OK, OK, XEP77_PROBLEM_STRANGE_ARG|XEP77_PROBLEM_EMAIL_ARG } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 }, OP_REGISTER } }, { "/connector/xep77/register/email-arg-ok", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, OK, OK, XEP77_PROBLEM_EMAIL_ARG } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 }, OP_REGISTER, (test_setup)_set_connector_email_prop } }, { "/connector/xep77/register/email-arg-ok/unknown-arg", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_REGISTRATION_UNSUPPORTED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, OK, OK, XEP77_PROBLEM_EMAIL_ARG|XEP77_PROBLEM_STRANGE_ARG } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 }, OP_REGISTER, (test_setup)_set_connector_email_prop } }, { "/connector/xep77/register/fail/conflict", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_REGISTRATION_CONFLICT, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, OK, OK, XEP77_PROBLEM_FAIL_CONFLICT } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 }, OP_REGISTER } }, { "/connector/xep77/register/fail/other", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_REGISTRATION_REJECTED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, OK, OK, XEP77_PROBLEM_FAIL_REJECTED } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 }, OP_REGISTER } }, { "/connector/xep77/register/nonsense", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_REGISTRATION_FAILED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, OK, OK, XEP77_PROBLEM_QUERY_NONSENSE } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 }, OP_REGISTER } }, { "/connector/xep77/register/already/get", NOISY, { S_NO_ERROR, 0 , 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, OK, OK, XEP77_PROBLEM_QUERY_ALREADY } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 }, OP_REGISTER } }, { "/connector/xep77/register/already/set", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, OK, OK, XEP77_PROBLEM_ALREADY } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 }, OP_REGISTER } }, { "/connector/xep77/register/not-available", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_REGISTRATION_UNAVAILABLE, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, OK, OK, XEP77_PROBLEM_NOT_AVAILABLE } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 }, OP_REGISTER } }, /* ******************************************************************** */ { "/connector/xep77/cancel/ok", NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 }, OP_CANCEL } }, { "/connector/xep77/cancel/denied", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_UNREGISTER_DENIED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, OK, OK, XEP77_PROBLEM_CANCEL_FAILED } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 }, OP_CANCEL } }, { "/connector/xep77/cancel/disabled", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_UNREGISTER_DENIED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, OK, OK, XEP77_PROBLEM_CANCEL_DISABLED } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 }, OP_CANCEL } }, { "/connector/xep77/cancel/rejected", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_UNREGISTER_FAILED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, OK, OK, XEP77_PROBLEM_CANCEL_REJECTED } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 }, OP_CANCEL } }, { "/connector/xep77/cancel/stream-closed", NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { OK, OK, OK, OK, OK, XEP77_PROBLEM_CANCEL_STREAM } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0 }, OP_CANCEL } }, /* ******************************************************************** */ /* old school jabber tests (pre XMPP 1.0) */ { "/connector/jabber/no-ssl/auth/digest", NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER } } }, { "/connector/jabber/no-ssl/auth/reject", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NOT_AUTHORIZED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER, OK, OK, OK, OK } }, { "moose", "blerg" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER } } }, { "/connector/jabber/no-ssl/auth/unavailable", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NOT_SUPPORTED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER, OK, OK, OK, JABBER_PROBLEM_AUTH_NIH } }, { "moose", "blerg" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER } } }, { "/connector/jabber/no-ssl/auth/bind-error", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_RESOURCE_CONFLICT, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER, OK, OK, OK, JABBER_PROBLEM_AUTH_BIND } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER } } }, { "/connector/jabber/no-ssl/auth/incomplete", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NO_CREDENTIALS, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER, OK, OK, OK, JABBER_PROBLEM_AUTH_PARTIAL } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER } } }, { "/connector/jabber/no-ssl/auth/failure", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_FAILURE, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER, OK, OK, OK, JABBER_PROBLEM_AUTH_FAILED } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER } } }, { "/connector/jabber/no-ssl/auth/bizarre", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER, OK, OK, OK, JABBER_PROBLEM_AUTH_STRANGE } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER } } }, { "/connector/jabber/no-ssl/auth/nonsense", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER, OK, OK, OK, JABBER_PROBLEM_AUTH_NONSENSE } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER } } }, { "/connector/jabber/no-ssl/auth/no-mechs", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NO_SUPPORTED_MECHANISMS, -1 }, { { TLS, "none" }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER } } }, { "/connector/jabber/no-ssl/auth/plain", NOISY, { S_NO_ERROR, }, { { TLS, "password" }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER } } }, { "/connector/jabber/no-ssl/auth/plain/rejected", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NOT_AUTHORIZED, -1 }, { { TLS, "password" }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER, OK, OK, OK, JABBER_PROBLEM_AUTH_REJECT } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER } } }, { "/connector/jabber/no-ssl/auth/digest/rejected", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NOT_AUTHORIZED, -1 }, { { TLS, "digest" }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER, OK, OK, OK, JABBER_PROBLEM_AUTH_REJECT } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER } } }, { "/connector/jabber/no-ssl/auth/old+sasl", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_AUTH_FEATURE, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER } } }, { "/connector/jabber/no-ssl/auth/old-sasl", NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_SASL, { XMPP_PROBLEM_OLD_AUTH_FEATURE, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER } } }, /* ******************************************************************** */ /* old SSL */ { "/connector/jabber/ssl/auth/digest", NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER|XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER, OLD_SSL } } }, { "/connector/jabber/ssl/auth/reject", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NOT_AUTHORIZED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER|XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "blerg" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER, OLD_SSL } } }, { "/connector/jabber/ssl/auth/unavailable", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NOT_SUPPORTED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER|XMPP_PROBLEM_OLD_SSL, OK, OK, OK, JABBER_PROBLEM_AUTH_NIH } }, { "moose", "blerg" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER, OLD_SSL } } }, { "/connector/jabber/ssl/auth/bind-error", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_RESOURCE_CONFLICT, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER|XMPP_PROBLEM_OLD_SSL, OK, OK, OK, JABBER_PROBLEM_AUTH_BIND } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER, OLD_SSL } } }, { "/connector/jabber/ssl/auth/incomplete", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NO_CREDENTIALS, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER|XMPP_PROBLEM_OLD_SSL, OK, OK, OK, JABBER_PROBLEM_AUTH_PARTIAL } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER, OLD_SSL } } }, { "/connector/jabber/ssl/auth/failure", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_FAILURE, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER|XMPP_PROBLEM_OLD_SSL, OK, OK, OK, JABBER_PROBLEM_AUTH_FAILED } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER, OLD_SSL } } }, { "/connector/jabber/ssl/auth/bizarre", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER|XMPP_PROBLEM_OLD_SSL, OK, OK, OK, JABBER_PROBLEM_AUTH_STRANGE } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER, OLD_SSL } } }, { "/connector/jabber/ssl/auth/nonsense", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER|XMPP_PROBLEM_OLD_SSL, OK, OK, OK, JABBER_PROBLEM_AUTH_NONSENSE } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER, OLD_SSL } } }, { "/connector/jabber/ssl/auth/no-mechs", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NO_SUPPORTED_MECHANISMS, -1 }, { { TLS, "none" }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER|XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER, OLD_SSL } } }, { "/connector/jabber/ssl/auth/plain", NOISY, { S_NO_ERROR, }, { { TLS, "password" }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER|XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER, OLD_SSL } } }, { "/connector/jabber/ssl/auth/plain/rejected", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NOT_AUTHORIZED, -1 }, { { TLS, "password" }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER|XMPP_PROBLEM_OLD_SSL, OK, OK, OK, JABBER_PROBLEM_AUTH_REJECT } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER, OLD_SSL } } }, { "/connector/jabber/ssl/auth/digest/rejected", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NOT_AUTHORIZED, -1 }, { { TLS, "digest" }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SERVER|XMPP_PROBLEM_OLD_SSL, OK, OK, OK, JABBER_PROBLEM_AUTH_REJECT } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER, OLD_SSL } } }, { "/connector/jabber/ssl/auth/old+sasl", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_AUTH_FEATURE|XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER, OLD_SSL } } }, { "/connector/jabber/ssl/auth/old-sasl", NOISY, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_SASL, { XMPP_PROBLEM_OLD_AUTH_FEATURE|XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, OLD_JABBER, OLD_SSL } } }, /* ******************************************************************* */ /* duplicate earlier blocks of tests, but with old SSL */ { "/connector+ssl/auth/secure/no-tlsplain/notls/nodigest", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NO_SUPPORTED_MECHANISMS, -1 }, { { NOTLS, "PLAIN" }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", DIGEST, TLS }, { NULL, 0, OLD_JABBER, OLD_SSL } } }, { "/connector+ssl/auth/secure/no-tlsplain/notls/digest", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { NOTLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", DIGEST, TLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/auth/insecure/no-tlsplain/notls/nodigest", NOISY, { S_NO_ERROR, 0, 0, "PLAIN" }, { { NOTLS, "PLAIN" }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/auth/insecure/no-tlsplain/notls/digest", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { NOTLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, /* **************************************************************** * * this will be a mix of failures and sucesses depending on whether * * we allow plain auth or not */ { "/connector+ssl/auth/secure/no-tlsplain/tls/plain", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NO_SUPPORTED_MECHANISMS, -1 }, { { TLS, "PLAIN" }, { SERVER_PROBLEM_INVALID_PASSWORD, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", DIGEST, TLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/auth/secure/tlsplain/tls/plain", NOISY, { S_NO_ERROR, 0, 0, "PLAIN" }, { { TLS, "PLAIN" }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/auth/insecure/no-tlsplain/tls/plain", NOISY, { S_NO_ERROR, 0, 0, "PLAIN" }, { { TLS, "PLAIN" }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", DIGEST, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/auth/insecure/tlsplain/tls/plain", NOISY, { S_NO_ERROR, 0, 0, "PLAIN" }, { { TLS, "PLAIN" }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/tls+auth/secure/no-tlsplain/tls/plain", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NO_SUPPORTED_MECHANISMS, -1 }, { { TLS, "PLAIN" }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", DIGEST, TLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/tls+auth/secure/tlsplain/tls/plain", NOISY, { S_NO_ERROR, 0, 0, "PLAIN" }, { { TLS, "PLAIN" }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/tls+auth/insecure/no-tlsplain/tls/plain", NOISY, { S_NO_ERROR, 0, 0, "PLAIN" }, { { TLS, "PLAIN" }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", DIGEST, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/tls+auth/insecure/tlsplain/tls/plain", NOISY, { S_NO_ERROR, 0, 0, "PLAIN" }, { { TLS, "PLAIN" }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, /* **************************************************************** * * these should all be digest auth successes */ { "/connector+ssl/auth/secure/no-tlsplain/tls/digest", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", DIGEST, TLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/auth/secure/tlsplain/tls/digest", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/auth/insecure/no-tlsplain/tls/digest", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", DIGEST, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/auth/insecure/tlsplain/tls/digest", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/tls+auth/secure/no-tlsplain/tls/digest", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", DIGEST, TLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/tls+auth/secure/tlsplain/tls/digest", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/tls+auth/insecure/no-tlsplain/tls/digest", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", DIGEST, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/tls+auth/insecure/tlsplain/tls/digest", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, /* ***************************************************************** * * SASL problems */ { "/connector+ssl/problem/sasl/bad-pass", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_FAILURE, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_INVALID_PASSWORD, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "foo", "bar" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "foo@weasel-juice.org", "notbar", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/problem/sasl/bad-user", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_FAILURE, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_INVALID_USERNAME, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "caribou@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/problem/sasl/no-sasl", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NOT_SUPPORTED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_SASL, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/problem/sas/no-mechanisms", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NOT_SUPPORTED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_MECHANISMS, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/problem/sasl/bad-mechanism", NOISY, { S_WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NO_SUPPORTED_MECHANISMS, -1 }, { { TLS, "omg-poniez" }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/problem/xmpp/version/0.x", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_NON_XMPP_V1_SERVER, -1 }, { { TLS, NULL, "0.9" }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, /* we actually tolerate > 1.0 versions */ { "/connector+ssl/problem/xmpp/version/1.x", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL, "1.1" }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/problem/xmpp/error/host-unknown", NOISY, { S_WOCKY_XMPP_STREAM_ERROR, WOCKY_XMPP_STREAM_ERROR_HOST_UNKNOWN, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OTHER_HOST|XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/problem/xmpp/error/bind-conflict", NOISY, { S_WOCKY_XMPP_STREAM_ERROR, WOCKY_XMPP_STREAM_ERROR_CONFLICT, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, BIND_PROBLEM_CLASH, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/problem/xmpp/error/session-fail", NOISY, { S_WOCKY_XMPP_STREAM_ERROR, WOCKY_XMPP_STREAM_ERROR_RESOURCE_CONSTRAINT, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, SESSION_PROBLEM_NO_SESSION, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/problem/xmpp/features", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_BAD_FEATURES, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_FEATURES|XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, /* WOCKY_CONNECTOR_ERROR_BIND_UNAVAILABLE */ { "/connector+ssl/problem/xmpp/no-bind", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_BIND_UNAVAILABLE, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_CANNOT_BIND|XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, /* WOCKY_CONNECTOR_ERROR_BIND_INVALID */ { "/connector+ssl/problem/xmpp/bind/invalid", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_BIND_INVALID, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, BIND_PROBLEM_INVALID, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, /* WOCKY_CONNECTOR_ERROR_BIND_DENIED */ { "/connector+ssl/problem/xmpp/bind/denied", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_BIND_DENIED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, BIND_PROBLEM_DENIED, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, /* WOCKY_CONNECTOR_ERROR_BIND_CONFLICT */ { "/connector+ssl/problem/xmpp/bind/conflict", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_BIND_CONFLICT, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, BIND_PROBLEM_CONFLICT, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, /* WOCKY_CONNECTOR_ERROR_BIND_REJECTED */ { "/connector+ssl/problem/xmpp/bind/rejected", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_BIND_REJECTED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, BIND_PROBLEM_REJECTED, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, /* WOCKY_CONNECTOR_ERROR_BIND_FAILED */ { "/connector+ssl/problem/xmpp/bind/failed", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_BIND_FAILED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, BIND_PROBLEM_FAILED, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/problem/xmpp/bind/nonsense", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_BIND_FAILED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, BIND_PROBLEM_NONSENSE, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/problem/xmpp/bind/no-jid", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, BIND_PROBLEM_NO_JID, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/problem/xmpp/session/none", NOISY, { S_NO_ERROR, 0, 0, "DIGEST-MD5" }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_NO_SESSION|XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, /* WOCKY_CONNECTOR_ERROR_SESSION_FAILED */ { "/connector+ssl/problem/xmpp/session/failed", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_SESSION_FAILED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, SESSION_PROBLEM_FAILED, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, /* WOCKY_CONNECTOR_ERROR_SESSION_DENIED */ { "/connector+ssl/problem/xmpp/session/denied", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_SESSION_DENIED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, SESSION_PROBLEM_DENIED, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, /* WOCKY_CONNECTOR_ERROR_SESSION_CONFLICT */ { "/connector+ssl/problem/xmpp/session/conflict", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_SESSION_CONFLICT, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, SESSION_PROBLEM_CONFLICT, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, /* WOCKY_CONNECTOR_ERROR_SESSION_REJECTED */ { "/connector+ssl/problem/xmpp/session/rejected", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_SESSION_REJECTED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, SESSION_PROBLEM_REJECTED, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/problem/xmpp/session/nonsense", NOISY, { S_WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_SESSION_FAILED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, SESSION_PROBLEM_NONSENSE, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/econnreset/server-start", NOISY, { S_ANY_ERROR, 0 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, SERVER_DEATH_SERVER_START, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/econnreset/client-open", NOISY, { S_ANY_ERROR, 0 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, SERVER_DEATH_CLIENT_OPEN, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/econnreset/server-open", NOISY, { S_ANY_ERROR, 0 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, SERVER_DEATH_SERVER_OPEN, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/econnreset/features", NOISY, { S_ANY_ERROR, 0 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, SERVER_DEATH_FEATURES, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector+ssl/econnreset/ssl-negotiate", QUIET, { S_ANY_ERROR, 0 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, SERVER_DEATH_TLS_NEG, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, NOTLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, /* ********************************************************************* */ /* certificate verification tests */ { "/connector/cert-verification/tls/nohost/ok", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1 } } }, { "/connector/multica-verification/tls/nohost/ok", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, STARTTLS, CERT_CHECK_STRICT, TLS_CA_DIR } } }, { "/connector/cert-verification/tls/host/ok", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "thud.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { "thud.org", 0, XMPP_V1 } } }, { "/connector/cert-verification/tls/nohost/fail/name-mismatch", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_NAME_MISMATCH, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "tomato-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@tomato-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1 } } }, { "/connector/cert-verification/tls/host/fail/name-mismatch", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_NAME_MISMATCH, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "tomato-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@tomato-juice.org", "something", PLAIN, TLS }, { "tomato-juice.org", 0, XMPP_V1 } } }, { "/connector/cert-verification/tls/expired/fail", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_EXPIRED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP, CERT_EXPIRED }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1 } } }, { "/connector/cert-verification/tls/inactive/fail", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_NOT_ACTIVE, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP, CERT_NOT_YET }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1 } } }, { "/connector/cert-verification/tls/selfsigned/fail", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_INVALID, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP, CERT_SELFSIGN }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1 } } }, { "/connector/cert-verification/tls/unknown/fail", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_SIGNER_UNKNOWN, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP, CERT_UNKNOWN }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1 } } }, /* This is a combination of the above test * (/connector/cert-verification/tls/unknown/fail) and * /connector/cert-verification/tls/host/fail/name-mismatch. It checks that * Wocky considers a hostname mismatch more erroneous than the certificate * being broken. */ { "/connector/cert-verification/tls/host/fail/name-mismatch-and-unknown", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_NAME_MISMATCH, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP, CERT_UNKNOWN }, { "tomato-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@tomato-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1 } } }, { "/connector/cert-verification/tls/wildcard/ok", QUIET, { S_NO_ERROR }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP, CERT_WILDCARD }, { "foo.weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { TLS_REQUIRED, { "moose@foo.weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, STARTTLS, CERT_CHECK_STRICT, TLS_CA_DIR } } }, { "/connector/cert-verification/tls/wildcard/level-mismatch/fail", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_NAME_MISMATCH, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP, CERT_WILDCARD }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, STARTTLS, CERT_CHECK_STRICT, TLS_CA_DIR } } }, { "/connector/cert-verification/tls/wildcard/glob-mismatch/fail", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_NAME_MISMATCH, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP, CERT_WILDCARD }, { "foo.diesel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { TLS_REQUIRED, { "moose@foo.diesel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, STARTTLS, CERT_CHECK_STRICT, TLS_CA_DIR } } }, { "/connector/cert-verification/tls/bad-wildcard/fail", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_NAME_MISMATCH, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP, CERT_BADWILD }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { TLS_REQUIRED, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, STARTTLS, CERT_CHECK_STRICT, TLS_CA_DIR } } }, { "/connector/cert-verification/tls/revoked/fail", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_REVOKED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP, CERT_REVOKED }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { TLS_REQUIRED, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, STARTTLS, CERT_CHECK_STRICT, TLS_CA_DIR } } }, { "/connector/cert-verification/tls/revoked/lenient/fail", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_REVOKED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP, CERT_REVOKED }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { TLS_REQUIRED, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, STARTTLS, CERT_CHECK_LENIENT, TLS_CA_DIR } } }, /* ********************************************************************* */ /* as above but with legacy ssl */ { "/connector/cert-verification/ssl/nohost/ok", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector/cert-verification/ssl/host/ok", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@thud.org", "something", PLAIN, TLS }, { "weasel-juice.org", PORT_XMPP, XMPP_V1, OLD_SSL } } }, { "/connector/cert-verification/ssl/nohost/fail/name-mismatch", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_NAME_MISMATCH, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "tomato-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@tomato-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector/cert-verification/ssl/host/fail/name-mismatch", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_NAME_MISMATCH, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "tomato-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@tomato-juice.org", "something", PLAIN, TLS }, { "tomato-juice.org", 0, XMPP_V1, OLD_SSL } } }, { "/connector/cert-verification/ssl/expired/fail", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_EXPIRED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP, CERT_EXPIRED }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector/cert-verification/ssl/inactive/fail", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_NOT_ACTIVE, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP, CERT_NOT_YET }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector/cert-verification/ssl/selfsigned/fail", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_INVALID, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP, CERT_SELFSIGN }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector/cert-verification/ssl/unknown/fail", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_SIGNER_UNKNOWN, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP, CERT_UNKNOWN }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL } } }, { "/connector/cert-verification/ssl/wildcard/ok", QUIET, { S_NO_ERROR }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP, CERT_WILDCARD }, { "foo.weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { TLS_REQUIRED, { "moose@foo.weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL, CERT_CHECK_STRICT, TLS_CA_DIR } } }, { "/connector/cert-verification/ssl/wildcard/level-mismatch/fail", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_NAME_MISMATCH, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP, CERT_WILDCARD }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL, CERT_CHECK_STRICT, TLS_CA_DIR } } }, { "/connector/cert-verification/ssl/wildcard/glob-mismatch/fail", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_NAME_MISMATCH, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP, CERT_WILDCARD }, { "foo.diesel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { TLS_REQUIRED, { "moose@foo.diesel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL, CERT_CHECK_STRICT, TLS_CA_DIR } } }, { "/connector/cert-verification/ssl/bad-wildcard/fail", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_NAME_MISMATCH, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP, CERT_BADWILD }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { TLS_REQUIRED, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL, CERT_CHECK_STRICT, TLS_CA_DIR } } }, { "/connector/cert-verification/ssl/revoked/fail", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_REVOKED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP, CERT_REVOKED }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { TLS_REQUIRED, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL, CERT_CHECK_STRICT, TLS_CA_DIR } } }, { "/connector/cert-verification/ssl/revoked/lenient/fail", QUIET, { S_WOCKY_TLS_CERT_ERROR, WOCKY_TLS_CERT_REVOKED, -1 }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP, CERT_REVOKED }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { TLS_REQUIRED, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL, CERT_CHECK_LENIENT, TLS_CA_DIR } } }, /* ********************************************************************* */ /* certificate non-verification tests */ { "/connector/cert-nonverification/tls/nohost/ok", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1 } } }, { "/connector/cert-nonverification/tls/host/ok", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "thud.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { "thud.org", 0, XMPP_V1, STARTTLS, CERT_CHECK_LENIENT } } }, { "/connector/cert-nonverification/tls/nohost/ok/name-mismatch", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { "tomato-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@tomato-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, STARTTLS, CERT_CHECK_LENIENT } } }, { "/connector/cert-nonverification/tls/host/ok/name-mismatch", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "tomato-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@tomato-juice.org", "something", PLAIN, TLS }, { "tomato-juice.org", 0, XMPP_V1, STARTTLS, CERT_CHECK_LENIENT } } }, { "/connector/cert-nonverification/tls/expired/ok", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP, CERT_EXPIRED }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, STARTTLS, CERT_CHECK_LENIENT } } }, { "/connector/cert-nonverification/tls/inactive/ok", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP, CERT_NOT_YET }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, STARTTLS, CERT_CHECK_LENIENT } } }, { "/connector/cert-nonverification/tls/selfsigned/ok", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP, CERT_SELFSIGN }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, STARTTLS, CERT_CHECK_LENIENT } } }, { "/connector/cert-nonverification/tls/unknown/ok", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, CONNECTOR_OK }, { "moose", "something" }, PORT_XMPP, CERT_UNKNOWN }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, STARTTLS, CERT_CHECK_LENIENT } } }, /* ********************************************************************* */ /* as above but with legacy ssl */ { "/connector/cert-nonverification/ssl/nohost/ok", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL, CERT_CHECK_LENIENT } } }, { "/connector/cert-nonverification/ssl/host/ok", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "weasel-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@thud.org", "something", PLAIN, TLS }, { "weasel-juice.org", PORT_XMPP, XMPP_V1, OLD_SSL, CERT_CHECK_LENIENT } } }, { "/connector/cert-nonverification/ssl/nohost/ok/name-mismatch", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { "tomato-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@tomato-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL, CERT_CHECK_LENIENT } } }, { "/connector/cert-nonverification/ssl/host/ok/name-mismatch", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP }, { NULL, 0, "tomato-juice.org", REACHABLE, NULL }, { PLAINTEXT_OK, { "moose@tomato-juice.org", "something", PLAIN, TLS }, { "tomato-juice.org", 0, XMPP_V1, OLD_SSL, CERT_CHECK_LENIENT } } }, { "/connector/cert-nonverification/ssl/expired/ok", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP, CERT_EXPIRED }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL, CERT_CHECK_LENIENT } } }, { "/connector/cert-nonverification/ssl/inactive/ok", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP, CERT_NOT_YET }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL, CERT_CHECK_LENIENT } } }, { "/connector/cert-nonverification/ssl/selfsigned/ok", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP, CERT_SELFSIGN }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL, CERT_CHECK_LENIENT } } }, { "/connector/cert-nonverification/ssl/unknown/ok", QUIET, { S_NO_ERROR, }, { { TLS, NULL }, { SERVER_PROBLEM_NO_PROBLEM, { XMPP_PROBLEM_OLD_SSL, OK, OK, OK, OK } }, { "moose", "something" }, PORT_XMPP, CERT_UNKNOWN }, { "weasel-juice.org", PORT_XMPP, "thud.org", REACHABLE, UNREACHABLE }, { PLAINTEXT_OK, { "moose@weasel-juice.org", "something", PLAIN, TLS }, { NULL, 0, XMPP_V1, OLD_SSL, CERT_CHECK_LENIENT } } }, /* we are done, cap the list: */ { NULL } }; /* ************************************************************************* */ #define STRING_OK(x) (((x) != NULL) && (*x != '\0')) static void setup_dummy_dns_entries (const test_t *test) { TestResolver *tr = TEST_RESOLVER (kludged); guint port = test->dns.port ? test->dns.port : PORT_XMPP; const char *domain = test->dns.srv; const char *host = test->dns.host; const char *addr = test->dns.addr; const char *s_ip = test->dns.srvhost; test_resolver_reset (tr); if (STRING_OK (domain) && STRING_OK (host)) test_resolver_add_SRV (tr, "xmpp-client", "tcp", domain, host, port); if (STRING_OK (domain) && STRING_OK (s_ip)) test_resolver_add_A (tr, domain, s_ip); if (STRING_OK (host) && STRING_OK (addr)) test_resolver_add_A (tr, host, addr); test_resolver_add_A (tr, INVISIBLE_HOST, UNREACHABLE); test_resolver_add_A (tr, VISIBLE_HOST, REACHABLE); } /* ************************************************************************* */ /* Dummy XMPP server */ static void start_dummy_xmpp_server (ServerParameters *srv); static gboolean client_connected (GIOChannel *channel, GIOCondition cond, gpointer data) { ServerParameters *srv = data; struct sockaddr_in client; socklen_t clen = sizeof (client); int ssock = g_io_channel_unix_get_fd (channel); int csock = accept (ssock, (struct sockaddr *) &client, &clen); GSocket *gsock = g_socket_new_from_fd (csock, NULL); ConnectorProblem *cproblem = &srv->problem.conn; GSocketConnection *gconn; if (csock < 0) { perror ("accept() failed"); g_warning ("accept() failed on socket that should have been ready."); return TRUE; } if (!srv->features.tls) cproblem->xmpp |= XMPP_PROBLEM_NO_TLS; gconn = g_object_new (G_TYPE_SOCKET_CONNECTION, "socket", gsock, NULL); g_object_unref (gsock); srv->server = test_connector_server_new (G_IO_STREAM (gconn), srv->features.auth_mech, srv->auth.user, srv->auth.pass, srv->features.version, cproblem, srv->problem.sasl, srv->cert); g_object_unref (gconn); /* Recursively start extra servers */ if (srv->extra_server != NULL) { test_connector_server_set_other_host (srv->server, REACHABLE, srv->extra_server->port); start_dummy_xmpp_server (srv->extra_server); } test_connector_server_start (srv->server); srv->watch = 0; return FALSE; } static void start_dummy_xmpp_server (ServerParameters *srv) { int ssock; int reuse = 1; struct sockaddr_in server; int res = -1; guint port = srv->port; if (port == 0) return; memset (&server, 0, sizeof (server)); server.sin_family = AF_INET; /* mingw doesn't support aton or pton so using more portable inet_addr */ server.sin_addr.s_addr = inet_addr ((const char * ) REACHABLE); server.sin_port = htons (port); ssock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); setsockopt (ssock, SOL_SOCKET, SO_REUSEADDR, (const char *) &reuse, sizeof (reuse)); #ifdef G_OS_UNIX setsockopt (ssock, IPPROTO_TCP, TCP_NODELAY, (const char *) &reuse, sizeof (reuse)); #endif res = bind (ssock, (struct sockaddr *) &server, sizeof (server)); if (res != 0) { int code = errno; char *err = g_strdup_printf ("bind to " REACHABLE ":%d failed", port); perror (err); g_free (err); exit (code); } res = listen (ssock, 1024); if (res != 0) { int code = errno; char *err = g_strdup_printf ("listen on " REACHABLE ":%d failed", port); perror (err); g_free (err); exit (code); } srv->channel = g_io_channel_unix_new (ssock); g_io_channel_set_flags (srv->channel, G_IO_FLAG_NONBLOCK, NULL); srv->watch = g_io_add_watch (srv->channel, G_IO_IN|G_IO_PRI, client_connected, srv); g_io_channel_set_close_on_unref (srv->channel, TRUE); return; } /* ************************************************************************* */ static void test_server_teardown_cb (GObject *source, GAsyncResult *result, gpointer user_data) { GMainLoop *loop = user_data; g_assert (test_connector_server_teardown_finish ( TEST_CONNECTOR_SERVER (source), result, NULL)); g_main_loop_quit (loop); } static void test_server_teardown (test_t *test, ServerParameters *srv) { /* Recursively teardown extra servers */ if (srv->extra_server != NULL) test_server_teardown (test, srv->extra_server); srv->extra_server = NULL; if (srv->server != NULL) { GMainLoop *loop = g_main_loop_new (NULL, FALSE); if (test->result.used_mech == NULL) { test->result.used_mech = g_strdup ( test_connector_server_get_used_mech (srv->server)); } /* Run until server is down */ test_connector_server_teardown (srv->server, test_server_teardown_cb, loop); g_main_loop_run (loop); g_clear_object (&srv->server); } if (srv->watch != 0) g_source_remove (srv->watch); srv->watch = 0; if (srv->channel != NULL) g_io_channel_unref (srv->channel); srv->channel = NULL; } static void test_done (GObject *source, GAsyncResult *res, gpointer data) { test_t *test = data; WockyConnector *wcon = WOCKY_CONNECTOR (source); WockyXmppConnection *conn = NULL; error = NULL; switch (test->client.op) { case OP_CONNECT: conn = wocky_connector_connect_finish (wcon, res, &test->result.jid, &test->result.sid, &error); test->ok = (conn != NULL); break; case OP_REGISTER: conn = wocky_connector_register_finish (wcon, res, &test->result.jid, &test->result.sid, &error); test->ok = (conn != NULL); break; case OP_CANCEL: test->ok = wocky_connector_unregister_finish (wcon, res, &error); break; } if (conn != NULL) test->result.xmpp = g_object_ref (conn); test_server_teardown (test, &test->server_parameters); g_main_loop_quit (mainloop); } typedef void (*test_func) (gconstpointer); #ifdef G_OS_UNIX static void connection_established_cb (WockyConnector *connector, GSocketConnection *conn, gpointer user_data) { GSocket *sock = g_socket_connection_get_socket (conn); gint fd, flag = 1; fd = g_socket_get_fd (sock); setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (const char *) &flag, sizeof (flag)); } #endif static gboolean start_test (gpointer data) { test_t *test = data; if (test->client.setup != NULL) (test->client.setup) (test); switch (test->client.op) { case OP_CONNECT: wocky_connector_connect_async (test->connector, NULL, test_done, data); break; case OP_REGISTER: wocky_connector_register_async (test->connector, NULL, test_done, data); break; case OP_CANCEL: wocky_connector_unregister_async (test->connector, NULL, test_done, data); break; } return FALSE; } static void run_test (gpointer data) { WockyConnector *wcon = NULL; WockyTLSHandler *handler; test_t *test = data; struct stat dummy; gchar *base; char *path; const gchar *ca; /* clean up any leftover messes from previous tests */ /* unlink the sasl db tmpfile, it will cause a deadlock */ base = g_get_current_dir (); path = g_strdup_printf ("%s/__db.%s", base, SASL_DB_NAME); g_free (base); g_assert ((g_stat (path, &dummy) != 0) || (g_unlink (path) == 0)); g_free (path); /* end of cleanup block */ start_dummy_xmpp_server (&test->server_parameters); setup_dummy_dns_entries (test); ca = test->client.options.ca ? test->client.options.ca : TLS_CA_CRT_FILE; /* insecure tls cert/etc not yet implemented */ handler = wocky_tls_handler_new (test->client.options.lax_ssl); wcon = g_object_new ( WOCKY_TYPE_CONNECTOR, "jid" , test->client.auth.jid, "password" , test->client.auth.pass, "xmpp-server" , test->client.options.host, "xmpp-port" , test->client.options.port, "tls-required" , test->client.require_tls, "encrypted-plain-auth-ok" , !test->client.auth.secure, /* this refers to PLAINTEXT vs CRYPT, not PLAIN vs DIGEST */ "plaintext-auth-allowed" , !test->client.auth.tls, "legacy" , test->client.options.jabber, "old-ssl" , test->client.options.ssl, "tls-handler" , handler, NULL); /* Make sure we only use the test CAs, not system-wide ones. */ wocky_tls_handler_forget_cas (handler); g_assert (wocky_tls_handler_get_cas (handler) == NULL); /* check if the cert paths are valid */ g_assert (g_file_test (TLS_CA_CRT_FILE, G_FILE_TEST_EXISTS)); wocky_tls_handler_add_ca (handler, ca); /* not having a CRL can expose a bug in the openssl error handling * (basically we get 'CRL not fetched' instead of 'Expired'): * The bug has been fixed, but we can keep checking for it by * dropping the CRLs when the test is for an expired cert */ if (test->server_parameters.cert != CERT_EXPIRED) wocky_tls_handler_add_crl (handler, TLS_CRL_DIR); g_object_unref (handler); test->connector = wcon; g_idle_add (start_test, test); #ifdef G_OS_UNIX /* set TCP_NODELAY as soon as possible */ g_signal_connect (test->connector, "connection-established", G_CALLBACK (connection_established_cb), NULL); #endif g_main_loop_run (mainloop); if (test->result.domain == S_NO_ERROR) { if (error != NULL) fprintf (stderr, "Error: %s.%d: %s\n", g_quark_to_string (error->domain), error->code, error->message); g_assert_no_error (error); if (test->client.op == OP_CANCEL) { g_assert (test->ok == TRUE); g_assert (test->result.xmpp == NULL); } else { g_assert (test->result.xmpp != NULL); /* make sure we selected the right auth mechanism */ if (test->result.mech != NULL) { g_assert_cmpstr (test->result.mech, ==, test->result.used_mech); } /* we got a JID back, I hope */ g_assert (test->result.jid != NULL); g_assert (*test->result.jid != '\0'); g_free (test->result.jid); /* we got a SID back, I hope */ g_assert (test->result.sid != NULL); g_assert (*test->result.sid != '\0'); g_free (test->result.sid); } /* property get/set functionality */ if (!strcmp (test->desc, CONNECTOR_INTERNALS_TEST)) { int i; gchar *identity, *session_id, *resource; WockyConnector *tmp = wocky_connector_new ("foo@bar.org", "abc", "xyz", NULL, NULL); WockyStanza *feat = NULL; gboolean jabber; gboolean oldssl; XmppProblem xproblem = test->server_parameters.problem.conn.xmpp; const gchar *prop = NULL; const gchar *str_prop[] = { "jid", "password", "xmpp-server", "email", NULL }; const gchar *str_vals[] = { "abc", "PASSWORD", "xmpp.server", "e@org", NULL }; const gchar *boolprop[] = { "plaintext-auth-allowed", "encrypted-plain-auth-ok", "tls-required", NULL }; g_object_get (wcon, "identity", &identity, "features", &feat, NULL); g_assert (identity != NULL); g_assert (*identity != '\0'); g_assert (feat != NULL); g_assert (G_OBJECT_TYPE (feat) == WOCKY_TYPE_STANZA); g_free (identity); g_object_unref (feat); identity = NULL; g_object_get (wcon, "session-id", &session_id, NULL); g_assert (session_id != NULL); g_assert (*session_id != '\0'); g_free (session_id); g_object_get (wcon, "resource", &resource, NULL); /* TODO: really? :resource gets updated to contain the actual * post-bind resource, but perhaps :resource should be updated too? */ g_assert_cmpstr (resource, ==, NULL); g_free (resource); g_object_get (wcon, "legacy", &jabber, "old-ssl", &oldssl, NULL); g_assert (jabber == (gboolean)(xproblem & XMPP_PROBLEM_OLD_SERVER)); g_assert (oldssl == (gboolean)(xproblem & XMPP_PROBLEM_OLD_SSL)); for (i = 0, prop = str_prop[0]; prop; prop = str_prop[++i]) { gchar *val = NULL; g_object_set (tmp, prop, str_vals[i], NULL); g_object_get (tmp, prop, &val, NULL); g_assert (!strcmp (val, str_vals[i])); g_assert (val != str_vals[i]); g_free (val); } for (i = 0, prop = boolprop[0]; prop; prop = boolprop[++i]) { gboolean val; g_object_set (tmp, prop, TRUE, NULL); g_object_get (tmp, prop, &val, NULL); g_assert (val); g_object_set (tmp, prop, FALSE, NULL); g_object_get (tmp, prop, &val, NULL); g_assert (!val); } g_object_set (tmp, "xmpp-port", 31415, NULL); g_object_get (tmp, "xmpp-port", &i, NULL); g_assert (i == 31415); g_object_unref (tmp); } } else { g_assert (test->result.xmpp == NULL); if (test->result.domain != S_ANY_ERROR) { /* We want the error to match either of result.code or * result.fallback_code, but don't care which. * The expected error domain is the same for either code. */ if (error->code == test->result.fallback_code) g_assert_error (error, map_static_domain (test->result.domain), test->result.fallback_code); else g_assert_error (error, map_static_domain (test->result.domain), test->result.code); } } if (wcon != NULL) g_object_unref (wcon); if (error != NULL) g_error_free (error); if (test->result.xmpp != NULL) g_object_unref (test->result.xmpp); g_free (test->result.used_mech); error = NULL; } int main (int argc, char **argv) { int i; gchar *base; gchar *path = NULL; struct stat dummy; int result; test_init (argc, argv); /* hook up the fake DNS resolver that lets us divert A and SRV queries * * into our local cache before asking the real DNS */ original = g_resolver_get_default (); kludged = g_object_new (TEST_TYPE_RESOLVER, "real-resolver", original, NULL); g_resolver_set_default (kludged); /* unlink the sasl db, we want to test against a fresh one */ base = g_get_current_dir (); path = g_strdup_printf ("%s/%s", base, SASL_DB_NAME); g_free (base); g_assert ((g_stat (path, &dummy) != 0) || (g_unlink (path) == 0)); g_free (path); mainloop = g_main_loop_new (NULL, FALSE); #ifdef HAVE_LIBSASL2 for (i = 0; tests[i].desc != NULL; i++) g_test_add_data_func (tests[i].desc, &tests[i], (test_func)run_test); #else g_message ("libsasl2 not found: skipping MD5 SASL tests"); for (i = 0; tests[i].desc != NULL; i++) { if (!wocky_strdiff (tests[i].result.mech, "DIGEST-MD5")) continue; g_test_add_data_func (tests[i].desc, &tests[i], (test_func)run_test); } #endif result = g_test_run (); test_deinit (); return result; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-porter-test.c0000664000175000017500000030662412332440453025643 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "wocky-test-stream.h" #include "wocky-test-helper.h" static void test_instantiation (void) { WockyPorter *porter; WockyXmppConnection *connection; WockyTestStream *stream;; stream = g_object_new (WOCKY_TYPE_TEST_STREAM, NULL); connection = wocky_xmpp_connection_new (stream->stream0); porter = wocky_c2s_porter_new (connection, "juliet@example.com/Balcony"); g_assert (porter != NULL); g_assert_cmpstr (wocky_porter_get_full_jid (porter), ==, "juliet@example.com/Balcony"); g_assert_cmpstr (wocky_porter_get_bare_jid (porter), ==, "juliet@example.com"); g_assert_cmpstr (wocky_porter_get_resource (porter), ==, "Balcony"); g_object_unref (porter); g_object_unref (connection); g_object_unref (stream); } /* send testing */ static void send_stanza_received_cb (GObject *source, GAsyncResult *res, gpointer user_data) { WockyXmppConnection *connection = WOCKY_XMPP_CONNECTION (source); WockyStanza *s; test_data_t *data = (test_data_t *) user_data; GError *error = NULL; WockyStanza *expected; s = wocky_xmpp_connection_recv_stanza_finish (connection, res, &error); g_assert (s != NULL); expected = g_queue_pop_head (data->expected_stanzas); g_assert (expected != NULL); test_assert_stanzas_equal (s, expected); if (g_queue_get_length (data->expected_stanzas) > 0) { /* We need to receive more stanzas */ wocky_xmpp_connection_recv_stanza_async ( WOCKY_XMPP_CONNECTION (source), NULL, send_stanza_received_cb, user_data); data->outstanding++; } g_object_unref (s); g_object_unref (expected); data->outstanding--; g_main_loop_quit (data->loop); } static void send_stanza_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *data = (test_data_t *) user_data; g_assert (wocky_porter_send_finish ( WOCKY_PORTER (source), res, NULL)); data->outstanding--; g_main_loop_quit (data->loop); } static void send_stanza_cancelled_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *data = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_porter_send_finish ( WOCKY_PORTER (source), res, &error)); g_assert (error->domain == G_IO_ERROR); g_assert (error->code == G_IO_ERROR_CANCELLED); g_error_free (error); data->outstanding--; g_main_loop_quit (data->loop); } static void test_send (void) { test_data_t *test = setup_test (); WockyStanza *s; test_open_connection (test); /* Send a stanza */ s = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "juliet@example.com", "romeo@example.net", NULL); wocky_porter_send_async (test->sched_in, s, NULL, send_stanza_cb, test); g_queue_push_tail (test->expected_stanzas, s); test->outstanding++; /* Send a stanza */ s = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "juliet@example.com", "tybalt@example.net", NULL); wocky_porter_send_async (test->sched_in, s, NULL, send_stanza_cb, test); g_queue_push_tail (test->expected_stanzas, s); test->outstanding++; /* Send two stanzas and cancel them immediately */ s = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "juliet@example.com", "peter@example.net", NULL); wocky_porter_send_async (test->sched_in, s, test->cancellable, send_stanza_cancelled_cb, test); g_object_unref (s); test->outstanding++; s = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "juliet@example.com", "samson@example.net", NULL); wocky_porter_send_async (test->sched_in, s, test->cancellable, send_stanza_cancelled_cb, test); g_object_unref (s); test->outstanding++; /* the stanza are not added to expected_stanzas as it was cancelled */ g_cancellable_cancel (test->cancellable); /* ... and a second (using the simple send method) */ s = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "juliet@example.com", "nurse@example.net", NULL); wocky_porter_send (test->sched_in, s); g_queue_push_tail (test->expected_stanzas, s); test->outstanding++; /* Send a last stanza using the full method so we are sure that all async * sending operation have been finished. This is important because * test_close_connection() will have to use this function to close the * connection. If there is still a pending sending operation, it will fail. */ s = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "juliet@example.com", "tybalt@example.net", NULL); wocky_porter_send_async (test->sched_in, s, NULL, send_stanza_cb, test); g_queue_push_tail (test->expected_stanzas, s); test->outstanding++; wocky_xmpp_connection_recv_stanza_async (test->out, NULL, send_stanza_received_cb, test); test_wait_pending (test); test_close_connection (test); teardown_test (test); } /* receive testing */ static gboolean test_receive_stanza_received_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; test_expected_stanza_received (test, stanza); return TRUE; } static void sched_close_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; g_assert (wocky_porter_close_finish ( WOCKY_PORTER (source), res, NULL)); test->outstanding--; g_main_loop_quit (test->loop); } static void close_sent_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; g_assert (wocky_xmpp_connection_send_close_finish ( WOCKY_XMPP_CONNECTION (source), res, NULL)); test->outstanding--; g_main_loop_quit (test->loop); } static void wait_close_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyXmppConnection *connection = WOCKY_XMPP_CONNECTION (source); WockyStanza *s; GError *error = NULL; s = wocky_xmpp_connection_recv_stanza_finish (connection, res, &error); g_assert (s == NULL); /* connection has been disconnected */ g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_CLOSED); g_error_free (error); /* close on our side */ wocky_xmpp_connection_send_close_async (connection, NULL, close_sent_cb, test); /* Don't decrement test->outstanding as we are waiting for another * callback */ g_main_loop_quit (test->loop); } static void test_receive (void) { test_data_t *test = setup_test (); WockyStanza *s; test_open_both_connections (test); /* Send a stanza */ s = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "juliet@example.com", "romeo@example.net", NULL); wocky_porter_send_async (test->sched_in, s, NULL, send_stanza_cb, test); g_queue_push_tail (test->expected_stanzas, s); /* We are waiting for the stanza to be sent and received on the other * side */ test->outstanding += 2; wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, 0, test_receive_stanza_received_cb, test, NULL); wocky_porter_start (test->sched_out); test_wait_pending (test); test_close_porter (test); teardown_test (test); } /* filter testing */ static gboolean test_filter_iq_received_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; test_expected_stanza_received (test, stanza); return TRUE; } static gboolean test_filter_presence_received_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { /* We didn't send any presence stanza so this callback shouldn't be * called */ g_assert_not_reached (); return TRUE; } static void test_filter (void) { test_data_t *test = setup_test (); WockyStanza *msg, *iq; test_open_both_connections (test); /* register an IQ filter */ wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, 0, test_filter_iq_received_cb, test, NULL); /* register a presence filter */ wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_PRESENCE, WOCKY_STANZA_SUB_TYPE_NONE, 0, test_filter_presence_received_cb, test, NULL); wocky_porter_start (test->sched_out); /* Send a message */ msg = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "juliet@example.com", "romeo@example.net", NULL); wocky_porter_send (test->sched_in, msg); /* We don't expect this stanza as we didn't register any message filter */ /* Send an IQ */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", NULL); wocky_porter_send (test->sched_in, iq); /* We expect to receive this stanza */ g_queue_push_tail (test->expected_stanzas, iq); test->outstanding++; test_wait_pending (test); g_object_unref (msg); test_close_porter (test); teardown_test (test); } /* test if the send queue is flushed before closing the connection */ static void test_close_stanza_received_cb (GObject *source, GAsyncResult *res, gpointer user_data) { WockyXmppConnection *connection = WOCKY_XMPP_CONNECTION (source); WockyStanza *s; test_data_t *test = (test_data_t *) user_data; GError *error = NULL; s = wocky_xmpp_connection_recv_stanza_finish (connection, res, &error); if (g_queue_get_length (test->expected_stanzas) > 0) { WockyStanza *expected; g_assert (s != NULL); expected = g_queue_pop_head (test->expected_stanzas); g_assert (expected != NULL); test_assert_stanzas_equal (s, expected); wocky_xmpp_connection_recv_stanza_async (connection, NULL, test_close_stanza_received_cb, user_data); test->outstanding++; g_object_unref (s); g_object_unref (expected); } else { g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_CLOSED); g_error_free (error); /* close on our side */ wocky_xmpp_connection_send_close_async (connection, NULL, close_sent_cb, test); } test->outstanding--; g_main_loop_quit (test->loop); } static void test_close_sched_close_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; g_assert (wocky_porter_close_finish ( WOCKY_PORTER (source), res, NULL)); test->outstanding--; g_main_loop_quit (test->loop); } static void closing_cb (WockyPorter *porter, test_data_t *test) { test->outstanding--; g_main_loop_quit (test->loop); } static void test_close_flush (void) { test_data_t *test = setup_test (); WockyStanza *s; test_open_both_connections (test); wocky_porter_start (test->sched_in); s = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "juliet@example.com", "romeo@example.net", NULL); wocky_porter_send (test->sched_in, s); g_queue_push_tail (test->expected_stanzas, s); test->outstanding++; wocky_xmpp_connection_recv_stanza_async (test->out, NULL, test_close_stanza_received_cb, test); g_signal_connect (test->sched_in, "closing", G_CALLBACK (closing_cb), test); wocky_porter_close_async (test->sched_in, NULL, test_close_sched_close_cb, test); test->outstanding += 3; test_wait_pending (test); teardown_test (test); } /* test if the right error is raised when trying to close a not started * porter */ static void test_close_not_started_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_porter_close_finish ( WOCKY_PORTER (source), res, &error)); g_assert_error (error, WOCKY_PORTER_ERROR, WOCKY_PORTER_ERROR_NOT_STARTED); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_close_not_started (void) { test_data_t *test = setup_test (); test_open_both_connections (test); wocky_porter_close_async (test->sched_in, NULL, test_close_not_started_cb, test); test->outstanding++; test_wait_pending (test); wocky_xmpp_connection_recv_stanza_async (test->out, NULL, wait_close_cb, test); wocky_porter_start (test->sched_in); wocky_porter_close_async (test->sched_in, NULL, sched_close_cb, test); test->outstanding += 2; test_wait_pending (test); teardown_test (test); } /* test if the right error is raised when trying to close the porter * twice */ static void test_close_twice_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_porter_close_finish ( WOCKY_PORTER (source), res, &error)); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PENDING); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_close_twice_cb2 (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_porter_close_finish ( WOCKY_PORTER (source), res, &error)); g_assert_error (error, WOCKY_PORTER_ERROR, WOCKY_PORTER_ERROR_CLOSED); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_close_twice (void) { test_data_t *test = setup_test (); test_open_both_connections (test); wocky_xmpp_connection_recv_stanza_async (test->out, NULL, wait_close_cb, test); wocky_porter_start (test->sched_in); wocky_porter_close_async (test->sched_in, NULL, sched_close_cb, test); wocky_porter_close_async (test->sched_in, NULL, test_close_twice_cb, test); test->outstanding += 3; test_wait_pending (test); /* Retry now that the porter has been closed */ wocky_porter_close_async (test->sched_in, NULL, test_close_twice_cb2, test); test->outstanding++; test_wait_pending (test); teardown_test (test); } /* Test if the remote-closed signal is emitted when the other side closes his * XMPP connection */ static void remote_closed_cb (WockyPorter *porter, test_data_t *test) { test->outstanding--; g_main_loop_quit (test->loop); } static void test_remote_close_in_close_send_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *data = (test_data_t *) user_data; g_assert (wocky_xmpp_connection_send_close_finish ( WOCKY_XMPP_CONNECTION (source), res, NULL)); data->outstanding--; g_main_loop_quit (data->loop); } static void test_remote_close (void) { test_data_t *test = setup_test (); test_open_both_connections (test); wocky_porter_start (test->sched_out); g_signal_connect (test->sched_out, "remote-closed", G_CALLBACK (remote_closed_cb), test); test->outstanding++; wocky_xmpp_connection_send_close_async ( WOCKY_XMPP_CONNECTION (test->in), NULL, test_remote_close_in_close_send_cb, test); test->outstanding++; test_wait_pending (test); wocky_porter_close_async (test->sched_out, NULL, sched_close_cb, test); test->outstanding++; test_wait_pending (test); teardown_test (test); } /* Test cancelling a close operation */ static void sched_close_cancelled_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_porter_close_finish ( WOCKY_PORTER (source), res, &error)); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_close_cancel_force_closed_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; wocky_porter_force_close_finish ( WOCKY_PORTER (source), res, &error); g_assert_no_error (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_close_cancel (void) { test_data_t *test = setup_test (); wocky_test_stream_set_write_mode (test->stream->stream0_output, WOCKY_TEST_STREAM_WRITE_COMPLETE); test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_xmpp_connection_recv_stanza_async (test->in, NULL, wait_close_cb, test); wocky_porter_close_async (test->sched_out, test->cancellable, sched_close_cancelled_cb, test); g_cancellable_cancel (test->cancellable); test->outstanding += 2; test_wait_pending (test); wocky_porter_force_close_async (test->sched_out, NULL, test_close_cancel_force_closed_cb, test); test->outstanding++; test_wait_pending (test); teardown_test (test); } /* Test if the remote-error signal is fired when porter got a read error */ static void remote_error_cb (WockyPorter *porter, GQuark domain, guint code, const gchar *message, test_data_t *test) { GError *err = g_error_new_literal (domain, code, message); g_assert_error (err, G_IO_ERROR, G_IO_ERROR_FAILED); g_error_free (err); test->outstanding--; g_main_loop_quit (test->loop); } static void test_reading_error (void) { test_data_t *test = setup_test (); test_open_both_connections (test); g_signal_connect (test->sched_out, "remote-error", G_CALLBACK (remote_error_cb), test); test->outstanding++; wocky_test_input_stream_set_read_error (test->stream->stream1_input); wocky_porter_start (test->sched_out); test_wait_pending (test); test_close_porter (test); teardown_test (test); } /* Test if the right error is raised when trying to send a stanza through a * closed porter */ static void test_send_closing_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *data = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_porter_send_finish ( WOCKY_PORTER (source), res, &error)); g_assert_error (error, WOCKY_PORTER_ERROR, WOCKY_PORTER_ERROR_CLOSING); g_error_free (error); data->outstanding--; g_main_loop_quit (data->loop); } static void test_send_closed_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *data = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_porter_send_finish ( WOCKY_PORTER (source), res, &error)); g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_IS_CLOSED); g_error_free (error); data->outstanding--; g_main_loop_quit (data->loop); } static void test_send_closed (void) { test_data_t *test = setup_test (); WockyStanza *s; test_open_both_connections (test); wocky_porter_start (test->sched_in); wocky_xmpp_connection_recv_stanza_async (test->out, NULL, wait_close_cb, test); wocky_porter_close_async (test->sched_in, NULL, sched_close_cb, test); s = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "juliet@example.com", "romeo@example.net", NULL); /* try to send a stanza while closing */ wocky_porter_send_async (test->sched_in, s, NULL, test_send_closing_cb, test); test->outstanding += 3; test_wait_pending (test); /* try to send a stanza after the closing */ wocky_porter_send_async (test->sched_in, s, NULL, test_send_closed_cb, test); g_object_unref (s); test->outstanding++; test_wait_pending (test); teardown_test (test); } /* test if the handler with the higher priority is called */ static void send_stanza (test_data_t *test, WockyStanza *stanza, gboolean expected) { wocky_porter_send (test->sched_in, stanza); if (expected) { g_queue_push_tail (test->expected_stanzas, stanza); test->outstanding++; } else { g_object_unref (stanza); } test_wait_pending (test); } static gboolean test_handler_priority_5 (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { /* This handler has the lowest priority and is not supposed to be called */ g_assert_not_reached (); return TRUE; } static gboolean test_handler_priority_10 (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanzaSubType sub_type; test_expected_stanza_received (test, stanza); wocky_stanza_get_type_info (stanza, NULL, &sub_type); /* This handler is supposed to only handle the get stanza */ g_assert (sub_type == WOCKY_STANZA_SUB_TYPE_GET); return TRUE; } static gboolean test_handler_priority_15 (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; test_expected_stanza_received (test, stanza); return TRUE; } static void test_handler_priority (void) { test_data_t *test = setup_test (); WockyStanza *iq; test_open_both_connections (test); /* register an IQ handler with a priority of 10 */ wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, 10, test_handler_priority_10, test, NULL); /* register an IQ handler with a priority of 5 */ wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, 5, test_handler_priority_5, test, NULL); wocky_porter_start (test->sched_out); /* Send a 'get' IQ */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", NULL); send_stanza (test, iq, TRUE); /* register an IQ handler with a priority of 15 */ wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, 15, test_handler_priority_15, test, NULL); /* Send a 'set' IQ */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, "juliet@example.com", "romeo@example.net", NULL); send_stanza (test, iq, TRUE); test_close_porter (test); teardown_test (test); } /* Test unregistering a handler */ static gboolean test_unregister_handler_10 (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { /* this handler is unregistred so shouldn't called */ g_assert_not_reached (); return TRUE; } static gboolean test_unregister_handler_5 (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; test_expected_stanza_received (test, stanza); return TRUE; } static void test_unregister_handler (void) { test_data_t *test = setup_test (); WockyStanza *iq; guint id; test_open_both_connections (test); /* register an IQ handler with a priority of 10 */ id = wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, 10, test_unregister_handler_10, test, NULL); /* register an IQ handler with a priority of 5 */ wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, 5, test_unregister_handler_5, test, NULL); wocky_porter_start (test->sched_out); /* unregister the first handler */ wocky_porter_unregister_handler (test->sched_out, id); /* Send a 'get' IQ */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", NULL); send_stanza (test, iq, TRUE); test_close_porter (test); teardown_test (test); } /* test registering a handler using a bare JID as filter criteria */ static gboolean test_handler_bare_jid_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; test_expected_stanza_received (test, stanza); return TRUE; } static void test_handler_bare_jid (void) { test_data_t *test = setup_test (); WockyStanza *iq; test_open_both_connections (test); /* register an IQ handler for all IQ from a bare jid */ wocky_porter_register_handler_from (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, "juliet@example.com", 0, test_handler_bare_jid_cb, test, NULL); wocky_porter_start (test->sched_out); /* Send a 'get' IQ from the bare jid */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", NULL); send_stanza (test, iq, TRUE); /* Send a 'get' IQ from another contact */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "samson@example.com/House", "romeo@example.net", NULL); send_stanza (test, iq, FALSE); /* Send a 'get' IQ from the bare jid + resource */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com/Pub", "romeo@example.net", NULL); send_stanza (test, iq, TRUE); test_close_porter (test); teardown_test (test); } /* test registering a handler using a full JID as filter criteria */ static gboolean test_handler_full_jid_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; test_expected_stanza_received (test, stanza); return TRUE; } static void test_handler_full_jid (void) { test_data_t *test = setup_test (); WockyStanza *iq; test_open_both_connections (test); /* register an IQ handler for all IQ from a bare jid */ wocky_porter_register_handler_from (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, "juliet@example.com/Pub", 0, test_handler_full_jid_cb, test, NULL); wocky_porter_start (test->sched_out); /* Send a 'get' IQ from the bare jid */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", NULL); send_stanza (test, iq, FALSE); /* Send a 'get' IQ from another contact */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "samson@example.com/House", "romeo@example.net", NULL); send_stanza (test, iq, FALSE); /* Send a 'get' IQ from the bare jid + resource */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com/Pub", "romeo@example.net", NULL); send_stanza (test, iq, TRUE); test_close_porter (test); teardown_test (test); } /* test registering a handler using a stanza as filter criteria */ static gboolean test_handler_stanza_jingle_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; const gchar *id; test_expected_stanza_received (test, stanza); id = wocky_node_get_attribute (wocky_stanza_get_top_node (stanza), "id"); g_assert (!wocky_strdiff (id, "3") || !wocky_strdiff (id, "4")); return TRUE; } static gboolean test_handler_stanza_terminate_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; const gchar *id; test_expected_stanza_received (test, stanza); id = wocky_node_get_attribute (wocky_stanza_get_top_node (stanza), "id"); g_assert (!wocky_strdiff (id, "5")); return TRUE; } static void test_handler_stanza (void) { test_data_t *test = setup_test (); WockyStanza *iq; test_open_both_connections (test); /* register an IQ handler for all the jingle stanzas related to one jingle * session */ wocky_porter_register_handler_from (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, "juliet@example.com", 0, test_handler_stanza_jingle_cb, test, '(', "jingle", ':', "urn:xmpp:jingle:1", '@', "sid", "my_sid", ')', NULL); wocky_porter_start (test->sched_out); wocky_porter_start (test->sched_in); /* Send a not jingle IQ */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, "juliet@example.com", "romeo@example.net", '@', "id", "1", NULL); send_stanza (test, iq, FALSE); /* Send a jingle IQ but related to another session */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, "juliet@example.com", "romeo@example.net", '@', "id", "2", '(', "jingle", ':', "urn:xmpp:jingle:1", '@', "sid", "another_sid", ')', NULL); send_stanza (test, iq, FALSE); /* Send a jingle IQ with the right sid but from the wrong contact */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, "tybalt@example.com", "romeo@example.net", '@', "id", "2", '(', "jingle", ':', "urn:xmpp:jingle:1", '@', "sid", "my_sid", ')', NULL); send_stanza (test, iq, FALSE); /* Send a jingle IQ related to the right session */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, "juliet@example.com", "romeo@example.net", '@', "id", "3", '(', "jingle", ':', "urn:xmpp:jingle:1", '@', "sid", "my_sid", ')', NULL); send_stanza (test, iq, TRUE); /* register a new IQ handler,with higher priority, handling session-terminate * with a specific test message */ wocky_porter_register_handler_from (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, "juliet@example.com", 10, test_handler_stanza_terminate_cb, test, '(', "jingle", ':', "urn:xmpp:jingle:1", '@', "action", "session-terminate", '(', "reason", '(', "success", ')', '(', "test", '$', "Sorry, gotta go!", ')', ')', ')', NULL); /* Send a session-terminate with the wrong message */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, "juliet@example.com", "romeo@example.net", '@', "id", "4", '(', "jingle", ':', "urn:xmpp:jingle:1", '@', "sid", "my_sid", '@', "action", "session-terminate", '(', "reason", '(', "success", ')', '(', "test", '$', "Bye Bye", ')', ')', ')', NULL); send_stanza (test, iq, TRUE); /* Send a session-terminate with the right message */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, "juliet@example.com", "romeo@example.net", '@', "id", "5", '(', "jingle", ':', "urn:xmpp:jingle:1", '@', "sid", "my_sid", '@', "action", "session-terminate", '(', "reason", '(', "success", ')', '(', "test", '$', "Sorry, gotta go!", ')', ')', ')', NULL); send_stanza (test, iq, TRUE); test_close_both_porters (test); teardown_test (test); } /* Cancel the sending of a stanza after it has been received */ static gboolean test_cancel_sent_stanza_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; test_expected_stanza_received (test, stanza); test_cancel_in_idle (test->cancellable); return TRUE; } static void test_cancel_sent_stanza_cancelled (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; /* Stanza has already be sent to _finish success */ g_assert (wocky_porter_send_finish ( WOCKY_PORTER (source), res, NULL)); test->outstanding--; g_main_loop_quit (test->loop); } static void test_cancel_sent_stanza (void) { test_data_t *test = setup_test (); WockyStanza *stanza; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_porter_start (test->sched_in); /* register a message handler */ wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, 0, test_cancel_sent_stanza_cb, test, NULL); stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, "juliet@example.com", "romeo@example.net", NULL); wocky_porter_send_async (test->sched_in, stanza, test->cancellable, test_cancel_sent_stanza_cancelled, test); g_queue_push_tail (test->expected_stanzas, stanza); test->outstanding += 2; test_wait_pending (test); test_close_both_porters (test); teardown_test (test); } /* Test if the error is correctly propagated when a writing error occurs */ static void test_writing_error_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_porter_send_finish ( WOCKY_PORTER (source), res, &error)); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_writing_error (void) { test_data_t *test = setup_test (); WockyStanza *s; test_open_connection (test); wocky_test_output_stream_set_write_error (test->stream->stream0_output); s = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "juliet@example.com", "romeo@example.net", NULL); test->outstanding++; wocky_porter_send_async (test->sched_in, s, NULL, test_writing_error_cb, test); test_wait_pending (test); g_object_unref (s); teardown_test (test); } /* Test send with reply */ static void test_send_iq_sent_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *data = (test_data_t *) user_data; g_assert (wocky_porter_send_finish ( WOCKY_PORTER (source), res, NULL)); data->outstanding--; g_main_loop_quit (data->loop); } static gboolean test_send_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; const gchar *id; gboolean cancelled; WockyStanzaSubType sub_type; test_expected_stanza_received (test, stanza); id = wocky_node_get_attribute (wocky_stanza_get_top_node (stanza), "id"); wocky_stanza_get_type_info (stanza, NULL, &sub_type); /* Reply of the "set" IQ is not expected as we are going to cancel it */ cancelled = (sub_type == WOCKY_STANZA_SUB_TYPE_SET); if (cancelled) g_cancellable_cancel (test->cancellable); /* Send a spoofed reply; should be ignored */ reply = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, "oscar@example.net", "juliet@example.com", '@', "id", id, NULL); wocky_porter_send (porter, reply); g_object_unref (reply); /* Send a reply without 'id' attribute; should be ignored */ reply = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, "romeo@example.net", "juliet@example.com", NULL); wocky_porter_send (porter, reply); g_object_unref (reply); /* Send reply */ reply = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, "romeo@example.net", "juliet@example.com", '@', "id", id, NULL); wocky_porter_send_async (porter, reply, NULL, test_send_iq_sent_cb, test); if (!cancelled) g_queue_push_tail (test->expected_stanzas, reply); else g_object_unref (reply); test->outstanding++; return TRUE; } static gboolean test_send_iq_abnormal_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; const gchar *id; WockyStanzaSubType sub_type; test_expected_stanza_received (test, stanza); id = wocky_node_get_attribute (wocky_stanza_get_top_node (stanza), "id"); wocky_stanza_get_type_info (stanza, NULL, &sub_type); /* Send a spoofed reply; should be ignored */ reply = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, "oscar@example.net", "juliet@example.com", '@', "id", id, NULL); wocky_porter_send (porter, reply); g_object_unref (reply); /* Send a reply without 'id' attribute; should be ignored */ reply = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, "rOmeO@examplE.neT", "juLiet@Example.cOm", NULL); wocky_porter_send (porter, reply); g_object_unref (reply); /* Send reply */ reply = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, "roMeo@eXampLe.net", "JulieT@ExamplE.com", '@', "id", id, NULL); wocky_porter_send_async (porter, reply, NULL, test_send_iq_sent_cb, test); g_queue_push_tail (test->expected_stanzas, reply); test->outstanding++; return TRUE; } static void test_send_iq_reply_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; reply = wocky_porter_send_iq_finish (WOCKY_PORTER (source), res, NULL); g_assert (reply != NULL); test_expected_stanza_received (test, reply); g_object_unref (reply); } static void test_send_iq_cancelled_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; GError *error = NULL; reply = wocky_porter_send_iq_finish (WOCKY_PORTER (source), res, &error); g_assert (reply == NULL); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_send_iq (void) { test_data_t *test = setup_test (); WockyStanza *iq; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_porter_start (test->sched_in); /* register an IQ handler */ wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, 0, test_send_iq_cb, test, NULL); /* Send an IQ query. We are going to cancel it after it has been received * but before we receive the reply so the callback won't be called.*/ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, "juliet@example.com", "romeo@example.net", NULL); wocky_porter_send_iq_async (test->sched_in, iq, test->cancellable, test_send_iq_cancelled_cb, test); g_queue_push_tail (test->expected_stanzas, iq); test->outstanding += 2; test_wait_pending (test); /* Send an IQ query */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", '@', "id", "1", NULL); wocky_porter_send_iq_async (test->sched_in, iq, NULL, test_send_iq_reply_cb, test); g_queue_push_tail (test->expected_stanzas, iq); test->outstanding += 2; test_wait_pending (test); test_close_both_porters (test); teardown_test (test); } static gboolean test_acknowledge_iq_acknowledge_cb ( WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = user_data; wocky_porter_acknowledge_iq (porter, stanza, '(', "sup-dawg", '@', "lions", "tigers", ')', NULL); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void test_iq_reply_no_id_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { WockyPorter *porter = WOCKY_PORTER (source); test_data_t *test = user_data; WockyStanza *reply; WockyStanza *expected_reply; GError *error = NULL; reply = wocky_porter_send_iq_finish (porter, result, &error); g_assert_no_error (error); g_assert (reply != NULL); expected_reply = g_queue_pop_head (test->expected_stanzas); g_assert (expected_reply != NULL); /* If we got the reply dispatched to us, the ID was correct — this is tested * elsewhere. So we don't need to test it again here. */ test_assert_stanzas_equal_no_id (reply, expected_reply); g_object_unref (reply); g_object_unref (expected_reply); test->outstanding--; g_main_loop_quit (test->loop); } /* Tests wocky_porter_acknowledge_iq(). */ static void test_acknowledge_iq (void) { test_data_t *test = setup_test (); WockyStanza *iq, *expected_reply; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_porter_start (test->sched_in); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, 0, test_acknowledge_iq_acknowledge_cb, test, NULL); /* We re-construct expected_reply for every test because… * test_assert_stanzas_equal_no_id() modifies the stanzas it's comparing to * add an id='' to the one which doesn't have one. */ /* Send a legal IQ (with a single child element). */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", '(', "sup-dawg", ')', NULL); expected_reply = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, "romeo@example.net", "juliet@example.com", '(', "sup-dawg", '@', "lions", "tigers", ')', NULL); wocky_porter_send_iq_async (test->sched_in, iq, NULL, test_iq_reply_no_id_cb, test); test->outstanding += 2; g_queue_push_tail (test->expected_stanzas, expected_reply); g_object_unref (iq); /* Send an illegal IQ with two child elements. We expect that * wocky_porter_acknowledge_iq() should cope. */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", '(', "sup-dawg", ')', '(', "i-heard-you-like-stanzas", ')', NULL); expected_reply = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, "romeo@example.net", "juliet@example.com", '(', "sup-dawg", '@', "lions", "tigers", ')', NULL); wocky_porter_send_iq_async (test->sched_in, iq, NULL, test_iq_reply_no_id_cb, test); test->outstanding += 2; g_queue_push_tail (test->expected_stanzas, expected_reply); g_object_unref (iq); /* Send another illegal IQ, with no child element at all. Obviously in real * life it should be nacked, but wocky_porter_acknowledge_iq() should still * cope. */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", NULL); expected_reply = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, "romeo@example.net", "juliet@example.com", '(', "sup-dawg", '@', "lions", "tigers", ')', NULL); wocky_porter_send_iq_async (test->sched_in, iq, NULL, test_iq_reply_no_id_cb, test); test->outstanding += 2; g_queue_push_tail (test->expected_stanzas, expected_reply); g_object_unref (iq); /* Finally, send an IQ that doesn't have an id='' attribute. This is really * illegal, but wocky_porter_acknowledge_iq() needs to deal because it * happens in practice. */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", NULL); wocky_porter_send (test->sched_in, iq); /* In this case, we only expect the recipient's callback to fire. There's no * way for it to send us an IQ back, so we don't need to wait for a reply * there. */ test->outstanding += 1; g_object_unref (iq); /* Off we go! */ test_wait_pending (test); test_close_both_porters (test); teardown_test (test); } static gboolean test_send_iq_error_nak_cb ( WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = user_data; wocky_porter_send_iq_error (porter, stanza, WOCKY_XMPP_ERROR_BAD_REQUEST, "bye bye beautiful"); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } /* Tests wocky_porter_send_iq_error(). */ static void test_send_iq_error (void) { test_data_t *test = setup_test (); WockyStanza *iq, *expected_reply; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_porter_start (test->sched_in); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, 0, test_send_iq_error_nak_cb, test, NULL); /* Send a legal IQ (with a single child element). */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", '(', "sup-dawg", ')', NULL); expected_reply = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, "romeo@example.net", "juliet@example.com", '(', "sup-dawg", ')', '(', "error", '@', "code", "400", '@', "type", "modify", '(', "bad-request", ':', WOCKY_XMPP_NS_STANZAS, ')', '(', "text", ':', WOCKY_XMPP_NS_STANZAS, '$', "bye bye beautiful", ')', ')', NULL); wocky_porter_send_iq_async (test->sched_in, iq, NULL, test_iq_reply_no_id_cb, test); test->outstanding += 2; g_queue_push_tail (test->expected_stanzas, expected_reply); g_object_unref (iq); /* Send an illegal IQ with two child elements. We expect that * wocky_porter_send_iq_error() should cope by just picking the first one. */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", '(', "sup-dawg", ')', '(', "i-heard-you-like-stanzas", ')', NULL); expected_reply = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, "romeo@example.net", "juliet@example.com", '(', "sup-dawg", ')', '(', "error", '@', "code", "400", '@', "type", "modify", '(', "bad-request", ':', WOCKY_XMPP_NS_STANZAS, ')', '(', "text", ':', WOCKY_XMPP_NS_STANZAS, '$', "bye bye beautiful", ')', ')', NULL); wocky_porter_send_iq_async (test->sched_in, iq, NULL, test_iq_reply_no_id_cb, test); test->outstanding += 2; g_queue_push_tail (test->expected_stanzas, expected_reply); g_object_unref (iq); /* Send another illegal IQ, with no child element at all. * wocky_porter_send_iq_error() should not blow up. */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", NULL); expected_reply = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, "romeo@example.net", "juliet@example.com", '(', "error", '@', "code", "400", '@', "type", "modify", '(', "bad-request", ':', WOCKY_XMPP_NS_STANZAS, ')', '(', "text", ':', WOCKY_XMPP_NS_STANZAS, '$', "bye bye beautiful", ')', ')', NULL); wocky_porter_send_iq_async (test->sched_in, iq, NULL, test_iq_reply_no_id_cb, test); test->outstanding += 2; g_queue_push_tail (test->expected_stanzas, expected_reply); g_object_unref (iq); /* Finally, send an IQ that doesn't have an id='' attribute. This is really * illegal, but wocky_porter_send_iq_error() needs to deal because it * happens in practice. */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", NULL); wocky_porter_send (test->sched_in, iq); /* In this case, we only expect the recipient's callback to fire. There's no * way for it to send us an IQ back, so we don't need to wait for a reply * there. */ test->outstanding += 1; g_object_unref (iq); test_wait_pending (test); test_close_both_porters (test); teardown_test (test); } typedef struct { test_data_t *test; GError error; } TestSendIqGErrorCtx; static gboolean test_send_iq_gerror_nak_cb ( WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { TestSendIqGErrorCtx *ctx = user_data; wocky_porter_send_iq_gerror (porter, stanza, &ctx->error); ctx->test->outstanding--; g_main_loop_quit (ctx->test->loop); return TRUE; } /* Tests wocky_porter_send_iq_gerror(). */ static void test_send_iq_gerror (void) { test_data_t *test = setup_test (); TestSendIqGErrorCtx ctx = { test, }; WockyStanza *iq, *expected_reply; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_porter_start (test->sched_in); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, 0, test_send_iq_gerror_nak_cb, &ctx, NULL); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", '(', "sup-dawg", ')', NULL); /* Test responding with a simple error */ ctx.error.domain = WOCKY_XMPP_ERROR; ctx.error.code = WOCKY_XMPP_ERROR_UNEXPECTED_REQUEST; ctx.error.message = "i'm twelve years old and what is this?"; expected_reply = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, "romeo@example.net", "juliet@example.com", '(', "sup-dawg", ')', '(', "error", '@', "code", "400", '@', "type", "wait", '(', "unexpected-request", ':', WOCKY_XMPP_NS_STANZAS, ')', '(', "text", ':', WOCKY_XMPP_NS_STANZAS, '$', ctx.error.message, ')', ')', NULL); wocky_porter_send_iq_async (test->sched_in, iq, NULL, test_iq_reply_no_id_cb, test); test->outstanding += 2; g_queue_push_tail (test->expected_stanzas, expected_reply); test_wait_pending (test); /* Test responding with an application-specific error */ ctx.error.domain = WOCKY_JINGLE_ERROR; ctx.error.code = WOCKY_JINGLE_ERROR_OUT_OF_ORDER; ctx.error.message = "i'm twelve years old and what is this?"; expected_reply = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, "romeo@example.net", "juliet@example.com", '(', "sup-dawg", ')', '(', "error", '@', "code", "400", '@', "type", "wait", '(', "unexpected-request", ':', WOCKY_XMPP_NS_STANZAS, ')', '(', "out-of-order", ':', WOCKY_XMPP_NS_JINGLE_ERRORS, ')', '(', "text", ':', WOCKY_XMPP_NS_STANZAS, '$', ctx.error.message, ')', ')', NULL); wocky_porter_send_iq_async (test->sched_in, iq, NULL, test_iq_reply_no_id_cb, test); test->outstanding += 2; g_queue_push_tail (test->expected_stanzas, expected_reply); test_wait_pending (test); g_object_unref (iq); test_close_both_porters (test); teardown_test (test); } static void test_send_iq_abnormal (void) { test_data_t *test = setup_test (); WockyStanza *iq; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_porter_start (test->sched_in); /* register an IQ handler (to send both the good and spoofed reply) */ wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, 0, test_send_iq_abnormal_cb, test, NULL); /* Send an IQ query */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "julIet@exampLe.com", "RoMeO@eXample.net", '@', "id", "1", NULL); wocky_porter_send_iq_async (test->sched_in, iq, NULL, test_send_iq_reply_cb, test); g_queue_push_tail (test->expected_stanzas, iq); test->outstanding += 2; test_wait_pending (test); test_close_both_porters (test); teardown_test (test); } /* Test if the error is correctly propagated when a writing error occurs while * sending an IQ */ static void test_send_iq_error_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_porter_send_iq_finish ( WOCKY_PORTER (source), res, &error)); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_error_while_sending_iq (void) { test_data_t *test = setup_test (); WockyStanza *iq; test_open_connection (test); wocky_test_output_stream_set_write_error (test->stream->stream0_output); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", '@', "id", "one", NULL); test->outstanding++; wocky_porter_send_iq_async (test->sched_in, iq, NULL, test_send_iq_error_cb, test); test_wait_pending (test); g_object_unref (iq); teardown_test (test); } /* Test implementing a filter using handlers */ static gboolean test_handler_filter_get_filter (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanzaSubType sub_type; gboolean result; wocky_stanza_get_type_info (stanza, NULL, &sub_type); if (sub_type == WOCKY_STANZA_SUB_TYPE_GET) { /* We filter 'get' IQ. Return TRUE to say that we handled this stanza so * the handling process will be stopped */ result = TRUE; } else { /* We don't handle this stanza so the other callback will be called */ g_queue_push_tail (test->expected_stanzas, stanza); g_object_ref (stanza); test->outstanding++; result = FALSE; } test_expected_stanza_received (test, stanza); return result; } static gboolean test_handler_filter_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; test_expected_stanza_received (test, stanza); return TRUE; } static void test_handler_filter (void) { test_data_t *test = setup_test (); WockyStanza *iq; test_open_both_connections (test); /* register an IQ handler which will act as a filter */ wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, 10, test_handler_filter_get_filter, test, NULL); /* register another handler with a smaller priority which will be called * after the filter */ wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, 5, test_handler_filter_cb, test, NULL); wocky_porter_start (test->sched_out); /* Send a 'get' IQ that will be filtered */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", NULL); send_stanza (test, iq, TRUE); /* Send a 'set' IQ that won't be filtered */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, "juliet@example.com", "romeo@example.net", NULL); send_stanza (test, iq, TRUE); test_close_porter (test); teardown_test (test); } static void unhandled_iq_reply_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { WockyPorter *porter = WOCKY_PORTER (source); test_data_t *test = user_data; GError *error = NULL; WockyStanza *reply = wocky_porter_send_iq_finish (porter, result, &error); gboolean is_error; WockyXmppErrorType type; GError *core = NULL; GError *specialized = NULL; WockyNode *specialized_node; g_assert_no_error (error); g_assert (reply != NULL); is_error = wocky_stanza_extract_errors (reply, &type, &core, &specialized, &specialized_node); /* The reply should have type='error'. */ g_assert (is_error); g_assert_cmpuint (type, ==, WOCKY_XMPP_ERROR_TYPE_CANCEL); g_assert_error (core, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_SERVICE_UNAVAILABLE); /* There should be no non-XMPP Core error condition. */ g_assert_no_error (specialized); g_assert (specialized_node == NULL); g_clear_error (&core); g_object_unref (reply); test->outstanding--; g_main_loop_quit (test->loop); } static void test_unhandled_iq (void) { test_data_t *test = setup_test (); WockyStanza *iq = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, NULL, '(', "framed-photograph", ':', "http://kimjongillookingatthings.tumblr.com", ')', NULL); test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_porter_start (test->sched_in); wocky_porter_send_iq_async (test->sched_out, iq, NULL, unhandled_iq_reply_cb, test); test->outstanding++; test_wait_pending (test); g_object_unref (iq); test_close_both_porters (test); teardown_test (test); } static gboolean test_handler_filter_from_juliet_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; const gchar *from; from = wocky_stanza_get_from (stanza); g_assert (!wocky_strdiff (from, "juliet@example.com")); test_expected_stanza_received (test, stanza); return TRUE; } static gboolean test_handler_filter_from_anyone_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; test_expected_stanza_received (test, stanza); return TRUE; } static void test_handler_filter_from (void) { test_data_t *test = setup_test (); WockyStanza *iq; test_open_both_connections (test); /* Register a handler for IQs with from=juliet@example.com */ wocky_porter_register_handler_from (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, "juliet@example.com", 10, test_handler_filter_from_juliet_cb, test, NULL); /* Register another handler, at a lower priority, for IQs from anyone */ wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, 5, test_handler_filter_from_anyone_cb, test, NULL); wocky_porter_start (test->sched_out); /* Send an IQ that will be filtered by from_juliet only */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", NULL); send_stanza (test, iq, TRUE); /* Send an IQ that will be filtered by from_null only */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "romeo@example.com", "juliet@example.net", NULL); send_stanza (test, iq, TRUE); /* Send an IQ that will be filtered by from_null only */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, "romeo@example.net", NULL); send_stanza (test, iq, TRUE); test_close_porter (test); teardown_test (test); } /* test if the right error is raised when trying to send an invalid IQ */ static void test_send_invalid_iq_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; GError *error = NULL; reply = wocky_porter_send_iq_finish (WOCKY_PORTER (source), res, &error); g_assert (reply == NULL); g_assert_error (error, WOCKY_PORTER_ERROR, WOCKY_PORTER_ERROR_NOT_IQ); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_send_invalid_iq (void) { test_data_t *test = setup_test (); WockyStanza *iq; test_open_both_connections (test); wocky_porter_start (test->sched_out); /* Try to send a message as an IQ */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, "juliet@example.com", "romeo@example.net", NULL); wocky_porter_send_iq_async (test->sched_in, iq, test->cancellable, test_send_invalid_iq_cb, test); g_object_unref (iq); test->outstanding++; /* Try to send an IQ reply */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, "juliet@example.com", "romeo@example.net", NULL); wocky_porter_send_iq_async (test->sched_in, iq, test->cancellable, test_send_invalid_iq_cb, test); g_object_unref (iq); test->outstanding++; test_wait_pending (test); test_close_porter (test); teardown_test (test); } /* Test sending IQ's to the server (no 'to' attribute). The JID we believe we * have matters, here. */ static gboolean test_send_iq_server_received_cb (WockyPorter *porter, WockyStanza *iq, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; WockyNode *node; const gchar *id; const gchar *from; test_expected_stanza_received (test, iq); node = wocky_stanza_get_top_node (iq); id = wocky_node_get_attribute (node, "id"); if (wocky_node_get_child (node, "first") != NULL) /* No from attribute */ from = NULL; else if (wocky_node_get_child (node, "second") != NULL) /* bare JID */ from = "juliet@example.com"; else if (wocky_node_get_child (node, "third") != NULL) /* full JID */ from = "juliet@example.com/Balcony"; else g_assert_not_reached (); /* Send reply */ reply = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, from, "juliet@example.com/Balcony", '@', "id", id, NULL); wocky_porter_send_async (porter, reply, NULL, test_send_iq_sent_cb, test); g_queue_push_tail (test->expected_stanzas, reply); test->outstanding++; return TRUE; } static void test_send_iq_server (void) { /* In this test "in" is Juliet, and "out" is her server */ test_data_t *test = setup_test_with_jids ("juliet@example.com/Balcony", "example.com"); WockyStanza *iq; const gchar *node[] = { "first", "second", "third", NULL }; guint i; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_porter_start (test->sched_in); /* register an IQ handler */ wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, test_send_iq_server_received_cb, test, NULL); /* From XMPP RFC: * "When a server generates a stanza from the server itself for delivery to * a connected client (e.g., in the context of data storage services * provided by the server on behalf of the client), the stanza MUST either * (1) not include a 'from' attribute or (2) include a 'from' attribute * whose value is the account's bare JID () or client's full * JID ()". * * Each reply will test one of these 3 options. */ for (i = 0; node[i] != NULL; i++) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", NULL, '(', node[i], ')', NULL); wocky_porter_send_iq_async (test->sched_in, iq, test->cancellable, test_send_iq_reply_cb, test); g_queue_push_tail (test->expected_stanzas, iq); test->outstanding += 2; test_wait_pending (test); } /* The same, but sending to our own bare JID. For instance, when we query * disco#info on our own bare JID on Prosody 0.6.1, the reply has no 'from' * attribute. */ for (i = 0; node[i] != NULL; i++) { iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "JULIET@EXAMPLE.COM", '(', node[i], ')', NULL); wocky_porter_send_iq_async (test->sched_in, iq, test->cancellable, test_send_iq_reply_cb, test); g_queue_push_tail (test->expected_stanzas, iq); test->outstanding += 2; test_wait_pending (test); } test_close_both_porters (test); teardown_test (test); } /* Unref the porter in the async close callback */ static void test_unref_when_closed_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; g_assert (wocky_porter_close_finish ( WOCKY_PORTER (source), res, NULL)); /* Porter has been closed, unref it */ g_object_unref (test->session_in); test->session_in = NULL; test->outstanding--; g_main_loop_quit (test->loop); } static void test_unref_when_closed (void) { test_data_t *test = setup_test (); test_open_both_connections (test); wocky_porter_start (test->sched_in); wocky_xmpp_connection_recv_stanza_async (test->out, NULL, test_close_stanza_received_cb, test); wocky_porter_close_async (test->sched_in, NULL, test_unref_when_closed_cb, test); test->outstanding += 3; test_wait_pending (test); teardown_test (test); } /* Both sides try to close the connection at the same time */ static void test_close_simultanously_recv_stanza_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *s; GError *error = NULL; s = wocky_xmpp_connection_recv_stanza_finish (WOCKY_XMPP_CONNECTION (source), res, &error); g_assert (s == NULL); g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_CLOSED); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_close_simultanously (void) { test_data_t *test = setup_test (); test_open_both_connections (test); wocky_porter_start (test->sched_in); /* Sent close from one side */ wocky_xmpp_connection_send_close_async (test->out, NULL, close_sent_cb, test); /* .. and from the other */ wocky_porter_close_async (test->sched_in, NULL, test_unref_when_closed_cb, test); /* Wait that the 'in' side received the close */ test->outstanding += 2; test_wait_pending (test); /* Now read the close on the 'out' side */ wocky_xmpp_connection_recv_stanza_async (test->out, NULL, test_close_simultanously_recv_stanza_cb, test); test->outstanding++; test_wait_pending (test); teardown_test (test); } /* We sent our close stanza but a reading error occurs (as a disconnection for * example) before the other side sends his close */ static void test_close_error_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_porter_close_finish ( WOCKY_PORTER (source), res, &error)); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_close_error (void) { test_data_t *test = setup_test (); wocky_test_stream_set_write_mode (test->stream->stream0_output, WOCKY_TEST_STREAM_WRITE_COMPLETE); test_open_both_connections (test); wocky_porter_start (test->sched_in); /* Sent close */ wocky_porter_close_async (test->sched_in, NULL, test_close_error_cb, test); wocky_xmpp_connection_recv_stanza_async (test->out, NULL, test_close_simultanously_recv_stanza_cb, test); /* Wait that the 'out' side received the close */ test->outstanding += 1; test_wait_pending (test); /* Something goes wrong */ wocky_test_input_stream_set_read_error (test->stream->stream0_input); /* The close operation is completed with an error */ test->outstanding += 1; test_wait_pending (test); teardown_test (test); } /* Try to send an IQ using a closing porter and cancel it immediately */ static void test_cancel_iq_closing (void) { test_data_t *test = setup_test (); WockyStanza *iq; test_open_both_connections (test); wocky_porter_start (test->sched_in); /* Start to close the porter */ wocky_porter_close_async (test->sched_in, NULL, test_close_sched_close_cb, test); /* Try to send a stanza using the closing porter */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, "juliet@example.com", "romeo@example.net", NULL); wocky_porter_send_iq_async (test->sched_in, iq, test->cancellable, test_send_closing_cb, test); /* Cancel the sending */ g_cancellable_cancel (test->cancellable); test->outstanding += 1; test_wait_pending (test); /* Make the call to wocky_porter_close_async() finish... */ wocky_xmpp_connection_send_close_async (test->out, NULL, close_sent_cb, test); test->outstanding += 2; test_wait_pending (test); g_object_unref (iq); teardown_test (test); } /* test stream errors */ static void test_stream_error_force_close_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; wocky_porter_force_close_finish ( WOCKY_PORTER (source), res, &error); g_assert_no_error (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_stream_error_cb (WockyPorter *porter, GQuark domain, guint code, const gchar *message, test_data_t *test) { GError *err = g_error_new_literal (domain, code, message); g_assert_error (err, WOCKY_XMPP_STREAM_ERROR, WOCKY_XMPP_STREAM_ERROR_CONFLICT); g_error_free (err); /* force closing of the porter */ wocky_porter_force_close_async (porter, NULL, test_stream_error_force_close_cb, test); } static void test_stream_error (void) { test_data_t *test = setup_test (); WockyStanza *error; test_open_both_connections (test); wocky_porter_start (test->sched_out); g_signal_connect (test->sched_out, "remote-error", G_CALLBACK (test_stream_error_cb), test); test->outstanding++; /* Try to send a stanza using the closing porter */ error = wocky_stanza_build (WOCKY_STANZA_TYPE_STREAM_ERROR, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, ':', WOCKY_XMPP_NS_STREAM, '(', "conflict", ':', WOCKY_XMPP_NS_STREAMS, ')', NULL); wocky_porter_send_async (test->sched_in, error, NULL, send_stanza_cb, test); test->outstanding++; test_wait_pending (test); g_object_unref (error); teardown_test (test); } /* test wocky_porter_close_force */ static void test_close_force_stanza_sent_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *data = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_porter_send_finish ( WOCKY_PORTER (source), res, &error)); g_assert_error (error, WOCKY_PORTER_ERROR, WOCKY_PORTER_ERROR_FORCIBLY_CLOSED); data->outstanding--; g_error_free (error); g_main_loop_quit (data->loop); } static void test_close_force_closed_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_porter_close_finish ( WOCKY_PORTER (source), res, &error)); g_assert_error (error, WOCKY_PORTER_ERROR, WOCKY_PORTER_ERROR_FORCIBLY_CLOSED); test->outstanding--; g_error_free (error); g_main_loop_quit (test->loop); } static void test_close_force_force_closed_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; wocky_porter_force_close_finish ( WOCKY_PORTER (source), res, &error); g_assert_no_error (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_close_force_closing_cb (WockyPorter *porter, test_data_t *test) { static gboolean fired = FALSE; g_assert (!fired); fired = TRUE; test->outstanding--; g_main_loop_quit (test->loop); } static void test_close_force (void) { test_data_t *test = setup_test (); WockyStanza *s; wocky_test_stream_set_write_mode (test->stream->stream0_output, WOCKY_TEST_STREAM_WRITE_COMPLETE); test_open_both_connections (test); wocky_porter_start (test->sched_in); /* Try to send a stanza; it will never reach the other side */ s = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "juliet@example.com", "romeo@example.net", NULL); g_signal_connect (test->sched_in, "closing", G_CALLBACK (test_close_force_closing_cb), test); wocky_porter_send_async (test->sched_in, s, NULL, test_close_force_stanza_sent_cb, test); /* Try to properly close the connection; we'll give up before it has been * done */ wocky_porter_close_async (test->sched_in, NULL, test_close_force_closed_cb, test); /* force closing */ wocky_porter_force_close_async (test->sched_in, NULL, test_close_force_force_closed_cb, test); test->outstanding += 4; test_wait_pending (test); g_object_unref (s); teardown_test (test); } /* call force_close after an error appeared on the connection */ static void test_close_force_after_error_error_cb (WockyPorter *porter, GQuark domain, guint code, const gchar *message, test_data_t *test) { GError *err = g_error_new_literal (domain, code, message); g_assert_error (err, WOCKY_XMPP_STREAM_ERROR, WOCKY_XMPP_STREAM_ERROR_CONFLICT); g_error_free (err); test->outstanding--; g_main_loop_quit (test->loop); } static void test_close_force_after_error (void) { test_data_t *test = setup_test (); WockyStanza *error; test_open_both_connections (test); wocky_porter_start (test->sched_out); g_signal_connect (test->sched_out, "remote-error", G_CALLBACK (test_close_force_after_error_error_cb), test); test->outstanding++; error = wocky_stanza_build (WOCKY_STANZA_TYPE_STREAM_ERROR, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, ':', WOCKY_XMPP_NS_STREAM, '(', "conflict", ':', WOCKY_XMPP_NS_STREAMS, ')', NULL); wocky_porter_send_async (test->sched_in, error, NULL, send_stanza_cb, test); test->outstanding++; test_wait_pending (test); /* Stream error has been handled, now force closing */ wocky_porter_force_close_async (test->sched_out, NULL, test_close_force_force_closed_cb, test); test->outstanding++; test_wait_pending (test); g_object_unref (error); teardown_test (test); } /* Test calling force_close after close has been called and the close stream * stanza has been sent */ static void test_close_force_after_close_sent_stanza_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyXmppConnection *connection = WOCKY_XMPP_CONNECTION (source); WockyStanza *s; GError *error = NULL; s = wocky_xmpp_connection_recv_stanza_finish (connection, res, &error); g_assert (s == NULL); /* connection has been disconnected */ g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_CLOSED); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_close_force_after_close_sent (void) { test_data_t *test = setup_test (); test_open_both_connections (test); wocky_porter_start (test->sched_in); wocky_xmpp_connection_recv_stanza_async (test->out, NULL, test_close_force_after_close_sent_stanza_cb, test); /* Try to properly close the connection; we'll give up before it has been * done */ wocky_porter_close_async (test->sched_in, NULL, test_close_force_closed_cb, test); /* Wait for the close stanza */ test->outstanding++; test_wait_pending (test); /* force closing */ wocky_porter_force_close_async (test->sched_in, NULL, test_close_force_force_closed_cb, test); test->outstanding += 2; test_wait_pending (test); teardown_test (test); } /* The remote connection is closed while we are waiting for an IQ reply */ static void open_connections_and_send_one_iq (test_data_t *test, GAsyncReadyCallback send_iq_callback) { WockyStanza *iq; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_porter_start (test->sched_in); /* register an IQ handler */ wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, 0, test_receive_stanza_received_cb, test, NULL); /* Send an IQ query */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", '@', "id", "1", NULL); wocky_porter_send_iq_async (test->sched_in, iq, NULL, send_iq_callback, test); g_queue_push_tail (test->expected_stanzas, iq); /* wait that the IQ has been received */ test->outstanding += 1; test_wait_pending (test); } static void test_wait_iq_reply_close_reply_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; GError *error = NULL; reply = wocky_porter_send_iq_finish (WOCKY_PORTER (source), res, &error); g_assert (reply == NULL); g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_CLOSED); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_wait_iq_reply_close (void) { test_data_t *test = setup_test (); open_connections_and_send_one_iq (test, test_wait_iq_reply_close_reply_cb); /* the other side closes the connection (and so won't send the IQ reply) */ wocky_porter_close_async (test->sched_out, NULL, test_close_sched_close_cb, test); /* the send IQ operation is finished (with an error) */ test->outstanding += 1; test_wait_pending (test); wocky_porter_close_async (test->sched_in, NULL, test_close_sched_close_cb, test); /* the 2 close operations are completed */ test->outstanding += 2; test_wait_pending (test); teardown_test (test); } /* Send an IQ and then force the closing of the connection before we received * the reply */ static void test_wait_iq_reply_force_close_reply_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; GError *error = NULL; reply = wocky_porter_send_iq_finish (WOCKY_PORTER (source), res, &error); g_assert (reply == NULL); g_assert_error (error, WOCKY_PORTER_ERROR, WOCKY_PORTER_ERROR_FORCIBLY_CLOSED); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_wait_iq_reply_force_close (void) { test_data_t *test = setup_test (); open_connections_and_send_one_iq (test, test_wait_iq_reply_force_close_reply_cb); /* force closing of our connection */ wocky_porter_force_close_async (test->sched_in, NULL, test_close_force_force_closed_cb, test); /* the send IQ operation is finished (with an error) and the force close * operation is completed */ test->outstanding += 2; test_wait_pending (test); wocky_porter_force_close_async (test->sched_out, NULL, test_close_force_force_closed_cb, test); test->outstanding += 1; test_wait_pending (test); teardown_test (test); } /* this tries to catch the case where we receive a remote-error, which * * results in a wocky_porter_force_close_async in the connected signal * * handler but the internal stanza_received_cb _also_ attempts to force * * a shutdown: when correctly functioning, only one of these will result * * in a force close operation and the other will noop. * * Typical failure cases are the shutdown not happening at all or being * * attempted twice and failing because the porter can only support one * * force close attempt (both indicate broken logic in the porter) */ static void test_remote_error (void) { test_data_t *test = setup_test (); WockyStanza *error = wocky_stanza_build (WOCKY_STANZA_TYPE_STREAM_ERROR, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, ':', WOCKY_XMPP_NS_STREAM, '(', "conflict", ':', WOCKY_XMPP_NS_STREAMS, ')', NULL); test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_porter_start (test->sched_in); /* this callback will force_close_async the OUT porter, * * and decrement test->outstanding when it has done so */ g_signal_connect (test->sched_out, "remote-error", G_CALLBACK (test_stream_error_cb), test); /* this pumps a stream error through the IN (server) porter * * which triggers the remote-error signal from the OUT porter */ wocky_porter_send_async (test->sched_in, error, NULL, send_stanza_cb, test); test->outstanding++; test_wait_pending (test); test->outstanding++; /* this is for the signal connect above */ /* this closes the IN (server) porter so that the test doesn't fail (we * * don't really care about the IN porter for the purposes of this test) */ wocky_porter_force_close_async (test->sched_in, NULL, test_close_force_force_closed_cb, test); test->outstanding++; /* now wait for the IN porter to shutdown and the remote-error callback * * to shut down the OUT porter */ test_wait_pending (test); g_object_unref (error); teardown_test (test); } /* Herein lies a regression test for a bug where, if a stanza had been passed * by the porter to the XmppConnection but not actually sent when the porter * was unreffed, the subsequent callback from the XmppConnection would crash * us. */ static gboolean idle_main_loop_quit (gpointer user_data) { g_main_loop_quit (user_data); return FALSE; } static void send_and_disconnect (void) { test_data_t *test = setup_test (); WockyStanza *lions = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, NULL, '(', "dummy", ':', "xmpp:stanza", '(', "nothing-to-see-here", ')', ')', NULL); GMainLoop *loop = g_main_loop_ref (test->loop); /* We try to send any old stanza. */ wocky_porter_send_async (test->sched_in, lions, NULL, NULL, NULL); /* Without giving the mainloop a chance to spin to call any callbacks at all, * we tear everything down, including the porters. This will make sched_in * add an idle to dispatch the (non-existent) callback for the stanza sent * above, saying that sending it failed. */ teardown_test (test); /* Now we spin the main loop until all (higher-priority) idles have fired. * * The bug we're testing for occured because the porter didn't keep itself * alive for the duration of the wocky_xmpp_connection_send_stanza_async() * call. So, when it'd finished calling the callback above, it'd die, and * then the send_stanza() operations would finish, and the porter's callback * would try to use the newly-freed porter and choke. */ g_idle_add_full (G_PRIORITY_LOW, idle_main_loop_quit, loop, NULL); g_main_loop_run (loop); g_main_loop_unref (loop); g_object_unref (lions); } static gboolean got_stanza_for_example_com ( WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = user_data; g_assert_cmpstr (wocky_stanza_get_from (stanza), ==, "example.com"); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } /* This is a regression test for a bug where registering a handler for a JID * with no node part was equivalent to registering a handler with from=NULL; * that is, we'd erroneously pass stanzas from *any* server to the handler * function even if it explicitly specified a JID which was just a domain, as * opposed to a JID with an '@' sign in it. */ static void handler_for_domain (void) { test_data_t *test = setup_test (); WockyStanza *irrelevant, *relevant; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_porter_start (test->sched_in); wocky_porter_register_handler_from (test->sched_in, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "example.com", WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, got_stanza_for_example_com, test, NULL); /* Send a stanza from some other random jid (at example.com, for the sake of * argument). The porter should ignore this stanza. */ irrelevant = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "lol@example.com", NULL, '(', "this-is-bullshit", ')', NULL); wocky_porter_send (test->sched_out, irrelevant); g_object_unref (irrelevant); relevant = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "example.com", NULL, '(', "i-am-a-fan-of-cocaine", ')', NULL); wocky_porter_send (test->sched_out, relevant); g_object_unref (relevant); test->outstanding += 1; test_wait_pending (test); test_close_both_porters (test); teardown_test (test); } static gboolean got_stanza_from_anyone ( WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = user_data; WockyNode *top = wocky_stanza_get_top_node (stanza); WockyNode *query = wocky_node_get_first_child (top); g_assert_cmpstr (query->name, ==, "anyone"); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static gboolean got_stanza_from_ourself ( WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = user_data; WockyNode *top = wocky_stanza_get_top_node (stanza); WockyNode *query = wocky_node_get_first_child (top); g_assert_cmpstr (query->name, ==, "ourself"); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static gboolean got_stanza_from_server ( WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = user_data; WockyNode *top = wocky_stanza_get_top_node (stanza); WockyNode *query = wocky_node_get_first_child (top); g_assert_cmpstr (query->name, ==, "server"); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void send_query_from ( test_data_t *test, const gchar *from, const gchar *query) { WockyStanza *s = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, from, NULL, '(', query, ')', NULL); wocky_porter_send (test->sched_out, s); g_object_unref (s); test->outstanding += 1; test_wait_pending (test); } static void handler_from_anyone (void) { test_data_t *test = setup_test_with_jids ("juliet@capulet.lit/Balcony", "capulet.lit"); test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_porter_start (test->sched_in); wocky_c2s_porter_register_handler_from_server ( WOCKY_C2S_PORTER (test->sched_in), WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL + 10, got_stanza_from_server, test, NULL); /* A catch-all IQ get handler. */ wocky_porter_register_handler_from_anyone (test->sched_in, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, got_stanza_from_anyone, test, NULL); /* And, for completeness, a handler for IQs sent by any incarnation * of ourself, at a lower priority to the handler for stanzas from the * server, but a higher priority to the catch-all handler. */ wocky_porter_register_handler_from (test->sched_in, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@capulet.lit", WOCKY_PORTER_HANDLER_PRIORITY_NORMAL + 5, got_stanza_from_ourself, test, NULL); /* All of the handlers assert on the name of the first child node, and then * return TRUE to prevent the stanza being handed to a lower-priority * handler. */ /* A stanza from a contact on a completely different server should be picked * up only by the general handler. */ send_query_from (test, "romeo@montague.lit/Garden", "anyone"); /* A stanza from a contact on our server should be picked up only by the * general handler (irrespective of whether they have a resource). */ send_query_from (test, "tybalt@capulet.lit", "anyone"); send_query_from (test, "tybalt@capulet.lit/FIXME", "anyone"); /* A stanza from our server's domain should be matched by * got_stanza_from_server(). See fd.o#39057. */ send_query_from (test, "capulet.lit", "server"); /* On the other hand, a stanza with no sender should be picked up by * got_stanza_from_server(). */ send_query_from (test, NULL, "server"); /* Similarly, stanzas from our bare JID should be handed to * got_stanza_from_server(). Because that function returns TRUE, the stanza * should not be handed to got_stanza_from_ourself(). */ send_query_from (test, "juliet@capulet.lit", "server"); send_query_from (test, "jULIet@cAPUlet.lIT", "server"); /* Similarly, stanzas from our own full JID go to got_stanza_from_server. */ send_query_from (test, "juliet@capulet.lit/Balcony", "server"); send_query_from (test, "JUlIet@CAPulet.LIt/Balcony", "server"); /* But stanzas from our other resources should go to * got_stanza_from_ourself(). */ send_query_from (test, "juliet@capulet.lit/FIXME", "ourself"); /* Heh, heh, resources are case-sensitive */ send_query_from (test, "juliet@capulet.lit/balcony", "ourself"); /* Meanwhile, back in communist russia: */ /* КАПУЛЭТ капулэт */ test_close_both_porters (test); teardown_test (test); } static void closed_cb (GObject *source, GAsyncResult *result, gpointer user_data) { WockyPorter *porter = WOCKY_PORTER (source); test_data_t *test = user_data; gboolean ret; GError *error = NULL; ret = wocky_porter_close_finish (porter, result, &error); g_assert_no_error (error); g_assert (ret); test->outstanding--; g_main_loop_quit (test->loop); } static void sent_stanza_cb (GObject *source, GAsyncResult *result, gpointer user_data) { WockyPorter *porter = WOCKY_PORTER (source); test_data_t *test = user_data; gboolean ret; GError *error = NULL; ret = wocky_porter_send_finish (porter, result, &error); g_assert_no_error (error); g_assert (ret); /* Close up both porters. There's no reason why either of these operations * should fail. */ wocky_porter_close_async (test->sched_out, NULL, closed_cb, test); wocky_porter_close_async (test->sched_in, NULL, closed_cb, test); } static void close_from_send_callback (void) { test_data_t *test = setup_test (); WockyStanza *stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, '(', "body", '$', "I am made of chalk.", ')', NULL); /* Fire up porters in both directions. */ test_open_both_connections (test); wocky_porter_start (test->sched_in); wocky_porter_start (test->sched_out); /* Send a stanza. Once it's been safely sent, we should be able to close up * the connection in both directions without any trouble. */ wocky_porter_send_async (test->sched_in, stanza, NULL, sent_stanza_cb, test); g_object_unref (stanza); /* The two outstanding events are both porters ultimately closing * successfully. */ test->outstanding += 2; test_wait_pending (test); teardown_test (test); } /* Callbacks used in send_from_send_callback() */ static gboolean message_received_cb ( WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = user_data; test_expected_stanza_received (test, stanza); return TRUE; } static void sent_second_or_third_stanza_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = user_data; GError *error = NULL; wocky_porter_send_finish (WOCKY_PORTER (source), result, &error); g_assert_no_error (error); test->outstanding--; g_main_loop_quit (test->loop); } static void sent_first_stanza_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = user_data; WockyStanza *third_stanza; GError *error = NULL; wocky_porter_send_finish (WOCKY_PORTER (source), result, &error); g_assert_no_error (error); third_stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, '(', "body", '$', "I am made of dur butter.", ')', NULL); wocky_porter_send_async (test->sched_in, third_stanza, NULL, sent_second_or_third_stanza_cb, test); g_queue_push_tail (test->expected_stanzas, third_stanza); /* One for the callback; one for the receiving end. */ test->outstanding += 2; test->outstanding--; g_main_loop_quit (test->loop); } static void send_from_send_callback (void) { test_data_t *test = setup_test (); WockyStanza *stanza; test_open_both_connections (test); wocky_porter_start (test->sched_in); wocky_porter_start (test->sched_out); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, message_received_cb, test, '(', "body", ')', NULL); /* Send a stanza; in the callback for this stanza, we'll send another stanza. */ stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, '(', "body", '$', "I am made of chalk.", ')', NULL); wocky_porter_send_async (test->sched_in, stanza, NULL, sent_first_stanza_cb, test); g_queue_push_tail (test->expected_stanzas, stanza); /* One for the callback; one for the receiving end. */ test->outstanding += 2; /* But before we've had a chance to send that one, send a second. */ stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, '(', "body", '$', "I am made of jelly.", ')', NULL); wocky_porter_send_async (test->sched_in, stanza, NULL, sent_second_or_third_stanza_cb, test); g_queue_push_tail (test->expected_stanzas, stanza); /* One for the callback; one for the receiving end. */ test->outstanding += 2; test_wait_pending (test); test_close_both_porters (test); teardown_test (test); } static gboolean test_reply_from_domain_handler_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; const gchar *id; test_expected_stanza_received (test, stanza); id = wocky_node_get_attribute (wocky_stanza_get_top_node (stanza), "id"); /* Reply with from="domain" */ reply = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, "example.com", "juliet@example.com", '@', "id", id, NULL); wocky_porter_send_async (porter, reply, NULL, test_send_iq_sent_cb, test); g_queue_push_tail (test->expected_stanzas, reply); test->outstanding++; return TRUE; } static void test_reply_from_domain (void) { test_data_t *test = setup_test (); WockyStanza *iq; g_test_bug ("39057"); /* Testing that when we send an iq to server, it can reply from the domain instead of full/bare jid. This happens with xmpp.messenger.live.com. ... ... */ test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_porter_start (test->sched_in); /* register an IQ handler */ wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, 0, test_reply_from_domain_handler_cb, test, NULL); /* Send an IQ query */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, NULL, '@', "id", "1", NULL); wocky_porter_send_iq_async (test->sched_in, iq, NULL, test_send_iq_reply_cb, test); g_queue_push_tail (test->expected_stanzas, iq); test->outstanding += 2; test_wait_pending (test); test_close_both_porters (test); teardown_test (test); } /* Callbacks used in wildcard_handlers() */ const gchar * const ROMEO = "romeo@montague.lit"; const gchar * const JULIET = "juliet@montague.lit"; static gboolean any_stanza_received_from_romeo_cb ( WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = user_data; g_assert_cmpstr (wocky_stanza_get_from (stanza), ==, ROMEO); test->outstanding--; g_main_loop_quit (test->loop); return FALSE; } static gboolean any_stanza_received_from_server_cb ( WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = user_data; g_assert_cmpstr (wocky_stanza_get_from (stanza), ==, NULL); test->outstanding--; g_main_loop_quit (test->loop); return FALSE; } static gboolean any_stanza_received_from_anyone_cb ( WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = user_data; test->outstanding--; g_main_loop_quit (test->loop); return FALSE; } static void wildcard_handlers (void) { test_data_t *test = setup_test (); WockyStanza *stanza; test_open_both_connections (test); wocky_porter_start (test->sched_in); wocky_porter_start (test->sched_out); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_NONE, WOCKY_STANZA_SUB_TYPE_NONE, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, any_stanza_received_from_anyone_cb, test, NULL); wocky_porter_register_handler_from (test->sched_out, WOCKY_STANZA_TYPE_NONE, WOCKY_STANZA_SUB_TYPE_NONE, ROMEO, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, any_stanza_received_from_romeo_cb, test, NULL); wocky_c2s_porter_register_handler_from_server ( WOCKY_C2S_PORTER (test->sched_out), WOCKY_STANZA_TYPE_NONE, WOCKY_STANZA_SUB_TYPE_NONE, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, any_stanza_received_from_server_cb, test, NULL); stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_HEADLINE, ROMEO, NULL, NULL); wocky_porter_send (test->sched_in, stanza); g_object_unref (stanza); test->outstanding += 2; stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, JULIET, NULL, NULL); wocky_porter_send (test->sched_in, stanza); g_object_unref (stanza); test->outstanding += 1; stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_STREAM_FEATURES, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, NULL); wocky_porter_send (test->sched_in, stanza); g_object_unref (stanza); test->outstanding += 2; test_wait_pending (test); test_close_both_porters (test); teardown_test (test); } int main (int argc, char **argv) { int result; test_init (argc, argv); g_test_add_func ("/xmpp-porter/initiation", test_instantiation); g_test_add_func ("/xmpp-porter/send", test_send); g_test_add_func ("/xmpp-porter/receive", test_receive); g_test_add_func ("/xmpp-porter/filter", test_filter); g_test_add_func ("/xmpp-porter/close-flush", test_close_flush); g_test_add_func ("/xmpp-porter/close-not-started", test_close_not_started); g_test_add_func ("/xmpp-porter/close-twice", test_close_twice); g_test_add_func ("/xmpp-porter/remote-close", test_remote_close); g_test_add_func ("/xmpp-porter/close-cancel", test_close_cancel); g_test_add_func ("/xmpp-porter/reading-error", test_reading_error); g_test_add_func ("/xmpp-porter/send-closed", test_send_closed); g_test_add_func ("/xmpp-porter/handler-priority", test_handler_priority); g_test_add_func ("/xmpp-porter/unregister-handler", test_unregister_handler); g_test_add_func ("/xmpp-porter/handler-bare-jid", test_handler_bare_jid); g_test_add_func ("/xmpp-porter/handler-bare-jid", test_handler_full_jid); g_test_add_func ("/xmpp-porter/handler-stanza", test_handler_stanza); g_test_add_func ("/xmpp-porter/cancel-sent-stanza", test_cancel_sent_stanza); g_test_add_func ("/xmpp-porter/writing-error", test_writing_error); g_test_add_func ("/xmpp-porter/send-iq", test_send_iq); g_test_add_func ("/xmpp-porter/acknowledge-iq", test_acknowledge_iq); g_test_add_func ("/xmpp-porter/send-iq-error", test_send_iq_error); g_test_add_func ("/xmpp-porter/send-iq-gerror", test_send_iq_gerror); g_test_add_func ("/xmpp-porter/send-iq-denormalised", test_send_iq_abnormal); g_test_add_func ("/xmpp-porter/error-while-sending-iq", test_error_while_sending_iq); g_test_add_func ("/xmpp-porter/handler-filter", test_handler_filter); g_test_add_func ("/xmpp-porter/unhandled-iq", test_unhandled_iq); g_test_add_func ("/xmpp-porter/send-invalid-iq", test_send_invalid_iq); g_test_add_func ("/xmpp-porter/handler-filter-from", test_handler_filter_from); g_test_add_func ("/xmpp-porter/send-iq-server", test_send_iq_server); g_test_add_func ("/xmpp-porter/unref-when-closed", test_unref_when_closed); g_test_add_func ("/xmpp-porter/close-simultanously", test_close_simultanously); g_test_add_func ("/xmpp-porter/close-error", test_close_error); g_test_add_func ("/xmpp-porter/cancel-iq-closing", test_cancel_iq_closing); g_test_add_func ("/xmpp-porter/stream-error", test_stream_error); g_test_add_func ("/xmpp-porter/close-force", test_close_force); g_test_add_func ("/xmpp-porter/close-force-after-error", test_close_force_after_error); g_test_add_func ("/xmpp-porter/close-force-after-close-sent", test_close_force_after_close_sent); g_test_add_func ("/xmpp-porter/wait-iq-reply-close", test_wait_iq_reply_close); g_test_add_func ("/xmpp-porter/wait-iq-reply-force-close", test_wait_iq_reply_force_close); g_test_add_func ("/xmpp-porter/avoid-double-force-close", test_remote_error); g_test_add_func ("/xmpp-porter/send-and-disconnect", send_and_disconnect); g_test_add_func ("/xmpp-porter/handler-for-domain", handler_for_domain); g_test_add_func ("/xmpp-porter/handler-from-anyone", handler_from_anyone); g_test_add_func ("/xmpp-porter/close-from-send-callback", close_from_send_callback); g_test_add_func ("/xmpp-porter/send-from-send-callback", send_from_send_callback); g_test_add_func ("/xmpp-porter/reply-from-domain", test_reply_from_domain); g_test_add_func ("/xmpp-porter/wildcard-handlers", wildcard_handlers); result = g_test_run (); test_deinit (); return result; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-test-stream.c0000664000175000017500000004456512005516162025624 0ustar00cassidycassidy00000000000000/* * wocky-test-stream.c - Source for WockyTestStream * Copyright (C) 2009 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "wocky-test-stream.h" G_DEFINE_TYPE (WockyTestStream, wocky_test_stream, G_TYPE_OBJECT); struct _WockyTestStreamPrivate { gboolean dispose_has_run; }; enum { PROP_IO_INPUT_STREAM = 1, PROP_IO_OUTPUT_STREAM }; static GType wocky_test_io_stream_get_type (void); static GType wocky_test_input_stream_get_type (void); static GType wocky_test_output_stream_get_type (void); typedef struct { GIOStream parent; GInputStream *input; GOutputStream *output; } WockyTestIOStream; typedef struct { GIOStreamClass parent; } WockyTestIOStreamClass; typedef struct { GOutputStream parent; GAsyncQueue *queue; WockyTestStreamWriteMode mode; GError *write_error /* no, this is not a coding style violation */; gboolean dispose_has_run; } WockyTestOutputStream; typedef struct { GOutputStreamClass parent_class; } WockyTestOutputStreamClass; typedef struct { GInputStream parent; GAsyncQueue *queue; guint offset; GArray *out_array; GSimpleAsyncResult *read_result; GCancellable *read_cancellable; gulong read_cancellable_sig_id; void *buffer; gsize count; GError *read_error /* no, this is not a coding style violation */; gboolean dispose_has_run; WockyTestStreamReadMode mode; WockyTestStreamDirectReadCb direct_read_cb; gpointer direct_read_user_data; gboolean corked; } WockyTestInputStream; typedef struct { GOutputStreamClass parent_class; } WockyTestInputStreamClass; G_DEFINE_TYPE (WockyTestIOStream, wocky_test_io_stream, G_TYPE_IO_STREAM); G_DEFINE_TYPE (WockyTestInputStream, wocky_test_input_stream, G_TYPE_INPUT_STREAM); G_DEFINE_TYPE (WockyTestOutputStream, wocky_test_output_stream, G_TYPE_OUTPUT_STREAM); #define WOCKY_TYPE_TEST_IO_STREAM (wocky_test_io_stream_get_type ()) #define WOCKY_TYPE_TEST_INPUT_STREAM (wocky_test_input_stream_get_type ()) #define WOCKY_TYPE_TEST_OUTPUT_STREAM (wocky_test_output_stream_get_type ()) #define WOCKY_TEST_IO_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ WOCKY_TYPE_TEST_IO_STREAM, \ WockyTestIOStream)) #define WOCKY_TEST_INPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ WOCKY_TYPE_TEST_INPUT_STREAM, \ WockyTestInputStream)) #define WOCKY_TEST_OUTPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ WOCKY_TYPE_TEST_OUTPUT_STREAM, \ WockyTestOutputStream)) static gboolean wocky_test_input_stream_try_read (WockyTestInputStream *self); static void output_data_written_cb (GOutputStream *output, WockyTestInputStream *input_stream) { wocky_test_input_stream_try_read (input_stream); } static void wocky_test_stream_init (WockyTestStream *self) { /* allocate any data required by the object here */ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_TEST_STREAM, WockyTestStreamPrivate); self->stream0_output = g_object_new (WOCKY_TYPE_TEST_OUTPUT_STREAM, NULL); self->stream1_output = g_object_new (WOCKY_TYPE_TEST_OUTPUT_STREAM, NULL); self->stream0_input = g_object_new (WOCKY_TYPE_TEST_INPUT_STREAM, NULL); WOCKY_TEST_INPUT_STREAM (self->stream0_input)->queue = g_async_queue_ref ( WOCKY_TEST_OUTPUT_STREAM (self->stream1_output)->queue); self->stream1_input = g_object_new (WOCKY_TYPE_TEST_INPUT_STREAM, NULL); WOCKY_TEST_INPUT_STREAM (self->stream1_input)->queue = g_async_queue_ref ( WOCKY_TEST_OUTPUT_STREAM (self->stream0_output)->queue); self->stream0 = g_object_new (WOCKY_TYPE_TEST_IO_STREAM, NULL); WOCKY_TEST_IO_STREAM (self->stream0)->input = self->stream0_input; WOCKY_TEST_IO_STREAM (self->stream0)->output = self->stream0_output; self->stream1 = g_object_new (WOCKY_TYPE_TEST_IO_STREAM, NULL); WOCKY_TEST_IO_STREAM (self->stream1)->input = self->stream1_input; WOCKY_TEST_IO_STREAM (self->stream1)->output = self->stream1_output; g_signal_connect (self->stream0_output, "data-written", G_CALLBACK (output_data_written_cb), self->stream1_input); g_signal_connect (self->stream1_output, "data-written", G_CALLBACK (output_data_written_cb), self->stream0_input); } static void wocky_test_stream_dispose (GObject *object); static void wocky_test_stream_class_init (WockyTestStreamClass *wocky_test_stream_class) { GObjectClass *object_class = G_OBJECT_CLASS (wocky_test_stream_class); g_type_class_add_private (wocky_test_stream_class, \ sizeof (WockyTestStreamPrivate)); object_class->dispose = wocky_test_stream_dispose; } static void wocky_test_stream_dispose (GObject *object) { WockyTestStream *self = WOCKY_TEST_STREAM (object); if (self->priv->dispose_has_run) return; self->priv->dispose_has_run = TRUE; g_object_unref (self->stream0); self->stream0 = NULL; g_object_unref (self->stream1); self->stream1 = NULL; if (G_OBJECT_CLASS (wocky_test_stream_parent_class)->dispose) G_OBJECT_CLASS (wocky_test_stream_parent_class)->dispose (object); } /* IO stream */ static void wocky_test_io_stream_init (WockyTestIOStream *self) { } static void wocky_test_io_stream_class_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyTestIOStream *self = WOCKY_TEST_IO_STREAM (object); switch (property_id) { case PROP_IO_INPUT_STREAM: g_value_set_object (value, self->input); break; case PROP_IO_OUTPUT_STREAM: g_value_set_object (value, self->output); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void wocky_test_io_stream_finalize (GObject *object) { WockyTestIOStream *self = WOCKY_TEST_IO_STREAM (object); g_object_unref (self->input); g_object_unref (self->output); if (G_OBJECT_CLASS (wocky_test_io_stream_parent_class)->finalize) G_OBJECT_CLASS (wocky_test_io_stream_parent_class)->finalize (object); } static GInputStream * wocky_test_io_stream_get_input_stream (GIOStream *stream) { return WOCKY_TEST_IO_STREAM (stream)->input; } static GOutputStream * wocky_test_io_stream_get_output_stream (GIOStream *stream) { return WOCKY_TEST_IO_STREAM (stream)->output; } static void wocky_test_io_stream_class_init ( WockyTestIOStreamClass *wocky_test_io_stream_class) { GObjectClass *obj_class = G_OBJECT_CLASS (wocky_test_io_stream_class); GIOStreamClass *stream_class = G_IO_STREAM_CLASS (wocky_test_io_stream_class); obj_class->finalize = wocky_test_io_stream_finalize; obj_class->get_property = wocky_test_io_stream_class_get_property; stream_class->get_input_stream = wocky_test_io_stream_get_input_stream; stream_class->get_output_stream = wocky_test_io_stream_get_output_stream; g_object_class_install_property (obj_class, PROP_IO_INPUT_STREAM, g_param_spec_object ("input-stream", "Input stream", "the input stream", G_TYPE_INPUT_STREAM, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (obj_class, PROP_IO_OUTPUT_STREAM, g_param_spec_object ("output-stream", "Output stream", "the output stream", G_TYPE_OUTPUT_STREAM, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); } /* Input stream */ static gssize wocky_test_input_stream_read (GInputStream *stream, void *buffer, gsize count, GCancellable *cancellable, GError **error) { WockyTestInputStream *self = WOCKY_TEST_INPUT_STREAM (stream); gsize written = 0; if (self->out_array == NULL) { g_assert (self->offset == 0); self->out_array = g_async_queue_pop (self->queue); } do { gsize towrite; if (self->mode == WOCK_TEST_STREAM_READ_COMBINE_SLICE && self->offset == 0) towrite = MIN (count - written, MAX (self->out_array->len/2, 1)); else towrite = MIN (count - written, self->out_array->len - self->offset); memcpy ((guchar *) buffer + written, self->out_array->data + self->offset, towrite); self->offset += towrite; written += towrite; if (self->offset == self->out_array->len) { g_array_unref (self->out_array); self->out_array = g_async_queue_try_pop (self->queue); self->offset = 0; } else if (self->mode == WOCK_TEST_STREAM_READ_COMBINE_SLICE) { break; } } while (self->mode != WOCK_TEST_STREAM_READ_EXACT && written < count && self->out_array != NULL); if (self->direct_read_cb != NULL) self->direct_read_cb (buffer, written, self->direct_read_user_data); return written; } static void read_async_complete (WockyTestInputStream *self) { GSimpleAsyncResult *r = self->read_result; if (self->read_cancellable != NULL) { g_signal_handler_disconnect (self->read_cancellable, self->read_cancellable_sig_id); g_object_unref (self->read_cancellable); self->read_cancellable = NULL; } self->read_result = NULL; g_simple_async_result_complete_in_idle (r); g_object_unref (r); } static void read_cancelled_cb (GCancellable *cancellable, WockyTestInputStream *self) { g_simple_async_result_set_error (self->read_result, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Reading cancelled"); self->buffer = NULL; read_async_complete (self); } static void wocky_test_input_stream_read_async (GInputStream *stream, void *buffer, gsize count, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyTestInputStream *self = WOCKY_TEST_INPUT_STREAM (stream); g_assert (self->buffer == NULL); g_assert (self->read_result == NULL); g_assert (self->read_cancellable == NULL); self->buffer = buffer; self->count = count; self->read_result = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, wocky_test_input_stream_read_async); if (self->read_error != NULL) { g_simple_async_result_set_from_error (self->read_result, self->read_error); g_error_free (self->read_error); self->read_error = NULL; read_async_complete (self); return; } if (cancellable != NULL) { self->read_cancellable = g_object_ref (cancellable); self->read_cancellable_sig_id = g_signal_connect (cancellable, "cancelled", G_CALLBACK (read_cancelled_cb), self); } wocky_test_input_stream_try_read (self); } static gssize wocky_test_input_stream_read_finish (GInputStream *stream, GAsyncResult *result, GError **error) { WockyTestInputStream *self = WOCKY_TEST_INPUT_STREAM (stream); gssize len = -1; if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) goto out; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), wocky_test_input_stream_read_async), -1); len = wocky_test_input_stream_read (stream, self->buffer, self->count, NULL, error); out: self->buffer = NULL; return len; } static gboolean wocky_test_input_stream_try_read (WockyTestInputStream *self) { if (self->read_result == NULL) /* No pending read operation */ return FALSE; if (self->out_array == NULL && g_async_queue_length (self->queue) == 0) return FALSE; if (self->corked) return FALSE; read_async_complete (self); return TRUE; } static void wocky_test_input_stream_init (WockyTestInputStream *self) { } static void wocky_test_input_stream_dispose (GObject *object) { WockyTestInputStream *self = WOCKY_TEST_INPUT_STREAM (object); if (self->dispose_has_run) return; self->dispose_has_run = TRUE; if (self->out_array != NULL) g_array_unref (self->out_array); self->out_array = NULL; if (self->queue != NULL) g_async_queue_unref (self->queue); self->queue = NULL; g_warn_if_fail (self->read_result == NULL); g_warn_if_fail (self->read_cancellable == NULL); /* release any references held by the object here */ if (G_OBJECT_CLASS (wocky_test_input_stream_parent_class)->dispose) G_OBJECT_CLASS (wocky_test_input_stream_parent_class)->dispose (object); } static void wocky_test_input_stream_class_init ( WockyTestInputStreamClass *wocky_test_input_stream_class) { GObjectClass *obj_class = G_OBJECT_CLASS (wocky_test_input_stream_class); GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (wocky_test_input_stream_class); obj_class->dispose = wocky_test_input_stream_dispose; stream_class->read_fn = wocky_test_input_stream_read; stream_class->read_async = wocky_test_input_stream_read_async; stream_class->read_finish = wocky_test_input_stream_read_finish; } /* Output stream */ enum { OUTPUT_DATA_WRITTEN, LAST_SIGNAL }; static guint output_signals[LAST_SIGNAL] = {0}; static gssize wocky_test_output_stream_write (GOutputStream *stream, const void *buffer, gsize count, GCancellable *cancellable, GError **error) { WockyTestOutputStream *self = WOCKY_TEST_OUTPUT_STREAM (stream); GArray *data; gsize written = count; if (self->mode == WOCKY_TEST_STREAM_WRITE_INCOMPLETE) written = MAX (count/2, 1); if (self->write_error != NULL) { *error = self->write_error; self->write_error = NULL; return -1; } data = g_array_sized_new (FALSE, FALSE, sizeof (guint8), written); g_array_insert_vals (data, 0, buffer, written); g_async_queue_push (self->queue, data); g_signal_emit (self, output_signals[OUTPUT_DATA_WRITTEN], 0); return written; } static void wocky_test_output_stream_write_async (GOutputStream *stream, const void *buffer, gsize count, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *simple; GError *error = NULL; gssize result; result = wocky_test_output_stream_write (stream, buffer, count, cancellable, &error); simple = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, wocky_test_output_stream_write_async); if (result == -1) { g_simple_async_result_set_from_error (simple, error); g_error_free (error); } else { g_simple_async_result_set_op_res_gssize (simple, result); } g_simple_async_result_complete_in_idle (simple); g_object_unref (simple); } static gssize wocky_test_output_stream_write_finish (GOutputStream *stream, GAsyncResult *result, GError **error) { if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) return -1; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (stream), wocky_test_output_stream_write_async), -1); return g_simple_async_result_get_op_res_gssize ( G_SIMPLE_ASYNC_RESULT (result)); } static void wocky_test_output_stream_dispose (GObject *object) { WockyTestOutputStream *self = WOCKY_TEST_OUTPUT_STREAM (object); if (self->dispose_has_run) return; self->dispose_has_run = TRUE; g_async_queue_push (self->queue, g_array_sized_new (FALSE, FALSE, sizeof (guint8), 0)); g_async_queue_unref (self->queue); /* release any references held by the object here */ if (G_OBJECT_CLASS (wocky_test_output_stream_parent_class)->dispose) G_OBJECT_CLASS (wocky_test_output_stream_parent_class)->dispose (object); } static void queue_destroyed (gpointer data) { g_array_free ((GArray *) data, TRUE); } static void wocky_test_output_stream_init (WockyTestOutputStream *self) { self->queue = g_async_queue_new_full (queue_destroyed); } static void wocky_test_output_stream_class_init ( WockyTestOutputStreamClass *wocky_test_output_stream_class) { GObjectClass *obj_class = G_OBJECT_CLASS (wocky_test_output_stream_class); GOutputStreamClass *stream_class = G_OUTPUT_STREAM_CLASS (wocky_test_output_stream_class); obj_class->dispose = wocky_test_output_stream_dispose; stream_class->write_fn = wocky_test_output_stream_write; stream_class->write_async = wocky_test_output_stream_write_async; stream_class->write_finish = wocky_test_output_stream_write_finish; output_signals[OUTPUT_DATA_WRITTEN] = g_signal_new ("data-written", G_OBJECT_CLASS_TYPE(wocky_test_output_stream_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } void wocky_test_input_stream_set_read_error (GInputStream *stream) { WockyTestInputStream *self = WOCKY_TEST_INPUT_STREAM (stream); if (self->read_result == NULL) { /* No pending read operation. Set the error so next read will fail */ self->read_error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED, "read error"); return; } g_simple_async_result_set_error (self->read_result, G_IO_ERROR, G_IO_ERROR_FAILED, "read error"); read_async_complete (self); } void wocky_test_output_stream_set_write_error (GOutputStream *stream) { WockyTestOutputStream *self = WOCKY_TEST_OUTPUT_STREAM (stream); self->write_error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED, "write error"); } void wocky_test_stream_set_mode (GInputStream *stream, WockyTestStreamReadMode mode) { WOCKY_TEST_INPUT_STREAM (stream)->mode = mode; } void wocky_test_stream_cork (GInputStream *stream, gboolean cork) { WockyTestInputStream *tstream = WOCKY_TEST_INPUT_STREAM (stream); tstream->corked = cork; if (cork == FALSE) wocky_test_input_stream_try_read (tstream); } void wocky_test_stream_set_direct_read_callback (GInputStream *stream, WockyTestStreamDirectReadCb cb, gpointer user_data) { WockyTestInputStream *tstream = WOCKY_TEST_INPUT_STREAM (stream); tstream->direct_read_cb = cb; tstream->direct_read_user_data = user_data; } void wocky_test_stream_set_write_mode (GOutputStream *stream, WockyTestStreamWriteMode mode) { WOCKY_TEST_OUTPUT_STREAM (stream)->mode = mode; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-pubsub-service-test.c0000664000175000017500000005672012005516162027263 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "wocky-pubsub-test-helpers.h" #include "wocky-test-helper.h" #include "wocky-test-stream.h" /* Test instantiating a WockyPubsubService object */ static WockySession * create_session (void) { WockyXmppConnection *connection; WockyTestStream *stream; WockySession *session; stream = g_object_new (WOCKY_TYPE_TEST_STREAM, NULL); connection = wocky_xmpp_connection_new (stream->stream0); session = wocky_session_new_with_connection (connection, "example.com"); g_object_unref (connection); g_object_unref (stream); return session; } static void test_instantiation (void) { WockyPubsubService *pubsub; WockySession *session; session = create_session (); pubsub = wocky_pubsub_service_new (session, "pubsub.localhost"); g_assert (pubsub != NULL); g_object_unref (pubsub); g_object_unref (session); } /* Test wocky_pubsub_service_ensure_node */ static void test_ensure_node (void) { WockyPubsubService *pubsub; WockySession *session; WockyPubsubNode *node; session = create_session (); pubsub = wocky_pubsub_service_new (session, "pubsub.localhost"); node = wocky_pubsub_service_lookup_node (pubsub, "node1"); g_assert (node == NULL); node = wocky_pubsub_service_ensure_node (pubsub, "node1"); g_assert (node != NULL); node = wocky_pubsub_service_lookup_node (pubsub, "node1"); g_assert (node != NULL); /* destroy the node */ g_object_unref (node); node = wocky_pubsub_service_lookup_node (pubsub, "node1"); g_assert (node == NULL); g_object_unref (pubsub); g_object_unref (session); } /* Test wocky_pubsub_service_get_default_node_configuration_async */ static gboolean test_get_default_node_configuration_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; reply = wocky_stanza_build_iq_result (stanza, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB_OWNER, '(', "default", '(', "x", ':', WOCKY_XMPP_NS_DATA, '@', "type", "form", '(', "field", '@', "type", "hidden", '@', "var", "FORM_TYPE", '(', "value", '$', WOCKY_XMPP_NS_PUBSUB_NODE_CONFIG, ')', ')', '(', "field", '@', "var", "pubsub#title", '@', "type", "text-single", '@', "label", "Title", ')', '(', "field", '@', "var", "pubsub#deliver_notifications", '@', "type", "boolean", '@', "label", "Deliver event notifications", ')', ')', ')', ')', NULL); wocky_porter_send (porter, reply); g_object_unref (reply); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void test_get_default_node_configuration_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyDataForm *form; WockyDataFormField *field; form = wocky_pubsub_service_get_default_node_configuration_finish ( WOCKY_PUBSUB_SERVICE (source), res, NULL); g_assert (form != NULL); field = g_hash_table_lookup (form->fields, "pubsub#title"); g_assert (field != NULL); field = g_hash_table_lookup (form->fields, "pubsub#deliver_notifications"); g_assert (field != NULL); g_object_unref (form); test->outstanding--; g_main_loop_quit (test->loop); } static void get_default_node_configuration_test (WockyPorterHandlerFunc iq_cb, GAsyncReadyCallback get_cb) { test_data_t *test = setup_test (); WockyPubsubService *pubsub; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_session_start (test->session_in); pubsub = wocky_pubsub_service_new (test->session_in, "pubsub.localhost"); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, iq_cb, test, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB_OWNER, '(', "default", ')', ')', NULL); wocky_pubsub_service_get_default_node_configuration_async (pubsub, NULL, get_cb, test); test->outstanding += 2; test_wait_pending (test); g_object_unref (pubsub); test_close_both_porters (test); teardown_test (test); } static void test_get_default_node_configuration (void) { get_default_node_configuration_test ( test_get_default_node_configuration_iq_cb, test_get_default_node_configuration_cb); } /* Try to retrieve default node configuration and get a insufficient * privileges error */ static gboolean test_get_default_node_configuration_insufficient_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; reply = wocky_stanza_build_iq_error (stanza, '(', "error", '@', "type", "auth", '(', "forbidden", ':', WOCKY_XMPP_NS_STANZAS, ')', ')', NULL); wocky_porter_send (porter, reply); g_object_unref (reply); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void test_get_default_node_configuration_insufficient_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyDataForm *form; GError *error = NULL; form = wocky_pubsub_service_get_default_node_configuration_finish ( WOCKY_PUBSUB_SERVICE (source), res, &error); g_assert (form == NULL); g_assert_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_FORBIDDEN); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_get_default_node_configuration_insufficient (void) { get_default_node_configuration_test ( test_get_default_node_configuration_insufficient_iq_cb, test_get_default_node_configuration_insufficient_cb); } /* Create a node with default config */ static gboolean test_create_node_no_config_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; WockyNode *node; node = wocky_node_get_child_ns (wocky_stanza_get_top_node (stanza), "pubsub", WOCKY_XMPP_NS_PUBSUB); g_assert (node != NULL); node = wocky_node_get_child (node, "create"); g_assert (node != NULL); g_assert (!wocky_strdiff (wocky_node_get_attribute (node, "node"), "node1")); reply = wocky_stanza_build_iq_result (stanza, NULL); wocky_porter_send (porter, reply); g_object_unref (reply); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void test_create_node_no_config_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyPubsubNode *node; node = wocky_pubsub_service_create_node_finish (WOCKY_PUBSUB_SERVICE (source), res, NULL); g_assert (node != NULL); g_assert (!wocky_strdiff (wocky_pubsub_node_get_name (node), "node1")); g_object_unref (node); test->outstanding--; g_main_loop_quit (test->loop); } static void create_node_test (WockyPorterHandlerFunc iq_cb, GAsyncReadyCallback create_cb, const gchar *node_name) { test_data_t *test = setup_test (); WockyPubsubService *pubsub; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_session_start (test->session_in); pubsub = wocky_pubsub_service_new (test->session_in, "pubsub.localhost"); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, iq_cb, test, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB, '(', "create", ')', ')', NULL); wocky_pubsub_service_create_node_async (pubsub, node_name, NULL, NULL, create_cb, test); test->outstanding += 2; test_wait_pending (test); g_object_unref (pubsub); test_close_both_porters (test); teardown_test (test); } static void test_create_node_no_config (void) { create_node_test (test_create_node_no_config_iq_cb, test_create_node_no_config_cb, "node1"); } /* creation of a node fails because service does not support node creation */ static gboolean test_create_node_unsupported_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; reply = wocky_stanza_build_iq_error (stanza, '(', "error", '@', "type", "cancel", '(', "feature-not-implemented", ':', WOCKY_XMPP_NS_STANZAS, ')', '(', "unsupported", ':', WOCKY_XMPP_NS_PUBSUB_ERRORS, '@', "feature", "create-nodes", ')', ')', NULL); wocky_porter_send (porter, reply); g_object_unref (reply); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void test_create_node_unsupported_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyPubsubNode *node; GError *error = NULL; node = wocky_pubsub_service_create_node_finish (WOCKY_PUBSUB_SERVICE (source), res, &error); g_assert (node == NULL); g_assert_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_FEATURE_NOT_IMPLEMENTED); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_create_node_unsupported (void) { create_node_test (test_create_node_unsupported_iq_cb, test_create_node_unsupported_cb, "node1"); } /* Create an instant node (no name passed) */ static gboolean test_create_instant_node_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; reply = wocky_stanza_build_iq_result (stanza, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB, '(', "create", '@', "node", "instant_node", ')', ')', NULL); wocky_porter_send (porter, reply); g_object_unref (reply); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void test_create_instant_node_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyPubsubNode *node; node = wocky_pubsub_service_create_node_finish (WOCKY_PUBSUB_SERVICE (source), res, NULL); g_assert (node != NULL); g_assert (!wocky_strdiff (wocky_pubsub_node_get_name (node), "instant_node")); g_object_unref (node); test->outstanding--; g_main_loop_quit (test->loop); } static void test_create_instant_node (void) { create_node_test (test_create_instant_node_iq_cb, test_create_instant_node_cb, NULL); } /* Ask for a node with one name, get one back with another */ static gboolean test_create_node_renamed_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; WockyNode *node; node = wocky_node_get_child_ns (wocky_stanza_get_top_node (stanza), "pubsub", WOCKY_XMPP_NS_PUBSUB); g_assert (node != NULL); node = wocky_node_get_child (node, "create"); g_assert (node != NULL); g_assert (!wocky_strdiff (wocky_node_get_attribute (node, "node"), "node1")); reply = wocky_stanza_build_iq_result (stanza, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB, '(', "create", '@', "node", "metal-bird", ')', ')', NULL); wocky_porter_send (porter, reply); g_object_unref (reply); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void test_create_node_renamed_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyPubsubNode *node; node = wocky_pubsub_service_create_node_finish (WOCKY_PUBSUB_SERVICE (source), res, NULL); g_assert (node != NULL); g_assert_cmpstr (wocky_pubsub_node_get_name (node), ==, "metal-bird"); g_object_unref (node); test->outstanding--; g_main_loop_quit (test->loop); } static void test_create_node_renamed (void) { create_node_test (test_create_node_renamed_iq_cb, test_create_node_renamed_cb, "node1"); } /* Create a node with configuration */ static void test_create_node_config_config_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyDataForm *form; gboolean set_succeeded; form = wocky_pubsub_service_get_default_node_configuration_finish ( WOCKY_PUBSUB_SERVICE (source), res, NULL); g_assert (form != NULL); set_succeeded = wocky_data_form_set_string (form, "pubsub#title", "Badger", FALSE); g_assert (set_succeeded); set_succeeded = wocky_data_form_set_boolean (form, "pubsub#deliver_notifications", FALSE, FALSE); g_assert (set_succeeded); wocky_pubsub_service_create_node_async (WOCKY_PUBSUB_SERVICE (source), "node1", form, NULL, test_create_node_no_config_cb, test); g_object_unref (form); test->outstanding--; g_main_loop_quit (test->loop); } static gboolean test_create_node_config_create_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *reply; WockyNode *node; GSList *l; gboolean form_type = FALSE, title = FALSE, notif = FALSE; node = wocky_node_get_child_ns (wocky_stanza_get_top_node (stanza), "pubsub", WOCKY_XMPP_NS_PUBSUB); g_assert (node != NULL); node = wocky_node_get_child (node, "configure"); g_assert (node != NULL); node = wocky_node_get_child_ns (node, "x", WOCKY_XMPP_NS_DATA); g_assert (node != NULL); for (l = node->children; l != NULL; l = g_slist_next (l)) { WockyNode *field = l->data; const gchar *type, *var, *value = NULL; WockyNode *v; g_assert (!wocky_strdiff (field->name, "field")); var = wocky_node_get_attribute (field, "var"); type = wocky_node_get_attribute (field, "type"); v = wocky_node_get_child (field, "value"); g_assert (v != NULL); value = v->content; if (!wocky_strdiff (var, "FORM_TYPE")) { g_assert (!wocky_strdiff (type, "hidden")); g_assert (!wocky_strdiff (value, WOCKY_XMPP_NS_PUBSUB_NODE_CONFIG)); form_type = TRUE; } else if (!wocky_strdiff (var, "pubsub#title")) { g_assert (!wocky_strdiff (type, "text-single")); g_assert (!wocky_strdiff (value, "Badger")); title = TRUE; } else if (!wocky_strdiff (var, "pubsub#deliver_notifications")) { g_assert (!wocky_strdiff (type, "boolean")); g_assert (!wocky_strdiff (value, "0")); notif = TRUE; } else g_assert_not_reached (); } g_assert (form_type && title && notif); reply = wocky_stanza_build_iq_result (stanza, NULL); wocky_porter_send (porter, reply); g_object_unref (reply); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void test_create_node_config (void) { test_data_t *test = setup_test (); WockyPubsubService *pubsub; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_session_start (test->session_in); pubsub = wocky_pubsub_service_new (test->session_in, "pubsub.localhost"); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, test_get_default_node_configuration_iq_cb, test, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB_OWNER, '(', "default", ')', ')', NULL); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, test_create_node_config_create_iq_cb, test, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB, '(', "create", ')', ')', NULL); wocky_pubsub_service_get_default_node_configuration_async (pubsub, NULL, test_create_node_config_config_cb, test); test->outstanding += 4; test_wait_pending (test); test_close_both_porters (test); teardown_test (test); g_object_unref (pubsub); } /* Four examples taken from §5.6 Retrieve Subscriptions */ typedef enum { MODE_NORMAL, MODE_NO_SUBSCRIPTIONS, MODE_BZZT, MODE_AT_NODE } RetrieveSubscriptionsMode; typedef struct { test_data_t *test; RetrieveSubscriptionsMode mode; } RetrieveSubscriptionsCtx; static CannedSubscriptions normal_subs[] = { { "node1", "francisco@denmark.lit", "subscribed", WOCKY_PUBSUB_SUBSCRIPTION_SUBSCRIBED, NULL }, { "node2", "francisco@denmark.lit/bonghits", "subscribed", WOCKY_PUBSUB_SUBSCRIPTION_SUBSCRIBED, NULL }, { "node5", "francisco@denmark.lit", "unconfigured", WOCKY_PUBSUB_SUBSCRIPTION_UNCONFIGURED, NULL }, { "node6", "francisco@denmark.lit", "pending", WOCKY_PUBSUB_SUBSCRIPTION_PENDING, NULL }, { NULL, } }; static CannedSubscriptions bonghit_subs[] = { { "bonghits", "bernardo@denmark.lit", "subscribed", WOCKY_PUBSUB_SUBSCRIPTION_SUBSCRIBED, "123-abc" }, { "bonghits", "bernardo@denmark.lit/i-am-poorly-read", "subscribed", WOCKY_PUBSUB_SUBSCRIPTION_SUBSCRIBED, "004-yyy" }, { NULL, } }; static WockyStanza * make_subscriptions_response (WockyStanza *stanza, const gchar *node, CannedSubscriptions *subs) { WockyStanza *reply; WockyNode *s; reply = wocky_stanza_build_iq_result (stanza, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB, '(', "subscriptions", '*', &s, ')', ')', NULL); if (node != NULL) wocky_node_set_attribute (s, "node", node); test_pubsub_add_subscription_nodes (s, subs, (node == NULL)); return reply; } static gboolean test_retrieve_subscriptions_iq_cb ( WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { RetrieveSubscriptionsCtx *ctx = user_data; test_data_t *test = ctx->test; WockyStanza *reply, *expected; WockyNode *subscriptions; expected = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, "pubsub.localhost", '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB, '(', "subscriptions", '*', &subscriptions, ')', ')', NULL); if (ctx->mode == MODE_AT_NODE) wocky_node_set_attribute (subscriptions, "node", "bonghits"); test_assert_stanzas_equal_no_id (stanza, expected); g_object_unref (expected); switch (ctx->mode) { case MODE_NORMAL: reply = make_subscriptions_response (stanza, NULL, normal_subs); break; case MODE_NO_SUBSCRIPTIONS: reply = make_subscriptions_response (stanza, NULL, NULL); break; case MODE_BZZT: { GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_FEATURE_NOT_IMPLEMENTED, "FIXME: " }; reply = wocky_stanza_build_iq_error (stanza, NULL); wocky_stanza_error_to_node (&e, wocky_stanza_get_top_node (reply)); break; } case MODE_AT_NODE: reply = make_subscriptions_response (stanza, "bonghits", bonghit_subs); break; default: g_assert_not_reached (); } wocky_porter_send (porter, reply); g_object_unref (reply); test->outstanding--; g_main_loop_quit (test->loop); return TRUE; } static void check_subscriptions ( GObject *source, GAsyncResult *res, CannedSubscriptions *expected_subs) { GList *subscriptions; g_assert (wocky_pubsub_service_retrieve_subscriptions_finish ( WOCKY_PUBSUB_SERVICE (source), res, &subscriptions, NULL)); test_pubsub_check_and_free_subscriptions (subscriptions, expected_subs); } static void retrieve_subscriptions_cb (GObject *source, GAsyncResult *res, gpointer user_data) { RetrieveSubscriptionsCtx *ctx = user_data; test_data_t *test = ctx->test; GError *error = NULL; switch (ctx->mode) { case MODE_NORMAL: check_subscriptions (source, res, normal_subs); break; case MODE_NO_SUBSCRIPTIONS: check_subscriptions (source, res, normal_subs + 4); break; case MODE_BZZT: g_assert (!wocky_pubsub_service_retrieve_subscriptions_finish ( WOCKY_PUBSUB_SERVICE (source), res, NULL, &error)); /* FIXME: moar detail */ g_assert_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_FEATURE_NOT_IMPLEMENTED); g_clear_error (&error); break; case MODE_AT_NODE: check_subscriptions (source, res, bonghit_subs); break; default: g_assert_not_reached (); } test->outstanding--; g_main_loop_quit (test->loop); } static void test_retrieve_subscriptions (gconstpointer mode_) { test_data_t *test = setup_test (); RetrieveSubscriptionsMode mode = GPOINTER_TO_UINT (mode_); RetrieveSubscriptionsCtx ctx = { test, mode }; WockyPubsubService *pubsub; WockyPubsubNode *node = NULL; test_open_both_connections (test); wocky_porter_start (test->sched_out); wocky_session_start (test->session_in); pubsub = wocky_pubsub_service_new (test->session_in, "pubsub.localhost"); wocky_porter_register_handler_from_anyone (test->sched_out, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_PORTER_HANDLER_PRIORITY_MAX, test_retrieve_subscriptions_iq_cb, &ctx, '(', "pubsub", ':', WOCKY_XMPP_NS_PUBSUB, '(', "subscriptions", ')', ')', NULL); if (mode == MODE_AT_NODE) node = wocky_pubsub_service_ensure_node (pubsub, "bonghits"); wocky_pubsub_service_retrieve_subscriptions_async (pubsub, node, NULL, retrieve_subscriptions_cb, &ctx); test->outstanding += 2; test_wait_pending (test); if (node != NULL) g_object_unref (node); test_close_both_porters (test); teardown_test (test); g_object_unref (pubsub); } int main (int argc, char **argv) { int result; test_init (argc, argv); g_test_add_func ("/pubsub-service/instantiation", test_instantiation); g_test_add_func ("/pubsub-service/ensure_node", test_ensure_node); g_test_add_func ("/pubsub-service/get-default-node-configuration", test_get_default_node_configuration); g_test_add_func ( "/pubsub-service/get-default-node-configuration-insufficient", test_get_default_node_configuration_insufficient); g_test_add_data_func ("/pubsub-service/retrieve-subscriptions/normal", GUINT_TO_POINTER (MODE_NORMAL), test_retrieve_subscriptions); g_test_add_data_func ("/pubsub-service/retrieve-subscriptions/none", GUINT_TO_POINTER (MODE_NO_SUBSCRIPTIONS), test_retrieve_subscriptions); g_test_add_data_func ("/pubsub-service/retrieve-subscriptions/error", GUINT_TO_POINTER (MODE_BZZT), test_retrieve_subscriptions); g_test_add_data_func ("/pubsub-service/retrieve-subscriptions/for-node", GUINT_TO_POINTER (MODE_AT_NODE), test_retrieve_subscriptions); g_test_add_func ("/pubsub-service/create-node-no-config", test_create_node_no_config); g_test_add_func ("/pubsub-service/create-node-unsupported", test_create_node_unsupported); g_test_add_func ("/pubsub-service/create-instant-node", test_create_instant_node); g_test_add_func ("/pubsub-service/create-node-renamed", test_create_node_renamed); g_test_add_func ("/pubsub-service/create-node-config", test_create_node_config); result = g_test_run (); test_deinit (); return result; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-xmpp-node-test.c0000664000175000017500000003263612212322440026226 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "wocky-test-helper.h" #define DUMMY_NS_A "urn:wocky:test:dummy:namespace:a" #define DUMMY_NS_B "urn:wocky:test:dummy:namespace:b" static void test_node_equal (void) { WockyStanza *a, *b; /* Simple IQ node */ a = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, "juliet@example.com", "romeo@example.org", NULL); test_assert_stanzas_equal (a, a); /* Same as 'a' but with an ID attribute */ b = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, "juliet@example.com", "romeo@example.org", '@', "id", "one", NULL); test_assert_stanzas_equal (b, b); test_assert_stanzas_not_equal (a, b); test_assert_stanzas_not_equal (b, a); g_object_unref (a); g_object_unref (b); } static void test_node_add_build (void) { WockyNode *n, *child; n = wocky_node_new ("testtree", DUMMY_NS_A); wocky_node_add_build (n, '(', "testnode", '@', "test", "attribute", '$', "testcontent", ')', NULL); g_assert_cmpint (g_slist_length (n->children), ==, 1); child = wocky_node_get_first_child (n); g_assert_cmpstr (child->name, ==, "testnode"); g_assert_cmpstr (wocky_node_get_ns (child), ==, DUMMY_NS_A); g_assert_cmpstr (child->content, ==, "testcontent"); g_assert_cmpint (g_slist_length (child->attributes), ==, 1); g_assert_cmpstr (wocky_node_get_attribute (child, "test"), ==, "attribute"); wocky_node_free (n); } static void test_set_attribute (void) { WockyStanza *a, *b, *c; a = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, "juliet@example.com", "romeo@example.org", NULL); b = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, "juliet@example.com", "romeo@example.org", '@', "foo", "badger", NULL); test_assert_stanzas_not_equal (a, b); wocky_node_set_attribute (wocky_stanza_get_top_node (a), "foo", "badger"); test_assert_stanzas_equal (a, b); c = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, "juliet@example.com", "romeo@example.org", '@', "foo", "snake", NULL); test_assert_stanzas_not_equal (b, c); wocky_node_set_attribute (wocky_stanza_get_top_node (b), "foo", "snake"); test_assert_stanzas_equal (b, c); g_object_unref (a); g_object_unref (b); g_object_unref (c); } static gboolean _check_attr_prefix (const gchar *urn, const gchar *prefix, const gchar *attr, const gchar *xml) { gboolean rval = FALSE; gchar *ns_str_a = g_strdup_printf (" xmlns:%s='%s'", prefix, urn); gchar *ns_str_b = g_strdup_printf (" xmlns:%s=\"%s\"", prefix, urn); gchar *attr_str = g_strdup_printf (" %s:%s=", prefix, attr); rval = ((strstr (xml, ns_str_a) != NULL) || (strstr (xml, ns_str_a) != NULL)) && (strstr (xml, attr_str) != NULL); g_free (ns_str_a); g_free (ns_str_b); g_free (attr_str); return rval; } static void test_append_content_n (void) { WockyStanza *a; const gchar *content = "badger badger badger"; guint i; size_t l; a = wocky_stanza_new ("message", WOCKY_XMPP_NS_JABBER_CLIENT); l = strlen (content); /* Append content byte by byte */ for (i = 0; i < l; i++) { wocky_node_append_content_n (wocky_stanza_get_top_node (a), content + i, 1); } g_assert (!wocky_strdiff (wocky_stanza_get_top_node (a)->content, content)); g_object_unref (a); } static void test_set_attribute_ns (void) { WockyStanza *sa; WockyStanza *sb; WockyNode *na; WockyNode *nb; const gchar *ca; const gchar *cb; const gchar *cx; const gchar *cy; gchar *xml_a; gchar *xml_b; gchar *pa; gchar *pb; GQuark qa; sa = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, "juliet@example.com", "romeo@example.org", NULL); sb = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, "juliet@example.com", "romeo@example.org", NULL); na = wocky_stanza_get_top_node (sa); nb = wocky_stanza_get_top_node (sb); test_assert_nodes_equal (na, nb); /* *********************************************************************** */ wocky_node_set_attribute_ns (na, "one", "1", DUMMY_NS_A); ca = wocky_node_get_attribute_ns (na, "one", DUMMY_NS_A); cb = wocky_node_get_attribute_ns (nb, "one", DUMMY_NS_A); cx = wocky_node_get_attribute_ns (na, "one", DUMMY_NS_B); cy = wocky_node_get_attribute (na, "one"); test_assert_nodes_not_equal (na, nb); g_assert (ca != NULL); g_assert (cb == NULL); g_assert (cx == NULL); g_assert (cy != NULL); g_assert (!strcmp (ca, "1")); /* *********************************************************************** */ /* set the attribute in the second node to make them equal again */ wocky_node_set_attribute_ns (nb, "one", "1", DUMMY_NS_A); ca = wocky_node_get_attribute_ns (na, "one", DUMMY_NS_A); cb = wocky_node_get_attribute_ns (nb, "one", DUMMY_NS_A); cx = wocky_node_get_attribute_ns (na, "one", DUMMY_NS_B); cy = wocky_node_get_attribute (na, "one"); test_assert_nodes_equal (na, nb); g_assert (ca != NULL); g_assert (cb != NULL); g_assert (cx == NULL); g_assert (cy != NULL); g_assert (!strcmp (ca, "1")); g_assert (!strcmp (ca, cb)); wocky_node_set_attribute_ns (nb, "one", "1", DUMMY_NS_A); cb = wocky_node_get_attribute_ns (nb, "one", DUMMY_NS_A); test_assert_nodes_equal (na, nb); g_assert (cb != NULL); g_assert (!strcmp (ca, cb)); /* *********************************************************************** */ /* change the namespaced atttribute */ wocky_node_set_attribute_ns (na, "one", "2", DUMMY_NS_A); ca = wocky_node_get_attribute_ns (na, "one", DUMMY_NS_A); cb = wocky_node_get_attribute_ns (nb, "one", DUMMY_NS_A); cx = wocky_node_get_attribute_ns (na, "one", DUMMY_NS_B); cy = wocky_node_get_attribute (na, "one"); test_assert_nodes_not_equal (na, nb); g_assert (ca != NULL); g_assert (cb != NULL); g_assert (cx == NULL); g_assert (cy != NULL); g_assert (!strcmp (ca, "2")); g_assert (strcmp (ca, cb)); /* *********************************************************************** */ /* add another attribute in a different namespace */ wocky_node_set_attribute_ns (na, "one", "3", DUMMY_NS_B); ca = wocky_node_get_attribute_ns (na, "one", DUMMY_NS_A); cb = wocky_node_get_attribute_ns (nb, "one", DUMMY_NS_A); cx = wocky_node_get_attribute_ns (na, "one", DUMMY_NS_B); cy = wocky_node_get_attribute (na, "one"); test_assert_nodes_not_equal (na, nb); g_assert (ca != NULL); g_assert (cb != NULL); g_assert (cx != NULL); g_assert (cy != NULL); g_assert (!strcmp (ca, "2")); g_assert (!strcmp (cx, "3")); g_assert (strcmp (ca, cb)); /* *********************************************************************** */ /* swap out the prefix for another one */ /* then check to see the right prefixes were assigned */ qa = g_quark_from_string (DUMMY_NS_B); xml_a = wocky_node_to_string (na); pa = g_strdup (wocky_node_attribute_ns_get_prefix_from_urn (DUMMY_NS_B)); pb = g_strdup (wocky_node_attribute_ns_get_prefix_from_quark (qa)); g_assert (!strcmp (pa, pb)); g_free (pb); /* change the prefix and re-write the attribute */ wocky_node_attribute_ns_set_prefix (qa, "moose"); wocky_node_set_attribute_ns (na, "one", "1", DUMMY_NS_B); xml_b = wocky_node_to_string (na); pb = g_strdup (wocky_node_attribute_ns_get_prefix_from_quark (qa)); g_assert (strcmp (pa, pb)); g_assert (_check_attr_prefix (DUMMY_NS_B, pa, "one", xml_a)); g_assert (_check_attr_prefix (DUMMY_NS_B, pb, "one", xml_b)); g_free (pa); g_free (pb); g_free (xml_a); g_free (xml_b); /* *********************************************************************** */ wocky_node_set_attribute_ns (na, "one", "4", DUMMY_NS_B); cx = wocky_node_get_attribute_ns (na, "one", DUMMY_NS_B); g_assert (cx != NULL); g_assert (!strcmp (cx, "4")); g_object_unref (sa); g_object_unref (sb); } static void do_test_iteration (WockyNodeIter *iter, const gchar **names) { WockyNode *node; int i = 0; while (wocky_node_iter_next (iter, &node)) { g_assert (names[i] != NULL && "Unexpected node"); g_assert_cmpstr (names[i], ==, wocky_node_get_attribute (node, "name")); i++; } g_assert (names[i] == NULL && "Expected more nodes"); } static void test_node_iteration (void) { WockyStanza *stanza; WockyNodeIter iter; const gchar *all[] = { "SPEEX", "THEORA", "GSM", "H264", "VIDEO?", "other", NULL }; const gchar *payloads[] = { "SPEEX", "THEORA", "GSM", "H264", NULL }; const gchar *audio[] = { "SPEEX", "GSM", NULL }; const gchar *video[] = { "THEORA", "H264", NULL }; const gchar *video_ns[] = { "THEORA", "H264", "VIDEO?", NULL }; const gchar *nothing[] = { NULL }; stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, "to", "from", '(', "payload-type", ':', WOCKY_NS_GOOGLE_SESSION_PHONE, '@', "name", "SPEEX", ')', '(', "payload-type", ':', WOCKY_NS_GOOGLE_SESSION_VIDEO, '@', "name", "THEORA", ')', '(', "payload-type", ':', WOCKY_NS_GOOGLE_SESSION_PHONE, '@', "name", "GSM", ')', '(', "payload-type", ':', WOCKY_NS_GOOGLE_SESSION_VIDEO, '@', "name", "H264", ')', '(', "video", ':', WOCKY_NS_GOOGLE_SESSION_VIDEO, '@', "name", "VIDEO?", ')', '(', "misc", '@', "name", "other", ')', NULL); /* All children */ wocky_node_iter_init (&iter, wocky_stanza_get_top_node (stanza), NULL, NULL); do_test_iteration (&iter, all); /* Only the payloads */ wocky_node_iter_init (&iter, wocky_stanza_get_top_node (stanza), "payload-type", NULL); do_test_iteration (&iter, payloads); /* Only phone payloads */ wocky_node_iter_init (&iter, wocky_stanza_get_top_node (stanza), "payload-type", WOCKY_NS_GOOGLE_SESSION_PHONE); do_test_iteration (&iter, audio); /* Only nodes with the phone namespace */ wocky_node_iter_init (&iter, wocky_stanza_get_top_node (stanza), NULL, WOCKY_NS_GOOGLE_SESSION_PHONE); do_test_iteration (&iter, audio); /* only video payloads */ wocky_node_iter_init (&iter, wocky_stanza_get_top_node (stanza), "payload-type", WOCKY_NS_GOOGLE_SESSION_VIDEO); do_test_iteration (&iter, video); /* only nodes with the video namespace */ wocky_node_iter_init (&iter, wocky_stanza_get_top_node (stanza), NULL, WOCKY_NS_GOOGLE_SESSION_VIDEO); do_test_iteration (&iter, video_ns); /* nothing */ wocky_node_iter_init (&iter, wocky_stanza_get_top_node (stanza), "badgers", NULL); do_test_iteration (&iter, nothing); wocky_node_iter_init (&iter, wocky_stanza_get_top_node (stanza), NULL, "snakes"); do_test_iteration (&iter, nothing); g_object_unref (stanza); } static void test_node_iter_remove (void) { WockyNode *top, *child; WockyNodeTree *tree = wocky_node_tree_new ("foo", "wocky:test", '*', &top, '(', "remove-me", ')', '(', "remove-me", ')', '(', "preserve-me", ')', '(', "remove-me", ')', '(', "preserve-me", ')', '(', "remove-me", ')', '(', "remove-me", ')', NULL); WockyNodeIter iter; wocky_node_iter_init (&iter, top, "remove-me", NULL); while (wocky_node_iter_next (&iter, NULL)) wocky_node_iter_remove (&iter); g_assert_cmpuint (g_slist_length (top->children), ==, 2); wocky_node_iter_init (&iter, top, NULL, NULL); while (wocky_node_iter_next (&iter, &child)) g_assert_cmpstr (child->name, ==, "preserve-me"); g_object_unref (tree); } static void test_get_first_child (void) { WockyNodeTree *tree = wocky_node_tree_new ("my-elixir", "my:poison", '(', "th5", ')', '(', "holomovement", ':', "chinese:lantern", ')', '(', "th5", ':', "chinese:lantern", ')', NULL); WockyNode *top = wocky_node_tree_get_top_node (tree); WockyNode *n; n = wocky_node_get_first_child (top); g_assert (n != NULL); g_assert_cmpstr ("th5", ==, n->name); g_assert_cmpstr ("my:poison", ==, wocky_node_get_ns (n)); n = wocky_node_get_child (top, "th5"); g_assert (n != NULL); g_assert_cmpstr ("th5", ==, n->name); g_assert_cmpstr ("my:poison", ==, wocky_node_get_ns (n)); n = wocky_node_get_child_ns (top, "th5", "chinese:lantern"); g_assert (n != NULL); g_assert_cmpstr ("th5", ==, n->name); g_assert_cmpstr ("chinese:lantern", ==, wocky_node_get_ns (n)); n = wocky_node_get_first_child_ns (top, "chinese:lantern"); g_assert (n != NULL); g_assert_cmpstr ("holomovement", ==, n->name); g_assert_cmpstr ("chinese:lantern", ==, wocky_node_get_ns (n)); g_object_unref (tree); } int main (int argc, char **argv) { int result; test_init (argc, argv); g_test_add_func ("/xmpp-node/node-equal", test_node_equal); g_test_add_func ("/xmpp-node/add-build", test_node_add_build); g_test_add_func ("/xmpp-node/set-attribute", test_set_attribute); g_test_add_func ("/xmpp-node/append-content-n", test_append_content_n); g_test_add_func ("/xmpp-node/set-attribute-ns", test_set_attribute_ns); g_test_add_func ("/xmpp-node/node-iterator", test_node_iteration); g_test_add_func ("/xmpp-node/node-iterator-remove", test_node_iter_remove); g_test_add_func ("/xmpp-node/get-first-child", test_get_first_child); result = g_test_run (); test_deinit (); return result; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-xmpp-connection-test.c0000664000175000017500000005713112005516162027443 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "wocky-test-stream.h" #include "wocky-test-helper.h" #define SIMPLE_MESSAGE \ " " \ " " \ " " \ " Art thou not Romeo, and a Montague? " \ " " \ "" static void test_instantiation (void) { WockyXmppConnection *connection; WockyTestStream *stream;; stream = g_object_new (WOCKY_TYPE_TEST_STREAM, NULL); connection = wocky_xmpp_connection_new (stream->stream0); g_assert (connection != NULL); g_object_unref (connection); g_object_unref (stream); } /* Simple message test */ static void stanza_received_cb (GObject *source, GAsyncResult *res, gpointer user_data) { WockyXmppConnection *connection = WOCKY_XMPP_CONNECTION (source); WockyStanza *s; test_data_t *data = (test_data_t *) user_data; GError *error = NULL; s = wocky_xmpp_connection_recv_stanza_finish (connection, res, &error); if (!data->parsed_stanza) { g_assert (s != NULL); data->parsed_stanza = TRUE; wocky_xmpp_connection_recv_stanza_async (WOCKY_XMPP_CONNECTION (source), NULL, stanza_received_cb, data); g_object_unref (s); } else { g_assert (s == NULL); g_main_loop_quit (data->loop); g_error_free (error); } } static void received_open_cb (GObject *source, GAsyncResult *res, gpointer user_data) { WockyXmppConnection *conn = WOCKY_XMPP_CONNECTION (source); if (!wocky_xmpp_connection_recv_open_finish (conn, res, NULL, NULL, NULL, NULL, NULL, NULL)) g_assert_not_reached (); wocky_xmpp_connection_recv_stanza_async (WOCKY_XMPP_CONNECTION (source), NULL, stanza_received_cb, user_data); } #define CHUNK_SIZE 13 static void test_recv_simple_message (void) { WockyXmppConnection *connection; WockyTestStream *stream; gsize len; gsize offset = 0; gchar message[] = SIMPLE_MESSAGE; GMainLoop *loop = NULL; test_data_t data = { NULL, FALSE }; loop = g_main_loop_new (NULL, FALSE); len = strlen (message); stream = g_object_new (WOCKY_TYPE_TEST_STREAM, NULL); connection = wocky_xmpp_connection_new (stream->stream0); g_timeout_add (1000, test_timeout_cb, NULL); data.loop = loop; wocky_xmpp_connection_recv_open_async (connection, NULL, received_open_cb, &data); while (offset < len) { guint l = MIN (len - offset, CHUNK_SIZE); while (g_main_context_iteration (NULL, FALSE)) ; g_output_stream_write_all (stream->stream1_output, message + offset, l, NULL, NULL, NULL); offset += l; } g_main_loop_run (loop); g_main_loop_unref (loop); g_object_unref (stream); g_object_unref (connection); } /* simple send message testing */ static void send_stanza_received_cb (GObject *source, GAsyncResult *res, gpointer user_data) { WockyXmppConnection *connection = WOCKY_XMPP_CONNECTION (source); WockyStanza *s; test_data_t *data = (test_data_t *) user_data; GError *error = NULL; s = wocky_xmpp_connection_recv_stanza_finish (connection, res, &error); g_assert (s != NULL); g_assert (!data->parsed_stanza); data->parsed_stanza = TRUE; g_object_unref (s); data->outstanding--; g_main_loop_quit (data->loop); } static void send_stanza_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *data = (test_data_t *) user_data; g_assert (wocky_xmpp_connection_send_stanza_finish ( WOCKY_XMPP_CONNECTION (source), res, NULL)); data->outstanding--; g_main_loop_quit (data->loop); } static void test_send_simple_message (void) { WockyStanza *s; test_data_t *test = setup_test (); test_open_connection (test); s = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "juliet@example.com", "romeo@example.net", '(', "html", ':', "http://www.w3.org/1999/xhtml", '(', "body", '$', "Art thou not Romeo, and a Montague?", ')', ')', NULL); wocky_xmpp_connection_send_stanza_async (WOCKY_XMPP_CONNECTION (test->in), s, NULL, send_stanza_cb, test); wocky_xmpp_connection_recv_stanza_async (WOCKY_XMPP_CONNECTION (test->out), NULL, send_stanza_received_cb, test); test->outstanding += 2; test_wait_pending (test); test_close_connection (test); g_object_unref (s); teardown_test (test); } /* Test for various error codes */ static void error_pending_open_received_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; g_assert (wocky_xmpp_connection_recv_open_finish ( WOCKY_XMPP_CONNECTION (source), result, NULL, NULL, NULL, NULL, NULL, NULL)); test->outstanding--; g_main_loop_quit (test->loop); } static void error_pending_recv_open_pending_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; WockyXmppConnection *conn = WOCKY_XMPP_CONNECTION (source); g_assert (!wocky_xmpp_connection_recv_open_finish ( conn, result, NULL, NULL, NULL, NULL, NULL, &error)); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PENDING); test->outstanding--; g_main_loop_quit (test->loop); g_error_free (error); } static void error_pending_stanza_received_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyStanza *s; g_assert ((s = wocky_xmpp_connection_recv_stanza_finish ( WOCKY_XMPP_CONNECTION (source), result, NULL)) != NULL); test->outstanding--; g_main_loop_quit (test->loop); g_object_unref (s); } static void error_pending_recv_stanza_pending_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (wocky_xmpp_connection_recv_stanza_finish ( WOCKY_XMPP_CONNECTION (source), result, &error) == NULL); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PENDING); test->outstanding--; g_main_loop_quit (test->loop); g_error_free (error); } static void error_pending_open_sent_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; g_assert (wocky_xmpp_connection_send_open_finish ( WOCKY_XMPP_CONNECTION (source), result, NULL)); test->outstanding--; g_main_loop_quit (test->loop); } static void error_pending_open_pending_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_xmpp_connection_send_open_finish ( WOCKY_XMPP_CONNECTION (source), result, &error)); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PENDING); test->outstanding--; g_main_loop_quit (test->loop); g_error_free (error); } static void error_pending_stanza_sent_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; g_assert (wocky_xmpp_connection_send_stanza_finish ( WOCKY_XMPP_CONNECTION (source), result, NULL)); test->outstanding--; g_main_loop_quit (test->loop); } static void error_pending_stanza_pending_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_xmpp_connection_send_stanza_finish ( WOCKY_XMPP_CONNECTION (source), result, &error)); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PENDING); test->outstanding--; g_main_loop_quit (test->loop); g_error_free (error); } static void error_pending_close_sent_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; g_assert (wocky_xmpp_connection_send_close_finish ( WOCKY_XMPP_CONNECTION (source), result, NULL)); test->outstanding--; g_main_loop_quit (test->loop); } static void error_pending_close_pending_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_xmpp_connection_send_close_finish ( WOCKY_XMPP_CONNECTION (source), result, &error)); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PENDING); test->outstanding--; g_main_loop_quit (test->loop); g_error_free (error); } static void test_error_pending_send_pending (test_data_t *test) { WockyStanza *stanza; stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "a"," b", NULL); /* should get a _PENDING error */ wocky_xmpp_connection_send_open_async (test->in, NULL, NULL, NULL, NULL, NULL, NULL, error_pending_open_pending_cb, test); /* should get a _PENDING error */ wocky_xmpp_connection_send_stanza_async (test->in, stanza, NULL, error_pending_stanza_pending_cb, test); /* should get a _PENDING error */ wocky_xmpp_connection_send_close_async (test->in, NULL, error_pending_close_pending_cb, test); test->outstanding += 3; g_object_unref (stanza); } static void test_error_pending (void) { test_data_t *test = setup_test (); WockyStanza *stanza; stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "a"," b", NULL); wocky_xmpp_connection_recv_open_async (test->out, NULL, error_pending_open_received_cb, test); test->outstanding++; wocky_xmpp_connection_recv_open_async (test->out, NULL, error_pending_open_pending_cb, test); test->outstanding++; g_main_loop_run (test->loop); wocky_xmpp_connection_recv_stanza_async (test->out, NULL, error_pending_recv_stanza_pending_cb, test); test->outstanding++; g_main_loop_run (test->loop); /* Should succeed */ wocky_xmpp_connection_send_open_async (test->in, NULL, NULL, NULL, NULL, NULL, NULL, error_pending_open_sent_cb, test); test->outstanding++; test_error_pending_send_pending (test); test_wait_pending (test); wocky_xmpp_connection_recv_stanza_async (test->out, NULL, error_pending_stanza_received_cb, test); test->outstanding++; wocky_xmpp_connection_recv_open_async (test->out, NULL, error_pending_recv_open_pending_cb, test); test->outstanding++; g_main_loop_run (test->loop); wocky_xmpp_connection_recv_stanza_async (test->out, NULL, error_pending_recv_stanza_pending_cb, test); test->outstanding++; g_main_loop_run (test->loop); /* should succeed */ wocky_xmpp_connection_send_stanza_async (test->in, stanza, NULL, error_pending_stanza_sent_cb, test); test->outstanding++; test_error_pending_send_pending (test); test_wait_pending (test); /* should succeed */ wocky_xmpp_connection_send_close_async (test->in, NULL, error_pending_close_sent_cb, test); test->outstanding++; test_error_pending_send_pending (test); test_wait_pending (test); teardown_test (test); g_object_unref (stanza); } /* not open errors */ static void error_not_open_send_stanza_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_xmpp_connection_send_stanza_finish ( WOCKY_XMPP_CONNECTION (source), result, &error)); g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_NOT_OPEN); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void error_not_open_send_close_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_xmpp_connection_send_close_finish ( WOCKY_XMPP_CONNECTION (source), result, &error)); g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_NOT_OPEN); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void error_not_open_recv_stanza_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (wocky_xmpp_connection_recv_stanza_finish ( WOCKY_XMPP_CONNECTION (source), result, &error) == NULL); g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_NOT_OPEN); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_error_not_open (void) { test_data_t *test = setup_test (); WockyStanza *stanza; stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "a"," b", NULL); wocky_xmpp_connection_send_stanza_async (test->in, stanza, NULL, error_not_open_send_stanza_cb, test); wocky_xmpp_connection_send_close_async (test->in, NULL, error_not_open_send_close_cb, test); wocky_xmpp_connection_recv_stanza_async (test->in, NULL, error_not_open_recv_stanza_cb, test); test->outstanding = 3; test_wait_pending (test); teardown_test (test); g_object_unref (stanza); } /* is open tests */ static void error_is_open_send_open_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_xmpp_connection_send_open_finish ( WOCKY_XMPP_CONNECTION (source), result, &error)); g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_IS_OPEN); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void is_open_send_open_cb (GObject *source, GAsyncResult *result, gpointer user_data) { g_assert (wocky_xmpp_connection_send_open_finish ( WOCKY_XMPP_CONNECTION (source), result, NULL)); wocky_xmpp_connection_send_open_async (WOCKY_XMPP_CONNECTION (source), NULL, NULL, NULL, NULL, NULL, NULL, error_is_open_send_open_cb, user_data); } static void error_is_open_recv_open_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_xmpp_connection_recv_open_finish ( WOCKY_XMPP_CONNECTION (source), result, NULL, NULL, NULL, NULL, NULL, &error)); g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_IS_OPEN); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void is_open_recv_open_cb (GObject *source, GAsyncResult *result, gpointer user_data) { WockyXmppConnection *conn = WOCKY_XMPP_CONNECTION (source); g_assert (wocky_xmpp_connection_recv_open_finish ( conn, result, NULL, NULL, NULL, NULL, NULL, NULL)); wocky_xmpp_connection_recv_open_async (WOCKY_XMPP_CONNECTION (source), NULL, error_is_open_recv_open_cb, user_data); } static void is_open_send_close_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; g_assert (wocky_xmpp_connection_send_close_finish ( WOCKY_XMPP_CONNECTION (source), result, NULL)); test->outstanding--; g_main_loop_quit (test->loop); } static void is_open_recv_close_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (wocky_xmpp_connection_recv_stanza_finish ( WOCKY_XMPP_CONNECTION (source), result, &error) == NULL); g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_CLOSED); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void error_is_closed_send_open_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_xmpp_connection_send_open_finish ( WOCKY_XMPP_CONNECTION (source), result, &error)); g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_IS_CLOSED); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void error_is_closed_send_stanza_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_xmpp_connection_send_stanza_finish ( WOCKY_XMPP_CONNECTION (source), result, &error)); g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_IS_CLOSED); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void error_is_closed_send_close_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_xmpp_connection_send_close_finish ( WOCKY_XMPP_CONNECTION (source), result, &error)); g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_IS_CLOSED); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void error_is_closed_recv_open_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_xmpp_connection_recv_open_finish ( WOCKY_XMPP_CONNECTION (source), result, NULL, NULL, NULL, NULL, NULL, &error)); g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_IS_CLOSED); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void error_is_closed_recv_stanza_cb (GObject *source, GAsyncResult *result, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; g_assert (wocky_xmpp_connection_recv_stanza_finish ( WOCKY_XMPP_CONNECTION (source), result, &error) == NULL); g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_IS_CLOSED); g_error_free (error); test->outstanding--; g_main_loop_quit (test->loop); } static void test_error_is_open_or_closed (void) { test_data_t *test = setup_test (); WockyStanza *stanza; stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "a"," b", NULL); wocky_xmpp_connection_send_open_async (WOCKY_XMPP_CONNECTION (test->in), NULL, NULL, NULL, NULL, NULL, NULL, is_open_send_open_cb, test); wocky_xmpp_connection_recv_open_async (WOCKY_XMPP_CONNECTION (test->out), NULL, is_open_recv_open_cb, test); test->outstanding = 2; test_wait_pending (test); /* Input and output side are open, so they can be closed */ wocky_xmpp_connection_send_close_async (WOCKY_XMPP_CONNECTION (test->in), NULL, is_open_send_close_cb, test); wocky_xmpp_connection_recv_stanza_async (WOCKY_XMPP_CONNECTION (test->out), NULL, is_open_recv_close_cb, test); test->outstanding = 2; test_wait_pending (test); /* both sides are closed, all calls should yield _IS_CLOSED errors */ wocky_xmpp_connection_send_open_async (WOCKY_XMPP_CONNECTION (test->in), NULL, NULL, NULL, NULL, NULL, NULL, error_is_closed_send_open_cb, test); wocky_xmpp_connection_send_stanza_async (WOCKY_XMPP_CONNECTION (test->in), stanza, NULL, error_is_closed_send_stanza_cb, test); wocky_xmpp_connection_send_close_async (WOCKY_XMPP_CONNECTION (test->in), NULL, error_is_closed_send_close_cb, test); wocky_xmpp_connection_recv_open_async (WOCKY_XMPP_CONNECTION (test->out), NULL, error_is_closed_recv_open_cb, test); wocky_xmpp_connection_recv_stanza_async (WOCKY_XMPP_CONNECTION (test->out), NULL, error_is_closed_recv_stanza_cb, test); test->outstanding = 5; test_wait_pending (test); teardown_test (test); g_object_unref (stanza); } /* Send cancelled */ static void recv_cancelled_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *data = (test_data_t *) user_data; GError *error = NULL; g_assert (!wocky_xmpp_connection_send_stanza_finish ( WOCKY_XMPP_CONNECTION (source), res, &error)); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); data->outstanding--; g_main_loop_quit (data->loop); g_error_free (error); } static void test_recv_cancel (void) { WockyStanza *stanza; test_data_t *test = setup_test (); GCancellable *cancellable; test_open_connection (test); stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "a"," b", NULL); cancellable = g_cancellable_new (); wocky_xmpp_connection_recv_stanza_async (WOCKY_XMPP_CONNECTION (test->out), cancellable, recv_cancelled_cb, test); g_cancellable_cancel (cancellable); test->outstanding++; test_wait_pending (test); g_object_unref (stanza); g_object_unref (cancellable); test_close_connection (test); teardown_test (test); } /* Send message in a big chunk */ static void test_recv_simple_message_in_one_chunk (void) { WockyXmppConnection *connection; WockyTestStream *stream; gsize len; gchar message[] = SIMPLE_MESSAGE; GMainLoop *loop = NULL; test_data_t data = { NULL, FALSE }; loop = g_main_loop_new (NULL, FALSE); len = strlen (message); stream = g_object_new (WOCKY_TYPE_TEST_STREAM, NULL); connection = wocky_xmpp_connection_new (stream->stream0); g_timeout_add (1000, test_timeout_cb, NULL); data.loop = loop; g_output_stream_write_all (stream->stream1_output, message, len, NULL, NULL, NULL); wocky_xmpp_connection_recv_open_async (connection, NULL, received_open_cb, &data); g_main_loop_run (loop); g_main_loop_unref (loop); g_object_unref (stream); g_object_unref (connection); } /* test force close */ static void force_close_cb (GObject *source, GAsyncResult *res, gpointer user_data) { WockyXmppConnection *conn = WOCKY_XMPP_CONNECTION (source); test_data_t *data = (test_data_t *) user_data; g_assert (wocky_xmpp_connection_force_close_finish (conn, res, NULL)); g_main_loop_quit (data->loop); } static void test_force_close (void) { WockyXmppConnection *connection; WockyTestStream *stream; GMainLoop *loop = NULL; test_data_t data = { NULL, FALSE }; loop = g_main_loop_new (NULL, FALSE); stream = g_object_new (WOCKY_TYPE_TEST_STREAM, NULL); connection = wocky_xmpp_connection_new (stream->stream0); g_timeout_add (1000, test_timeout_cb, NULL); data.loop = loop; wocky_xmpp_connection_force_close_async (connection, NULL, force_close_cb, &data); g_main_loop_run (loop); g_main_loop_unref (loop); g_object_unref (stream); g_object_unref (connection); } int main (int argc, char **argv) { int result; test_init (argc, argv); g_test_add_func ("/xmpp-connection/initiation", test_instantiation); g_test_add_func ("/xmpp-connection/recv-simple-message", test_recv_simple_message); g_test_add_func ("/xmpp-connection/send-simple-message", test_send_simple_message); g_test_add_func ("/xmpp-connection/error-pending", test_error_pending); g_test_add_func ("/xmpp-connection/error-not-open", test_error_not_open); g_test_add_func ("/xmpp-connection/error-is-open-or-closed", test_error_is_open_or_closed); g_test_add_func ("/xmpp-connection/recv-cancel", test_recv_cancel); g_test_add_func ("/xmpp-connection/recv-simple-message-in-one-chunk", test_recv_simple_message_in_one_chunk); g_test_add_func ("/xmpp-connection/force-close", test_force_close); result = g_test_run (); test_deinit (); return result; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-contact-factory-test.c0000664000175000017500000001124512005516162027416 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "wocky-test-helper.h" static void test_instantiation (void) { WockyContactFactory *factory; factory = wocky_contact_factory_new (); g_object_unref (factory); } gboolean add_signal_received = FALSE; static void bare_contact_added (WockyContactFactory *factory, WockyBareContact *contact, gpointer data) { add_signal_received = TRUE; } static void test_ensure_bare_contact (void) { WockyContactFactory *factory; WockyBareContact *juliet, *a, *b; factory = wocky_contact_factory_new (); juliet = wocky_bare_contact_new ("juliet@example.org"); add_signal_received = FALSE; g_signal_connect (factory, "bare-contact-added", G_CALLBACK (bare_contact_added), NULL); a = wocky_contact_factory_ensure_bare_contact (factory, "juliet@example.org"); g_assert (wocky_bare_contact_equal (a, juliet)); g_assert (add_signal_received); b = wocky_contact_factory_ensure_bare_contact (factory, "juliet@example.org"); g_assert (a == b); g_object_unref (factory); g_object_unref (juliet); g_object_unref (a); g_object_unref (b); } static void test_lookup_bare_contact (void) { WockyContactFactory *factory; WockyBareContact *contact; factory = wocky_contact_factory_new (); g_assert (wocky_contact_factory_lookup_bare_contact (factory, "juliet@example.org") == NULL); contact = wocky_contact_factory_ensure_bare_contact (factory, "juliet@example.org"); g_assert (wocky_contact_factory_lookup_bare_contact (factory, "juliet@example.org") != NULL); g_object_unref (contact); /* contact has been disposed and so is not in the factory anymore */ g_assert (wocky_contact_factory_lookup_bare_contact (factory, "juliet@example.org") == NULL); g_object_unref (factory); } static void resource_contact_added (WockyContactFactory *factory, WockyBareContact *contact, gpointer data) { add_signal_received = TRUE; } static void test_ensure_resource_contact (void) { WockyContactFactory *factory; WockyBareContact *juliet, *bare; WockyResourceContact *juliet_balcony, *juliet_pub, *a, *b; GSList *resources; factory = wocky_contact_factory_new (); juliet = wocky_bare_contact_new ("juliet@example.org"); juliet_balcony = wocky_resource_contact_new (juliet, "Balcony"); juliet_pub = wocky_resource_contact_new (juliet, "Pub"); add_signal_received = FALSE; g_signal_connect (factory, "resource-contact-added", G_CALLBACK (resource_contact_added), NULL); /* Bare contact isn't in the factory yet */ a = wocky_contact_factory_ensure_resource_contact (factory, "juliet@example.org/Balcony"); g_assert (wocky_resource_contact_equal (a, juliet_balcony)); g_assert (add_signal_received); bare = wocky_contact_factory_lookup_bare_contact (factory, "juliet@example.org"); g_assert (bare != NULL); /* Resource has been added to the bare contact */ resources = wocky_bare_contact_get_resources (bare); g_assert_cmpuint (g_slist_length (resources), ==, 1); g_assert (g_slist_find (resources, a) != NULL); g_slist_free (resources); /* Bare contact is already in the factory */ b = wocky_contact_factory_ensure_resource_contact (factory, "juliet@example.org/Pub"); g_assert (wocky_resource_contact_equal (b, juliet_pub)); g_object_unref (factory); g_object_unref (juliet); g_object_unref (juliet_balcony); g_object_unref (juliet_pub); g_object_unref (a); g_object_unref (b); } static void test_lookup_resource_contact (void) { WockyContactFactory *factory; WockyResourceContact *contact; factory = wocky_contact_factory_new (); g_assert (wocky_contact_factory_lookup_resource_contact (factory, "juliet@example.org/Balcony") == NULL); contact = wocky_contact_factory_ensure_resource_contact (factory, "juliet@example.org/Balcony"); g_assert (wocky_contact_factory_lookup_resource_contact (factory, "juliet@example.org/Balcony") != NULL); g_object_unref (factory); g_object_unref (contact); } int main (int argc, char **argv) { int result; test_init (argc, argv); g_test_add_func ("/contact-factory/instantiation", test_instantiation); g_test_add_func ("/contact-factory/ensure-bare-contact", test_ensure_bare_contact); g_test_add_func ("/contact-factory/lookup-bare-contact", test_lookup_bare_contact); g_test_add_func ("/contact-factory/ensure-resource-contact", test_ensure_resource_contact); g_test_add_func ("/contact-factory/lookup-resource-contact", test_lookup_resource_contact); result = g_test_run (); test_deinit (); return result; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/test-resolver.c0000664000175000017500000002367012005516162025032 0ustar00cassidycassidy00000000000000/* * test-resolver.c - Source for TestResolver * Copyright © 2009 Collabora Ltd. * @author Vivek Dasmohapatra * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* this code largely culled from gunixresolver.c in glib and modified to * make a dummy resolver we can insert duff records in on the fly */ /* examples: * GResolver *original; * GResolver *kludged; * original = g_resolver_get_default (); * kludged = g_object_new (TEST_TYPE_RESOLVER, "real-resolver", original, NULL); * g_resolver_set_default (kludged); * test_resolver_add_SRV (TEST_RESOLVER (kludged), * "xmpp-client", "tcp", "jabber.earth.li", "localhost", 1337); * test_resolver_add_A (TEST_RESOLVER (kludged), "localhost", "127.0.1.1"); */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #ifdef G_OS_WIN32 #include #include #else #include #include #include #endif #include "test-resolver.h" #ifdef G_LOG_DOMAIN #undef G_LOG_DOMAIN #endif #define G_LOG_DOMAIN "test-resolver" enum { PROP_REAL_RESOLVER = 1, }; typedef struct _fake_host { char *key; char *addr; } fake_host; typedef struct _fake_serv { char *key; GSrvTarget *srv; } fake_serv; G_DEFINE_TYPE (TestResolver, test_resolver, G_TYPE_RESOLVER); /* ************************************************************************* */ static gchar * _service_rrname (const char *service, const char *protocol, const char *domain) { gchar *rrname, *ascii_domain = NULL; if (g_hostname_is_non_ascii (domain)) domain = ascii_domain = g_hostname_to_ascii (domain); rrname = g_strdup_printf ("_%s._%s.%s", service, protocol, domain); g_free (ascii_domain); return rrname; } static GList * find_fake_services (TestResolver *tr, const char *name) { GList *fake = NULL; GList *rval = NULL; for (fake = tr->fake_SRV; fake; fake = fake->next) { fake_serv *entry = fake->data; if (entry && !g_strcmp0 (entry->key, name)) rval = g_list_append (rval, g_srv_target_copy (entry->srv)); } return rval; } static GList * find_fake_hosts (TestResolver *tr, const char *name) { GList *fake = NULL; GList *rval = NULL; for (fake = tr->fake_A; fake; fake = fake->next) { fake_host *entry = fake->data; if (entry && !g_strcmp0 (entry->key, name)) rval = g_list_append (rval, g_inet_address_new_from_string (entry->addr)); } return rval; } static GList * srv_target_list_copy (GList *addr) { GList *copy = NULL; GList *l; for (l = addr; l != NULL; l = l->next) copy = g_list_prepend (copy, g_srv_target_copy (l->data)); return g_list_reverse (copy); } static void srv_target_list_free (GList *addr) { g_list_foreach (addr, (GFunc) g_srv_target_free, NULL); g_list_free (addr); } static GList * object_list_copy (GList *objs) { g_list_foreach (objs, (GFunc) g_object_ref, NULL); return g_list_copy (objs); } static void object_list_free (GList *objs) { g_list_foreach (objs, (GFunc) g_object_unref, NULL); g_list_free (objs); } static void lookup_service_async (GResolver *resolver, const char *rr, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer data) { TestResolver *tr = TEST_RESOLVER (resolver); GList *addr = find_fake_services (tr, rr); GObject *source = G_OBJECT (resolver); GSimpleAsyncResult *res = NULL; #ifdef DEBUG_FAKEDNS GList *x; #endif if (addr != NULL) { #ifdef DEBUG_FAKEDNS for (x = addr; x; x = x->next) g_debug ("FAKE SRV: addr: %s; port: %d; prio: %d; weight: %d;\n", g_srv_target_get_hostname ((GSrvTarget *) x->data), g_srv_target_get_port ((GSrvTarget *) x->data), g_srv_target_get_priority ((GSrvTarget *) x->data), g_srv_target_get_weight ((GSrvTarget *) x->data)); #endif res = g_simple_async_result_new (source, cb, data, lookup_service_async); } else { res = g_simple_async_result_new_error (source, cb, data, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND, "No fake SRV record registered"); } g_simple_async_result_set_op_res_gpointer (res, addr, (GDestroyNotify) srv_target_list_free); g_simple_async_result_complete (res); g_object_unref (res); } static GList * lookup_service_finish (GResolver *resolver, GAsyncResult *result, GError **error) { GList *res = NULL; GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); if (g_simple_async_result_propagate_error (simple, error)) return NULL; res = g_simple_async_result_get_op_res_gpointer (simple); return srv_target_list_copy (res); } static void lookup_by_name_async (GResolver *resolver, const gchar *hostname, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer data) { TestResolver *tr = TEST_RESOLVER (resolver); GList *addr = find_fake_hosts (tr, hostname); GObject *source = G_OBJECT (resolver); GSimpleAsyncResult *res = NULL; #ifdef DEBUG_FAKEDNS GList *x; char a[32]; #endif if (addr != NULL) { #ifdef DEBUG_FAKEDNS for (x = addr; x; x = x->next) g_debug ("FAKE HOST: addr: %s;\n", inet_ntop (AF_INET, g_inet_address_to_bytes (x->data), a, sizeof (a))); #endif res = g_simple_async_result_new (source, cb, data, lookup_by_name_async); } else { res = g_simple_async_result_new_error (source, cb, data, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND, "No fake hostname record registered"); } g_simple_async_result_set_op_res_gpointer (res, addr, (GDestroyNotify) object_list_free); g_simple_async_result_complete_in_idle (res); g_object_unref (res); } static GList * lookup_by_name_finish (GResolver *resolver, GAsyncResult *result, GError **error) { GList *res = NULL; GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); if (g_simple_async_result_propagate_error (simple, error)) return NULL; res = g_simple_async_result_get_op_res_gpointer (simple); return object_list_copy (res); } /* ************************************************************************* */ static void test_resolver_init (TestResolver *tr) { } static void test_resolver_set_property (GObject *object, guint propid, const GValue *value, GParamSpec *pspec) { TestResolver *resolver = TEST_RESOLVER (object); switch (propid) { case PROP_REAL_RESOLVER: if (resolver->real_resolver != NULL) g_object_unref (resolver->real_resolver); resolver->real_resolver = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); break; } } static void test_resolver_get_property (GObject *object, guint propid, GValue *value, GParamSpec *pspec) { TestResolver *resolver = TEST_RESOLVER (object); switch (propid) { case PROP_REAL_RESOLVER: g_value_set_object (value, resolver->real_resolver); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec); break; } } static void test_resolver_class_init (TestResolverClass *klass) { GResolverClass *resolver_class = G_RESOLVER_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass); GParamSpec *spec; object_class->set_property = test_resolver_set_property; object_class->get_property = test_resolver_get_property; spec = g_param_spec_object ("real-resolver", "real-resolver", "The real resolver to use when we don't have a kludge entry", G_TYPE_RESOLVER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT); g_object_class_install_property (object_class, PROP_REAL_RESOLVER, spec); resolver_class->lookup_by_name_async = lookup_by_name_async; resolver_class->lookup_by_name_finish = lookup_by_name_finish; resolver_class->lookup_service_async = lookup_service_async; resolver_class->lookup_service_finish = lookup_service_finish; } void test_resolver_reset (TestResolver *tr) { GList *fake = NULL; for (fake = tr->fake_A; fake; fake = fake->next) { fake_host *entry = fake->data; g_free (entry->key); g_free (entry->addr); g_free (entry); } g_list_free (tr->fake_A); tr->fake_A = NULL; for (fake = tr->fake_SRV; fake; fake = fake->next) { fake_serv *entry = fake->data; g_free (entry->key); g_srv_target_free (entry->srv); g_free (entry); } g_list_free (tr->fake_SRV); tr->fake_SRV = NULL; } gboolean test_resolver_add_A (TestResolver *tr, const char *hostname, const char *addr) { fake_host *entry = g_new0( fake_host, 1 ); entry->key = g_strdup (hostname); entry->addr = g_strdup (addr); tr->fake_A = g_list_append (tr->fake_A, entry); return TRUE; } gboolean test_resolver_add_SRV (TestResolver *tr, const char *service, const char *protocol, const char *domain, const char *addr, guint16 port) { char *key = _service_rrname (service, protocol, domain); fake_serv *entry = g_new0 (fake_serv, 1); GSrvTarget *serv = g_srv_target_new (addr, port, 0, 0); entry->key = key; entry->srv = serv; tr->fake_SRV = g_list_append (tr->fake_SRV, entry); return TRUE; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-bare-contact-test.c0000664000175000017500000002511212005516162026656 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "wocky-test-helper.h" static void test_instantiation (void) { WockyBareContact *a, *b; a = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", NULL); g_assert (WOCKY_IS_BARE_CONTACT (a)); /* WockyBareContact is a sub-class of WockyContact */ g_assert (WOCKY_IS_CONTACT (a)); b = wocky_bare_contact_new ("romeo@example.net"); g_assert (wocky_bare_contact_equal (a, b)); g_object_unref (a); g_object_unref (b); } static void test_contact_equal (void) { WockyBareContact *a, *b, *c, *d, *e, *f, *g, *h, *i; const gchar *groups[] = { "Friends", "Badger", NULL }; const gchar *groups2[] = { "Friends", "Snake", NULL }; const gchar *groups3[] = { "Badger", "Friends", NULL }; const gchar *groups4[] = { "aa", "bb", NULL }; const gchar *groups5[] = { "ab", "ba", NULL }; a = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "name", "Romeo", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH, "groups", groups, NULL); g_assert (wocky_bare_contact_equal (a, a)); g_assert (!wocky_bare_contact_equal (a, NULL)); g_assert (!wocky_bare_contact_equal (NULL, a)); /* Different jid */ b = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.org", "name", "Romeo", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH, "groups", groups, NULL); g_assert (!wocky_bare_contact_equal (a, b)); /* Different name */ c = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "name", "Juliet", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH, "groups", groups, NULL); g_assert (!wocky_bare_contact_equal (a, c)); /* Different subscription */ d = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "name", "Romeo", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_TO, "groups", groups, NULL); g_assert (!wocky_bare_contact_equal (a, d)); /* Different groups */ e = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "name", "Romeo", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH, "groups", groups2, NULL); g_assert (!wocky_bare_contact_equal (a, e)); /* Same groups but in a different order */ f = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "name", "Romeo", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH, "groups", groups3, NULL); g_assert (wocky_bare_contact_equal (a, f)); /* No group defined */ g = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "name", "Romeo", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH, NULL); g_assert (wocky_bare_contact_equal (g, g)); g_assert (!wocky_bare_contact_equal (a, g)); /* regression test: used to fail with old group comparison algorithm */ h = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "groups", groups4, NULL); i = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "groups", groups5, NULL); g_assert (!wocky_bare_contact_equal (h, i)); g_object_unref (a); g_object_unref (b); g_object_unref (c); g_object_unref (d); g_object_unref (e); g_object_unref (f); g_object_unref (g); g_object_unref (h); g_object_unref (i); } /* test wocky_bare_contact_add_group */ static void test_add_group (void) { WockyBareContact *a, *b, *c, *d; const gchar *groups[] = { "Friends", "Badger", NULL }; const gchar *groups2[] = { "Friends", "Badger", "Snake", NULL }; const gchar *groups3[] = { "Friends", NULL }; a = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "name", "Romeo", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH, "groups", groups, NULL); /* same as 'a' but with one more group */ b = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "name", "Romeo", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH, "groups", groups2, NULL); g_assert (!wocky_bare_contact_equal (a, b)); wocky_bare_contact_add_group (a, "Snake"); g_assert (wocky_bare_contact_equal (a, b)); /* try to add an already present group is no-op */ wocky_bare_contact_add_group (a, "Snake"); g_assert (wocky_bare_contact_equal (a, b)); /* No group */ c = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "name", "Romeo", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH, NULL); d = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "name", "Romeo", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH, "groups", groups3, NULL); g_assert (!wocky_bare_contact_equal (c, d)); wocky_bare_contact_add_group (c, "Friends"); g_assert (wocky_bare_contact_equal (c, d)); g_object_unref (a); g_object_unref (b); g_object_unref (c); g_object_unref (d); } /* test wocky_bare_contact_in_group */ static void test_in_group (void) { WockyBareContact *a, *b; const gchar *groups[] = { "Friends", "Badger", NULL }; a = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "name", "Romeo", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH, "groups", groups, NULL); g_assert (wocky_bare_contact_in_group (a, "Friends")); g_assert (wocky_bare_contact_in_group (a, "Badger")); g_assert (!wocky_bare_contact_in_group (a, "Snake")); /* no group defined */ b = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "name", "Romeo", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH, NULL); g_assert (!wocky_bare_contact_in_group (b, "Snake")); g_object_unref (a); g_object_unref (b); } /* test wocky_bare_contact_remove_group */ static void test_remove_group (void) { WockyBareContact *a, *b, *c; const gchar *groups[] = { "Friends", "Badger", NULL }; const gchar *groups2[] = { "Badger", NULL }; a = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "name", "Romeo", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH, "groups", groups, NULL); /* same as 'a' but with one more group */ b = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "name", "Romeo", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH, "groups", groups2, NULL); g_assert (!wocky_bare_contact_equal (a, b)); wocky_bare_contact_remove_group (a, "Friends"); g_assert (wocky_bare_contact_equal (a, b)); /* try to remove an already not present group is no-op */ wocky_bare_contact_remove_group (a, "Friends"); g_assert (wocky_bare_contact_equal (a, b)); /* no group defined */ c = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "name", "Romeo", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH, NULL); g_assert (wocky_bare_contact_equal (c, c)); wocky_bare_contact_remove_group (c, "Misc"); g_assert (wocky_bare_contact_equal (c, c)); g_object_unref (a); g_object_unref (b); g_object_unref (c); } static void test_contact_copy (void) { WockyBareContact *a, *copy; const gchar *groups[] = { "Friends", "Badger", NULL }; /* Full contact */ a = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "name", "Romeo", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH, "groups", groups, NULL); copy = wocky_bare_contact_copy (a); g_assert (wocky_bare_contact_equal (a, copy)); g_object_unref (copy); g_object_unref (a); /* No name */ a = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH, "groups", groups, NULL); copy = wocky_bare_contact_copy (a); g_assert (wocky_bare_contact_equal (a, copy)); g_object_unref (copy); g_object_unref (a); /* No subscription */ a = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "groups", groups, NULL); copy = wocky_bare_contact_copy (a); g_assert (wocky_bare_contact_equal (a, copy)); g_object_unref (copy); g_object_unref (a); /* No group */ a = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "romeo@example.net", "subscription", WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH, NULL); copy = wocky_bare_contact_copy (a); g_assert (wocky_bare_contact_equal (a, copy)); g_object_unref (copy); g_object_unref (a); } static void test_add_get_resource (void) { WockyBareContact *bare; WockyResourceContact *resource_1, *resource_2; GSList *resources; bare = wocky_bare_contact_new ("juliet@example.org"); resources = wocky_bare_contact_get_resources (bare); g_assert_cmpuint (g_slist_length (resources), ==, 0); /* add a ressource */ resource_1 = wocky_resource_contact_new (bare, "Resource1"); wocky_bare_contact_add_resource (bare, resource_1); resources = wocky_bare_contact_get_resources (bare); g_assert_cmpuint (g_slist_length (resources), ==, 1); g_assert (g_slist_find (resources, resource_1) != NULL); g_slist_free (resources); /* add another resource */ resource_2 = wocky_resource_contact_new (bare, "Resource2"); wocky_bare_contact_add_resource (bare, resource_2); resources = wocky_bare_contact_get_resources (bare); g_assert_cmpuint (g_slist_length (resources), ==, 2); g_assert (g_slist_find (resources, resource_1) != NULL); g_assert (g_slist_find (resources, resource_2) != NULL); g_slist_free (resources); /* first resource is disposed and so automatically removed */ g_object_unref (resource_1); resources = wocky_bare_contact_get_resources (bare); g_assert_cmpuint (g_slist_length (resources), ==, 1); g_assert (g_slist_find (resources, resource_2) != NULL); g_slist_free (resources); g_object_unref (bare); g_object_unref (resource_2); } int main (int argc, char **argv) { int result; test_init (argc, argv); g_test_add_func ("/bare-contact/instantiation", test_instantiation); g_test_add_func ("/bare-contact/contact-equal", test_contact_equal); g_test_add_func ("/bare-contact/add-group", test_add_group); g_test_add_func ("/bare-contact/in-group", test_in_group); g_test_add_func ("/bare-contact/remove-group", test_remove_group); g_test_add_func ("/bare-contact/contact-copy", test_contact_copy); g_test_add_func ("/bare-contact/add-get-resource", test_add_get_resource); result = g_test_run (); test_deinit (); return result; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/summarise-tests.py0000755000175000017500000000241112225363340025560 0ustar00cassidycassidy00000000000000#!/usr/bin/env python import sys import xml.dom.minidom as minidom def process(testbinary): cases = 0 passes = 0 failures = [] for e in testbinary.childNodes: if e.nodeType != e.ELEMENT_NODE or e.localName != 'testcase': continue if e.hasAttribute('skipped'): continue path = e.getAttribute("path") cases = cases + 1 status = e.getElementsByTagName('status')[0] if status.getAttribute('result') != 'success': failures += [ path ] return (cases, failures) doc = minidom.parse(sys.argv[1]) okay = True tests = {} for e in doc.childNodes[0].childNodes: if e.nodeType != e.ELEMENT_NODE or e.localName != 'testbinary': continue path = e.getAttribute("path") cases, failures = process(e) ocases, ofailures = tests.get (path, [ 0, []]) tests[path] = [ ocases + cases, ofailures + failures ] for name, [cases, failures] in tests.iteritems(): if failures == []: result = 'PASS' else: result = 'FAIL' okay = False print "%s: %s: %u/%u tests passed" % (result, name, cases - len (failures), cases) for f in failures: print "\tFailure: %s" % f if not okay: print "Disaster! Calamity!" sys.exit(1) telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-data-form-test.c0000664000175000017500000006651212005516162026177 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "wocky-test-helper.h" static void test_new_from_form (void) { WockyStanza *stanza; WockyNode *node; WockyDataForm *form; GError *error = NULL; stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ,WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, NULL); /* node doesn't contain a form */ form = wocky_data_form_new_from_form (wocky_stanza_get_top_node (stanza), &error); g_assert (form == NULL); g_assert_error (error, WOCKY_DATA_FORM_ERROR, WOCKY_DATA_FORM_ERROR_NOT_FORM); g_clear_error (&error); /* add 'x' node */ node = wocky_node_add_child_ns (wocky_stanza_get_top_node (stanza), "x", WOCKY_XMPP_NS_DATA); /* the x node doesn't have a 'type' attribute */ form = wocky_data_form_new_from_form (wocky_stanza_get_top_node (stanza), &error); g_assert (form == NULL); g_assert_error (error, WOCKY_DATA_FORM_ERROR, WOCKY_DATA_FORM_ERROR_WRONG_TYPE); g_clear_error (&error); /* set wrong type */ wocky_node_set_attribute (node, "type", "badger"); form = wocky_data_form_new_from_form (wocky_stanza_get_top_node (stanza), &error); g_assert (form == NULL); g_assert_error (error, WOCKY_DATA_FORM_ERROR, WOCKY_DATA_FORM_ERROR_WRONG_TYPE); g_clear_error (&error); /* set the right type */ wocky_node_set_attribute (node, "type", "form"); form = wocky_data_form_new_from_form (wocky_stanza_get_top_node (stanza), &error); g_assert (form != NULL); g_assert_no_error (error); g_object_unref (form); g_object_unref (stanza); } static WockyStanza * create_bot_creation_form_stanza (void) { /* This stanza is inspired from Example 2 of XEP-0004: Data Forms */ return wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ,WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '(', "x", ':', WOCKY_XMPP_NS_DATA, '@', "type", "form", '(', "title", '$', "My Title", ')', '(', "instructions", '$', "Badger", ')', /* hidden field */ '(', "field", '@', "type", "hidden", '@', "var", "FORM_TYPE", '(', "value", '$', "jabber:bot", ')', ')', /* fixed field */ '(', "field", '@', "type", "fixed", '(', "value", '$', "fixed value", ')', ')', /* text-single field */ '(', "field", '@', "type", "text-single", '@', "var", "botname", '@', "label", "The name of your bot", ')', /* field with no type. type='' is only a SHOULD; the default is * text-single */ '(', "field", '@', "var", "pseudonym", '@', "label", "Your bot's name at the weekend", ')', /* text-multi field */ '(', "field", '@', "type", "text-multi", '@', "var", "description", '@', "label", "Helpful description of your bot", ')', /* boolean field */ '(', "field", '@', "type", "boolean", '@', "var", "public", '@', "label", "Public bot?", '(', "required", ')', '(', "value", '$', "false", ')', ')', /* text-private field */ '(', "field", '@', "type", "text-private", '@', "var", "password", '@', "label", "Password for special access", ')', /* list-multi field */ '(', "field", '@', "type", "list-multi", '@', "var", "features", '@', "label", "What features will the bot support?", '(', "option", '@', "label", "Contests", '(', "value", '$', "contests", ')', ')', '(', "option", '@', "label", "News", '(', "value", '$', "news", ')', ')', '(', "option", '@', "label", "Polls", '(', "value", '$', "polls", ')', ')', '(', "option", '@', "label", "Reminders", '(', "value", '$', "reminders", ')', ')', '(', "option", '@', "label", "Search", '(', "value", '$', "search", ')', ')', '(', "value", '$', "news", ')', '(', "value", '$', "search", ')', ')', /* list-single field */ '(', "field", '@', "type", "list-single", '@', "var", "maxsubs", '@', "label", "Maximum number of subscribers", '(', "value", '$', "20", ')', '(', "option", '@', "label", "10", '(', "value", '$', "10", ')', ')', '(', "option", '@', "label", "20", '(', "value", '$', "20", ')', ')', '(', "option", '@', "label", "30", '(', "value", '$', "30", ')', ')', '(', "option", '@', "label", "50", '(', "value", '$', "50", ')', ')', '(', "option", '@', "label", "100", '(', "value", '$', "100", ')', ')', '(', "option", '@', "label", "None", '(', "value", '$', "none", ')', ')', ')', /* jid-multi field */ '(', "field", '@', "type", "jid-multi", '@', "var", "invitelist", '@', "label", "People to invite", '(', "desc", '$', "Tell friends", ')', ')', /* jid-single field */ '(', "field", '@', "type", "jid-single", '@', "var", "botjid", '@', "label", "The JID of the bot", ')', ')', NULL); } static void test_parse_form (void) { WockyStanza *stanza; WockyDataForm *form; GSList *l; /* used to check that fields are stored in the right order */ WockyDataFormField expected_types[] = { { WOCKY_DATA_FORM_FIELD_TYPE_HIDDEN, "FORM_TYPE", NULL, NULL, FALSE, NULL, NULL, NULL }, { WOCKY_DATA_FORM_FIELD_TYPE_FIXED, NULL, NULL, NULL, FALSE, NULL, NULL, NULL }, { WOCKY_DATA_FORM_FIELD_TYPE_TEXT_SINGLE, "botname", "The name of your bot", NULL, FALSE, NULL, NULL, NULL }, { WOCKY_DATA_FORM_FIELD_TYPE_TEXT_SINGLE, "pseudonym", "Your bot's name at the weekend", NULL, FALSE, NULL, NULL, NULL }, { WOCKY_DATA_FORM_FIELD_TYPE_TEXT_MULTI, "description", "Helpful description of your bot", NULL, FALSE, NULL, NULL, NULL }, { WOCKY_DATA_FORM_FIELD_TYPE_BOOLEAN, "public", "Public bot?", NULL, TRUE, NULL, NULL, NULL }, { WOCKY_DATA_FORM_FIELD_TYPE_TEXT_PRIVATE, "password", "Password for special access", NULL, FALSE, NULL, NULL, NULL }, { WOCKY_DATA_FORM_FIELD_TYPE_LIST_MULTI, "features", "What features will the bot support?", NULL, FALSE, NULL, NULL, NULL }, { WOCKY_DATA_FORM_FIELD_TYPE_LIST_SINGLE, "maxsubs", "Maximum number of subscribers", NULL, FALSE, NULL, NULL, NULL }, { WOCKY_DATA_FORM_FIELD_TYPE_JID_MULTI, "invitelist", "People to invite", "Tell friends", FALSE, NULL, NULL, NULL }, { WOCKY_DATA_FORM_FIELD_TYPE_JID_SINGLE, "botjid", "The JID of the bot", NULL, FALSE, NULL, NULL, NULL }, }; guint i; WockyDataFormField *field; GStrv strv; WockyDataFormFieldOption features_options[] = { { "Contests", "contests" }, { "News", "news" }, { "Polls", "polls" }, { "Reminders", "reminders" }, { "Search", "search" }, }; WockyDataFormFieldOption maxsubs_options[] = { { "10", "10" }, { "20", "20" }, { "30", "30" }, { "50", "50" }, { "100", "100" }, { "None", "none" }, }; stanza = create_bot_creation_form_stanza (); form = wocky_data_form_new_from_form (wocky_stanza_get_top_node (stanza), NULL); g_assert (form != NULL); g_object_unref (stanza); g_assert_cmpstr (wocky_data_form_get_title (form), ==, "My Title"); g_assert_cmpstr (wocky_data_form_get_instructions (form), ==, "Badger"); g_assert_cmpuint (g_slist_length (form->fields_list), ==, 11); for (l = form->fields_list, i = 0; l != NULL; l = g_slist_next (l), i++) { field = l->data; g_assert (field != NULL); g_assert_cmpuint (field->type, ==, expected_types[i].type); g_assert_cmpstr (field->var, ==, expected_types[i].var); g_assert_cmpstr (field->label, ==, expected_types[i].label); g_assert_cmpstr (field->desc, ==, expected_types[i].desc); g_assert (field->required == expected_types[i].required); g_assert (field->value == NULL); } g_assert_cmpuint (g_hash_table_size (form->fields), ==, 10); /* check hidden field */ field = g_hash_table_lookup (form->fields, "FORM_TYPE"); g_assert (field != NULL); g_assert (G_VALUE_TYPE (field->default_value) == G_TYPE_STRING); g_assert_cmpstr (g_value_get_string (field->default_value), ==, "jabber:bot"); g_assert (field->options == NULL); /* check text-single field */ field = g_hash_table_lookup (form->fields, "botname"); g_assert (field != NULL); g_assert (field->default_value == NULL); g_assert (field->options == NULL); /* check implicitly text-single field */ field = g_hash_table_lookup (form->fields, "pseudonym"); g_assert (field != NULL); g_assert (field->default_value == NULL); g_assert (field->options == NULL); /* check text-multi field */ field = g_hash_table_lookup (form->fields, "description"); g_assert (field != NULL); g_assert (field->default_value == NULL); g_assert (field->options == NULL); /* check boolean field */ field = g_hash_table_lookup (form->fields, "public"); g_assert (field != NULL); g_assert (G_VALUE_TYPE (field->default_value) == G_TYPE_BOOLEAN); g_assert (!g_value_get_boolean (field->default_value)); g_assert (field->options == NULL); /* check text-private field */ field = g_hash_table_lookup (form->fields, "password"); g_assert (field != NULL); g_assert (field->default_value == NULL); g_assert (field->options == NULL); /* check list-multi field */ field = g_hash_table_lookup (form->fields, "features"); g_assert (field != NULL); g_assert (G_VALUE_TYPE (field->default_value) == G_TYPE_STRV); strv = g_value_get_boxed (field->default_value); g_assert_cmpuint (g_strv_length (strv), ==, 2); g_assert_cmpstr (strv[0], ==, "news"); g_assert_cmpstr (strv[1], ==, "search"); g_assert_cmpuint (g_slist_length (field->options), ==, 5); for (l = field->options, i = 0; l != NULL; l = g_slist_next (l), i++) { WockyDataFormFieldOption *option = l->data; g_assert_cmpstr (option->value, ==, features_options[i].value); g_assert_cmpstr (option->label, ==, features_options[i].label); } /* check list-single field */ field = g_hash_table_lookup (form->fields, "maxsubs"); g_assert (field != NULL); g_assert (G_VALUE_TYPE (field->default_value) == G_TYPE_STRING); g_assert_cmpstr (g_value_get_string (field->default_value), ==, "20"); g_assert_cmpuint (g_slist_length (field->options), ==, 6); for (l = field->options, i = 0; l != NULL; l = g_slist_next (l), i++) { WockyDataFormFieldOption *option = l->data; g_assert_cmpstr (option->value, ==, maxsubs_options[i].value); g_assert_cmpstr (option->label, ==, maxsubs_options[i].label); } /* check jid-multi field */ field = g_hash_table_lookup (form->fields, "invitelist"); g_assert (field != NULL); g_assert (field->default_value == NULL); g_assert (field->options == NULL); /* check boolean field */ field = g_hash_table_lookup (form->fields, "botjid"); g_assert (field != NULL); g_assert (field->default_value == NULL); g_assert (field->options == NULL); g_object_unref (form); } static void test_raw_value_contents (void) { WockyStanza *stanza; WockyDataForm *form; const gchar *description[] = { "Badger", "Mushroom", "Snake", NULL }; gboolean set_succeeded; /* Create fields without WockyNode to trigger this bug: * https://bugs.freedesktop.org/show_bug.cgi?id=43584 */ form = g_object_new (WOCKY_TYPE_DATA_FORM, NULL); g_assert (form != NULL); /* set text-single field */ set_succeeded = wocky_data_form_set_string (form, "botname", "The Jabber Google Bot", FALSE); g_assert (!set_succeeded); set_succeeded = wocky_data_form_set_string (form, "botname", "The Jabber Google Bot", TRUE); g_assert (set_succeeded); /* set text-multi field */ set_succeeded = wocky_data_form_set_strv (form, "description", description, FALSE); g_assert (!set_succeeded); set_succeeded = wocky_data_form_set_strv (form, "description", description, TRUE); g_assert (set_succeeded); /* set boolean field */ set_succeeded = wocky_data_form_set_boolean (form, "public", FALSE, FALSE); g_assert (!set_succeeded); set_succeeded = wocky_data_form_set_boolean (form, "public", FALSE, TRUE); g_assert (set_succeeded); stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL, NULL); wocky_data_form_add_to_node (form, wocky_stanza_get_top_node (stanza)); g_object_unref (stanza); g_object_unref (form); } static void test_submit (void) { WockyStanza *stanza; WockyDataForm *form; WockyNode *x; GSList *l; const gchar *description[] = { "Badger", "Mushroom", "Snake", NULL }; const gchar *features[] = { "news", "search", NULL }; const gchar *invitees[] = { "juliet@example.org", "romeo@example.org", NULL }; gboolean set_succeeded; stanza = create_bot_creation_form_stanza (); form = wocky_data_form_new_from_form (wocky_stanza_get_top_node (stanza), NULL); g_assert (form != NULL); g_object_unref (stanza); /* set text-single field */ set_succeeded = wocky_data_form_set_string (form, "botname", "The Jabber Google Bot", FALSE); g_assert (set_succeeded); /* set text-multi field */ set_succeeded = wocky_data_form_set_strv (form, "description", description, FALSE); g_assert (set_succeeded); /* set boolean field */ set_succeeded = wocky_data_form_set_boolean (form, "public", FALSE, FALSE); g_assert (set_succeeded); /* set text-private field */ set_succeeded = wocky_data_form_set_string (form, "password", "S3cr1t", FALSE); g_assert (set_succeeded); /* set list-multi field */ set_succeeded = wocky_data_form_set_strv (form, "features", features, FALSE); g_assert (set_succeeded); /* set list-single field */ set_succeeded = wocky_data_form_set_string (form, "maxsubs", "20", FALSE); g_assert (set_succeeded); /* set jid-multi field */ set_succeeded = wocky_data_form_set_strv (form, "invitelist", invitees, FALSE); g_assert (set_succeeded); /* set jid-single field */ set_succeeded = wocky_data_form_set_string (form, "botjid", "bobot@example.org", FALSE); g_assert (set_succeeded); stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL, NULL); wocky_data_form_submit (form, wocky_stanza_get_top_node (stanza)); x = wocky_node_get_child_ns (wocky_stanza_get_top_node (stanza), "x", WOCKY_XMPP_NS_DATA); g_assert (x != NULL); g_assert_cmpstr (wocky_node_get_attribute (x, "type"), ==, "submit"); for (l = x->children; l != NULL; l = g_slist_next (l)) { WockyNode *v, *node = l->data; const gchar *var, *type, *value = NULL; g_assert_cmpstr (node->name, ==, "field"); var = wocky_node_get_attribute (node, "var"); g_assert (var != NULL); type = wocky_node_get_attribute (node, "type"); v = wocky_node_get_child (node, "value"); if (v != NULL) value = v->content; if (!wocky_strdiff (var, "FORM_TYPE")) { g_assert_cmpstr (type, ==, "hidden"); g_assert_cmpstr (value, ==, "jabber:bot"); } else if (!wocky_strdiff (var, "botname")) { g_assert_cmpstr (type, ==, "text-single"); g_assert_cmpstr (value, ==, "The Jabber Google Bot"); } else if (!wocky_strdiff (var, "description")) { GSList *m; gboolean badger = FALSE, mushroom = FALSE, snake = FALSE; g_assert_cmpstr (type, ==, "text-multi"); for (m = node->children; m != NULL; m = g_slist_next (m)) { WockyNode *tmp = m->data; g_assert_cmpstr (tmp->name, ==, "value"); if (!wocky_strdiff (tmp->content, "Badger")) badger = TRUE; else if (!wocky_strdiff (tmp->content, "Mushroom")) mushroom = TRUE; else if (!wocky_strdiff (tmp->content, "Snake")) snake = TRUE; else g_assert_not_reached (); } g_assert (badger && mushroom && snake); } else if (!wocky_strdiff (var, "public")) { g_assert_cmpstr (type, ==, "boolean"); g_assert_cmpstr (value, ==, "0"); } else if (!wocky_strdiff (var, "password")) { g_assert_cmpstr (type, ==, "text-private"); g_assert_cmpstr (value, ==, "S3cr1t"); } else if (!wocky_strdiff (var, "features")) { GSList *m; gboolean news = FALSE, search = FALSE; g_assert_cmpstr (type, ==, "list-multi"); for (m = node->children; m != NULL; m = g_slist_next (m)) { WockyNode *tmp = m->data; g_assert_cmpstr (tmp->name, ==, "value"); if (!wocky_strdiff (tmp->content, "news")) news = TRUE; else if (!wocky_strdiff (tmp->content, "search")) search = TRUE; else g_assert_not_reached (); } g_assert (news && search); } else if (!wocky_strdiff (var, "maxsubs")) { g_assert_cmpstr (type, ==, "list-single"); g_assert_cmpstr (value, ==, "20"); } else if (!wocky_strdiff (var, "invitelist")) { GSList *m; gboolean juliet = FALSE, romeo = FALSE; g_assert_cmpstr (type, ==, "jid-multi"); for (m = node->children; m != NULL; m = g_slist_next (m)) { WockyNode *tmp = m->data; g_assert_cmpstr (tmp->name, ==, "value"); if (!wocky_strdiff (tmp->content, "juliet@example.org")) juliet = TRUE; else if (!wocky_strdiff (tmp->content, "romeo@example.org")) romeo = TRUE; else g_assert_not_reached (); } g_assert (juliet && romeo); } else if (!wocky_strdiff (var, "botjid")) { g_assert_cmpstr (type, ==, "jid-single"); g_assert_cmpstr (value, ==, "bobot@example.org"); } else g_assert_not_reached (); } g_object_unref (stanza); g_object_unref (form); } /* Test creating and submitting a form response blindly, without first asking * the server for the form fields. */ static void test_submit_blindly (void) { WockyDataForm *form = g_object_new (WOCKY_TYPE_DATA_FORM, NULL); const gchar * const the_xx[] = { "Romy", "Oliver", "Jamie", NULL }; gboolean succeeded; WockyStanza *stanza, *expected; /* We didn't actually parse a form, so it doesn't have any pre-defined * fields. Thus, the setters should all fail if we don't tell them to create * the fields if missing. */ succeeded = wocky_data_form_set_string (form, "band-name", "The XX", FALSE); g_assert (!succeeded); succeeded = wocky_data_form_set_strv (form, "band-members", the_xx, FALSE); g_assert (!succeeded); succeeded = wocky_data_form_set_boolean (form, "is-meh", TRUE, FALSE); g_assert (!succeeded); g_assert (form->fields_list == NULL); g_assert_cmpuint (0, ==, g_hash_table_size (form->fields)); /* Since the form doesn't have a FORM_TYPE yet, we should be able to set it. */ succeeded = wocky_data_form_set_type (form, "http://example.com/band-info"); g_assert (succeeded); /* But now that it does have one, we shouldn't be able to change it. */ succeeded = wocky_data_form_set_type (form, "stoats"); g_assert (!succeeded); /* If we forcibly create the fields we care about, setting them should * succeed, and they should show up when we submit the form! */ succeeded = wocky_data_form_set_string (form, "band-name", "The XX", TRUE); g_assert (succeeded); succeeded = wocky_data_form_set_strv (form, "band-members", the_xx, TRUE); g_assert (succeeded); succeeded = wocky_data_form_set_boolean (form, "is-meh", TRUE, TRUE); g_assert (succeeded); stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL, NULL); wocky_data_form_submit (form, wocky_stanza_get_top_node (stanza)); expected = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL, '(', "x", ':', WOCKY_XMPP_NS_DATA, '@', "type", "submit", '(', "field", '@', "type", "hidden", '@', "var", "FORM_TYPE", '(', "value", '$', "http://example.com/band-info", ')', ')', '(', "field", '@', "var", "band-name", '(', "value", '$', "The XX", ')', ')', '(', "field", '@', "var", "band-members", '(', "value", '$', "Romy", ')', '(', "value", '$', "Oliver", ')', '(', "value", '$', "Jamie", ')', ')', '(', "field", '@', "var", "is-meh", '(', "value", '$', "1", ')', ')', ')', NULL); test_assert_stanzas_equal_no_id (expected, stanza); g_object_unref (expected); g_object_unref (stanza); g_object_unref (form); } static WockyStanza * create_search_form_stanza (void) { /* This stanza is inspired from Example 6 of XEP-0004: Data Forms */ return wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ,WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '(', "x", ':', WOCKY_XMPP_NS_DATA, '@', "type", "form", '(', "title", '$', "My Title", ')', '(', "instructions", '$', "Badger", ')', '(', "field", '@', "type", "text-single", '@', "var", "search_request", ')', ')', NULL); } static void test_parse_multi_result (void) { WockyStanza *stanza; WockyDataForm *form; GSList *l; gboolean item1 = FALSE, item2 = FALSE; stanza = create_search_form_stanza (); form = wocky_data_form_new_from_form (wocky_stanza_get_top_node (stanza), NULL); g_assert (form != NULL); g_object_unref (stanza); /* create the result stanza */ stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '(', "x", ':', WOCKY_XMPP_NS_DATA, '@', "type", "result", '(', "title", '$', "Search result", ')', '(', "reported", '(', "field", '@', "var", "name", '@', "type", "text-single", ')', '(', "field", '@', "var", "url", '@', "type", "text-single", ')', ')', /* first item */ '(', "item", '(', "field", '@', "var", "name", '(', "value", '$', "name1", ')', ')', '(', "field", '@', "var", "url", '(', "value", '$', "url1", ')', ')', ')', /* second item */ '(', "item", '(', "field", '@', "var", "name", '(', "value", '$', "name2", ')', ')', '(', "field", '@', "var", "url", '(', "value", '$', "url2", ')', ')', ')', ')', NULL); g_assert (wocky_data_form_parse_result (form, wocky_stanza_get_top_node (stanza), NULL)); g_object_unref (stanza); g_assert_cmpuint (g_slist_length (form->results), ==, 2); for (l = form->results; l != NULL; l = g_slist_next (l)) { GSList *result = l->data, *m; gboolean name = FALSE, url = FALSE; for (m = result; m != NULL; m = g_slist_next (m)) { WockyDataFormField *field = m->data; if (!wocky_strdiff (field->var, "name")) { if (!wocky_strdiff (g_value_get_string (field->value), "name1")) item1 = TRUE; else if (!wocky_strdiff (g_value_get_string (field->value), "name2")) item2 = TRUE; else g_assert_not_reached (); name = TRUE; } else if (!wocky_strdiff (field->var, "url")) { if (item2) g_assert_cmpstr (g_value_get_string (field->value), ==, "url2"); else if (item1) g_assert_cmpstr (g_value_get_string (field->value), ==, "url1"); else g_assert_not_reached (); url = TRUE; } else g_assert_not_reached (); } g_assert (name && url); } g_assert (item1 && item2); g_object_unref (form); } static void test_parse_single_result (void) { WockyStanza *stanza; WockyDataForm *form; GSList *result, *l; gboolean form_type = FALSE, botname = FALSE; stanza = create_bot_creation_form_stanza (); form = wocky_data_form_new_from_form (wocky_stanza_get_top_node (stanza), NULL); g_assert (form != NULL); g_object_unref (stanza); /* create the result stanza */ stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '(', "x", ':', WOCKY_XMPP_NS_DATA, '@', "type", "result", /* hidden field */ '(', "field", '@', "type", "hidden", '@', "var", "FORM_TYPE", '(', "value", '$', "jabber:bot", ')', ')', /* text-single field */ '(', "field", '@', "type", "text-single", '@', "var", "botname", '(', "value", '$', "The Bot", ')', ')', ')', NULL); g_assert (wocky_data_form_parse_result (form, wocky_stanza_get_top_node (stanza), NULL)); g_object_unref (stanza); g_assert_cmpuint (g_slist_length (form->results), ==, 1); result = form->results->data; g_assert_cmpuint (g_slist_length (result), ==, 2); for (l = result; l != NULL; l = g_slist_next (l)) { WockyDataFormField *field = l->data; if (!wocky_strdiff (field->var, "FORM_TYPE")) { g_assert_cmpstr (g_value_get_string (field->value), ==, "jabber:bot"); g_assert (field->type == WOCKY_DATA_FORM_FIELD_TYPE_HIDDEN); form_type = TRUE; } else if (!wocky_strdiff (field->var, "botname")) { g_assert_cmpstr (g_value_get_string (field->value), ==, "The Bot"); g_assert (field->type == WOCKY_DATA_FORM_FIELD_TYPE_TEXT_SINGLE); botname = TRUE; } else g_assert_not_reached (); } g_assert (form_type && botname); g_object_unref (form); } int main (int argc, char **argv) { int result; test_init (argc, argv); g_test_add_func ("/data-form/instantiation", test_new_from_form); g_test_add_func ("/data-form/parse-form", test_parse_form); g_test_add_func ("/data-form/raw_value_contents", test_raw_value_contents); g_test_add_func ("/data-form/submit", test_submit); g_test_add_func ("/data-form/submit-blindly", test_submit_blindly); g_test_add_func ("/data-form/parse-multi-result", test_parse_multi_result); g_test_add_func ("/data-form/parse-single-result", test_parse_single_result); result = g_test_run (); test_deinit (); return result; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-test-helper.c0000664000175000017500000001647412212322440025600 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "wocky-test-helper.h" #include "wocky-test-stream.h" #define TIMEOUT 10 gboolean test_timeout_cb (gpointer data) { g_test_message ("Timeout reached :("); g_assert_not_reached (); return FALSE; } static test_data_t * setup_test_full (guint timeout, const gchar *in_jid, const gchar *out_jid) { test_data_t *data; data = g_new0 (test_data_t, 1); data->loop = g_main_loop_new (NULL, FALSE); data->stream = g_object_new (WOCKY_TYPE_TEST_STREAM, NULL); data->in = wocky_xmpp_connection_new (data->stream->stream0); data->out = wocky_xmpp_connection_new (data->stream->stream1); data->session_in = wocky_session_new_with_connection (data->in, in_jid); data->session_out = wocky_session_new_with_connection (data->out, out_jid); data->sched_in = wocky_session_get_porter (data->session_in); data->sched_out = wocky_session_get_porter (data->session_out); data->expected_stanzas = g_queue_new (); data->cancellable = g_cancellable_new (); data->timeout_id = g_timeout_add_seconds (timeout, test_timeout_cb, NULL); return data; } test_data_t * setup_test_with_jids (const gchar *in_jid, const gchar *out_jid) { return setup_test_full (TIMEOUT, in_jid, out_jid); } test_data_t * setup_test_with_timeout (guint timeout) { return setup_test_full (timeout, "example.com", "example.com"); } test_data_t * setup_test (void) { return setup_test_full (TIMEOUT, "example.com", "example.com"); } void teardown_test (test_data_t *data) { g_main_loop_unref (data->loop); g_object_unref (data->stream); g_object_unref (data->in); g_object_unref (data->out); if (data->session_in != NULL) g_object_unref (data->session_in); if (data->session_out != NULL) g_object_unref (data->session_out); g_object_unref (data->cancellable); g_source_remove (data->timeout_id); /* All the stanzas should have been received */ g_assert (g_queue_get_length (data->expected_stanzas) == 0); g_queue_free (data->expected_stanzas); g_free (data); } void test_wait_pending (test_data_t *test) { while (test->outstanding > 0) g_main_loop_run (test->loop); } static void send_received_open_cb (GObject *source, GAsyncResult *res, gpointer user_data) { WockyXmppConnection *conn = WOCKY_XMPP_CONNECTION (source); test_data_t *d = (test_data_t *) user_data; g_assert (wocky_xmpp_connection_recv_open_finish (conn, res, NULL, NULL, NULL, NULL, NULL, NULL)); d->outstanding--; g_main_loop_quit (d->loop); } static void send_open_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *data = (test_data_t *) user_data; WockyXmppConnection *conn; g_assert (wocky_xmpp_connection_send_open_finish ( WOCKY_XMPP_CONNECTION (source), res, NULL)); /* The other connection has to receive the opening */ if (WOCKY_XMPP_CONNECTION (source) == data->in) conn = data->out; else conn = data->in; wocky_xmpp_connection_recv_open_async (conn, NULL, send_received_open_cb, user_data); } static void open_connection (test_data_t *test, WockyXmppConnection *connection) { wocky_xmpp_connection_send_open_async (connection, NULL, NULL, NULL, NULL, NULL, NULL, send_open_cb, test); test->outstanding++; test_wait_pending (test); } /* Open XMPP the 'in' connection */ void test_open_connection (test_data_t *test) { open_connection (test, test->in); } /* Open both XMPP connections */ void test_open_both_connections (test_data_t *test) { open_connection (test, test->in); open_connection (test, test->out); } static void wait_close_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *data = (test_data_t *) user_data; WockyStanza *s; GError *error = NULL; s = wocky_xmpp_connection_recv_stanza_finish (WOCKY_XMPP_CONNECTION (source), res, &error); g_assert (s == NULL); /* connection has been disconnected */ g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_CLOSED); g_error_free (error); data->outstanding--; g_main_loop_quit (data->loop); } static void close_sent_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *data = (test_data_t *) user_data; g_assert (wocky_xmpp_connection_send_close_finish ( WOCKY_XMPP_CONNECTION (source), res, NULL)); data->outstanding--; g_main_loop_quit (data->loop); } /* Close XMPP connections on both sides */ void test_close_connection (test_data_t *test) { wocky_xmpp_connection_recv_stanza_async (test->out, NULL, wait_close_cb, test); test->outstanding++; /* Close the connection */ wocky_xmpp_connection_send_close_async ( WOCKY_XMPP_CONNECTION (test->in), NULL, close_sent_cb, test); test->outstanding++; test_wait_pending (test); } static void sched_close_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; GError *error = NULL; gboolean ret = wocky_porter_close_finish ( WOCKY_PORTER (source), res, &error); g_assert_no_error (error); g_assert (ret); test->outstanding--; g_main_loop_quit (test->loop); } static void wait_sched_close_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; WockyXmppConnection *connection = WOCKY_XMPP_CONNECTION (source); WockyStanza *s; GError *error = NULL; s = wocky_xmpp_connection_recv_stanza_finish (connection, res, &error); g_assert (s == NULL); /* connection has been disconnected */ g_assert_error (error, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_CLOSED); g_error_free (error); /* close on our side */ wocky_xmpp_connection_send_close_async (connection, NULL, close_sent_cb, test); /* Don't decrement test->outstanding as we are waiting for another * callback */ g_main_loop_quit (test->loop); } void test_close_porter (test_data_t *test) { /* close connections */ wocky_xmpp_connection_recv_stanza_async (test->in, NULL, wait_sched_close_cb, test); wocky_porter_close_async (test->sched_out, NULL, sched_close_cb, test); test->outstanding += 2; test_wait_pending (test); } void test_expected_stanza_received (test_data_t *test, WockyStanza *stanza) { WockyStanza *expected; expected = g_queue_pop_head (test->expected_stanzas); g_assert (expected != NULL); test_assert_nodes_equal (wocky_stanza_get_top_node (stanza), wocky_stanza_get_top_node (expected)); g_object_unref (expected); test->outstanding--; g_main_loop_quit (test->loop); } void test_close_both_porters (test_data_t *test) { wocky_porter_close_async (test->sched_out, NULL, sched_close_cb, test); wocky_porter_close_async (test->sched_in, NULL, sched_close_cb, test); test->outstanding += 2; test_wait_pending (test); } void test_init (int argc, char **argv) { g_test_init (&argc, &argv, NULL); g_test_bug_base ("http://bugs.freedesktop.org/show_bug.cgi?id="); g_type_init (); wocky_init (); } void test_deinit (void) { wocky_deinit (); } static gboolean cancel_in_idle_cb (gpointer cancellable) { g_cancellable_cancel (cancellable); return FALSE; } void test_cancel_in_idle (GCancellable *cancellable) { g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, cancel_in_idle_cb, g_object_ref (cancellable), g_object_unref); } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-stanza-test.c0000664000175000017500000006011612212322440025611 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "wocky-test-helper.h" static void test_copy (void) { WockyStanza *iq, *copy, *expected; iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", '@', "id", "one", '(', "query", ':', "http://jabber.org/protocol/disco#items", ')', NULL); /* just to make sure */ expected = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", '@', "id", "one", '(', "query", ':', "http://jabber.org/protocol/disco#items", ')', NULL); copy = wocky_stanza_copy (iq); g_assert (copy != NULL); test_assert_stanzas_equal (iq, copy); test_assert_stanzas_equal (expected, copy); g_object_unref (iq); g_object_unref (copy); g_object_unref (expected); } static void test_build_iq_result_simple_ack (void) { WockyStanza *iq, *reply, *expected; iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", '@', "id", "one", '(', "query", ':', "http://jabber.org/protocol/disco#items", ')', NULL); /* Send a simple ACK */ expected = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, "romeo@example.net", "juliet@example.com", '@', "id", "one", NULL); reply = wocky_stanza_build_iq_result (iq, NULL); g_assert (reply != NULL); test_assert_stanzas_equal (reply, expected); g_object_unref (reply); g_object_unref (expected); g_object_unref (iq); } static void test_build_iq_result_complex_reply (void) { WockyStanza *iq, *reply, *expected; iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", '@', "id", "one", '(', "query", ':', "http://jabber.org/protocol/disco#items", ')', NULL); /* Send a more complex reply */ expected = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, "romeo@example.net", "juliet@example.com", '@', "id", "one", '(', "query", ':', "http://jabber.org/protocol/disco#items", '(', "item", '@', "jid", "streamhostproxy.example.net", '@', "name", "Bytestreams Proxy", ')', ')', NULL); reply = wocky_stanza_build_iq_result (iq, '(', "query", ':', "http://jabber.org/protocol/disco#items", '(', "item", '@', "jid", "streamhostproxy.example.net", '@', "name", "Bytestreams Proxy", ')', ')', NULL); g_assert (reply != NULL); test_assert_stanzas_equal (reply, expected); g_object_unref (reply); g_object_unref (expected); g_object_unref (iq); } static void test_build_iq_result_no_to_attr (void) { WockyStanza *iq, *reply, *expected; /* Send a reply to an IQ with no "to" attribute. */ iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", NULL, '@', "id", "one", '(', "query", ':', "http://jabber.org/protocol/disco#items", ')', NULL); /* Send a simple ACK */ expected = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, "juliet@example.com", '@', "id", "one", NULL); reply = wocky_stanza_build_iq_result (iq, NULL); g_assert (reply != NULL); test_assert_stanzas_equal (reply, expected); g_object_unref (reply); g_object_unref (expected); g_object_unref (iq); } static void test_build_iq_error_simple_error (void) { WockyStanza *iq, *reply, *expected; iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", '@', "id", "one", '(', "query", ':', "http://jabber.org/protocol/disco#items", ')', NULL); /* Send a simple error */ expected = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, "romeo@example.net", "juliet@example.com", '@', "id", "one", '(', "query", ':', "http://jabber.org/protocol/disco#items", ')', NULL); reply = wocky_stanza_build_iq_error (iq, NULL); g_assert (reply != NULL); test_assert_stanzas_equal (reply, expected); g_object_unref (reply); g_object_unref (expected); g_object_unref (iq); } static void test_build_iq_error_complex (void) { WockyStanza *iq, *reply, *expected; iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "juliet@example.com", "romeo@example.net", '@', "id", "one", '(', "query", ':', "http://jabber.org/protocol/disco#items", ')', NULL); /* Send a more complex reply */ expected = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, "romeo@example.net", "juliet@example.com", '@', "id", "one", '(', "query", ':', "http://jabber.org/protocol/disco#items", ')', '(', "error", '@', "code", "403", '@', "type", "auth", ')', NULL); reply = wocky_stanza_build_iq_error (iq, '(', "error", '@', "code", "403", '@', "type", "auth", ')', NULL); g_assert (reply != NULL); test_assert_stanzas_equal (reply, expected); g_object_unref (reply); g_object_unref (expected); g_object_unref (iq); } static void check_error (WockyStanza *stanza, GQuark domain, gint code, const gchar *msg) { GError *error = NULL; g_assert (wocky_stanza_extract_stream_error (stanza, &error)); g_assert_error (error, domain, code); g_assert_cmpstr (error->message, ==, msg); g_error_free (error); } static void test_extract_stanza_error (void) { WockyStanza *stanza; GError *error = NULL; /* Valid stream error without message */ stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_STREAM_ERROR, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, ':', WOCKY_XMPP_NS_STREAM, '(', "conflict", ':', WOCKY_XMPP_NS_STREAMS, ')', NULL); check_error (stanza, WOCKY_XMPP_STREAM_ERROR, WOCKY_XMPP_STREAM_ERROR_CONFLICT, ""); g_object_unref (stanza); /* Valid stream error with message */ stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_STREAM_ERROR, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, ':', WOCKY_XMPP_NS_STREAM, '(', "system-shutdown", ':', WOCKY_XMPP_NS_STREAMS, ')', '(', "text", ':', WOCKY_XMPP_NS_STREAMS, '$', "bye bye", ')', NULL); check_error (stanza, WOCKY_XMPP_STREAM_ERROR, WOCKY_XMPP_STREAM_ERROR_SYSTEM_SHUTDOWN, "bye bye"); g_object_unref (stanza); /* Unknown stream error */ stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_STREAM_ERROR, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, ':', WOCKY_XMPP_NS_STREAM, '(', "badger", ':', WOCKY_XMPP_NS_STREAMS, ')', NULL); check_error (stanza, WOCKY_XMPP_STREAM_ERROR, WOCKY_XMPP_STREAM_ERROR_UNKNOWN, ""); g_object_unref (stanza); /* Not an error */ stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, ':', WOCKY_XMPP_NS_STREAM, NULL); g_assert (!wocky_stanza_extract_stream_error (stanza, &error)); g_assert_no_error (error); g_object_unref (stanza); } static void test_extract_errors_not_error (void) { WockyStanza *stanza; WockyXmppErrorType type; GError *core = NULL, *specialized = NULL; WockyNode *specialized_node = NULL; gboolean ret; /* As a prelude, check that it does the right thing for non-errors. */ stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, "from", "to", '(', "hello-thar", ')', NULL); ret = wocky_stanza_extract_errors (stanza, &type, &core, &specialized, &specialized_node); g_assert (!ret); g_assert_no_error (core); g_assert_no_error (specialized); g_assert (specialized_node == NULL); g_object_unref (stanza); } static void test_extract_errors_without_description (void) { WockyStanza *stanza; WockyXmppErrorType type; GError *core = NULL, *specialized = NULL; WockyNode *specialized_node = NULL; gboolean ret; /* Test a boring error with no description */ stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, "from", "to", '(', "error", '@', "type", "modify", '(', "bad-request", ':', WOCKY_XMPP_NS_STANZAS, ')', ')', NULL); ret = wocky_stanza_extract_errors (stanza, &type, &core, &specialized, &specialized_node); g_assert (ret); g_assert_cmpuint (type, ==, WOCKY_XMPP_ERROR_TYPE_MODIFY); g_assert_error (core, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST); g_assert_cmpstr (core->message, ==, ""); g_clear_error (&core); g_assert_no_error (specialized); g_assert (specialized_node == NULL); g_object_unref (stanza); } static void test_extract_errors_with_text (void) { WockyStanza *stanza; const gchar *description = "I am a sentence."; WockyXmppErrorType type; GError *core = NULL, *specialized = NULL; WockyNode *specialized_node = NULL; /* Now a different error with some text */ stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, "from", "to", '(', "error", '@', "type", "cancel", '(', "item-not-found", ':', WOCKY_XMPP_NS_STANZAS, ')', '(', "text", ':', WOCKY_XMPP_NS_STANZAS, '$', description, ')', ')', NULL); wocky_stanza_extract_errors (stanza, &type, &core, &specialized, &specialized_node); g_assert_cmpuint (type, ==, WOCKY_XMPP_ERROR_TYPE_CANCEL); g_assert_error (core, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_ITEM_NOT_FOUND); g_assert_cmpstr (core->message, ==, description); g_clear_error (&core); g_assert_no_error (specialized); g_assert (specialized_node == NULL); g_object_unref (stanza); } static void test_extract_errors_application_specific_unknown (void) { WockyStanza *stanza; WockyXmppErrorType type; GError *core = NULL, *specialized = NULL; WockyNode *specialized_node = NULL; /* Another error, with an application-specific element we don't understand */ stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, "from", "to", '(', "error", '@', "type", "cancel", '(', "subscription-required", ':', WOCKY_XMPP_NS_STANZAS, ')', '(', "buy-a-private-cloud", ':', "http://example.com/angry-cloud", ')', ')', NULL); wocky_stanza_extract_errors (stanza, &type, &core, &specialized, &specialized_node); g_assert_cmpuint (type, ==, WOCKY_XMPP_ERROR_TYPE_CANCEL); g_assert_error (core, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_SUBSCRIPTION_REQUIRED); g_assert_cmpstr (core->message, ==, ""); g_clear_error (&core); g_assert_no_error (specialized); /* The namespace is not registered, @specialized is not set. However we * assume that any other namespace element is a specialized error, and it * should get returned in @specialized_node */ g_assert (specialized_node); g_assert_cmpstr (specialized_node->name, ==, "buy-a-private-cloud"); g_assert_cmpstr (wocky_node_get_ns (specialized_node), ==, "http://example.com/angry-cloud"); g_object_unref (stanza); } static void test_extract_errors_jingle_error (void) { WockyStanza *stanza; const gchar *description = "I am a sentence."; WockyXmppErrorType type; GError *core = NULL, *specialized = NULL; WockyNode *specialized_node = NULL; /* A Jingle error! With the child nodes in an erratic order */ stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, "from", "to", '(', "error", '@', "type", "cancel", '(', "tie-break", ':', WOCKY_XMPP_NS_JINGLE_ERRORS, ')', '(', "text", ':', WOCKY_XMPP_NS_STANZAS, '$', description, ')', '(', "conflict", ':', WOCKY_XMPP_NS_STANZAS, ')', ')', NULL); wocky_stanza_extract_errors (stanza, &type, &core, &specialized, &specialized_node); g_assert_cmpuint (type, ==, WOCKY_XMPP_ERROR_TYPE_CANCEL); g_assert_error (core, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_CONFLICT); g_assert_cmpstr (core->message, ==, description); g_clear_error (&core); g_assert_error (specialized, WOCKY_JINGLE_ERROR, WOCKY_JINGLE_ERROR_TIE_BREAK); g_assert_cmpstr (specialized->message, ==, description); g_clear_error (&specialized); g_assert (specialized_node != NULL); g_assert_cmpstr (specialized_node->name, ==, "tie-break"); /* With the same stanza, let's try ignoring all out params: */ wocky_stanza_extract_errors (stanza, NULL, NULL, NULL, NULL); g_object_unref (stanza); } static void test_extract_errors_extra_application_specific (void) { WockyStanza *stanza; const gchar *description = "I am a sentence."; WockyXmppErrorType type; GError *core = NULL, *specialized = NULL; WockyNode *specialized_node = NULL; /* Jingle error! + Bogus extra app specific error, which should be ignored */ stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, "from", "to", '(', "error", '@', "type", "cancel", '(', "tie-break", ':', WOCKY_XMPP_NS_JINGLE_ERRORS, ')', '(', "out-of-order", ':', WOCKY_XMPP_NS_JINGLE_ERRORS, ')', '(', "text", ':', WOCKY_XMPP_NS_STANZAS, '$', description, ')', '(', "conflict", ':', WOCKY_XMPP_NS_STANZAS, ')', ')', NULL); wocky_stanza_extract_errors (stanza, &type, &core, &specialized, &specialized_node); g_assert_cmpuint (type, ==, WOCKY_XMPP_ERROR_TYPE_CANCEL); g_assert_error (core, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_CONFLICT); g_assert_cmpstr (core->message, ==, description); g_clear_error (&core); g_assert_error (specialized, WOCKY_JINGLE_ERROR, WOCKY_JINGLE_ERROR_TIE_BREAK); g_assert_cmpstr (specialized->message, ==, description); g_clear_error (&specialized); g_assert (specialized_node != NULL); g_assert_cmpstr (specialized_node->name, ==, "tie-break"); g_object_unref (stanza); } static void test_extract_errors_legacy_code (void) { WockyStanza *stanza; WockyXmppErrorType type; GError *core = NULL, *specialized = NULL; WockyNode *specialized_node = NULL; /* How about a legacy error code? */ stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, "from", "to", '(', "error", '@', "code", "408", ')', NULL); wocky_stanza_extract_errors (stanza, &type, &core, &specialized, &specialized_node); /* XEP-0086 §3 says that 408 maps to remote-server-timeout, type=wait */ g_assert_cmpuint (type, ==, WOCKY_XMPP_ERROR_TYPE_WAIT); g_assert_error (core, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_REMOTE_SERVER_TIMEOUT); /* No assertion about the message. As an implementation detail, it's probably * the definition of r-s-t from XMPP Core. */ g_clear_error (&core); g_assert_no_error (specialized); g_assert (specialized_node == NULL); g_object_unref (stanza); } static void test_extract_errors_unrecognised_condition (void) { WockyNodeTree *error_tree; WockyXmppErrorType type; GError *core = NULL, *specialized = NULL; WockyNode *specialized_node = NULL; const gchar *text = "The room is currently overactive, please try again later"; /* I got a error back from prosody with type='wait', but * Wocky didn't know about policy-violation (which was introduced in * RFC6120). Not only did it ignore , it also ignored * type='wait' and returned the default, WOCKY_XMPP_ERROR_TYPE_CANCEL. */ g_test_bug ("43166#c9"); error_tree = wocky_node_tree_new ("error", WOCKY_XMPP_NS_JABBER_CLIENT, '@', "type", "wait", '(', "typo-violation", ':', WOCKY_XMPP_NS_STANZAS, ')', '(', "text", ':', WOCKY_XMPP_NS_STANZAS, '$', text, ')', NULL); wocky_xmpp_error_extract (wocky_node_tree_get_top_node (error_tree), &type, &core, &specialized, &specialized_node); g_assert_cmpuint (type, ==, WOCKY_XMPP_ERROR_TYPE_WAIT); /* Wocky should default to undefined-condition when the server returns an * unknown core error element. */ g_assert_error (core, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_UNDEFINED_CONDITION); g_assert_cmpstr (core->message, ==, text); g_clear_error (&core); /* The unrecognised error element was in the :xmpp-stanzas namespace, so it * shouldn't be returned as a specialized error. */ g_assert_no_error (specialized); g_assert (specialized_node == NULL); g_object_unref (error_tree); } static void test_extract_errors_no_sense (void) { WockyStanza *stanza; WockyXmppErrorType type; GError *core = NULL, *specialized = NULL; WockyNode *specialized_node = NULL; /* An error that makes no sense */ stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, "from", "to", '(', "error", '@', "aoeu", "snth", '(', "hoobily-lala-whee", ')', '(', "møøse", ':', WOCKY_XMPP_NS_STANZAS, ')', ')', NULL); wocky_stanza_extract_errors (stanza, &type, &core, &specialized, &specialized_node); /* 'cancel' is the most sensible default if we have no idea. */ g_assert_cmpuint (type, ==, WOCKY_XMPP_ERROR_TYPE_CANCEL); g_assert_error (core, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_UNDEFINED_CONDITION); g_clear_error (&core); g_assert_no_error (specialized); g_assert (specialized_node != NULL); g_assert_cmpstr (specialized_node->name, ==, "hoobily-lala-whee"); g_object_unref (stanza); } static void test_extract_errors_not_really (void) { WockyStanza *stanza; WockyXmppErrorType type; GError *core = NULL, *specialized = NULL; WockyNode *specialized_node = NULL; /* And finally, a stanza with type='error' but no at all... */ stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, "from", "to", NULL); wocky_stanza_extract_errors (stanza, &type, &core, &specialized, &specialized_node); /* 'cancel' is the most sensible default if we have no idea. */ g_assert_cmpuint (type, ==, WOCKY_XMPP_ERROR_TYPE_CANCEL); g_assert_error (core, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_UNDEFINED_CONDITION); g_clear_error (&core); g_assert_no_error (specialized); g_assert (specialized_node == NULL); g_object_unref (stanza); } #define assert_cmperr(e1, e2) \ G_STMT_START { \ g_assert_error (e1, e2->domain, e2->code); \ g_assert_cmpstr (e1->message, ==, e2->message); \ } G_STMT_END static void test_stanza_error_to_node_core (void) { GError *e = NULL; GError *core = NULL, *specialized = NULL; const gchar *description = "bzzzt"; WockyStanza *stanza, *expected; /* An XMPP Core stanza error */ g_set_error_literal (&e, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_REMOTE_SERVER_TIMEOUT, description); stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, "from", "to", NULL); wocky_stanza_error_to_node (e, wocky_stanza_get_top_node (stanza)); expected = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, "from", "to", '(', "error", '@', "type", "wait", '@', "code", "504", /* Per XEP-0086 */ '(', "remote-server-timeout", ':', WOCKY_XMPP_NS_STANZAS, ')', '(', "text", ':', WOCKY_XMPP_NS_STANZAS, '$', description, ')', ')', NULL); test_assert_stanzas_equal (stanza, expected); /* Let's see how it roundtrips: */ wocky_stanza_extract_errors (stanza, NULL, &core, &specialized, NULL); assert_cmperr (e, core); g_assert_no_error (specialized); g_object_unref (stanza); g_object_unref (expected); g_clear_error (&e); g_clear_error (&core); } static void test_stanza_error_to_node_jingle (void) { GError *e = NULL; GError *core = NULL, *specialized = NULL; const gchar *description = "bzzzt"; WockyStanza *stanza, *expected; /* How about a nice game of Jingle? */ g_set_error_literal (&e, WOCKY_JINGLE_ERROR, WOCKY_JINGLE_ERROR_UNKNOWN_SESSION, description); stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, "from", "to", NULL); wocky_stanza_error_to_node (e, wocky_stanza_get_top_node (stanza)); expected = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_ERROR, "from", "to", '(', "error", '@', "type", "cancel", '@', "code", "404", /* Per XEP-0086 */ '(', "item-not-found", ':', WOCKY_XMPP_NS_STANZAS, ')', '(', "unknown-session", ':', WOCKY_XMPP_NS_JINGLE_ERRORS, ')', '(', "text", ':', WOCKY_XMPP_NS_STANZAS, '$', description, ')', ')', NULL); test_assert_stanzas_equal (stanza, expected); /* Let's see how it roundtrips: */ wocky_stanza_extract_errors (stanza, NULL, &core, &specialized, NULL); g_assert_error (core, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_ITEM_NOT_FOUND); assert_cmperr (e, specialized); g_object_unref (stanza); g_object_unref (expected); g_clear_error (&e); g_clear_error (&core); g_clear_error (&specialized); } static void test_unknown ( gconstpointer name_null_ns) { const gchar *name = name_null_ns; const gchar *ns = name + strlen (name) + 1; WockyStanza *stanza = wocky_stanza_new (name, ns); WockyStanzaType type; wocky_stanza_get_type_info (stanza, &type, NULL); g_assert_cmpuint (type, ==, WOCKY_STANZA_TYPE_UNKNOWN); g_object_unref (stanza); } int main (int argc, char **argv) { int result; test_init (argc, argv); g_test_add_func ("/xmpp-stanza/copy", test_copy); g_test_add_func ("/xmpp-stanza/iq-result/build-simple-ack", test_build_iq_result_simple_ack); g_test_add_func ("/xmpp-stanza/iq-result/build-complex-reply", test_build_iq_result_complex_reply); g_test_add_func ("/xmpp-stanza/iq-result/build-no-to-attr", test_build_iq_result_no_to_attr); g_test_add_func ("/xmpp-stanza/errors/build-simple", test_build_iq_error_simple_error); g_test_add_func ("/xmpp-stanza/errors/build-complex", test_build_iq_error_complex); g_test_add_func ("/xmpp-stanza/errors/extract-stanza", test_extract_stanza_error); g_test_add_func ("/xmpp-stanza/errors/not-error", test_extract_errors_not_error); g_test_add_func ("/xmpp-stanza/errors/without-description", test_extract_errors_without_description); g_test_add_func ("/xmpp-stanza/errors/with-text", test_extract_errors_with_text); g_test_add_func ("/xmpp-stanza/errors/application-specific-unknown", test_extract_errors_application_specific_unknown); g_test_add_func ("/xmpp-stanza/errors/jingle-error", test_extract_errors_jingle_error); g_test_add_func ("/xmpp-stanza/errors/extra-application-specific", test_extract_errors_extra_application_specific); g_test_add_func ("/xmpp-stanza/errors/legacy-code", test_extract_errors_legacy_code); g_test_add_func ("/xmpp-stanza/errors/unrecognised-condition", test_extract_errors_unrecognised_condition); g_test_add_func ("/xmpp-stanza/errors/no-sense", test_extract_errors_no_sense); g_test_add_func ("/xmpp-stanza/errors/not-really", test_extract_errors_not_really); g_test_add_func ("/xmpp-stanza/errors/stanza-to-node", test_stanza_error_to_node_core); g_test_add_func ("/xmpp-stanza/errors/stanza-to-node-jingle", test_stanza_error_to_node_jingle); g_test_add_data_func ("/xmpp-stanza/types/unknown-stanza-type", "this-will-never-be-real\0" WOCKY_XMPP_NS_JABBER_CLIENT, test_unknown); g_test_add_data_func ("/xmpp-stanza/types/wrong-namespaces", "challenge\0this:is:not:the:sasl:namespace", test_unknown); result = g_test_run (); test_deinit (); return result; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/gabble.supp0000644000175000017500000000702211544576223024177 0ustar00cassidycassidy00000000000000# Gabble leaks { we leak one default resource hash per process Memcheck:Leak ... fun:g_compute_checksum_for_data fun:sha1_hex fun:gabble_connection_constructed } { Test resolver leaks the records that were added Memcheck:Leak ... fun:test_resolver_add_A } # Glib type registration one-time leaks { g_type_init_with_debug_flags leaks one-time per registered type Memcheck:Leak ... fun:g_type_init_with_debug_flags } { g_type_register_fundamental, same story Memcheck:Leak ... fun:g_type_register_fundamental } { Various mixins set type qdata, types stay alive Memcheck:Leak ... fun:g_type_set_qdata } { Information about static interface lives forever Memcheck:Leak ... fun:g_type_add_interface_static } { Type prerequisites Memcheck:Leak ... fun:g_type_interface_add_prerequisite } { Various memory is never freed when first initializing a type class Memcheck:Leak ... fun:g_type_class_ref } # Glib mainloop one time leaks { Default main context stays alive an keeps an array around for pending fds Memcheck:Leak fun:malloc fun:g_malloc fun:g_main_context_iterate } { Default main context stays alive an keeps an array for pending dispatches Memcheck:Leak ... fun:g_ptr_array_add fun:g_main_context_check fun:g_main_context_iterate } { Global hashtable of signal handlers, memory allocated when resized Memcheck:Leak fun:calloc fun:g_malloc0 fun:g_hash_table_remove_internal fun:g_signal_handlers_destroy } { g_main_loop_run constructs a GStaticPrivate GMainDispatch Memcheck:Leak ... fun:get_dispatch } # glib one-time initialisaton of various bits { Random seed initialization Memcheck:Leak ... fun:g_rand_new fun:g_random_int_range } { GDataSet has a global hashtable that leaks per process Memcheck:Leak ... fun:g_data_initialize } { GIO has a static mapping to various connection factories Memcheck:Leak ... fun:g_socket_connection_factory_register_type } { GLib has a static copy of the userdir Memcheck:Leak ... fun:g_init_user_config_dir } { Caching of the tmp location Memcheck:Leak ... fun:g_get_any_init_do } { thread init causes g_get_language_name to cache stuff Memcheck:Leak ... fun:g_get_language_names } { Thread initialisation Memcheck:Leak ... fun:g_private_new_posix_impl } { Thread initialisation Memcheck:Leak ... fun:g_thread_init_glib } # telepathy-glib leaks the dbus connection, which causes dbus to have some # stuff around on exit... { the subtree that stores objects is reallocated in _register_g_object Memcheck:Leak ... fun:dbus_g_connection_register_g_object } { As we leak a connection, the corresponding dataslots bookkeeping is leaked Memcheck:Leak ... fun:dbus_realloc fun:_dbus_data_slot_allocator_alloc fun:tp_dbus_daemon_constructor } { As we leak a connection, the corresponding dataslots bookkeeping is leaked Memcheck:Leak ... fun:dbus_realloc fun:_dbus_data_slot_list_set fun:dbus_connection_set_data fun:tp_dbus_daemon_constructor } # dbus-glib type registration one-time leaks { dbus-glib specialized GTypes are permanent Memcheck:Leak ... fun:lookup_or_register_specialized } { dbus-glib object type information leaks Memcheck:Leak ... fun:dbus_g_object_type_install_info } # misc library one-time leaks { global gnutls data Memcheck:Leak ... fun:gnutls_global_init } { selinux, we just don't know Memcheck:Leak fun:malloc fun:getdelim obj:/lib/libselinux.so.1 } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-jid-validation-test.c0000664000175000017500000000344012005516162027212 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "wocky-test-helper.h" static void valid (gconstpointer data) { const gchar *jid = data; g_assert (wocky_decode_jid (jid, NULL, NULL, NULL)); } static void invalid (gconstpointer data) { const gchar *jid = data; g_assert (!wocky_decode_jid (jid, NULL, NULL, NULL)); } int main (int argc, char **argv) { int result; test_init (argc, argv); g_test_add_data_func ("/jid/valid/simple", "foo@bar.com/baz", valid); g_test_add_data_func ("/jid/valid/no-resource", "foo@bar.com", valid); g_test_add_data_func ("/jid/valid/no-node", "bar.com/baz", valid); g_test_add_data_func ("/jid/valid/just-domain", "bar.com", valid); g_test_add_data_func ("/jid/valid/ip", "foo@127.0.0.1", valid); g_test_add_data_func ("/jid/valid/ipv6", "foo@2:0:1cfe:face:b00c::3", valid); g_test_add_data_func ("/jid/valid/russian", "Анна@Каренина.ru", valid); g_test_add_data_func ("/jid/invalid/empty", "", invalid); g_test_add_data_func ("/jid/invalid/just-node", "foo@", invalid); g_test_add_data_func ("/jid/invalid/node-and-resource", "foo@/lol", invalid); g_test_add_data_func ("/jid/invalid/just-resource", "/lol", invalid); g_test_add_data_func ("/jid/invalid/garbage", "(*&$(*)", invalid); g_test_add_data_func ("/jid/invalid/space-domain", "foo bar", invalid); g_test_add_data_func ("/jid/invalid/two-ats", "squid@cat@battle", invalid); #if 0 /* These are improperly accepted. */ g_test_add_data_func ("/jid/invalid/space-node", "i am a@fish", invalid); /* U+00A0 NO-BREAK SPACE is in Table C.1.2, which is forbidden in domains. */ g_test_add_data_func ("/jid/invalid/nbsp-domain", "foo bar", invalid); #endif result = g_test_run (); test_deinit (); return result; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/connector-test-plan.txt0000644000175000017500000001201611544576223026511 0ustar00cassidycassidy00000000000000Tests: Syntactic validity: Invalid JID (empty) → Bad JID error Invalid JID (no domain) → Bad JID error ============================================================================ Connection details: DOMAIN = latter part of JID HOST = specific host provided by user SRV = host + port from SRV record SRV │ Host │ Port │ Expected Attempt: ────┼──────┼──────┼────────────────────────────── 0 │ 0 │ 0 │ connect to DOMAIN + 5222 0 │ 0 │ 1 │ connect to DOMAIN + port 0 │ 1 │ 0 │ connect to HOST + 5222 0 │ 1 │ 1 │ connect to specified HOST+PORT 0 │ ☠ │ 0 │ duff host. die. 0 │ ☠ │ 1 │ duff host. die. 1 │ 0 │ 0 │ connect to SRV 1 │ 0 │ 1 │ connect to DOMAIN + PORT 1 │ 1 │ 0 │ connect to HOST + 5222 1 │ 1 │ 1 │ connect to HOST + PORT 1 │ ☠ │ 0 │ duff host. die. 1 │ ☠ │ 1 │ duff host. die. ☠ │ 0 │ 0 │ duff SRV. die. ☠ │ 0 │ 1 │ connect to DOMAIN + PORT ☠ │ 1 │ 0 │ connect to HOST + 5222 ☠ │ 1 │ 1 │ connect to HOST + port ☠ │ ☠ │ 0 │ duff HOST. die. ☠ │ ☠ │ 1 │ duff HOST. die. ============================================================================ Feature Requirements/Support tests: +TLS = TLS provided by server -TLS = TLS not provided INSEC AUTH = Insecure auth channels permitted TLS PLAIN = Insecure auth over TLS permitted DIGEST = + → digest auth available; - → only PLAIN available Tests flagged with * need to be repeated 4 times, with good auth details, a bad password, a bad user and with both wrong. The rest should fail before we get that far. ────┬────────────┬────────────┬─────────────────┬────────────────────────┐ TLS │ INSEC AUTH │ TLS PLAIN │ Server Features │ Attempted Action(s) │ 0 │ 0 │ x │ -TLS-DIGEST │ auth failure │ 0 │ 0 │ x │ -TLS+DIGEST │ digest auth * │ 0 │ 1 │ x │ -TLS-DIGEST │ plain auth * │ 0 │ 1 │ x │ -TLS+DIGEST │ digest auth * │ ────┼────────────┼────────────┼─────────────────┼────────────────────────┤ 1 │ 0 │ 0 │ -TLS │ TLS neg failure │ 1 │ 0 │ 1 │ -TLS │ TLS neg failure │ 1 │ 1 │ 0 │ -TLS │ TLS neg failure │ 1 │ 1 │ 1 │ -TLS │ TLS neg failure │ ────┼────────────┼────────────┼─────────────────┼────────────────────────┤ 0 │ 0 │ 0 │ +TLS-DIGEST │ TLS auth failure │ 0 │ 0 │ 1 │ +TLS-DIGEST │ TLS plain auth * │ 0 │ 1 │ 0 │ +TLS-DIGEST │ TLS plain auth * │ 0 │ 1 │ 1 │ +TLS-DIGEST │ TLS plain auth * │ 1 │ 0 │ 0 │ +TLS-DIGEST │ TLS auth failure │ 1 │ 0 │ 1 │ +TLS-DIGEST │ TLS plain auth * │ 1 │ 1 │ 0 │ +TLS-DIGEST │ TLS plain auth * │ 1 │ 1 │ 1 │ +TLS-DIGEST │ TLS plain auth * │ ────┼────────────┼────────────┼─────────────────┼────────────────────────┤ 0 │ 0 │ 0 │ +TLS+DIGEST │ TLS digest auth * │ 0 │ 0 │ 1 │ +TLS+DIGEST │ TLS digest auth * │ 0 │ 1 │ 0 │ +TLS+DIGEST │ TLS digest auth * │ 0 │ 1 │ 1 │ +TLS+DIGEST │ TLS digest auth * │ 1 │ 0 │ 0 │ +TLS+DIGEST │ TLS digest auth * │ 1 │ 0 │ 1 │ +TLS+DIGEST │ TLS digest auth * │ 1 │ 1 │ 0 │ +TLS+DIGEST │ TLS digest auth * │ 1 │ 1 │ 0 │ +TLS+DIGEST │ TLS digest auth * │ ────┴────────────┴────────────┴─────────────────┴────────────────────────┘ telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-test-sasl-auth.c0000664000175000017500000002254412005516162026223 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "wocky-test-sasl-auth-server.h" #include "wocky-test-sasl-handler.h" #include "wocky-test-stream.h" #include "wocky-test-helper.h" #include typedef struct { gchar *description; gchar *mech; gboolean allow_plain; GQuark domain; int code; ServerProblem problem; gboolean wrong_username; gboolean wrong_password; const gchar *username; const gchar *password; const gchar *servername; } test_t; GMainLoop *mainloop; GIOStream *xmpp_connection; WockyXmppConnection *conn; WockySaslAuth *sasl = NULL; gboolean authenticated = FALSE; gboolean run_done = FALSE; test_t *current_test = NULL; GError *error = NULL; static void post_auth_recv_stanza (GObject *source, GAsyncResult *result, gpointer user_data) { WockyStanza *stanza; GError *e = NULL; /* ignore all stanza until close */ stanza = wocky_xmpp_connection_recv_stanza_finish ( WOCKY_XMPP_CONNECTION (source), result, &e); if (stanza != NULL) { g_object_unref (stanza); wocky_xmpp_connection_recv_stanza_async ( WOCKY_XMPP_CONNECTION (source), NULL, post_auth_recv_stanza, user_data); } else { g_assert_error (e, WOCKY_XMPP_CONNECTION_ERROR, WOCKY_XMPP_CONNECTION_ERROR_CLOSED); g_error_free (e); run_done = TRUE; g_main_loop_quit (mainloop); } } static void post_auth_close_sent (GObject *source, GAsyncResult *result, gpointer user_data) { g_assert (wocky_xmpp_connection_send_close_finish ( WOCKY_XMPP_CONNECTION (source), result, NULL)); wocky_xmpp_connection_recv_stanza_async (WOCKY_XMPP_CONNECTION (source), NULL, post_auth_recv_stanza, user_data); } static void post_auth_open_received (GObject *source, GAsyncResult *result, gpointer user_data) { g_assert (wocky_xmpp_connection_recv_open_finish ( WOCKY_XMPP_CONNECTION (source), result, NULL, NULL, NULL, NULL, NULL, NULL)); wocky_xmpp_connection_send_close_async (WOCKY_XMPP_CONNECTION (source), NULL, post_auth_close_sent, user_data); } static void post_auth_open_sent (GObject *source, GAsyncResult *result, gpointer user_data) { g_assert (wocky_xmpp_connection_send_open_finish ( WOCKY_XMPP_CONNECTION (source), result, NULL)); wocky_xmpp_connection_recv_open_async (WOCKY_XMPP_CONNECTION (source), NULL, post_auth_open_received, user_data); } static void sasl_auth_finished_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GError *auth_error = NULL; test_t *test = (test_t *) user_data; if (wocky_sasl_auth_authenticate_finish (WOCKY_SASL_AUTH (source), res, &auth_error)) { authenticated = TRUE; wocky_xmpp_connection_reset (conn); wocky_xmpp_connection_send_open_async (conn, test->servername, NULL, "1.0", NULL, NULL, NULL, post_auth_open_sent, NULL); } else { error = auth_error; run_done = TRUE; g_main_loop_quit (mainloop); } } static void feature_stanza_received (GObject *source, GAsyncResult *res, gpointer user_data) { WockyStanza *stanza; WockyAuthHandler *test_handler; WockyAuthRegistry *auth_registry; test_t *test = (test_t *) user_data; stanza = wocky_xmpp_connection_recv_stanza_finish ( WOCKY_XMPP_CONNECTION (source), res, NULL); g_assert (stanza != NULL); g_assert (sasl == NULL); sasl = wocky_sasl_auth_new (test->servername, test->wrong_username ? "wrong" : test->username, test->wrong_password ? "wrong" : test->password, WOCKY_XMPP_CONNECTION (source), NULL); g_object_get (sasl, "auth-registry", &auth_registry, NULL); test_handler = WOCKY_AUTH_HANDLER (wocky_test_sasl_handler_new ()); wocky_auth_registry_add_handler (auth_registry, test_handler); g_object_unref (test_handler); g_object_unref (auth_registry); wocky_sasl_auth_authenticate_async (sasl, stanza, current_test->allow_plain, FALSE, NULL, sasl_auth_finished_cb, test); g_object_unref (stanza); } static void stream_open_received (GObject *source, GAsyncResult *res, gpointer user_data) { g_assert (wocky_xmpp_connection_recv_open_finish ( WOCKY_XMPP_CONNECTION (source), res, NULL, NULL, NULL, NULL, NULL, NULL)); /* Get the features stanza and wait for the connection closing*/ wocky_xmpp_connection_recv_stanza_async (WOCKY_XMPP_CONNECTION (source), NULL, feature_stanza_received, user_data); } static void stream_open_sent (GObject *source, GAsyncResult *res, gpointer user_data) { g_assert (wocky_xmpp_connection_send_open_finish ( WOCKY_XMPP_CONNECTION (source), res, NULL)); wocky_xmpp_connection_recv_open_async (WOCKY_XMPP_CONNECTION (source), NULL, stream_open_received, user_data); } static void run_test (gconstpointer user_data) { TestSaslAuthServer *server; WockyTestStream *stream; test_t *test = (test_t *) user_data; stream = g_object_new (WOCKY_TYPE_TEST_STREAM, NULL); server = test_sasl_auth_server_new (stream->stream0, test->mech, test->username, test->password, test->servername, test->problem, TRUE); authenticated = FALSE; run_done = FALSE; current_test = test; xmpp_connection = stream->stream1; conn = wocky_xmpp_connection_new (xmpp_connection); wocky_xmpp_connection_send_open_async (conn, test->servername, NULL, "1.0", NULL, NULL, NULL, stream_open_sent, test); if (!run_done) { g_main_loop_run (mainloop); } if (sasl != NULL) { g_object_unref (sasl); sasl = NULL; } test_sasl_auth_server_stop (server); g_object_unref (server); g_object_unref (stream); g_object_unref (conn); if (test->domain == 0) { g_assert (authenticated); g_assert_no_error (error); } else { g_assert (!authenticated); g_assert_error (error, test->domain, test->code); } if (error != NULL) g_error_free (error); error = NULL; } #define SUCCESS(desc, mech, allow_plain) \ { desc, mech, allow_plain, 0, 0, SERVER_PROBLEM_NO_PROBLEM, FALSE, FALSE, \ "test", "test123", NULL } #define FAIL(desc, mech, allow_plain, domain, code, problem) \ { desc, mech, allow_plain, domain, code, problem, FALSE, FALSE, \ "test", "test123", NULL } int main (int argc, char **argv) { int result; test_t tests[] = { SUCCESS("/xmpp-sasl/normal-auth", NULL, TRUE), SUCCESS("/xmpp-sasl/no-plain", NULL, FALSE), SUCCESS("/xmpp-sasl/only-plain", "PLAIN", TRUE), SUCCESS("/xmpp-sasl/only-digest-md5", "DIGEST-MD5", TRUE), { "/xmpp-sasl/digest-md5-final-data-in-success", "DIGEST-MD5", TRUE, 0, 0, SERVER_PROBLEM_FINAL_DATA_IN_SUCCESS, FALSE, FALSE, "test", "test123", NULL }, FAIL("/xmpp-sasl/no-supported-mechs", "NONSENSE", TRUE, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NO_SUPPORTED_MECHANISMS, SERVER_PROBLEM_NO_PROBLEM), FAIL("/xmpp-sasl/refuse-plain-only", "PLAIN", FALSE, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NO_SUPPORTED_MECHANISMS, SERVER_PROBLEM_NO_PROBLEM), FAIL("/xmpp-sasl/no-sasl-support", NULL, TRUE, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NOT_SUPPORTED, SERVER_PROBLEM_NO_SASL), { "/xmpp-sasl/wrong-username-plain", "PLAIN", TRUE, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_FAILURE, SERVER_PROBLEM_INVALID_USERNAME, TRUE, FALSE, "test", "test123" }, { "/xmpp-sasl/wrong-username-md5", "DIGEST-MD5", TRUE, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_FAILURE, SERVER_PROBLEM_INVALID_USERNAME, TRUE, FALSE, "test", "test123" }, { "/xmpp-sasl/wrong-password-plain", "PLAIN", TRUE, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_FAILURE, SERVER_PROBLEM_INVALID_PASSWORD, FALSE, TRUE, "test", "test123" }, { "/xmpp-sasl/wrong-password-md5", "DIGEST-MD5", TRUE, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_FAILURE, SERVER_PROBLEM_INVALID_PASSWORD, FALSE, TRUE, "test", "test123" }, /* Redo the MD5-DIGEST test with a username, password and realm that * happens to generate a \0 byte in the md5 hash of * 'username:realm:password'. This used to trigger a bug in the sasl helper * when calculating the A! part of the response MD5-DIGEST hash */ { "/xmpp-sasl/digest-md5-A1-null-byte", "DIGEST-MD5", TRUE, 0, 0, SERVER_PROBLEM_NO_PROBLEM, FALSE, FALSE, "moose", "something", "cass-x200s" }, /* Redo the MD5-DIGEST test with extra whitespace in the challenge */ { "/xmpp-sasl/digest-md5-spaced-challenge", "DIGEST-MD5", FALSE, 0, 0, SERVER_PROBLEM_SPACE_CHALLENGE, FALSE, FALSE, "moose", "something", "cass-x200s" }, /* Redo the MD5-DIGEST test with extra \ escapes in the challenge */ { "/xmpp-sasl/digest-md5-slash-challenge", "DIGEST-MD5", FALSE, 0, 0, SERVER_PROBLEM_SLASH_CHALLENGE, FALSE, FALSE, "moose", "something", "cass-x200s" }, { "/xmpp-sasl/external-handler-fail", "X-TEST", FALSE, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_FAILURE, SERVER_PROBLEM_INVALID_PASSWORD, FALSE, FALSE, "dave", "daisy daisy", "hal" }, { "/xmpp-sasl/external-handler-succeed", "X-TEST", FALSE, 0, 0, SERVER_PROBLEM_NO_PROBLEM, FALSE, FALSE, "ripley", "open sesame", "mother" }, }; test_init (argc, argv); mainloop = g_main_loop_new (NULL, FALSE); for (guint i = 0; i < G_N_ELEMENTS (tests); i++) g_test_add_data_func (tests[i].description, &tests[i], run_test); result = g_test_run (); test_deinit (); return result; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-sasl-utils-test.c0000664000175000017500000001315512212322440026412 0ustar00cassidycassidy00000000000000/* * wocky-sasl-utils-test.c - Test sasl utilities * Copyright (C) 2010 Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include typedef struct { guint8 *key; gsize key_len; guint8 *data; gsize data_len; guint8 *result; } digest_test; /* HMAC-SHA1 test vectors as per RFC 2202 */ /* Test 1 */ guint8 key_sha1_test1[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b }; guint8 result_sha1_test1[] = { 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, 0xf1, 0x46, 0xbe, 0x00 }; /* Test 2 */ guint8 result_sha1_test2[] = { 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74, 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a, 0x7c, 0x79 }; /* Test 3 */ guint8 key_sha1_test3[] = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }; guint8 data_sha1_test3[] = { 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd }; guint8 result_sha1_test3[] = { 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, 0x91, 0xa3, 0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, 0x63, 0xf1, 0x75, 0xd3 }; /* Test 4 */ guint8 key_sha1_test4[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 }; guint8 data_sha1_test4[] = { 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd }; guint8 result_sha1_test4[] = { 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, 0xbc, 0x84, 0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c, 0x2d, 0x72, 0x35, 0xda }; /* Test 5 */ guint8 key_sha1_test5[] = { 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }; guint8 result_sha1_test5[] = { 0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2, 0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04 }; /* Test 6 & 7*/ guint8 key_sha1_test6_7[] = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }; guint8 result_sha1_test6[] = { 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, 0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, 0xed, 0x40, 0x21, 0x12 }; guint8 result_sha1_test7[] = { 0xe8, 0xe9, 0x9d, 0xf, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b, 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x8, 0xbb, 0xff, 0x1a, 0x91 }; digest_test hmac_sha1_tests[] = { { key_sha1_test1, 20, (guint8 *) "Hi There", 8, result_sha1_test1 }, { (guint8 *) "Jefe", 4, (guint8 *) "what do ya want for nothing?", 28, result_sha1_test2 }, { key_sha1_test3, 20, data_sha1_test3, 50, result_sha1_test3 }, { key_sha1_test4, 25, data_sha1_test4, 50, result_sha1_test4 }, { key_sha1_test5, 20, (guint8 *) "Test With Truncation", 20, result_sha1_test5 }, { key_sha1_test6_7, 80, (guint8 *) "Test Using Larger Than Block-Size Key - Hash Key First", 54, result_sha1_test6 }, { key_sha1_test6_7, 80, (guint8 *) "Test Using Larger Than Block-Size Key and Larger" \ " Than One Block-Size Data", 73, result_sha1_test7, }, { NULL, 0, NULL, 0, NULL }, }; static void test_sasl_utils_hmac_sha1 (digest_test *t) { GByteArray *result = sasl_calculate_hmac_sha1 (t->key, t->key_len, t->data, t->data_len); int i; for (i = 0; i < g_checksum_type_get_length (G_CHECKSUM_SHA1); i++) g_assert_cmphex (result->data[i], ==, t->result[i]); g_byte_array_unref (result); } int main (int argc, char **argv) { int i; g_test_init (&argc, &argv, NULL); for (i = 0 ; hmac_sha1_tests[i].key_len > 0 ; i++) { gchar *name = g_strdup_printf ("/sasl-utils/hmac-sha1-%d", i + 1); g_test_add_data_func (name, hmac_sha1_tests + i, (void (*)(const void *)) test_sasl_utils_hmac_sha1); g_free (name); } return g_test_run (); } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-caps-hash-test.c0000664000175000017500000005624612212322440026171 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "wocky-test-helper.h" static gboolean check_hash (WockyStanza *stanza, const gchar *expected) { gchar *hash; hash = wocky_caps_hash_compute_from_node ( wocky_stanza_get_top_node (stanza)); g_assert_cmpstr (hash, ==, expected); g_object_unref (stanza); g_free (hash); return TRUE; } static void test_simple (void) { /* Simple example from XEP-0115 */ WockyStanza *stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_RESULT, NULL, NULL, '(', "identity", '@', "category", "client", '@', "name", "Exodus 0.9.1", '@', "type", "pc", ')', '(', "feature", '@', "var", "http://jabber.org/protocol/disco#info", ')', '(', "feature", '@', "var", "http://jabber.org/protocol/disco#items", ')', '(', "feature", '@', "var", "http://jabber.org/protocol/muc", ')', '(', "feature", '@', "var", "http://jabber.org/protocol/caps", ')', NULL); check_hash (stanza, "QgayPKawpkPSDYmwT/WM94uAlu0="); } static void test_complex (void) { /* Complex example from XEP-0115 */ WockyStanza *stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, NULL, "badger", '(', "identity", '@', "category", "client", '@', "name", "Psi 0.11", '@', "type", "pc", '#', "en", ')', '(', "identity", '@', "category", "client", '@', "name", "Ψ 0.11", '@', "type", "pc", '#', "el", ')', '(', "feature", '@', "var", "http://jabber.org/protocol/disco#info", ')', '(', "feature", '@', "var", "http://jabber.org/protocol/disco#items", ')', '(', "feature", '@', "var", "http://jabber.org/protocol/muc", ')', '(', "feature", '@', "var", "http://jabber.org/protocol/caps", ')', '(', "x", ':', "jabber:x:data", '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '@', "type", "hidden", '(', "value", '$', "urn:xmpp:dataforms:softwareinfo", ')', ')', '(', "field", '@', "var", "ip_version", '(', "value", '$', "ipv4", ')', '(', "value", '$', "ipv6", ')', ')', '(', "field", '@', "var", "os", '(', "value", '$', "Mac", ')', ')', '(', "field", '@', "var", "os_version", '(', "value", '$', "10.5.1", ')', ')', '(', "field", '@', "var", "software", '(', "value", '$', "Psi", ')', ')', '(', "field", '@', "var", "software_version", '(', "value", '$', "0.11", ')', ')', ')', NULL); check_hash (stanza, "q07IKJEyjvHSyhy//CH0CxmKi8w="); } static void test_sorting_simple (void) { WockyStanza *stanza; gchar *one, *two; stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, NULL, "badger", '(', "identity", '@', "category", "client", '@', "name", "Psi 0.11", '@', "type", "pc", '#', "en", ')', '(', "identity", '@', "category", "client", '@', "name", "Ψ 0.11", '@', "type", "pc", '#', "el", ')', NULL); one = wocky_caps_hash_compute_from_node ( wocky_stanza_get_top_node (stanza)); g_object_unref (stanza); stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, NULL, "badger", '(', "identity", '@', "category", "client", '@', "name", "Ψ 0.11", '@', "type", "pc", '#', "el", ')', '(', "identity", '@', "category", "client", '@', "name", "Psi 0.11", '@', "type", "pc", '#', "en", ')', NULL); two = wocky_caps_hash_compute_from_node ( wocky_stanza_get_top_node (stanza)); g_object_unref (stanza); g_assert_cmpstr (one, ==, two); g_free (one); g_free (two); } static void test_sorting_complex (void) { WockyStanza *stanza; gchar *one, *two; stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, NULL, "badger", '(', "identity", '@', "category", "client", '@', "name", "Psi 0.11", '@', "type", "pc", '#', "en", ')', '(', "identity", '@', "category", "client", '@', "name", "Ψ 0.11", '@', "type", "pc", '#', "el", ')', '(', "feature", '@', "var", "http://jabber.org/protocol/disco#info", ')', '(', "feature", '@', "var", "http://jabber.org/protocol/disco#items", ')', '(', "feature", '@', "var", "http://jabber.org/protocol/muc", ')', '(', "feature", '@', "var", "http://jabber.org/protocol/caps", ')', '(', "x", ':', "jabber:x:data", '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '@', "type", "hidden", '(', "value", '$', "urn:xmpp:dataforms:softwareinfo", ')', ')', '(', "field", '@', "var", "ip_version", '(', "value", '$', "ipv4", ')', '(', "value", '$', "ipv6", ')', ')', '(', "field", '@', "var", "os", '(', "value", '$', "Mac", ')', ')', '(', "field", '@', "var", "os_version", '(', "value", '$', "10.5.1", ')', ')', '(', "field", '@', "var", "software", '(', "value", '$', "Psi", ')', ')', '(', "field", '@', "var", "software_version", '(', "value", '$', "0.11", ')', ')', ')', '(', "x", ':', "jabber:x:data", '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '@', "type", "hidden", '(', "value", '$', "urn:xmpp:dataforms:somethingelse", ')', ')', '(', "field", '@', "var", "foo", '(', "value", '$', "bananas", ')', '(', "value", '$', "cheese", ')', ')', '(', "field", '@', "var", "wheeeeee", '(', "value", '$', "I'm on a rollercoster", ')', ')', '(', "field", '@', "var", "loldongz", '@', "type", "boolean", '(', "value", '$', "1", ')', ')', ')', NULL); one = wocky_caps_hash_compute_from_node ( wocky_stanza_get_top_node (stanza)); g_object_unref (stanza); stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, NULL, "badger", '(', "feature", '@', "var", "http://jabber.org/protocol/disco#items", ')', '(', "x", ':', "jabber:x:data", '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '@', "type", "hidden", '(', "value", '$', "urn:xmpp:dataforms:somethingelse", ')', ')', '(', "field", '@', "var", "wheeeeee", '(', "value", '$', "I'm on a rollercoster", ')', ')', '(', "field", '@', "var", "loldongz", '@', "type", "boolean", '(', "value", '$', "1", ')', ')', '(', "field", '@', "var", "foo", '(', "value", '$', "cheese", ')', '(', "value", '$', "bananas", ')', ')', ')', '(', "feature", '@', "var", "http://jabber.org/protocol/muc", ')', '(', "identity", '@', "category", "client", '@', "name", "Ψ 0.11", '@', "type", "pc", '#', "el", ')', '(', "feature", '@', "var", "http://jabber.org/protocol/disco#info", ')', '(', "x", ':', "jabber:x:data", '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '@', "type", "hidden", '(', "value", '$', "urn:xmpp:dataforms:softwareinfo", ')', ')', '(', "field", '@', "var", "software", '(', "value", '$', "Psi", ')', ')', '(', "field", '@', "var", "os", '(', "value", '$', "Mac", ')', ')', '(', "field", '@', "var", "os_version", '(', "value", '$', "10.5.1", ')', ')', '(', "field", '@', "var", "software_version", '(', "value", '$', "0.11", ')', ')', '(', "field", '@', "var", "ip_version", '(', "value", '$', "ipv4", ')', '(', "value", '$', "ipv6", ')', ')', ')', '(', "identity", '@', "category", "client", '@', "name", "Psi 0.11", '@', "type", "pc", '#', "en", ')', '(', "feature", '@', "var", "http://jabber.org/protocol/caps", ')', NULL); two = wocky_caps_hash_compute_from_node ( wocky_stanza_get_top_node (stanza)); g_object_unref (stanza); g_assert_cmpstr (one, ==, two); g_free (one); g_free (two); } static void test_dataforms_invalid (void) { gchar *out; /* this stanza has a bad data form type */ WockyStanza *stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, NULL, "badger", '(', "identity", '@', "category", "client", '@', "name", "Psi 0.11", '@', "type", "pc", '#', "en", ')', '(', "x", ':', "jabber:x:data", '@', "type", "lol", ')', NULL); out = wocky_caps_hash_compute_from_node ( wocky_stanza_get_top_node (stanza)); g_object_unref (stanza); /* should be NULL because of type="lol" */ g_assert (out == NULL); /* now with no FORM_TYPE field but fine otherwise */ stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, NULL, "badger", '(', "identity", '@', "category", "client", '@', "name", "Psi 0.11", '@', "type", "pc", '#', "en", ')', '(', "x", ':', "jabber:x:data", '@', "type", "result", '(', "field", '@', "var", "ip_version", '(', "value", '$', "ipv4", ')', '(', "value", '$', "ipv6", ')', ')', ')', NULL); /* should just be ignoring the invalid data form as XEP-0115 section * "5.4 Processing Method", bullet point 3.6 tells us */ check_hash (stanza, "9LXnSGAOqGkjoewMq7WHTF4wK/U="); /* now with a FORM_TYPE but not type="hidden" */ stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, NULL, "badger", '(', "identity", '@', "category", "client", '@', "name", "Psi 0.11", '@', "type", "pc", '#', "en", ')', '(', "x", ':', "jabber:x:data", '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '(', "value", '$', "urn:xmpp:dataforms:softwareinfo", ')', ')', ')', NULL); /* should just be ignoring the invalid data form as XEP-0115 section * "5.4 Processing Method", bullet point 3.6 tells us */ check_hash (stanza, "9LXnSGAOqGkjoewMq7WHTF4wK/U="); /* now with but fine otherwise; * this will fail because we have everything about the field but the * actual value */ stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, NULL, "badger", '(', "identity", '@', "category", "client", '@', "name", "Psi 0.11", '@', "type", "pc", '#', "en", ')', '(', "x", ':', "jabber:x:data", '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '@', "type", "hidden", '(', "value", '$', "urn:xmpp:dataforms:softwareinfo", ')', ')', '(', "field", '@', "var", "lol_version", '(', "value", ')', ')', ')', NULL); out = wocky_caps_hash_compute_from_node ( wocky_stanza_get_top_node (stanza)); g_object_unref (stanza); g_assert (out == NULL); /* now with but fine otherwise; this will fail * because we have everything about the field but the actual * value */ stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, NULL, "badger", '(', "identity", '@', "category", "client", '@', "name", "Psi 0.11", '@', "type", "pc", '#', "en", ')', '(', "x", ':', "jabber:x:data", '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '@', "type", "hidden", '(', "value", '$', "urn:xmpp:dataforms:softwareinfo", ')', ')', '(', "field", '@', "var", "lol_version", ')', ')', NULL); out = wocky_caps_hash_compute_from_node ( wocky_stanza_get_top_node (stanza)); g_object_unref (stanza); g_assert (out == NULL); /* now with but fine otherwise; the data form parser will * ignore fields with no var='' attribute so this will succeed */ stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, NULL, "badger", '(', "identity", '@', "category", "client", '@', "name", "Psi 0.11", '@', "type", "pc", '#', "en", ')', '(', "x", ':', "jabber:x:data", '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '@', "type", "hidden", '(', "value", '$', "urn:xmpp:dataforms:softwareinfo", ')', ')', '(', "field", ')', ')', NULL); out = wocky_caps_hash_compute_from_node ( wocky_stanza_get_top_node (stanza)); g_object_unref (stanza); g_assert_cmpstr (out, ==, "wMFSetHbIiscGZgVgx4CZMaYIBQ="); g_free (out); } static void test_dataforms_fixed_and_no_var (void) { WockyStanza *stanza; gchar *out; g_test_bug ("61433"); /* with no var='' attribute is legal in data forms in * general, but the hashing algorithm doesn't specify what to do in this * case. We choose to make it fail; previously, we crashed. */ stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, NULL, "badger", '(', "identity", '@', "category", "client", '@', "name", "Psi 0.11", '@', "type", "pc", '#', "en", ')', '(', "x", ':', "jabber:x:data", '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '@', "type", "hidden", '(', "value", '$', "urn:xmpp:dataforms:softwareinfo", ')', ')', '(', "field", '@', "type", "fixed", '(', "value", '$', "trolololol", ')', ')', ')', NULL); out = wocky_caps_hash_compute_from_node ( wocky_stanza_get_top_node (stanza)); g_object_unref (stanza); g_assert_cmpstr (out, ==, NULL); g_free (out); } static void test_dataforms_form_type_wrong_type (void) { WockyStanza *stanza; /* 6. If the response includes an extended service discovery information * form where the FORM_TYPE field is not of type "hidden" or the form * does not include a FORM_TYPE field, ignore the form but continue * processing. * * This form's FORM_TYPE is of type boolean. This used to crash the hashing * code. */ g_test_bug ("61433"); stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, NULL, "badger", '(', "identity", '@', "category", "client", '@', "name", "Psi 0.11", '@', "type", "pc", '#', "en", ')', '(', "x", ':', "jabber:x:data", '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '@', "type", "boolean", '(', "value", '$', "true", ')', ')', ')', NULL); check_hash (stanza, "9LXnSGAOqGkjoewMq7WHTF4wK/U="); } static void test_dataforms_form_type_without_value (void) { WockyStanza *stanza; /* XEP-0115 says: * * 5. If the response includes more than one extended service discovery * information form with the same FORM_TYPE or the FORM_TYPE field * contains more than one element with different XML * character data, consider the entire response to be ill-formed. * 6. If the response includes an extended service discovery information * form where the FORM_TYPE field is not of type "hidden" or the form * does not include a FORM_TYPE field, ignore the form but continue * processing. * * Neither item covers the case where there is a FORM_TYPE field of type * "hidden" with no . I choose to treat it as 5 above. */ g_test_bug ("61433"); stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, NULL, "badger", '(', "identity", '@', "category", "client", '@', "name", "Psi 0.11", '@', "type", "pc", '#', "en", ')', '(', "x", ':', "jabber:x:data", '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '@', "type", "hidden", ')', ')', NULL); check_hash (stanza, NULL); } static void test_dataforms_form_type_two_both_with_no_value (void) { WockyStanza *stanza; /* This ought to be equivalent to test_dataforms_form_type_without_value but * there was a crash in the form-sorting code, which of course doesn't * trigger if there's only one form. */ g_test_bug ("61433"); stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, NULL, "badger", '(', "identity", '@', "category", "client", '@', "name", "Psi 0.11", '@', "type", "pc", '#', "en", ')', '(', "x", ':', "jabber:x:data", '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '@', "type", "hidden", ')', ')', '(', "x", ':', "jabber:x:data", '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '@', "type", "hidden", ')', ')', NULL); check_hash (stanza, NULL); } static void test_dataforms_same_type (void) { gchar *out; /* stanza has two data forms both with the same FORM_TYPE value */ WockyStanza *stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, NULL, "badger", '(', "identity", '@', "category", "client", '@', "name", "Psi 0.11", '@', "type", "pc", '#', "en", ')', '(', "feature", '@', "var", "http://jabber.org/protocol/caps", ')', '(', "x", ':', "jabber:x:data", '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '@', "type", "hidden", '(', "value", '$', "urn:xmpp:dataforms:softwareinfo", ')', ')', '(', "field", '@', "var", "ip_version", '(', "value", '$', "ipv4", ')', '(', "value", '$', "ipv6", ')', ')', '(', "field", '@', "var", "os", '(', "value", '$', "Mac", ')', ')', '(', "field", '@', "var", "os_version", '(', "value", '$', "10.5.1", ')', ')', '(', "field", '@', "var", "software", '(', "value", '$', "Psi", ')', ')', '(', "field", '@', "var", "software_version", '(', "value", '$', "0.11", ')', ')', ')', '(', "x", ':', "jabber:x:data", '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '@', "type", "hidden", '(', "value", '$', "urn:xmpp:dataforms:softwareinfo", ')', ')', '(', "field", '@', "var", "ip_version", '(', "value", '$', "ipv4", ')', '(', "value", '$', "ipv6", ')', ')', '(', "field", '@', "var", "os", '(', "value", '$', "Mac", ')', ')', '(', "field", '@', "var", "os_version", '(', "value", '$', "10.5.1", ')', ')', '(', "field", '@', "var", "software", '(', "value", '$', "Psi", ')', ')', '(', "field", '@', "var", "software_version", '(', "value", '$', "0.11", ')', ')', ')', NULL); out = wocky_caps_hash_compute_from_node ( wocky_stanza_get_top_node (stanza)); g_object_unref (stanza); g_assert (out == NULL); } static void test_dataforms_boolean_values (void) { WockyStanza *stanza; gchar *one, *two; stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, NULL, "badger", '(', "identity", '@', "category", "client", '@', "name", "Ψ 0.11", '@', "type", "pc", '#', "el", ')', '(', "feature", '@', "var", "http://jabber.org/protocol/disco#info", ')', '(', "x", ':', "jabber:x:data", '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '@', "type", "hidden", '(', "value", '$', "urn:xmpp:dataforms:softwareinfo", ')', ')', '(', "field", '@', "var", "software", '@', "type", "boolean", '(', "value", '$', "1", ')', ')', ')', NULL); one = wocky_caps_hash_compute_from_node ( wocky_stanza_get_top_node (stanza)); g_object_unref (stanza); stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, NULL, "badger", '(', "identity", '@', "category", "client", '@', "name", "Ψ 0.11", '@', "type", "pc", '#', "el", ')', '(', "feature", '@', "var", "http://jabber.org/protocol/disco#info", ')', '(', "x", ':', "jabber:x:data", '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '@', "type", "hidden", '(', "value", '$', "urn:xmpp:dataforms:softwareinfo", ')', ')', '(', "field", '@', "var", "software", '@', "type", "boolean", '(', "value", '$', "true", ')', ')', ')', NULL); two = wocky_caps_hash_compute_from_node ( wocky_stanza_get_top_node (stanza)); g_object_unref (stanza); g_assert (one != NULL); g_assert (two != NULL); g_assert_cmpstr (one, !=, two); g_free (one); g_free (two); } int main (int argc, char **argv) { int result; test_init (argc, argv); g_test_add_func ("/caps-hash/simple", test_simple); g_test_add_func ("/caps-hash/complex", test_complex); g_test_add_func ("/caps-hash/sorting/simple", test_sorting_simple); g_test_add_func ("/caps-hash/sorting/complex", test_sorting_complex); g_test_add_func ("/caps-hash/dataforms/invalid", test_dataforms_invalid); g_test_add_func ("/caps-hash/dataforms/invalid/fixed-and-no-var", test_dataforms_fixed_and_no_var); g_test_add_func ("/caps-hash/dataforms/invalid/form_type/wrong-type", test_dataforms_form_type_wrong_type); g_test_add_func ("/caps-hash/dataforms/invalid/form_type/no-value", test_dataforms_form_type_without_value); g_test_add_func ("/caps-hash/dataforms/invalid/form_type/two-both-with-no-value", test_dataforms_form_type_two_both_with_no_value); g_test_add_func ("/caps-hash/dataforms/same-type", test_dataforms_same_type); g_test_add_func ("/caps-hash/dataforms/boolean-values", test_dataforms_boolean_values); result = g_test_run (); test_deinit (); return result; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-xmpp-readwrite-test.c0000664000175000017500000001276712005516162027300 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "wocky-test-helper.h" #define TO "example.net" #define FROM "julliet@example.com" #define XMPP_VERSION "1.0" #define LANG "en" #define DUMMY_NS "urn:wocky:test:blah:blah:blah" static WockyStanza * create_stanza (void) { WockyStanza *stanza; WockyNode *html; WockyNode *head; stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "juliet@example.com", "romeo@example.net", '(', "html", ':', "http://www.w3.org/1999/xhtml", '(', "body", '$', "Art thou not Romeo, and a Montague?", ')', ')', NULL); html = wocky_node_get_child (wocky_stanza_get_top_node (stanza), "html"); head = wocky_node_add_child (html, "head"); wocky_node_set_attribute_ns (head, "rev", "0xbad1dea", DUMMY_NS); return stanza; } static void test_readwrite (void) { WockyXmppReader *reader; WockyXmppWriter *writer; WockyStanza *received = NULL, *sent; const guint8 *data; gsize length; gchar *to, *from, *version, *lang; int i; writer = wocky_xmpp_writer_new (); reader = wocky_xmpp_reader_new (); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_INITIAL); wocky_xmpp_writer_stream_open (writer, TO, FROM, XMPP_VERSION, LANG, NULL, &data, &length); wocky_xmpp_reader_push (reader, data, length); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_OPENED); g_object_get (reader, "to", &to, "from", &from, "version", &version, "lang", &lang, NULL); g_assert (!wocky_strdiff (to, TO)); g_assert (!wocky_strdiff (from, FROM)); g_assert (!wocky_strdiff (version, XMPP_VERSION)); g_assert (!wocky_strdiff (lang, LANG)); g_free (to); g_free (from); g_free (version); g_free (lang); sent = create_stanza (); for (i = 0; i < 3 ; i++) { WockyNode *html; WockyNode *head; const gchar *attr_recv = NULL; const gchar *attr_send = NULL; const gchar *attr_none = NULL; g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_OPENED); wocky_xmpp_writer_write_stanza (writer, sent, &data, &length); wocky_xmpp_reader_push (reader, data, length); received = wocky_xmpp_reader_pop_stanza (reader); g_assert (received != NULL); test_assert_stanzas_equal (sent, received); html = wocky_node_get_child (wocky_stanza_get_top_node (received), "html"); head = wocky_node_get_child (html, "head"); attr_recv = wocky_node_get_attribute_ns (head, "rev", DUMMY_NS); attr_none = wocky_node_get_attribute_ns (head, "rev", DUMMY_NS ":x"); html = wocky_node_get_child (wocky_stanza_get_top_node (sent), "html"); head = wocky_node_get_child (html, "head"); attr_send = wocky_node_get_attribute_ns (head, "rev", DUMMY_NS); g_assert (attr_none == NULL); g_assert (attr_recv != NULL); g_assert (attr_send != NULL); g_assert (!strcmp (attr_send, attr_recv)); g_object_unref (received); /* No more stanzas in the queue */ received = wocky_xmpp_reader_pop_stanza (reader); g_assert (received == NULL); } wocky_xmpp_writer_write_stanza (writer, sent, &data, &length); wocky_xmpp_reader_push (reader, data, length); wocky_xmpp_writer_stream_close (writer, &data, &length); wocky_xmpp_reader_push (reader, data, length); /* Stream state should stay open until we popped the last stanza */ g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_OPENED); received = wocky_xmpp_reader_pop_stanza (reader); g_assert (received != NULL); test_assert_stanzas_equal (sent, received); g_object_unref (received); /* Last stanza pop, stream should be closed */ g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_CLOSED); /* No more stanzas in the queue */ received = wocky_xmpp_reader_pop_stanza (reader); g_assert (received == NULL); g_object_unref (sent); g_object_unref (reader); g_object_unref (writer); } static void test_readwrite_nostream (void) { WockyXmppReader *reader; WockyXmppWriter *writer; WockyStanza *received = NULL, *sent; const guint8 *data; gsize length; int i; writer = wocky_xmpp_writer_new_no_stream (); reader = wocky_xmpp_reader_new_no_stream (); sent = create_stanza (); for (i = 0 ; i < 3 ; i++) { g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_OPENED); wocky_xmpp_writer_write_stanza (writer, sent, &data, &length); wocky_xmpp_reader_push (reader, data, length); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_OPENED); received = wocky_xmpp_reader_pop_stanza (reader); g_assert (received != NULL); test_assert_stanzas_equal (sent, received); g_assert (wocky_xmpp_reader_get_state (reader) == WOCKY_XMPP_READER_STATE_CLOSED); wocky_xmpp_reader_reset (reader); g_object_unref (received); } g_object_unref (sent); g_object_unref (reader); g_object_unref (writer); } int main (int argc, char **argv) { int result; test_init (argc, argv); g_test_add_func ("/xmpp-readwrite/readwrite", test_readwrite); g_test_add_func ("/xmpp-readwrite/readwrite-nostream", test_readwrite_nostream); result = g_test_run (); test_deinit (); return result; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/tp-glib.supp0000644000175000017500000001020111544576223024312 0ustar00cassidycassidy00000000000000# Valgrind error suppression file # ============================= libc ================================== { ld.so initialization + selinux Memcheck:Leak ... fun:_dl_init obj:/lib/ld-*.so } { dlopen initialization, triggered by handle-leak-debug code Memcheck:Leak ... fun:__libc_dlopen_mode fun:init fun:backtrace fun:handle_leak_debug_bt fun:dynamic_ensure_handle fun:tp_handle_ensure } # ============================= GLib ================================== { g_set_prgname copies its argument Memcheck:Leak ... fun:g_set_prgname } { one g_get_charset per child^Wprocess Memcheck:Leak ... fun:g_get_charset } { GQuarks can't be freed Memcheck:Leak ... fun:g_quark_from_static_string } { GQuarks can't be freed Memcheck:Leak ... fun:g_quark_from_string } { interned strings can't be freed Memcheck:Leak ... fun:g_intern_string } { interned strings can't be freed Memcheck:Leak ... fun:g_intern_static_string } { shared global default g_main_context Memcheck:Leak ... fun:g_main_context_new fun:g_main_context_default } { GTest initialization Memcheck:Leak ... fun:g_test_init fun:main } { GTest admin Memcheck:Leak ... fun:g_test_add_vtable } { GTest pseudorandomness Memcheck:Leak ... fun:g_rand_new_with_seed_array fun:test_run_seed ... fun:g_test_run } { GSLice initialization Memcheck:Leak ... fun:g_malloc0 fun:g_slice_init_nomessage fun:g_slice_alloc } # ============================= GObject =============================== { g_type_init Memcheck:Leak ... fun:g_type_init } { g_type_register_static Memcheck:Leak ... fun:g_type_register_static } # ============================= dbus-glib ============================= { dbus-glib, https://bugs.freedesktop.org/show_bug.cgi?id=14125 Memcheck:Addr4 fun:g_hash_table_foreach obj:/usr/lib/libdbus-glib-1.so.2.1.0 fun:g_object_run_dispose } { registering marshallers is permanent Memcheck:Leak ... fun:dbus_g_object_register_marshaller_array fun:dbus_g_object_register_marshaller } { dbus-glib specialized GTypes are permanent Memcheck:Leak ... fun:dbus_g_type_specialized_init } { libdbus shared connection Memcheck:Leak ... fun:dbus_g_bus_get } { dbus-gobject registrations aren't freed unless we fall off the bus Memcheck:Leak ... fun:g_slist_append fun:dbus_g_connection_register_g_object } { DBusGProxy slots aren't freed unless we fall off the bus Memcheck:Leak ... fun:dbus_connection_allocate_data_slot ... fun:dbus_g_proxy_constructor } { error registrations are for life, not just for Christmas Memcheck:Leak ... fun:dbus_g_error_domain_register } # ============================= telepathy-glib ======================== { tp_dbus_daemon_constructor @daemons once per DBusConnection Memcheck:Leak ... fun:g_slice_alloc fun:tp_dbus_daemon_constructor } { tp_proxy_subclass_add_error_mapping refs the enum Memcheck:Leak ... fun:g_type_class_ref fun:tp_proxy_subclass_add_error_mapping } { tp_proxy_or_subclass_hook_on_interface_add never frees its list Memcheck:Leak ... fun:tp_proxy_or_subclass_hook_on_interface_add } { tp_dbus_daemon_constructor filter not freed til we fall off the bus Memcheck:Leak ... fun:dbus_connection_add_filter fun:tp_dbus_daemon_constructor } # ============================= unclassified ========================== { creating param specs in tp_proxy_class_intern_init Memcheck:Leak fun:memalign fun:posix_memalign fun:slab_allocator_alloc_chunk fun:g_slice_alloc fun:g_slice_alloc0 fun:g_type_create_instance fun:g_param_spec_internal fun:g_param_spec_string } { ld.so initialization on glibc 2.9 Memcheck:Cond fun:_dl_relocate_object fun:dl_main fun:_dl_sysdep_start fun:_dl_start obj:/lib/ld-2.9.so } { ld.so initialization on glibc 2.9 Memcheck:Cond fun:strlen fun:_dl_init_paths fun:dl_main fun:_dl_sysdep_start fun:_dl_start obj:/lib/ld-2.9.so } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-node-tree-test.c0000664000175000017500000000501112212322440026164 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "wocky-test-helper.h" static void test_build_simple_tree (void) { WockyNodeTree *tree; WockyNode *n; tree = wocky_node_tree_new ("lions", "animals", '(', "distribution", '$', "Only in kenya", ')', NULL); g_assert (tree != NULL); n = wocky_node_tree_get_top_node (tree); g_assert (n != NULL); g_assert_cmpstr (n->name, ==, "lions"); g_assert_cmpstr (wocky_node_get_ns (n), ==, "animals"); g_assert_cmpint (g_slist_length (n->children), ==, 1); n = wocky_node_get_first_child (n); g_assert (n != NULL); g_assert_cmpstr (n->name, ==, "distribution"); g_assert_cmpstr (wocky_node_get_ns (n), ==, "animals"); g_assert_cmpstr (n->content, ==, "Only in kenya"); g_object_unref (tree); } static void test_tree_from_node (void) { WockyNodeTree *a, *b; a = wocky_node_tree_new ("noms", "foodstocks", '(', "item", '@', "origin", "Italy", '$', "Plum cake", ')', NULL); b = wocky_node_tree_new_from_node (wocky_node_tree_get_top_node (a)); test_assert_nodes_equal (wocky_node_tree_get_top_node (a), wocky_node_tree_get_top_node (b)); g_object_unref (a); g_object_unref (b); } static void test_node_add_tree (void) { WockyNodeTree *origin, *ashes, *destination; WockyNode *ash, *top; WockyNode *ash_copy; origin = wocky_node_tree_new ("Eyjafjallajökull", "urn:wocky:lol:ísland", '(', "æsc", '*', &ash, '@', "type", "vulcanic", '(', "description", '$', "Black and smokey", ')', ')', NULL); ashes = wocky_node_tree_new_from_node (ash); destination = wocky_node_tree_new ("europe", "urn:wocky:lol:noplanesforyou", '*', &top, NULL); ash_copy = wocky_node_add_node_tree (top, ashes); test_assert_nodes_equal (ash_copy, ash); test_assert_nodes_equal ( wocky_node_get_first_child (wocky_node_tree_get_top_node (destination)), wocky_node_get_first_child (wocky_node_tree_get_top_node (origin))); g_object_unref (origin); g_object_unref (ashes); g_object_unref (destination); } int main (int argc, char **argv) { int result; test_init (argc, argv); g_test_add_func ("/xmpp-node-tree/simple-tree", test_build_simple_tree); g_test_add_func ("/xmpp-node-tree/tree-from-node", test_tree_from_node); g_test_add_func ("/xmpp-node-tree/node-add-tree", test_node_add_tree); result = g_test_run (); test_deinit (); return result; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-resource-contact-test.c0000664000175000017500000000620212005516162027573 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "wocky-test-helper.h" static void test_instantiation (void) { WockyBareContact *bare_contact; WockyResourceContact *resource_contact; bare_contact = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "juliet@example.net", NULL); resource_contact = g_object_new (WOCKY_TYPE_RESOURCE_CONTACT, "resource", "Balcony", "bare-contact", bare_contact, NULL); g_assert (WOCKY_IS_RESOURCE_CONTACT (resource_contact)); /* WockyResourceContact is a sub-class of WockyContact */ g_assert (WOCKY_IS_CONTACT (resource_contact)); g_object_unref (resource_contact); resource_contact = wocky_resource_contact_new (bare_contact, "Balcony"); g_assert (WOCKY_IS_RESOURCE_CONTACT (resource_contact)); g_assert (WOCKY_IS_CONTACT (resource_contact)); g_object_unref (resource_contact); g_object_unref (bare_contact); } static void test_get_resource (void) { WockyBareContact *bare_contact; WockyResourceContact *resource_contact; bare_contact = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "juliet@example.net", NULL); resource_contact = wocky_resource_contact_new (bare_contact, "Balcony"); g_assert (!wocky_strdiff ( wocky_resource_contact_get_resource (resource_contact), "Balcony")); g_object_unref (bare_contact); g_object_unref (resource_contact); } static void test_get_bare_contact (void) { WockyBareContact *bare_contact; WockyResourceContact *resource_contact; bare_contact = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", "juliet@example.net", NULL); resource_contact = wocky_resource_contact_new (bare_contact, "Balcony"); g_assert (wocky_resource_contact_get_bare_contact (resource_contact) == bare_contact); g_object_unref (bare_contact); g_object_unref (resource_contact); } static void test_equal (void) { WockyBareContact *a, *b; WockyResourceContact *a_1, *a_2, *b_1; a = wocky_bare_contact_new ("a@example.net"); a_1 = wocky_resource_contact_new (a, "Resource1"); g_assert (wocky_resource_contact_equal (a_1, a_1)); g_assert (!wocky_resource_contact_equal (a_1, NULL)); g_assert (!wocky_resource_contact_equal (NULL, a_1)); a_2 = wocky_resource_contact_new (a, "Resource2"); g_assert (!wocky_resource_contact_equal (a_1, a_2)); b = wocky_bare_contact_new ("b@example.net"); b_1 = wocky_resource_contact_new (b, "Resource1"); g_assert (!wocky_resource_contact_equal (b_1, a_1)); g_assert (!wocky_resource_contact_equal (b_1, a_2)); g_object_unref (a); g_object_unref (b); g_object_unref (a_1); g_object_unref (a_2); g_object_unref (b_1); } int main (int argc, char **argv) { int result; test_init (argc, argv); g_test_add_func ("/resource-contact/instantiation", test_instantiation); g_test_add_func ("/resource-contact/get-resource", test_get_resource); g_test_add_func ("/resource-contact/get-bare-contact", test_get_bare_contact); g_test_add_func ("/resource-contact/equal", test_equal); result = g_test_run (); test_deinit (); return result; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/Makefile.in0000664000175000017500000030501712332443664024124 0ustar00cassidycassidy00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ noinst_PROGRAMS = $(am__EXEEXT_4) $(am__EXEEXT_3) @HAVE_LIBSASL2_TRUE@am__append_1 = wocky-test-sasl-auth @HAVE_LIBSASL2_TRUE@am__append_2 = wocky-dummy-xmpp-server @HAVE_GIO_PROXY_TRUE@am__append_3 = wocky-http-proxy-test check_PROGRAMS = $(am__EXEEXT_3) DIST_COMMON = $(top_srcdir)/tools/check-coding-style.mk \ $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp README subdir = tests ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/as-compiler-flag.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/tp-compiler-flag.m4 \ $(top_srcdir)/m4/tp-compiler-warnings.m4 \ $(top_srcdir)/m4/wocky-gcov.m4 $(top_srcdir)/m4/wocky-lcov.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = @HAVE_LIBSASL2_TRUE@am__EXEEXT_1 = wocky-test-sasl-auth$(EXEEXT) @HAVE_GIO_PROXY_TRUE@am__EXEEXT_2 = wocky-http-proxy-test$(EXEEXT) am__EXEEXT_3 = wocky-bare-contact-test$(EXEEXT) \ wocky-caps-hash-test$(EXEEXT) wocky-connector-test$(EXEEXT) \ wocky-contact-factory-test$(EXEEXT) \ wocky-data-form-test$(EXEEXT) \ wocky-jid-validation-test$(EXEEXT) \ wocky-loopback-test$(EXEEXT) wocky-node-tree-test$(EXEEXT) \ wocky-pep-service-test$(EXEEXT) wocky-ping-test$(EXEEXT) \ wocky-porter-test$(EXEEXT) wocky-pubsub-node-test$(EXEEXT) \ wocky-pubsub-service-test$(EXEEXT) \ wocky-resource-contact-test$(EXEEXT) \ wocky-roster-test$(EXEEXT) wocky-sasl-utils-test$(EXEEXT) \ wocky-scram-sha1-test$(EXEEXT) wocky-session-test$(EXEEXT) \ wocky-stanza-test$(EXEEXT) wocky-tls-test$(EXEEXT) \ wocky-utils-test$(EXEEXT) wocky-xmpp-connection-test$(EXEEXT) \ wocky-xmpp-node-test$(EXEEXT) wocky-xmpp-reader-test$(EXEEXT) \ wocky-xmpp-readwrite-test$(EXEEXT) $(am__EXEEXT_1) \ $(am__EXEEXT_2) @HAVE_LIBSASL2_TRUE@am__EXEEXT_4 = wocky-dummy-xmpp-server$(EXEEXT) PROGRAMS = $(noinst_PROGRAMS) am_wocky_bare_contact_test_OBJECTS = wocky-test-helper.$(OBJEXT) \ wocky-test-stream.$(OBJEXT) wocky-bare-contact-test.$(OBJEXT) wocky_bare_contact_test_OBJECTS = \ $(am_wocky_bare_contact_test_OBJECTS) wocky_bare_contact_test_LDADD = $(LDADD) wocky_bare_contact_test_DEPENDENCIES = \ $(top_builddir)/wocky/libwocky.la AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am_wocky_caps_hash_test_OBJECTS = wocky-caps-hash-test.$(OBJEXT) \ wocky-test-helper.$(OBJEXT) wocky-test-stream.$(OBJEXT) wocky_caps_hash_test_OBJECTS = $(am_wocky_caps_hash_test_OBJECTS) wocky_caps_hash_test_LDADD = $(LDADD) wocky_caps_hash_test_DEPENDENCIES = $(top_builddir)/wocky/libwocky.la am_wocky_connector_test_OBJECTS = \ wocky_connector_test-wocky-connector-test.$(OBJEXT) \ wocky_connector_test-wocky-test-sasl-auth-server.$(OBJEXT) \ wocky_connector_test-wocky-test-connector-server.$(OBJEXT) \ wocky_connector_test-wocky-test-helper.$(OBJEXT) \ wocky_connector_test-wocky-test-stream.$(OBJEXT) \ wocky_connector_test-test-resolver.$(OBJEXT) wocky_connector_test_OBJECTS = $(am_wocky_connector_test_OBJECTS) wocky_connector_test_DEPENDENCIES = $(LDADD) wocky_connector_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(wocky_connector_test_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_wocky_contact_factory_test_OBJECTS = wocky-test-helper.$(OBJEXT) \ wocky-test-stream.$(OBJEXT) \ wocky-contact-factory-test.$(OBJEXT) wocky_contact_factory_test_OBJECTS = \ $(am_wocky_contact_factory_test_OBJECTS) wocky_contact_factory_test_LDADD = $(LDADD) wocky_contact_factory_test_DEPENDENCIES = \ $(top_builddir)/wocky/libwocky.la am_wocky_data_form_test_OBJECTS = wocky-test-helper.$(OBJEXT) \ wocky-test-stream.$(OBJEXT) wocky-data-form-test.$(OBJEXT) wocky_data_form_test_OBJECTS = $(am_wocky_data_form_test_OBJECTS) wocky_data_form_test_LDADD = $(LDADD) wocky_data_form_test_DEPENDENCIES = $(top_builddir)/wocky/libwocky.la am_wocky_dummy_xmpp_server_OBJECTS = \ wocky_dummy_xmpp_server-wocky-dummy-xmpp-server.$(OBJEXT) \ wocky_dummy_xmpp_server-wocky-test-connector-server.$(OBJEXT) \ wocky_dummy_xmpp_server-wocky-test-helper.$(OBJEXT) \ wocky_dummy_xmpp_server-wocky-test-stream.$(OBJEXT) \ wocky_dummy_xmpp_server-wocky-test-sasl-auth-server.$(OBJEXT) wocky_dummy_xmpp_server_OBJECTS = \ $(am_wocky_dummy_xmpp_server_OBJECTS) wocky_dummy_xmpp_server_DEPENDENCIES = $(LDADD) wocky_dummy_xmpp_server_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_wocky_http_proxy_test_OBJECTS = wocky-http-proxy-test.$(OBJEXT) \ wocky-test-helper.$(OBJEXT) wocky-test-stream.$(OBJEXT) wocky_http_proxy_test_OBJECTS = $(am_wocky_http_proxy_test_OBJECTS) wocky_http_proxy_test_LDADD = $(LDADD) wocky_http_proxy_test_DEPENDENCIES = \ $(top_builddir)/wocky/libwocky.la am_wocky_jid_validation_test_OBJECTS = \ wocky-jid-validation-test.$(OBJEXT) \ wocky-test-helper.$(OBJEXT) wocky-test-stream.$(OBJEXT) wocky_jid_validation_test_OBJECTS = \ $(am_wocky_jid_validation_test_OBJECTS) wocky_jid_validation_test_LDADD = $(LDADD) wocky_jid_validation_test_DEPENDENCIES = \ $(top_builddir)/wocky/libwocky.la am_wocky_loopback_test_OBJECTS = wocky-test-helper.$(OBJEXT) \ wocky-test-stream.$(OBJEXT) wocky-loopback-test.$(OBJEXT) wocky_loopback_test_OBJECTS = $(am_wocky_loopback_test_OBJECTS) wocky_loopback_test_LDADD = $(LDADD) wocky_loopback_test_DEPENDENCIES = $(top_builddir)/wocky/libwocky.la am_wocky_node_tree_test_OBJECTS = wocky-test-helper.$(OBJEXT) \ wocky-test-stream.$(OBJEXT) wocky-node-tree-test.$(OBJEXT) wocky_node_tree_test_OBJECTS = $(am_wocky_node_tree_test_OBJECTS) wocky_node_tree_test_LDADD = $(LDADD) wocky_node_tree_test_DEPENDENCIES = $(top_builddir)/wocky/libwocky.la am_wocky_pep_service_test_OBJECTS = wocky-test-helper.$(OBJEXT) \ wocky-test-stream.$(OBJEXT) wocky-pep-service-test.$(OBJEXT) wocky_pep_service_test_OBJECTS = $(am_wocky_pep_service_test_OBJECTS) wocky_pep_service_test_LDADD = $(LDADD) wocky_pep_service_test_DEPENDENCIES = \ $(top_builddir)/wocky/libwocky.la am_wocky_ping_test_OBJECTS = wocky-ping-test.$(OBJEXT) \ wocky-test-helper.$(OBJEXT) wocky-test-stream.$(OBJEXT) wocky_ping_test_OBJECTS = $(am_wocky_ping_test_OBJECTS) wocky_ping_test_LDADD = $(LDADD) wocky_ping_test_DEPENDENCIES = $(top_builddir)/wocky/libwocky.la am_wocky_porter_test_OBJECTS = wocky-porter-test.$(OBJEXT) \ wocky-test-helper.$(OBJEXT) wocky-test-stream.$(OBJEXT) wocky_porter_test_OBJECTS = $(am_wocky_porter_test_OBJECTS) wocky_porter_test_LDADD = $(LDADD) wocky_porter_test_DEPENDENCIES = $(top_builddir)/wocky/libwocky.la am_wocky_pubsub_node_test_OBJECTS = wocky-test-helper.$(OBJEXT) \ wocky-test-stream.$(OBJEXT) \ wocky-pubsub-test-helpers.$(OBJEXT) \ wocky-pubsub-node-test.$(OBJEXT) wocky_pubsub_node_test_OBJECTS = $(am_wocky_pubsub_node_test_OBJECTS) wocky_pubsub_node_test_LDADD = $(LDADD) wocky_pubsub_node_test_DEPENDENCIES = \ $(top_builddir)/wocky/libwocky.la am_wocky_pubsub_service_test_OBJECTS = wocky-test-helper.$(OBJEXT) \ wocky-test-stream.$(OBJEXT) \ wocky-pubsub-test-helpers.$(OBJEXT) \ wocky-pubsub-service-test.$(OBJEXT) wocky_pubsub_service_test_OBJECTS = \ $(am_wocky_pubsub_service_test_OBJECTS) wocky_pubsub_service_test_LDADD = $(LDADD) wocky_pubsub_service_test_DEPENDENCIES = \ $(top_builddir)/wocky/libwocky.la am_wocky_resource_contact_test_OBJECTS = wocky-test-helper.$(OBJEXT) \ wocky-test-stream.$(OBJEXT) \ wocky-resource-contact-test.$(OBJEXT) wocky_resource_contact_test_OBJECTS = \ $(am_wocky_resource_contact_test_OBJECTS) wocky_resource_contact_test_LDADD = $(LDADD) wocky_resource_contact_test_DEPENDENCIES = \ $(top_builddir)/wocky/libwocky.la am_wocky_roster_test_OBJECTS = wocky-roster-test.$(OBJEXT) \ wocky-test-helper.$(OBJEXT) wocky-test-stream.$(OBJEXT) wocky_roster_test_OBJECTS = $(am_wocky_roster_test_OBJECTS) wocky_roster_test_LDADD = $(LDADD) wocky_roster_test_DEPENDENCIES = $(top_builddir)/wocky/libwocky.la am_wocky_sasl_utils_test_OBJECTS = wocky-sasl-utils-test.$(OBJEXT) wocky_sasl_utils_test_OBJECTS = $(am_wocky_sasl_utils_test_OBJECTS) wocky_sasl_utils_test_LDADD = $(LDADD) wocky_sasl_utils_test_DEPENDENCIES = \ $(top_builddir)/wocky/libwocky.la am_wocky_scram_sha1_test_OBJECTS = wocky-scram-sha1-test.$(OBJEXT) \ wocky-test-helper.$(OBJEXT) wocky-test-stream.$(OBJEXT) wocky_scram_sha1_test_OBJECTS = $(am_wocky_scram_sha1_test_OBJECTS) wocky_scram_sha1_test_LDADD = $(LDADD) wocky_scram_sha1_test_DEPENDENCIES = \ $(top_builddir)/wocky/libwocky.la am_wocky_session_test_OBJECTS = wocky-test-helper.$(OBJEXT) \ wocky-test-stream.$(OBJEXT) wocky-session-test.$(OBJEXT) wocky_session_test_OBJECTS = $(am_wocky_session_test_OBJECTS) wocky_session_test_LDADD = $(LDADD) wocky_session_test_DEPENDENCIES = $(top_builddir)/wocky/libwocky.la am_wocky_stanza_test_OBJECTS = wocky-test-helper.$(OBJEXT) \ wocky-test-stream.$(OBJEXT) wocky-stanza-test.$(OBJEXT) wocky_stanza_test_OBJECTS = $(am_wocky_stanza_test_OBJECTS) wocky_stanza_test_LDADD = $(LDADD) wocky_stanza_test_DEPENDENCIES = $(top_builddir)/wocky/libwocky.la am_wocky_test_sasl_auth_OBJECTS = \ wocky_test_sasl_auth-wocky-test-helper.$(OBJEXT) \ wocky_test_sasl_auth-wocky-test-sasl-auth.$(OBJEXT) \ wocky_test_sasl_auth-wocky-test-sasl-handler.$(OBJEXT) \ wocky_test_sasl_auth-wocky-test-sasl-auth-server.$(OBJEXT) \ wocky_test_sasl_auth-wocky-test-stream.$(OBJEXT) wocky_test_sasl_auth_OBJECTS = $(am_wocky_test_sasl_auth_OBJECTS) wocky_test_sasl_auth_DEPENDENCIES = $(LDADD) wocky_test_sasl_auth_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ am_wocky_tls_test_OBJECTS = wocky_tls_test-wocky-tls-test.$(OBJEXT) \ wocky_tls_test-wocky-test-helper.$(OBJEXT) \ wocky_tls_test-wocky-test-stream.$(OBJEXT) wocky_tls_test_OBJECTS = $(am_wocky_tls_test_OBJECTS) wocky_tls_test_LDADD = $(LDADD) wocky_tls_test_DEPENDENCIES = $(top_builddir)/wocky/libwocky.la wocky_tls_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(wocky_tls_test_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o \ $@ am_wocky_utils_test_OBJECTS = wocky-utils-test.$(OBJEXT) wocky_utils_test_OBJECTS = $(am_wocky_utils_test_OBJECTS) wocky_utils_test_LDADD = $(LDADD) wocky_utils_test_DEPENDENCIES = $(top_builddir)/wocky/libwocky.la am_wocky_xmpp_connection_test_OBJECTS = \ wocky-xmpp-connection-test.$(OBJEXT) \ wocky-test-helper.$(OBJEXT) wocky-test-stream.$(OBJEXT) wocky_xmpp_connection_test_OBJECTS = \ $(am_wocky_xmpp_connection_test_OBJECTS) wocky_xmpp_connection_test_LDADD = $(LDADD) wocky_xmpp_connection_test_DEPENDENCIES = \ $(top_builddir)/wocky/libwocky.la am_wocky_xmpp_node_test_OBJECTS = wocky-test-helper.$(OBJEXT) \ wocky-test-stream.$(OBJEXT) wocky-xmpp-node-test.$(OBJEXT) wocky_xmpp_node_test_OBJECTS = $(am_wocky_xmpp_node_test_OBJECTS) wocky_xmpp_node_test_LDADD = $(LDADD) wocky_xmpp_node_test_DEPENDENCIES = $(top_builddir)/wocky/libwocky.la am_wocky_xmpp_reader_test_OBJECTS = wocky-test-helper.$(OBJEXT) \ wocky-test-stream.$(OBJEXT) wocky-xmpp-reader-test.$(OBJEXT) wocky_xmpp_reader_test_OBJECTS = $(am_wocky_xmpp_reader_test_OBJECTS) wocky_xmpp_reader_test_LDADD = $(LDADD) wocky_xmpp_reader_test_DEPENDENCIES = \ $(top_builddir)/wocky/libwocky.la am_wocky_xmpp_readwrite_test_OBJECTS = wocky-test-stream.$(OBJEXT) \ wocky-test-helper.$(OBJEXT) \ wocky-xmpp-readwrite-test.$(OBJEXT) wocky_xmpp_readwrite_test_OBJECTS = \ $(am_wocky_xmpp_readwrite_test_OBJECTS) wocky_xmpp_readwrite_test_LDADD = $(LDADD) wocky_xmpp_readwrite_test_DEPENDENCIES = \ $(top_builddir)/wocky/libwocky.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(wocky_bare_contact_test_SOURCES) \ $(wocky_caps_hash_test_SOURCES) \ $(wocky_connector_test_SOURCES) \ $(wocky_contact_factory_test_SOURCES) \ $(wocky_data_form_test_SOURCES) \ $(wocky_dummy_xmpp_server_SOURCES) \ $(wocky_http_proxy_test_SOURCES) \ $(wocky_jid_validation_test_SOURCES) \ $(wocky_loopback_test_SOURCES) $(wocky_node_tree_test_SOURCES) \ $(wocky_pep_service_test_SOURCES) $(wocky_ping_test_SOURCES) \ $(wocky_porter_test_SOURCES) $(wocky_pubsub_node_test_SOURCES) \ $(wocky_pubsub_service_test_SOURCES) \ $(wocky_resource_contact_test_SOURCES) \ $(wocky_roster_test_SOURCES) $(wocky_sasl_utils_test_SOURCES) \ $(wocky_scram_sha1_test_SOURCES) $(wocky_session_test_SOURCES) \ $(wocky_stanza_test_SOURCES) $(wocky_test_sasl_auth_SOURCES) \ $(wocky_tls_test_SOURCES) $(wocky_utils_test_SOURCES) \ $(wocky_xmpp_connection_test_SOURCES) \ $(wocky_xmpp_node_test_SOURCES) \ $(wocky_xmpp_reader_test_SOURCES) \ $(wocky_xmpp_readwrite_test_SOURCES) DIST_SOURCES = $(wocky_bare_contact_test_SOURCES) \ $(wocky_caps_hash_test_SOURCES) \ $(wocky_connector_test_SOURCES) \ $(wocky_contact_factory_test_SOURCES) \ $(wocky_data_form_test_SOURCES) \ $(wocky_dummy_xmpp_server_SOURCES) \ $(wocky_http_proxy_test_SOURCES) \ $(wocky_jid_validation_test_SOURCES) \ $(wocky_loopback_test_SOURCES) $(wocky_node_tree_test_SOURCES) \ $(wocky_pep_service_test_SOURCES) $(wocky_ping_test_SOURCES) \ $(wocky_porter_test_SOURCES) $(wocky_pubsub_node_test_SOURCES) \ $(wocky_pubsub_service_test_SOURCES) \ $(wocky_resource_contact_test_SOURCES) \ $(wocky_roster_test_SOURCES) $(wocky_sasl_utils_test_SOURCES) \ $(wocky_scram_sha1_test_SOURCES) $(wocky_session_test_SOURCES) \ $(wocky_stanza_test_SOURCES) $(wocky_test_sasl_auth_SOURCES) \ $(wocky_tls_test_SOURCES) $(wocky_utils_test_SOURCES) \ $(wocky_xmpp_connection_test_SOURCES) \ $(wocky_xmpp_node_test_SOURCES) \ $(wocky_xmpp_reader_test_SOURCES) \ $(wocky_xmpp_readwrite_test_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_CODING_STYLE_CHECKS = @ENABLE_CODING_STYLE_CHECKS@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ FFLAGS = @FFLAGS@ FGREP = @FGREP@ GCOV = @GCOV@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_LIBS = @GCOV_LIBS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_FOR_STREAM_CIPHERS_CFLAGS = @GNUTLS_FOR_STREAM_CIPHERS_CFLAGS@ GNUTLS_FOR_STREAM_CIPHERS_LIBS = @GNUTLS_FOR_STREAM_CIPHERS_LIBS@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HEADER_DIR = @HEADER_DIR@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LCOV_PATH = @LCOV_PATH@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBIPHB_CFLAGS = @LIBIPHB_CFLAGS@ LIBIPHB_LIBS = @LIBIPHB_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSASL2_CFLAGS = @LIBSASL2_CFLAGS@ LIBSASL2_LIBS = @LIBSASL2_LIBS@ LIBTOOL = @LIBTOOL@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MOSTLYCLEANFILES = @MOSTLYCLEANFILES@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHARED_SUFFIX = @SHARED_SUFFIX@ SHELL = @SHELL@ SOUP_CFLAGS = @SOUP_CFLAGS@ SOUP_LIBS = @SOUP_LIBS@ SQLITE_CFLAGS = @SQLITE_CFLAGS@ SQLITE_LIBS = @SQLITE_LIBS@ STRIP = @STRIP@ TLS_CFLAGS = @TLS_CFLAGS@ TLS_LIBS = @TLS_LIBS@ VERSION = @VERSION@ WOCKY_CFLAGS = @WOCKY_CFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ have_gcov = @have_gcov@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ############################################################################ # x509 certificates: TEST_DIR := @abs_top_srcdir@/tests SUMMARY := $(TEST_DIR)/summarise-tests.py CERT_DIR := $(TEST_DIR)/certs CA_KEY := $(CERT_DIR)/ca-0-key.pem CA_CERT := $(CERT_DIR)/ca-0-cert.pem SS_KEY := $(CERT_DIR)/ss-key.pem SS_CERT := $(CERT_DIR)/ss-cert.pem REV_KEY := $(CERT_DIR)/rev-key.pem REV_CERT := $(CERT_DIR)/rev-cert.pem EXP_KEY := $(CERT_DIR)/exp-key.pem EXP_CERT := $(CERT_DIR)/exp-cert.pem NEW_KEY := $(CERT_DIR)/new-key.pem NEW_CERT := $(CERT_DIR)/new-cert.pem TLS_KEY := $(CERT_DIR)/tls-key.pem TLS_CERT := $(CERT_DIR)/tls-cert.pem WILD_KEY := $(CERT_DIR)/wild-key.pem WILD_CERT := $(CERT_DIR)/wild-cert.pem BADWILD_KEY := $(CERT_DIR)/badwild-key.pem BADWILD_CERT := $(CERT_DIR)/badwild-cert.pem CA_DIR := $(CERT_DIR)/cas CRL_DIR := $(CERT_DIR)/crl UNKNOWN_KEY := $(CERT_DIR)/unknown-key.pem UNKNOWN_CERT := $(CERT_DIR)/unknown-cert.pem INCLUDES := -I$(top_builddir)/wocky TLSDEFS := -DTLS_CA_KEY_FILE='"$(CA_KEY)"' \ -DTLS_CA_CRT_FILE='"$(CA_CERT)"' \ -DTLS_SS_KEY_FILE='"$(SS_KEY)"' \ -DTLS_SS_CRT_FILE='"$(SS_CERT)"' \ -DTLS_EXP_KEY_FILE='"$(EXP_KEY)"' \ -DTLS_EXP_CRT_FILE='"$(EXP_CERT)"' \ -DTLS_NEW_KEY_FILE='"$(NEW_KEY)"' \ -DTLS_NEW_CRT_FILE='"$(NEW_CERT)"' \ -DTLS_REV_KEY_FILE='"$(REV_KEY)"' \ -DTLS_REV_CRT_FILE='"$(REV_CERT)"' \ -DTLS_UNKNOWN_KEY_FILE='"$(UNKNOWN_KEY)"' \ -DTLS_UNKNOWN_CRT_FILE='"$(UNKNOWN_CERT)"' \ -DTLS_SERVER_KEY_FILE='"$(TLS_KEY)"' \ -DTLS_SERVER_CRT_FILE='"$(TLS_CERT)"'\ -DTLS_WILD_KEY_FILE='"$(WILD_KEY)"' \ -DTLS_WILD_CRT_FILE='"$(WILD_CERT)"' \ -DTLS_BADWILD_CRT_FILE='"$(BADWILD_CERT)"' \ -DTLS_BADWILD_KEY_FILE='"$(BADWILD_KEY)"' \ -DTLS_CRL_DIR='"$(CRL_DIR)"' \ -DTLS_CA_DIR='"$(CA_DIR)"' ############################################################################ TEST_PROGS = wocky-bare-contact-test wocky-caps-hash-test \ wocky-connector-test wocky-contact-factory-test \ wocky-data-form-test wocky-jid-validation-test \ wocky-loopback-test wocky-node-tree-test \ wocky-pep-service-test wocky-ping-test wocky-porter-test \ wocky-pubsub-node-test wocky-pubsub-service-test \ wocky-resource-contact-test wocky-roster-test \ wocky-sasl-utils-test wocky-scram-sha1-test wocky-session-test \ wocky-stanza-test wocky-tls-test wocky-utils-test \ wocky-xmpp-connection-test wocky-xmpp-node-test \ wocky-xmpp-reader-test wocky-xmpp-readwrite-test $(NULL) \ $(am__append_1) $(am__append_3) wocky_bare_contact_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-bare-contact-test.c wocky_caps_hash_test_SOURCES = wocky-caps-hash-test.c \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h EXTRA_wocky_connector_test_DEPENDENCIES = $(CA_DIR) certs wocky_connector_test_SOURCES = \ wocky-connector-test.c \ wocky-test-sasl-auth-server.c \ wocky-test-sasl-auth-server.h \ wocky-test-connector-server.c \ wocky-test-connector-server.h \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ test-resolver.c test-resolver.h wocky_connector_test_LDADD = $(LDADD) @LIBSASL2_LIBS@ wocky_connector_test_CFLAGS = $(AM_CFLAGS) @LIBSASL2_CFLAGS@ $(TLSDEFS) wocky_contact_factory_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-contact-factory-test.c wocky_data_form_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-data-form-test.c wocky_dummy_xmpp_server_SOURCES = wocky-dummy-xmpp-server.c \ wocky-test-connector-server.c wocky-test-connector-server.h \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-test-sasl-auth-server.c wocky-test-sasl-auth-server.h wocky_dummy_xmpp_server_LDADD = $(LDADD) @LIBSASL2_LIBS@ wocky_dummy_xmpp_server_CFLAGS = $(AM_CFLAGS) @LIBSASL2_CFLAGS@ $(TLSDEFS) wocky_http_proxy_test_SOURCES = wocky-http-proxy-test.c \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h wocky_jid_validation_test_SOURCES = \ wocky-jid-validation-test.c \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h wocky_loopback_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-loopback-test.c wocky_node_tree_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-node-tree-test.c wocky_pep_service_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-pep-service-test.c wocky_ping_test_SOURCES = \ wocky-ping-test.c \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h wocky_porter_test_SOURCES = \ wocky-porter-test.c \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h wocky_pubsub_node_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-pubsub-test-helpers.c wocky-pubsub-test-helpers.h \ wocky-pubsub-node-test.c wocky_pubsub_service_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-pubsub-test-helpers.c wocky-pubsub-test-helpers.h \ wocky-pubsub-service-test.c wocky_resource_contact_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-resource-contact-test.c wocky_roster_test_SOURCES = \ wocky-roster-test.c \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h wocky_sasl_utils_test_SOURCES = wocky-sasl-utils-test.c wocky_scram_sha1_test_SOURCES = wocky-scram-sha1-test.c \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h wocky_session_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-session-test.c wocky_stanza_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-stanza-test.c wocky_test_sasl_auth_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-sasl-auth.c \ wocky-test-sasl-handler.c \ wocky-test-sasl-handler.h \ wocky-test-sasl-auth-server.c \ wocky-test-sasl-auth-server.h \ wocky-test-stream.c \ wocky-test-stream.h wocky_test_sasl_auth_LDADD = $(LDADD) @LIBSASL2_LIBS@ wocky_test_sasl_auth_CFLAGS = $(AM_CFLAGS) @LIBSASL2_CFLAGS@ wocky_tls_test_SOURCES = \ wocky-tls-test.c \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h wocky_tls_test_CFLAGS = $(AM_CFLAGS) $(TLSDEFS) wocky_utils_test_SOURCES = wocky-utils-test.c wocky_xmpp_connection_test_SOURCES = \ wocky-xmpp-connection-test.c \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h wocky_xmpp_node_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-xmpp-node-test.c wocky_xmpp_reader_test_SOURCES = \ wocky-test-helper.c wocky-test-helper.h \ wocky-test-stream.c wocky-test-stream.h \ wocky-xmpp-reader-test.c wocky_xmpp_readwrite_test_SOURCES = \ wocky-test-stream.c wocky-test-stream.h \ wocky-test-helper.c wocky-test-helper.h \ wocky-xmpp-readwrite-test.c AM_CFLAGS = $(ERROR_CFLAGS) $(GCOV_CFLAGS) @GLIB_CFLAGS@ \ @LIBXML2_CFLAGS@ @TLS_CFLAGS@ @WOCKY_CFLAGS@ AM_LDFLAGS = $(GCOV_LIBS) @GLIB_LIBS@ @LIBXML2_LIBS@ @TLS_LIBS@ LDADD = $(top_builddir)/wocky/libwocky.la check_c_sources = $(notdir $(wildcard $(srcdir)/*.c) $(wildcard $(srcdir)/*.h)) ############################################################################ SUPPRESSIONS = \ threadlocal.supp \ gabble.supp \ tp-glib.supp CLEANFILES = test-report.xml \ sasl-test.db EXTRA_DIST = $(SUPPRESSIONS) \ README \ connector-test-plan.txt \ summarise-tests.py \ wocky-dummy-xmpp-server.c \ $(wildcard $(srcdir)/certs/*.cfg) \ $(wildcard $(srcdir)/certs/*.pem) \ $(wildcard $(srcdir)/certs/cas/*.pem) \ $(wildcard $(srcdir)/certs/cas/*.0) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/tools/check-coding-style.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu tests/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/tools/check-coding-style.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list wocky-bare-contact-test$(EXEEXT): $(wocky_bare_contact_test_OBJECTS) $(wocky_bare_contact_test_DEPENDENCIES) $(EXTRA_wocky_bare_contact_test_DEPENDENCIES) @rm -f wocky-bare-contact-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_bare_contact_test_OBJECTS) $(wocky_bare_contact_test_LDADD) $(LIBS) wocky-caps-hash-test$(EXEEXT): $(wocky_caps_hash_test_OBJECTS) $(wocky_caps_hash_test_DEPENDENCIES) $(EXTRA_wocky_caps_hash_test_DEPENDENCIES) @rm -f wocky-caps-hash-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_caps_hash_test_OBJECTS) $(wocky_caps_hash_test_LDADD) $(LIBS) wocky-connector-test$(EXEEXT): $(wocky_connector_test_OBJECTS) $(wocky_connector_test_DEPENDENCIES) $(EXTRA_wocky_connector_test_DEPENDENCIES) @rm -f wocky-connector-test$(EXEEXT) $(AM_V_CCLD)$(wocky_connector_test_LINK) $(wocky_connector_test_OBJECTS) $(wocky_connector_test_LDADD) $(LIBS) wocky-contact-factory-test$(EXEEXT): $(wocky_contact_factory_test_OBJECTS) $(wocky_contact_factory_test_DEPENDENCIES) $(EXTRA_wocky_contact_factory_test_DEPENDENCIES) @rm -f wocky-contact-factory-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_contact_factory_test_OBJECTS) $(wocky_contact_factory_test_LDADD) $(LIBS) wocky-data-form-test$(EXEEXT): $(wocky_data_form_test_OBJECTS) $(wocky_data_form_test_DEPENDENCIES) $(EXTRA_wocky_data_form_test_DEPENDENCIES) @rm -f wocky-data-form-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_data_form_test_OBJECTS) $(wocky_data_form_test_LDADD) $(LIBS) wocky-dummy-xmpp-server$(EXEEXT): $(wocky_dummy_xmpp_server_OBJECTS) $(wocky_dummy_xmpp_server_DEPENDENCIES) $(EXTRA_wocky_dummy_xmpp_server_DEPENDENCIES) @rm -f wocky-dummy-xmpp-server$(EXEEXT) $(AM_V_CCLD)$(wocky_dummy_xmpp_server_LINK) $(wocky_dummy_xmpp_server_OBJECTS) $(wocky_dummy_xmpp_server_LDADD) $(LIBS) wocky-http-proxy-test$(EXEEXT): $(wocky_http_proxy_test_OBJECTS) $(wocky_http_proxy_test_DEPENDENCIES) $(EXTRA_wocky_http_proxy_test_DEPENDENCIES) @rm -f wocky-http-proxy-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_http_proxy_test_OBJECTS) $(wocky_http_proxy_test_LDADD) $(LIBS) wocky-jid-validation-test$(EXEEXT): $(wocky_jid_validation_test_OBJECTS) $(wocky_jid_validation_test_DEPENDENCIES) $(EXTRA_wocky_jid_validation_test_DEPENDENCIES) @rm -f wocky-jid-validation-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_jid_validation_test_OBJECTS) $(wocky_jid_validation_test_LDADD) $(LIBS) wocky-loopback-test$(EXEEXT): $(wocky_loopback_test_OBJECTS) $(wocky_loopback_test_DEPENDENCIES) $(EXTRA_wocky_loopback_test_DEPENDENCIES) @rm -f wocky-loopback-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_loopback_test_OBJECTS) $(wocky_loopback_test_LDADD) $(LIBS) wocky-node-tree-test$(EXEEXT): $(wocky_node_tree_test_OBJECTS) $(wocky_node_tree_test_DEPENDENCIES) $(EXTRA_wocky_node_tree_test_DEPENDENCIES) @rm -f wocky-node-tree-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_node_tree_test_OBJECTS) $(wocky_node_tree_test_LDADD) $(LIBS) wocky-pep-service-test$(EXEEXT): $(wocky_pep_service_test_OBJECTS) $(wocky_pep_service_test_DEPENDENCIES) $(EXTRA_wocky_pep_service_test_DEPENDENCIES) @rm -f wocky-pep-service-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_pep_service_test_OBJECTS) $(wocky_pep_service_test_LDADD) $(LIBS) wocky-ping-test$(EXEEXT): $(wocky_ping_test_OBJECTS) $(wocky_ping_test_DEPENDENCIES) $(EXTRA_wocky_ping_test_DEPENDENCIES) @rm -f wocky-ping-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_ping_test_OBJECTS) $(wocky_ping_test_LDADD) $(LIBS) wocky-porter-test$(EXEEXT): $(wocky_porter_test_OBJECTS) $(wocky_porter_test_DEPENDENCIES) $(EXTRA_wocky_porter_test_DEPENDENCIES) @rm -f wocky-porter-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_porter_test_OBJECTS) $(wocky_porter_test_LDADD) $(LIBS) wocky-pubsub-node-test$(EXEEXT): $(wocky_pubsub_node_test_OBJECTS) $(wocky_pubsub_node_test_DEPENDENCIES) $(EXTRA_wocky_pubsub_node_test_DEPENDENCIES) @rm -f wocky-pubsub-node-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_pubsub_node_test_OBJECTS) $(wocky_pubsub_node_test_LDADD) $(LIBS) wocky-pubsub-service-test$(EXEEXT): $(wocky_pubsub_service_test_OBJECTS) $(wocky_pubsub_service_test_DEPENDENCIES) $(EXTRA_wocky_pubsub_service_test_DEPENDENCIES) @rm -f wocky-pubsub-service-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_pubsub_service_test_OBJECTS) $(wocky_pubsub_service_test_LDADD) $(LIBS) wocky-resource-contact-test$(EXEEXT): $(wocky_resource_contact_test_OBJECTS) $(wocky_resource_contact_test_DEPENDENCIES) $(EXTRA_wocky_resource_contact_test_DEPENDENCIES) @rm -f wocky-resource-contact-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_resource_contact_test_OBJECTS) $(wocky_resource_contact_test_LDADD) $(LIBS) wocky-roster-test$(EXEEXT): $(wocky_roster_test_OBJECTS) $(wocky_roster_test_DEPENDENCIES) $(EXTRA_wocky_roster_test_DEPENDENCIES) @rm -f wocky-roster-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_roster_test_OBJECTS) $(wocky_roster_test_LDADD) $(LIBS) wocky-sasl-utils-test$(EXEEXT): $(wocky_sasl_utils_test_OBJECTS) $(wocky_sasl_utils_test_DEPENDENCIES) $(EXTRA_wocky_sasl_utils_test_DEPENDENCIES) @rm -f wocky-sasl-utils-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_sasl_utils_test_OBJECTS) $(wocky_sasl_utils_test_LDADD) $(LIBS) wocky-scram-sha1-test$(EXEEXT): $(wocky_scram_sha1_test_OBJECTS) $(wocky_scram_sha1_test_DEPENDENCIES) $(EXTRA_wocky_scram_sha1_test_DEPENDENCIES) @rm -f wocky-scram-sha1-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_scram_sha1_test_OBJECTS) $(wocky_scram_sha1_test_LDADD) $(LIBS) wocky-session-test$(EXEEXT): $(wocky_session_test_OBJECTS) $(wocky_session_test_DEPENDENCIES) $(EXTRA_wocky_session_test_DEPENDENCIES) @rm -f wocky-session-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_session_test_OBJECTS) $(wocky_session_test_LDADD) $(LIBS) wocky-stanza-test$(EXEEXT): $(wocky_stanza_test_OBJECTS) $(wocky_stanza_test_DEPENDENCIES) $(EXTRA_wocky_stanza_test_DEPENDENCIES) @rm -f wocky-stanza-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_stanza_test_OBJECTS) $(wocky_stanza_test_LDADD) $(LIBS) wocky-test-sasl-auth$(EXEEXT): $(wocky_test_sasl_auth_OBJECTS) $(wocky_test_sasl_auth_DEPENDENCIES) $(EXTRA_wocky_test_sasl_auth_DEPENDENCIES) @rm -f wocky-test-sasl-auth$(EXEEXT) $(AM_V_CCLD)$(wocky_test_sasl_auth_LINK) $(wocky_test_sasl_auth_OBJECTS) $(wocky_test_sasl_auth_LDADD) $(LIBS) wocky-tls-test$(EXEEXT): $(wocky_tls_test_OBJECTS) $(wocky_tls_test_DEPENDENCIES) $(EXTRA_wocky_tls_test_DEPENDENCIES) @rm -f wocky-tls-test$(EXEEXT) $(AM_V_CCLD)$(wocky_tls_test_LINK) $(wocky_tls_test_OBJECTS) $(wocky_tls_test_LDADD) $(LIBS) wocky-utils-test$(EXEEXT): $(wocky_utils_test_OBJECTS) $(wocky_utils_test_DEPENDENCIES) $(EXTRA_wocky_utils_test_DEPENDENCIES) @rm -f wocky-utils-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_utils_test_OBJECTS) $(wocky_utils_test_LDADD) $(LIBS) wocky-xmpp-connection-test$(EXEEXT): $(wocky_xmpp_connection_test_OBJECTS) $(wocky_xmpp_connection_test_DEPENDENCIES) $(EXTRA_wocky_xmpp_connection_test_DEPENDENCIES) @rm -f wocky-xmpp-connection-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_xmpp_connection_test_OBJECTS) $(wocky_xmpp_connection_test_LDADD) $(LIBS) wocky-xmpp-node-test$(EXEEXT): $(wocky_xmpp_node_test_OBJECTS) $(wocky_xmpp_node_test_DEPENDENCIES) $(EXTRA_wocky_xmpp_node_test_DEPENDENCIES) @rm -f wocky-xmpp-node-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_xmpp_node_test_OBJECTS) $(wocky_xmpp_node_test_LDADD) $(LIBS) wocky-xmpp-reader-test$(EXEEXT): $(wocky_xmpp_reader_test_OBJECTS) $(wocky_xmpp_reader_test_DEPENDENCIES) $(EXTRA_wocky_xmpp_reader_test_DEPENDENCIES) @rm -f wocky-xmpp-reader-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_xmpp_reader_test_OBJECTS) $(wocky_xmpp_reader_test_LDADD) $(LIBS) wocky-xmpp-readwrite-test$(EXEEXT): $(wocky_xmpp_readwrite_test_OBJECTS) $(wocky_xmpp_readwrite_test_DEPENDENCIES) $(EXTRA_wocky_xmpp_readwrite_test_DEPENDENCIES) @rm -f wocky-xmpp-readwrite-test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(wocky_xmpp_readwrite_test_OBJECTS) $(wocky_xmpp_readwrite_test_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-bare-contact-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-caps-hash-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-contact-factory-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-data-form-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-http-proxy-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-jid-validation-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-loopback-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-node-tree-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-pep-service-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-ping-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-porter-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-pubsub-node-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-pubsub-service-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-pubsub-test-helpers.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-resource-contact-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-roster-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-sasl-utils-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-scram-sha1-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-session-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-stanza-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-test-helper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-test-stream.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-utils-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-xmpp-connection-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-xmpp-node-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-xmpp-reader-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-xmpp-readwrite-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky_connector_test-test-resolver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky_connector_test-wocky-connector-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky_connector_test-wocky-test-connector-server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky_connector_test-wocky-test-helper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky_connector_test-wocky-test-sasl-auth-server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky_connector_test-wocky-test-stream.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky_dummy_xmpp_server-wocky-dummy-xmpp-server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-connector-server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-helper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-sasl-auth-server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-stream.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky_test_sasl_auth-wocky-test-helper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-auth-server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-auth.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-handler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky_test_sasl_auth-wocky-test-stream.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky_tls_test-wocky-test-helper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky_tls_test-wocky-test-stream.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky_tls_test-wocky-tls-test.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< wocky_connector_test-wocky-connector-test.o: wocky-connector-test.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -MT wocky_connector_test-wocky-connector-test.o -MD -MP -MF $(DEPDIR)/wocky_connector_test-wocky-connector-test.Tpo -c -o wocky_connector_test-wocky-connector-test.o `test -f 'wocky-connector-test.c' || echo '$(srcdir)/'`wocky-connector-test.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_connector_test-wocky-connector-test.Tpo $(DEPDIR)/wocky_connector_test-wocky-connector-test.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-connector-test.c' object='wocky_connector_test-wocky-connector-test.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -c -o wocky_connector_test-wocky-connector-test.o `test -f 'wocky-connector-test.c' || echo '$(srcdir)/'`wocky-connector-test.c wocky_connector_test-wocky-connector-test.obj: wocky-connector-test.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -MT wocky_connector_test-wocky-connector-test.obj -MD -MP -MF $(DEPDIR)/wocky_connector_test-wocky-connector-test.Tpo -c -o wocky_connector_test-wocky-connector-test.obj `if test -f 'wocky-connector-test.c'; then $(CYGPATH_W) 'wocky-connector-test.c'; else $(CYGPATH_W) '$(srcdir)/wocky-connector-test.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_connector_test-wocky-connector-test.Tpo $(DEPDIR)/wocky_connector_test-wocky-connector-test.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-connector-test.c' object='wocky_connector_test-wocky-connector-test.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -c -o wocky_connector_test-wocky-connector-test.obj `if test -f 'wocky-connector-test.c'; then $(CYGPATH_W) 'wocky-connector-test.c'; else $(CYGPATH_W) '$(srcdir)/wocky-connector-test.c'; fi` wocky_connector_test-wocky-test-sasl-auth-server.o: wocky-test-sasl-auth-server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -MT wocky_connector_test-wocky-test-sasl-auth-server.o -MD -MP -MF $(DEPDIR)/wocky_connector_test-wocky-test-sasl-auth-server.Tpo -c -o wocky_connector_test-wocky-test-sasl-auth-server.o `test -f 'wocky-test-sasl-auth-server.c' || echo '$(srcdir)/'`wocky-test-sasl-auth-server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_connector_test-wocky-test-sasl-auth-server.Tpo $(DEPDIR)/wocky_connector_test-wocky-test-sasl-auth-server.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-sasl-auth-server.c' object='wocky_connector_test-wocky-test-sasl-auth-server.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -c -o wocky_connector_test-wocky-test-sasl-auth-server.o `test -f 'wocky-test-sasl-auth-server.c' || echo '$(srcdir)/'`wocky-test-sasl-auth-server.c wocky_connector_test-wocky-test-sasl-auth-server.obj: wocky-test-sasl-auth-server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -MT wocky_connector_test-wocky-test-sasl-auth-server.obj -MD -MP -MF $(DEPDIR)/wocky_connector_test-wocky-test-sasl-auth-server.Tpo -c -o wocky_connector_test-wocky-test-sasl-auth-server.obj `if test -f 'wocky-test-sasl-auth-server.c'; then $(CYGPATH_W) 'wocky-test-sasl-auth-server.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-sasl-auth-server.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_connector_test-wocky-test-sasl-auth-server.Tpo $(DEPDIR)/wocky_connector_test-wocky-test-sasl-auth-server.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-sasl-auth-server.c' object='wocky_connector_test-wocky-test-sasl-auth-server.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -c -o wocky_connector_test-wocky-test-sasl-auth-server.obj `if test -f 'wocky-test-sasl-auth-server.c'; then $(CYGPATH_W) 'wocky-test-sasl-auth-server.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-sasl-auth-server.c'; fi` wocky_connector_test-wocky-test-connector-server.o: wocky-test-connector-server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -MT wocky_connector_test-wocky-test-connector-server.o -MD -MP -MF $(DEPDIR)/wocky_connector_test-wocky-test-connector-server.Tpo -c -o wocky_connector_test-wocky-test-connector-server.o `test -f 'wocky-test-connector-server.c' || echo '$(srcdir)/'`wocky-test-connector-server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_connector_test-wocky-test-connector-server.Tpo $(DEPDIR)/wocky_connector_test-wocky-test-connector-server.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-connector-server.c' object='wocky_connector_test-wocky-test-connector-server.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -c -o wocky_connector_test-wocky-test-connector-server.o `test -f 'wocky-test-connector-server.c' || echo '$(srcdir)/'`wocky-test-connector-server.c wocky_connector_test-wocky-test-connector-server.obj: wocky-test-connector-server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -MT wocky_connector_test-wocky-test-connector-server.obj -MD -MP -MF $(DEPDIR)/wocky_connector_test-wocky-test-connector-server.Tpo -c -o wocky_connector_test-wocky-test-connector-server.obj `if test -f 'wocky-test-connector-server.c'; then $(CYGPATH_W) 'wocky-test-connector-server.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-connector-server.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_connector_test-wocky-test-connector-server.Tpo $(DEPDIR)/wocky_connector_test-wocky-test-connector-server.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-connector-server.c' object='wocky_connector_test-wocky-test-connector-server.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -c -o wocky_connector_test-wocky-test-connector-server.obj `if test -f 'wocky-test-connector-server.c'; then $(CYGPATH_W) 'wocky-test-connector-server.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-connector-server.c'; fi` wocky_connector_test-wocky-test-helper.o: wocky-test-helper.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -MT wocky_connector_test-wocky-test-helper.o -MD -MP -MF $(DEPDIR)/wocky_connector_test-wocky-test-helper.Tpo -c -o wocky_connector_test-wocky-test-helper.o `test -f 'wocky-test-helper.c' || echo '$(srcdir)/'`wocky-test-helper.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_connector_test-wocky-test-helper.Tpo $(DEPDIR)/wocky_connector_test-wocky-test-helper.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-helper.c' object='wocky_connector_test-wocky-test-helper.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -c -o wocky_connector_test-wocky-test-helper.o `test -f 'wocky-test-helper.c' || echo '$(srcdir)/'`wocky-test-helper.c wocky_connector_test-wocky-test-helper.obj: wocky-test-helper.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -MT wocky_connector_test-wocky-test-helper.obj -MD -MP -MF $(DEPDIR)/wocky_connector_test-wocky-test-helper.Tpo -c -o wocky_connector_test-wocky-test-helper.obj `if test -f 'wocky-test-helper.c'; then $(CYGPATH_W) 'wocky-test-helper.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-helper.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_connector_test-wocky-test-helper.Tpo $(DEPDIR)/wocky_connector_test-wocky-test-helper.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-helper.c' object='wocky_connector_test-wocky-test-helper.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -c -o wocky_connector_test-wocky-test-helper.obj `if test -f 'wocky-test-helper.c'; then $(CYGPATH_W) 'wocky-test-helper.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-helper.c'; fi` wocky_connector_test-wocky-test-stream.o: wocky-test-stream.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -MT wocky_connector_test-wocky-test-stream.o -MD -MP -MF $(DEPDIR)/wocky_connector_test-wocky-test-stream.Tpo -c -o wocky_connector_test-wocky-test-stream.o `test -f 'wocky-test-stream.c' || echo '$(srcdir)/'`wocky-test-stream.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_connector_test-wocky-test-stream.Tpo $(DEPDIR)/wocky_connector_test-wocky-test-stream.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-stream.c' object='wocky_connector_test-wocky-test-stream.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -c -o wocky_connector_test-wocky-test-stream.o `test -f 'wocky-test-stream.c' || echo '$(srcdir)/'`wocky-test-stream.c wocky_connector_test-wocky-test-stream.obj: wocky-test-stream.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -MT wocky_connector_test-wocky-test-stream.obj -MD -MP -MF $(DEPDIR)/wocky_connector_test-wocky-test-stream.Tpo -c -o wocky_connector_test-wocky-test-stream.obj `if test -f 'wocky-test-stream.c'; then $(CYGPATH_W) 'wocky-test-stream.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-stream.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_connector_test-wocky-test-stream.Tpo $(DEPDIR)/wocky_connector_test-wocky-test-stream.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-stream.c' object='wocky_connector_test-wocky-test-stream.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -c -o wocky_connector_test-wocky-test-stream.obj `if test -f 'wocky-test-stream.c'; then $(CYGPATH_W) 'wocky-test-stream.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-stream.c'; fi` wocky_connector_test-test-resolver.o: test-resolver.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -MT wocky_connector_test-test-resolver.o -MD -MP -MF $(DEPDIR)/wocky_connector_test-test-resolver.Tpo -c -o wocky_connector_test-test-resolver.o `test -f 'test-resolver.c' || echo '$(srcdir)/'`test-resolver.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_connector_test-test-resolver.Tpo $(DEPDIR)/wocky_connector_test-test-resolver.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-resolver.c' object='wocky_connector_test-test-resolver.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -c -o wocky_connector_test-test-resolver.o `test -f 'test-resolver.c' || echo '$(srcdir)/'`test-resolver.c wocky_connector_test-test-resolver.obj: test-resolver.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -MT wocky_connector_test-test-resolver.obj -MD -MP -MF $(DEPDIR)/wocky_connector_test-test-resolver.Tpo -c -o wocky_connector_test-test-resolver.obj `if test -f 'test-resolver.c'; then $(CYGPATH_W) 'test-resolver.c'; else $(CYGPATH_W) '$(srcdir)/test-resolver.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_connector_test-test-resolver.Tpo $(DEPDIR)/wocky_connector_test-test-resolver.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-resolver.c' object='wocky_connector_test-test-resolver.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_connector_test_CFLAGS) $(CFLAGS) -c -o wocky_connector_test-test-resolver.obj `if test -f 'test-resolver.c'; then $(CYGPATH_W) 'test-resolver.c'; else $(CYGPATH_W) '$(srcdir)/test-resolver.c'; fi` wocky_dummy_xmpp_server-wocky-dummy-xmpp-server.o: wocky-dummy-xmpp-server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) -MT wocky_dummy_xmpp_server-wocky-dummy-xmpp-server.o -MD -MP -MF $(DEPDIR)/wocky_dummy_xmpp_server-wocky-dummy-xmpp-server.Tpo -c -o wocky_dummy_xmpp_server-wocky-dummy-xmpp-server.o `test -f 'wocky-dummy-xmpp-server.c' || echo '$(srcdir)/'`wocky-dummy-xmpp-server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_dummy_xmpp_server-wocky-dummy-xmpp-server.Tpo $(DEPDIR)/wocky_dummy_xmpp_server-wocky-dummy-xmpp-server.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-dummy-xmpp-server.c' object='wocky_dummy_xmpp_server-wocky-dummy-xmpp-server.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) -c -o wocky_dummy_xmpp_server-wocky-dummy-xmpp-server.o `test -f 'wocky-dummy-xmpp-server.c' || echo '$(srcdir)/'`wocky-dummy-xmpp-server.c wocky_dummy_xmpp_server-wocky-dummy-xmpp-server.obj: wocky-dummy-xmpp-server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) -MT wocky_dummy_xmpp_server-wocky-dummy-xmpp-server.obj -MD -MP -MF $(DEPDIR)/wocky_dummy_xmpp_server-wocky-dummy-xmpp-server.Tpo -c -o wocky_dummy_xmpp_server-wocky-dummy-xmpp-server.obj `if test -f 'wocky-dummy-xmpp-server.c'; then $(CYGPATH_W) 'wocky-dummy-xmpp-server.c'; else $(CYGPATH_W) '$(srcdir)/wocky-dummy-xmpp-server.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_dummy_xmpp_server-wocky-dummy-xmpp-server.Tpo $(DEPDIR)/wocky_dummy_xmpp_server-wocky-dummy-xmpp-server.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-dummy-xmpp-server.c' object='wocky_dummy_xmpp_server-wocky-dummy-xmpp-server.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) -c -o wocky_dummy_xmpp_server-wocky-dummy-xmpp-server.obj `if test -f 'wocky-dummy-xmpp-server.c'; then $(CYGPATH_W) 'wocky-dummy-xmpp-server.c'; else $(CYGPATH_W) '$(srcdir)/wocky-dummy-xmpp-server.c'; fi` wocky_dummy_xmpp_server-wocky-test-connector-server.o: wocky-test-connector-server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) -MT wocky_dummy_xmpp_server-wocky-test-connector-server.o -MD -MP -MF $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-connector-server.Tpo -c -o wocky_dummy_xmpp_server-wocky-test-connector-server.o `test -f 'wocky-test-connector-server.c' || echo '$(srcdir)/'`wocky-test-connector-server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-connector-server.Tpo $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-connector-server.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-connector-server.c' object='wocky_dummy_xmpp_server-wocky-test-connector-server.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) -c -o wocky_dummy_xmpp_server-wocky-test-connector-server.o `test -f 'wocky-test-connector-server.c' || echo '$(srcdir)/'`wocky-test-connector-server.c wocky_dummy_xmpp_server-wocky-test-connector-server.obj: wocky-test-connector-server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) -MT wocky_dummy_xmpp_server-wocky-test-connector-server.obj -MD -MP -MF $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-connector-server.Tpo -c -o wocky_dummy_xmpp_server-wocky-test-connector-server.obj `if test -f 'wocky-test-connector-server.c'; then $(CYGPATH_W) 'wocky-test-connector-server.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-connector-server.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-connector-server.Tpo $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-connector-server.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-connector-server.c' object='wocky_dummy_xmpp_server-wocky-test-connector-server.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) -c -o wocky_dummy_xmpp_server-wocky-test-connector-server.obj `if test -f 'wocky-test-connector-server.c'; then $(CYGPATH_W) 'wocky-test-connector-server.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-connector-server.c'; fi` wocky_dummy_xmpp_server-wocky-test-helper.o: wocky-test-helper.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) -MT wocky_dummy_xmpp_server-wocky-test-helper.o -MD -MP -MF $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-helper.Tpo -c -o wocky_dummy_xmpp_server-wocky-test-helper.o `test -f 'wocky-test-helper.c' || echo '$(srcdir)/'`wocky-test-helper.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-helper.Tpo $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-helper.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-helper.c' object='wocky_dummy_xmpp_server-wocky-test-helper.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) -c -o wocky_dummy_xmpp_server-wocky-test-helper.o `test -f 'wocky-test-helper.c' || echo '$(srcdir)/'`wocky-test-helper.c wocky_dummy_xmpp_server-wocky-test-helper.obj: wocky-test-helper.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) -MT wocky_dummy_xmpp_server-wocky-test-helper.obj -MD -MP -MF $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-helper.Tpo -c -o wocky_dummy_xmpp_server-wocky-test-helper.obj `if test -f 'wocky-test-helper.c'; then $(CYGPATH_W) 'wocky-test-helper.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-helper.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-helper.Tpo $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-helper.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-helper.c' object='wocky_dummy_xmpp_server-wocky-test-helper.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) -c -o wocky_dummy_xmpp_server-wocky-test-helper.obj `if test -f 'wocky-test-helper.c'; then $(CYGPATH_W) 'wocky-test-helper.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-helper.c'; fi` wocky_dummy_xmpp_server-wocky-test-stream.o: wocky-test-stream.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) -MT wocky_dummy_xmpp_server-wocky-test-stream.o -MD -MP -MF $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-stream.Tpo -c -o wocky_dummy_xmpp_server-wocky-test-stream.o `test -f 'wocky-test-stream.c' || echo '$(srcdir)/'`wocky-test-stream.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-stream.Tpo $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-stream.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-stream.c' object='wocky_dummy_xmpp_server-wocky-test-stream.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) -c -o wocky_dummy_xmpp_server-wocky-test-stream.o `test -f 'wocky-test-stream.c' || echo '$(srcdir)/'`wocky-test-stream.c wocky_dummy_xmpp_server-wocky-test-stream.obj: wocky-test-stream.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) -MT wocky_dummy_xmpp_server-wocky-test-stream.obj -MD -MP -MF $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-stream.Tpo -c -o wocky_dummy_xmpp_server-wocky-test-stream.obj `if test -f 'wocky-test-stream.c'; then $(CYGPATH_W) 'wocky-test-stream.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-stream.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-stream.Tpo $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-stream.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-stream.c' object='wocky_dummy_xmpp_server-wocky-test-stream.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) -c -o wocky_dummy_xmpp_server-wocky-test-stream.obj `if test -f 'wocky-test-stream.c'; then $(CYGPATH_W) 'wocky-test-stream.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-stream.c'; fi` wocky_dummy_xmpp_server-wocky-test-sasl-auth-server.o: wocky-test-sasl-auth-server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) -MT wocky_dummy_xmpp_server-wocky-test-sasl-auth-server.o -MD -MP -MF $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-sasl-auth-server.Tpo -c -o wocky_dummy_xmpp_server-wocky-test-sasl-auth-server.o `test -f 'wocky-test-sasl-auth-server.c' || echo '$(srcdir)/'`wocky-test-sasl-auth-server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-sasl-auth-server.Tpo $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-sasl-auth-server.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-sasl-auth-server.c' object='wocky_dummy_xmpp_server-wocky-test-sasl-auth-server.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) -c -o wocky_dummy_xmpp_server-wocky-test-sasl-auth-server.o `test -f 'wocky-test-sasl-auth-server.c' || echo '$(srcdir)/'`wocky-test-sasl-auth-server.c wocky_dummy_xmpp_server-wocky-test-sasl-auth-server.obj: wocky-test-sasl-auth-server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) -MT wocky_dummy_xmpp_server-wocky-test-sasl-auth-server.obj -MD -MP -MF $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-sasl-auth-server.Tpo -c -o wocky_dummy_xmpp_server-wocky-test-sasl-auth-server.obj `if test -f 'wocky-test-sasl-auth-server.c'; then $(CYGPATH_W) 'wocky-test-sasl-auth-server.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-sasl-auth-server.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-sasl-auth-server.Tpo $(DEPDIR)/wocky_dummy_xmpp_server-wocky-test-sasl-auth-server.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-sasl-auth-server.c' object='wocky_dummy_xmpp_server-wocky-test-sasl-auth-server.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_dummy_xmpp_server_CFLAGS) $(CFLAGS) -c -o wocky_dummy_xmpp_server-wocky-test-sasl-auth-server.obj `if test -f 'wocky-test-sasl-auth-server.c'; then $(CYGPATH_W) 'wocky-test-sasl-auth-server.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-sasl-auth-server.c'; fi` wocky_test_sasl_auth-wocky-test-helper.o: wocky-test-helper.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) -MT wocky_test_sasl_auth-wocky-test-helper.o -MD -MP -MF $(DEPDIR)/wocky_test_sasl_auth-wocky-test-helper.Tpo -c -o wocky_test_sasl_auth-wocky-test-helper.o `test -f 'wocky-test-helper.c' || echo '$(srcdir)/'`wocky-test-helper.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_test_sasl_auth-wocky-test-helper.Tpo $(DEPDIR)/wocky_test_sasl_auth-wocky-test-helper.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-helper.c' object='wocky_test_sasl_auth-wocky-test-helper.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) -c -o wocky_test_sasl_auth-wocky-test-helper.o `test -f 'wocky-test-helper.c' || echo '$(srcdir)/'`wocky-test-helper.c wocky_test_sasl_auth-wocky-test-helper.obj: wocky-test-helper.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) -MT wocky_test_sasl_auth-wocky-test-helper.obj -MD -MP -MF $(DEPDIR)/wocky_test_sasl_auth-wocky-test-helper.Tpo -c -o wocky_test_sasl_auth-wocky-test-helper.obj `if test -f 'wocky-test-helper.c'; then $(CYGPATH_W) 'wocky-test-helper.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-helper.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_test_sasl_auth-wocky-test-helper.Tpo $(DEPDIR)/wocky_test_sasl_auth-wocky-test-helper.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-helper.c' object='wocky_test_sasl_auth-wocky-test-helper.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) -c -o wocky_test_sasl_auth-wocky-test-helper.obj `if test -f 'wocky-test-helper.c'; then $(CYGPATH_W) 'wocky-test-helper.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-helper.c'; fi` wocky_test_sasl_auth-wocky-test-sasl-auth.o: wocky-test-sasl-auth.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) -MT wocky_test_sasl_auth-wocky-test-sasl-auth.o -MD -MP -MF $(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-auth.Tpo -c -o wocky_test_sasl_auth-wocky-test-sasl-auth.o `test -f 'wocky-test-sasl-auth.c' || echo '$(srcdir)/'`wocky-test-sasl-auth.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-auth.Tpo $(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-auth.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-sasl-auth.c' object='wocky_test_sasl_auth-wocky-test-sasl-auth.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) -c -o wocky_test_sasl_auth-wocky-test-sasl-auth.o `test -f 'wocky-test-sasl-auth.c' || echo '$(srcdir)/'`wocky-test-sasl-auth.c wocky_test_sasl_auth-wocky-test-sasl-auth.obj: wocky-test-sasl-auth.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) -MT wocky_test_sasl_auth-wocky-test-sasl-auth.obj -MD -MP -MF $(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-auth.Tpo -c -o wocky_test_sasl_auth-wocky-test-sasl-auth.obj `if test -f 'wocky-test-sasl-auth.c'; then $(CYGPATH_W) 'wocky-test-sasl-auth.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-sasl-auth.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-auth.Tpo $(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-auth.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-sasl-auth.c' object='wocky_test_sasl_auth-wocky-test-sasl-auth.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) -c -o wocky_test_sasl_auth-wocky-test-sasl-auth.obj `if test -f 'wocky-test-sasl-auth.c'; then $(CYGPATH_W) 'wocky-test-sasl-auth.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-sasl-auth.c'; fi` wocky_test_sasl_auth-wocky-test-sasl-handler.o: wocky-test-sasl-handler.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) -MT wocky_test_sasl_auth-wocky-test-sasl-handler.o -MD -MP -MF $(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-handler.Tpo -c -o wocky_test_sasl_auth-wocky-test-sasl-handler.o `test -f 'wocky-test-sasl-handler.c' || echo '$(srcdir)/'`wocky-test-sasl-handler.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-handler.Tpo $(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-handler.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-sasl-handler.c' object='wocky_test_sasl_auth-wocky-test-sasl-handler.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) -c -o wocky_test_sasl_auth-wocky-test-sasl-handler.o `test -f 'wocky-test-sasl-handler.c' || echo '$(srcdir)/'`wocky-test-sasl-handler.c wocky_test_sasl_auth-wocky-test-sasl-handler.obj: wocky-test-sasl-handler.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) -MT wocky_test_sasl_auth-wocky-test-sasl-handler.obj -MD -MP -MF $(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-handler.Tpo -c -o wocky_test_sasl_auth-wocky-test-sasl-handler.obj `if test -f 'wocky-test-sasl-handler.c'; then $(CYGPATH_W) 'wocky-test-sasl-handler.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-sasl-handler.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-handler.Tpo $(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-handler.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-sasl-handler.c' object='wocky_test_sasl_auth-wocky-test-sasl-handler.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) -c -o wocky_test_sasl_auth-wocky-test-sasl-handler.obj `if test -f 'wocky-test-sasl-handler.c'; then $(CYGPATH_W) 'wocky-test-sasl-handler.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-sasl-handler.c'; fi` wocky_test_sasl_auth-wocky-test-sasl-auth-server.o: wocky-test-sasl-auth-server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) -MT wocky_test_sasl_auth-wocky-test-sasl-auth-server.o -MD -MP -MF $(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-auth-server.Tpo -c -o wocky_test_sasl_auth-wocky-test-sasl-auth-server.o `test -f 'wocky-test-sasl-auth-server.c' || echo '$(srcdir)/'`wocky-test-sasl-auth-server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-auth-server.Tpo $(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-auth-server.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-sasl-auth-server.c' object='wocky_test_sasl_auth-wocky-test-sasl-auth-server.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) -c -o wocky_test_sasl_auth-wocky-test-sasl-auth-server.o `test -f 'wocky-test-sasl-auth-server.c' || echo '$(srcdir)/'`wocky-test-sasl-auth-server.c wocky_test_sasl_auth-wocky-test-sasl-auth-server.obj: wocky-test-sasl-auth-server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) -MT wocky_test_sasl_auth-wocky-test-sasl-auth-server.obj -MD -MP -MF $(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-auth-server.Tpo -c -o wocky_test_sasl_auth-wocky-test-sasl-auth-server.obj `if test -f 'wocky-test-sasl-auth-server.c'; then $(CYGPATH_W) 'wocky-test-sasl-auth-server.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-sasl-auth-server.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-auth-server.Tpo $(DEPDIR)/wocky_test_sasl_auth-wocky-test-sasl-auth-server.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-sasl-auth-server.c' object='wocky_test_sasl_auth-wocky-test-sasl-auth-server.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) -c -o wocky_test_sasl_auth-wocky-test-sasl-auth-server.obj `if test -f 'wocky-test-sasl-auth-server.c'; then $(CYGPATH_W) 'wocky-test-sasl-auth-server.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-sasl-auth-server.c'; fi` wocky_test_sasl_auth-wocky-test-stream.o: wocky-test-stream.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) -MT wocky_test_sasl_auth-wocky-test-stream.o -MD -MP -MF $(DEPDIR)/wocky_test_sasl_auth-wocky-test-stream.Tpo -c -o wocky_test_sasl_auth-wocky-test-stream.o `test -f 'wocky-test-stream.c' || echo '$(srcdir)/'`wocky-test-stream.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_test_sasl_auth-wocky-test-stream.Tpo $(DEPDIR)/wocky_test_sasl_auth-wocky-test-stream.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-stream.c' object='wocky_test_sasl_auth-wocky-test-stream.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) -c -o wocky_test_sasl_auth-wocky-test-stream.o `test -f 'wocky-test-stream.c' || echo '$(srcdir)/'`wocky-test-stream.c wocky_test_sasl_auth-wocky-test-stream.obj: wocky-test-stream.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) -MT wocky_test_sasl_auth-wocky-test-stream.obj -MD -MP -MF $(DEPDIR)/wocky_test_sasl_auth-wocky-test-stream.Tpo -c -o wocky_test_sasl_auth-wocky-test-stream.obj `if test -f 'wocky-test-stream.c'; then $(CYGPATH_W) 'wocky-test-stream.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-stream.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_test_sasl_auth-wocky-test-stream.Tpo $(DEPDIR)/wocky_test_sasl_auth-wocky-test-stream.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-stream.c' object='wocky_test_sasl_auth-wocky-test-stream.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_test_sasl_auth_CFLAGS) $(CFLAGS) -c -o wocky_test_sasl_auth-wocky-test-stream.obj `if test -f 'wocky-test-stream.c'; then $(CYGPATH_W) 'wocky-test-stream.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-stream.c'; fi` wocky_tls_test-wocky-tls-test.o: wocky-tls-test.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_tls_test_CFLAGS) $(CFLAGS) -MT wocky_tls_test-wocky-tls-test.o -MD -MP -MF $(DEPDIR)/wocky_tls_test-wocky-tls-test.Tpo -c -o wocky_tls_test-wocky-tls-test.o `test -f 'wocky-tls-test.c' || echo '$(srcdir)/'`wocky-tls-test.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_tls_test-wocky-tls-test.Tpo $(DEPDIR)/wocky_tls_test-wocky-tls-test.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-tls-test.c' object='wocky_tls_test-wocky-tls-test.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_tls_test_CFLAGS) $(CFLAGS) -c -o wocky_tls_test-wocky-tls-test.o `test -f 'wocky-tls-test.c' || echo '$(srcdir)/'`wocky-tls-test.c wocky_tls_test-wocky-tls-test.obj: wocky-tls-test.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_tls_test_CFLAGS) $(CFLAGS) -MT wocky_tls_test-wocky-tls-test.obj -MD -MP -MF $(DEPDIR)/wocky_tls_test-wocky-tls-test.Tpo -c -o wocky_tls_test-wocky-tls-test.obj `if test -f 'wocky-tls-test.c'; then $(CYGPATH_W) 'wocky-tls-test.c'; else $(CYGPATH_W) '$(srcdir)/wocky-tls-test.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_tls_test-wocky-tls-test.Tpo $(DEPDIR)/wocky_tls_test-wocky-tls-test.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-tls-test.c' object='wocky_tls_test-wocky-tls-test.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_tls_test_CFLAGS) $(CFLAGS) -c -o wocky_tls_test-wocky-tls-test.obj `if test -f 'wocky-tls-test.c'; then $(CYGPATH_W) 'wocky-tls-test.c'; else $(CYGPATH_W) '$(srcdir)/wocky-tls-test.c'; fi` wocky_tls_test-wocky-test-helper.o: wocky-test-helper.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_tls_test_CFLAGS) $(CFLAGS) -MT wocky_tls_test-wocky-test-helper.o -MD -MP -MF $(DEPDIR)/wocky_tls_test-wocky-test-helper.Tpo -c -o wocky_tls_test-wocky-test-helper.o `test -f 'wocky-test-helper.c' || echo '$(srcdir)/'`wocky-test-helper.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_tls_test-wocky-test-helper.Tpo $(DEPDIR)/wocky_tls_test-wocky-test-helper.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-helper.c' object='wocky_tls_test-wocky-test-helper.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_tls_test_CFLAGS) $(CFLAGS) -c -o wocky_tls_test-wocky-test-helper.o `test -f 'wocky-test-helper.c' || echo '$(srcdir)/'`wocky-test-helper.c wocky_tls_test-wocky-test-helper.obj: wocky-test-helper.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_tls_test_CFLAGS) $(CFLAGS) -MT wocky_tls_test-wocky-test-helper.obj -MD -MP -MF $(DEPDIR)/wocky_tls_test-wocky-test-helper.Tpo -c -o wocky_tls_test-wocky-test-helper.obj `if test -f 'wocky-test-helper.c'; then $(CYGPATH_W) 'wocky-test-helper.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-helper.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_tls_test-wocky-test-helper.Tpo $(DEPDIR)/wocky_tls_test-wocky-test-helper.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-helper.c' object='wocky_tls_test-wocky-test-helper.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_tls_test_CFLAGS) $(CFLAGS) -c -o wocky_tls_test-wocky-test-helper.obj `if test -f 'wocky-test-helper.c'; then $(CYGPATH_W) 'wocky-test-helper.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-helper.c'; fi` wocky_tls_test-wocky-test-stream.o: wocky-test-stream.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_tls_test_CFLAGS) $(CFLAGS) -MT wocky_tls_test-wocky-test-stream.o -MD -MP -MF $(DEPDIR)/wocky_tls_test-wocky-test-stream.Tpo -c -o wocky_tls_test-wocky-test-stream.o `test -f 'wocky-test-stream.c' || echo '$(srcdir)/'`wocky-test-stream.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_tls_test-wocky-test-stream.Tpo $(DEPDIR)/wocky_tls_test-wocky-test-stream.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-stream.c' object='wocky_tls_test-wocky-test-stream.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_tls_test_CFLAGS) $(CFLAGS) -c -o wocky_tls_test-wocky-test-stream.o `test -f 'wocky-test-stream.c' || echo '$(srcdir)/'`wocky-test-stream.c wocky_tls_test-wocky-test-stream.obj: wocky-test-stream.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_tls_test_CFLAGS) $(CFLAGS) -MT wocky_tls_test-wocky-test-stream.obj -MD -MP -MF $(DEPDIR)/wocky_tls_test-wocky-test-stream.Tpo -c -o wocky_tls_test-wocky-test-stream.obj `if test -f 'wocky-test-stream.c'; then $(CYGPATH_W) 'wocky-test-stream.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-stream.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/wocky_tls_test-wocky-test-stream.Tpo $(DEPDIR)/wocky_tls_test-wocky-test-stream.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wocky-test-stream.c' object='wocky_tls_test-wocky-test-stream.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(wocky_tls_test_CFLAGS) $(CFLAGS) -c -o wocky_tls_test-wocky-test-stream.obj `if test -f 'wocky-test-stream.c'; then $(CYGPATH_W) 'wocky-test-stream.c'; else $(CYGPATH_W) '$(srcdir)/wocky-test-stream.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile $(PROGRAMS) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am check-local clean \ clean-checkPROGRAMS clean-generic clean-libtool \ clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am test-report: test-report.xml gtester-report $(top_builddir)/tests/$@.xml > \ $(top_builddir)/tests/$@.html test-report.xml: ${TEST_PROGS} test test: ${TEST_PROGS} gtester -o test-report.xml -k --verbose ${TEST_PROGS} @if [ -x $(which python) ] ; then \ $(SUMMARY) $@-report.xml ; \ else \ echo "No python available, not summarizing test results" ; \ fi test-%: wocky-%-test gtester -o $@-report.xml -k --verbose $< @if [ -x $(which python) ] ; then \ $(SUMMARY) $@-report.xml ; \ else \ echo "No python available, not summarizing test results" ; \ fi .PHONY: test test-report check-coding-style: @fail=0; \ if test -n "$(check_misc_sources)"; then \ tools_dir=$(top_srcdir)/tools \ sh $(top_srcdir)/tools/check-misc.sh \ $(addprefix $(srcdir)/,$(check_misc_sources)) || fail=1; \ fi; \ if test -n "$(check_c_sources)"; then \ tools_dir=$(top_srcdir)/tools \ sh $(top_srcdir)/tools/check-c-style.sh \ $(addprefix $(srcdir)/,$(check_c_sources)) || fail=1; \ fi;\ if test yes = "$(ENABLE_CODING_STYLE_CHECKS)"; then \ exit "$$fail";\ else \ exit 0;\ fi check-local: test check-coding-style # valgrind any given test by running make test.valgrind %.valgrind: % G_SLICE=always-malloc \ G_DEBUG=gc-friendly \ valgrind -q \ $(foreach s,$(SUPPRESSIONS),--suppressions=$(srcdir)/$(s)) \ --tool=memcheck --leak-check=full --trace-children=yes \ --leak-resolution=high --num-callers=20 \ ./$* $(TEST_ARGS) 2>&1 | tee "valgrind.$*.log" @if grep "==" "valgrind.$*.log" > /dev/null 2>&1; then \ exit 1; \ fi valgrind: $(TEST_PROGS) @echo "Valgrinding tests ..." @failed=0; \ for t in $(filter-out $(VALGRIND_TESTS_DISABLE),$(TEST_PROGS)); do \ $(MAKE) $$t.valgrind; \ if test "$$?" -ne 0; then \ echo "Valgrind error for test $$t"; \ failed=`expr $$failed + 1`; \ whicht="$$whicht $$t"; \ fi; \ done; \ if test "$$failed" -ne 0; then \ echo "$$failed tests had leaks or errors under valgrind:"; \ echo "$$whicht"; \ false; \ fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-dummy-xmpp-server.c0000664000175000017500000000464712212322440026764 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include "wocky-test-connector-server.h" GMainLoop *loop; static gboolean server_quit (GIOChannel *channel, GIOCondition cond, gpointer data) { g_main_loop_quit (loop); return FALSE; } static gboolean client_connected (GIOChannel *channel, GIOCondition cond, gpointer data) { struct sockaddr_in client; socklen_t clen = sizeof (client); int ssock = g_io_channel_unix_get_fd (channel); int csock = accept (ssock, (struct sockaddr *)&client, &clen); GSocket *gsock = g_socket_new_from_fd (csock, NULL); ConnectorProblem cproblem = { 0, }; GSocketConnection *gconn; pid_t pid = 0; TestConnectorServer *server; if (csock < 0) { perror ("accept() failed"); g_warning ("accept() failed on socket that should have been ready."); return TRUE; } switch ((pid = fork ())) { case -1: perror ("Failed to spawn child process"); g_main_loop_quit (loop); break; case 0: while (g_source_remove_by_user_data (loop)); g_io_channel_shutdown (channel, TRUE, NULL); gconn = g_object_new (G_TYPE_SOCKET_CONNECTION, "socket", gsock, NULL); server = test_connector_server_new (G_IO_STREAM (gconn), NULL, "foo", "bar", "1.0", &cproblem, SERVER_PROBLEM_NO_PROBLEM, CERT_STANDARD); test_connector_server_start (server); return FALSE; default: g_socket_close (gsock, NULL); return TRUE; } return FALSE; } int main (int argc, char **argv) { int ssock; int reuse = 1; struct sockaddr_in server; GIOChannel *channel; memset (&server, 0, sizeof (server)); g_type_init (); loop = g_main_loop_new (NULL, FALSE); server.sin_family = AF_INET; inet_aton ("127.0.0.1", &server.sin_addr); server.sin_port = htons (5222); ssock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); setsockopt (ssock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof (reuse)); bind (ssock, (struct sockaddr *)&server, sizeof (server)); listen (ssock, 1024); channel = g_io_channel_unix_new (ssock); g_io_add_watch (channel, G_IO_IN|G_IO_PRI, client_connected, loop); g_io_add_watch (channel, G_IO_ERR|G_IO_NVAL, server_quit, loop); g_main_loop_run (loop); } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-loopback-test.c0000664000175000017500000001046312005516162026111 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "wocky-test-helper.h" /* I'm not happy about this, but the existing test stuff really relies * on having multiple streams */ typedef struct { test_data_t data; GIOStream *stream; WockyXmppConnection *conn; WockySession *session; WockyPorter *porter; } loopback_test_t; static gboolean test_timeout (gpointer data) { g_test_message ("Timeout reached :("); g_assert_not_reached (); return FALSE; } static loopback_test_t * setup (void) { loopback_test_t *test = g_slice_new0 (loopback_test_t); test->data.loop = g_main_loop_new (NULL, FALSE); test->data.cancellable = g_cancellable_new (); test->data.timeout_id = g_timeout_add_seconds (10, test_timeout, NULL); test->data.expected_stanzas = g_queue_new (); test->stream = wocky_loopback_stream_new (); test->conn = wocky_xmpp_connection_new (test->stream); test->session = wocky_session_new_with_connection (test->conn, "example.com"); test->porter = wocky_session_get_porter (test->session); return test; } static void send_received_open_cb (GObject *source, GAsyncResult *res, gpointer user_data) { WockyXmppConnection *conn = WOCKY_XMPP_CONNECTION (source); loopback_test_t *d = (loopback_test_t *) user_data; g_assert (wocky_xmpp_connection_recv_open_finish (conn, res, NULL, NULL, NULL, NULL, NULL, NULL)); wocky_session_start (d->session); d->data.outstanding--; g_main_loop_quit (d->data.loop); } static void send_open_cb (GObject *source, GAsyncResult *res, gpointer user_data) { WockyXmppConnection *conn = WOCKY_XMPP_CONNECTION (source); g_assert (wocky_xmpp_connection_send_open_finish (conn, res, NULL)); wocky_xmpp_connection_recv_open_async (conn, NULL, send_received_open_cb, user_data); } static void start_test (loopback_test_t *test) { wocky_xmpp_connection_send_open_async (test->conn, NULL, NULL, NULL, NULL, NULL, NULL, send_open_cb, test); test->data.outstanding++; test_wait_pending (&(test->data)); } static void close_cb (GObject *source, GAsyncResult *res, gpointer user_data) { loopback_test_t *test = user_data; g_assert (wocky_porter_close_finish (WOCKY_PORTER (source), res, NULL)); test->data.outstanding--; g_main_loop_quit (test->data.loop); g_main_loop_unref (test->data.loop); g_object_unref (test->session); g_object_unref (test->conn); g_object_unref (test->data.cancellable); g_source_remove (test->data.timeout_id); g_assert (g_queue_get_length (test->data.expected_stanzas) == 0); g_queue_free (test->data.expected_stanzas); g_slice_free (loopback_test_t, test); } static void cleanup (loopback_test_t *test) { wocky_porter_close_async (test->porter, NULL, close_cb, test); test->data.outstanding++; test_wait_pending (&(test->data)); } static void send_stanza_cb (GObject *source, GAsyncResult *res, gpointer user_data) { test_data_t *data = (test_data_t *) user_data; g_assert (wocky_porter_send_finish ( WOCKY_PORTER (source), res, NULL)); data->outstanding--; g_main_loop_quit (data->loop); } /* receive testing */ static gboolean test_receive_stanza_received_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { test_data_t *test = (test_data_t *) user_data; test_expected_stanza_received (test, stanza); return TRUE; } static void test_receive (void) { loopback_test_t *test = setup (); WockyStanza *s; start_test (test); wocky_porter_register_handler_from_anyone (test->porter, WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, 0, test_receive_stanza_received_cb, test, NULL); /* Send a stanza */ s = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_CHAT, "juliet@example.com", "romeo@example.net", NULL); wocky_porter_send_async (test->porter, s, NULL, send_stanza_cb, test); g_queue_push_tail (test->data.expected_stanzas, s); /* We are waiting for the stanza to be sent and received on the other * side */ test->data.outstanding += 2; test_wait_pending (&(test->data)); cleanup (test); } int main (int argc, char **argv) { int result; test_init (argc, argv); g_test_add_func ("/loopback-porter/receive", test_receive); result = g_test_run (); test_deinit (); return result; } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-test-stream.h0000644000175000017500000000661611622404715025626 0ustar00cassidycassidy00000000000000/* * wocky-test-stream.h - Header for WockyTestStream * Copyright (C) 2009 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __WOCKY_TEST_STREAM_H__ #define __WOCKY_TEST_STREAM_H__ #include #include G_BEGIN_DECLS typedef struct _WockyTestStream WockyTestStream; typedef struct _WockyTestStreamClass WockyTestStreamClass; typedef struct _WockyTestStreamPrivate WockyTestStreamPrivate; struct _WockyTestStreamClass { GObjectClass parent_class; }; struct _WockyTestStream { GObject parent; GIOStream *stream0; GIOStream *stream1; GInputStream *stream0_input; GOutputStream *stream0_output; GInputStream *stream1_input; GOutputStream *stream1_output; WockyTestStreamPrivate *priv; }; GType wocky_test_stream_get_type (void); /* TYPE MACROS */ #define WOCKY_TYPE_TEST_STREAM \ (wocky_test_stream_get_type ()) #define WOCKY_TEST_STREAM(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_TEST_STREAM, WockyTestStream)) #define WOCKY_TEST_STREAM_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_TEST_STREAM, WockyTestStreamClass)) #define WOCKY_IS_TEST_STREAM(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_TEST_STREAM)) #define WOCKY_IS_TEST_STREAM_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_TEST_STREAM)) #define WOCKY_TEST_STREAM_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_TEST_STREAM, WockyTestStreamClass)) void wocky_test_input_stream_set_read_error (GInputStream *stream); void wocky_test_output_stream_set_write_error (GOutputStream *stream); void wocky_test_stream_cork (GInputStream *stream, gboolean cork); typedef enum { /* one read can have data from two writes, but never has all the data * from one specific write */ WOCK_TEST_STREAM_READ_COMBINE_SLICE = 0, /* one read reads as much as is available */ WOCK_TEST_STREAM_READ_COMBINE, /* one read reads only data from one write */ WOCK_TEST_STREAM_READ_EXACT, } WockyTestStreamReadMode; typedef enum { /* all writes are only half-done, default */ WOCKY_TEST_STREAM_WRITE_INCOMPLETE = 0, /* Always succeed in writing everything */ WOCKY_TEST_STREAM_WRITE_COMPLETE = 1, } WockyTestStreamWriteMode; void wocky_test_stream_set_mode (GInputStream *stream, WockyTestStreamReadMode mode); void wocky_test_stream_set_write_mode (GOutputStream *stream, WockyTestStreamWriteMode mode); typedef void (*WockyTestStreamDirectReadCb) (const gchar *buff, gsize len, gpointer user_data); void wocky_test_stream_set_direct_read_callback (GInputStream *stream, WockyTestStreamDirectReadCb cb, gpointer user_data); G_END_DECLS #endif /* #ifndef __WOCKY_TEST_STREAM_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-pubsub-test-helpers.c0000664000175000017500000000266312005516162027262 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-pubsub-test-helpers.h" #include void test_pubsub_add_subscription_nodes ( WockyNode *subscriptions_node, CannedSubscriptions *subs, gboolean include_node) { CannedSubscriptions *l; for (l = subs; l != NULL && l->node != NULL; l++) { WockyNode *sub = wocky_node_add_child (subscriptions_node, "subscription"); if (include_node) wocky_node_set_attribute (sub, "node", l->node); wocky_node_set_attribute (sub, "jid", l->jid); wocky_node_set_attribute (sub, "subscription", l->subscription); if (l->subid != NULL) wocky_node_set_attribute (sub, "subid", l->subid); } } void test_pubsub_check_and_free_subscriptions ( GList *subscriptions, const CannedSubscriptions *expected_subs) { GList *l; guint i = 0; for (l = subscriptions; l != NULL; l = l->next, i++) { WockyPubsubSubscription *sub = l->data; g_assert (expected_subs[i].jid != NULL); g_assert_cmpstr (expected_subs[i].jid, ==, sub->jid); g_assert_cmpstr (expected_subs[i].node, ==, wocky_pubsub_node_get_name (sub->node)); g_assert_cmpuint (expected_subs[i].state, ==, sub->state); g_assert_cmpstr (expected_subs[i].subid, ==, sub->subid); } g_assert_cmpstr (expected_subs[i].jid, ==, NULL); wocky_pubsub_subscription_list_free (subscriptions); } telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-test-connector-server.h0000664000175000017500000001412712212322440027615 0ustar00cassidycassidy00000000000000/* * wocky-test-sasl-auth-server.h - Header for TestSaslAuthServer * Copyright (C) 2006 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_CONNECTOR_SERVER_H__ #define __TEST_CONNECTOR_SERVER_H__ #include #include #include "wocky-test-sasl-auth-server.h" G_BEGIN_DECLS #define CONNPROBLEM(x) (0x1 << x) typedef enum { XMPP_PROBLEM_NONE = 0, XMPP_PROBLEM_BAD_XMPP = CONNPROBLEM (0), XMPP_PROBLEM_NO_TLS = CONNPROBLEM (1), XMPP_PROBLEM_TLS_REFUSED = CONNPROBLEM (2), XMPP_PROBLEM_FEATURES = CONNPROBLEM (3), XMPP_PROBLEM_OLD_SERVER = CONNPROBLEM (4), XMPP_PROBLEM_WEAK_SSL = CONNPROBLEM (5), XMPP_PROBLEM_OLD_SSL = CONNPROBLEM (6), XMPP_PROBLEM_OTHER_HOST = CONNPROBLEM (7), XMPP_PROBLEM_TLS_LOAD = CONNPROBLEM (8), XMPP_PROBLEM_NO_SESSION = CONNPROBLEM (10), XMPP_PROBLEM_CANNOT_BIND = CONNPROBLEM (11), XMPP_PROBLEM_OLD_AUTH_FEATURE = CONNPROBLEM (12), XMPP_PROBLEM_SEE_OTHER_HOST = CONNPROBLEM (13), } XmppProblem; typedef enum { BIND_PROBLEM_NONE = 0, BIND_PROBLEM_INVALID = CONNPROBLEM(0), BIND_PROBLEM_DENIED = CONNPROBLEM(1), BIND_PROBLEM_CONFLICT = CONNPROBLEM(2), BIND_PROBLEM_CLASH = CONNPROBLEM(3), BIND_PROBLEM_REJECTED = CONNPROBLEM(4), BIND_PROBLEM_FAILED = CONNPROBLEM(5), BIND_PROBLEM_NO_JID = CONNPROBLEM(6), BIND_PROBLEM_NONSENSE = CONNPROBLEM(7), } BindProblem; typedef enum { SESSION_PROBLEM_NONE = 0, SESSION_PROBLEM_NO_SESSION = CONNPROBLEM(0), SESSION_PROBLEM_FAILED = CONNPROBLEM(1), SESSION_PROBLEM_DENIED = CONNPROBLEM(2), SESSION_PROBLEM_CONFLICT = CONNPROBLEM(3), SESSION_PROBLEM_REJECTED = CONNPROBLEM(4), SESSION_PROBLEM_NONSENSE = CONNPROBLEM(5), } SessionProblem; typedef enum { SERVER_DEATH_NONE = 0, SERVER_DEATH_SERVER_START = CONNPROBLEM(0), SERVER_DEATH_CLIENT_OPEN = CONNPROBLEM(1), SERVER_DEATH_SERVER_OPEN = CONNPROBLEM(2), SERVER_DEATH_FEATURES = CONNPROBLEM(3), SERVER_DEATH_TLS_NEG = CONNPROBLEM(4), } ServerDeath; typedef enum { JABBER_PROBLEM_NONE = 0, JABBER_PROBLEM_AUTH_REJECT = CONNPROBLEM (0), JABBER_PROBLEM_AUTH_BIND = CONNPROBLEM (1), JABBER_PROBLEM_AUTH_PARTIAL = CONNPROBLEM (2), JABBER_PROBLEM_AUTH_FAILED = CONNPROBLEM (3), JABBER_PROBLEM_AUTH_STRANGE = CONNPROBLEM (4), JABBER_PROBLEM_AUTH_NIH = CONNPROBLEM (5), JABBER_PROBLEM_AUTH_NONSENSE = CONNPROBLEM (6), } JabberProblem; typedef enum { XEP77_PROBLEM_NONE = 0, XEP77_PROBLEM_ALREADY = CONNPROBLEM(0), XEP77_PROBLEM_FAIL_CONFLICT = CONNPROBLEM(1), XEP77_PROBLEM_FAIL_REJECTED = CONNPROBLEM(2), XEP77_PROBLEM_NOT_AVAILABLE = CONNPROBLEM(3), XEP77_PROBLEM_QUERY_NONSENSE = CONNPROBLEM(4), XEP77_PROBLEM_QUERY_ALREADY = CONNPROBLEM(5), XEP77_PROBLEM_NO_ARGS = CONNPROBLEM(6), XEP77_PROBLEM_EMAIL_ARG = CONNPROBLEM(7), XEP77_PROBLEM_STRANGE_ARG = CONNPROBLEM(8), XEP77_PROBLEM_CANCEL_REJECTED = CONNPROBLEM(9), XEP77_PROBLEM_CANCEL_DISABLED = CONNPROBLEM(10), XEP77_PROBLEM_CANCEL_FAILED = CONNPROBLEM(11), XEP77_PROBLEM_CANCEL_STREAM = CONNPROBLEM(12), } XEP77Problem; typedef enum { CERT_STANDARD, CERT_EXPIRED, CERT_NOT_YET, CERT_UNKNOWN, CERT_SELFSIGN, CERT_REVOKED, CERT_WILDCARD, CERT_BADWILD, CERT_NONE, } CertSet; typedef struct { XmppProblem xmpp; BindProblem bind; SessionProblem session; ServerDeath death; JabberProblem jabber; XEP77Problem xep77; } ConnectorProblem; typedef struct _TestConnectorServer TestConnectorServer; typedef struct _TestConnectorServerClass TestConnectorServerClass; typedef struct _TestConnectorServerPrivate TestConnectorServerPrivate; struct _TestConnectorServerClass { GObjectClass parent_class; }; struct _TestConnectorServer { GObject parent; TestConnectorServerPrivate *priv; }; GType test_connector_server_get_type (void); /* TYPE MACROS */ #define TEST_TYPE_CONNECTOR_SERVER \ (test_connector_server_get_type ()) #define TEST_CONNECTOR_SERVER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), TEST_TYPE_CONNECTOR_SERVER, \ TestConnectorServer)) #define TEST_CONNECTOR_SERVER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), TEST_TYPE_CONNECTOR_SERVER, \ TestConnectorServerClass)) #define TEST_IS_CONNECTOR_SERVER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), TEST_TYPE_CONNECTOR_SERVER)) #define TEST_IS_CONNECTOR_SERVER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), TEST_TYPE_CONNECTOR_SERVER)) #define TEST_CONNECTOR_SERVER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_CONNECTOR_SERVER, \ TestConnectorServerClass)) TestConnectorServer * test_connector_server_new (GIOStream *stream, gchar *mech, const gchar *user, const gchar *pass, const gchar *version, ConnectorProblem *problem, ServerProblem sasl_problem, CertSet cert); void test_connector_server_start (TestConnectorServer *self); void test_connector_server_set_other_host (TestConnectorServer *self, const gchar *host, guint port); void test_connector_server_teardown (TestConnectorServer *self, GAsyncReadyCallback callback, gpointer user_data); gboolean test_connector_server_teardown_finish (TestConnectorServer *self, GAsyncResult *result, GError *error); const gchar *test_connector_server_get_used_mech (TestConnectorServer *self); G_END_DECLS #endif /* #ifndef __TEST_CONNECTOR_SERVER_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/tests/test-resolver.h0000664000175000017500000000416611720661341025041 0ustar00cassidycassidy00000000000000/* * test-resolver.c - Source for TestResolver * Copyright © 2009 Collabora Ltd. * @author Vivek Dasmohapatra * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TEST_RESOLVER_H__ #define __TEST_RESOLVER_H__ #include #include G_BEGIN_DECLS GType test_resolver_get_type (void); #define TEST_TYPE_RESOLVER (test_resolver_get_type ()) #define TEST_RESOLVER(o) \ (G_TYPE_CHECK_INSTANCE_CAST ((o), TEST_TYPE_RESOLVER, TestResolver)) #define TEST_RESOLVER_CLASS(k) \ (G_TYPE_CHECK_CLASS_CAST((k), TEST_TYPE_RESOLVER, TestResolverClass)) #define TEST_IS_RESOLVER(o) \ (G_TYPE_CHECK_INSTANCE_TYPE ((o), TEST_TYPE_RESOLVER)) #define TEST_IS_RESOLVER_CLASS(k) \ (G_TYPE_CHECK_CLASS_TYPE ((k), TEST_TYPE_RESOLVER)) #define TEST_RESOLVER_GET_CLASS(o) \ (G_TYPE_INSTANCE_GET_CLASS ((o), TEST_TYPE_RESOLVER, TestResolverClass)) typedef struct { GResolver parent_instance; GResolver *real_resolver; GList *fake_A; GList *fake_SRV; } TestResolver; typedef struct { GResolverClass parent_class; } TestResolverClass; void test_resolver_reset (TestResolver *tr); gboolean test_resolver_add_A (TestResolver *tr, const char *hostname, const char *addr); gboolean test_resolver_add_SRV (TestResolver *tr, const char *service, const char *protocol, const char *domain, const char *addr, guint16 port); G_END_DECLS #endif /* __TEST_RESOLVER_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/tests/wocky-test-helper.h0000664000175000017500000000575212212322440025602 0ustar00cassidycassidy00000000000000#ifndef __WOCKY_TEST_HELPER_H__ #define __WOCKY_TEST_HELPER_H__ G_BEGIN_DECLS #include #include "wocky-test-stream.h" typedef struct { GMainLoop *loop; gboolean parsed_stanza; GQueue *expected_stanzas; WockyXmppConnection *in; WockyXmppConnection *out; WockyPorter *sched_in; WockyPorter *sched_out; WockySession *session_in; WockySession *session_out; WockyTestStream *stream; guint outstanding; GCancellable *cancellable; gulong timeout_id; } test_data_t; test_data_t * setup_test (void); test_data_t * setup_test_with_timeout (guint timeout); test_data_t * setup_test_with_jids (const gchar *in_jid, const gchar *out_jid); void teardown_test (test_data_t *data); void test_wait_pending (test_data_t *test); gboolean test_timeout_cb (gpointer data); void test_open_connection (test_data_t *test); void test_close_connection (test_data_t *test); void test_open_both_connections (test_data_t *test); void test_close_porter (test_data_t *test); void test_expected_stanza_received (test_data_t *test, WockyStanza *stanza); void test_close_both_porters (test_data_t *test); void test_cancel_in_idle (GCancellable *cancellable); #define test_assert_nodes_equal(n1, n2) \ G_STMT_START { \ if (!wocky_node_equal ((n1), (n2))) \ g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ g_strdup_printf ("Nodes not equal:\n%s\n\n%s", \ wocky_node_to_string (n1), \ wocky_node_to_string (n2))); \ } G_STMT_END #define test_assert_stanzas_equal(s1, s2) \ test_assert_nodes_equal (wocky_stanza_get_top_node (s1), \ wocky_stanza_get_top_node (s2)) #define test_assert_nodes_not_equal(n1, n2) \ G_STMT_START { \ if (wocky_node_equal ((n1), (n2))) \ g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ g_strdup_printf ("Nodes unexpectedly equal:\n%s\n\n%s", \ wocky_node_to_string (n1), \ wocky_node_to_string (n2))); \ } G_STMT_END #define test_assert_stanzas_not_equal(s1, s2) \ test_assert_nodes_not_equal (wocky_stanza_get_top_node (s1), \ wocky_stanza_get_top_node (s2)) /* Slightly evil macro that tests that two stanzas are equal, except that if * one has an id and the other does not this is not considered a difference. It * modifies the stanzas because I am lazy. */ #define test_assert_stanzas_equal_no_id(s1, s2) \ G_STMT_START { \ WockyNode *n1 = wocky_stanza_get_top_node (s1); \ WockyNode *n2 = wocky_stanza_get_top_node (s2); \ const gchar *_id1 = wocky_node_get_attribute (n1, "id"); \ const gchar *_id2 = wocky_node_get_attribute (n2, "id"); \ if (_id1 == NULL && _id2 != NULL) \ wocky_node_set_attribute (n1, "id", _id2); \ else if (_id1 != NULL && _id2 == NULL) \ wocky_node_set_attribute (n2, "id", _id1); \ test_assert_stanzas_equal (s1, s2); \ } G_STMT_END void test_init (int argc, char **argv); void test_deinit (void); G_END_DECLS #endif /* #ifndef __WOCKY_TEST_HELPER_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/m4/0000775000175000017500000000000012332445273021225 5ustar00cassidycassidy00000000000000telepathy-gabble-0.18.3/lib/ext/wocky/m4/Makefile.am0000644000175000017500000000004311544576223023260 0ustar00cassidycassidy00000000000000EXTRA_DIST = \ as-compiler-flag.m4 telepathy-gabble-0.18.3/lib/ext/wocky/m4/libtool.m40000644000175000017500000105756412332443661023152 0ustar00cassidycassidy00000000000000# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010, 2011 Free Software # Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool 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. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ]) # serial 57 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_CC_BASENAME(CC) # ------------------- # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. m4_defun([_LT_CC_BASENAME], [for cc_temp in $1""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from `configure', and `config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # `config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain="$ac_aux_dir/ltmain.sh" ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the `libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to `config.status' so that its # declaration there will have the same value as in `configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags="_LT_TAGS"dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the `libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into `config.status', and then the shell code to quote escape them in # for loops in `config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # `#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test $lt_write_fail = 0 && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ \`$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test $[#] != 0 do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try \`$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try \`$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test "$silent" = yes && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # _LT_COPYING _LT_LIBTOOL_TAGS # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) _LT_PROG_REPLACE_SHELLFNS mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test $_lt_result -eq 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS="$save_LDFLAGS" ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[[012]]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test "$lt_cv_ld_force_load" = "yes"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" m4_if([$1], [CXX], [ if test "$lt_cv_apple_cc_single_mod" != "yes"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script which will find a shell with a builtin # printf (which we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case "$ECHO" in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [ --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified).], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([${with_sysroot}]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and in which our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; *-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD="${LD-ld}_sol2" fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test x"[$]$2" = xyes; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" ]) if test x"[$]$2" = xyes; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n $lt_cv_sys_max_cmd_len ; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "$cross_compiling" = yes; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links="nottested" if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", [Define to the sub-directory in which libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existent directories. if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Add ABI-specific directories to the system library path. sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([], [sys_lib_dlsearch_path_spec], [2], [Run-time system search path for libraries]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program which can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program which can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi]) if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64 which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global defined # symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS="$save_LDFLAGS"]) if test "$lt_cv_irix_exported_symbol" = yes; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ;; esac fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting ${shlibpath_var} if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report which library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC="$lt_save_CC" ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GXX" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared # libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ func_to_tool_file "$lt_outputfile"~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; gnu*) ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd2*) # C++ shared libraries are fairly broken _LT_TAGVAR(ld_shlibs, $1)=no ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(GCC, $1)="$GXX" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test "$_lt_caught_CXX_error" != yes AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case ${prev}${p} in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" || test $p = "-R"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test "$pre_test_object_deps_done" = no; then case ${prev} in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)="${prev}${p}" else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)="$p" else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)="$p" else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test "X$F77" = "Xno"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_F77" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$G77" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" CFLAGS="$lt_save_CFLAGS" fi # test "$_lt_disable_F77" != yes AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test "X$FC" = "Xno"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_FC" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test "$_lt_disable_FC" != yes AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [AC_MSG_CHECKING([whether the shell understands some XSI constructs]) # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes AC_MSG_RESULT([$xsi_shell]) _LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) AC_MSG_CHECKING([whether the shell understands "+="]) lt_shell_append=no ( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes AC_MSG_RESULT([$lt_shell_append]) _LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) # ------------------------------------------------------ # In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and # '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. m4_defun([_LT_PROG_FUNCTION_REPLACE], [dnl { sed -e '/^$1 ()$/,/^} # $1 /c\ $1 ()\ {\ m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) } # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: ]) # _LT_PROG_REPLACE_SHELLFNS # ------------------------- # Replace existing portable implementations of several shell functions with # equivalent extended shell implementations where those features are available.. m4_defun([_LT_PROG_REPLACE_SHELLFNS], [if test x"$xsi_shell" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"}]) _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl func_split_long_opt_name=${1%%=*} func_split_long_opt_arg=${1#*=}]) _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) fi if test x"$lt_shell_append" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl func_quote_for_eval "${2}" dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) fi ]) # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine which file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS telepathy-gabble-0.18.3/lib/ext/wocky/m4/wocky-gcov.m40000644000175000017500000000267711544576223023575 0ustar00cassidycassidy00000000000000dnl Detect and set flags for gcov AC_DEFUN([WOCKY_GCOV], [ enable=$1 GCOV=`echo $CC | sed s/gcc/gcov/g` AC_CHECK_PROG(have_gcov, $GCOV, yes, no) AS_COMPILER_FLAG(["-fprofile-arcs"], [flag_profile_arcs=yes], [flag_profile_arcs=no]) AS_COMPILER_FLAG(["-ftest-coverage"], [flag_test_coverage=yes], [flag_test_coverage=no]) if test "x$enable" = xyes && test "x$GCC" = "xyes" && test "$flag_profile_arcs" = yes && test "$flag_test_coverage" = yes ; then GCOV_CFLAGS="$GCOV_CFLAGS -fprofile-arcs -ftest-coverage" dnl remove any -O flags - FIXME: is this needed ? GCOV_CFLAGS=`echo "$GCOV_CFLAGS" | sed -e 's/-O[[0-9]]*//g'` dnl libtool 1.5.22 and lower strip -fprofile-arcs from the flags dnl passed to the linker, which is a bug; -fprofile-arcs implicitly dnl links in -lgcov, so we do it explicitly here for the same effect GCOV_LIBS=-lgcov AC_SUBST([MOSTLYCLEANFILES], "*.bb *.bbg *.da *.gcov *.gcda *.gcno") AC_DEFINE_UNQUOTED(HAVE_GCOV, 1, [Defined if gcov is enabled to force a rebuild due to config.h changing]) CFLAGS="-O0" AC_SUBST(CFLAGS) CXXFLAGS="-O0" AC_SUBST(CXXFLAGS) FFLAGS="-O0" AC_SUBST(FFLAGS) CCASFLAGS="-O0" AC_SUBST(CCASFLAGS) AC_MSG_NOTICE([gcov enabled, setting CFLAGS and friends to $CFLAGS]) fi AC_SUBST(GCOV_CFLAGS) AC_SUBST(GCOV_LIBS) AC_SUBST(GCOV) AM_CONDITIONAL(HAVE_GCOV, test x$have_gcov = xyes) ]) telepathy-gabble-0.18.3/lib/ext/wocky/m4/lt~obsolete.m40000644000175000017500000001375612332443661024052 0ustar00cassidycassidy00000000000000# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) telepathy-gabble-0.18.3/lib/ext/wocky/m4/gtk-doc.m40000644000175000017500000000477212062651145023024 0ustar00cassidycassidy00000000000000dnl -*- mode: autoconf -*- # serial 1 dnl Usage: dnl GTK_DOC_CHECK([minimum-gtk-doc-version]) AC_DEFUN([GTK_DOC_CHECK], [ AC_REQUIRE([PKG_PROG_PKG_CONFIG]) AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first dnl check for tools we added during development AC_PATH_PROG([GTKDOC_CHECK],[gtkdoc-check]) AC_PATH_PROGS([GTKDOC_REBASE],[gtkdoc-rebase],[true]) AC_PATH_PROG([GTKDOC_MKPDF],[gtkdoc-mkpdf]) dnl for overriding the documentation installation directory AC_ARG_WITH([html-dir], AS_HELP_STRING([--with-html-dir=PATH], [path to installed docs]),, [with_html_dir='${datadir}/gtk-doc/html']) HTML_DIR="$with_html_dir" AC_SUBST([HTML_DIR]) dnl enable/disable documentation building AC_ARG_ENABLE([gtk-doc], AS_HELP_STRING([--enable-gtk-doc], [use gtk-doc to build documentation [[default=no]]]),, [enable_gtk_doc=no]) if test x$enable_gtk_doc = xyes; then ifelse([$1],[], [PKG_CHECK_EXISTS([gtk-doc],, AC_MSG_ERROR([gtk-doc not installed and --enable-gtk-doc requested]))], [PKG_CHECK_EXISTS([gtk-doc >= $1],, AC_MSG_ERROR([You need to have gtk-doc >= $1 installed to build $PACKAGE_NAME]))]) dnl don't check for glib if we build glib if test "x$PACKAGE_NAME" != "xglib"; then dnl don't fail if someone does not have glib PKG_CHECK_MODULES(GTKDOC_DEPS, glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0,,[:]) fi fi AC_MSG_CHECKING([whether to build gtk-doc documentation]) AC_MSG_RESULT($enable_gtk_doc) dnl enable/disable output formats AC_ARG_ENABLE([gtk-doc-html], AS_HELP_STRING([--enable-gtk-doc-html], [build documentation in html format [[default=yes]]]),, [enable_gtk_doc_html=yes]) AC_ARG_ENABLE([gtk-doc-pdf], AS_HELP_STRING([--enable-gtk-doc-pdf], [build documentation in pdf format [[default=no]]]),, [enable_gtk_doc_pdf=no]) if test -z "$GTKDOC_MKPDF"; then enable_gtk_doc_pdf=no fi if test -z "$AM_DEFAULT_VERBOSITY"; then AM_DEFAULT_VERBOSITY=1 fi AC_SUBST([AM_DEFAULT_VERBOSITY]) AM_CONDITIONAL([ENABLE_GTK_DOC], [test x$enable_gtk_doc = xyes]) AM_CONDITIONAL([GTK_DOC_BUILD_HTML], [test x$enable_gtk_doc_html = xyes]) AM_CONDITIONAL([GTK_DOC_BUILD_PDF], [test x$enable_gtk_doc_pdf = xyes]) AM_CONDITIONAL([GTK_DOC_USE_LIBTOOL], [test -n "$LIBTOOL"]) AM_CONDITIONAL([GTK_DOC_USE_REBASE], [test -n "$GTKDOC_REBASE"]) ]) telepathy-gabble-0.18.3/lib/ext/wocky/m4/ltversion.m40000644000175000017500000000126212332443661023512 0ustar00cassidycassidy00000000000000# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 3337 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.2]) m4_define([LT_PACKAGE_REVISION], [1.3337]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.2' macro_revision='1.3337' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) telepathy-gabble-0.18.3/lib/ext/wocky/m4/ltoptions.m40000644000175000017500000003007312332443661023522 0ustar00cassidycassidy00000000000000# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, # Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 7 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option `$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl `shared' nor `disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the `shared' and # `disable-shared' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the `static' and # `disable-static' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the `fast-install' # and `disable-fast-install' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the `pic-only' and `no-pic' # LT_INIT options. # MODE is either `yes' or `no'. If omitted, it defaults to `both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for lt_pkg in $withval; do IFS="$lt_save_ifs" if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS="$lt_save_ifs" ;; esac], [pic_mode=default]) test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) telepathy-gabble-0.18.3/lib/ext/wocky/m4/as-compiler-flag.m40000644000175000017500000000136311544576223024616 0ustar00cassidycassidy00000000000000dnl as-compiler-flag.m4 0.1.0 dnl autostars m4 macro for detection of compiler flags dnl David Schleef dnl $Id: as-compiler-flag.m4,v 1.1 2005/06/18 18:02:46 burgerman Exp $ dnl AS_COMPILER_FLAG(CFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED]) dnl Tries to compile with the given CFLAGS. dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags, dnl and ACTION-IF-NOT-ACCEPTED otherwise. AC_DEFUN([AS_COMPILER_FLAG], [ AC_MSG_CHECKING([to see if compiler understands $1]) save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $1" AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no]) CFLAGS="$save_CFLAGS" if test "X$flag_ok" = Xyes ; then $2 true else $3 true fi AC_MSG_RESULT([$flag_ok]) ]) telepathy-gabble-0.18.3/lib/ext/wocky/m4/wocky-lcov.m40000644000175000017500000000104211544576223023563 0ustar00cassidycassidy00000000000000dnl Check for lcov utility AC_DEFUN([WOCKY_LCOV], [ enable=$1 AC_CHECK_PROGS(LCOV_PATH, lcov) if test -n "$LCOV_PATH" ; then AC_MSG_CHECKING([whether lcov accepts --compat-libtool]) if $LCOV_PATH --compat-libtool --help > /dev/null 2>&1 ; then AC_MSG_RESULT(ok) else AC_MSG_RESULT(no) AC_MSG_WARN([lcov option --compat-libtool is not supported]) AC_MSG_WARN([update lcov to version > 1.5]) LCOV_PATH="" fi fi AM_CONDITIONAL(HAVE_LCOV, test -n "$LCOV_PATH" && test "x$enable" = xyes) ]) telepathy-gabble-0.18.3/lib/ext/wocky/m4/ltsugar.m40000644000175000017500000001042412332443661023146 0ustar00cassidycassidy00000000000000# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59 which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) telepathy-gabble-0.18.3/lib/ext/wocky/m4/tp-compiler-flag.m40000644000175000017500000000170411544576223024635 0ustar00cassidycassidy00000000000000dnl A version of AS_COMPILER_FLAG that supports both C and C++. dnl Based on: dnl as-compiler-flag.m4 0.1.0 dnl autostars m4 macro for detection of compiler flags dnl David Schleef dnl $Id: as-compiler-flag.m4,v 1.1 2005/06/18 18:02:46 burgerman Exp $ dnl TP_COMPILER_FLAG(CFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED]) dnl Tries to compile with the given CFLAGS and CXXFLAGS. dnl dnl Runs ACTION-IF-ACCEPTED if the compiler for the currently selected dnl AC_LANG can compile with the flags, and ACTION-IF-NOT-ACCEPTED otherwise. AC_DEFUN([TP_COMPILER_FLAG], [ AC_MSG_CHECKING([to see if compiler understands $1]) save_CFLAGS="$CFLAGS" save_CXXFLAGS="$CXXFLAGS" CFLAGS="$CFLAGS $1" CXXFLAGS="$CXXFLAGS $1" AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no]) CFLAGS="$save_CFLAGS" CXXFLAGS="$save_CXXFLAGS" if test "X$flag_ok" = Xyes ; then $2 true else $3 true fi AC_MSG_RESULT([$flag_ok]) ]) telepathy-gabble-0.18.3/lib/ext/wocky/m4/Makefile.in0000664000175000017500000003171112332443664023277 0ustar00cassidycassidy00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = m4 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/as-compiler-flag.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/tp-compiler-flag.m4 \ $(top_srcdir)/m4/tp-compiler-warnings.m4 \ $(top_srcdir)/m4/wocky-gcov.m4 $(top_srcdir)/m4/wocky-lcov.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_CODING_STYLE_CHECKS = @ENABLE_CODING_STYLE_CHECKS@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ FFLAGS = @FFLAGS@ FGREP = @FGREP@ GCOV = @GCOV@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_LIBS = @GCOV_LIBS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_FOR_STREAM_CIPHERS_CFLAGS = @GNUTLS_FOR_STREAM_CIPHERS_CFLAGS@ GNUTLS_FOR_STREAM_CIPHERS_LIBS = @GNUTLS_FOR_STREAM_CIPHERS_LIBS@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HEADER_DIR = @HEADER_DIR@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LCOV_PATH = @LCOV_PATH@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBIPHB_CFLAGS = @LIBIPHB_CFLAGS@ LIBIPHB_LIBS = @LIBIPHB_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSASL2_CFLAGS = @LIBSASL2_CFLAGS@ LIBSASL2_LIBS = @LIBSASL2_LIBS@ LIBTOOL = @LIBTOOL@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MOSTLYCLEANFILES = @MOSTLYCLEANFILES@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHARED_SUFFIX = @SHARED_SUFFIX@ SHELL = @SHELL@ SOUP_CFLAGS = @SOUP_CFLAGS@ SOUP_LIBS = @SOUP_LIBS@ SQLITE_CFLAGS = @SQLITE_CFLAGS@ SQLITE_LIBS = @SQLITE_LIBS@ STRIP = @STRIP@ TLS_CFLAGS = @TLS_CFLAGS@ TLS_LIBS = @TLS_LIBS@ VERSION = @VERSION@ WOCKY_CFLAGS = @WOCKY_CFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ have_gcov = @have_gcov@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ as-compiler-flag.m4 all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu m4/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu m4/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: telepathy-gabble-0.18.3/lib/ext/wocky/m4/tp-compiler-warnings.m40000644000175000017500000000240111544576223025547 0ustar00cassidycassidy00000000000000dnl TP_COMPILER_WARNINGS(VARIABLE, WERROR_BY_DEFAULT, DESIRABLE, UNDESIRABLE) dnl $1 (VARIABLE): the variable to put flags into dnl $2 (WERROR_BY_DEFAULT): a command returning true if -Werror should be the dnl default dnl $3 (DESIRABLE): warning flags we want (e.g. all extra shadow) dnl $4 (UNDESIRABLE): warning flags we don't want (e.g. dnl missing-field-initializers unused-parameter) AC_DEFUN([TP_COMPILER_WARNINGS], [ AC_REQUIRE([AC_ARG_ENABLE])dnl AC_REQUIRE([AC_HELP_STRING])dnl AC_REQUIRE([TP_COMPILER_FLAG])dnl tp_warnings="" for tp_flag in $3; do TP_COMPILER_FLAG([-W$tp_flag], [tp_warnings="$tp_warnings -W$tp_flag"]) done tp_error_flags="-Werror" TP_COMPILER_FLAG([-Werror], [tp_werror=yes], [tp_werror=no]) for tp_flag in $4; do TP_COMPILER_FLAG([-Wno-$tp_flag], [tp_warnings="$tp_warnings -Wno-$tp_flag"]) TP_COMPILER_FLAG([-Wno-error=$tp_flag], [tp_error_flags="$tp_error_flags -Wno-error=$tp_flag"], [tp_werror=no]) done AC_ARG_ENABLE([Werror], AC_HELP_STRING([--disable-Werror], [compile without -Werror (normally enabled in development builds)]), tp_werror=$enableval, :) if test "x$tp_werror" = xyes && $2; then $1="$tp_warnings $tp_error_flags" else $1="$tp_warnings" fi ]) telepathy-gabble-0.18.3/lib/ext/wocky/install-sh0000755000175000017500000003325512332443664022721 0ustar00cassidycassidy00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2011-11-20.07; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: telepathy-gabble-0.18.3/lib/ext/wocky/config.sub0000755000175000017500000010550312332443664022674 0ustar00cassidycassidy00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012, 2013 Free Software Foundation, Inc. timestamp='2012-12-29' # This file 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 3 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, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches with a ChangeLog entry to config-patches@gnu.org. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 \ | ns16k | ns32k \ | open8 \ | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i386-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-* | ppc64p7-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: telepathy-gabble-0.18.3/lib/ext/wocky/ChangeLog0000644000175000017500000361127412332445274022474 0ustar00cassidycassidy00000000000000commit f58bf0bb331a736b4a282452f70ca409de3fac7d Author: Guillaume Desmottes Date: Wed May 7 14:25:33 2014 +0200 wocky-jingle-info: don't try using self if it's NULL This callback can deal with self being destroyed but it was trying to access self->priv before early returning. wocky/wocky-jingle-info.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) commit 0db9f32fd023fc728abf1780c26b957102c3292e Author: Simon McVittie Date: Wed Mar 19 12:16:14 2014 +0000 data-form: reformat blocks so recent gtk-doc can cope Recent (Markdown-based) gtk-doc doesn't like spanning more than one line, causing a build failure. Reviewed-by: Guillaume Desmottes wocky/wocky-data-form.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) commit 4914050394b62b197e69f065962dafa8d27d8fcc Author: Guillaume Desmottes Date: Fri Feb 14 11:47:10 2014 +0100 jingle-content: reset idle ID in its callback The callback returns FALSE so the source will be invalidated. Recent GLib now raises a critical when attempting to remove an invalid ID, making some jingle tests failing. (cherry picked from commit 01fbaec365cc58d6f3de46ce3f54f6413f3ec0f9) wocky/wocky-jingle-content.c | 2 ++ 1 file changed, 2 insertions(+) commit 677b984c434b31483e1348069e1463d963b077e1 Author: David Edmundson Date: Mon Sep 2 01:32:14 2013 +0000 If we send an IQ to a server allow "from" to be empty wocky/wocky-c2s-porter.c | 10 ++++++++++ 1 file changed, 10 insertions(+) commit d7b1e68d8ef5249d3bce5de45d4fb882c399435a Author: Simon McVittie Date: Fri Aug 9 16:08:15 2013 +0100 Fix examples' and tests' dependencies All Automake products automatically depend on their SOURCES and everything identifiable as a file in their LDADD, unless you set their DEPENDENCIES, which take precedence (and have "replace", not "add", semantics). As a result, setting DEPENDENCIES is actually harmful here: it makes the tests and examples not depend on their own source code! For the one test that has non-trivial extra dependencies, use EXTRA_x_DEPENDENCIES, which has the desired semantics. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=67953 Signed-off-by: Simon McVittie Reviewed-by: Vivek Dasmohapatra examples/Makefile.am | 5 ----- tests/Makefile.am | 30 +----------------------------- 2 files changed, 1 insertion(+), 34 deletions(-) commit 8a21c43636459138bac752ed87329ef086ba9bc8 Author: Simon McVittie Date: Thu Aug 8 17:48:54 2013 +0100 Tests: don't assume that other things can sneak in ahead of cancellation The porter test asserted that if you cancelled the sending of a stanza after it had already been (sent and) received, the send reported success, not cancellation; and the SASL auth test asserted that if you closed a connection at around the same time that a cancellable had been cancelled, the close reported success, not cancellation. However, recent GLib seems to be either more careful about deferring the results of async operations to an idle, or more consistent about reporting the cancellation as an error even if the operation's success had already been recorded. As a result, these operations reported cancellation. To avoid that, delay the cancellation a little. [Mike Ruprecht clarified on IRC that "more consistent about reporting the cancellation as an error" is one of the changes from GIO being ported to GTask in 2.36. -smcv] Bug: https://bugs.freedesktop.org/show_bug.cgi?id=67900 Signed-off-by: Simon McVittie Reviewed-by: Vivek Dasmohapatra tests/Makefile.am | 2 ++ tests/wocky-porter-test.c | 2 +- tests/wocky-test-helper.c | 16 ++++++++++++++++ tests/wocky-test-helper.h | 2 ++ tests/wocky-test-sasl-auth-server.c | 6 ++---- 5 files changed, 23 insertions(+), 5 deletions(-) commit 27aafa9b9398fce336be2b22d3ebe3fbd82c0f05 Author: Simon McVittie Date: Thu Aug 8 17:43:17 2013 +0100 wocky-dummy-xmpp-server: don't turn off non-blocking on the socket The very next thing we did with it was to give it to GSocketConnection, which would turn on non-blocking again; so this code wasn't doing anything except harming our portability. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=67900 Signed-off-by: Simon McVittie Reviewed-by: Vivek Dasmohapatra tests/wocky-dummy-xmpp-server.c | 4 ---- 1 file changed, 4 deletions(-) commit 8aab0cf5ded07ef59a0f381cccd9c8a437bd61b5 Author: Simon McVittie Date: Thu Aug 8 17:41:50 2013 +0100 wocky-xmpp-reader-test: don't assume non-characters will be replaced GLib now follows Unicode Corrigendum 9, which clarifies that libraries shouldn't prohibit non-characters. We were assuming it did. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=67900 Signed-off-by: Simon McVittie Reviewed-by: Vivek Dasmohapatra tests/wocky-xmpp-reader-test.c | 43 +++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) commit b30fd16a74865c371b32f89a7a304005d7d4881f Author: Simon McVittie Date: Thu Aug 8 16:50:11 2013 +0100 wocky-connector-test: stop putting sockets in blocking mode GSocket configures its underlying fd to be in non-blocking mode, and implements blocking calls by select()ing (or equivalent) first. If we break this assumption, most test cases in wocky-connector-test hang in a recv() that should have been non-blocking. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=67900 Signed-off-by: Simon McVittie Reviewed-by: Vivek Dasmohapatra tests/wocky-connector-test.c | 13 ------------- 1 file changed, 13 deletions(-) commit 21d2afd4981fb07ecde77b86b6cc997294950f29 Author: Simon McVittie Date: Wed Aug 7 18:59:27 2013 +0100 docs: expect wocky-jingle-*.xml to be generated, not jingle-*.xml I'm not sure whether this ever worked correctly, but the build currently fails on Debian unstable, and this fixes it. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=67875 Signed-off-by: Simon McVittie Reviewed-by: Guillaume Desmottes docs/reference/wocky-docs.sgml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) commit 7f139058d3323d99b11667f93cb4abcb3ccc9c4d Author: Simon McVittie Date: Mon Jun 3 10:54:16 2013 +0100 WockyJingleSession: check more preconditions in public API Some were already checked, but as assertions: this is (now) public library API, so downgrade to g_return_if_fail(). Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65131 Signed-off-by: Simon McVittie Reviewed-by: Xavier Claessens wocky/wocky-jingle-session.c | 88 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 73 insertions(+), 15 deletions(-) commit 92700fd33acbe264f1794cf0f3a39d3ad5692ccf Author: Simon McVittie Date: Mon Jun 3 10:38:04 2013 +0100 WockyJingleFactory: ref session while calling parse() wocky_jingle_session_parse() advances the session's state machine. In particular, it may cause termination, which causes the session to be removed from the factory's hash table, which may cause its last ref to be released. Until recently, this would have gone unnoticed, but wocky_jingle_session_acknowledge_iq() now emits a signal from the session (to check whether it has the "is Google webmail" quirk), and that causes a check that it is in fact still a valid session object. Also correct a misleading comment spotted while debugging this: priv->sessions owns both key and sess. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65131 Signed-off-by: Simon McVittie Reviewed-by: Xavier Claessens wocky/wocky-jingle-factory.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) commit 0561059639160cbd11e1764ef861348c0c23831c Author: Simon McVittie Date: Thu May 30 16:38:35 2013 +0100 Acknowledge Jingle IQs in a way that the Google webmail client likes The Google webmail client currently starts calls like this: ... ... (This isn't valid XMPP Core, because 'An IQ stanza of type "get" or "set" MUST contain exactly one child element', but we can tolerate it.) When called, it also echoes the contents of the sender's IQ back to the sender. It appears that this is how, when it makes an outgoing call, it determines which dialect the recipient wants to use: the recipient echoes the appropriate child element. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65131 Reviewed-by: Xavier Claessens wocky/wocky-jingle-factory.c | 2 +- wocky/wocky-jingle-session.c | 73 +++++++++++++++++++++++++++++++++++++++----- wocky/wocky-jingle-session.h | 3 ++ 3 files changed, 70 insertions(+), 8 deletions(-) commit b7a89063d05ccdd361d309b8d9df845f186102d6 Author: Simon McVittie Date: Thu May 30 16:37:35 2013 +0100 Require GLib 2.32 This avoids compilation failing because the new(ish) g_thread_new wasn't available in our target version. telepathy-gabble indirectly depends on GLib 2.32 anyway, via telepathy-glib 0.20. Reviewed-by: Xavier Claessens configure.ac | 8 ++++---- tests/wocky-connector-test.c | 5 ----- tests/wocky-dummy-xmpp-server.c | 4 ---- tests/wocky-http-proxy-test.c | 4 ---- tests/wocky-sasl-utils-test.c | 4 ---- tests/wocky-test-helper.c | 4 ---- wocky/wocky-uninstalled.pc.in | 2 +- wocky/wocky.pc.in | 2 +- 8 files changed, 6 insertions(+), 27 deletions(-) commit d6c995608d4840df2bef38a5baf8e5b0f90915f8 Merge: cb1aa11 ff317a2 Author: Simon McVittie Date: Thu May 30 12:52:49 2013 +0100 Merge branch 'gabble-0.16' commit ff317a2783058e8e90fac21bd8ba18359c5401f9 Author: Simon McVittie Date: Mon May 27 13:16:22 2013 +0100 CVE-2013-1431: respect tls-required flag on legacy Jabber servers It's checked elsewhere for XMPP 1.0 servers, which can either use "old SSL" or perform STARTTLS. Legacy Jabber can only use "old SSL", which is similar to https - connect to a separate port, typically 5223, and start speaking SSL - so if the connection was ever going to be encrypted, by this point it already would be. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65036 Reviewed-by: Sjoerd Simons wocky/wocky-connector.c | 3 +++ 1 file changed, 3 insertions(+) commit cb1aa11735d309a75377d2ab2134ea7cd166417e Author: Will Thompson Date: Thu Mar 21 16:01:49 2013 +0000 Make examples/Makefile.am indentation consistent examples/Makefile.am | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) commit ddb6ec63fa948164e34003aff0304d0f946d1adf Author: Will Thompson Date: Thu Mar 21 16:01:00 2013 +0000 dump-certificates: check (and fix) coding style examples/Makefile.am | 4 +++- examples/dump-certificates.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) commit 8c8360c7d6e85db1d64025b058b4b215ecee22a1 Author: Will Thompson Date: Tue Feb 26 10:22:49 2013 +0000 Regression tests for malformed FORM_TYPE crashes These pass because 565f2ed54. tests/wocky-caps-hash-test.c | 126 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) commit 492b2320150635141ffe36e47e17376f6fc239aa Author: Will Thompson Date: Mon Feb 25 09:37:55 2013 +0000 Regression test for hashing anonymous fields https://bugs.freedesktop.org/show_bug.cgi?id=61433 tests/wocky-caps-hash-test.c | 47 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) commit d739d2e14952a1e75571de7839827d73f9568df4 Author: Dominique Leuenberger Date: Fri Mar 15 19:33:30 2013 +0100 examples: link against gnutls Bug: https://bugs.freedesktop.org/show_bug.cgi?id=61792 Reviewed-by: Simon McVittie examples/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) commit 9ea3d83bd6a191a4964cfa5cb92eb3720556d2f6 Author: Will Thompson Date: Fri Mar 1 16:45:22 2013 +0000 Fix enumtype generation in out-of-tree builds wocky/Makefile.am | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) commit d822581db0752351850b7e7ddfe3e70008897a5b Merge: e77ed03 565f2ed Author: Will Thompson Date: Fri Mar 1 15:04:11 2013 +0000 Merge branch 'gabble-0.16' commit 565f2ed54f53adc7bd6793a0e746ceb349843408 Author: Will Thompson Date: Tue Feb 26 10:18:37 2013 +0000 caps_hash: don't crash if FORM_TYPE has no Previously there were a couple of ways this could crash: * First, if you had a with no child, field->default_value would be NULL so g_value_get_string (field->default_value) would critical and return NULL and then you'll be in undefined hell. * Having fixed that, the code to sort data forms by FORM_TYPE would also crash because it happens before the FORM_TYPEs have been validated and used g_value_get_string() without checking and then strcmp()ed the possibly-NULL result. I actually have a work-in-progress branch that makes this all a lot less hairy by adding, among other things, a wocky_data_form_get_form_type() function which can do the validation for us. But better to fix the crashes before refactoring them away. https://bugs.freedesktop.org/show_bug.cgi?id=61433 wocky/wocky-caps-hash.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) commit 3e17bf71aa47e7fe52c7053ec5cf44836cf5bd03 Author: Will Thompson Date: Mon Feb 25 09:35:13 2013 +0000 caps_hash_compute_from_lists: skip anonymous fields https://bugs.freedesktop.org/show_bug.cgi?id=61433 wocky/wocky-caps-hash.c | 8 ++++++++ 1 file changed, 8 insertions(+) commit 099f5b1c7119d2d7d81970958fc8b8d19e3fc5e8 Author: Will Thompson Date: Mon Feb 25 09:32:27 2013 +0000 wocky_data_form_field_cmp: cope with var being NULL https://bugs.freedesktop.org/show_bug.cgi?id=61433 wocky/wocky-data-form.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit e77ed03f870529c027b5abe98cd7f4620a063995 Author: Will Thompson Date: Fri Feb 22 18:40:15 2013 +0000 WockyConnector: reduce duplicated code to complete result Notice that some of the paths set priv->result to NULL before completing it, and some do not. I particularly like the one in establish_session_recv_cb which assigns priv->result to a tmp variable but forgets to set priv->result to NULL! I hoped this would make the connector re-usable between successful connection attempts, but it doesn't because priv->conn is not cleared out so it crashes when the stream is establed the second time you call wocky_connector_connect_async(). At least all the code paths crash consistently now, though! (Previously if you had connected to a pre-XMPP Jabber server, wocky_connector_connect_async() did not immediately reject a second call and would crash later in the same way this now does.) wocky/wocky-connector.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) commit f236fff2b16dd135b025c7291ae4383b945bcc4e Author: Will Thompson Date: Fri Feb 22 10:41:46 2013 +0000 connector-test: use properly-named variables. This made the assertion that failed confusing: the message was about 'identity', but it was actually a test of the 'resource' property. tests/wocky-connector-test.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) commit 57fa65482d32721a31403c8f09af8ea6ee431a6f Author: Will Thompson Date: Fri Feb 22 10:38:36 2013 +0000 Fix wocky-connector-test I changed the default value for WockyConnector:resource to NULL in 5fb069a, but didn't update the test accordingly. tests/wocky-connector-test.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit 883cd456c08964d01d323a6cfc1590ce858ea653 Author: Will Thompson Date: Fri Feb 22 10:29:30 2013 +0000 receive-messages example: add a --resource parameter examples/receive-messages.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) commit 5fb069a253550389704912c8c11e5291b72ee168 Author: Will Thompson Date: Fri Feb 22 10:28:01 2013 +0000 Connector: don't try to generate a random resource Previously, there was no way to leave the resource entirely up to the server: while the binding code deals correctly with priv->resource being NULL, it was impossible to make it NULL. But the random resource generation was broken, too: the RNG was never seeded so the resource always came out the same. wocky/wocky-connector.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) commit 0fc8f511683054634d7ba5d447e38a634400eebb Author: Will Thompson Date: Wed Feb 20 08:51:50 2013 +0000 muc: include GError and type in both error signals wocky/wocky-muc.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) commit 7ca0eac40f543bdd75eb18a29cf2d0cbaed40ff6 Author: Will Thompson Date: Wed Feb 20 08:38:53 2013 +0000 WockyXmppError: update to RFC 6120 The changes are: * payment-required is removed; * not-authorized is added to the schema (it was already defined in Wocky); * policy-violation is added. XEP-0086 doesn't define an error code mapping for it, so I chose 406 "Not Acceptable". wocky/wocky-xmpp-error.c | 10 ++++++++++ wocky/wocky-xmpp-error.h | 20 ++++++++++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) commit b2e1a6d147a3931190e2d328feb1f5c62e6ac7d8 Author: Will Thompson Date: Wed Feb 20 08:19:37 2013 +0000 Correctly extract type='' from unrecognised errors tests/wocky-stanza-test.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-error.c | 12 ++++++++++-- 2 files changed, 58 insertions(+), 2 deletions(-) commit a904ca719ee560fc0b81b58a8a14efa0c181b9d4 Author: Will Thompson Date: Wed Feb 20 08:19:07 2013 +0000 tests: define bug base in test_init(). tests/wocky-porter-test.c | 1 - tests/wocky-test-helper.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) commit 15900dd582e17cb1951dea92e8b6c7b9409cf63c Author: Will Thompson Date: Fri Feb 15 17:15:22 2013 +0000 muc: remove prototypes for nonexistant initiate_{async,finish} wocky/wocky-muc.h | 10 ---------- 1 file changed, 10 deletions(-) commit 34ceef43a3ada2cbe043a8f7ab8448bf0ab912f0 Author: Will Thompson Date: Fri Feb 15 17:14:46 2013 +0000 Muc: document a load of things Lots of the signals had inline comments describing their parameter lists, but no gtk-doc comments. wocky/wocky-muc.c | 174 +++++++++++++++++++++++++++++++++++++++++++++--------- wocky/wocky-muc.h | 4 +- 2 files changed, 148 insertions(+), 30 deletions(-) commit 827a5df6ab791a86fa0c446ac24e84b3b376f118 Author: Will Thompson Date: Thu Feb 14 22:29:19 2013 +0000 Make (more of) WockyMuc docs appear Astonishingly, putting the instance struct before the class struct makes WockyMuc's signals and properties show up in the generated documentation. wocky/wocky-muc.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) commit df148442015e6121e6ea50675c7068dcd478fd6a Author: Will Thompson Date: Wed Feb 13 18:48:09 2013 +0000 Add vcard namespace constants. wocky/wocky-namespaces.h | 2 ++ 1 file changed, 2 insertions(+) commit 57085645d2c21c042961ed79fc02408e9d5f4c3b Author: Will Thompson Date: Wed Feb 13 18:43:15 2013 +0000 Fix reference to wocky_porter_register_handler() This was renamed to wocky_porter_register_handler_from(), but its documentation was not updated. Also, the arguments to the function were wrong: there was a NULL where the JID should be, and the JID appeared later in the wrong place. While we're here, fix some formatting earlier on in the same comment. I think using @ rather than the trick is more legible. wocky/wocky-porter.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) commit 795a6501309814bc3a8476975bb2baf9bc86a4fa Author: Will Thompson Date: Wed Feb 13 18:33:16 2013 +0000 Fix docs for plural WockyStanzas wocky/wocky-connector.c | 2 +- wocky/wocky-xmpp-connection.c | 2 +- wocky/wocky-xmpp-writer.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) commit b02a6be37011696d9416d5debf6af21ece98d3bd Author: Will Thompson Date: Tue Jan 22 16:22:27 2013 +0000 connector-test: avoid using system-wide CAs This shouldn't affect the outcome of the tests, because we don't check with any certificates signed by system-wide CAs. But just for completeness... Reviewed-by: Sjoerd Simons tests/wocky-connector-test.c | 4 ++++ 1 file changed, 4 insertions(+) commit d3d17080b3f355ba1d0962e7a6fd087302605b20 Author: Will Thompson Date: Tue Jan 22 16:16:43 2013 +0000 TLSHandler: improve documentation. Reviewed-by: Sjoerd Simons wocky/wocky-tls-handler.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) commit f00bb950ec980a13bcf478b6495c1ed46f3df39b Author: Will Thompson Date: Tue Jan 22 16:08:04 2013 +0000 examples: add --ignore-ssl-errors Just for the sake of people testing against localhost. Reviewed-by: Sjoerd Simons examples/receive-messages.c | 29 ++++++++++++++++++++++++++--- examples/send-message.c | 29 ++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 6 deletions(-) commit 5a1095c725d9f549c8cbb70f87509287f83b004d Author: Will Thompson Date: Tue Jan 22 15:58:27 2013 +0000 TLSHandler: add API to forget all CA paths Now that Wocky uses the system-wide CA path by default, let's provide a way to turn that off if you have some weird requirement. Reviewed-by: Sjoerd Simons wocky/wocky-tls-handler.c | 18 ++++++++++++++++++ wocky/wocky-tls-handler.h | 1 + 2 files changed, 19 insertions(+) commit d0dfb66907dbcd9a3bf732b0bda96ee233847b6d Author: Will Thompson Date: Tue Jan 22 15:56:35 2013 +0000 Find and use a sensible default CA certificate path This is taken from Gabble, and makes Wocky's certificate checking work out of the box. Reviewed-by: Sjoerd Simons configure.ac | 36 ++++++++++++++++++++++++++++++++++++ wocky/wocky-tls-handler.c | 23 ++++++++++++----------- 2 files changed, 48 insertions(+), 11 deletions(-) commit 7958dac78b8b1035197ce2ec3e1d2a517322c1b1 Author: Will Thompson Date: Tue Jan 22 15:01:59 2013 +0000 dump-certificates: remove "bye, bye" from output Reviewed-by: Sjoerd Simons examples/dump-certificates.c | 1 - 1 file changed, 1 deletion(-) commit c7add406d1328b148f8bd8c2355b7000b6bc06fb Author: Will Thompson Date: Tue Jan 22 11:51:27 2013 +0000 TLSConnector, TLSHandler: don't ignore SSL errors by default If you don't specify a WockyTLSHandler for your WockyConnector, then WockyTLSConnector creates one for itself. Previously, it defaulted to silently ignoring SSL errors. Whoops. Gabble is not affected by this issue, because it provides its own TLSHandler, and it defaults to telling it to fail on SSL errors. Reviewed-by: Sjoerd Simons wocky/wocky-tls-connector.c | 2 +- wocky/wocky-tls-handler.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) commit e6e1d6378304d747310efea4c3543822470b500a Author: Will Thompson Date: Fri Jan 18 11:46:39 2013 +0000 Improve wocky_{decode,compose}_jid documentation These days, JIDs are defined in RFC 6122. wocky/wocky-utils.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) commit a38dbe13ebf4eef59fbd1a868464987e204ea609 Author: Will Thompson Date: Wed Jan 16 10:55:10 2013 +0000 Fix filenames in jingle headers to include wocky- prefix This makes no functional difference, of course. wocky/wocky-jingle-content.h | 2 +- wocky/wocky-jingle-factory.c | 2 +- wocky/wocky-jingle-factory.h | 2 +- wocky/wocky-jingle-info-internal.h | 2 +- wocky/wocky-jingle-info.c | 2 +- wocky/wocky-jingle-info.h | 2 +- wocky/wocky-jingle-media-rtp.c | 2 +- wocky/wocky-jingle-media-rtp.h | 2 +- wocky/wocky-jingle-session.h | 2 +- wocky/wocky-jingle-transport-google.c | 2 +- wocky/wocky-jingle-transport-google.h | 2 +- wocky/wocky-jingle-transport-iceudp.c | 2 +- wocky/wocky-jingle-transport-iceudp.h | 2 +- wocky/wocky-jingle-transport-iface.c | 2 +- wocky/wocky-jingle-transport-iface.h | 2 +- wocky/wocky-jingle-transport-rawudp.c | 2 +- wocky/wocky-jingle-transport-rawudp.h | 2 +- wocky/wocky-jingle-types.h | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) commit e9f10f8d0d738fa105499813655ac479df3ef2db Author: Will Thompson Date: Wed Jan 16 10:53:25 2013 +0000 Replace more references to Gabble in Jingle code. Jonny says: > I did a git grep -i gabble in your wocky tree and there are loads of > references that probably shouldn't be around anymore, like header > guards, comments listing the filename as gabble-jingle-session.c and > stuff like that. It would be nicer to have less of this. wocky/wocky-google-relay.h | 6 +++--- wocky/wocky-jingle-content.c | 2 +- wocky/wocky-jingle-media-rtp.c | 3 ++- wocky/wocky-jingle-session.c | 4 ++-- wocky/wocky-jingle-types.h | 6 +++--- 5 files changed, 11 insertions(+), 10 deletions(-) commit 94f17c60447ef09cc48428e56e9646284de28ead Author: Will Thompson Date: Wed Jan 16 10:27:28 2013 +0000 Add Jingle headers to wocky.h Some of the Jingle code itself included wocky.h, which led to include loops and sadness, so I've changed that too. I also added WOCKY_H_INSIDE and WOCKY_COMPILATION guards to the Jingle headers. wocky/wocky-google-relay.h | 3 +++ wocky/wocky-jingle-content.c | 1 + wocky/wocky-jingle-content.h | 3 +++ wocky/wocky-jingle-factory.c | 4 ++-- wocky/wocky-jingle-factory.h | 3 +++ wocky/wocky-jingle-info-internal.h | 3 +++ wocky/wocky-jingle-info.c | 2 ++ wocky/wocky-jingle-info.h | 5 ++++- wocky/wocky-jingle-media-rtp.c | 1 + wocky/wocky-jingle-media-rtp.h | 3 +++ wocky/wocky-jingle-session.c | 4 ++-- wocky/wocky-jingle-session.h | 4 +++- wocky/wocky-jingle-transport-google.c | 1 + wocky/wocky-jingle-transport-google.h | 3 +++ wocky/wocky-jingle-transport-iceudp.c | 1 + wocky/wocky-jingle-transport-iceudp.h | 3 +++ wocky/wocky-jingle-transport-iface.h | 4 +++- wocky/wocky-jingle-transport-rawudp.h | 3 +++ wocky/wocky-jingle-types.h | 3 +++ wocky/wocky.h | 10 ++++++++++ 20 files changed, 57 insertions(+), 7 deletions(-) commit 0d4741e43ae46e56a59231aacfbabef029309e0b Author: Will Thompson Date: Wed Jan 16 09:59:19 2013 +0000 Prefix jingle-related files with wocky- Jonny said on : > I see you've moved this stuff into wocky/jingle-*.[ch]. Although I > hate the "wocky-" prefix as much as anyone else, I think inconsistency > is even worse. What are your thoughts on this? I think he is correct. wocky/Makefile.am | 48 +- wocky/google-relay.c | 325 ----- wocky/google-relay.h | 45 - wocky/jingle-content.c | 1422 ------------------- wocky/jingle-content.h | 165 --- wocky/jingle-factory.c | 620 -------- wocky/jingle-factory.h | 90 -- wocky/jingle-info-internal.h | 29 - wocky/jingle-info.c | 729 ---------- wocky/jingle-info.h | 121 -- wocky/jingle-media-rtp.c | 1589 --------------------- wocky/jingle-media-rtp.h | 126 -- wocky/jingle-session.c | 2515 --------------------------------- wocky/jingle-session.h | 135 -- wocky/jingle-transport-google.c | 641 --------- wocky/jingle-transport-google.h | 70 - wocky/jingle-transport-iceudp.c | 617 -------- wocky/jingle-transport-iceudp.h | 66 - wocky/jingle-transport-iface.c | 282 ---- wocky/jingle-transport-iface.h | 109 -- wocky/jingle-transport-rawudp.c | 403 ------ wocky/jingle-transport-rawudp.h | 66 - wocky/jingle-types.h | 154 -- wocky/wocky-google-relay.c | 325 +++++ wocky/wocky-google-relay.h | 45 + wocky/wocky-jingle-content.c | 1422 +++++++++++++++++++ wocky/wocky-jingle-content.h | 165 +++ wocky/wocky-jingle-factory.c | 620 ++++++++ wocky/wocky-jingle-factory.h | 90 ++ wocky/wocky-jingle-info-internal.h | 29 + wocky/wocky-jingle-info.c | 729 ++++++++++ wocky/wocky-jingle-info.h | 121 ++ wocky/wocky-jingle-media-rtp.c | 1589 +++++++++++++++++++++ wocky/wocky-jingle-media-rtp.h | 126 ++ wocky/wocky-jingle-session.c | 2515 +++++++++++++++++++++++++++++++++ wocky/wocky-jingle-session.h | 135 ++ wocky/wocky-jingle-transport-google.c | 641 +++++++++ wocky/wocky-jingle-transport-google.h | 70 + wocky/wocky-jingle-transport-iceudp.c | 617 ++++++++ wocky/wocky-jingle-transport-iceudp.h | 66 + wocky/wocky-jingle-transport-iface.c | 282 ++++ wocky/wocky-jingle-transport-iface.h | 109 ++ wocky/wocky-jingle-transport-rawudp.c | 403 ++++++ wocky/wocky-jingle-transport-rawudp.h | 66 + wocky/wocky-jingle-types.h | 154 ++ 45 files changed, 10343 insertions(+), 10343 deletions(-) commit 8d95d1911ba96d4fe97e08b33796c97030a25e0f Author: Will Thompson Date: Tue Jan 15 17:34:18 2013 +0000 Document ::new-candidates, ::remote-media-description and others wocky/jingle-content.c | 7 +++++++ wocky/jingle-media-rtp.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) commit 2cd46f5f8b96ad1af60d3bea5a48466592b43f31 Author: Will Thompson Date: Mon Jan 14 16:32:51 2013 +0000 jingle-transport-google: remove redundant media-type lookup The 'media' variable was not used. wocky/jingle-transport-google.c | 3 --- 1 file changed, 3 deletions(-) commit 63e3f0d8035cd82575774b91c9ce0ed087af7582 Author: Will Thompson Date: Mon Jan 14 16:31:54 2013 +0000 Add missing G_END_DECLS to Jingle headers Some headers are still missing both, but having just G_BEGIN_DECLS without G_END_DECLS is asking for trouble. wocky/jingle-content.h | 2 ++ wocky/jingle-media-rtp.h | 2 ++ wocky/jingle-session.h | 2 ++ wocky/jingle-transport-google.h | 2 ++ wocky/jingle-transport-iceudp.h | 2 ++ wocky/jingle-transport-rawudp.h | 2 ++ 6 files changed, 12 insertions(+) commit c9834fa18324eeb18146376cad91c79977fb9cb6 Author: Will Thompson Date: Mon Jan 14 16:29:14 2013 +0000 Document JingleMediaDescription and JingleReason wocky/jingle-media-rtp.c | 22 ++++++++++++++++++++++ wocky/jingle-types.h | 9 +++++++++ 2 files changed, 31 insertions(+) commit ef7ad1196c3810d11b7d264f84b0eadc3849f27b Author: Will Thompson Date: Fri Jan 11 12:55:04 2013 +0000 Document ::terminated, _terminate() and JingleState wocky/jingle-session.c | 34 +++++++++++++++++++++++++++++++++- wocky/jingle-types.h | 20 ++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) commit 63a0a96459f3d58d42e3027ef334677549114da0 Author: Will Thompson Date: Thu Jan 10 13:35:11 2013 +0000 Document wocky_jingle_session_accept() wocky/jingle-session.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) commit 0d4466491baf32d1756a5bc55ada680228752a2a Author: Will Thompson Date: Thu Jan 10 12:06:21 2013 +0000 Enable jingle_media_rtp_set_local_media_description docstring wocky/jingle-media-rtp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit f995a54f20a08a92974a7d865e8c1ec25e17fb18 Author: Will Thompson Date: Wed Jan 9 16:12:34 2013 +0000 jingle: document some methods wocky/jingle-content.c | 11 ++++++++++- wocky/jingle-media-rtp.c | 27 +++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) commit 82f2006f332eca746a68800c454a756b7f82b2d4 Author: Will Thompson Date: Tue Jan 8 15:09:52 2013 +0000 jingle-session: remove vestigial GabbleMediaSessionMode enum wocky/jingle-session.h | 6 ------ 1 file changed, 6 deletions(-) commit e83f9d8367a12c3edb61cb8b83f68742af4ec157 Author: Will Thompson Date: Tue Jan 8 15:01:28 2013 +0000 Document WOCKY_NODE_LANGUAGE wocky/wocky-node.h | 1 + 1 file changed, 1 insertion(+) commit 48c1697c88c3746fca0da512df4ce64224db02d3 Author: Will Thompson Date: Tue Jan 8 15:00:25 2013 +0000 docs: include jingle stuff gtk-doc is a little confused by some of the typedefs being in jingle-types.h but his is better than nothing. docs/reference/wocky-docs.sgml | 11 +++++++++++ 1 file changed, 11 insertions(+) commit 892ff6363f8a6cc5f1a077cc919edfbf3b994d23 Author: Will Thompson Date: Tue Jan 8 14:59:17 2013 +0000 docs: fix including enumtype documentation. I broke this in 9c98c48a, which switched to generating a single file with all the types. docs/reference/wocky-docs.sgml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) commit 46e8d6b7db39fda37615c7a628c69e845d434a2b Author: Will Thompson Date: Tue Jan 8 14:49:50 2013 +0000 Improve some Jingle docstrings. wocky/jingle-factory.c | 18 ++++++++++++++++++ wocky/jingle-media-rtp.c | 2 +- wocky/jingle-session.c | 22 ++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) commit b35851c9d241dcbc937da441635af27221933dfd Author: Will Thompson Date: Mon Jan 7 16:49:12 2013 +0000 JingleSession: only emit about-to-initiate once Previously, about-to-initiate would be emitted on every call to try_session_initiate_or_accept(), whether or not all contents were actually ready. This is relatively harmless – it's only used as a hook for sending directed presence to contacts not subscribed to us – but looked wrong and is redundant. wocky/jingle-session.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) commit 265627a4b93ce5fc824037815ae9362d6ec72229 Author: Will Thompson Date: Thu Dec 20 10:45:09 2012 +0000 jingle-factory.h: remove stray semicolon. GCC in pedantic mode complains "ISO C does not allow extra ';' outside of a function". wocky/jingle-factory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit bab335ff2d8b907071ad200ea6f6fffc73c37c09 Author: Will Thompson Date: Thu Dec 20 10:45:02 2012 +0000 Install jingle-types.h wocky/Makefile.am | 1 + 1 file changed, 1 insertion(+) commit aaefe6f7bb05c1b6900586b6af20716dbd133f57 Author: Will Thompson Date: Wed Dec 12 15:56:03 2012 +0000 Add optional libsoup dependency for google:relay Sigh. configure.ac | 14 ++++++++++++++ wocky/Makefile.am | 2 ++ 2 files changed, 16 insertions(+) commit 9302f6b95002b4bb9c41bceb56e23d15d96875c7 Author: Will Thompson Date: Tue Dec 11 18:23:03 2012 +0000 Add Jingle code to build; tweak till it builds Aside from removing a few leftover Gabble/telepathy-glib imports, this is basically mechanical. wocky/Makefile.am | 23 ++++++++++++++ wocky/google-relay.c | 4 +-- wocky/jingle-content.c | 13 ++++---- wocky/jingle-factory.c | 14 ++++----- wocky/jingle-info.c | 21 +++++++------ wocky/jingle-media-rtp.c | 66 ++++++++++++++++++++--------------------- wocky/jingle-session.c | 57 +++++++++++++++++------------------ wocky/jingle-transport-google.c | 8 ++--- wocky/jingle-transport-iceudp.c | 10 +++---- wocky/jingle-transport-iface.c | 1 - wocky/jingle-transport-rawudp.c | 9 +++--- 11 files changed, 120 insertions(+), 106 deletions(-) commit edf725dca6554d233807d1266c46fd6196dff845 Author: Will Thompson Date: Tue Dec 11 18:02:05 2012 +0000 Import Gabble's Jingle code. This corresponds to 8bb117691 in Gabble. wocky/google-relay.c | 325 ++++++ wocky/google-relay.h | 45 + wocky/jingle-content.c | 1407 ++++++++++++++++++++++ wocky/jingle-content.h | 163 +++ wocky/jingle-factory.c | 604 ++++++++++ wocky/jingle-factory.h | 90 ++ wocky/jingle-info-internal.h | 29 + wocky/jingle-info.c | 730 ++++++++++++ wocky/jingle-info.h | 121 ++ wocky/jingle-media-rtp.c | 1517 ++++++++++++++++++++++++ wocky/jingle-media-rtp.h | 124 ++ wocky/jingle-session.c | 2447 +++++++++++++++++++++++++++++++++++++++ wocky/jingle-session.h | 139 +++ wocky/jingle-transport-google.c | 644 +++++++++++ wocky/jingle-transport-google.h | 68 ++ wocky/jingle-transport-iceudp.c | 617 ++++++++++ wocky/jingle-transport-iceudp.h | 64 + wocky/jingle-transport-iface.c | 283 +++++ wocky/jingle-transport-iface.h | 109 ++ wocky/jingle-transport-rawudp.c | 404 +++++++ wocky/jingle-transport-rawudp.h | 64 + wocky/jingle-types.h | 125 ++ 22 files changed, 10119 insertions(+) commit 2166311066382662dc9cb712445b93a1c8b18fa2 Author: Will Thompson Date: Tue Dec 11 17:46:14 2012 +0000 Add a debug flag for Jingle stuff. It's called "media" so that GABBLE_DEBUG=media will still work, if that matters to anyone. wocky/wocky-debug.c | 1 + wocky/wocky-debug.h | 1 + 2 files changed, 2 insertions(+) commit c93bd526f058dc26c888e2527b0b6c4c2c285295 Author: Will Thompson Date: Tue Dec 11 17:34:44 2012 +0000 Add namespaces used by the Jingle code. I'm pretty unhappy about the quirks being added here, but there we go. wocky/wocky-namespaces.h | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) commit 44db2c0d1bec2a2358071bfe3a8d3246d4ab8a39 Author: Will Thompson Date: Tue Dec 11 17:24:41 2012 +0000 debug: add DEBUG_NODE() It's used in the Jingle code I'll import shortly. wocky/wocky-debug-internal.h | 14 ++++++++++++++ wocky/wocky-debug.c | 29 +++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 4 deletions(-) commit afde9190f3ecb381c09096f13ab67179da7285e3 Author: Will Thompson Date: Wed Dec 12 17:00:33 2012 +0000 Add a pkg-config file. It's only useful if both the shared library is enabled, and the headers are to be installed. If so, great happiness ensues. .gitignore | 1 + configure.ac | 1 + wocky/Makefile.am | 5 +++++ wocky/wocky-uninstalled.pc.in | 1 - wocky/wocky.pc.in | 11 +++++++++++ 5 files changed, 18 insertions(+), 1 deletion(-) commit b2521e80d00cd6fa6743699f3f5247318c438b84 Author: Will Thompson Date: Wed Dec 12 14:44:23 2012 +0000 Include the enumtypes header in wocky.h wocky/wocky.h | 1 + 1 file changed, 1 insertion(+) commit 9c98c48aef1f85eff2e48105ab7a05a966ff0029 Author: Will Thompson Date: Wed Dec 12 14:39:36 2012 +0000 Simplify generating GEnums/GFlags This version of the rule is taken from Gabble. It puts them all together in one file, and determines the naming from the names of the enumeration types, rather than from the filenames, which is clearer and saner. (Under the previous rule, the Jingle code I am about to import ended up with enums like JINGLE_TYPE_JINGLE_REASON because the file was called jingle-foo.h and the type was called WockyJingleReason...) wocky/Makefile.am | 63 +++++++++++++++++++------------------------- wocky/wocky-auth-registry.h | 2 +- wocky/wocky-connector.h | 2 +- wocky/wocky-data-form.h | 2 +- wocky/wocky-muc.h | 2 +- wocky/wocky-pubsub-node.h | 2 +- wocky/wocky-pubsub-service.h | 2 +- wocky/wocky-tls.h | 2 +- wocky/wocky-xmpp-error.h | 2 +- wocky/wocky-xmpp-reader.h | 2 +- 10 files changed, 36 insertions(+), 45 deletions(-) commit e8c7970c2a6ca04b98e2d329834d49ea18c91de7 Author: Will Thompson Date: Mon Nov 26 15:53:41 2012 +0000 Make wocky_node_{add,prepend}_node_tree return the node This is by analogy to wocky_node_add_child, which returns the newly-added node. tests/wocky-node-tree-test.c | 5 ++++- wocky/wocky-node.c | 20 ++++++++++++++------ wocky/wocky-node.h | 4 ++-- 3 files changed, 20 insertions(+), 9 deletions(-) commit e49a114960f78c490f9614cc1138e4f862162cde Author: Will Thompson Date: Mon Nov 26 15:45:22 2012 +0000 Add wocky_node_iter_remove() I find myself wanting this in Gabble's vcard code. tests/wocky-xmpp-node-test.c | 30 ++++++++++++++++++++++++++++++ wocky/wocky-node.c | 33 ++++++++++++++++++++++++++++++++- wocky/wocky-node.h | 3 +++ 3 files changed, 65 insertions(+), 1 deletion(-) commit 6982dc11dcf44dff4f26f59a33c572c13ba3ba09 Author: Will Thompson Date: Wed Dec 5 18:35:12 2012 +0000 tests: sort the Makefile I'm afraid you'll have to take my word for it that I did nothing except (manually!) sort this Makefile and correct some erratic formatting. tests/Makefile.am | 264 +++++++++++++++++++++++++++--------------------------- 1 file changed, 131 insertions(+), 133 deletions(-) commit 53485968a3bd2e96c8ccc5ca12a1dbe9e9a83bc4 Author: Will Thompson Date: Fri Nov 23 11:37:08 2012 +0000 connector: simplify including state in debug messages I noticed an debug message saying Authentication Completed: : received XMPP version=1.0 stream open from server in a debug log, and this ^^^^ annoyed me, so I fixed it by deleting code. wocky/wocky-connector.c | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) commit 40a2f1d4ac5a85af6910f3785acc4453dc72f3dc Author: Will Thompson Date: Tue Jul 5 18:56:33 2011 +0100 wocky_auth_registry_has_mechanism: simplify! wocky/wocky-auth-registry.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) commit e4f0d1ef5a858125f993d597c52c94340f092003 Author: Will Thompson Date: Tue Jul 5 18:55:52 2011 +0100 wocky_auth_registry_has_mechanism: fix coding style wocky/wocky-auth-registry.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) commit 5fc55e8ae0915d03c57555c8927985f4d57c3792 Author: Olivier Crête Date: Tue Jul 5 18:55:26 2011 +0100 Don't put const before G*List, it does not make sense wocky/wocky-auth-registry.c | 14 +++++++------- wocky/wocky-auth-registry.h | 6 +++--- wocky/wocky-pubsub-node-protected.h | 2 +- wocky/wocky-pubsub-node.c | 6 +++--- wocky/wocky-pubsub-node.h | 2 +- wocky/wocky-utils.c | 4 ++-- wocky/wocky-utils.h | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) commit 388f4fbd9474cf92b9c7f0cca8871fe5e4dc7569 Merge: 71d05e7 881f00f Author: Will Thompson Date: Wed Nov 21 17:42:08 2012 +0000 Merge branch 'wildcarded-certificate-check' commit 881f00f7008f1b25194adbf351e93ce0f0d37136 Author: Will Thompson Date: Wed Nov 21 17:25:33 2012 +0000 gnutls: explain why wildcard verification is needed wocky/wocky-tls.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) commit 7cdf9a81aad1b09e33f1d26bf768fea0b81eff12 Author: Will Thompson Date: Wed Nov 21 17:23:46 2012 +0000 gnutls: simplify wildcard validation wocky/wocky-tls.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) commit a71ea75ee7e1fd53da6c78fb7cd277f3268b7065 Author: Will Thompson Date: Wed Nov 21 17:19:41 2012 +0000 openssl: make wildcard handling more obviously right wocky/wocky-openssl.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) commit 1439b551f0d9a10a2d9956c05fe614ce72740d4c Author: Will Thompson Date: Wed Nov 21 17:16:28 2012 +0000 openssl: don't reimplement g_ascii_strcasecmp wocky/wocky-openssl.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) commit 71d05e73c96f11174b3e388800d678bcb4a1dabb Author: Will Thompson Date: Fri Nov 16 17:00:12 2012 +0000 C2SPorter: validate JIDs to match sooner. Previously the JID was not validated until a few functions deep from wocky_c2s_porter_register_handler_from_by_stanza(), where it was checked with g_assert(). This moves the validation further out, to the point where we should have criticalled and returned. https://bugs.freedesktop.org/show_bug.cgi?id=51528 wocky/wocky-c2s-porter.c | 52 +++++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 21 deletions(-) commit 762c8281d37f065a174220e802afc599df2bcfdc Merge: 3b8e105 6812be7 Author: Will Thompson Date: Fri Nov 16 15:25:28 2012 +0000 Merge branch 'salut-0.8' commit 6812be7c0da6cb39c4f6bb449e374a2c96f007bb Author: Will Thompson Date: Fri Nov 16 12:52:07 2012 +0000 MetaPorter: don't match sender on C2S porters When someone registers a handler for stanzas from a particular contact on WockyMetaPorter, it previously would pass that contact's JID down to the relevant C2S porter. This is both unnecessary (we know who stanzas on any given C2S porter are from) and broken: iChat does not set from='' on its outgoing stanzas, so they would never match any handlers. https://bugs.freedesktop.org/show_bug.cgi?id=51527 wocky/wocky-meta-porter.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) commit 3b8e10508cc3df67de30c52db272e6fdbdef5815 Author: Will Thompson Date: Wed Nov 14 18:28:05 2012 +0000 dump-certificates: don't use real passwords examples/dump-certificates.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) commit ded49b6801c402dde75492d9d4b0b948c4bad35d Author: Stef Walter Date: Wed Apr 13 16:10:27 2011 +0200 examples: Add example which dumps recieved TLS certificates to stdout https://bugs.freedesktop.org/show_bug.cgi?id=36207 .gitignore | 1 + examples/Makefile.am | 7 ++ examples/dump-certificates.c | 173 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 181 insertions(+) commit 31f33f4ba66bcdddda84b419cf4960073d071290 Author: Will Thompson Date: Mon Nov 12 14:03:00 2012 +0000 Test WockyXmppReader:default-namespace. tests/wocky-xmpp-reader-test.c | 69 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) commit a7eace097402481b6fbf957dc12d2763a97c0202 Author: Will Thompson Date: Mon Nov 12 11:44:31 2012 +0000 Miscellaneous docstring cleanup wocky/wocky-data-form.h | 8 ++++++-- wocky/wocky-pubsub-helpers.c | 3 ++- wocky/wocky-stanza.c | 19 ++++++++++--------- wocky/wocky-xmpp-reader.c | 4 ++-- 4 files changed, 20 insertions(+), 14 deletions(-) commit 5915026706a53b498a5b3cf53a1144fdd8370b30 Author: Will Thompson Date: Mon Nov 12 11:17:14 2012 +0000 XmppReader: add _new_no_stream_ns() wrapper wocky/wocky-xmpp-reader.c | 19 +++++++++++++++++++ wocky/wocky-xmpp-reader.h | 2 ++ 2 files changed, 21 insertions(+) commit 9a47ab52cac8f3aaea09644f9f26090171df5906 Author: Will Thompson Date: Thu Nov 8 16:36:53 2012 +0000 XmppReader: add a construct-only property for default ns wocky/wocky-xmpp-reader.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) commit 00e60596a0910bd153cfb92e2e2321d0874992e2 Author: Will Thompson Date: Tue Nov 6 20:01:07 2012 +0000 stanza: store quarks for known types' namespaces wocky/wocky-stanza.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) commit e6316c18df82928f2174538c33fb2d5267db8c0d Author: Will Thompson Date: Tue Nov 6 19:57:03 2012 +0000 stanza: check the namespace when determining type I can't believe we had this bug for so long... Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=57016 tests/wocky-stanza-test.c | 22 ++++++++++++++++++++++ wocky/wocky-stanza.c | 10 +++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) commit 5753ec4b61dd246a7e3d588949fe5e84b86975d9 Author: Will Thompson Date: Tue Nov 6 20:45:44 2012 +0000 wocky_stanza_get_type_info(): get top node once wocky/wocky-stanza.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) commit 8ad2d40ad4f1abb6c85db0a4b5404fac59d92adc Author: Will Thompson Date: Wed Oct 31 17:51:00 2012 +0000 Use wocky_stanza_extract_stream_error() more widely wocky/wocky-jabber-auth.c | 9 ++------- wocky/wocky-sasl-auth.c | 9 ++------- 2 files changed, 4 insertions(+), 14 deletions(-) commit e5f1843e69cc6499c88deeb83d650a1deee0e798 Author: Will Thompson Date: Wed Oct 31 19:08:23 2012 +0000 C2SPorter: improve check for queueable stanzas wocky/wocky-c2s-porter.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) commit e9397d15f4b5ee0939f5e4c7a9023669994c3d1d Author: Will Thompson Date: Wed Oct 31 17:50:45 2012 +0000 Use wocky_stanza_has_type() in a few places. wocky/wocky-connector.c | 8 ++++---- wocky/wocky-stanza.c | 6 +----- 2 files changed, 5 insertions(+), 9 deletions(-) commit 1596d117d59ef4ff182e708a0b4a60d8ddc5a6d7 Author: Will Thompson Date: Wed Oct 31 17:47:59 2012 +0000 Add wocky_stanza_has_type() This is a bit like wocky_node_matches(). It doesn't let you match on the SubType, which may be an oversight but a few places I checked need to allow either a particular SubType or NONE, so I thought I'd keep it simple. wocky/wocky-stanza.c | 13 +++++++++++++ wocky/wocky-stanza.h | 2 ++ 2 files changed, 15 insertions(+) commit e9eec82a6df70d43fd5bc5713afb7e031aecd012 Author: Will Thompson Date: Mon Oct 29 17:16:40 2012 +0000 Replace homegrown macro with g_clear_object wocky/wocky-connector.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) commit 7ceba80a29b1ea627baca69b4e752ccb1c67b341 Author: Will Thompson Date: Mon Oct 1 18:57:36 2012 +0100 XmppReader: allow subclasses to specify stream element name/ns This might be useful if you were implementing server-to-server communication, or (more pertinently) for parsing Google Talk's conversation logs. wocky/wocky-xmpp-reader.c | 14 ++++++++++---- wocky/wocky-xmpp-reader.h | 4 ++++ 2 files changed, 14 insertions(+), 4 deletions(-) commit 0c9e226e165803d53a278b5fdbb3fb4c3f2330b0 Author: Jonny Lamb Date: Fri May 4 11:26:19 2012 +0100 connector test: set TCP_NODELAY for both server and client sockets This cuts the time it takes to run this test by roughly 27 seconds. Great stuff. Signed-off-by: Jonny Lamb tests/wocky-connector-test.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) commit e091bf2dd912e2aaf87fc0a6f2232553d26e7c0a Author: Jonny Lamb Date: Fri May 4 08:25:51 2012 +0100 connector: add ::connection-established Signed-off-by: Jonny Lamb wocky/wocky-connector.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) commit 0d3055853942fc57ff88fd0aa09f30731436d408 Author: Will Thompson Date: Mon Jul 23 15:02:59 2012 +0100 SCRAM: correct logic in server-final message handling The server-final message looks like this: server-final-message = (server-error / verifier) ["," extensions] server-error = "e=" server-error-value verifier = "v=" base64 The code was trying to check “is there at least one attribute, and is it a verifier?”. But instead it was checking “is there at least one attribute, and if not, is the non-existant attribute a verifier?” by comparing the uninitialized 'attr' variable to 'v'. I've checked other calls to scram_get_next_attr_value() and they seem to get the logic the right way round. This bug does not cause a security vulnerability. If the uninitialized 'attr' variable happens to contain the character 'v', then the following call to scram_check_server_verification() will compare the contents of value (which ought to be a verification string, but is NULL) to the verification string as calculated by Wocky (which is not NULL) and so Wocky will abort the connection. Thanks to Ed Catmur for reporting the use of an uninitialized variable on . Reviewed-by: Jonny Lamb wocky/wocky-sasl-scram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 9d5d16dabbb84a44d230996cd1d1480f5b767ec0 Author: Xavier Claessens Date: Tue Jun 19 13:08:11 2012 +0200 Add unit test for see-other-host stream error tests/wocky-connector-test.c | 169 +++++++++++++++++++++++------------- tests/wocky-test-connector-server.c | 57 ++++++++++++ tests/wocky-test-connector-server.h | 5 ++ 3 files changed, 172 insertions(+), 59 deletions(-) commit d065b5ccf63b3a02a132cee370407a8a115fc444 Author: Xavier Claessens Date: Wed Jun 13 14:39:50 2012 +0200 WockyConnector: Support see-other-host wocky/wocky-connector.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) commit 3012a34361e6ca61e897d9e74079752b00c28ede Author: Xavier Claessens Date: Mon Jun 18 17:49:21 2012 +0200 WockyConnector: Fix problem if host is an ipv6 or contains a port Make WockyConnector::connect_to_host_async() uses g_socket_client_connect_to_host_async()'s semantic. It means that the port argument is used only if the host does not already contains a port. wocky/wocky-connector.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) commit 1a0d974dfdb503968731908664baabd8421acd86 Author: Xavier Claessens Date: Tue Jun 19 17:37:04 2012 +0200 WockyConnector: Remove unused private member wocky/wocky-connector.c | 3 --- 1 file changed, 3 deletions(-) commit 8e25a880611955859a6c8e7aca5033ee64451471 Author: Vivek Dasmohapatra Date: Thu May 10 20:03:17 2012 +0100 Add CRL tests to connector test list tests/wocky-connector-test.c | 55 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) commit 814202d9185a1373384597b5c36eaa4383dfa7e5 Author: Vivek Dasmohapatra Date: Thu May 10 19:34:40 2012 +0100 Recreate CRL for revoked cert test tests/Certificates.mk | 1 + tests/certs/ca-0-crl.cfg | 89 ++++++++++++++++++++++++++++++++++++++++++++ tests/certs/ca-0-crl.pem | 13 +++++++ tests/certs/crl/ca-0-crl.pem | 13 +++++++ 4 files changed, 116 insertions(+) commit 7d14776ad3182e76a2ce3f0d5fe9a9db089d3bb3 Author: Vivek Dasmohapatra Date: Thu May 10 19:29:33 2012 +0100 Add CRL support to wocky-tls-connector wocky/wocky-tls-connector.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) commit 07ac5b44e6f09e0c3ec78f73fdd7ca3b9e9ca9cd Author: Vivek Dasmohapatra Date: Thu May 10 19:29:08 2012 +0100 Add CRL support to wocky-tls-handler wocky/wocky-tls-handler.c | 43 +++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-tls-handler.h | 3 +++ 2 files changed, 46 insertions(+) commit e4812722e460f8ebd014eced924e6bb5c6c70d00 Author: Vivek Dasmohapatra Date: Thu May 10 19:28:20 2012 +0100 Add CRL support to wocky-tls and wocky-openssl wocky/wocky-openssl.c | 43 ++++++++++++++++++++++++++++++++++++++- wocky/wocky-tls.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-tls.h | 1 + 3 files changed, 99 insertions(+), 1 deletion(-) commit c132b9d299936eb9880015f0f5978053fa95fb48 Author: Vivek Dasmohapatra Date: Wed May 9 22:28:14 2012 +0100 For OpenSSL we need to squash CRL fetch failure errors and reverify when !strict wocky/wocky-openssl.c | 149 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 96 insertions(+), 53 deletions(-) commit 66953c17cd93fa9bcbd657139ff3e23b2fc3684c Author: Vivek Dasmohapatra Date: Wed May 9 22:26:09 2012 +0100 Self signed certs should still have the CA bit set (was making a test fail) tests/certs/ss-cert.cfg | 2 +- tests/certs/ss-cert.pem | 42 +++++++++++++++++++++--------------------- 2 files changed, 22 insertions(+), 22 deletions(-) commit 5fe9c3a75526ed0115b09b433370920558164969 Author: Vivek Dasmohapatra Date: Wed May 9 16:49:57 2012 +0100 Disallow *oogle.com certs on gnutls as well (cf *.google.com) wocky/wocky-tls.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 106 insertions(+), 13 deletions(-) commit 0c8d0c9b1f871d8794a3c6716540a904dfba989a Author: Vivek Dasmohapatra Date: Tue May 8 19:06:22 2012 +0100 Wildcard handling was stack-hungry, too lenient for "*foo" vs "*.foo" wildcards wocky/wocky-openssl.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) commit deba3a4d4a817ae93735382f309eec09d09de15d Author: Vivek Dasmohapatra Date: Tue May 8 19:04:36 2012 +0100 Add tests for matched, unmatched and bad wildcards for STARTTLS and SSL tests/wocky-connector-test.c | 98 ++++++++++++++++++++++++++++++++++++- tests/wocky-test-connector-server.c | 2 + tests/wocky-test-connector-server.h | 2 + 3 files changed, 101 insertions(+), 1 deletion(-) commit d841c407daa7c966884368d221329ff2749f4dcf Author: Vivek Dasmohapatra Date: Wed May 9 17:01:52 2012 +0100 Add defines for new ssl certificates for wildcard tests tests/Makefile.am | 10 ++++++++++ 1 file changed, 10 insertions(+) commit 19a646ceda01c071e3b2a6902cba10e11f1093bf Author: Vivek Dasmohapatra Date: Tue May 8 19:02:14 2012 +0100 Add good and bad wildcard certificates, provide a helper for creating new certs The helper is not run automatically, but provides a way for new certs to be created should new tests require them. tests/Certificates.mk | 120 +++++++++++++++++++++++++++++++++++ tests/certs/badwild-cert.cfg | 89 ++++++++++++++++++++++++++ tests/certs/badwild-cert.pem | 26 ++++++++ tests/certs/badwild-key.pem | 145 +++++++++++++++++++++++++++++++++++++++++++ tests/certs/wild-cert.cfg | 89 ++++++++++++++++++++++++++ tests/certs/wild-cert.pem | 26 ++++++++ tests/certs/wild-key.pem | 145 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 640 insertions(+) commit a3ec82f5edf56b30f7c116065998f573652e0ff4 Author: Vivek Dasmohapatra Date: Tue May 8 18:52:07 2012 +0100 Update the PEM hashes so that OpenSSL multi-CA tests work again tests/certs/cas/8a76ade9.0 | 1 + tests/certs/cas/ae5bb84e.0 | 1 + tests/certs/cas/e7df1717.0 | 1 + tests/certs/crl/e7df1717.r0 | 1 + 4 files changed, 4 insertions(+) commit 439f3efe6dca643ec7c15c52b8f1577a370577d6 Author: Nicolas Dufresne Date: Thu Apr 5 11:01:48 2012 -0400 Removed remaining CRL define in tests tests/Makefile.am | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) commit a5feff5ff5ed88739e91cfc0a19d3cb4deb4c4f3 Author: Siraj Razick Date: Thu Apr 5 10:59:43 2012 -0400 Check the validity of TLS_CA_CRT_FILE and TLS_CRL_DIR The test cases should fail with a more obvious error when passing non-existent directories and certificates. https://bugs.freedesktop.org/show_bug.cgi?id=43844 tests/wocky-connector-test.c | 3 +++ 1 file changed, 3 insertions(+) commit e2b1699db4d8d2102f658d7b9ac09909ce86aac7 Author: Guillaume Desmottes Date: Wed Apr 4 10:00:15 2012 +0200 use new GLib API checking macros configure.ac | 3 +++ 1 file changed, 3 insertions(+) commit 26d079908e9e91f3659f5616af6b879f8bb0ac4d Author: Guillaume Desmottes Date: Wed Apr 4 10:35:06 2012 +0200 add missing config.h includes examples/receive-messages.c | 4 ++++ examples/register.c | 4 ++++ examples/send-message.c | 4 ++++ examples/unregister.c | 4 ++++ tests/test-resolver.c | 4 ++++ tests/wocky-bare-contact-test.c | 4 ++++ tests/wocky-caps-hash-test.c | 4 ++++ tests/wocky-contact-factory-test.c | 4 ++++ tests/wocky-data-form-test.c | 4 ++++ tests/wocky-dummy-xmpp-server.c | 4 ++++ tests/wocky-http-proxy-test.c | 4 ++++ tests/wocky-jid-validation-test.c | 4 ++++ tests/wocky-loopback-test.c | 4 ++++ tests/wocky-node-tree-test.c | 4 ++++ tests/wocky-pep-service-test.c | 4 ++++ tests/wocky-ping-test.c | 4 ++++ tests/wocky-porter-test.c | 4 ++++ tests/wocky-pubsub-node-test.c | 4 ++++ tests/wocky-pubsub-service-test.c | 4 ++++ tests/wocky-pubsub-test-helpers.c | 4 ++++ tests/wocky-resource-contact-test.c | 4 ++++ tests/wocky-roster-test.c | 4 ++++ tests/wocky-sasl-utils-test.c | 4 ++++ tests/wocky-scram-sha1-test.c | 4 ++++ tests/wocky-session-test.c | 4 ++++ tests/wocky-stanza-test.c | 4 ++++ tests/wocky-test-helper.c | 4 ++++ tests/wocky-test-sasl-auth-server.c | 4 +++- tests/wocky-test-sasl-auth.c | 4 ++++ tests/wocky-test-sasl-handler.c | 3 +++ tests/wocky-test-stream.c | 4 ++++ tests/wocky-utils-test.c | 4 ++++ tests/wocky-xmpp-connection-test.c | 4 ++++ tests/wocky-xmpp-node-test.c | 4 ++++ tests/wocky-xmpp-reader-test.c | 4 ++++ tests/wocky-xmpp-readwrite-test.c | 4 ++++ wocky/wocky-auth-handler.c | 3 +++ wocky/wocky-auth-registry.c | 4 ++++ wocky/wocky-data-form.c | 4 ++++ wocky/wocky-debug.c | 3 +++ wocky/wocky-heartbeat-source.c | 4 ++++ wocky/wocky-jabber-auth-digest.c | 3 +++ wocky/wocky-jabber-auth-password.c | 3 +++ wocky/wocky-jabber-auth.c | 3 +++ wocky/wocky-loopback-stream.c | 4 ++++ wocky/wocky-meta-porter.c | 4 ++++ wocky/wocky-muc.c | 4 ++++ wocky/wocky-node-tree.c | 3 +++ wocky/wocky-node.c | 4 ++++ wocky/wocky-openssl-dh1024.c | 4 ++++ wocky/wocky-openssl-dh2048.c | 4 ++++ wocky/wocky-openssl-dh4096.c | 4 ++++ wocky/wocky-openssl-dh512.c | 4 ++++ wocky/wocky-pep-service.c | 4 ++++ wocky/wocky-ping.c | 4 ++++ wocky/wocky-porter.c | 4 ++++ wocky/wocky-pubsub-helpers.c | 4 ++++ wocky/wocky-pubsub-node.c | 4 ++++ wocky/wocky-pubsub-service.c | 4 ++++ wocky/wocky-roster.c | 4 ++++ wocky/wocky-sasl-auth.c | 4 ++++ wocky/wocky-sasl-digest-md5.c | 3 +++ wocky/wocky-sasl-plain.c | 3 +++ wocky/wocky-sasl-scram.c | 5 +++++ wocky/wocky-sasl-utils.c | 4 ++++ wocky/wocky-stanza.c | 3 +++ wocky/wocky-utils.c | 4 ++++ wocky/wocky-xmpp-error.c | 4 ++++ wocky/wocky-xmpp-reader.c | 4 ++++ wocky/wocky-xmpp-writer.c | 4 ++++ wocky/wocky.c | 4 ++++ 71 files changed, 274 insertions(+), 1 deletion(-) commit f26612018fe65d78581bfc5c8c23608d23750686 Author: Guillaume Desmottes Date: Wed Apr 4 10:34:15 2012 +0200 wocky-xmpp-readwrite-test.c: rename VERSION to XMPP_VERSION VERSION is defined in config.h tests/wocky-xmpp-readwrite-test.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit 5e3fe022d9eecf8943663b1e622569226920177a Author: Nicolas Dufresne Date: Wed Feb 1 16:27:38 2012 -0500 Remove wocky_tls_session_add_crl This is unused by Gabble, unsupported by GIO. Correct usage of such a feature would be system whide, not really per-applications. .gitignore | 2 -- tests/Makefile.am | 5 +---- tests/certs/ca-0-crl.cfg | 2 -- tests/certs/ca-0-crl.pem | 13 ------------ tests/certs/crl/c5d5c0da.r0 | 1 - tests/certs/crl/ca-0-crl.pem | 13 ------------ tests/wocky-connector-test.c | 49 -------------------------------------------- wocky/wocky-openssl.c | 33 +++++++++-------------------- wocky/wocky-tls-connector.c | 14 +------------ wocky/wocky-tls-handler.c | 39 ----------------------------------- wocky/wocky-tls-handler.h | 3 --- wocky/wocky-tls.c | 49 ++++++++++++++------------------------------ wocky/wocky-tls.h | 1 - 13 files changed, 27 insertions(+), 197 deletions(-) commit 2de11b18fc9b4b0f30b7f02fb7c68fb29455c585 Author: Jonny Lamb Date: Tue Apr 3 17:03:48 2012 -0400 tests/Makefile: fix warnings when running autoreconf Signed-off-by: Jonny Lamb tests/Makefile.am | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) commit fe5b396b46d963cd1fa8c2e6cd9d36012edd5867 Author: Olli Salli Date: Fri Mar 16 19:22:54 2012 +0200 Add wocky_send_ll_pep_event utility function This is essentially salut_send_ll_pep_event, but using WockyXep0115Capabilities to decide who to send the stanza to. wocky/wocky-pubsub-helpers.c | 78 +++++++++++++++++++++++++++++++++++++++++++- wocky/wocky-pubsub-helpers.h | 5 ++- 2 files changed, 81 insertions(+), 2 deletions(-) commit 8c31eb275050fd62e2c486211c4cb34b10cd8fe4 Author: Olli Salli Date: Fri Mar 16 19:08:49 2012 +0200 Add has_feature to the WockyXep0115Capabilities interface wocky/wocky-xep-0115-capabilities.c | 17 ++++++++++++++++- wocky/wocky-xep-0115-capabilities.h | 13 +++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) commit a8011aa7e549cfde28adad41d1a1c6f39fafba69 Author: Guillaume Desmottes Date: Thu Mar 15 10:01:45 2012 +0100 connector: display the port when falling back to HOST wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 707bf14a43bf41739f1fd126c301a4a1c88b7a37 Author: Mikhail Zabaluev Date: Fri Mar 9 17:09:20 2012 +0200 Delist the internal headers from installed headers Reviewed-By: Simon McVittie wocky/Makefile.am | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) commit 520016c06c3c7440c925bde233842deafce76208 Author: Simon McVittie Date: Thu Feb 23 11:52:59 2012 +0000 If configured with --enable-shared-suffix=*, install a shared library The suffix should be something like gabble-0.15.4, to yield libwocky-gabble-0.15.4.so ("the Wocky from Gabble 0.15.4"). configure.ac | 10 ++++++++++ wocky/Makefile.am | 9 +++++++++ 2 files changed, 19 insertions(+) commit 8db06f5deefc6dd61504e769ee4d534f182c3a77 Author: Simon McVittie Date: Thu Feb 23 11:50:28 2012 +0000 Use LIBADD properly, rather than putting libraries in LDFLAGS wocky/Makefile.am | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) commit 81fe73ceb5b0693a92c2247bdb1da11b363b79dd Author: Simon McVittie Date: Tue Feb 21 13:25:24 2012 +0000 GNUTLS backend: don't use 0 as an error domain It's never been considered valid, and since GLib 2.31.something it issues a warning, which breaks the Gabble regression tests. We're still using 0 as the error code because WockyTLSError has apparently never actually defined what its error enum is, and in its existing uses in the OpenSSL backend it's an OpenSSL error code, which is obviously not applicable here. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=46379 Reviewed-by: Vivek Dasmohapatra wocky/Makefile.am | 1 + wocky/wocky-openssl.c | 22 -------------------- wocky/wocky-tls-common.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-tls.c | 17 +++++----------- 4 files changed, 58 insertions(+), 34 deletions(-) commit 17af336d3fe42109e9ab067c27bd9f20a915f9e5 Author: Will Thompson Date: Mon Feb 6 14:56:27 2012 +0000 Namespace debug flags. For better or worse, we expose these to applications, so we should namespace them. (This isn't purely theoretical: the names clash with the same ones in Gibber within Salut.) tests/wocky-test-connector-server.c | 2 +- wocky/wocky-auth-registry.c | 2 +- wocky/wocky-bare-contact.c | 2 +- wocky/wocky-c2s-porter.c | 2 +- wocky/wocky-caps-cache.c | 2 +- wocky/wocky-caps-hash.c | 2 +- wocky/wocky-connector.c | 2 +- wocky/wocky-contact-factory.c | 2 +- wocky/wocky-contact.c | 2 +- wocky/wocky-data-form.c | 2 +- wocky/wocky-debug-internal.h | 16 +++++++------- wocky/wocky-debug.c | 44 ++++++++++++++++++------------------- wocky/wocky-debug.h | 44 ++++++++++++++++++------------------- wocky/wocky-disco-identity.c | 2 +- wocky/wocky-heartbeat-source.c | 2 +- wocky/wocky-jabber-auth-digest.c | 2 +- wocky/wocky-jabber-auth-password.c | 2 +- wocky/wocky-jabber-auth.c | 2 +- wocky/wocky-ll-connection-factory.c | 2 +- wocky/wocky-ll-connector.c | 2 +- wocky/wocky-meta-porter.c | 2 +- wocky/wocky-muc.c | 2 +- wocky/wocky-openssl.c | 2 +- wocky/wocky-pep-service.c | 2 +- wocky/wocky-ping.c | 2 +- wocky/wocky-pubsub-node.c | 2 +- wocky/wocky-pubsub-service.c | 2 +- wocky/wocky-resource-contact.c | 2 +- wocky/wocky-roster.c | 2 +- wocky/wocky-sasl-auth.c | 2 +- wocky/wocky-sasl-digest-md5.c | 2 +- wocky/wocky-sasl-plain.c | 2 +- wocky/wocky-sasl-scram.c | 2 +- wocky/wocky-tls-connector.c | 2 +- wocky/wocky-tls-handler.c | 2 +- wocky/wocky-tls.c | 2 +- wocky/wocky-xmpp-reader.c | 4 ++-- wocky/wocky-xmpp-writer.c | 4 ++-- 38 files changed, 89 insertions(+), 89 deletions(-) commit 132d73e09abb9c08f61cebe1cd0ca6d7cbc8b7c0 Merge: bcf78e4 6de1714 Author: Will Thompson Date: Mon Feb 6 13:27:00 2012 +0000 Merge branch 'headers' https://bugs.freedesktop.org/show_bug.cgi?id=27489 Reviewed-by: Simon McVittie commit 6de1714422763cb4b96be9dd9085b8745b19d18a Author: Will Thompson Date: Wed Feb 1 16:19:15 2012 +0000 Move some of pubsub-node-protected.h to internal.h As Simon mentions on and comments in that file specify, some bits of wocky-pubsub-node-protected.h are intended for applications, and other bits are internal to Wocky. So let's split the later bits into a new header, wocky-pubsub-node-internal.h, which is not included by wocky.h and has internal-only header guards. wocky/Makefile.am | 1 + wocky/wocky-pubsub-node-internal.h | 44 +++++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-node-protected.h | 20 +---------------- wocky/wocky-pubsub-node.c | 1 + wocky/wocky-pubsub-service.c | 1 + 5 files changed, 48 insertions(+), 19 deletions(-) commit 25cc1aba2e10faa7d85030a57331c541a04cbe4d Author: Will Thompson Date: Wed Feb 1 15:55:03 2012 +0000 Include wocky-debug.h from wocky.h wocky/wocky-debug.h | 4 ++-- wocky/wocky.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) commit 33b31b5d6be1b46b3e8d28e3f38b15f94ae1401f Author: Will Thompson Date: Wed Feb 1 15:47:18 2012 +0000 Always define WockyDebugFlags and wocky_debug_set_flags() If wocky-debug.h is to contain API for applications, that API should probably always be defined. wocky/wocky-debug.c | 6 ++++++ wocky/wocky-debug.h | 8 -------- 2 files changed, 6 insertions(+), 8 deletions(-) commit 2beb6fe89dac878b1a786033bf452d10b3f8ad56 Author: Will Thompson Date: Wed Feb 1 15:31:26 2012 +0000 Move most of debug.h to debug-internal.h Gabble uses a couple of bits of this API to turn on a little bit of Wocky's debug output for the purposes of the D-Bus debugging interface, so making debug.h internal-only is not going to fly. However, most of it really is internal-only. tests/wocky-test-connector-server.c | 2 +- wocky/Makefile.am | 1 + wocky/wocky-auth-registry.c | 2 +- wocky/wocky-bare-contact.c | 2 +- wocky/wocky-c2s-porter.c | 2 +- wocky/wocky-caps-cache.c | 2 +- wocky/wocky-caps-hash.c | 2 +- wocky/wocky-connector.c | 2 +- wocky/wocky-contact-factory.c | 2 +- wocky/wocky-contact.c | 2 +- wocky/wocky-data-form.c | 2 +- wocky/wocky-debug-internal.h | 86 +++++++++++++++++++++++++++++++++++++ wocky/wocky-debug.c | 2 +- wocky/wocky-debug.h | 64 --------------------------- wocky/wocky-disco-identity.c | 2 +- wocky/wocky-heartbeat-source.c | 2 +- wocky/wocky-jabber-auth-digest.c | 2 +- wocky/wocky-jabber-auth-password.c | 2 +- wocky/wocky-jabber-auth.c | 2 +- wocky/wocky-ll-connection-factory.c | 2 +- wocky/wocky-ll-connector.c | 2 +- wocky/wocky-meta-porter.c | 2 +- wocky/wocky-muc.c | 2 +- wocky/wocky-openssl.c | 2 +- wocky/wocky-pep-service.c | 2 +- wocky/wocky-ping.c | 2 +- wocky/wocky-pubsub-node.c | 2 +- wocky/wocky-pubsub-service.c | 2 +- wocky/wocky-resource-contact.c | 2 +- wocky/wocky-roster.c | 2 +- wocky/wocky-sasl-auth.c | 2 +- wocky/wocky-sasl-digest-md5.c | 2 +- wocky/wocky-sasl-plain.c | 2 +- wocky/wocky-sasl-scram.c | 2 +- wocky/wocky-stanza.c | 2 +- wocky/wocky-tls-connector.c | 2 +- wocky/wocky-tls-handler.c | 2 +- wocky/wocky-tls.c | 2 +- wocky/wocky-xmpp-reader.c | 2 +- wocky/wocky-xmpp-writer.c | 2 +- 40 files changed, 124 insertions(+), 101 deletions(-) commit 2f0be660cd161f5abcb2ab57331e85d0415415ea Author: Will Thompson Date: Tue Jan 31 16:58:02 2012 +0000 Make #include the only legal import. examples/receive-messages.c | 4 --- examples/register.c | 3 +- examples/send-message.c | 4 --- examples/unregister.c | 3 +- tests/wocky-bare-contact-test.c | 4 +-- tests/wocky-caps-hash-test.c | 3 +- tests/wocky-connector-test.c | 6 +--- tests/wocky-contact-factory-test.c | 3 +- tests/wocky-data-form-test.c | 5 +--- tests/wocky-http-proxy-test.c | 8 ++++- tests/wocky-jid-validation-test.c | 2 +- tests/wocky-loopback-test.c | 3 +- tests/wocky-node-tree-test.c | 3 +- tests/wocky-pep-service-test.c | 4 +-- tests/wocky-ping-test.c | 5 +--- tests/wocky-porter-test.c | 5 +--- tests/wocky-pubsub-node-test.c | 4 +-- tests/wocky-pubsub-service-test.c | 6 +--- tests/wocky-pubsub-test-helpers.c | 2 +- tests/wocky-pubsub-test-helpers.h | 2 +- tests/wocky-resource-contact-test.c | 3 +- tests/wocky-roster-test.c | 8 +---- tests/wocky-sasl-utils-test.c | 2 +- tests/wocky-scram-sha1-test.c | 2 +- tests/wocky-session-test.c | 3 +- tests/wocky-stanza-test.c | 5 +--- tests/wocky-test-connector-server.c | 13 ++++----- tests/wocky-test-helper.c | 2 -- tests/wocky-test-helper.h | 4 +-- tests/wocky-test-sasl-auth-server.c | 3 -- tests/wocky-test-sasl-auth-server.h | 3 +- tests/wocky-test-sasl-auth.c | 4 +-- tests/wocky-test-sasl-handler.c | 2 +- tests/wocky-tls-test.c | 3 +- tests/wocky-utils-test.c | 2 +- tests/wocky-xmpp-connection-test.c | 3 +- tests/wocky-xmpp-node-test.c | 5 +--- tests/wocky-xmpp-reader-test.c | 2 -- tests/wocky-xmpp-readwrite-test.c | 4 +-- wocky/Makefile.am | 4 ++- wocky/wocky-auth-handler.h | 3 ++ wocky/wocky-auth-registry.h | 5 +++- wocky/wocky-bare-contact.h | 3 ++ wocky/wocky-c2s-porter.h | 3 ++ wocky/wocky-caps-cache.h | 3 ++ wocky/wocky-caps-hash.h | 3 ++ wocky/wocky-connector.h | 3 ++ wocky/wocky-contact-factory.h | 3 ++ wocky/wocky-contact.h | 3 ++ wocky/wocky-data-form.h | 3 ++ wocky/wocky-debug.h | 3 ++ wocky/wocky-disco-identity.h | 3 ++ wocky/wocky-heartbeat-source.h | 4 +++ wocky/wocky-http-proxy.h | 3 ++ wocky/wocky-jabber-auth-digest.h | 4 +++ wocky/wocky-jabber-auth-password.h | 4 +++ wocky/wocky-jabber-auth.h | 3 ++ wocky/wocky-ll-connection-factory.h | 3 ++ wocky/wocky-ll-connector.h | 3 ++ wocky/wocky-ll-contact.h | 3 ++ wocky/wocky-loopback-stream.h | 3 ++ wocky/wocky-meta-porter.h | 3 ++ wocky/wocky-muc.h | 4 +++ wocky/wocky-namespaces.h | 3 ++ wocky/wocky-node-private.h | 3 ++ wocky/wocky-node-tree.h | 3 ++ wocky/wocky-node.h | 3 ++ wocky/wocky-pep-service.h | 3 ++ wocky/wocky-ping.h | 3 ++ wocky/wocky-porter.h | 3 ++ wocky/wocky-pubsub-helpers.h | 3 ++ wocky/wocky-pubsub-node-protected.h | 3 ++ wocky/wocky-pubsub-node.h | 3 ++ wocky/wocky-pubsub-service-protected.h | 3 ++ wocky/wocky-pubsub-service.h | 3 ++ wocky/wocky-resource-contact.h | 3 ++ wocky/wocky-roster.h | 3 ++ wocky/wocky-sasl-auth.h | 3 ++ wocky/wocky-sasl-digest-md5.h | 4 +++ wocky/wocky-sasl-plain.h | 4 +++ wocky/wocky-sasl-scram.h | 5 +++- wocky/wocky-session.h | 3 ++ wocky/wocky-stanza.h | 3 ++ wocky/wocky-tls-connector.h | 3 ++ wocky/wocky-tls-handler.h | 3 ++ wocky/wocky-tls.h | 3 ++ wocky/wocky-types.h | 3 ++ wocky/wocky-utils.h | 3 ++ wocky/wocky-xep-0115-capabilities.h | 3 ++ wocky/wocky-xmpp-connection.h | 3 ++ wocky/wocky-xmpp-error.h | 3 ++ wocky/wocky-xmpp-reader.h | 3 ++ wocky/wocky-xmpp-writer.h | 3 ++ wocky/wocky.h | 53 ++++++++++++++++++++++++++++++++++ 94 files changed, 268 insertions(+), 110 deletions(-) commit 4c8a53c6d00231203cab1f9f14959825a2adedb3 Author: Will Thompson Date: Tue Jan 31 16:26:57 2012 +0000 Include foo-enumtypes.h from each foo.h I think it's reasonable to assume that importing the header which gives you WockyXmppError should also give you WOCKY_TYPE_XMPP_ERROR. wocky/wocky-auth-registry.h | 1 + wocky/wocky-connector.c | 1 - wocky/wocky-connector.h | 2 +- wocky/wocky-data-form.c | 1 - wocky/wocky-data-form.h | 1 + wocky/wocky-jabber-auth.c | 1 - wocky/wocky-muc.c | 2 -- wocky/wocky-muc.h | 1 + wocky/wocky-openssl.c | 1 - wocky/wocky-pubsub-node.c | 1 - wocky/wocky-pubsub-node.h | 1 + wocky/wocky-pubsub-service.c | 1 - wocky/wocky-pubsub-service.h | 1 + wocky/wocky-sasl-auth.c | 1 - wocky/wocky-tls.c | 1 - wocky/wocky-tls.h | 2 ++ wocky/wocky-xmpp-error.c | 1 - wocky/wocky-xmpp-error.h | 1 + wocky/wocky-xmpp-reader.h | 1 + 19 files changed, 10 insertions(+), 12 deletions(-) commit fe9b08f15f346676c67c798f6f626839a0f5f71b Author: Will Thompson Date: Tue Jan 31 14:39:56 2012 +0000 AuthHandler: add a bit of documentation. wocky/wocky-auth-handler.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-auth-handler.h | 19 ++++++++------- 2 files changed, 69 insertions(+), 9 deletions(-) commit fcf4ab9b107a3a3d25a129dc86fd2edcd5188a38 Author: Will Thompson Date: Tue Jan 31 14:39:40 2012 +0000 Remove prototype for wocky_auth_handler_free() This function doesn't exist. wocky/wocky-auth-handler.h | 3 --- 1 file changed, 3 deletions(-) commit b7310bd0535931fd9afa76b124981d23ae71207f Author: Will Thompson Date: Tue Jan 31 11:25:49 2012 +0000 docs: use @... not @Varargs Apparently the latter stopped being recognized by gtk-doc at some point. :( wocky/wocky-c2s-porter.c | 2 +- wocky/wocky-node-tree.c | 2 +- wocky/wocky-node.c | 4 ++-- wocky/wocky-porter.c | 6 +++--- wocky/wocky-stanza.c | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) commit bcf78e4f3de03921f72b783c1f86f18da716fa70 Merge: f5adf2d 8a4afe1 Author: Jonny Lamb Date: Wed Feb 1 13:36:43 2012 -0500 Merge remote-tracking branch 'siraj/mingw32-warn' commit f5adf2d1141e4dfd3aeb9ca043825e66ba4a556e Author: Will Thompson Date: Wed Feb 1 13:10:50 2012 +0000 test-helper: give sched_close_cb a more debuggable assertion Asserting that wocky_porter_close_finish() returns TRUE is fine and all, but when it fails you get no information about why it failed. By passing a non-NULL GError ** parameter and asserting on that error first, we get the details of what actually happened immediately. tests/wocky-test-helper.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) commit eecef2669555c65c20a01c55b7166593bac1d96b Author: Will Thompson Date: Wed Feb 1 13:05:08 2012 +0000 porter-test: fix /handler-stanza test_close_porter() assumes test->sched_in has not been started, and calls wocky_xmpp_connection_recv_stanza_async() on test->in; the callback assumes that the call has failed with an error indicating that the stream has been closed. This would be fine if the test was sure there were no stanzas in the queue in test->in, but since my change to make WockyC2SPorter send back an error in response to unhandled IQs, this assumption is no longer true: there are error replies sitting around waiting to be handled. So this patch just makes this test turn both porters on and then use test_close_both_porters(). tests/wocky-porter-test.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 43d93377facac1a7b9bae8e898c29b245ec476f5 Author: Will Thompson Date: Fri Mar 4 10:36:26 2011 +0000 C2SPorter: reply to unhandled IQ get/sets. XMPP Core requires that we reply to all IQs we receive. If no handler claims responsibility for an incoming IQ, the porter should send back a error. (Currently, Gabble does this.) https://bugs.freedesktop.org/show_bug.cgi?id=34975 tests/wocky-porter-test.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-c2s-porter.c | 20 +++++++++++---- 2 files changed, 79 insertions(+), 5 deletions(-) commit d1896284653c29577b3ecb037406a9ab84a810df Merge: fef0ba2 f481ea9 Author: Will Thompson Date: Tue Jan 31 17:06:00 2012 +0000 Merge branch '45400-pep-service-rummage-for-items' commit fef0ba21349c8f1434ed93766b6e35c787cbbbae Author: Simon McVittie Date: Thu Jan 26 16:00:23 2012 +0000 Remove and other remnants of gcrypt This doesn't seem to be used for anything, and creates an artificial dependency on gcrypt, which GNUTLS 3 no longer uses. Verified to pass tests on Debian's gnutls26 2.12.16-1 package, but insufficient to make tests pass on gnutls28 3.0.12-1. Reviewed-by: Will Thompson Bug: https://bugs.freedesktop.org/show_bug.cgi?id=43992 Bug-Debian: http://bugs.debian.org/638420 Android.mk | 2 +- wocky/Makefile.am | 2 +- wocky/wocky-tls.c | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) commit 982b60b0b64704a84cbfa6d0156187622a73c611 Author: Simon McVittie Date: Thu Jan 26 15:08:31 2012 +0000 Use g_getenv and g_strtoull instead of getenv and atoi We don't include stdlib.h (except accidentally, via gcrypt.h), which we should if we're going to use its functions. In both cases GLib has a portable version, and our coding style is generally to prefer the GLib versions of things, so let's use those. Reviewed-by: Will Thompson Bug: https://bugs.freedesktop.org/show_bug.cgi?id=43992 wocky/wocky-tls.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) commit f481ea91d5278178ca25abd9fd1f95283d2b0794 Author: Will Thompson Date: Mon Jan 30 17:08:23 2012 +0000 PepService: update © years. wocky/wocky-pep-service.c | 2 +- wocky/wocky-pep-service.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) commit 5cd7e850bbd71605cf9e954c6a13afe8f5560dea Author: Will Thompson Date: Mon Jan 30 16:05:34 2012 +0000 PepService::changed: pass element to callback tests/wocky-pep-service-test.c | 60 +++++++++++++++++++++++++++++++++--------- wocky/wocky-pep-service.c | 16 ++++++++--- 2 files changed, 60 insertions(+), 16 deletions(-) commit 10e528fb92452b21ac67a0685ed16c24ea66cba7 Author: Will Thompson Date: Mon Jan 30 15:41:24 2012 +0000 PepService: return node from get() tests/wocky-pep-service-test.c | 9 +++++++-- wocky/wocky-pep-service.c | 22 +++++++++++++++++++++- wocky/wocky-pep-service.h | 1 + 3 files changed, 29 insertions(+), 3 deletions(-) commit 2a8023ac04fdd4a3321f08c9664e63998e8689a3 Author: Will Thompson Date: Mon Jan 30 15:31:47 2012 +0000 PepService: use G_GNUC_WARN_UNUSED_RESULT as needed. wocky/wocky-pep-service.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit 8a4afe112d4a61ffe9fa0fd629dd92fdc90e68b7 Author: Siraj Razick Date: Thu Jan 26 16:20:04 2012 -0500 Fix warnings from wocky-connector-test.c under mingw32 In windows socket API setsockopt takes a const char * as the fourth parameter, while on Linux it takes a void * so we cast to const char * which will work under both the platforms. This patch also move flags veriable in client_connected to the unix part of the ifdef, to remove warnings which shows up with mingw32. tests/wocky-connector-test.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) commit 97a5823f03850f70bbd1da12af1364adc925e494 Author: Siraj Razick Date: Thu Jan 26 16:13:18 2012 -0500 TLS: replace gsize and gssize with size_t and ssize_t gnutls_transport_set_push_function expects a function of ssize_t (*gnutls_push_func)(gnutls_transport_ptr_t, const void*, size_t); and in mingw32 gsize and gssize doesn't expend to size_t or ssize_t. this results in mingw32 builds fail due to the warning. https://bugs.freedesktop.org/show_bug.cgi?id=45272 wocky/wocky-tls.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) commit 3b6bae256972241e12a7c47b1bb821dda348b409 Author: Siraj Razick Date: Thu Jan 26 15:14:02 2012 -0500 TLS: Rename _stat variable to peer_cert_status _stat shadows a global variable defined in mingw32 so this patch renames it to peer_cert_status in wocky_tls_session_verify_peer https://bugs.freedesktop.org/show_bug.cgi?id=45272 wocky/wocky-tls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit f7d8ff028c63447e67efe87a5224419ca89bb715 Author: Simon McVittie Date: Thu Jan 26 15:07:02 2012 +0000 Fix coding style so the tests can pass tests/wocky-connector-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 44a326f3ab2aafea7a78df6ac75e9b4c014fe0e8 Author: Siraj Razick Date: Wed Dec 21 12:29:29 2011 -0500 Build fixes for Windows These changes enables us to cross-compile wocky for windows with mingw32 tests/Makefile.am | 2 +- tests/test-resolver.c | 6 ++++++ tests/wocky-connector-test.c | 24 ++++++++++++++++++++---- wocky/wocky-meta-porter.c | 8 ++++++++ 4 files changed, 35 insertions(+), 5 deletions(-) commit 8a1a8d94d40d731a8045d4fb2a67a65484a7983c Author: Alban Crequy Date: Fri Dec 16 16:15:09 2011 +0000 wocky_data_form_set_type: add default value and raw content They are needed for wocky_caps_hash_compute_from_lists(). https://bugs.freedesktop.org/show_bug.cgi?id=43891 wocky/wocky-data-form.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) commit 9e38356210772956d1d05e5eed2e485df962ceee Author: Xavier Claessens Date: Wed Dec 14 15:33:03 2011 +0100 Use G_GINT64_FORMAT instead of %li wocky/wocky-heartbeat-source.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) commit 244dd4e32315ba79d2ff340e7a87a4be3b9dd5e8 Author: Xavier Claessens Date: Wed Dec 14 12:28:36 2011 +0100 Add tests/wocky-dummy-xmpp-server.c to build system and fix it Code that we don't build won't build. .gitignore | 1 + tests/Makefile.am | 13 +++++++++++++ tests/wocky-dummy-xmpp-server.c | 15 ++++++++++----- 3 files changed, 24 insertions(+), 5 deletions(-) commit 85556079abd82cc6d86a395e5b3e9e35da1482a8 Author: Xavier Claessens Date: Wed Dec 14 10:51:58 2011 +0100 Fix build warnings with glib 2.32 tests/wocky-http-proxy-test.c | 4 ++++ tests/wocky-sasl-utils-test.c | 4 ++++ tests/wocky-test-helper.c | 3 +++ 3 files changed, 11 insertions(+) commit d1ebf26eb23a307d8e45f7b49770481151c0ab26 Author: Xavier Claessens Date: Mon Nov 7 13:00:31 2011 +0100 g_source_get_current_time() is replaced by g_source_get_time() configure.ac | 2 +- wocky/wocky-heartbeat-source.c | 52 ++++++++++++++++++------------------------ 2 files changed, 23 insertions(+), 31 deletions(-) commit 194c14c2b244eeec197261b1063e75d6f21e996c Author: Alban Crequy Date: Wed Dec 7 18:19:14 2011 +0000 test: dataforms: add a test for bug fdo#43584 https://bugs.freedesktop.org/show_bug.cgi?id=43584 tests/wocky-data-form-test.c | 47 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) commit b0a398bc4f75bf86e4e4df171df79b52e9fd3503 Author: Alban Crequy Date: Wed Dec 7 16:50:02 2011 +0000 dataforms: fix crash in add_field_to_node_using_default() field->raw_value_contents was not initialized when the field was not coming from a WockyNode. It leads to a segfault in add_field_to_node_using_default(). The following code was triggering the crash: form = g_object_new (WOCKY_TYPE_DATA_FORM, NULL); wocky_data_form_set_string (form, "field", "value", TRUE); wocky_data_form_add_to_node (form, ...); This patch initializes field->raw_value_contents when the WockyNode is created through data_form_set_value(). The unit tests are updated to check this. https://bugs.freedesktop.org/show_bug.cgi?id=43584 wocky/wocky-data-form.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) commit 1cb38f6d3ceba586e3a98be285f172fc8448becd Author: Alban Crequy Date: Wed Dec 7 16:49:40 2011 +0000 wocky_data_form_set_string: fix documentation wocky/wocky-data-form.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit 509688872eb7df6c38e1efcebc4a7eea032cfcac Merge: 1628149 9905ee7 Author: Sjoerd Simons Date: Tue Nov 29 12:51:54 2011 +0100 Merge branch 'invalid-character-test' commit 9905ee72891d4e16898f70d37a5bf4da65b438ec Author: Sjoerd Simons Date: Mon Nov 28 11:16:15 2011 +0100 Add a test for filtering non-character unicode codepoints tests/wocky-xmpp-reader-test.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) commit f4900b0325ef211a0cef27620f436daeb6ecf6d3 Author: Sjoerd Simons Date: Mon Nov 28 10:47:11 2011 +0100 Ensure all data in a WockyNode is validated according to the rules in g_utf8_validate In some cases valid utf-8, but for non-character codepoints gets send through xmpp. Other parts of the system can get confused by those (e.g. D-Bus doesn't allow them in strings). So we need to ensure that they get filtered out as soon as possible. There are two obvious places to do this, either in the XmppReader or the Nodes. Doing it in the nodes has the advantage of ensuring consistency for all data going into the Node, not just what was read from xmpp directly. Furthermore the Node api calls already copy the strings internally, which is a good place place to do the conversions if needed. wocky/wocky-node.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 102 insertions(+), 10 deletions(-) commit 16281498c3613e237b4096ee99789f80d02076c8 Author: Alvaro Soliverez Date: Fri Nov 11 15:20:06 2011 -0300 Support building under Android, modified from an original patch by Derek Foreman https://bugs.freedesktop.org/show_bug.cgi?id=42509 .gitignore | 1 + Android.mk | 32 ++++++++++++++++++++++++++++++++ wocky/Makefile.am | 9 ++++++++- 3 files changed, 41 insertions(+), 1 deletion(-) commit bcce213e495424684e2cda11f6e5559032e481b4 Author: Will Thompson Date: Fri Nov 18 13:47:51 2011 +0000 Use wocky_node_matches() in a couple of places wocky/wocky-connector.c | 3 +-- wocky/wocky-data-form.c | 3 +-- wocky/wocky-tls-connector.c | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) commit ac6bfbe70f5ac35d0b998854d3d5ae17ee55be78 Author: Will Thompson Date: Fri Nov 18 12:40:47 2011 +0000 Add wocky_node_matches{,_q} This makes it easier to verify that a node has the name and namespace you expect. Reviewed-by: Jonny Lamb wocky/wocky-node.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-node.h | 10 ++++++++++ 2 files changed, 59 insertions(+) commit 79008a4927792ddda8720d70d09948951e1b8423 Author: Will Thompson Date: Wed Nov 16 09:05:59 2011 +0000 meta-porter: emit ::sending when a child porter does wocky/wocky-meta-porter.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) commit e34be9ed3748699425ee4c4565c6a01a65f4d6d5 Author: Will Thompson Date: Wed Nov 16 08:59:33 2011 +0000 Porter: add stanza being sent to ::sending This is useful in writing an XMPP console for Gabble. wocky/wocky-c2s-porter.c | 4 ++-- wocky/wocky-porter.c | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) commit 502b3aa449dc9a2bfafd68eedf46531f31071432 Author: Will Thompson Date: Mon Jun 27 19:47:08 2011 +0100 Porter: support matching STANZA_TYPE_NONE For really specialised cases, like an XML console in Gabble, you want to be able to match stanzas of any type. The docs claim you can do this, but they lie. I could be convinced that the correct way to do this is to add a fourth method, wocky_porter_register_handler_for_any_stanza (), and that the server/anyone/from variants are unnecessary. Thoughts? https://bugs.freedesktop.org/show_bug.cgi?id=38577 tests/wocky-porter-test.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-c2s-porter.c | 43 +++++++++++++++----- wocky/wocky-meta-porter.c | 7 +++- wocky/wocky-porter.c | 56 ++++++++++++++++++++------ 4 files changed, 182 insertions(+), 24 deletions(-) commit fb661a1c9edfd362cb367535c477650f50c50889 Author: Xavier Claessens Date: Wed Nov 16 16:27:37 2011 +0100 Also replace g_byte_array_free with g_byte_array_unref tests/wocky-sasl-utils-test.c | 2 +- wocky/wocky-sasl-scram.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) commit 97c206797c9bb0f1893f845c01f28c301b92200e Author: Xavier Claessens Date: Wed Nov 16 15:55:42 2011 +0100 Use _unref instead of _free _destroy when possible.unref Replace g_(ptr_)array_free (foo, TRUE) and g_hash_table_destroy with respectively g_(ptr_)array_unref (foo) and g_hash_table_unref. I used this command to generate this patch: for f in `find -name "*.c"`; do sed -i $f -re 's/g_ptr_array_free \(([^ ,]+), TRUE\)/g_ptr_array_unref \(\1\)/'; done See Danielle's blog for explanation of possible bug _free can do: http://blogs.gnome.org/danni/2011/11/16/mistakes-with-g_value_set_boxed/ tests/wocky-roster-test.c | 2 +- tests/wocky-test-stream.c | 4 ++-- wocky/wocky-bare-contact.c | 4 ++-- wocky/wocky-c2s-porter.c | 4 ++-- wocky/wocky-caps-hash.c | 12 ++++++------ wocky/wocky-contact-factory.c | 6 +++--- wocky/wocky-disco-identity.c | 2 +- wocky/wocky-loopback-stream.c | 4 ++-- wocky/wocky-meta-porter.c | 6 +++--- wocky/wocky-pubsub-service.c | 2 +- wocky/wocky-roster.c | 8 ++++---- wocky/wocky-sasl-digest-md5.c | 4 ++-- 12 files changed, 29 insertions(+), 29 deletions(-) commit c216947c02b161eb4ab11ec8ae1b2e9b99a703ed Author: Xavier Claessens Date: Wed Nov 16 15:55:32 2011 +0100 Add coding style check for g_hash_table_destroy and g_array_free usage tools/check-c-style.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) commit a0e74a1cd04ab5e35922536f047664a5ce69c114 Author: Jonny Lamb Date: Tue Nov 15 10:04:54 2011 +0000 sasl test: fix build failure on older libsasl2s A second try. Signed-off-by: Jonny Lamb tests/wocky-test-sasl-auth-server.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) commit 7216cb27349d336dfdedf571fd0923324bce2ead Author: Jonny Lamb Date: Tue Nov 15 09:10:13 2011 +0000 sasl test: define sasl_callback_ft if not already done so We could have upped the dependency on libsasl2 but given this is just a test I thought it wasn't worth the bother of having to make sure everyone had the newer library version and blah blah blah, so I just did this. Signed-off-by: Jonny Lamb tests/wocky-test-sasl-auth-server.c | 4 ++++ 1 file changed, 4 insertions(+) commit c4e19a478599d12824dddcba83de907fa8adf310 Author: Xavier Claessens Date: Tue Oct 25 16:44:36 2011 +0200 Accept from="server.com" as stanzas coming from server Some servers does not set the full/bare jid. Fixes fdo#39057 tests/wocky-porter-test.c | 80 ++++++++++++++++++++++++++++++++++++++++++++--- wocky/wocky-c2s-porter.c | 14 +++++---- 2 files changed, 84 insertions(+), 10 deletions(-) commit ac0030bef952d974c9a6c64f73f2710add65a5fa Merge: 1db5b28 1ee6695 Author: Danielle Madeley Date: Mon Nov 7 21:54:06 2011 +1100 Merge branch 'trivia' commit 1ee66951f5cf501d139477fcff940306446520d3 Author: Danielle Madeley Date: Mon Nov 7 21:43:11 2011 +1100 wocky-muc: return NULL if a timestamp can't be determined Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=42652 wocky/wocky-muc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) commit 1db5b28824c279308adb8c110dd69c9915a6726f Merge: f0b6203 1f29491 Author: Danielle Madeley Date: Mon Nov 7 20:52:24 2011 +1100 Merge branch 'wocky-muc-gdatetime' commit f0b6203d4d50055a73680ad606f47c29f8a80525 Merge: db8b2b0 4d5b82b Author: Jonny Lamb Date: Wed Nov 2 09:19:57 2011 +0000 Merge branch 'caps-forms' commit db8b2b02c0f8e6f1f33c96a0559d2c006c765b98 Author: Sjoerd Simons Date: Tue Nov 1 09:25:22 2011 +0100 tests: Fix compilation error with libsasl2 wocky-test-sasl-auth-server.c: In function ‘test_sasl_auth_server_new’: wocky-test-sasl-auth-server.c:932:17: error: expected ‘)’ before ‘proc’ wocky-test-sasl-auth-server.c:932:22: error: expected ‘)’ before ‘(’ token wocky-test-sasl-auth-server.c:932:30: error: expected ‘}’ before ‘test_sasl_server_auth_log’ wocky-test-sasl-auth-server.c:933:5: error: initialization from incompatible pointer type [-Werror] wocky-test-sasl-auth-server.c:933:5: error: (near initialization for ‘callbacks[1].proc’) [-Werror] wocky-test-sasl-auth-server.c: At top level: wocky-test-sasl-auth-server.c:886:1: error: ‘test_sasl_server_auth_log’ defined but not used [-Werror=unused-function] tests/wocky-test-sasl-auth-server.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) commit 1f2949120297e4ac2b3abbbe916a8f9b34f702ce Author: Danielle Madeley Date: Mon Oct 17 22:39:00 2011 +1100 [muc] Port time_t to GDateTime wocky/wocky-muc.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) commit 4d5b82ba40d0481aed58ec8c19c8fc605da03379 Author: Jonny Lamb Date: Thu Oct 13 15:11:20 2011 +0100 caps-hash-test: update tests for new hashing behaviour Signed-off-by: Jonny Lamb tests/wocky-caps-hash-test.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) commit 8426f1ecd75fb086b803dffd58e7ef7a2a2b0600 Author: Jonny Lamb Date: Thu Oct 13 14:50:46 2011 +0100 caps-hash: ignore data forms with non-hidden FORM_TYPE fields Related to: fd.o#41719 Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 8 ++++++++ 1 file changed, 8 insertions(+) commit 2b9d9a1371af12ee95235a8cbad36747372abcdd Author: Jonny Lamb Date: Thu Oct 13 14:49:28 2011 +0100 caps-hash: don't bail on hashing if there's no FORM_TYPE Fixes: fd.o#41719 Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) commit 3c43751dc90e4cdb08f57f48e2a8e6adf715ed8e Author: Cosimo Cecchi Date: Wed Oct 12 17:45:49 2011 +0100 test-resolver: don't include glib/types.h directly Use the glib.h header instead. tests/test-resolver.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 6cc87601d31cbe365d3d51a8c91bfbca4cbd14f6 Author: Will Thompson Date: Wed Oct 12 16:06:21 2011 +0100 C2SPorter: correct _enable_power_saving docs was being interpreted as a docbook tag; and the second bullet is no longer true: only PEP updates in particular known namespaces are considered unimportant. wocky/wocky-c2s-porter.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) commit 400035360b8f6463c362ea35f4b4580cb52e9e77 Author: Will Thompson Date: Wed Oct 12 16:08:49 2011 +0100 gtk-doc: Fix out-of-tree builds with 1.17 configure.ac | 2 +- docs/reference/Makefile.am | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) commit 4f0c186180cf64f56072c30bca05a4272b06d2cf Author: Will Thompson Date: Wed Oct 12 16:06:42 2011 +0100 gtk-doc: use no-tmpl flavour. This stops gtk-doc even generating the legacy .tmpl files, for a marginally faster (and less crufty) documentation build process. configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 8b8603bb3bf0258b05ef8ed9051d9922d80c6753 Author: Xavier Claessens Date: Sat Oct 1 13:42:31 2011 +0200 Add wocky_auth_registry_supports_one_of() Reviewed-by: Will Thompson wocky/wocky-auth-registry.c | 147 ++++++++++++++++++++++++++++++-------------- wocky/wocky-auth-registry.h | 5 ++ 2 files changed, 105 insertions(+), 47 deletions(-) commit 069d5d347be1f97e4408cf8e59017911a50de2d3 Author: Will Thompson Date: Fri Sep 30 16:41:24 2011 +0100 NodeTree: fix _new example It was legal before, but the tree it built made no sense! wocky/wocky-node-tree.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) commit 28da3d1e5e94635a9ac7a0e886ed20dae87d8556 Author: Jonny Lamb Date: Wed Sep 7 14:57:28 2011 +0100 pubsub-helpers: add node name as attribute on items node Previously I had erroneously done this: ... ... Where actually, it should be: ... ... Bad me. Signed-off-by: Jonny Lamb wocky/wocky-pubsub-helpers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit cac7727c18341e977c12e42e5dcea4a86c4b90a4 Author: Will Thompson Date: Mon Sep 5 18:10:27 2011 +0100 C2SPorter: clear up English properly. I feel threatened. wocky/wocky-c2s-porter.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) commit 3d05bdac0d8bf77f310ecb6558121cd50bed7fbb Author: Will Thompson Date: Mon Sep 5 18:06:55 2011 +0100 C2SPorter: correctly conjugate the verb "to threaten" wocky/wocky-c2s-porter.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit 6d5932dcfc171de0b9169449c965d89e94cd797e Author: Will Thompson Date: Thu Sep 1 09:30:23 2011 +0100 Connector: change misleading “Bad SRV record” message Failing to connect to the server specified by an SRV record doesn't mean the record is wrong: it could well be that the server is broken. Reviewed-by: Danielle Madeley wocky/wocky-connector.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) commit d37c814b0ac7a38f3820a6e0d273e0b50303c373 Author: Will Thompson Date: Wed Aug 31 10:33:33 2011 +0100 connector-test: use !=, not |= Thanks, clang! Reviewed-by: Jonny Lamb tests/wocky-connector-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 891dfc761b465f5c195917b60d9fbcede54ee6d8 Author: Marco Barisione Date: Wed Aug 17 13:25:03 2011 +0100 sasl-digest-md5: the response needs both the realm and server Some of the fields in the response wocky sends to the server require the realm (like the "realm" field) while others require the server name (like the "digest-uri" field). Usually this bug is not noticeable as the realm and the server name are the same. Reviewed-by: Vivek Dasmohapatra wocky/wocky-sasl-digest-md5.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit c6850584919e4f2f1ab2644c67e6a2ee024d61a9 Merge: 5ba6fef 0396dd2 Author: Marco Barisione Date: Fri Aug 5 15:19:53 2011 +0100 Merge branch 'gabble-0.12' commit 0396dd2a97f3dcf3709ed3fe0582262df04bd95e Author: Siraj Razick Date: Wed Jul 20 22:10:14 2011 +0530 Use GQueue instead of GList* for queueable_stanza_pattern wocky/wocky-c2s-porter.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) commit 051a35f63b42d6d5ef274b12a606ec30821ab1b7 Author: Siraj Razick Date: Wed Jul 20 20:38:52 2011 +0530 Avoid filtering all PEP messages This patch filters only a fixed set of PEP messages, with +notify wocky/wocky-c2s-porter.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) commit 5ba6fef79f37d1dd1f112db12e539fc8e74c23e3 Merge: 73d9ace e1c92e2 Author: Marco Barisione Date: Wed Aug 3 14:28:26 2011 +0100 Merge branch 'whitespace-ping' Reviewed-by: Will Thompson Fixes: commit e1c92e217e7e2ada88333047f18fd1150b1b2299 Author: Marco Barisione Date: Mon Aug 1 13:28:06 2011 +0100 ping: send whitespace pings instead of XMPP ones Whitespace pings can save power on cellular connections. The code to reply to XMPP pings is left untouched as other clients or the server could ping us. tests/wocky-ping-test.c | 34 ++++++++++++++++++++-------------- wocky/wocky-ping.c | 23 +++++++++-------------- 2 files changed, 29 insertions(+), 28 deletions(-) commit dc03988d9d55d02a941c2c89fdaa4324f1b3f18c Author: Marco Barisione Date: Tue Aug 2 14:36:06 2011 +0100 wocky-test-stream: allow to get notified directly whenever data is read The callback passed to wocky_test_stream_set_direct_read_callback() is called whenever data is read by-passing all the other layers on top. tests/wocky-test-stream.c | 16 ++++++++++++++++ tests/wocky-test-stream.h | 6 ++++++ 2 files changed, 22 insertions(+) commit 461cc42da79bbc77d24a13577deed477440b3493 Author: Marco Barisione Date: Mon Aug 1 13:10:15 2011 +0100 c2s-porter: add send_whitespace_ping_(async|finish) methods wocky/wocky-c2s-porter.c | 143 ++++++++++++++++++++++++++++++++++++++++++++--- wocky/wocky-c2s-porter.h | 11 ++++ 2 files changed, 145 insertions(+), 9 deletions(-) commit 4bbb2d9ad5293dc717c06c3999d5576969051793 Author: Marco Barisione Date: Mon Aug 1 13:17:18 2011 +0100 c2s-porter: share the code to terminate the pending operations wocky/wocky-c2s-porter.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) commit 8fa37b29cc4399ac69c33c4ae4f196e38fa68892 Author: Marco Barisione Date: Mon Aug 1 13:01:58 2011 +0100 xmpp-connection: add send_whitespace_ping_(async|finish) methods wocky/wocky-xmpp-connection.c | 93 +++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-connection.h | 10 +++++ 2 files changed, 103 insertions(+) commit e18970ce5108903b412fd95f94c38bd3e987e480 Author: Marco Barisione Date: Fri Jul 29 14:32:56 2011 +0100 ping: make the "porter" property a WockyC2SPorter Keepalives don't make sense on meta porters. tests/wocky-ping-test.c | 6 ++++-- wocky/wocky-ping.c | 19 +++++++++++-------- wocky/wocky-ping.h | 4 ++-- 3 files changed, 17 insertions(+), 12 deletions(-) commit 73d9acef993e4bc1ca4709815fef390eb324eb58 Merge: 4a16e1c f46210d Author: Marco Barisione Date: Wed Aug 3 14:25:49 2011 +0100 Merge branch 'stream-ciphers' Reviewed-by: Will Thompson Fixes: commit f46210d0fb3a7333b61ba3d02b6760d398be7b49 Author: Marco Barisione Date: Mon Aug 1 17:03:02 2011 +0100 openssl: prefer stream ciphers when --enable-stream-ciphers is used wocky/wocky-openssl.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) commit 3f091f2ff4e97a533142b88f8b8844c53e579ea4 Author: Marco Barisione Date: Mon Aug 1 16:59:22 2011 +0100 tls: prefer stream ciphers when --enable-stream-ciphers is used In case this option is used gnutls 2.12.0 is needed. configure.ac | 7 +++++++ wocky/wocky-tls.c | 27 +++++++++++++++++++++++---- 2 files changed, 30 insertions(+), 4 deletions(-) commit e71f2054f4e6a593b9296ba761fcf6d94c8f980c Author: Marco Barisione Date: Mon Aug 1 16:56:31 2011 +0100 configure: add an --enable-prefer-stream-ciphers option configure.ac | 11 +++++++++++ 1 file changed, 11 insertions(+) commit 4a16e1cb80ad124726f7e517b0d141bf5b921788 Merge: 5f5db5c faf9011 Author: Will Thompson Date: Wed Jul 27 14:29:18 2011 +0100 Merge branch 'gabble-0.12' Conflicts: wocky/wocky-muc.c commit faf9011d6d9ee075deaee3ff4ea77a73c17561cd Author: Sjoerd Simons Date: Tue Jul 26 11:01:11 2011 +0100 s/WockyTestSTreamReadMode/WockyTestStreamReadMode/ tests/wocky-test-stream.c | 4 ++-- tests/wocky-test-stream.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) commit 4518b2c17508ff427aa6d4f253e660b0da98a2b0 Author: Sjoerd Simons Date: Tue Jul 26 10:31:22 2011 +0100 Rename the tls test from /openssl to /tls to avoid confusion tests/wocky-tls-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 2dfc0356903962e457b185135f0122ac18f99254 Author: Sjoerd Simons Date: Tue Jul 26 10:28:39 2011 +0100 Make the tls test send a big chunk of data To make sure we stress some more codepaths, send more data then what will fit in an SSL Record (16k in gnutls it seems). Randomly generate the data to make sure it doesn't compress well enough such that what needs to be sent out is actually small enough tests/wocky-tls-test.c | 58 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 11 deletions(-) commit 1051de8fc4fdb26ed08f7029a1ff9a571775708c Author: Sjoerd Simons Date: Tue Jul 26 10:05:41 2011 +0100 Add an incomplete write mode to the test-stream To stress the various bit of code a bit more, make writes by default never succeed completely. Only write half the buffer that is given to us as this causes some more code-paths to be tested. Unfortunately some tests seem to be too sensitive to this. So switch them back to the old write mode. tests/wocky-porter-test.c | 10 +++++++++- tests/wocky-test-stream.c | 18 +++++++++++++++--- tests/wocky-test-stream.h | 10 ++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) commit 502a365c34c9b684bb586e0761c0ce762fcd5d2b Author: Sjoerd Simons Date: Tue Jul 26 10:40:17 2011 +0100 Always write out all data gnutls requested Because of a bug in the gnutls backend our outgoing stream would get stalled if we couldn't write enough data as _try_operation doesn't properly check what caused GNUTLS_E_AGAIN. Unfortunately if we fix that, we trigger bugs in GnuTLS (now fixed in gnutls git), which break the invariants of the push function. To keep compatibility with older gnutls, simply make our backend always try to write out all data gnutls asked us for. Doing so guarantees that GNUTLS_E_AGAIN will never be caused by a partial write. wocky/wocky-tls.c | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) commit 5f5db5c78ee12adc08e36d3bede1b10615838715 Author: Will Thompson Date: Fri Jul 8 14:43:28 2011 +0100 Connector tests: always check return when expecting failure Previously, when we were expecting a specific error code to be returned, we would not check that the connector had returned NULL rather than a WockyXmppConnection. This had the side-effect that, when these cases failed, the test would segfault (because 'error' was NULL) rather than producing a meaningful assertion failure. tests/wocky-connector-test.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) commit 511c0b934912a5591ed16346bd0dd35f76edf601 Author: Will Thompson Date: Fri Jul 8 14:29:44 2011 +0100 configure: set HAVE_LIBSASL2=no if we don't have it This fixes the configure summary. Previously it would say (for instance): Features: TLS Backend..........: openssl SASL2 Tests..........: gtk-doc documentation: no libiphb integration..: no With this change, it reads: Features: TLS Backend..........: openssl SASL2 Tests..........: no gtk-doc documentation: no libiphb integration..: no configure.ac | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 6386d79ceae96fd26de83de8f3747e628005ca77 Author: Will Thompson Date: Fri Jul 8 14:24:52 2011 +0100 Fix GnuTLS build with --disable-debug Sorry, I must have missed this while juggling unneeded patches. wocky/wocky-tls.c | 2 -- 1 file changed, 2 deletions(-) commit b3cbfa07168c8721c7874e0e76b62b5443f280cc Merge: 35b2171 8245688 Author: Will Thompson Date: Fri Jul 8 14:10:01 2011 +0100 Merge branch 'debug-stubs' https://bugs.freedesktop.org/show_bug.cgi?id=39046 Reviewed-by: Guillaume Desmottes commit 824568824e078ce57df6841aeb54ca90a7865667 Author: Will Thompson Date: Thu Jul 7 16:50:20 2011 +0100 Replace stub DEBUG macros with no-op static inline functions Previously, if --disable-debug was passed to configure, DEBUG (and DEBUG_STANZA and DEBUG_NODE_TREE) were defined to expand to 'do { } while (0)'. This meant that the arguments passed to them were not actually present in the pre-processed C source, which often triggered warnings about assigning to variables and never reading from them. Instead, we define them to be variadic static inline functions. The compiler should optimize this away, but since we do not use -Wunused-arguments the call should still count as reading from the variable, and thus set-but-unused warnings will not be triggered. This means we don't have to mess around wrapping code to initialize variables only used in debug messages with #ifdef ENABLE_DEBUG any more. It's true that, if the compiler is insufficiently smart, this might cause a small amount of unnecessary work to be done at runtime—for instance, ping_iq_cb retrieves the from='' attribute of the stanza it's replying to—but none of these are likely to be too expensive (compared to the cost of constantly calling wocky_debug(), which is the real reason that --disable-debug exists). I am proud of this trick. wocky/wocky-debug.h | 28 +++++++++++++++++++--------- wocky/wocky-ping.c | 2 -- wocky/wocky-xmpp-reader.c | 2 -- 3 files changed, 19 insertions(+), 13 deletions(-) commit 87388e9a381bac19d9ebcd900d1382f4ea37b13a Author: Will Thompson Date: Thu Jul 7 16:29:56 2011 +0100 TLS: use GEnum for WockyTLSVerificationLevel names This both simplifies the code, and squashes a set-but-unused warning when building with --disable-debug. wocky/wocky-openssl.c | 11 +++-------- wocky/wocky-tls.c | 10 ++++------ 2 files changed, 7 insertions(+), 14 deletions(-) commit 4c0dacf431b9e3da2296b9a1d3918f03734b7c96 Author: Will Thompson Date: Thu Jul 7 15:41:48 2011 +0100 GnuTLS: remove a massive row of asterisks This function defines a static lookup table mapping GnuTLS certificate status enum members to Wocky's equivalent. It is prefixed by a comment containing English prose, and is followed by a comment containing a row of seventy-one asterisks. This patch removes seventy-three asterisks, two forward slashes, four spaces and a newline. wocky/wocky-tls.c | 1 - 1 file changed, 1 deletion(-) commit 35b217123b9cde48ba7a3e963c8c172fb0c91591 Merge: c5b4ef6 bdcaaaa Author: Marco Barisione Date: Thu Jul 7 14:17:00 2011 +0100 Merge branch 'extra-certificate-identities' Reviewed-by: Will Thompson commit bdcaaaa767974d1a0ea80f6c068616e80938b7da Author: Marco Barisione Date: Tue Jun 28 15:34:33 2011 +0100 openssl: check the certificate name against the extra identities too wocky/wocky-openssl.c | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) commit 34dd84db74d67b9072620afe14c82a7da12b6086 Author: Marco Barisione Date: Tue Jun 28 15:34:03 2011 +0100 tls: check the certificate name against the extra identities too wocky/wocky-tls.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 4 deletions(-) commit 31d6355ec34bda6862c90a9b355dfc63339f34ad Author: Marco Barisione Date: Tue Jul 5 17:30:56 2011 +0100 tls: rename the variable for the number of peers for clarity wocky/wocky-tls.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) commit e2cbe9608be709a4c7a6b9be2edcd46622ec440f Author: Marco Barisione Date: Tue Jun 28 15:33:34 2011 +0100 tls: rearrange wocky_tls_session_verify_peer() to reduce code duplication wocky/wocky-tls.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) commit c6a14a4806128310cdfaaf406f241efa2175dcf2 Author: Marco Barisione Date: Tue Jun 28 15:33:12 2011 +0100 tls: style fix; add missing braces around a long if block wocky/wocky-tls.c | 90 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 46 insertions(+), 44 deletions(-) commit ecfb927b8685729fdcb8faa2fba48874c307276b Author: Marco Barisione Date: Tue Jun 28 15:32:42 2011 +0100 Add an extra_identify argument to the TLS verification functions We need to be able to pass extra host names that we consider valid to the code that verifies TLS certificates. This is useful, for instance, when using Google apps. Rather than providing a certificate for the JID’s domain part, the server provides a certificate for talk.google.com; if the user has explicitly configured a ‘Google Talk’ account, it's reasonable to accept certificates for this domain. wocky/wocky-connector.c | 4 ++-- wocky/wocky-openssl.c | 1 + wocky/wocky-tls-connector.c | 6 +++++- wocky/wocky-tls-connector.h | 1 + wocky/wocky-tls-handler.c | 26 ++++++++++++++++++-------- wocky/wocky-tls-handler.h | 2 ++ wocky/wocky-tls.c | 1 + wocky/wocky-tls.h | 1 + 8 files changed, 31 insertions(+), 11 deletions(-) commit c5b4ef67402decceb4ab70537292cdb3bc75ccff Author: Will Thompson Date: Thu Jun 2 11:43:16 2011 +0100 OpenSSL: squash GCC 4.6 -Wunused-but-set-variable warnings Ironically these variables were added to squash warnings from static analysis … Reviewed-by: Jonny Lamb Fixes: wocky/wocky-openssl.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) commit 97f469e3b33c3d8c5ec4505096fce06539a421d7 Author: Jonny Lamb Date: Thu Jul 7 08:12:58 2011 +0100 meta-porter: deal with bad addresses on incoming connections Someone was running "nmap localhost" (get out more) and Salut was asserting because g_socket_connection_get_remote_address was returning NULL but we weren't dealing with it. Let's deal with it properly. Fixes: fd.o#39018 Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) commit 262c7b199e4b02285be38505727e64c3796e4b79 Author: Will Thompson Date: Thu Jun 9 16:56:17 2011 +0100 Connector: clarify debug in host fallback path. wocky/wocky-connector.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) commit 1260c3dd450241307043b2c4c66addf38bdb4e48 Author: Will Thompson Date: Thu Jun 9 16:52:09 2011 +0100 Connector: make XMPP version='' debug message NULL-safe This is safe on Linux, but will inevitably slip through unnoticed on a hypothetical Win32 port and crash for some poor user. wocky/wocky-connector.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 243c846e0abc10884e484ee6c0de95147ad28bf3 Author: Will Thompson Date: Thu Jun 9 16:49:24 2011 +0100 Connector: clarify legacy auth selection I think this is clearer than a goto. wocky/wocky-connector.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) commit 1704ac6716e2b983f3c53bc609bdce6f35a17739 Author: Will Thompson Date: Thu Jun 9 16:36:17 2011 +0100 Legacy auth: document jabberd 1.4 workaround While debugging a completely unrelated issue, I was pretty surprised to see that the username was included in the initial get. Some git archaeology turned up the reason. So let's document this in the code and in the regression test. tests/wocky-test-connector-server.c | 12 +++++++++--- wocky/wocky-jabber-auth.c | 5 +++++ 2 files changed, 14 insertions(+), 3 deletions(-) commit 955e09193a3935ea496545b507a9ce667b2693fe Author: Will Thompson Date: Wed Jun 1 13:43:41 2011 +0100 MUC: allow own presence to be passed to other handlers This is, roughly speaking, a backport of 9064ddf. Fixes: wocky/wocky-muc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 9064ddfd7afd83c892f65be8365dec242dcce880 Author: Will Thompson Date: Wed Jun 1 13:43:41 2011 +0100 MUC: allow own presence to be passed to other handlers Fixes: wocky/wocky-muc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit e3b3e06417dd95e9b36b0bcc4a2ca8d8a437fd5c Author: Will Thompson Date: Wed Jun 1 11:49:32 2011 +0100 MUC: remove now-unnecessary goto This does not modify the values returned by handle_presence_standard() in each case. wocky/wocky-muc.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) commit 961ab6f804ef504b7d0555fd1932d0d66785f22b Author: Will Thompson Date: Tue May 31 18:16:40 2011 +0100 MUC: early-return for presence without There are no code changes in this commit: it's just turning a big if block into an early return. wocky/wocky-muc.c | 174 +++++++++++++++++++++++++++--------------------------- 1 file changed, 87 insertions(+), 87 deletions(-) commit 191337045819cbdd2781c03e652ca2551ce3ede9 Author: Will Thompson Date: Tue May 31 18:05:05 2011 +0100 MUC: hoist JID decoding up to main handler The sub-handler actually didn't use the JID components at all, it just parsed it for fun. And the other sub-handler only uses the resource. It's neater to pull extracting that into the top handler: it'll save us needing a 'goto' for cleanup. wocky/wocky-muc.c | 50 +++++++++++++++++--------------------------------- 1 file changed, 17 insertions(+), 33 deletions(-) commit bf3d194a15e5efd870a8df48873564897c06270e Author: Will Thompson Date: Tue May 31 17:53:35 2011 +0100 MUC: remove redundant checks We know that presence stanzas passed to this callback have a from='', and that it's right, because we specified it when calling wocky_porter_register_handler_from(). And we know that they're presence stanzas, for the same reason. wocky/wocky-muc.c | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) commit b37d550628783049c3cbb36e7d4c775e2269c068 Author: Will Thompson Date: Tue May 31 17:44:24 2011 +0100 MUC: simplify extracting from It's technically legal to have more than one within : Multiple instances of the element MAY be included but only if each instance possesses an 'xml:lang' attribute with a distinct language value. — http://xmpp.org/rfcs/rfc3921.html#rfc.section.2.2.2.2 So what we were doing before (concatenating the contents of all of them) is even more wrong than just picking the first one. wocky/wocky-muc.c | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) commit 6c1e30ecb10ff10391437d16275fb1e20ff52915 Author: Will Thompson Date: Tue May 31 17:18:57 2011 +0100 MUC: represent status code set as a bitfield wocky/wocky-muc.c | 124 ++++++++++++++++++++++-------------------------------- 1 file changed, 51 insertions(+), 73 deletions(-) commit 80289030646436225c6f6e8cc9ce5fd9025238ab Author: Will Thompson Date: Tue May 31 16:56:18 2011 +0100 MUC: use a node iterator when parsing status codes wocky/wocky-muc.c | 56 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 26 deletions(-) commit 0a764d2151bdda2d6d5314122110faf0fd2f4dc8 Author: Will Thompson Date: Tue May 31 16:48:13 2011 +0100 MUC: remove weird casts when parsing status codes wocky/wocky-muc.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) commit 4e4ad3674b7f96f4fdfc39375715aff6b703ef7c Author: Will Thompson Date: Tue May 31 16:39:46 2011 +0100 MUC: document WockyMucStatusCode marginally more usefully wocky/wocky-muc.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 0d7c58ce7fcf3b909857147afc38571bdd0bf689 Author: Will Thompson Date: Tue May 31 16:34:40 2011 +0100 MUC: turn status code enum into bit flags wocky/wocky-muc.h | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) commit 3db3ab03828b5d953a8cf05c95f995e5cb8e27b9 Merge: 07a2269 161e973 Author: Marco Barisione Date: Mon May 16 16:37:39 2011 +0100 Merge branch 'iphb-system-sync' Reviewed-by: Simon McVittie Fixes: commit 161e97327b1cf1b3013801f86c9e86f2a945017f Author: Marco Barisione Date: Wed May 11 18:29:24 2011 +0100 Heartbeat: synchronise the wakeups with other applications wocky/wocky-heartbeat-source.c | 61 +++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 15 deletions(-) commit 06e8d6978a7a9a28b1d34b1d079e8e33d48e1267 Author: Marco Barisione Date: Mon May 16 15:01:57 2011 +0100 configure: depend on libiphb >= 0.61.31 The newer libiphb is needed to help synchronisation between multiple applications. configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 07a226925f7fccad7d38dc165318858f76f36bd3 Merge: 7608a03 3c2ab01 Author: Jonny Lamb Date: Wed May 4 09:50:59 2011 +0100 Merge branch 'ns' commit 3c2ab0158eabc1e82e1cadb457719ffddc6cc3d5 Author: Jonny Lamb Date: Wed May 4 09:07:08 2011 +0100 namespaces: include both jabber:iq:oob and jabber:x:oob Nothing appears to use the old WOCKY_XMPP_NS_OOB, so I don't think this will break anything. Signed-off-by: Jonny Lamb wocky/wocky-namespaces.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) commit 7608a038991602233a146e3fa8d2d770d599ca34 Author: Will Thompson Date: Tue May 3 16:00:55 2011 +0100 MetaPorter: fix chaining up to constructed. (I'd forgotten to actually amend the patch. Whoops.) wocky/wocky-meta-porter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit f7b2930b22d9bcb1d964b12110ee5d320694400e Author: Will Thompson Date: Tue May 3 15:40:58 2011 +0100 Porters: chain up in constructed Reviewed-by: Jonny Lamb wocky/wocky-c2s-porter.c | 3 +++ wocky/wocky-meta-porter.c | 3 +++ 2 files changed, 6 insertions(+) commit d4f7e060c7e967bc0d78a823e88b3b45390dcff6 Author: Jonny Lamb Date: Tue May 3 10:03:22 2011 +0100 ll-connector: remove set but unused variable Signed-off-by: Jonny Lamb wocky/wocky-ll-connector.c | 3 --- 1 file changed, 3 deletions(-) commit 3d127bedd7da28a6af3e32334ce8545f1cb7369e Author: Marco Barisione Date: Thu Apr 28 17:50:28 2011 +0100 openssl: maintain compatibility with OpenSSL < 1.0 too Reviewed-by: Sjoerd Simons wocky/wocky-openssl.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) commit 471b25356420d33670a18b8310cfd2c7bfd9efdd Author: Jonny Lamb Date: Thu Apr 28 14:32:32 2011 +0100 xmpp-reader: ifdef out a variable that's only used in a DEBUG call Signed-off-by: Jonny Lamb wocky/wocky-xmpp-reader.c | 2 ++ 1 file changed, 2 insertions(+) commit 5455a6c494e2f65e8a3ba7cd0f955e02f3d65af9 Author: Jonny Lamb Date: Fri Apr 22 12:12:25 2011 +0100 data-form: add more docs for add_to_node() Signed-off-by: Jonny Lamb wocky/wocky-data-form.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) commit a56c69c450c0062797903a1a468f3db2399108f1 Author: Jonny Lamb Date: Fri Apr 22 11:56:05 2011 +0100 data-form: add a add_to_node function This is for adding a data form to an existing node like the query node of a disco response. Signed-off-by: Jonny Lamb wocky/wocky-data-form.c | 35 +++++++++++++++++++++++++++++++++++ wocky/wocky-data-form.h | 2 ++ 2 files changed, 37 insertions(+) commit 65d4af1972fc4b7d3519421ec7080b07c23a88ae Author: Jonny Lamb Date: Fri Apr 22 11:54:53 2011 +0100 xep-0115-capabilities: add TODO for features and identities Signed-off-by: Jonny Lamb wocky/wocky-xep-0115-capabilities.h | 1 + 1 file changed, 1 insertion(+) commit 7462be59c033f03804c754ddb13c80e2f97c88aa Author: Jonny Lamb Date: Fri Apr 22 09:18:28 2011 +0100 session: add get_jid() function Signed-off-by: Jonny Lamb wocky/wocky-session.c | 8 ++++++++ wocky/wocky-session.h | 2 ++ 2 files changed, 10 insertions(+) commit d118866339f92736be01b7bdf10ef48694f77037 Author: Jonny Lamb Date: Tue Apr 19 13:17:32 2011 +0100 XEP-0115 capabilities: add interface Signed-off-by: Jonny Lamb wocky/Makefile.am | 2 ++ wocky/wocky-xep-0115-capabilities.c | 60 ++++++++++++++++++++++++++++++++++ wocky/wocky-xep-0115-capabilities.h | 65 +++++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+) commit c3f7e85443d95a762cd804adeb42c13f0f9b2a43 Merge: a36dd1f deb4840 Author: Jonny Lamb Date: Fri Apr 22 08:57:16 2011 +0100 Merge branch 'caps-hash' Conflicts: docs/reference/wocky-docs.sgml wocky/Makefile.am Signed-off-by: Jonny Lamb commit deb4840972ef760c2c24d03c81e73f4d060adfb6 Author: Jonny Lamb Date: Tue Apr 19 12:10:41 2011 +0100 data-form: rename default_value_str to raw_value_contents Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 6 +++--- wocky/wocky-data-form.c | 30 +++++++++++++++--------------- wocky/wocky-data-form.h | 2 +- 3 files changed, 19 insertions(+), 19 deletions(-) commit 7567223d6898d9b52e2ca4e7dcf913dd07f01763 Author: Jonny Lamb Date: Mon Apr 11 17:07:18 2011 +0100 data-form: change the default_value_str field struct member to hold a strv This moves the converting different GValue types to strings from the caps hash code back into the data form code and simplifies things. Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 96 ++++++++++++------------------------------------- wocky/wocky-data-form.c | 69 ++++++++++++++++++++--------------- wocky/wocky-data-form.h | 6 ++-- 3 files changed, 66 insertions(+), 105 deletions(-) commit b1b031b49febb4323679cbb3f64d6f1c4611393a Author: Jonny Lamb Date: Mon Apr 4 12:53:51 2011 +0100 caps-hash: use the actual string value when hashing boolean default values Signed-off-by: Jonny Lamb tests/wocky-caps-hash-test.c | 74 ++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-caps-hash.c | 11 ++----- 2 files changed, 77 insertions(+), 8 deletions(-) commit c2a09a2edac255c0e1fa592cfd4ae8a582fd138d Author: Jonny Lamb Date: Mon Apr 4 12:53:20 2011 +0100 data-form: add another member to Field struct for actual boolean values Signed-off-by: Jonny Lamb wocky/wocky-data-form.c | 47 ++++++++++++++++++++++++++++++++++------------- wocky/wocky-data-form.h | 3 +++ 2 files changed, 37 insertions(+), 13 deletions(-) commit f26dd38b1a97e34093e009b633cad54b43141d8b Author: Jonny Lamb Date: Mon Apr 4 13:27:47 2011 +0100 caps-hash: check whether there are multiple forms with the same name during, not before Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) commit a36dd1fec168abf1924757aeba7124172b9a79f5 Author: Jonny Lamb Date: Thu Apr 7 10:47:31 2011 +0100 meta-porter: use a union to avoid strict aliasing problems This solution was taken from my solution to the same thing in https://bugzilla.gnome.org/show_bug.cgi?id=646082. Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) commit 697698e42a67057d176dd45d6b5f6cb98bb7b9ee Author: Sjoerd Simons Date: Thu Apr 7 11:01:27 2011 +0200 Save const returns in const variables wocky/wocky-openssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit b032eb73fe610b0e90e1f7bcd3a361607b607aa9 Author: Jonny Lamb Date: Thu Apr 7 10:10:43 2011 +0100 meta-porter: add a FIXME for the v6-in-v4 functions Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 2 ++ 1 file changed, 2 insertions(+) commit a4db103910f0e9768945c8ae222778bdda59ca7b Author: Jonny Lamb Date: Thu Apr 7 09:34:03 2011 +0100 c2s-porter: don't blindly disconnect the IQ handler cancellable Signed-off-by: Jonny Lamb wocky/wocky-c2s-porter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) commit 7c920ba2ac8cf5c9757c2c39a4fc0b2e61f707eb Author: Jonny Lamb Date: Wed Apr 6 14:39:16 2011 +0100 meta-porter: hack around v6-in-v4 addresses being exposed This commit should be reverted when we depend on a GLib new enough to fix bgo#646082. Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 54 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) commit 3b75abc45c51f18be79ac15685efc28ecc822851 Author: Jonny Lamb Date: Wed Apr 6 10:34:02 2011 +0100 meta-porter: disconnect porter signal handlers before trying to close it Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 6 ++++++ 1 file changed, 6 insertions(+) commit d208ffca52be5d0a0e585db8ea6d592ce84edfaa Author: Jonny Lamb Date: Wed Apr 6 10:32:58 2011 +0100 meta-porter: clean up porter closing callbacks They all share more code now, the signal handler disconnection is in its own function and the porter timeouts are no longer removed. Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) commit b2304457ef55403509d7c4df85d968dc12410be1 Author: Jonny Lamb Date: Wed Apr 6 10:22:20 2011 +0100 contact-factory: weak unref an existing LL contact if we're replacing it Also, stop making more dups of JIDs than necessary, again. Signed-off-by: Jonny Lamb wocky/wocky-contact-factory.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) commit 9d4802deb229e4a104c5dabea9fb1575c4cdd106 Author: Jonny Lamb Date: Tue Apr 5 16:57:11 2011 +0100 meta-porter: don't start multiple timeouts for freeing the PorterData 1. open a connection to a contact 2. create a PorterData struct, the timeout starts 3. call hold, the timeout stops 4. remote contact closes connection, the porter disappears and the timeout stops 5. call unhold, the refcount is now 0 so the timeout starts 6. a new connection appears for the contact so it's referenced by the PorterData struct and a timeout is started BINGO! THAT'S TWO TIMEOUTS STARTED! 7. the first timeout is called, the porter is closed and struct freed 8. the second timeout is called, the struct is already freed so we crash here I think this is the right fix, because this means that if you hold() the PorterData struct will stay around, but if you unhold() it will disappear. Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 5 +++++ 1 file changed, 5 insertions(+) commit 63b8269d73a285dd35873a843d52674869c6ddf3 Author: Jonny Lamb Date: Tue Apr 5 13:36:43 2011 +0100 contact-factory: don't dup a string twice when once will do Signed-off-by: Jonny Lamb wocky/wocky-contact-factory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit b93eb03e0ba117392ecdc40b23ad9a54af1ce3a7 Author: Jonny Lamb Date: Tue Apr 5 11:51:41 2011 +0100 gitignore: ignore more emacs rubbish Signed-off-by: Jonny Lamb .gitignore | 1 + 1 file changed, 1 insertion(+) commit 35dd2dc08c83bd24af209b952dff8f6f9c075161 Author: Jonny Lamb Date: Fri Apr 1 14:48:10 2011 +0100 meta-porter: don't assert if we have another connection It turns out this assertion was being hit a little too often and it was actually somewhat feasible. Let's clear up new connections when they're not needed. I thought about adding some kind of support for multiple porters for this case but it got a bit hairy and I feel that if you already have an open connection to a contact and another appears, this is possibly a bug elsewhere. Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) commit 1769216bed3a8633cebd1e15bc79d0cb72bb3088 Author: Jonny Lamb Date: Fri Apr 1 14:48:00 2011 +0100 meta-porter: stamp on a from contact for IQ replies too Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) commit c74ca7ea411cca7ee49b77532a5aa2611e8f9faa Author: Jonny Lamb Date: Fri Apr 1 09:54:43 2011 +0100 meta-porter: also connect to WockyC2SPorter::remote-error Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) commit c7db5937c099717d508c488c724531131293f4c7 Merge: 637c8b2 3507a19 Author: Jonny Lamb Date: Thu Mar 31 13:14:02 2011 +0100 Merge branch 'meta-fixes' commit 637c8b2ebe4df64bf2733efb3ca15a2033254f69 Author: Jonny Lamb Date: Wed Mar 23 16:44:28 2011 +0000 stanza: add wocky_stanza_copy Signed-off-by: Jonny Lamb tests/wocky-stanza-test.c | 34 ++++++++++++++++++++++++++++++++++ wocky/wocky-stanza.c | 14 ++++++++++++++ wocky/wocky-stanza.h | 2 ++ 3 files changed, 50 insertions(+) commit 3507a196e2f72a1693c24f03339260ba52d0e195 Author: Jonny Lamb Date: Thu Mar 31 11:05:50 2011 +0100 meta-porter: unref async result after calling a method on the source object Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 3db9f852cb1cef9fea984cc52bbe8b24a9903237 Author: Jonny Lamb Date: Thu Mar 31 09:32:42 2011 +0100 meta-porter: store the contact JID on the actual C2S porter object Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) commit afcf1727d6fe7a5a0123c47034165bd87e7679ca Author: Jonny Lamb Date: Thu Mar 31 09:32:09 2011 +0100 meta-porter: use g_clear_error Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) commit 49a90d75db307249e41311b796092d91f9f2f90c Author: Jonny Lamb Date: Thu Mar 31 09:30:59 2011 +0100 meta-porter: close a porter properly before disposing it Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) commit 01548dd48a90b8f56a6a0d8763a26b1a71b0f9d2 Author: Jonny Lamb Date: Thu Mar 31 09:30:13 2011 +0100 meta-porter: keep a ref on self during connecting a connection Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) commit 37da8370cac07133af6d36a3b8403b70405ef220 Author: Jonny Lamb Date: Thu Mar 31 09:29:30 2011 +0100 meta-porter: also debug what IP a new connection is from Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) commit 9c4b6aaabcd57a48c8ae7c2e734e419336347c61 Author: Jonny Lamb Date: Thu Mar 31 09:27:38 2011 +0100 meta-porter: unref async result after calling a method on the source object Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) commit dcfc45feb4373968989fd3e1cd9ffe3d0d5786da Author: Jonny Lamb Date: Thu Mar 31 09:26:57 2011 +0100 meta-porter: get the property name for the socket connection right Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit b796e6c3a625a86c71c3928426f79b07a91d2b7a Author: Jonny Lamb Date: Thu Mar 31 09:23:56 2011 +0100 ll-connector: remove unnecessary unrefs of self Whoops, added by mistake. Signed-off-by: Jonny Lamb wocky/wocky-ll-connector.c | 3 --- 1 file changed, 3 deletions(-) commit 8b2fcd085171fe72c368595ed4aa8808c52af047 Author: Jonny Lamb Date: Thu Mar 31 09:23:03 2011 +0100 contact-factory: ensure we don't get a NULL when ensuring a LL contact This crashes inside GHashTable as it's looking for a NULL key. Signed-off-by: Jonny Lamb wocky/wocky-contact-factory.c | 2 ++ 1 file changed, 2 insertions(+) commit c75d42181919d270da1c2ef2b9139781dbed1517 Merge: f13a64a 8e47aa9 Author: Will Thompson Date: Tue Mar 29 14:28:54 2011 +0100 Merge branch 'whitespace-only-bodies' Reviewed-by: Jonny Lamb Fixes: commit 8e47aa9b34b7fb8957e3b7be74d7c8dc7f49f39e Author: Will Thompson Date: Tue Mar 29 13:43:33 2011 +0100 Morse and Lewis were Oxfordshire police. I'm truly ashamed that I got this wrong. tests/wocky-xmpp-reader-test.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit f13a64ac9a75a44b0542df3b8a9ce49a0ebc1f9f Author: Will Thompson Date: Fri Mar 25 12:01:03 2011 +0000 MUC: remove content-free headers and unused returns Reviewed-by: Jonny Lamb wocky/wocky-muc.c | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) commit c4cd1516b38df51d50f8be9f207fc0933e805584 Author: Jonny Lamb Date: Fri Mar 25 15:23:16 2011 +0000 ll-connector: check the cancellable for !NULL before unreffing it Signed-off-by: Jonny Lamb wocky/wocky-ll-connector.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) commit f06ca27d72c18f2c77b010a4c1083e56b372f51f Author: Jonny Lamb Date: Fri Mar 25 15:13:43 2011 +0000 ll-connector: free the async result before the connector itself We need to allow the LL connector to dispose properly by dropping its last ref held by the GSimpleAsyncResult before actually unreffing itself. Signed-off-by: Jonny Lamb wocky/wocky-ll-connector.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) commit 7be06a577234e467a82f259b4db81b14c7a801fd Author: Stef Walter Date: Wed Mar 23 10:58:43 2011 +0100 Hold off on depending on gio 2.28 just for one function. Replace g_simple_async_result_take_error() with g_simple_async_result_set_error() and g_simple_async_result_set_from_error() configure.ac | 2 +- wocky/wocky-ll-connection-factory.c | 11 +++++------ wocky/wocky-ll-connector.c | 27 +++++++++++---------------- wocky/wocky-meta-porter.c | 14 +++++++++----- wocky/wocky-uninstalled.pc.in | 2 +- 5 files changed, 27 insertions(+), 29 deletions(-) commit 59ac2219bd44399949c6732dafa402786b317404 Author: Jonny Lamb Date: Fri Mar 11 10:38:33 2011 +0000 pubsub-helpers: add make_event_stanza helper function Signed-off-by: Jonny Lamb wocky/wocky-pubsub-helpers.c | 50 ++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-helpers.h | 5 +++++ 2 files changed, 55 insertions(+) commit 506ffdf83b335175e037385b6cf323c6c94f0728 Author: Jonny Lamb Date: Tue Mar 22 15:40:22 2011 +0000 examples: use wocky_session_new_with_connection wocky_session_new() was renamed to this in my meta-porter branch. Signed-off-by: Jonny Lamb examples/receive-messages.c | 2 +- examples/send-message.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) commit 1343f70de56c6917a224b3c2618eaf654a9fc958 Merge: 9165184 901aca4 Author: Jonny Lamb Date: Tue Mar 22 15:31:20 2011 +0000 Merge branch 'meta-porter' Conflicts: docs/reference/wocky-docs.sgml wocky/wocky-debug.h Signed-off-by: Jonny Lamb Reviewed-by: Will Thompson commit 901aca41915146f450842d7ab41071d5dd0e4f46 Author: Jonny Lamb Date: Tue Mar 22 15:08:41 2011 +0000 meta-porter: ensure the ClosePorter closure if freed even if there are none to close Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) commit 018286b9c3f881fe35f2facfb5f52264dd99e231 Author: Jonny Lamb Date: Tue Mar 22 15:02:32 2011 +0000 meta-porter: fix tallying up calls to the close_async function PorterData* can have a NULL porter, which means the meta-porter doesn't need to close it. However, previously, the close_all_porters function didn't care about that and treated as that a remaining porter anyway. Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) commit 5dd3fcd91d00332f126d447bdc76cecfd0b355ce Author: Jonny Lamb Date: Tue Mar 22 10:04:57 2011 +0000 configure: depend on gio >= 2.28 At least g_simple_async_result_take_error needs this. Signed-off-by: Jonny Lamb configure.ac | 2 +- wocky/wocky-uninstalled.pc.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) commit 807c680b413dbef620a9ee560493f56cfc945184 Author: Jonny Lamb Date: Mon Mar 21 09:27:15 2011 +0000 meta-porter: don't leak the stanza if send_iq_finish wasn't called We get a new ref to the new stanza from the c2s porter's send_iq_finish. We now set that as the simple async result's gpointer with free func of g_object_unref. The finish func returns a new ref to the stanza so that when the simple async result is completed it unrefs the stanza leaving the only ref in the callback (unless it has already been unreffed there). Bingo. Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) commit ff6037a2a24288d80fa201bd00b0dc9b5d668971 Author: Jonny Lamb Date: Mon Mar 21 09:23:12 2011 +0000 meta-porter: clarify closing all porters code Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) commit 5a13d595205c0a5dacff0eb8a29063e8dd4c0554 Author: Jonny Lamb Date: Mon Mar 21 09:20:17 2011 +0000 meta-porter: don't create a new GList twice needlessly Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 2 -- 1 file changed, 2 deletions(-) commit 4d31698c7664b828ce19d559ec782df6a5df5b20 Author: Jonny Lamb Date: Mon Mar 21 09:18:26 2011 +0000 meta-porter: bail out of start if the socket listener fails to listen Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 1 + 1 file changed, 1 insertion(+) commit 00dd8fc007dec252f6255bdcc0e31821d94aedcd Author: Jonny Lamb Date: Mon Mar 21 09:16:49 2011 +0000 meta-porter: add the other arguments to stanza_handler_new Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) commit bf09868c378b95bd0f2eb48c534d72a1352b9d42 Author: Jonny Lamb Date: Mon Mar 21 09:13:36 2011 +0000 meta-porter: critical on setting the JID twice Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) commit 916518447065436474ddd0d86462dafa3e28815e Author: Marco Barisione Date: Fri Mar 18 18:26:49 2011 +0000 SaslAuth: fix a wrong variable name (it's "sasl", not "self") Reviewed-by: Will Thompson wocky/wocky-sasl-auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 683d2cf1c5d4095b9413442d4cafb4e850c47952 Author: Marco Barisione Date: Fri Mar 18 17:35:09 2011 +0000 SaslAuth: Don't process stanzas received after disconnection Fixes: Reviewed-by: Will Thompson wocky/wocky-sasl-auth.c | 9 +++++++++ 1 file changed, 9 insertions(+) commit 27252c32885bcc057654dcbc3191812b745238a2 Merge: d3354fd c0638dd Author: Will Thompson Date: Thu Mar 17 16:29:27 2011 +0000 Merge branch 'examples' Reviewed-by: Jonny Lamb Fixes: commit c0638dd2dfc88c5d8404618fe359f5a1185d13d0 Author: Will Thompson Date: Thu Mar 17 15:33:40 2011 +0000 examples: correctly publish 'chat' presence examples/receive-messages.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 43cd47e8868587e6304dbf305135424443f11cc1 Author: Will Thompson Date: Thu Mar 17 15:27:47 2011 +0000 porter-test: remove stray g_print (G_STRFUNC)s tests/wocky-porter-test.c | 4 ---- 1 file changed, 4 deletions(-) commit 4766171bc6a764c5cb49a341595fff96fd66fec6 Author: Will Thompson Date: Wed Mar 16 18:57:04 2011 +0000 Connector: simplify building a debug string wocky/wocky-connector.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) commit 1d3db8d669e73f6d18f3130891e53d19913ad0f2 Author: Will Thompson Date: Wed Mar 16 18:25:44 2011 +0000 SaslAuth: use WockyNodeIter to iterate mechanisms wocky/wocky-sasl-auth.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) commit 08d26f1f52da184266301a76030e75b94cdd953f Author: Will Thompson Date: Wed Feb 16 16:37:23 2011 +0000 Stanza: Improve error message on type/subtype mismatch Previously, if you tried to build a stanza of TYPE_MESSAGE with SUB_TYPE_GET (say), you got this super-clear critical: wocky-CRITICAL **: check_sub_type: assertion `sub_type_names[sub_type].type == WOCKY_STANZA_TYPE_NONE || sub_type_names[sub_type].type == type' failed Luddite quotes and all. It's much clearer if we include the human-readable names. wocky/wocky-stanza.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) commit c3b05e3331b883eb192ebca87be393be047944fd Author: Will Thompson Date: Wed Mar 16 18:52:48 2011 +0000 Add a simple example of receiving incoming messages. .gitignore | 1 + examples/Makefile.am | 5 ++ examples/receive-messages.c | 195 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 201 insertions(+) commit 7920415a3f3434c755a120d3e5c050ef8762b506 Author: Will Thompson Date: Wed Mar 16 18:31:54 2011 +0000 Remove connect example. The vast, vast majority of this example dealt with connecting before the connector existed. Now it does, that part's unnecessary—it's just a poor clone of the connector—and the remainder is subsumed by send-message. .gitignore | 1 - examples/Makefile.am | 7 +- examples/connect.c | 432 --------------------------------------------------- 3 files changed, 1 insertion(+), 439 deletions(-) commit 5f37fa362ee2dcf3995f8a9a7ba8506b2c9777a6 Author: Will Thompson Date: Tue Feb 15 15:51:46 2011 +0000 Add a simple example of sending a message. .gitignore | 1 + examples/Makefile.am | 5 ++ examples/send-message.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) commit de8d20d065f554f6ae7fd1945649dbf0322b2971 Author: Will Thompson Date: Thu Mar 17 14:04:01 2011 +0000 Porter: test sending from send_async() callback. When I was briefly hunting the bug Jonny fixed, I though that the following (untested) scenario might not work: • Tell the porter to send two messages; • In the callback for the first one having been sent, tell the porter to send a third. So I wrote the test, and it does work. Hooray. tests/wocky-porter-test.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) commit 902aa24b5d9519fbc6ec3fcbd7c353cbbc42930d Author: Will Thompson Date: Wed Feb 16 17:56:59 2011 +0000 Add a test case for closing a porter from a send_async callback This is a regression test for the bug fixed in the previous commit. tests/wocky-porter-test.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) commit cf8b0dbabe4b153f0e62c5483507cef89a30177f Author: Jonny Lamb Date: Fri Mar 11 09:54:19 2011 +0000 porter: don't close twice if we close in a send callback We need to decide before we complete the "send stanza" asynchronous operation whether we have a close result pending. If we don't, we can get into a pickle if the callback to send_async calls close_async. The problem is that close_async doesn't use the same stanza queue as send_async so needs special-casing. For example: Previously, we send a stanza using send_async. The simple async result would be completed with g_simple_async_result_complete() and the callback to send_async would be called. However, if in the callback close_async is called, the stream close is sent directly with wocky_xmpp_connection_send_close_async and priv->close_result is assigned. Once the callback returns, send_stanza_cb continues BUT at the end there is a test for whether there is a close result pending. This is for when you send a whole bunch of stanzas followed by a close request, so the porter waits until all the stanzas are sent before sending the stream close, which is cool. However, priv->close_result is now != NULL so the porter thinks we're in exactly that case -- that we're waiting until all the stanzas are sent and will try and send a stream close afterwards. As we've already done that the xmpp connection will say "hey another send operation pending" and everything will fall apart. Signed-off-by: Jonny Lamb wocky/wocky-c2s-porter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) commit d3354fd9c095a2c7c1f381e62a4d7b8481fd9edc Merge: cf9bb4a 45bb1dc Author: Jonny Lamb Date: Thu Mar 17 09:09:57 2011 +0000 Merge remote branch 'ptlo/stanza-queueing-c2s' commit 45bb1dc9fcd3171983e785b238a0e35c3e72a294 Author: Senko Rasic Date: Tue Mar 15 13:20:15 2011 +0100 WockyC2SPorter: queue unimportant stanza in power saving mode wocky/wocky-c2s-porter.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++- wocky/wocky-c2s-porter.h | 3 + 2 files changed, 150 insertions(+), 1 deletion(-) commit 4bb6e6fc14c8014e653a4cb812a220fdc5f14147 Author: Jonny Lamb Date: Wed Mar 16 10:46:21 2011 +0000 meta-porter: clarify borrow_connection docstring Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) commit e46d8083b9a7401b9080c37e4c06b48c9f511b62 Author: Jonny Lamb Date: Wed Mar 16 10:29:31 2011 +0000 meta-porter: don't refer to missing arguments in documentation Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) commit 544956df89dbad2d0712a4d736a08eff0becfa19 Author: Jonny Lamb Date: Wed Mar 16 10:27:36 2011 +0000 meta-porter: give functions who require ll contacts that signature Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 8 ++++---- wocky/wocky-meta-porter.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) commit 7cb02519648fea65317a51f5e3ebe85f79b668b8 Author: Jonny Lamb Date: Wed Mar 16 10:20:48 2011 +0000 meta-porter: add a stanza_handler_new to stop duplicating code Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) commit 3d616a5da98686ff68c7ec73f78169e5ec2f3597 Author: Jonny Lamb Date: Wed Mar 16 10:15:13 2011 +0000 meta-porter: continue using wocky_stanza_get_ functions Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit c357d3309905b4b35e9541c9899dd49ace00e2bd Author: Jonny Lamb Date: Wed Mar 16 10:11:34 2011 +0000 meta-porter: use better callback names when using open_porter_if_necessary Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) commit 20c50ed7dea3b03bcfb17b917b0f73527ebc51e8 Author: Jonny Lamb Date: Wed Mar 16 10:03:23 2011 +0000 meta-porter: use wocky_stanza_get_from Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) commit c0c789bc14dd1a4c3220f4bb6a53eaeb803433a4 Author: Jonny Lamb Date: Wed Mar 16 10:00:15 2011 +0000 meta-porter: change variable name to be a little less confusing Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit 27260ccf388c1f9a6b498561658d8aa2971fa004 Author: Jonny Lamb Date: Wed Mar 16 09:58:00 2011 +0000 meta-porter: make open_porter_if_necessary take a async result and user data Turns out two user datas wasn't necessary! Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 51 ++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 25 deletions(-) commit 4cbc9642b23585d8aa85abfae578c80af004c4f6 Author: Jonny Lamb Date: Wed Mar 16 09:51:32 2011 +0000 meta-porter: don't leak and report more errors when setting up the loopback porter Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) commit 25ef4db47a538827397c6bc5fe0feeca16a25b8b Author: Jonny Lamb Date: Wed Mar 16 09:44:01 2011 +0000 meta-porter: remove NewConnectionData We can get the socket address later. Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 47 ++++++++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 27 deletions(-) commit daf1a426a6e2dd7079ee7b5e99934fbe55bcd896 Author: Jonny Lamb Date: Wed Mar 16 09:37:48 2011 +0000 meta-porter: refactor duplicated code into another function Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) commit 55acacdf14ece714bfeb74b5554303ddc1687264 Author: Jonny Lamb Date: Wed Mar 16 09:30:34 2011 +0000 meta-porter: clarify porter disposed weak ref callback name Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) commit e1ab0e953cfe66aa4d20c318c47b985d2802703a Author: Jonny Lamb Date: Wed Mar 16 09:24:35 2011 +0000 meta-porter: remove unnecessary weak reffing of the c2s porter Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) commit ec72ecf69ad36a96ebbb028af1a7d83a2f36b7f7 Author: Jonny Lamb Date: Wed Mar 16 09:16:56 2011 +0000 meta-porter: include missing porter recipient in debug message Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 0537e42cb88fa664178bed703cb66ee3304cd4dd Author: Jonny Lamb Date: Wed Mar 16 09:07:43 2011 +0000 meta-porter: only allow set_jid to be called once Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) commit 6e484c8d874a36c95f07b31a114f879c453ae072 Author: Jonny Lamb Date: Wed Mar 16 08:58:25 2011 +0000 meta-porter: stop talking about references in docstrings Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) commit cf9bb4a08d6ba577937603b2c899d5e00408115a Author: Will Thompson Date: Tue Mar 15 18:22:35 2011 +0000 Roster: remove dead google_roster code. We don't use this class at all. I'm tempted to remove it entirely. But this was triggering unused variable warnings. Reviewed-by: Sjoerd Simons wocky/wocky-roster.c | 15 --------------- 1 file changed, 15 deletions(-) commit 37fe2e992fa482c36abae85ed07df49a3a307937 Author: Jonny Lamb Date: Mon Mar 14 14:40:15 2011 +0000 ll-connector: use GAsyncInitable and make API easier to understand. Signed-off-by: Jonny Lamb wocky/wocky-ll-connector.c | 225 ++++++++++++++++++++++++++------------------- wocky/wocky-ll-connector.h | 16 ++-- wocky/wocky-meta-porter.c | 26 ++---- 3 files changed, 150 insertions(+), 117 deletions(-) commit bbaeb4a4ce8e02c364c93949a041be369bd0466c Author: Jonny Lamb Date: Mon Mar 14 12:06:59 2011 +0000 loopback-connection: rename to loopback-stream Signed-off-by: Jonny Lamb tests/wocky-loopback-test.c | 4 +- wocky/Makefile.am | 4 +- wocky/wocky-loopback-connection.c | 544 -------------------------------------- wocky/wocky-loopback-connection.h | 67 ----- wocky/wocky-loopback-stream.c | 544 ++++++++++++++++++++++++++++++++++++++ wocky/wocky-loopback-stream.h | 67 +++++ wocky/wocky-meta-porter.c | 4 +- 7 files changed, 617 insertions(+), 617 deletions(-) commit 5cc57e7166807b911a5ea1cbcfa0b4cb28688fc5 Author: Jonny Lamb Date: Mon Mar 14 12:02:48 2011 +0000 meta-porter: rename ref/unref to hold/unhold Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 24 ++++++++++++------------ wocky/wocky-meta-porter.h | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) commit b230d9aa66b6835cc5688b8bf9dc2dec233e5657 Author: Jonny Lamb Date: Mon Mar 14 11:51:39 2011 +0000 ll-connector: send stream features in incoming connections too Signed-off-by: Jonny Lamb wocky/wocky-ll-connector.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) commit 05caefc9bac290525b8be7d5c75034fb27fe7cca Author: Jonny Lamb Date: Mon Mar 14 11:49:33 2011 +0000 ll-connector: chain up to constructed first Signed-off-by: Jonny Lamb wocky/wocky-ll-connector.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit 9cb140595d2d163810d72768075f2a9178b1413c Author: Jonny Lamb Date: Mon Mar 14 10:56:24 2011 +0000 ll-connector: reference _new functions in connect_async docstring Signed-off-by: Jonny Lamb wocky/wocky-ll-connector.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 83fceb9a01975163bb65c4c081ad182051ba1a97 Author: Jonny Lamb Date: Mon Mar 14 10:40:24 2011 +0000 ll-connection-factory: use a GQueue It's more clear than a couple of GList pointers. Signed-off-by: Jonny Lamb wocky/wocky-ll-connection-factory.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) commit 92bda0a09cf5b9fd282b6a63171d01fd0f6c7351 Author: Jonny Lamb Date: Mon Mar 14 10:17:35 2011 +0000 ll-connection-factory: check whether the cancellable has been cancelled Signed-off-by: Jonny Lamb wocky/wocky-ll-connection-factory.c | 10 ++++++++++ 1 file changed, 10 insertions(+) commit d87861c3af468b1a66b862c69b8f09ab677169c8 Author: Jonny Lamb Date: Mon Mar 14 10:12:35 2011 +0000 connection-factory: rename to ll-connection-factory Signed-off-by: Jonny Lamb wocky/Makefile.am | 4 +- wocky/wocky-connection-factory.c | 266 ------------------------------------ wocky/wocky-connection-factory.h | 89 ------------ wocky/wocky-ll-connection-factory.c | 266 ++++++++++++++++++++++++++++++++++++ wocky/wocky-ll-connection-factory.h | 89 ++++++++++++ wocky/wocky-meta-porter.c | 12 +- 6 files changed, 363 insertions(+), 363 deletions(-) commit e3f1e091e087942944b38a66554716ba316e30d9 Author: Jonny Lamb Date: Mon Mar 14 10:00:39 2011 +0000 ll-contact: re-word get_addresses docstring Signed-off-by: Jonny Lamb wocky/wocky-ll-contact.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) commit 37b5701f9c7d99c077e3286881992af11a883f7e Author: Jonny Lamb Date: Mon Mar 14 09:59:32 2011 +0000 ll-contact: annotate return type of get_addresses Signed-off-by: Jonny Lamb wocky/wocky-ll-contact.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 3280a8dde69ddfe5e3853b2cbf8068232fa1652b Author: Jonny Lamb Date: Mon Mar 14 09:57:34 2011 +0000 ll-contact: spell out ll acronym in docstring Signed-off-by: Jonny Lamb wocky/wocky-ll-contact.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit e9f5d05edddcf678d2fb143c5332705e6b406719 Author: Jonny Lamb Date: Mon Mar 14 09:42:07 2011 +0000 stanza: separate contact object into to and from objects Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 8 +++---- wocky/wocky-stanza.c | 59 ++++++++++++++++++++++++++++++++++++----------- wocky/wocky-stanza.h | 7 ++++-- 3 files changed, 54 insertions(+), 20 deletions(-) commit 2a4c323c0d490f863728c48c79333edc0a99ed82 Author: Jonny Lamb Date: Mon Mar 14 09:22:58 2011 +0000 utils: use G_STMT_{START,END} in new implement macro Signed-off-by: Jonny Lamb wocky/wocky-utils.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) commit 13bd32864d690f61267b61389b1f414754f44f6c Author: Jonny Lamb Date: Fri Mar 11 15:22:39 2011 +0000 caps-hash: fix up some code after running it through the style checker Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 72ad9c1e37fd05fbda8549a3b14ddb2a77da418e Author: Jonny Lamb Date: Fri Mar 11 15:17:00 2011 +0000 caps-hash: test having bad nodes in data form fields Signed-off-by: Jonny Lamb tests/wocky-caps-hash-test.c | 93 ++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-caps-hash.c | 41 ++++++++++++++++--- 2 files changed, 129 insertions(+), 5 deletions(-) commit 9d50b575a41fc5e3648023fbae372c06168ce983 Author: Jonny Lamb Date: Fri Mar 11 14:27:33 2011 +0000 caps-hash: fail if there are multiple data forms with the same type Signed-off-by: Jonny Lamb tests/wocky-caps-hash-test.c | 84 ++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-caps-hash.c | 24 +++++++++++++ 2 files changed, 108 insertions(+) commit 21d7db7c112b3397416a4ccb660243d218816fa1 Author: Jonny Lamb Date: Fri Mar 11 14:26:12 2011 +0000 caps-hash: add more debugging for a missing FORM_TYPE field Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) commit f4562b8d5588f7bb18d3618af447aef735928833 Author: Jonny Lamb Date: Fri Mar 11 14:15:31 2011 +0000 caps-hash-test: add a test for a dataform without FORM_TYPE Signed-off-by: Jonny Lamb tests/wocky-caps-hash-test.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) commit 59d84e5eb286595ee5b4f68f1c280c07479f2c45 Author: Jonny Lamb Date: Fri Mar 11 14:08:18 2011 +0000 caps-hash: bail if there is no FORM_TYPE field in the data form Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) commit 3d2d30ef018a16ec7d80c055eddf734ea0f56007 Author: Jonny Lamb Date: Fri Mar 11 14:07:52 2011 +0000 caps-hash: free sha1'd string Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 1 + 1 file changed, 1 insertion(+) commit 7b640b914b214fc9c3248652e4af07d3a9d94e93 Author: Jonny Lamb Date: Fri Mar 11 13:58:10 2011 +0000 caps-hash: also handle booleans Signed-off-by: Jonny Lamb tests/wocky-caps-hash-test.c | 10 ++++++++++ wocky/wocky-caps-hash.c | 6 +++++- 2 files changed, 15 insertions(+), 1 deletion(-) commit 116af1e57c66bc2183cc667e5970ec8f93860965 Author: Jonny Lamb Date: Fri Mar 11 13:57:48 2011 +0000 caps-hash: ensure multi-text values are sorted Signed-off-by: Jonny Lamb tests/wocky-caps-hash-test.c | 2 +- wocky/wocky-caps-hash.c | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) commit 4e4226dfef22e367dd7eb153f44578b7fc6bf67e Author: Jonny Lamb Date: Fri Mar 11 13:42:39 2011 +0000 caps-hash: use a switch and deal with all dataform field types Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 51 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 15 deletions(-) commit 3f0a9c6a3d03e6dd92874fb328e637aecce782e4 Author: Jonny Lamb Date: Fri Mar 11 10:28:18 2011 +0000 meta-porter: add more interesting debug messages Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) commit e763571868f715378a51acee823ebde65891998b Merge: 5cd5394 a17332c Author: Will Thompson Date: Thu Mar 10 15:33:16 2011 +0000 Merge remote-tracking branch 'stefw/error-always-specialized-node' Fixes: Fixes: Reviewed-by: Will Thompson commit a17332c8441b3e5dddb46ff50987bb1f38def647 Author: Stef Walter Date: Thu Mar 10 15:55:29 2011 +0100 Refine behavior of wocky_xmpp_error_extract() for specialized errors. We return the first specialized error. There should only be one according to the XMPP specs. @specialized and @specialized_node always match. https://bugs.freedesktop.org/show_bug.cgi?id=35086 tests/wocky-stanza-test.c | 68 ++++++++++++++++++++++++++++++++++++++++++----- wocky/wocky-xmpp-error.c | 11 ++++---- 2 files changed, 68 insertions(+), 11 deletions(-) commit 71303eba13770a8628b8af62c3b08e9c6fb79954 Author: Stef Walter Date: Mon Mar 7 16:55:20 2011 +0100 wocky_xmpp_error_extract() fills in @specialized_node for any app error. Don't just limit parsing/setting of @specialized_node to error codes which have been specifically registered with a WockyXmppErrorSpecialization. Fill in @specialized when the error code has been specifically registered. Fill in @specialized_node when a registered error domain matches, whether or not the specific code has been registered. https://bugs.freedesktop.org/show_bug.cgi?id=35086 wocky/wocky-xmpp-error.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) commit 441f5c02e8a930d07ed81d93ff2f04eb95ab51f7 Author: Stef Walter Date: Thu Mar 10 15:28:43 2011 +0100 Fix memory leak in tests. tests/wocky-stanza-test.c | 2 ++ 1 file changed, 2 insertions(+) commit 5cd5394a90ebefb95171aff007c073b2fd2fece6 Author: Will Thompson Date: Thu Mar 10 13:38:21 2011 +0000 Make PubsubAffiliation and PubsubSubscription docs appear Wtf! Reviewed-by: Jonny Lamb wocky/wocky-pubsub-node.h | 1 + wocky/wocky-pubsub-service.h | 1 + 2 files changed, 2 insertions(+) commit 02f235609a9cfc4df076c3d4fc1d01e39c91b9e5 Author: Stef Walter Date: Thu Mar 10 14:20:20 2011 +0100 Split up the XMPP stanza tests, so each test tests one thing. https://bugs.freedesktop.org/show_bug.cgi?id=35175 tests/wocky-stanza-test.c | 155 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 144 insertions(+), 11 deletions(-) commit 4c557f412d52ed121d04eec4a3e10b2511cf11a8 Author: Jonny Lamb Date: Thu Mar 10 11:58:48 2011 +0000 openssl: stop using OPAQUE_TYPE_ prefixes here too Like in 9984d84ea288b4c but I forgot about to build the openssl backend so only just noticed it had broken. Signed-off-by: Jonny Lamb wocky/wocky-openssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 1eec342d97afb81c77c0377d6ba964b41101d804 Author: Jonny Lamb Date: Thu Mar 10 11:54:38 2011 +0000 porter: initialize GError* to NULL to fix coding style checks Signed-off-by: Jonny Lamb wocky/wocky-porter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 20a857391a832077ebfd48fe3503ef737bde8c49 Merge: dbf5020 3961b80 Author: Jonny Lamb Date: Thu Mar 10 11:42:21 2011 +0000 Merge branch 'gee-tee-kay-doc' commit dbf50208beffa638fb814bdb1b42aac919eadbea Merge: 99018a2 84edb4f Author: Will Thompson Date: Thu Mar 10 10:51:36 2011 +0000 Merge branch 'ack-and-nak' Fixes: Reviewed-by: Jonny Lamb commit 3961b809f22f532541b73fe332d9465fb1032c3e Author: Jonny Lamb Date: Wed Mar 9 16:21:38 2011 +0000 pep-service: document everything Signed-off-by: Jonny Lamb wocky/wocky-pep-service.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++- wocky/wocky-pep-service.h | 13 +++++--- 2 files changed, 90 insertions(+), 5 deletions(-) commit cd6ceec9b550ceb30782954244ad3c3a7869e83d Author: Jonny Lamb Date: Wed Mar 9 09:58:03 2011 +0000 xmpp-error: fix WockyXmppErrorSpecialization docs Signed-off-by: Jonny Lamb wocky/wocky-xmpp-error.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit ab85e5a992c59b8a42d163a4a0d645a7e5b8bb25 Author: Jonny Lamb Date: Wed Mar 9 09:52:24 2011 +0000 node: add note about the gtk-doc bug we're hitting Signed-off-by: Jonny Lamb wocky/wocky-node.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 60ee6333a7a7637eb482b04f2fe581dc1c4f9694 Author: Jonny Lamb Date: Wed Mar 9 09:43:01 2011 +0000 node: document NodeIter's members as private Signed-off-by: Jonny Lamb wocky/wocky-node.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) commit c2772ff7d0a832dc34ebaa0585f66e7be7de190d Author: Jonny Lamb Date: Wed Mar 9 09:42:05 2011 +0000 node: remove confusing comment describing nodes Signed-off-by: Jonny Lamb wocky/wocky-node.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit e1530e0b18976468920a40d8cc3436e896f1485c Author: Jonny Lamb Date: Tue Mar 8 15:43:13 2011 +0000 contact: no need to forward-define WockyContact Signed-off-by: Jonny Lamb wocky/wocky-contact.h | 4 ++-- wocky/wocky-types.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) commit d11a8114a1cb547eaf4ca12b3df59d81724a1ae7 Author: Jonny Lamb Date: Tue Mar 8 15:38:55 2011 +0000 jabber-auth-digest: make class and object struct members private Signed-off-by: Jonny Lamb wocky/wocky-jabber-auth-digest.h | 2 ++ 1 file changed, 2 insertions(+) commit 97fffc5f6ee3638352f10eca71a9507484822279 Author: Jonny Lamb Date: Tue Mar 8 15:38:37 2011 +0000 wocky-docs.sgml: add some other missing files Signed-off-by: Jonny Lamb docs/reference/wocky-docs.sgml | 2 ++ 1 file changed, 2 insertions(+) commit da3e300a56c1decd2e1a599b1cfb0dbfd6d2da9a Author: Jonny Lamb Date: Tue Mar 8 15:22:46 2011 +0000 wocky-docs.sgml: use Wocky, not wocky Happy, not sad. :-) Signed-off-by: Jonny Lamb docs/reference/wocky-docs.sgml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 3909ea620aaf579ee6a0e35ee9850d8553a40a4b Author: Jonny Lamb Date: Tue Mar 8 15:22:02 2011 +0000 wocky-docs.sgml: re-add the enumtypes files Signed-off-by: Jonny Lamb docs/reference/wocky-docs.sgml | 9 +++++++++ 1 file changed, 9 insertions(+) commit 60e3415f308f568089ca49791d657ace6500e811 Author: Jonny Lamb Date: Tue Mar 8 15:18:45 2011 +0000 xmpp-error: don't typedef the structs directly Like a few commits ago. Signed-off-by: Jonny Lamb wocky/wocky-xmpp-error.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) commit 363c5a62159eed5e48c096b34f5b9e15cfd978e4 Author: Jonny Lamb Date: Tue Mar 8 15:18:35 2011 +0000 porter: fix reference to porter error Signed-off-by: Jonny Lamb wocky/wocky-porter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit dadc629fc9e262ed448fa0ed886e23ea16447d4d Author: Jonny Lamb Date: Tue Mar 8 15:18:17 2011 +0000 c2s-porter: fix link to register_handler_from_server Signed-off-by: Jonny Lamb wocky/wocky-c2s-porter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit ba23c83032462081fee5414bf5d1f77d13b4cab2 Author: Jonny Lamb Date: Tue Mar 8 15:13:21 2011 +0000 data-form: add a section header Signed-off-by: Jonny Lamb wocky/wocky-data-form.c | 10 ++++++++++ 1 file changed, 10 insertions(+) commit eb3a37018975eae1905ac7069e0899f44fbaae4c Author: Jonny Lamb Date: Tue Mar 8 15:12:26 2011 +0000 data-form: don't typedef the struct directly This way gtk-doc picks up the struct. Not sure why. Signed-off-by: Jonny Lamb wocky/wocky-data-form.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) commit d4055e010d0a8e6b033362590cc36f0d0991b7cb Author: Jonny Lamb Date: Tue Mar 8 15:11:53 2011 +0000 tls-connector: document :tls-handler Signed-off-by: Jonny Lamb wocky/wocky-tls-connector.c | 5 +++++ 1 file changed, 5 insertions(+) commit f239831aa994934d93a41fc06b4feb9110049c32 Author: Jonny Lamb Date: Tue Mar 8 15:11:22 2011 +0000 auth-registry: fix typos when referencing other functions Signed-off-by: Jonny Lamb wocky/wocky-auth-registry.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit e95a93d98030f8b5dfe5f680ade44b94133142c5 Author: Jonny Lamb Date: Tue Mar 8 15:11:02 2011 +0000 wocky-docs.sgml: add missing include of wocky-tls-handler.xml Signed-off-by: Jonny Lamb docs/reference/wocky-docs.sgml | 1 + 1 file changed, 1 insertion(+) commit da25e325df1b2973e0f2ec1f2258f7796388fd73 Author: Jonny Lamb Date: Tue Mar 8 14:56:24 2011 +0000 all: document Class structs Mostly with dummy text. Signed-off-by: Jonny Lamb wocky/wocky-auth-registry.h | 29 +++++++++++++++++++++++++++++ wocky/wocky-bare-contact.h | 7 +++++++ wocky/wocky-c2s-porter.h | 8 ++++++++ wocky/wocky-caps-cache.h | 8 ++++++++ wocky/wocky-connector.h | 8 ++++++++ wocky/wocky-contact-factory.h | 8 ++++++++ wocky/wocky-contact.h | 7 +++++++ wocky/wocky-data-form.h | 22 ++++++++++++++++++++++ wocky/wocky-jabber-auth.h | 8 ++++++++ wocky/wocky-muc.h | 8 ++++++++ wocky/wocky-node-tree.h | 9 ++++++++- wocky/wocky-pep-service.h | 8 ++++++++ wocky/wocky-ping.h | 8 ++++++++ wocky/wocky-pubsub-node.h | 7 +++++++ wocky/wocky-resource-contact.h | 7 +++++++ wocky/wocky-roster.h | 8 ++++++++ wocky/wocky-sasl-auth.h | 8 ++++++++ wocky/wocky-session.h | 7 +++++++ wocky/wocky-stanza.h | 10 +++++++++- wocky/wocky-tls-connector.h | 8 ++++++++ wocky/wocky-tls-handler.h | 15 +++++++++++++++ wocky/wocky-xmpp-connection.h | 8 ++++++++ wocky/wocky-xmpp-reader.h | 8 ++++++++ wocky/wocky-xmpp-writer.h | 8 ++++++++ 24 files changed, 230 insertions(+), 2 deletions(-) commit a2780e30ba820c926098a2459f9dda06b86ee90a Author: Jonny Lamb Date: Tue Mar 8 14:16:31 2011 +0000 xmpp-error: document more enums and structs Signed-off-by: Jonny Lamb wocky/wocky-xmpp-error.h | 63 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 9 deletions(-) commit 1b8831d4485c0000282aa67aa5e3fbb31f0da7d3 Author: Jonny Lamb Date: Tue Mar 8 13:58:56 2011 +0000 node: add a workaround for gtk-doc's parser being broken I'll file a bug, like, way soon. Signed-off-by: Jonny Lamb wocky/wocky-node.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit db7308a6632c01ba654f1fba03e54c0824544ce5 Author: Jonny Lamb Date: Tue Mar 8 13:42:36 2011 +0000 pubsub-service: fix typo in argument docs Signed-off-by: Jonny Lamb wocky/wocky-pubsub-service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit bcd82c253ca516132cbaeeb93868f5aeb1026fe3 Author: Jonny Lamb Date: Tue Mar 8 13:40:10 2011 +0000 debug: make flag enum values private Signed-off-by: Jonny Lamb wocky/wocky-debug.h | 1 + 1 file changed, 1 insertion(+) commit 1ef35279fade3b1f29ca9677b22146a89aa893ec Author: Jonny Lamb Date: Tue Mar 8 13:38:46 2011 +0000 porter: document the interface struct Signed-off-by: Jonny Lamb wocky/wocky-porter.h | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) commit 2ae30124e5e87ab8d8b81b216ae4100831b0f350 Author: Jonny Lamb Date: Tue Mar 8 13:09:48 2011 +0000 docs: escape XML tags in gtk-doc properly Signed-off-by: Jonny Lamb wocky/wocky-auth-handler.h | 40 +++++++++++++++++++++------------------- wocky/wocky-stanza.h | 22 +++++++++++----------- wocky/wocky-xmpp-error.c | 9 +++++---- 3 files changed, 37 insertions(+), 34 deletions(-) commit c6b93921eb831840e913837f6939f688eace639b Author: Jonny Lamb Date: Tue Mar 8 12:03:05 2011 +0000 wocky-docs.sgml: include annotation-glossary.xml to silence more warnings Signed-off-by: Jonny Lamb docs/reference/wocky-docs.sgml | 1 + 1 file changed, 1 insertion(+) commit 9984d84ea288b4c5b0a2bac24c608745ee890c9e Author: Jonny Lamb Date: Tue Mar 8 11:52:01 2011 +0000 tls: stop using OPAQUE_TYPE_ prefixes; it confuses gtk-doc Signed-off-by: Jonny Lamb wocky/wocky-tls.c | 4 ++-- wocky/wocky-tls.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) commit b0ae9960ef300f141ec317e1c2524fc3dcc7dad2 Author: Jonny Lamb Date: Tue Mar 8 11:49:15 2011 +0000 wocky-docs.sgml: remove unnessary includes Signed-off-by: Jonny Lamb docs/reference/wocky-docs.sgml | 2 -- 1 file changed, 2 deletions(-) commit ddd7608a27a56c966640a06cead18a6fb9f16617 Author: Jonny Lamb Date: Tue Mar 8 11:40:47 2011 +0000 data-form: don't use gtk-doc style comments for static functions Signed-off-by: Jonny Lamb wocky/wocky-data-form.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit b2efe47fb0707c860e25f406ca024cfeb771c0a8 Author: Jonny Lamb Date: Tue Mar 8 11:35:19 2011 +0000 namespaces: ensure all have wocky prefix Signed-off-by: Jonny Lamb wocky/wocky-muc.c | 4 ++-- wocky/wocky-namespaces.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) commit 6843d76c8849a7bfdede53bb2b6f328356faf2a7 Author: Jonny Lamb Date: Tue Mar 8 11:32:39 2011 +0000 wocky-docs.sgml: re-arrange docs and include missing files Signed-off-by: Jonny Lamb docs/reference/wocky-docs.sgml | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) commit 8b55bc0137bfdaaf9039d75e16393a4cdda0d524 Author: Jonny Lamb Date: Tue Mar 8 11:32:21 2011 +0000 xmpp-error: document error type and stream error type enums Signed-off-by: Jonny Lamb wocky/wocky-xmpp-error.c | 6 -- wocky/wocky-xmpp-error.h | 161 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 155 insertions(+), 12 deletions(-) commit 78122f3a67d29792a5879628e67f210788d20cc9 Author: Jonny Lamb Date: Tue Mar 8 10:53:39 2011 +0000 xmpp-error: make function argument name consistent between definition and declaration Signed-off-by: Jonny Lamb wocky/wocky-xmpp-error.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit e26c1bdf34b61c7af9f62a658aa166a5adbadf46 Author: Jonny Lamb Date: Tue Mar 8 10:52:26 2011 +0000 debug: rename DebugFlags enum to WockyDebugFlags Signed-off-by: Jonny Lamb wocky/wocky-debug.c | 16 ++++++++-------- wocky/wocky-debug.h | 14 +++++++------- 2 files changed, 15 insertions(+), 15 deletions(-) commit cf0dd58b0d1cc19d619244819dae6964288eb3df Author: Jonny Lamb Date: Tue Mar 8 10:50:25 2011 +0000 data-form: document more enums and structs Signed-off-by: Jonny Lamb wocky/wocky-data-form.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) commit f9f1b00b5991ebca4edb80991207aed8b3413438 Author: Jonny Lamb Date: Tue Mar 8 10:50:11 2011 +0000 node: document more enums and structs Signed-off-by: Jonny Lamb wocky/wocky-node.h | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) commit 9e423113aad41b86a63d3cce1291f9ffbe8e118a Author: Jonny Lamb Date: Tue Mar 8 10:18:15 2011 +0000 xmpp-connection: fix name of argument in gtk-doc Signed-off-by: Jonny Lamb wocky/wocky-xmpp-connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 4c6680f5ecb11d1cc6632c12b9c7d97fa3b638cd Author: Jonny Lamb Date: Tue Mar 8 10:17:25 2011 +0000 pubsub-service: document PubsubServiceError Signed-off-by: Jonny Lamb wocky/wocky-pubsub-service.h | 6 ++++++ 1 file changed, 6 insertions(+) commit ab5503eff37f086809f01ba08a7424e0b193d1cd Author: Jonny Lamb Date: Tue Mar 8 10:15:56 2011 +0000 muc: fix up documentation of enums Signed-off-by: Jonny Lamb wocky/wocky-muc.h | 163 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 127 insertions(+), 36 deletions(-) commit 01669f3bbd4bf9466b4c05bf75235a85e436ed28 Author: Jonny Lamb Date: Tue Mar 8 09:13:00 2011 +0000 stanza: document StanzaType and StanzaSubType enums Signed-off-by: Jonny Lamb wocky/wocky-stanza.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) commit dbd2c93d0d777091df23d16239d51032b90f20a7 Author: Jonny Lamb Date: Tue Mar 8 09:08:16 2011 +0000 connector: make WockyConnectorError conform a little more Signed-off-by: Jonny Lamb wocky/wocky-connector.h | 66 ++++++++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 28 deletions(-) commit ccc668e882edb10c635c6e3282e4af0d63853ef8 Author: Jonny Lamb Date: Tue Mar 8 09:07:45 2011 +0000 auth-handler: re-add < and > characters to show tags gtk-doc apparently deals with them. Signed-off-by: Jonny Lamb wocky/wocky-auth-handler.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) commit 133a2c5f0e0a71dccfa8c18a209632ac072e4642 Author: Jonny Lamb Date: Tue Mar 8 08:42:55 2011 +0000 roster: document WockyRosterSubscriptionFlags Signed-off-by: Jonny Lamb wocky/wocky-roster.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) commit 3e49397df467c25830e1c4b36f732743b588a841 Author: Jonny Lamb Date: Tue Mar 8 08:36:20 2011 +0000 auth-registry: fix up all gtk-doc docs What a generic commit message. Signed-off-by: Jonny Lamb wocky/wocky-auth-registry.h | 114 ++++++++++++++++++++++++++++++++------------ 1 file changed, 83 insertions(+), 31 deletions(-) commit da5d9fada6922b43a0ac1a58385c82613ad5bb02 Author: Jonny Lamb Date: Mon Mar 7 15:33:59 2011 +0000 auth-handler: fix up documentation of class functions ...in most ways possible. Signed-off-by: Jonny Lamb wocky/wocky-auth-handler.h | 52 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 16 deletions(-) commit 5172562d92d85e65204dfa447acb190dfd0f7dc3 Author: Jonny Lamb Date: Mon Mar 7 15:33:13 2011 +0000 connector: add missing argument docs Signed-off-by: Jonny Lamb wocky/wocky-connector.c | 5 +++++ 1 file changed, 5 insertions(+) commit 3af290067b782c53d6b1a4e55e10cbe75c5405e3 Author: Jonny Lamb Date: Mon Mar 7 15:32:57 2011 +0000 connector: don't put comments where annotations are meant to go Signed-off-by: Jonny Lamb wocky/wocky-connector.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 2ef37a93ca0e845824c6b681a4e49d7ac1761439 Author: Jonny Lamb Date: Mon Mar 7 15:22:40 2011 +0000 connector: remove enum member docs as they've been removed Signed-off-by: Jonny Lamb wocky/wocky-connector.h | 5 ----- 1 file changed, 5 deletions(-) commit d8d98b898148076d4b346c1d0a3b61999a4e3faa Author: Jonny Lamb Date: Wed Mar 2 16:25:05 2011 +0000 porter: G_GNUC_WARN_UNUSED_RESULT need not be in the interface vfunc Signed-off-by: Jonny Lamb wocky/wocky-porter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 4f91ede6ddd14ee67b818726e32b561bcd4a50fa Author: Jonny Lamb Date: Mon Mar 7 14:41:39 2011 +0000 meta-porter: create a loopback porter for stanzas for yourself Signed-off-by: Jonny Lamb wocky/wocky-meta-porter.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) commit b1168ad194943eadd8bb1381ef9392b80492e7ba Author: Jonny Lamb Date: Mon Mar 7 14:41:17 2011 +0000 loopback-connection: dispose the in/out streams only after they've been closed Signed-off-by: Jonny Lamb wocky/wocky-loopback-connection.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit 68243ab51601302d79c17e1cfba53fc45340f86c Author: Jonny Lamb Date: Mon Mar 7 11:57:23 2011 +0000 tests: add a simple test for the loopback connection Signed-off-by: Jonny Lamb tests/Makefile.am | 7 ++ tests/wocky-loopback-test.c | 191 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) commit 91cdffaaa241f8595d65111edb75dde440b5fc95 Author: Jonny Lamb Date: Mon Mar 7 11:56:55 2011 +0000 loopback-connection: added files Perhaps this should be called WockyLoopbackStream? Signed-off-by: Jonny Lamb wocky/Makefile.am | 2 + wocky/wocky-loopback-connection.c | 544 ++++++++++++++++++++++++++++++++++++++ wocky/wocky-loopback-connection.h | 67 +++++ 3 files changed, 613 insertions(+) commit 5e62f6126ec0101c30c9b154d57bcd9a134ec055 Author: Jonny Lamb Date: Wed Mar 2 16:27:45 2011 +0000 session: add set_jid function This is useful for being able to create a link-local session (and therefore the meta porter) and start listening on a port without knowing your JID properly yet. E.g. session = wocky_session_new_ll (NULL); wocky_session_start (session); porter = wocky_session_get_porter (session); port = wocky_meta_porter_get_port (WOCKY_META_PORTER (porter)); /* announce through mdns that we're listening on this port */ /* avahi tells us our fqdn */ jid = avahi_now_that_we_are_connected_tell_me_my_jid (); wocky_session_set_jid (jid); Signed-off-by: Jonny Lamb wocky/wocky-session.c | 16 ++++++++++++++++ wocky/wocky-session.h | 2 ++ 2 files changed, 18 insertions(+) commit de95c177539fddc613efa0fdede675e6b9b376ce Author: Jonny Lamb Date: Wed Mar 2 16:27:22 2011 +0000 session: add new_ll function for link-local sessions Signed-off-by: Jonny Lamb wocky/wocky-session.c | 26 ++++++++++++++++++++++---- wocky/wocky-session.h | 2 ++ 2 files changed, 24 insertions(+), 4 deletions(-) commit dba6805a40435d690061d24ad5c6936b32eb71ea Author: Jonny Lamb Date: Wed Mar 2 16:27:01 2011 +0000 docs: added c2s-porter to docs Signed-off-by: Jonny Lamb docs/reference/wocky-docs.sgml | 1 + 1 file changed, 1 insertion(+) commit ad2d79eb7a11acc68f0e741e3b2722339b9ca489 Author: Jonny Lamb Date: Wed Mar 2 16:26:50 2011 +0000 meta-porter: added files Signed-off-by: Jonny Lamb docs/reference/wocky-docs.sgml | 1 + wocky/Makefile.am | 2 + wocky/wocky-meta-porter.c | 1611 ++++++++++++++++++++++++++++++++++++++++ wocky/wocky-meta-porter.h | 97 +++ 4 files changed, 1711 insertions(+) commit 84edb4f0db762517eaec1790a2e6b7821f9ba332 Author: Will Thompson Date: Mon Mar 7 14:12:30 2011 +0000 Add wocky_xmpp_stanza_error_to_string() wocky/wocky-xmpp-error.c | 33 +++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-error.h | 1 + 2 files changed, 34 insertions(+) commit 3edc55b42a4fdc2a5829bad5e4f137118a84ba36 Author: Will Thompson Date: Mon Mar 7 12:05:20 2011 +0000 Add wocky_porter_send_iq_gerror() tests/wocky-porter-test.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-porter.c | 57 +++++++++++++++++++++++----- wocky/wocky-porter.h | 5 +++ 3 files changed, 148 insertions(+), 9 deletions(-) commit 7d10fad8b09220baaa8a83a7897f28d1342bd68c Author: Will Thompson Date: Thu Mar 3 17:12:50 2011 +0000 build_iq_error(): clarify RFC3920 reference wocky/wocky-stanza.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) commit a398a8bb8b5604b563089b459f6ffade96f66eda Author: Will Thompson Date: Wed Mar 2 15:03:14 2011 +0000 Add wocky_porter_send_iq_error() This new helper function makes it easier to nak an IQ. tests/wocky-porter-test.c | 134 ++++++++++++++++++++++++++++++++++++++++++++-- wocky/wocky-porter.c | 54 +++++++++++++++++++ wocky/wocky-porter.h | 6 +++ 3 files changed, 190 insertions(+), 4 deletions(-) commit 1b5139b290641a23d0a413f352343615a7810bcc Author: Will Thompson Date: Mon Sep 6 13:45:26 2010 +0100 Add a regression test for whitespace-only bodies. This tests for the bug fixed in the previous commit, namely . The first part of the test—checking that whitespace surrounding non-whitespace isn't stripped—already worked, but was untested. The second part was the bug in question. tests/wocky-xmpp-reader-test.c | 54 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) commit a9e55164d226568a9a2a85d8974e84e0783af01b Author: Will Thompson Date: Thu Mar 3 16:12:04 2011 +0000 WockyXmppReader: Don't drop whitespace-only contents For some reason, Wocky went out of its way to drop the contents of nodes if they were purely whitespace. I don't see the point of this, and it causes user-visible changes. If I send a contact a message containing only spaces, I'd expect them to receive my message; but because the as passed up to Gabble has no contents, Gabble doesn't show it to the user. Arguably Gabble should show an empty message even if the body is empty, but if we're doing that we shouldn't mangle whitespace-only bodies. (Besides, how else am I going to do the whitespace-only OTR handshake?) Fixes: wocky/wocky-xmpp-reader.c | 10 ---------- 1 file changed, 10 deletions(-) commit 21003231466b39ba3acb30f827f5ac5c70304f0c Author: Will Thompson Date: Wed Mar 2 15:01:20 2011 +0000 wocky_stanza_build_iq_error(): include query. XMPP Core says that IQ errors SHOULD include the query from the original request. wocky_stanza_build_iq_error() should do this for us. tests/wocky-pubsub-service-test.c | 13 ---------- tests/wocky-stanza-test.c | 6 ++--- wocky/wocky-stanza.c | 54 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 16 deletions(-) commit 98111e64216f98434dd09e7b9e1c4ed8e0ab8520 Author: Will Thompson Date: Wed Mar 2 15:00:30 2011 +0000 Rename send-iq-error test to error-while-sending-iq This is a clearer name for this test case, and also doesn't clash with a test I'm adding. tests/wocky-porter-test.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) commit 0a7538e718f2eb88a55374c6bb84082475ea1ddb Author: Will Thompson Date: Wed Mar 2 14:57:39 2011 +0000 wocky_node_get_first_child(): allow childless nodes. Previously, this function criticalled if the node passed to it had no children. This seems unnecessary: there's a perfectly good value we can return in this situation, namely NULL. wocky/wocky-node.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) commit a6a2caf114f9db9e9b4c2b0ce81a65e83da0080a Author: Will Thompson Date: Wed Mar 2 14:32:56 2011 +0000 stanza-test: fix error structure. The "more complex reply" test_build_iq_error had a broken structure: it put the inside the query element, rather than alongside it. tests/wocky-stanza-test.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) commit 6b1229d4579cba10d51485d4d8d5ce6c8e4bb529 Author: Will Thompson Date: Wed Mar 2 13:32:09 2011 +0000 Add wocky_stanza_build_iq_error_va This is just for symmetry with wocky_stanza_build_iq_result_va(); we don't actually need it yet. wocky/wocky-stanza.c | 8 ++++++++ wocky/wocky-stanza.h | 3 +++ 2 files changed, 11 insertions(+) commit 19e6e1278c4787cca1adc72943868dcfd6165b6a Author: Will Thompson Date: Wed Mar 2 13:22:45 2011 +0000 Add wocky_node_prepend_node_tree() This is akin to wocky_node_add_node_tree() wocky/wocky-node.c | 22 ++++++++++++++++++++++ wocky/wocky-node.h | 3 +++ 2 files changed, 25 insertions(+) commit a80461b731ef946f96102fc88cc7badd77aeca3e Author: Will Thompson Date: Wed Mar 2 13:22:26 2011 +0000 Tweak wocky_node_add_node_tree()'s docstring wocky/wocky-node.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) commit 64969415af3b45ef61a75040201b42a23433e377 Author: Will Thompson Date: Tue Mar 1 16:26:22 2011 +0000 Add wocky_porter_acknowledge_iq() tests/wocky-porter-test.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-ping.c | 11 +--- wocky/wocky-porter.c | 41 +++++++++++++ wocky/wocky-porter.h | 5 ++ wocky/wocky-stanza.c | 8 +++ wocky/wocky-stanza.h | 3 + 6 files changed, 207 insertions(+), 10 deletions(-) commit 4926bcc6e2bd5845025da138925427eb69f2d7cd Author: Will Thompson Date: Mon Feb 28 21:52:32 2011 +0000 Make build_iq_{reply,error} cope with NULL ids. Although it violates XMPP Core, some servers send IQs without an id='' attribute. Rather than requiring the handlers to check for the id='' attribute, this patch makes wocky_stanza_build_iq_{reply,error} return NULL—rather than criticalling and returning NULL—if the stanza being replied to has no id=''. wocky/wocky-ping.c | 8 ++++++-- wocky/wocky-roster.c | 7 +++++-- wocky/wocky-stanza.c | 4 +++- 3 files changed, 14 insertions(+), 5 deletions(-) commit 99018a2410a6fe72fa881f9fd8bd54dcc02c41fb Merge: 5e748b2 87f2783 Author: Will Thompson Date: Thu Mar 3 17:21:25 2011 +0000 Merge branch 'misc' Reviewed-by: Jonny Lamb commit 87f278396aa690142ad57e3c8ccfdc8cc7abeb55 Author: Will Thompson Date: Thu Mar 3 16:03:30 2011 +0000 XmppReader: clarify handling regular nodes' attributes This brings this loop in line with the corresponding loop for attributes in the stream opening. wocky/wocky-xmpp-reader.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) commit b997e46000b70f2e05368eec3f52e0e183df98c5 Author: Will Thompson Date: Thu Mar 3 15:38:03 2011 +0000 XmppReader: Split _start_element_ns in half. This function had two entirely distinct sections: handling the stream open, and handling the start of a normal, mid-stream element. This suggests that they should be two functions! wocky/wocky-xmpp-reader.c | 181 ++++++++++++++++++++++++++-------------------- 1 file changed, 103 insertions(+), 78 deletions(-) commit 22642c634a4f0ecc21fae76c0af049fa6277aeee Author: Jonny Lamb Date: Thu Mar 3 13:14:59 2011 +0000 caps-hash: bail on making the caps hash if parsing a dataform fails Also add a test! zomg! Signed-off-by: Jonny Lamb tests/wocky-caps-hash-test.c | 28 ++++++++++++++++++++++++++++ wocky/wocky-caps-hash.c | 5 +++-- 2 files changed, 31 insertions(+), 2 deletions(-) commit e0bd0226312ac485e6b635e97593502d5537d86a Author: Jonny Lamb Date: Thu Mar 3 11:06:35 2011 +0000 disco-identity: don't critical when trying to copy NULL Signed-off-by: Jonny Lamb wocky/wocky-disco-identity.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 6790d6b9e64104fdc6aea6df994ccc4117a35d92 Author: Jonny Lamb Date: Thu Mar 3 10:35:24 2011 +0000 caps-hash: display a warning when hitting an unknown data field type Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 4 ++++ 1 file changed, 4 insertions(+) commit a83447a22c090cfbf078849998a19a1979e474ea Author: Jonny Lamb Date: Thu Mar 3 10:28:41 2011 +0000 caps-hash: remove assertion that we have a FORM_TYPE field Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit df42485b6257086d177e92b326926934c1be4a68 Author: Jonny Lamb Date: Thu Mar 3 10:26:14 2011 +0000 data-form: clean up code for determining data form field types Thanks to William Thompson for the suggestion. Signed-off-by: Jonny Lamb wocky/wocky-data-form.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) commit 55b4db92591ecc72bd5393d2ae66d84fbc8e9063 Author: Will Thompson Date: Mon Feb 7 14:21:13 2011 +0100 XmppReader: don't crash on Previously, if the stream header contained a 'lang' attribute with no namespace prefix, we'd pass NULL to strcmp, and crash. tests/wocky-xmpp-reader-test.c | 26 ++++++++++++++++++++++++++ wocky/wocky-xmpp-reader.c | 5 ++++- 2 files changed, 30 insertions(+), 1 deletion(-) commit 33195c80d34dce29a466dabfa3bb494f7b3554ae Author: Will Thompson Date: Sat Feb 5 13:33:25 2011 +0100 Fix hypothetical NULL dereference on stream open. clang --analyze pointed out that, technically, 'uri' can be NULL here. This would mean that the server sending us a stream open without a namespace would crash us! So, we use wocky_strdiff rather than strcmp. wocky/wocky-xmpp-reader.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) commit f2456f33b940e5526746eff86cec41e3e967b3ef Author: Will Thompson Date: Mon Feb 7 14:03:14 2011 +0100 Clarify parsing stream opening wocky/wocky-xmpp-reader.c | 52 ++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 25 deletions(-) commit 8136e1381e660088800d0fd8538c518c84f77618 Author: Will Thompson Date: Mon Feb 7 13:51:58 2011 +0100 Add more assertions to stanza build interpreter clang complained that we were dereferencing 'stack', which may be NULL. It was right: previously we could get into this situation with only a warning before a NULL pointer dereference. This patch adds assertions at the points where we would crash anyway. wocky/wocky-node.c | 8 ++++++++ 1 file changed, 8 insertions(+) commit 09eb96d7a0f8ab60ec08c293f3d3bdca10355833 Author: Will Thompson Date: Mon Feb 7 13:35:12 2011 +0100 auth: Remove unneeded assignments and variables. These were found by the excellent clang --analyze. wocky/wocky-jabber-auth.c | 4 ---- wocky/wocky-sasl-scram.c | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) commit d855ca88c2bde3c0bf0c01d11117475f46d41de9 Author: Will Thompson Date: Sat Feb 5 15:18:02 2011 +0100 Fix overriding type='' when creating error nodes. Wocky has support for turning GErrors into nodes; using wocky_xmpp_error_register_domain() you can define your own specializations of standard stanza errors. By default the standard type='' for the ‘parent’ stanza error is used, but you can override this when registering a mapping. However, the code to generate error nodes didn't actually use the overridden type. (clang --analyze noticed this). (We don't actually use this code, but …) wocky/wocky-xmpp-error.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 70496f785fefe6e5593c51f8c1b3d2ab79fa0c73 Author: Will Thompson Date: Fri Feb 4 13:27:02 2011 +0100 wocky_caps_cache_dup_shared(): correct docs The docstring refers to an argument that doesn't exist on this function. wocky/wocky-caps-cache.c | 1 - 1 file changed, 1 deletion(-) commit 860185ca57e338aa1954ecb723925b84ed7b191a Author: Jonny Lamb Date: Mon Feb 28 13:58:55 2011 +0000 ll-connector: wait for features to be sent before continuing Signed-off-by: Jonny Lamb wocky/wocky-ll-connector.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) commit 5bafc9b5c4a762c3835a83d5eeae8dd44ef779a9 Author: Jonny Lamb Date: Fri Feb 25 14:55:11 2011 +0000 ll-connector: added new files Signed-off-by: Jonny Lamb wocky/Makefile.am | 2 + wocky/wocky-ll-connector.c | 453 +++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-ll-connector.h | 92 +++++++++ 3 files changed, 547 insertions(+) commit d9e5561e60485ff61c10715cb662998326fbc79c Author: Jonny Lamb Date: Fri Feb 25 14:34:41 2011 +0000 connection-factory: add files Perhaps this should be called ll-connection-factory, to emphasize the link-local emphasis? Signed-off-by: Jonny Lamb wocky/Makefile.am | 2 + wocky/wocky-connection-factory.c | 266 +++++++++++++++++++++++++++++++++++++++ wocky/wocky-connection-factory.h | 89 +++++++++++++ wocky/wocky-debug.c | 1 + wocky/wocky-debug.h | 1 + 5 files changed, 359 insertions(+) commit 27808b494f65ae5fdc8b97e05b58032dd27068b4 Author: Jonny Lamb Date: Fri Feb 25 14:19:52 2011 +0000 session: rename new to new_with_connection Signed-off-by: Jonny Lamb tests/wocky-pubsub-node-test.c | 4 ++-- tests/wocky-pubsub-service-test.c | 2 +- tests/wocky-roster-test.c | 2 +- tests/wocky-session-test.c | 6 +++--- tests/wocky-test-helper.c | 4 ++-- wocky/wocky-session.c | 2 +- wocky/wocky-session.h | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) commit 90e9a9e664d7878fa7a169d85ee9b58eac325c62 Author: Jonny Lamb Date: Fri Feb 25 14:18:23 2011 +0000 contact-factory: add support for LL contacts Signed-off-by: Jonny Lamb wocky/wocky-contact-factory.c | 121 +++++++++++++++++++++++++++++++++++++++++- wocky/wocky-contact-factory.h | 14 +++++ 2 files changed, 133 insertions(+), 2 deletions(-) commit c2fada22e35de44101faa8e7eaf0b31b2a46b6d0 Author: Jonny Lamb Date: Fri Feb 25 14:14:35 2011 +0000 ll-contact: added new files Signed-off-by: Jonny Lamb wocky/Makefile.am | 2 + wocky/wocky-ll-contact.c | 288 +++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-ll-contact.h | 81 +++++++++++++ wocky/wocky-types.h | 1 + 4 files changed, 372 insertions(+) commit 93ef951516b1339a6417014f1d4b87f25aed9bea Author: Jonny Lamb Date: Fri Feb 25 14:06:51 2011 +0000 stanza: fix argument indentation Signed-off-by: Jonny Lamb wocky/wocky-stanza.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) commit 1f9ab7cd3614534cbc1bcbd53e4f025f58ee5f5e Author: Jonny Lamb Date: Fri Feb 25 14:05:51 2011 +0000 stanza: add build_to_contact function Signed-off-by: Jonny Lamb wocky/wocky-stanza.c | 26 ++++++++++++++++++++++++++ wocky/wocky-stanza.h | 4 ++++ 2 files changed, 30 insertions(+) commit 342fee05e569ddc80b0a5de51f0d537aa4c0acb5 Author: Jonny Lamb Date: Fri Feb 25 14:04:59 2011 +0000 stanza: associate a WockyContact with each stanza Signed-off-by: Jonny Lamb wocky/wocky-stanza.c | 41 +++++++++++++++++++++++++++++++++++++++++ wocky/wocky-stanza.h | 6 ++++++ 2 files changed, 47 insertions(+) commit b459853883dd1d4c3c47c42647aebe305200fce5 Author: Jonny Lamb Date: Fri Feb 25 14:03:45 2011 +0000 stanza: make dispose and finalize static Signed-off-by: Jonny Lamb wocky/wocky-stanza.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) commit 13191d4866acea9607c3c29093a40c774878d79f Author: Jonny Lamb Date: Fri Feb 25 13:58:42 2011 +0000 resource-contact: implement dup_jid Signed-off-by: Jonny Lamb wocky/wocky-resource-contact.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) commit 68d21d640869d57a9720eec76fe02c08f13da880 Author: Jonny Lamb Date: Fri Feb 25 13:58:29 2011 +0000 bare-contact: implement dup_jid Signed-off-by: Jonny Lamb wocky/wocky-bare-contact.c | 9 +++++++++ 1 file changed, 9 insertions(+) commit f48ced6ecdb775763fbf8adcd59130540071a756 Author: Jonny Lamb Date: Fri Feb 25 13:58:13 2011 +0000 contact: add dup_jid function Signed-off-by: Jonny Lamb wocky/wocky-contact.c | 11 +++++++++++ wocky/wocky-contact.h | 6 ++++++ 2 files changed, 17 insertions(+) commit c71df0e0b513dab7f291d6152a9f7f6bd0eca456 Author: Jonny Lamb Date: Fri Feb 25 13:51:08 2011 +0000 utils: add implement_finish_return_pointer macro No copy function. Signed-off-by: Jonny Lamb wocky/wocky-utils.h | 10 ++++++++++ 1 file changed, 10 insertions(+) commit 5e748b2edcba058a40e547656cd898f56ae48784 Author: Jonny Lamb Date: Tue Mar 1 13:45:58 2011 +0000 porter: add reference to from_server register variant Signed-off-by: Jonny Lamb wocky/wocky-porter.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 71c7aa98ef45f8dcf97492dedc8886a4384837a7 Author: Jonny Lamb Date: Tue Mar 1 13:24:16 2011 +0000 porter: fix gtk-doc of @from in all from register variants Signed-off-by: Jonny Lamb wocky/wocky-porter.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) commit 294396b441b0c6c628a8d3f421c118ba732eb692 Author: Jonny Lamb Date: Tue Mar 1 13:24:03 2011 +0000 porter: move from_server register variant to c2s porter Signed-off-by: Jonny Lamb tests/wocky-porter-test.c | 3 +- wocky/wocky-c2s-porter.c | 145 +++++++++++++++++++++++++++++++++++++++-- wocky/wocky-c2s-porter.h | 27 ++++++++ wocky/wocky-porter.c | 162 +--------------------------------------------- wocky/wocky-porter.h | 36 ----------- wocky/wocky-roster.c | 4 +- 6 files changed, 173 insertions(+), 204 deletions(-) commit dd4e2a24438739475537bff267a66175ca2e8227 Author: Jonny Lamb Date: Tue Mar 1 08:25:21 2011 +0000 porter: use g_once_init_enter instead of a initialized gboolean Signed-off-by: Jonny Lamb wocky/wocky-porter.c | 198 +++++++++++++++++++++++++-------------------------- 1 file changed, 99 insertions(+), 99 deletions(-) commit 39b1a9431f4d96f8b8daa836ac6fbf848005b787 Author: Jonny Lamb Date: Tue Mar 1 08:25:12 2011 +0000 porter: rename _stanza variants to _by_stanza Signed-off-by: Jonny Lamb wocky/wocky-c2s-porter.c | 18 +++++++++--------- wocky/wocky-porter.c | 30 +++++++++++++++--------------- wocky/wocky-porter.h | 12 ++++++------ 3 files changed, 30 insertions(+), 30 deletions(-) commit aed067fca404d2a70b871dab90201cf5540388da Author: Jonny Lamb Date: Tue Mar 1 08:14:02 2011 +0000 {,c2s-}porter: fix copyright years Signed-off-by: Jonny Lamb wocky/wocky-c2s-porter.c | 2 +- wocky/wocky-c2s-porter.h | 4 ++-- wocky/wocky-porter.c | 2 +- wocky/wocky-porter.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) commit 4577a263f7c8548913691a6fc7b014255051e209 Author: Jonny Lamb Date: Mon Feb 28 14:34:42 2011 +0000 porter: fix typo in ::sending gtk-doc Signed-off-by: Jonny Lamb wocky/wocky-porter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 0474633d7a79d33235388962bf76cf3845f2d27b Author: Jonny Lamb Date: Mon Feb 28 14:28:51 2011 +0000 porter: make sure register_handler_*_stanza functions take good stanzas Signed-off-by: Jonny Lamb wocky/wocky-porter.c | 3 +++ 1 file changed, 3 insertions(+) commit 668c72d36b8698283d3be5ef2e7f9f8e81609457 Author: Jonny Lamb Date: Mon Feb 28 14:27:33 2011 +0000 porter: move c2s properties and signals to the interface Signed-off-by: Jonny Lamb wocky/wocky-c2s-porter.c | 129 +++++------------------------------------------ wocky/wocky-porter.c | 105 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 116 deletions(-) commit 2f308d251ee95504e05b17c98799a3ac131c24bc Author: Jonny Lamb Date: Mon Feb 28 08:58:06 2011 +0000 wocky: fix header guard comment Signed-off-by: Jonny Lamb wocky/wocky.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 0e5371a5abae18f737b18670fcd89d61a59e29f1 Author: Jonny Lamb Date: Mon Feb 28 08:55:51 2011 +0000 porter: turn the porter into an interface and implement it in a C2S porter This will be a pretty horrible patch, soz. Signed-off-by: Jonny Lamb tests/wocky-porter-test.c | 4 +- wocky/Makefile.am | 2 + wocky/wocky-c2s-porter.c | 1896 ++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-c2s-porter.h | 75 ++ wocky/wocky-porter.c | 1900 +++++---------------------------------------- wocky/wocky-porter.h | 178 +++-- wocky/wocky-session.c | 3 +- 7 files changed, 2276 insertions(+), 1782 deletions(-) commit 95dab3a1aa7a0e0823ca7bf175d1a84440031450 Author: Jonny Lamb Date: Fri Feb 25 16:00:25 2011 +0000 porter: add register_handler_from{,_anyone,_server}_stanza functions Also small documentation fixes in the _va functions. Signed-off-by: Jonny Lamb wocky/wocky-porter.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++---- wocky/wocky-porter.h | 27 ++++++++ 2 files changed, 192 insertions(+), 12 deletions(-) commit 035cf150fdf4558930ce88ca393f6a5d360c1b66 Author: Jonny Lamb Date: Mon Feb 14 13:15:16 2011 +0000 wocky: don't use absolute paths in enumtypes headers Signed-off-by: Jonny Lamb wocky/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit bed7014377bb94e9933063c346c86c2989df5e3c Merge: 7adf35f 3aab9dd Author: Will Thompson Date: Fri Feb 25 15:25:15 2011 +0000 Merge branch 'register-handler-from' Reviewed-by: Jonny Lamb commit 7adf35f585b92ac1ee1d562b36473dcfc4433966 Merge: 913dc10 6a13743 Author: Will Thompson Date: Fri Feb 25 13:31:03 2011 +0000 Merge remote-tracking branch 'jonny/blow-away-corrupt-caps-caches' Reviewed-by: Simon McVittie Fixes: commit 3aab9dd609906b62247c32621e3b93186b69bc44 Author: Will Thompson Date: Mon Feb 7 21:07:27 2011 +0000 Porter: make sender matching for handlers explicit. Previously, passing from=NULL to wocky_porter_register_handler() made the handler match stanzas with any sender. Unfortunately, this was confused in a few places in Gabble—and once in WockyRoster, complete with a FIXME—with matching messages from the server, which should have no from='' attribute, or your own bare or full JID. tests/wocky-pep-service-test.c | 4 +- tests/wocky-ping-test.c | 4 +- tests/wocky-porter-test.c | 246 ++++++++++++++++++----- tests/wocky-pubsub-node-test.c | 28 +-- tests/wocky-pubsub-service-test.c | 20 +- tests/wocky-roster-test.c | 68 +++---- wocky/wocky-muc.c | 4 +- wocky/wocky-pep-service.c | 6 +- wocky/wocky-ping.c | 4 +- wocky/wocky-porter.c | 400 ++++++++++++++++++++++++++++++++------ wocky/wocky-porter.h | 40 +++- wocky/wocky-pubsub-service.c | 2 +- wocky/wocky-roster.c | 14 +- 13 files changed, 650 insertions(+), 190 deletions(-) commit 342f820a211b01c1fba6e264ced8e71a8032ceea Author: Will Thompson Date: Sat Feb 5 15:44:03 2011 +0100 Porter: refactor matching stanzas from the server. wocky/wocky-porter.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) commit 9cc779ecb64823357c20f53072231a0616ec9744 Author: Will Thompson Date: Sat Feb 5 04:21:59 2011 +0100 Porter: fix matching handlers from JIDs sans node part Previously, registering a handler for a JID with no node part was accidentally equivalent to registering a handler with from=NULL; that is, we'd erroneously pass stanzas from *any* server to the handler function even if it explicitly specified a JID which was just a domain, as opposed to a JID with an '@' sign in it. This patch corrects this error, and adds a simple regression test. tests/wocky-porter-test.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-porter.c | 4 +--- 2 files changed, 60 insertions(+), 3 deletions(-) commit 95ff513fe1f5252a7b7fa4af338fc793b4775ce2 Author: Will Thompson Date: Fri Feb 4 18:03:19 2011 +0100 Add wocky_porter_register_handler_va(). wocky/wocky-porter.c | 80 +++++++++++++++++++++++++++++++++++++++++----------- wocky/wocky-porter.h | 9 ++++++ 2 files changed, 73 insertions(+), 16 deletions(-) commit 913dc10f79a5717ee2995056e1a2c07425e29ebc Author: Jonny Lamb Date: Fri Feb 4 15:37:37 2011 +0000 node: add set_attributes function Signed-off-by: Jonny Lamb wocky/wocky-node.c | 30 ++++++++++++++++++++++++++++++ wocky/wocky-node.h | 3 +++ 2 files changed, 33 insertions(+) commit 58d08be6bdbe119add2a6fb0ebe2298bb383c857 Author: Jonny Lamb Date: Fri Feb 4 11:15:12 2011 +0000 caps-hash: allow @dataforms be NULL Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) commit 19a7d037cc4e1be0666e1f6528e09a58490d0524 Author: Jonny Lamb Date: Fri Feb 4 11:09:06 2011 +0000 caps-hash-test: add a complex sorting test Signed-off-by: Jonny Lamb tests/wocky-caps-hash-test.c | 161 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 159 insertions(+), 2 deletions(-) commit 4386247cefa33464c7730c172bfe92ac6b0a4d3e Author: Jonny Lamb Date: Fri Feb 4 11:08:40 2011 +0000 caps-hash: fix creating hash from node with multiple data forms Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit bfd5f5383dc9288e2f1e9ecaab0fdce846dc6553 Author: Jonny Lamb Date: Fri Feb 4 11:08:25 2011 +0000 caps-hash: remove silly free function Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) commit 8ff62bd7353593783f5c59f5b07720fc9ac1a146 Author: Jonny Lamb Date: Fri Feb 4 10:42:08 2011 +0000 caps-hash: clarify dataforms_cmp Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) commit 9955dd81eba5477cecc2f321547dbc954971c8df Author: Jonny Lamb Date: Fri Feb 4 09:50:15 2011 +0000 caps-hash: also sort dataform fields Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 10 ++++++++-- wocky/wocky-data-form.c | 9 +++++++++ wocky/wocky-data-form.h | 3 +++ 3 files changed, 20 insertions(+), 2 deletions(-) commit be9f692fd9e535b405e6835c17a9d8141d884cf7 Author: Jonny Lamb Date: Fri Feb 4 09:49:18 2011 +0000 caps-hash: fix typo in dataform sorting code Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 1905ed28823b119eb0d290cc9a1ed79a50712963 Author: Jonny Lamb Date: Thu Feb 3 11:33:56 2011 +0000 caps-hash: ensure the features, identities and dataforms are sorted ...and add a test for it. Signed-off-by: Jonny Lamb tests/wocky-caps-hash-test.c | 53 ++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-caps-hash.c | 47 ++++++++++++++++++++++++++++++--------- 2 files changed, 90 insertions(+), 10 deletions(-) commit 6a1374307087ae19db8df3059ac8c1057290e3e8 Author: Will Thompson Date: Wed Dec 1 19:16:39 2010 +0000 CapsCache: remove an unneeded assertion. If caps_cache_open() returns TRUE but self->priv->db is NULL, the worst that happens is that we don't use a caps cache this session. Besides, by inspection that will never happen, except if sqlite3_open is broken, in which case we're dead a long time ago. Signed-off-by: Jonny Lamb wocky/wocky-caps-cache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit d11983ffe837e912a0580a6447a1dc7504dccad7 Author: Will Thompson Date: Thu Nov 25 17:44:00 2010 +0000 CapsCache: don't potentially double-free statement caps_cache_bind_*() call sqlite3_finalize() on the statement you pass in if binding fails. So we should not 'goto OUT' (which also finalizes the statement) when they fail. Note that binding a query parameter failing indicates a programming error, not a runtime error. Thus, this is a pretty academic fix. Signed-off-by: Jonny Lamb wocky/wocky-caps-cache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit f591217805cdb3eccfaaec8a8c8899d1f8ddf55a Author: Will Thompson Date: Thu Nov 25 17:43:43 2010 +0000 CapsCache: add a satity check to prepare() Signed-off-by: Jonny Lamb wocky/wocky-caps-cache.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) commit cfd0c2def4833dc6c1849f452f00e712bc604a11 Author: Will Thompson Date: Thu Jun 24 12:03:40 2010 +0100 Blow away corrupt caps caches Signed-off-by: Jonny Lamb wocky/wocky-caps-cache.c | 75 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 19 deletions(-) commit 863a47e086152ed72df3e59dec69bfb9266014c4 Author: Jonny Lamb Date: Wed Jan 26 13:06:40 2011 +0000 disco-identity: add WOCKY_TYPE_... macro Signed-off-by: Jonny Lamb wocky/wocky-disco-identity.h | 1 + 1 file changed, 1 insertion(+) commit efa313340ff1b5ed53030b8d23057f3e59e9a7df Author: Jonny Lamb Date: Wed Jan 26 10:31:16 2011 +0000 data-form: fix default type and text-multi detection The type defaults to text-single regardless of the existance of a child. Signed-off-by: Jonny Lamb wocky/wocky-data-form.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) commit cbc8ff8fa5d8acedeadb0ba18f313711ce661a47 Author: Jonny Lamb Date: Wed Jan 26 09:47:10 2011 +0000 caps-hash: turn caps_hash_compute into wocky_caps_hash_compute_from_lists Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 18 +++++++++++++++--- wocky/wocky-caps-hash.h | 6 +++++- 2 files changed, 20 insertions(+), 4 deletions(-) commit 837b31eeef93f1c46692a76befa7f600c6594e65 Author: Jonny Lamb Date: Wed Jan 26 09:32:48 2011 +0000 caps-hash: support multiple data forms Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 77 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 17 deletions(-) commit aac6f882e8bab79e51e20bf0fbee80ae86f9fd98 Author: Jonny Lamb Date: Wed Jan 26 09:30:19 2011 +0000 data-form: add new_from_node function Signed-off-by: Jonny Lamb wocky/wocky-data-form.c | 30 ++++++++++++++++++++++++------ wocky/wocky-data-form.h | 3 +++ 2 files changed, 27 insertions(+), 6 deletions(-) commit 578a1b74e9743d7a60373fb5074924a3108f49a0 Author: Jonny Lamb Date: Wed Jan 26 09:17:08 2011 +0000 caps-hash: removed "wocky does not do..." comment Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 4 ---- 1 file changed, 4 deletions(-) commit 5de07e3513f662160233165712fe5b9358f9a676 Author: Jonny Lamb Date: Wed Jan 26 09:15:01 2011 +0000 caps-hash: fixed typo Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 2270ffc468ae4358144f10a0f8c2b3423b0d1ba8 Author: Jonny Lamb Date: Wed Jan 26 09:14:21 2011 +0000 disco-identity: add cmp function Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 17 ++++++----------- wocky/wocky-disco-identity.c | 30 ++++++++++++++++++++++++++++++ wocky/wocky-disco-identity.h | 2 ++ 3 files changed, 38 insertions(+), 11 deletions(-) commit 27de40f87c5620f3cbf27ececfa30ccbe66b8124 Author: Jonny Lamb Date: Tue Jan 25 17:35:24 2011 +0000 disco-identity: fix header guard Signed-off-by: Jonny Lamb wocky/wocky-disco-identity.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit ca4e3f7ad0a6ef89b641f694258f0baf4fad7e7c Author: Jonny Lamb Date: Tue Jan 25 17:32:49 2011 +0000 caps-hash: fix year Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 2 +- wocky/wocky-caps-hash.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) commit b388359cecab1c354580fa98561fcff2534180c0 Author: Jonny Lamb Date: Tue Jan 25 17:31:50 2011 +0000 disco-identity: style trivia Signed-off-by: Jonny Lamb wocky/wocky-disco-identity.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) commit 521cc33c40ec568c54dc2ad3a46d19a6596e2d59 Author: Jonny Lamb Date: Tue Jan 25 17:28:21 2011 +0000 disco-identity: remove getters Signed-off-by: Jonny Lamb wocky/wocky-disco-identity.c | 56 -------------------------------------------- wocky/wocky-disco-identity.h | 10 ++++---- 2 files changed, 4 insertions(+), 62 deletions(-) commit 37f9038739938e8a6f2a339b81a34a32137cd7cd Author: Jonny Lamb Date: Tue Jan 25 17:02:40 2011 +0000 caps-cache: use WockyDataForm to parse the data forms Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 215 +++++++++--------------------------------------- 1 file changed, 41 insertions(+), 174 deletions(-) commit 0f44eccae95249ecaec69715c380eb9707f24496 Author: Jonny Lamb Date: Tue Jan 25 16:42:56 2011 +0000 data-form: detect whether we're actually text-multi We need this for this: http://xmpp.org/extensions/xep-0115.html#ver-gen-complex Signed-off-by: Jonny Lamb wocky/wocky-data-form.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) commit 9e5f94f4d87818126ca69988689ef66ba7d4dace Author: Jonny Lamb Date: Tue Jan 25 15:54:26 2011 +0000 data-form: allow type="result" as well as type="form" Signed-off-by: Jonny Lamb wocky/wocky-data-form.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit 2f3f9c890a76d630f72991f071819cac8ebf3fb9 Author: Jonny Lamb Date: Tue Jan 25 14:34:10 2011 +0000 tests: add caps hash test ...from Gabble. Signed-off-by: Jonny Lamb tests/Makefile.am | 9 +++- tests/wocky-caps-hash-test.c | 114 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 2 deletions(-) commit 9e15a33f9c8ac94448b33d7088f7a93cef8121a6 Author: Jonny Lamb Date: Tue Jan 25 14:33:33 2011 +0000 node: add attribute build tag for wocky_stanza_build Signed-off-by: Jonny Lamb wocky/wocky-node.c | 9 +++++++++ wocky/wocky-node.h | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) commit f3c69e238ea1683a88978ac4c59031edd8af0870 Author: Jonny Lamb Date: Tue Jan 25 10:54:23 2011 +0000 disco-identity: make a boxed type Signed-off-by: Jonny Lamb wocky/wocky-disco-identity.c | 3 +++ wocky/wocky-disco-identity.h | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) commit a37948c77254c53fc830e527c3d6718e91df7ba9 Author: Jonny Lamb Date: Tue Jan 25 10:54:07 2011 +0000 disco-identity: rename _get_type to _get_identity_type Signed-off-by: Jonny Lamb wocky/wocky-disco-identity.c | 4 ++-- wocky/wocky-disco-identity.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) commit 1efddcfc52f46202a516c97c754938528f635d83 Author: Jonny Lamb Date: Mon Jan 24 11:29:49 2011 +0000 disco-identity: add more documentation Signed-off-by: Jonny Lamb docs/reference/wocky-docs.sgml | 1 + wocky/wocky-disco-identity.c | 87 ++++++++++++++++++++++++++++++++++++++---- wocky/wocky-disco-identity.h | 11 +++++- 3 files changed, 89 insertions(+), 10 deletions(-) commit 72657801003469feab10665b32a582fbc6c08218 Author: Jonny Lamb Date: Mon Jan 24 11:26:38 2011 +0000 disco-identity: add some WARN_UNUSED_RESULTs Signed-off-by: Jonny Lamb wocky/wocky-disco-identity.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) commit 704ce8ef6aac173f67164ab23e216cfd2afe5e2b Author: Jonny Lamb Date: Mon Jan 24 10:57:05 2011 +0000 caps-hash: add documentation Signed-off-by: Jonny Lamb docs/reference/wocky-docs.sgml | 1 + wocky/wocky-caps-hash.c | 28 ++++++++++++++++------------ wocky/wocky-caps-hash.h | 2 +- 3 files changed, 18 insertions(+), 13 deletions(-) commit c08c0f7c002a8a1755f198367ced6858bdbf2253 Author: Jonny Lamb Date: Mon Jan 24 10:50:35 2011 +0000 caps-cache: remove copy-paste error in documentation Signed-off-by: Jonny Lamb wocky/wocky-caps-cache.c | 1 - 1 file changed, 1 deletion(-) commit 339635a4b2129f585ae720dde3af8ccfc81730ea Author: Jonny Lamb Date: Fri Jan 21 16:34:53 2011 +0000 caps-hash: use wocky_node convenience functions WockyNode knows that xml:lang and xmlns attributes mean a bit more than an attribute with those names. Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 469d81f9f36fb35ab2947eaadbc452bf00b6418a Author: Jonny Lamb Date: Fri Jan 21 16:34:42 2011 +0000 caps-hash: fix typo Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit dbcc556adcf59612ee231ab410ff6115b83c0d6f Author: Jonny Lamb Date: Thu Jan 20 14:13:39 2011 +0000 caps-hash: make build in Wocky and rename s/gabble/wocky/g Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 218 +++++++++++++++++------------------------------- wocky/wocky-caps-hash.h | 10 +-- 2 files changed, 81 insertions(+), 147 deletions(-) commit 8ebef4c221f56c55d175af880b1bda99cf0efcfe Author: Jonny Lamb Date: Thu Jan 20 14:13:29 2011 +0000 disco-identity: add from Gabble Signed-off-by: Jonny Lamb wocky/Makefile.am | 4 ++ wocky/wocky-disco-identity.c | 160 +++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-disco-identity.h | 58 ++++++++++++++++ 3 files changed, 222 insertions(+) commit 2c648be4944d3f65032fe2c5ad96ddcf58aaf852 Author: Jonny Lamb Date: Thu Jan 20 13:34:10 2011 +0000 caps-hash: add caps-hash.[ch] from gabble Signed-off-by: Jonny Lamb wocky/wocky-caps-hash.c | 439 ++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-caps-hash.h | 32 ++++ 2 files changed, 471 insertions(+) commit b3812fad955afdbf21602039035ae9c377e99d5d Author: Jonny Lamb Date: Tue Jan 18 11:36:38 2011 +0000 caps-cache: store caps cache in .cache/caps/caps-cache.db Signed-off-by: Jonny Lamb wocky/wocky-caps-cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit cc4e726670d37ecbe68069e2b8af79454bedf7e4 Author: Jonny Lamb Date: Tue Jan 18 08:59:19 2011 +0000 caps-cache: add documentation Signed-off-by: Jonny Lamb docs/reference/wocky-docs.sgml | 1 + wocky/wocky-caps-cache.c | 60 +++++++++++++++++++++++++++++++++++++++--- wocky/wocky-caps-cache.h | 2 +- 3 files changed, 59 insertions(+), 4 deletions(-) commit 27c0a93f851917334ce0177daf3eadfc0ac7a007 Author: Jonny Lamb Date: Tue Jan 18 08:58:27 2011 +0000 caps-cache: stop declaring a non-existent get_singleton function Signed-off-by: Jonny Lamb wocky/wocky-caps-cache.h | 3 --- 1 file changed, 3 deletions(-) commit 3f42c9a47510557b718f5c5e162f3bb34032e1fe Author: Jonny Lamb Date: Tue Jan 18 08:56:51 2011 +0000 wocky: link to sqlite3 Signed-off-by: Jonny Lamb configure.ac | 10 +++++++--- docs/reference/Makefile.am | 4 ++-- wocky/Makefile.am | 4 ++-- 3 files changed, 11 insertions(+), 7 deletions(-) commit ac5467999fd4d202bf69d9d41899fd142f935e24 Author: Jonny Lamb Date: Tue Jan 18 08:27:39 2011 +0000 caps-cache: typedef object and class structs ... for consistency. Signed-off-by: Jonny Lamb wocky/wocky-caps-cache.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) commit 58e062587ccb4940420a0e52817569cae9d193dd Author: Jonny Lamb Date: Tue Jan 18 08:24:42 2011 +0000 caps-cache: misc. style changes Signed-off-by: Jonny Lamb wocky/wocky-caps-cache.c | 52 +++++++++++++++++++++++------------------------- wocky/wocky-caps-cache.h | 24 ++++++++++------------ 2 files changed, 36 insertions(+), 40 deletions(-) commit d97129d0ab8ad1abd72a3d4f80ab993be7e0db72 Author: Jonny Lamb Date: Tue Jan 18 08:24:23 2011 +0000 caps-cache: don't save caps cache into a telepathy directory Signed-off-by: Jonny Lamb wocky/wocky-caps-cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 8b19a91ed6b0bf4d6ccfbd1425c36ed08895c01e Author: Jonny Lamb Date: Tue Jan 18 08:20:17 2011 +0000 caps-cache: copy over from Gabble with s/gabble/wocky/g Signed-off-by: Jonny Lamb wocky/Makefile.am | 2 + wocky/wocky-caps-cache.c | 716 +++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-caps-cache.h | 88 ++++++ wocky/wocky-debug.c | 1 + wocky/wocky-debug.h | 1 + 5 files changed, 808 insertions(+) commit 6e64eff081fa59ce533728b2b1838cf0c798d968 Author: Will Thompson Date: Mon Jan 10 11:12:42 2011 +0000 Muc: correctly parse the 'composing' chat state. In 6b6f09d97f91de66c11a4b6a7e28222e8dc911f6 I replaced a lookup table for parsing these with GEnum. What I (and the reviewer) didn't notice is that the WockyMucMsgState enum doesn't actually correspond to the names used in XEP-0085! Since 'typing' isn't a thing in XMPP, the 'composing' state was misparsed. wocky/wocky-muc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 14bdb7c316028b9df67ebe6ad2e9f729d024ff74 Author: Sjoerd Simons Date: Fri Dec 24 20:54:53 2010 +0100 DEBUG once per mainloop iteration is bad, remove wocky/wocky-heartbeat-source.c | 1 - 1 file changed, 1 deletion(-) commit 8db5c13fe1895625a80d66ce2aef376cae6e9f8f Author: Nicolas Dufresne Date: Tue Sep 28 18:41:58 2010 -0400 Add assertions to ensure async resources are freed Add assertions to make sure async resources GCancellable and GSimpleAsyncResult are freed before a new async calls are attempted. wocky/wocky-openssl.c | 1 + wocky/wocky-porter.c | 4 ++++ wocky/wocky-tls-connector.c | 1 + wocky/wocky-tls.c | 1 + 4 files changed, 7 insertions(+) commit 6c92f00e745f65e05bc8379410ef096be2699b77 Author: Nicolas Dufresne Date: Mon Sep 27 18:28:40 2010 -0400 Fix wocky_implement_finish_*() macro * Fixed missing scope (G_STMT_START/G_STMT_END) and missing parenthesis * Don't call copy_func if the result is NULL (enabling use of g_object_ref as copy_func). * Added missing ; now required when those macro are called. wocky/wocky-pubsub-node.c | 12 ++++---- wocky/wocky-pubsub-service.c | 2 +- wocky/wocky-utils.h | 68 ++++++++++++++++++++++++++++---------------- 3 files changed, 50 insertions(+), 32 deletions(-) commit f38f22015aa144614c2d7295b59af3ae017bf313 Author: Will Thompson Date: Wed Dec 15 19:32:47 2010 +0000 Heartbeat: safely stop polling iphb FD. wocky_heartbeat_source_degrade() is also used to clean up in wocky_heartbeat_source_finalize(). By the time the latter is called, WockyHeartbeatSource (which is-a GSource) has been destroyed in the GSource sense, which implicitly removes all poll FDs. So we need to guard our call to g_source_remove_poll with a check for whether we've been destroyed or not. We could alternatively have two different cleanup functions, one for when we're degrading and one for when we're being destroyed, but I think this is simpler. wocky/wocky-heartbeat-source.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) commit 5a119a61e8e19741bd5a26333f4f54c12296943e Author: Will Thompson Date: Tue Aug 17 16:38:29 2010 +0100 MUC: only include when joining. Fixes: wocky/wocky-muc.c | 15 +++++++-------- wocky/wocky-muc.h | 3 +-- 2 files changed, 8 insertions(+), 10 deletions(-) commit 51dd1729f561058153e1a98f03be24c0228e5747 Author: Will Thompson Date: Tue Aug 17 16:27:48 2010 +0100 Inline wocky_muc_send_presence() It's only used in one place for now, and that one place is going to have to use wocky_muc_create_presence() directly anyway when the latter doesn't add the node. wocky/wocky-muc.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) commit e8c68ba002bf94862a94e90e29fa223b05815a74 Author: Will Thompson Date: Sat Nov 20 11:38:48 2010 +0000 connector-test: fix a typo of 'sasl' /connector/problem/sas/no-mechanisms should read /connector/problem/sasl/no-mechanisms. tests/wocky-connector-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 877802c153392f272d9708a0f15c81b679c51042 Author: Will Thompson Date: Sat Nov 20 11:31:32 2010 +0000 examples/connect: always call wocky_init(). The previous fix, in d0977e8, only called wocky_init() on one branch. Thus, the example worked in 'connector' mode, but not in 'raw' mode (the default)... We should just call it up-front alongside g_type_init(). examples/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 94240be7cef4d878410cb0843063d4f75b270edb Author: Simon McVittie Date: Tue Nov 23 16:00:59 2010 +0000 Add maintainer-upload-docs target to Makefile.am Makefile.am | 5 +++++ 1 file changed, 5 insertions(+) commit 4ea0e486e9b40d64b16dc566714f613b6b430e77 Author: Jonny Lamb Date: Mon Nov 15 13:10:23 2010 +0000 auth-registry: add a namespace to auth mechanism constants Signed-off-by: Jonny Lamb wocky/wocky-auth-registry.c | 8 ++++---- wocky/wocky-auth-registry.h | 8 ++++---- wocky/wocky-jabber-auth-digest.c | 2 +- wocky/wocky-jabber-auth-password.c | 2 +- wocky/wocky-jabber-auth.c | 4 ++-- wocky/wocky-sasl-digest-md5.c | 2 +- wocky/wocky-sasl-plain.c | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) commit 29ac49f0cd6f052bf7ab29010853e37510af1437 Merge: 5b6ea68 5ec9c99 Author: Will Thompson Date: Wed Nov 10 15:56:59 2010 +0000 Merge branch 'iphb' commit 5b6ea68ad8300919341d30fc4b35303b65258e93 Author: Will Thompson Date: Wed Nov 10 14:47:02 2010 +0000 OpenSSL: improve debugging output for ignored errors We reasonably frequently hit UNABLE_TO_GET_CRL. Currently, the debug output is kind of surprising: check_peer_name: wocky-openssl.c:877: got cname 'ovi.com' from x509 name, nid #0 compare_wildcarded_hostname: wocky-openssl.c:831: ovi.com ~ ovi.com wocky_tls_session_verify_peer: wocky-openssl.c:1058: cert verification error: 3 xmpp_init: wocky-connector.c:1056: sending XMPP stream open to server What's actually happening here is that we're ignoring error 3 (UNABLE_TO_GET_CRL) because it's completely harmless. But to the uninformed reader it looks like an error should have occurred. wocky/wocky-openssl.c | 5 +++++ 1 file changed, 5 insertions(+) commit 4ce13bb2306dc8da26a9bf21dedc279a3f472dd9 Author: Will Thompson Date: Wed Nov 10 14:37:31 2010 +0000 OpenSSL: don't erroneously truncate X509_NAMEs. The manpage for X509_NAME_get_text_by_NID() says: At most len bytes will be written and the text written to buf will be null terminated. And: If buf is then the amount of space needed in buf (excluding the final null) is returned. So we call X509_NAME_get_text_by_NID() once, passing a NULL buffer, to discover how long a buffer we have to allocate. Then we allocate that buffer, and pass it back in. But while the returned length excludes the null terminator, the length we pass in should include it. This fixes an issue where, when connecting to (for example) door.com, we'd erroneously believe that its certificate is for "door.co" and reject it. Reviewed-by: Simon McVittie wocky/wocky-openssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit b0ebed783ce4c2b27ad5d35f6cf847d9f5363962 Author: Will Thompson Date: Wed Nov 10 14:36:48 2010 +0000 OpenSSL: add debug output to check_peer_name() It'd be useful to be able to see from a debug log where in the certificate the name being examined was found. Reviewed-by: Simon McVittie wocky/wocky-openssl.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) commit 5ec9c99b5b7bc7179df62ad31e2af1d9ef7a5f87 Author: Will Thompson Date: Mon Oct 25 12:34:13 2010 +0100 Clarify that moving next_wakeup into the past is okay wocky/wocky-heartbeat-source.c | 3 +++ 1 file changed, 3 insertions(+) commit 01811a4a6ed0ac6ad5f9439d12560d787c97570d Author: Will Thompson Date: Mon Oct 25 11:58:52 2010 +0100 Ping test: reduce the number of pings sent and time waited I think it's important that we send more than one ping in a row, to ensure that scheduling the next wakeup works. It's also important that we wait longer than one ping interval when checking that no more pings are sent. Finally, we do need to test turning pings back on after turning them off. But previously we waited for three pings, turned off pings and waited three seconds to check we don't get any pings we don't expect, and then turned them back on and waited for three more. This is overkill; this patch makes us wait for two pings, wait for two seconds after turning them off, and only wait for one more ping after turning them back on. tests/wocky-ping-test.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit 2aef513cca19ecf74475c8058ed1f272c69c083e Author: Will Thompson Date: Mon Oct 25 11:58:35 2010 +0100 Heartbeat: add this/next wakeup timestamps to debug output wocky/wocky-heartbeat-source.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) commit 803f671f4e1421c5d8ead77babab97e98a7e0a0a Author: Will Thompson Date: Thu Oct 21 18:55:20 2010 +0100 Heartbeat: explain why _new() doesn't use update_interval() I just tried refactoring things to make wocky_heartbeat_source_new() call wocky_heartbeat_source_update_interval(). It broke, because the latter uses g_source_get_current_time(). Maybe it shouldn't... but it seems reasonable to assume we're attached to a main context when someone calls wocky_heartbeat_source_update_interval(). wocky/wocky-heartbeat-source.c | 4 ++++ 1 file changed, 4 insertions(+) commit 83494b109f1ac08777c8a49ed82aa0d4c127bb77 Author: Will Thompson Date: Thu Oct 21 18:37:27 2010 +0100 Ping: flag ping-interval property as CONSTRUCT This means it's set by the time that we construct the heartbeat. It shouldn't make a difference, but it reduces spurious debug output. wocky/wocky-ping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 4e9f9530383d1162619c7e214dc18c64d64a1468 Author: Will Thompson Date: Tue Oct 19 19:04:57 2010 +0100 Improve WockyPing's debugging output. wocky/wocky-ping.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) commit 7cb68e637937b67866d2f17effb5de728e516c27 Author: Will Thompson Date: Tue Oct 19 14:17:25 2010 +0100 Heartbeat: handle max_interval = 0 This is used to indicate that the heartbeat should be disabled. tests/wocky-ping-test.c | 32 +++++++++++++++++++++- wocky/wocky-heartbeat-source.c | 61 +++++++++++++++++++++++++++++++++++------- 2 files changed, 82 insertions(+), 11 deletions(-) commit 38445ac40d4ad5c4bda86f491ffa11f3d0de6313 Author: Will Thompson Date: Tue Oct 19 14:52:21 2010 +0100 Add more debugging to the heartbeat wocky/wocky-heartbeat-source.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) commit 8704ea463278220f1514b981a8feafc448b4e3e1 Author: Will Thompson Date: Tue Oct 19 14:42:59 2010 +0100 Heartbeat: split degrading out of finalize Previously, we called wocky_heartbeat_source_finalize() whenever the heartbeat service had failed for any reason, which happened to do nothing more harmful than closing the connection to the heartbeat service. But this isn't particularly easy to read. Splitting the guts of the function out into wocky_heartbeat_source_degrade() makes the code more self-documenting. wocky/wocky-heartbeat-source.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) commit edbe19e12ae0350309b22126767428a5f623d7a6 Author: Will Thompson Date: Tue Oct 19 14:21:16 2010 +0100 Replace WockyPing's timeouts with WockyHeartbeat This strictly speaking introduces a regression: we no longer delay the next ping whenever we send data. But actually, I don't think this is all that necessary: if we want to do something in response to getting no replies to our pings, we have to be sure we're sending them in the first place. They're only tiny. wocky/wocky-ping.c | 78 +++++++++++++----------------------------------------- 1 file changed, 19 insertions(+), 59 deletions(-) commit dae40a8fc8a9b3449bf532a59d2169bd3e894470 Author: Will Thompson Date: Tue Oct 19 14:17:53 2010 +0100 Document heartbeat methods. wocky/wocky-heartbeat-source.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) commit 408ee992c698e195428fb976180de1563cf44834 Author: Will Thompson Date: Mon Oct 18 16:59:11 2010 +0100 Bake iphb interval policy into WockyHeartbeatSource Ultimately, the choice of how much earlier than the desired keepalive interval we're happy to be woken up by the system heartbeat service is pretty much arbitrary. So let's just bake it into the place where iphb is directly used. wocky/wocky-heartbeat-source.c | 18 ++++++++++++------ wocky/wocky-heartbeat-source.h | 2 -- 2 files changed, 12 insertions(+), 8 deletions(-) commit ed4f81dfda49ea0aab5d90dcf67439a2857a8d35 Author: Will Thompson Date: Fri Oct 15 16:10:01 2010 +0100 Heartbeat: support updating the interval on the fly wocky/wocky-heartbeat-source.c | 24 ++++++++++++++++++++++++ wocky/wocky-heartbeat-source.h | 5 +++++ 2 files changed, 29 insertions(+) commit 57e76648dd5024be789ecf3b4bfc2441198f97ac Author: Will Thompson Date: Mon Oct 18 13:49:13 2010 +0100 Heartbeat: extract common iphb_wait()-calling code wocky/wocky-heartbeat-source.c | 43 +++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) commit 83ca63974353febaaf5afcbb9e2734820a4182da Author: Will Thompson Date: Mon Oct 18 11:34:23 2010 +0100 Heartbeat: fall back to internal timeouts If we're not built with libiphb support, or if we get any errors in the course of using libiphb, this patch makes WockyHeartbeatSource simply act as a timeout source. wocky/wocky-heartbeat-source.c | 147 +++++++++++++++++++++++++++-------------- 1 file changed, 99 insertions(+), 48 deletions(-) commit 64540f03af6182f537959637a803a47554b4dcda Author: Will Thompson Date: Fri Oct 15 15:52:04 2010 +0100 Add a GSource wrapping libiphb. The Loudmouth patch to add libiphb support for Maemo 5 intertwingled it with other keepalive logic, but I think separating it out makes it cleaner. libiphb is part of DSME (http://gitorious.org/dsme/) which is now LGPL v2.1 (note: not "or later"). This is an optional dependency, so doesn't impact Wocky's license in general. Currently the source is completely inert if we don't have iphb support; it'll be fixed to fall back to acting as a timeout source later. configure.ac | 9 ++ wocky/Makefile.am | 5 +- wocky/wocky-debug.c | 1 + wocky/wocky-debug.h | 1 + wocky/wocky-heartbeat-source.c | 190 +++++++++++++++++++++++++++++++++++++++++ wocky/wocky-heartbeat-source.h | 37 ++++++++ 6 files changed, 242 insertions(+), 1 deletion(-) commit add1c55989ef3d3fa4a871d4ad217a49d301d2dc Author: Will Thompson Date: Mon Oct 25 11:39:28 2010 +0100 Fix DEBUGGING macro to call wocky_debug_flag_is_set() Hey, looks like no-one's used this before in Wocky. ;-) wocky/wocky-debug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit e54631ff2db562b0b104ef9a7f949d3fb2fb8df2 Author: Will Thompson Date: Tue Oct 19 16:56:02 2010 +0100 Test sending a stanza just before destroying porter. I'm astonished that this didn't have a test already. If we call wocky_porter_send_async(), then destroy the porter, and only then spin the main loop, we'd crash. This is because after the porter died, it'd take the xmpp connection down, which would then fire a callback to tell the porter that sending a stanza failed. The fix is simple: ref the porter across calls to wocky_xmpp_connection_send_stanza_async(). Reviewed-by: Nicolas Dufresne Fixes: tests/wocky-porter-test.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-porter.c | 4 +++- 2 files changed, 52 insertions(+), 1 deletion(-) commit cc5c5309c21694a4c120c4ba9f01fb12f27cb7ef Author: Will Thompson Date: Wed Oct 20 15:53:06 2010 +0100 OpenSSL: report hostname mismatch over other errors. I think this is more useful behaviour. Who cares if you can't find the CA for a certificate, if the certificate isn't even for the right domain? :) The GnuTLS backend already has this behaviour. tests/wocky-connector-test.c | 18 ++++++++++++++++++ wocky/wocky-openssl.c | 27 ++++++++------------------- 2 files changed, 26 insertions(+), 19 deletions(-) commit 5079a1ec30235c76f5b2b18655799849d26f90bf Author: Will Thompson Date: Wed Oct 20 15:44:14 2010 +0100 OpenSSL: clarify anonymous certificate handling wocky/wocky-openssl.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) commit 36af8b71fdd7ee9869ebdc584631cb51fe589aac Author: Will Thompson Date: Wed Oct 20 12:46:52 2010 +0100 TestConnectorServer: use '*' in a _build() call tests/wocky-test-connector-server.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) commit 86046ac87936bbadc0b6d7a4679d85a0f094e407 Author: Will Thompson Date: Wed Oct 20 00:09:17 2010 +0100 Remove unnecessary MUC namespace abbreviations. I like avoiding typing as much as the next person, but. (This will break Gabble, which uses WOCKY_NS_MUC_OWN.) wocky/wocky-muc.c | 2 +- wocky/wocky-namespaces.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) commit e25cc2a0c89ce9270da04199d4be73ec9c6b5dcf Author: Will Thompson Date: Tue Oct 19 19:01:13 2010 +0100 Use wocky_stanza_get_{from,to} tests/wocky-porter-test.c | 3 +-- tests/wocky-roster-test.c | 3 +-- wocky/wocky-muc.c | 5 ++--- wocky/wocky-pep-service.c | 3 +-- wocky/wocky-porter.c | 9 +++------ wocky/wocky-roster.c | 3 +-- 6 files changed, 9 insertions(+), 17 deletions(-) commit 181a042eb85a59497d6361b68d125df0db4ed092 Author: Will Thompson Date: Tue Oct 19 18:55:55 2010 +0100 Add wocky_stanza_get_{from,to} wocky/wocky-stanza.c | 34 ++++++++++++++++++++++++++++++++++ wocky/wocky-stanza.h | 3 +++ 2 files changed, 37 insertions(+) commit 8924acd99e33b5fce0bcf395fe4ad25470417f21 Author: Will Thompson Date: Tue Oct 19 13:45:47 2010 +0100 Check debug flags correctly when logging stanzas These two stray 's's drove me extra crazy while debugging a bizarre memory corruption bug. wocky/wocky-debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 635df31cbd8f9d7302b694bbf59157f58101a950 Author: Will Thompson Date: Thu Oct 14 23:49:13 2010 +0100 Fix up wocky-utils comment trivia. The introductory comments in wocky-utils.[ch] claimed the files to be called gibber-util.[ch]. Also, the header guard was singular, not plural. This offends me. wocky/wocky-utils.c | 4 ++-- wocky/wocky-utils.h | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) commit 5c4c8ecf1656cc593b0af19cd1a9b2db940f601c Author: Will Thompson Date: Tue Apr 20 16:42:15 2010 +0100 Correct documentation of wocky_node_is_superset wocky/wocky-node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit caece2b087b505f1be4637dbff89679295d83e61 Author: Will Thompson Date: Tue Apr 13 22:46:28 2010 +0100 Give a useful critical when you mess up _stanza_build() wocky/wocky-node.c | 1 + 1 file changed, 1 insertion(+) commit bfcdeadf0781d6d2cb2d7e1b9a93756dc4ecce5c Author: Nicolas Dufresne Date: Thu Oct 14 19:20:30 2010 -0400 Fixe last bad comparision in OpenSSL code wocky/wocky-openssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 2e7d77f14f3404ade60431cad82fc8a91eabb145 Author: Nicolas Dufresne Date: Thu Oct 14 19:08:21 2010 -0400 Fix boolean comparision in OpenSSL code This change was introduced by accident in leak-fix branch while doing some refactoring. This will hopefully solve OpenSSL build errors. wocky/wocky-openssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 66e264e385cf2cbbd09a2d9723720d5c5bd4ec57 Merge: d339fbc d67a032 Author: Nicolas Dufresne Date: Thu Oct 14 18:44:43 2010 -0400 Merge branch 'wocky-0.10' commit d67a032e68d08825b0aa7eb42673393ba68a1403 Author: Nicolas Dufresne Date: Thu Oct 14 11:33:04 2010 -0400 Use G_N_ELEMENT to get array size tests/wocky-http-proxy-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 78c7d6cd96a44d3aa2235a0640be18e9979c6f54 Author: Nicolas Dufresne Date: Thu Oct 14 11:32:20 2010 -0400 Avoid magic numbers implementing str_has_prefix_case() tests/wocky-http-proxy-test.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) commit 3989fcaa2dad9dbf689c29729a11cb731e9264ca Author: Nicolas Dufresne Date: Thu Oct 14 11:27:02 2010 -0400 Use g_assert_cmpstr() for better output tests/wocky-http-proxy-test.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) commit 850cb5a5c849322a71b08304b69d2214250ecaa3 Author: Nicolas Dufresne Date: Thu Oct 14 11:25:40 2010 -0400 Use g_assert_cmpuint for better output tests/wocky-http-proxy-test.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) commit d339fbcabd6b1aabcac52817e2cb5480ff9d3e31 Merge: 2cf2577 e957e75 Author: Nicolas Dufresne Date: Wed Oct 13 11:56:44 2010 -0400 Merge branch 'leak-fix' Reviewed-by: Will Thompson commit e957e75e785200991b3f346298a7d3c0f4e3584e Author: Nicolas Dufresne Date: Wed Oct 13 11:49:31 2010 -0400 More style fix when doing if on pointers tests/wocky-connector-test.c | 2 +- tests/wocky-test-connector-server.c | 2 +- wocky/wocky-muc.c | 8 ++++---- wocky/wocky-openssl.c | 18 +++++++++--------- wocky/wocky-tls.c | 16 ++++++++-------- wocky/wocky-utils.c | 4 ++-- wocky/wocky-xmpp-writer.c | 2 +- 7 files changed, 26 insertions(+), 26 deletions(-) commit ae8abda698643d2d9b7ef9c962f3c5e0d5ff81a8 Author: Nicolas Dufresne Date: Wed Oct 13 11:23:20 2010 -0400 Fix coding style error introduced in leak fixes tests/wocky-test-connector-server.c | 4 ++-- tests/wocky-test-sasl-auth-server.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) commit 7a5ebbd8a6b160cd3b65e66b12c55892dff47c92 Author: Nicolas Dufresne Date: Tue Oct 12 15:50:45 2010 -0400 Don't leak tls_connection on error wocky/wocky-tls-connector.c | 7 +++++++ 1 file changed, 7 insertions(+) commit d65e92b2637718e9af2b85416bd354c911dac55f Author: Nicolas Dufresne Date: Tue Oct 12 15:30:30 2010 -0400 Don't leak last read buffer wocky/wocky-tls.c | 5 +++++ 1 file changed, 5 insertions(+) commit 88938428ad9152e02eff643ec412a3154cf1658a Author: Nicolas Dufresne Date: Tue Oct 12 15:01:02 2010 -0400 Don't leak errors in TLS tests tests/wocky-test-connector-server.c | 8 ++++++-- wocky/wocky-tls-connector.c | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) commit b54b111ac40c996896181a2f0b43fac8eb7b51c3 Author: Nicolas Dufresne Date: Fri Oct 8 17:50:55 2010 -0400 Only ref the cancellable if a callback is provided tests/wocky-test-sasl-auth-server.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) commit 4461be9b3cb5776b55e4fe8f1ef2d9939d160d20 Author: Nicolas Dufresne Date: Fri Oct 8 17:21:06 2010 -0400 Don't leak GSocket tests/wocky-connector-test.c | 1 + 1 file changed, 1 insertion(+) commit 97dbbfad80b373586e6d37d4a4e664e7b78b56d0 Author: Nicolas Dufresne Date: Fri Oct 8 17:19:51 2010 -0400 Don't leak errors tests/wocky-test-connector-server.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) commit 14df6aef00ab2880bb86ac86f88b9193ea8848cc Author: Nicolas Dufresne Date: Fri Oct 8 17:10:27 2010 -0400 Don't leak SASLServer by overwriting it tests/wocky-test-connector-server.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) commit f4e0ce027040dff5c7ddcb0cec62b2e4d3c02cf5 Author: Nicolas Dufresne Date: Fri Oct 8 17:10:05 2010 -0400 Don't leak TLSSession tests/wocky-test-connector-server.c | 4 ++++ 1 file changed, 4 insertions(+) commit 7c4468651d85d3904a7f2365c1d55e862cc44c7d Author: Nicolas Dufresne Date: Fri Oct 8 17:09:44 2010 -0400 Don't leak TLSConnection tests/wocky-test-connector-server.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) commit d8b8d403234d177b9ab1f7aed29569c1f434bca5 Author: Nicolas Dufresne Date: Fri Oct 8 16:58:32 2010 -0400 Don't leak error in test resolver tests/test-resolver.c | 64 +++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 33 deletions(-) commit 6246d9ad7290b86b3cbf29c2ad829bc8fdad7f68 Author: Nicolas Dufresne Date: Thu Oct 7 14:03:11 2010 -0400 Keep GCancellable alive during the async calls Keep a reference on GCancellable for the time of the async calls. This is important to allow simple cancel and forget of cancellable by caller. Most call were already implemented correctly, this patch fixes the remaining. tests/wocky-test-sasl-auth-server.c | 21 ++++++++++++++++- tests/wocky-test-stream.c | 9 +++++-- wocky/wocky-openssl.c | 11 +++++++-- wocky/wocky-porter.c | 32 +++++++++++++++++++++---- wocky/wocky-tls.c | 9 +++++-- wocky/wocky-xmpp-connection.c | 47 +++++++++++++++++++++++++++++++++---- 6 files changed, 112 insertions(+), 17 deletions(-) commit 8e254f7f3e571d739e233034682facbf63efc51c Author: Nicolas Dufresne Date: Fri Oct 8 16:41:37 2010 -0400 Don't leak current path string wocky/wocky-utils.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit f13a2c8e9af91762d86b6cd26cba57f2f0cb47fd Author: Nicolas Dufresne Date: Fri Oct 8 13:01:11 2010 -0400 Fix function implementation coding style wocky/wocky-porter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit bb9b190f87db3eb60d1748f399fcd298c31d2c8c Author: Nicolas Dufresne Date: Fri Oct 8 12:30:53 2010 -0400 Don't leak a ref on TlsConnection in verify_async wocky/wocky-tls-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit bb167324fb0a1c9b21b7a7d7d1146ca8753c0d65 Author: Nicolas Dufresne Date: Thu Oct 7 19:10:09 2010 -0400 Add explicit _stop() to test SASL auth server The test SASL auth server did not have a _stop() method. As the call to new() starts an infinit async call on internal XmppConnection, the Xmpp Connection get leaked. Adding an explici _stop(), fixes this issue. tests/wocky-test-sasl-auth-server.c | 29 ++++++++++++++++++++++++----- tests/wocky-test-sasl-auth-server.h | 2 ++ tests/wocky-test-sasl-auth.c | 2 ++ 3 files changed, 28 insertions(+), 5 deletions(-) commit 2cf2577a5465d8b13fa3d72e73cc384a68dd488d Author: Will Thompson Date: Fri Oct 8 13:45:43 2010 +0100 OpenSSL: add a missing 'break'. This was broken in 9a3f3bc8, which added the case for UNABLE_TO_GET_CRL. Reviewed-by: Simon McVittie wocky/wocky-openssl.c | 1 + 1 file changed, 1 insertion(+) commit a70a56c6f232bb9bffc91b68898f4d2b396a503f Author: Will Thompson Date: Fri Oct 8 13:44:04 2010 +0100 Clarify extracting error type. wocky_enum_from_nick() doesn't modify its final parameter if it returns FALSE, so this code already did the right thing for unrecognised error types. But this patch rearranges the code to make this clearer. Reviewed-by: Simon McVittie wocky/wocky-xmpp-error.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) commit 7e22acb544bffb4bae9fd13da72e20f3f438d87d Author: Nicolas Dufresne Date: Thu Oct 7 19:09:35 2010 -0400 Don't leak a GAsyncResult in WockyPorter wocky/wocky-porter.c | 2 ++ 1 file changed, 2 insertions(+) commit f8c72df24c89f839f1819c78e3de3f5e03529b61 Author: Nicolas Dufresne Date: Thu Oct 7 16:46:28 2010 -0400 Fixed memmory leak in WockySaslScam wocky/wocky-sasl-scram.c | 8 ++++++++ 1 file changed, 8 insertions(+) commit 30166aeb891b0ceca7995268846fe900fd13b06a Author: Nicolas Dufresne Date: Tue Oct 5 15:12:12 2010 -0400 Unit tests for HTTP Proxy support This implements unit test for the wocky internal implementation of HTTP Connect. tests/Makefile.am | 9 + tests/wocky-http-proxy-test.c | 385 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 394 insertions(+) commit 60278f0fef9a5075f91c3dffe56352448695fb5e Author: Nicolas Dufresne Date: Tue Oct 5 15:10:27 2010 -0400 Implement HTTP basic proxy authentication This adds HTTP basic proxy authentication as requesting in bugs.fd.o #16034 wocky/wocky-http-proxy.c | 109 +++++++++++++++++++++++++++-------------------- 1 file changed, 63 insertions(+), 46 deletions(-) commit 210523aab3532d2c77bffa933aea8d761e08d0ab Author: Nicolas Dufresne Date: Tue Oct 5 15:06:40 2010 -0400 Handle EOS gracefully by manually generating error GIO does not return an error on EOS so we need to manually generate an error when the EOS arrived too soon. wocky/wocky-http-proxy.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) commit 953d5a19779ad88f0cf44b08d2f1851dea3b8ce5 Author: Nicolas Dufresne Date: Tue Oct 5 15:03:03 2010 -0400 Remove HTTP error code for known errors The HTTP error code is not that usefull for error that we know about. wocky/wocky-http-proxy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 13e657288e24ab640560dbaf44d7853678c793da Author: Nicolas Dufresne Date: Thu Sep 30 15:25:59 2010 -0400 Improve error message in HTTPProxy Adds error code to message and nicier handling of broken reply. wocky/wocky-http-proxy.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) commit 31a75968dfc980bb9267db3e0da251f1b9332707 Author: Nicolas Dufresne Date: Thu Sep 30 15:25:00 2010 -0400 Free variables as soon as they are no longer needed This allow reducing the amount of dupplicated free/unref in the error label. wocky/wocky-http-proxy.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) commit 7f12560eb5ddedad674a5a9421ef3193b3cfa96d Author: Nicolas Dufresne Date: Thu Sep 30 15:23:30 2010 -0400 Fix coding style * Use explicit comparision * Unified GDataInputStream variable as data_in * Add missing white space before/after if wocky/wocky-http-proxy.c | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) commit 2ba0e569c9953651f800372cd2f7f3638dee09e3 Author: Nicolas Dufresne Date: Thu Sep 30 15:11:03 2010 -0400 Remove unsuded wocky_http_proxy_finalize() WockyHttpProxy does not have any internal resources so wocky_http_proxy_finalize() is not used at all, removing it. wocky/wocky-http-proxy.c | 11 ----------- 1 file changed, 11 deletions(-) commit 38e1a9077d0f9cd90c3d41635485956d3ca8cbae Author: Nicolas Dufresne Date: Thu Sep 30 15:09:44 2010 -0400 Don't use double underscore Double underscores variable and macro are reserved for compilers. wocky/wocky-http-proxy.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit 92d16af8158bd45263f38db1d8b1787e661b4ca9 Author: Nicolas Dufresne Date: Thu Sep 30 14:12:59 2010 -0400 Added proxy sources to extra dist When GIO does not support proxy we need to put the proxy specific sources in the EXTRA_DIST list to ensure it is being shipped. wocky/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) commit 668837041c03de92be41bd70247bde4b733dc6e8 Author: Nicolas Dufresne Date: Thu Aug 26 11:29:12 2010 -0400 Added support for HTTP Connect Proxy This patch registers an HTTP Connect extension to GLib proxy facility. This extension is triggered (whenever an HTTPS proxy is set) when legacy_ssl is being by providing a https:// base URI to the GSocketClient connect method. configure.ac | 8 + wocky/Makefile.am | 8 + wocky/wocky-connector.c | 33 +++- wocky/wocky-http-proxy.c | 414 +++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-http-proxy.h | 43 +++++ 5 files changed, 502 insertions(+), 4 deletions(-) commit 3d8bd1bd1e3857f1a14dbba92a8fe6bf7f790054 Author: Nicolas Dufresne Date: Thu Sep 23 14:22:11 2010 -0400 GSimpleAsyncResult source tags should be _async This makes Wocky closer to GAsyncResult conventions by using the _async function as source tag instead of _finish. (Bug #26770) tests/wocky-test-connector-server.c | 2 +- tests/wocky-test-sasl-auth-server.c | 4 +- tests/wocky-test-stream.c | 84 ++++++++++++++++++------------------- wocky/wocky-auth-registry.c | 12 +++--- wocky/wocky-jabber-auth.c | 4 +- wocky/wocky-muc.c | 2 +- wocky/wocky-pep-service.c | 4 +- wocky/wocky-porter.c | 16 +++---- wocky/wocky-pubsub-service.c | 4 +- wocky/wocky-roster.c | 24 +++++------ wocky/wocky-sasl-auth.c | 4 +- wocky/wocky-tls-connector.c | 4 +- wocky/wocky-tls-handler.c | 4 +- wocky/wocky-xmpp-connection.c | 24 +++++------ 14 files changed, 96 insertions(+), 96 deletions(-) commit 1b2804c9fd2d46bdc01a43a004183ea1c5d8957d Author: Sjoerd Simons Date: Fri Oct 1 15:19:59 2010 +0100 Increase test timeout to 10 seconds tests/wocky-test-helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit f7531b2e77056471a0a0cb089346b4d8f15dc945 Author: Sjoerd Simons Date: Fri Oct 1 14:52:31 2010 +0100 Update the CRL to only expect a new update in 2038 tests/certs/ca-0-crl.cfg | 1 + tests/certs/ca-0-crl.pem | 16 ++++++++-------- tests/certs/crl/ca-0-crl.pem | 16 ++++++++-------- 3 files changed, 17 insertions(+), 16 deletions(-) commit 81d91749669806cb0e05954af26a75778bbf1fe8 Author: Sjoerd Simons Date: Fri Oct 1 12:21:02 2010 +0100 Fix compilation with older glib tests/wocky-connector-test.c | 5 +++++ 1 file changed, 5 insertions(+) commit f2cb0f6fc98b7d75b08516710046977195e26faa Author: Sjoerd Simons Date: Thu Sep 30 17:46:06 2010 +0100 Accept recoverable errors and fixup namespaces with extra spaces tests/wocky-xmpp-reader-test.c | 33 +++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-reader.c | 21 ++++++++++++++++----- 2 files changed, 49 insertions(+), 5 deletions(-) commit d3e68d03f79625f695601b3b69dd853785fc14f3 Author: Sjoerd Simons Date: Wed Sep 29 16:22:19 2010 +0100 Handle the connection being disconnected by the remote side more gracefully wocky/wocky-tls.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) commit 9d74bc20a9ad3118f28a896483f6a36e46b036eb Author: Sjoerd Simons Date: Thu Sep 30 16:52:25 2010 +0100 Cope with new GIO giving more precise error information tests/wocky-connector-test.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) commit 7d33e5c6d2499c2cad0e476d646feb548fb25d5b Author: Sjoerd Simons Date: Thu Sep 30 16:41:53 2010 +0100 Always use enum values for codes, not 0... tests/wocky-connector-test.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) commit 69ce5d52e44bf1fcf9b420a1a91031714188f4ac Author: Sjoerd Simons Date: Thu Sep 30 16:34:07 2010 +0100 Support fallback error codes Over time GIO got more precise about its error codes, so add support for a fallback error code that's also accepted tests/wocky-connector-test.c | 472 +++++++++++++++++++++++-------------------- 1 file changed, 253 insertions(+), 219 deletions(-) commit fb2f241fce7f7c106c16519c5e2be4eca4fbc34a Author: Sjoerd Simons Date: Thu Sep 30 13:50:13 2010 +0100 Use an internal enum to error code mapping instead of hardcoding quark strings tests/wocky-connector-test.c | 490 ++++++++++++++++++++++--------------------- 1 file changed, 256 insertions(+), 234 deletions(-) commit 4816b2d65de1c66bb95de02c55e138264c28dbc7 Author: Will Thompson Date: Thu Sep 30 14:17:31 2010 +0100 Ignore gtkdoc scanner. Reviewed-by: Simon McVittie .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit a8002b2bbfbd259961c59a7f714e25ad14fc521f Author: Will Thompson Date: Thu Sep 30 10:33:00 2010 +0100 OpenSSL: include error domain in debug, too There's really no point in including the error code if we don't include the domain it belongs to, too. Reviewed-by: Jonny Lamb wocky/wocky-openssl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 790bf30d1832ac8f678d3e5f0dc051dd392a3f26 Author: Will Thompson Date: Thu Sep 30 10:27:55 2010 +0100 OpenSSL: fix a debug format string. There are four parameters after this format string, but the string only contains three placeholders. GCC, quite rightly, gets upset. This was broken in 551e3ad. Reviewed-by: Jonny Lamb wocky/wocky-openssl.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) commit 61764f3912aa1f3b2d881fe518a701253fe4249c Merge: dbbea11 0b104ce Author: Will Thompson Date: Fri Sep 24 12:05:07 2010 +0100 Merge branch 'wocky-0.10' commit 0b104ceae9edd2fa860f5ddb193d5b077da7b9f6 Author: Will Thompson Date: Fri Sep 24 11:38:56 2010 +0100 Check return of wocky_xmpp_connection_send_stanza_finish Reviewed-by: Simon McVittie wocky/wocky-tls-connector.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) commit e4842e8ac07922c51a790be12ddc59c286727d36 Author: Guillaume Desmottes Date: Thu Sep 23 16:23:56 2010 +0200 check if the result contains an error *before* g_simple_async_result_is_valid That's the usual pattern. If we early return in the _async function and raise an error using g_simple_async_report_error_in_idle(), then the result doesn't have a source tag. wocky/wocky-utils.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) commit b8db8f2e648a27e9020a99e027041cafb29e0c20 Author: Guillaume Desmottes Date: Thu Sep 23 16:22:51 2010 +0200 wocky_implement_finish_return_copy_pointer: return NULL and not FALSE wocky/wocky-utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit dbbea11d86d0f154c3b5728803f8e237fe5acad8 Author: Guillaume Desmottes Date: Thu Sep 23 16:23:56 2010 +0200 check if the result contains an error *before* g_simple_async_result_is_valid That's the usual pattern. If we early return in the _async function and raise an error using g_simple_async_report_error_in_idle(), then the result doesn't have a source tag. wocky/wocky-utils.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) commit 0c6c1d659ffc51e03de97f7e9fdc97648e5eb1e2 Author: Guillaume Desmottes Date: Thu Sep 23 16:22:51 2010 +0200 wocky_implement_finish_return_copy_pointer: return NULL and not FALSE wocky/wocky-utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit cb7d242e9f771b5d4af8f5fc8aa35304a038a810 Author: Vivek Dasmohapatra Date: Wed Sep 22 12:14:45 2010 +0100 Explain why ignore_warning is there in the write_op implementation wocky/wocky-openssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 551e3ad46325674015503049d2908d59df407efc Author: Vivek Dasmohapatra Date: Tue Sep 21 00:09:59 2010 +0100 Don't retry indefinitely on failed OpenSSL writes Previously, the response to any partial write was to try again later, even if the error returned indicated that it would never succeed. Instead, we should only retry later if WOULD_BLOCK is returned (indicating only that the write buffer is full, as opposed to an actual error). This error was only in the OpenSSL backend; gnutls does not require us to implement this logic at all. wocky/wocky-openssl.c | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) commit 87a64d465283ab01baceca9aefbb15a80b391b7f Author: Cosimo Cecchi Date: Tue Sep 14 19:27:57 2010 +0200 Update examples and tests to new API examples/connect.c | 2 +- examples/register.c | 2 +- examples/unregister.c | 2 +- tests/wocky-connector-test.c | 9 ++++++--- 4 files changed, 9 insertions(+), 6 deletions(-) commit 66689d2b261e442cdec52a42acd259beb2f0ed00 Author: Cosimo Cecchi Date: Tue Sep 14 19:27:28 2010 +0200 connector: use a GCancellable for async operations And pass it when we send/receive stanzas. wocky/wocky-connector.c | 100 +++++++++++++++++++++++++++++++++++------------- wocky/wocky-connector.h | 3 ++ 2 files changed, 77 insertions(+), 26 deletions(-) commit 4d228e61d6068291e8281440aab729d5e4a216ba Author: Cosimo Cecchi Date: Tue Sep 14 19:26:00 2010 +0200 sasl-auth: use the GCancellable if available wocky/wocky-sasl-auth.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) commit 286e88f6fb3f3ec451c71bfb361b993d7b37eb8f Author: Cosimo Cecchi Date: Tue Sep 14 19:25:34 2010 +0200 jabber-auth: use the GCancellable if it's available wocky/wocky-jabber-auth.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) commit 0d4b3ff855fef2732cf024a7bdb6574d3b45ad7a Author: Cosimo Cecchi Date: Tue Sep 14 19:24:48 2010 +0200 tls-connector: add a GCancellable argument And use it if available when sending/receiving stanzas. wocky/wocky-tls-connector.c | 34 +++++++++++++++++++++++++++++----- wocky/wocky-tls-connector.h | 1 + 2 files changed, 30 insertions(+), 5 deletions(-) commit b2ad17044f1cadf61aa7d3df51660221ea775720 Author: Will Thompson Date: Mon Sep 6 18:07:56 2010 +0100 Fix tests for chat.facebook.com workaround. The test case matching the chat.facebook.com situation was expected to fail to connect, but the workaround made connecting succeed, breaking the test suite. I'm a bad person. So. I repurposed that test case to be one which is supposed to succeed, and made a clone for a slightly different situation which should still fail to connect. tests/wocky-connector-test.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) commit 96b18769a65b9c46d02137d496091f9f0e74e23f Author: Will Thompson Date: Mon Sep 6 17:33:14 2010 +0100 Remove redundant error-checking from connector test. g_assert_error() gives us all the same information the previous fprintf() calls did, and performs all the same checks. tests/wocky-connector-test.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) commit db37ac7a706d8fcdb45374ba9cbc22e02e9a65b0 Author: Will Thompson Date: Mon Sep 6 17:31:57 2010 +0100 Trick the coding style checker wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 0f04327f892ecd3fcb1cfb411cd8c0eefc4aaf25 Author: Will Thompson Date: Sat Aug 28 18:03:11 2010 +0100 Work around chat.facebook.com's broken SRV record. _xmpp-client._tcp.chat.facebook.com returns a CNAME record, not a SRV record. (But only on some connections! Apparently some people just get nothing back, or something.) Anyway, if you get unlucky, this mean Wocky just gave up and threw an error. Instead, if a domain has an SRV record and we fail to connect to it, we now fall back to connecting to the domain directly; if the latter fails too, we report the original error. If a domain has no SRV record, we fall back fully, and the behaviour is unchanged. Fixes: Reviewed-by: Simon McVittie wocky/wocky-connector.c | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) commit 9a3f3bc862a4ab368b231e96633326f4cafe4c6e Author: Vivek Dasmohapatra Date: Thu Sep 2 19:50:25 2010 +0100 Not having a CRL for a cert that advertises one is not necessarily an error Only stop if the user has requested strict checking. All it means is we haven't downloaded the CRL and installed it on our system somewhere. wocky/wocky-openssl.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) commit 34d4cea28542b11507c096e3d56120ee0972b62b Author: Cosimo Cecchi Date: Mon Aug 30 11:36:35 2010 +0200 configure: add configure output configure.ac | 15 +++++++++++++++ 1 file changed, 15 insertions(+) commit 75219825d61edec6e2b1ad5efe29d8fbf0540d6e Author: Cosimo Cecchi Date: Mon Aug 30 11:36:07 2010 +0200 configure: always set the right value to $enable_coverage configure.ac | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) commit 80a14a93939cf9125a91f4698bdc91a61ac67e19 Author: Cosimo Cecchi Date: Mon Aug 30 11:35:33 2010 +0200 configure: always set the right value to $with_tls configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit f049ff52818a36d1f69a79d045c6ab34b12b5807 Author: Cosimo Cecchi Date: Mon Aug 30 11:33:48 2010 +0200 configure: cleanup debug checks configure.ac | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) commit d1445f724ddb0ce70ce3a73c9a7fe307f3cfc8e2 Author: Will Thompson Date: Tue Aug 24 22:42:08 2010 +0100 Pubsub: unleak calls to g_simple_async_result_get_source_object() I tracked down a bug in Gabble to not unreffing the result of g_simple_async_result_get_source_object() and thought I'd check Wocky. I'm proud to report that I am responsible for all instances of this error in Wocky. I'm even prouder to report that I found it once before, added a comment explaining it, and then promptly forgot about it IN THE SAME FILE. Dunce hat for me. Reviewed-by: Simon McVittie wocky/wocky-pubsub-node.c | 3 +++ wocky/wocky-pubsub-service.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) commit cfe1bd86d1143631218e97396122c7f4b4d8cf85 Author: Adam Conrad Date: Thu Aug 19 18:52:25 2010 +0100 Update wocky-uninstalled.pc.in to match the previous out-of-tree build fix wocky/wocky-uninstalled.pc.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 12f2eff683846e3a72ad04eb9921b1c1a85e0c44 Author: Adam Conrad Date: Thu Aug 19 17:02:18 2010 +0100 Fix out-of-tree builds for examples and tests with an explicit include to wocky's generated headers examples/Makefile.am | 2 ++ tests/Makefile.am | 1 + 2 files changed, 3 insertions(+) commit 46b00685f4725b5a297b4364b72edfa255245d3e Author: Sjoerd Simons Date: Tue Aug 17 19:10:37 2010 +0100 Don't use a va_list twice wocky/wocky-tls-connector.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 38298718b84682941e0b98d68884a561511ca08f Author: Sjoerd Simons Date: Wed Aug 11 12:35:05 2010 +0100 Improve debugging output slightly tests/wocky-tls-test.c | 2 +- wocky/wocky-tls.c | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) commit eacb3e4f7baa6e361fbd88373212cb5ec4b0c7d2 Author: Sjoerd Simons Date: Wed Aug 11 12:29:50 2010 +0100 Use NORMAL instead of SECURE as the priority string NORMAL priority implies all secure algorithms, the only thing SECURE adds in gnutls 2.8 is that it orders 256 ciphers before 128 ones. In 2.10 SECURE also implies using only SHA512 bit signatures, which breaks our test-suite (as our certificate aren't 512 bits :( ). For compatibility reasons switch to NORMAL as the priority string, there is no reason to try to be more secure then what is considered normal by the gnutls people. wocky/wocky-tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 357a928cf8c1f6a20077225c30d21fdfaf66e500 Author: Cosimo Cecchi Date: Thu Jul 22 18:29:56 2010 +0200 Set the cert type to X509 when using OpenSSL wocky/wocky-openssl.c | 3 +++ 1 file changed, 3 insertions(+) commit fb31331fa0061df833dd6913c27828b72f729d3d Author: Cosimo Cecchi Date: Wed Jul 21 17:32:33 2010 +0200 Don't use the removed property in the test. tests/wocky-connector-test.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) commit ea901a00b11989a59222e870e4bd59636f5170c5 Author: Cosimo Cecchi Date: Wed Jul 21 17:32:11 2010 +0200 Remove an unused property. wocky/wocky-connector.c | 19 ------------------- 1 file changed, 19 deletions(-) commit 42a1e4f227ac6c2415c28403243000e33b7f638d Author: Cosimo Cecchi Date: Wed Jul 21 17:29:43 2010 +0200 Don't change error types for some errors. We use them e.g. in the tests to verify critical conditions. wocky/wocky-tls-connector.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) commit 59d826492c2c1fabdf5edb5c7d5151e1f94e5d38 Author: Cosimo Cecchi Date: Wed Jul 21 17:25:13 2010 +0200 Don't verify the peername when we're lenient. Fixes a regression from the split of the TLS connector. wocky/wocky-tls-handler.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) commit dbfd01acf41c35a5268cfa54d01bd98b0069db02 Author: Cosimo Cecchi Date: Fri Jul 16 12:21:55 2010 +0200 Update tests to the new API. examples/connect.c | 2 +- examples/register.c | 2 +- examples/unregister.c | 2 +- tests/wocky-connector-test.c | 12 +++++++++--- 4 files changed, 12 insertions(+), 6 deletions(-) commit 119ae9ea12998c0ee35a80fdb97afed7a172c5bd Author: Cosimo Cecchi Date: Fri Jul 16 12:20:48 2010 +0200 Add a way to get certificates from the session. wocky/wocky-openssl.c | 43 +++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-tls.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- wocky/wocky-tls.h | 15 ++++++++++++--- 3 files changed, 99 insertions(+), 4 deletions(-) commit 5195ba48b5c59a7147c7bfa177df8c4a55af569d Author: Cosimo Cecchi Date: Fri Jul 16 12:19:33 2010 +0200 Use WockyTLS[Handler, Module] in the connector wocky/wocky-connector.c | 418 +++++++++++------------------------------------- wocky/wocky-connector.h | 11 +- 2 files changed, 97 insertions(+), 332 deletions(-) commit 1af3dbb353f609b51c4084a84d485252d351fe7f Author: Cosimo Cecchi Date: Fri Jul 16 12:11:55 2010 +0200 Add WockyTLSConnector. wocky/Makefile.am | 2 + wocky/wocky-tls-connector.c | 444 ++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-tls-connector.h | 78 ++++++++ 3 files changed, 524 insertions(+) commit ca1eb15d3252817f61d42443f5ff1ff021dbcd1f Author: Cosimo Cecchi Date: Fri Jul 16 12:11:29 2010 +0200 Add WockyTLSHandler. wocky/Makefile.am | 2 + wocky/wocky-tls-handler.c | 346 ++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-tls-handler.h | 95 +++++++++++++ 3 files changed, 443 insertions(+) commit f43255812862592c2d46bb89b274e03a521ba9d7 Author: Cosimo Cecchi Date: Fri Jul 16 17:46:07 2010 +0200 Add utility to print debug from varargs. wocky/wocky-debug.c | 18 ++++++++++++------ wocky/wocky-debug.h | 4 ++++ 2 files changed, 16 insertions(+), 6 deletions(-) commit bf208dbc50a9660465387d39ed9768ee30ebca71 Merge: 294e7a7 93c156d Author: Will Thompson Date: Fri Jul 16 16:27:43 2010 +0100 Merge branch 'coverity' Reviewed-by: Simon McVittie commit 93c156d5d95dd424cd67ca697d6750c7a511035f Author: Will Thompson Date: Fri Jul 16 16:00:35 2010 +0100 Don't leak if start_auth() fails. wocky/wocky-jabber-auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 0384177b10a9bf5046da4e7bdec8eb1a1fed1e23 Author: Will Thompson Date: Fri Jul 16 15:58:20 2010 +0100 Fix a NULL check in digest_md5_make_initial_response wocky/wocky-sasl-digest-md5.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit d6c65173e096dc9fe3d3d03bc1be39f6a5439536 Author: Will Thompson Date: Fri Jul 16 15:55:46 2010 +0100 Simplify building resource binding stanza wocky/wocky-connector.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) commit 7296028c4c562e76f91e637daecda96bec5ef73c Author: Will Thompson Date: Fri Jul 16 15:38:39 2010 +0100 Remove unused Node variable. wocky/wocky-xmpp-error.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) commit 294e7a70f2ed28fe712983a5b2a9ad6a327f133b Author: Cosimo Cecchi Date: Fri Jul 2 12:16:42 2010 +0200 Correct a typo in gtk-doc header. wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 8a362a2b4406542b7f7ec2c68379fa8bc7f0c1a7 Author: Sjoerd Simons Date: Fri Jun 25 17:19:22 2010 +0100 Make the server salt a proper base64 string tests/wocky-scram-sha1-test.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) commit c4799c2ca67ba57229d61d426b99d3a611da44cd Author: Sjoerd Simons Date: Fri Jun 25 17:19:06 2010 +0100 Properly initialze base64 state and save wocky/wocky-sasl-scram.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 8f74264e32fe3f0df01fbb9e34e47a4223e9d279 Author: Sjoerd Simons Date: Fri Jun 25 15:19:12 2010 +0100 Add some static tests for scram-sha1 tests/Makefile.am | 9 ++- tests/wocky-scram-sha1-test.c | 131 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+), 1 deletion(-) commit 34516056bc94690be77c5106af3b0c54d9dfcc52 Author: Sjoerd Simons Date: Fri Jun 25 15:15:24 2010 +0100 Log the difference between actual and expected verification result wocky/wocky-sasl-scram.c | 5 +++++ 1 file changed, 5 insertions(+) commit 67bf3f27316f53a1c4e28db563a3c7af0520a320 Author: Sjoerd Simons Date: Thu Jun 24 12:49:26 2010 +0100 Test resetting the reader at odd times tests/wocky-xmpp-reader-test.c | 44 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) commit b85abc7144808a77f7d20015514e36ff7c1c1ab8 Author: Sjoerd Simons Date: Thu Jun 24 12:48:52 2010 +0100 Completely clear the parser state when resetting wocky/wocky-xmpp-reader.c | 85 ++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 45 deletions(-) commit 8cda83781b95f7f63a8062e76f153ed012e95cb3 Author: Simon McVittie Date: Wed Jun 23 13:52:16 2010 +0100 Build enum types for all error domains Reviewed-by: Sjoerd Simons wocky/Makefile.am | 6 ++++++ 1 file changed, 6 insertions(+) commit e41093fb12ccc84078507aaf84d215ddb2cb163f Author: Lars Noschinski Date: Tue Jun 22 19:06:05 2010 +0100 Remove GNUTLS_VERIFY_DO_NOT_ALLOW_SAME from VERIFY_NORMAL mode wocky/wocky-tls.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) commit 87ceeac46a1db5e2e3f4a4a04e3fb9a52ffca4ea Merge: 59668c5 cd298b2 Author: Simon McVittie Date: Tue Jun 22 18:27:20 2010 +0100 Merge branch 'spoofing' Reviewed-by: Sjoerd Simons commit cd298b2941d137c1e921d8ee257ffbeb3a7e6c21 Author: Simon McVittie Date: Tue Jun 22 18:24:00 2010 +0100 Add simple tests for wocky_porter_get_full_jid and friends tests/wocky-porter-test.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) commit d2aa806d75caff61a061b727b25865b8de5fca7b Author: Simon McVittie Date: Tue Jun 22 16:08:59 2010 +0100 Test what happens when the server replies with a different version of our bare JID tests/wocky-porter-test.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) commit f255b7efe02fe2110397baeb72cf44e9817d9967 Author: Simon McVittie Date: Tue Jun 22 15:38:28 2010 +0100 fd.o #28647: adjust spoofing detection to be aware of our own JIDs wocky/wocky-porter.c | 82 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 20 deletions(-) commit b4c4da28daabc2b443f53820787222b2d28d8fa3 Author: Simon McVittie Date: Tue Jun 22 15:37:51 2010 +0100 fd.o #26961: WockyPorter: have a full JID property, and derive the bare JID and resource tests/wocky-porter-test.c | 2 +- wocky/wocky-porter.c | 123 +++++++++++++++++++++++++++++++++++++++++++++- wocky/wocky-porter.h | 7 ++- wocky/wocky-session.c | 2 +- 4 files changed, 130 insertions(+), 4 deletions(-) commit 9f8ea758535bcb67cdcdb4b10f4c39b99c817e0f Author: Simon McVittie Date: Tue Jun 22 18:19:45 2010 +0100 WockySession: have a full JID construct-time property tests/wocky-porter-test.c | 7 +++++-- tests/wocky-pubsub-node-test.c | 4 ++-- tests/wocky-pubsub-service-test.c | 2 +- tests/wocky-roster-test.c | 2 +- tests/wocky-session-test.c | 6 +++--- tests/wocky-test-helper.c | 25 ++++++++++++++++++++----- tests/wocky-test-helper.h | 1 + wocky/wocky-session.c | 28 ++++++++++++++++++++++++---- wocky/wocky-session.h | 3 ++- 9 files changed, 59 insertions(+), 19 deletions(-) commit b72e4774c2bc0adbff7167695d70151bccc3955a Author: Simon McVittie Date: Tue Jun 22 15:34:02 2010 +0100 Test wocky_compose_jid tests/Makefile.am | 6 +++++- tests/wocky-utils-test.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) commit 4dc7976016d8fbd638ac2a16724fc541e3c4b13c Author: Simon McVittie Date: Tue Jun 22 15:33:19 2010 +0100 Factor out the end of wocky_normalise_jid into wocky_compose_jid wocky/wocky-utils.c | 56 +++++++++++++++++++++++++++++++++++------------------ wocky/wocky-utils.h | 3 +++ 2 files changed, 40 insertions(+), 19 deletions(-) commit 0e9d5cd64967535cc060c2a8848685293bd6ce69 Author: Simon McVittie Date: Tue Jun 22 15:32:48 2010 +0100 .gitignore: ignore all test binaries by naming convention .gitignore | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) commit 59668c53aac6b181d9708d2f7ec7cbeb6229f214 Author: Will Thompson Date: Tue Jun 15 23:13:12 2010 +0100 Use a better workaround for GTalk server SSL bugs The Google Talk server gets upset if you use TLSv1_client_method (). You can either use SSLv23, or set the NO_TICKET option. Allegedly, the former may stop SSL compression working, which is bad, and allows falling back to SSLv2, which is also bad. While we're here, let's throw in the standard set of bug workaround options. Reviewed-by: Vivek Dasmohapatra wocky/wocky-openssl.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) commit 0207bfd23fcb1ce3e118aeba7cc03e57d1a13993 Author: Will Thompson Date: Wed Jun 16 12:42:50 2010 +0100 Fix test coding style checks in out-of-tree builds Reviewed-by: Simon McVittie tests/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 32c5022a02e12c102a3a0bf4a0f2d72015189fdc Author: Simon McVittie Date: Tue Jun 15 14:55:19 2010 +0100 fd.o #27488: wocky_connector_connect_finish, _register_finish: put GError last This is more conventional, and (eventually) nicer for bindings. Reviewed-by: Sjoerd Simons examples/connect.c | 2 +- examples/register.c | 2 +- tests/wocky-connector-test.c | 8 ++++---- wocky/wocky-connector.c | 12 ++++++------ wocky/wocky-connector.h | 8 ++++---- 5 files changed, 16 insertions(+), 16 deletions(-) commit 42f58783611f23d4210a09d1039b31170ec75c4d Author: Simon McVittie Date: Tue Jun 15 14:49:47 2010 +0100 .gitignore: add gtkdoc's sections.txt, which is autogenerated in this project .gitignore | 1 + 1 file changed, 1 insertion(+) commit a57811f15b08d3b23d059de42b5fe0c39c11833c Author: Simon McVittie Date: Tue Jun 15 14:49:23 2010 +0100 .gitignore: add another test .gitignore | 1 + 1 file changed, 1 insertion(+) commit 51affd5099e4178cbd07dc379c3970a9986da74a Author: Will Thompson Date: Mon Jun 14 15:03:35 2010 +0100 Check wocky_porter_send_iq_finish()'s return is used wocky/wocky-porter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 1394d8694c3c064587586aa84ce8631c3473d91a Author: Sjoerd Simons Date: Sun Jun 13 13:48:39 2010 +0100 Add support for SCRAM-SHA1 wocky/Makefile.am | 2 + wocky/wocky-auth-registry.c | 12 +- wocky/wocky-sasl-scram.c | 590 ++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-sasl-scram.h | 72 ++++++ 4 files changed, 675 insertions(+), 1 deletion(-) commit e1eec240c432419d8b3d39c904bfe6b1a93b7508 Author: Sjoerd Simons Date: Sun Jun 13 13:41:58 2010 +0100 Test our HMAC-SHA1 implementation .gitignore | 1 + tests/Makefile.am | 10 ++- tests/wocky-sasl-utils-test.c | 163 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+), 2 deletions(-) commit 4fa923f35c99a3b5e404c22cab9ee36e1fbdd416 Author: Sjoerd Simons Date: Sun Jun 13 13:37:33 2010 +0100 Add utilities for nonce generation and HMAC-SHA1 wocky/Makefile.am | 2 + wocky/wocky-sasl-digest-md5.c | 19 +------- wocky/wocky-sasl-utils.c | 103 ++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-sasl-utils.h | 36 +++++++++++++++ 4 files changed, 143 insertions(+), 17 deletions(-) commit 5a1976e7de0701f4fd71844833a45b7b01e57361 Author: Sjoerd Simons Date: Mon Jun 14 12:22:27 2010 +0100 Use wildcard for coding style checks to catch everything tests/Makefile.am | 23 +---------------------- tests/wocky-dummy-xmpp-server.c | 6 +++--- 2 files changed, 4 insertions(+), 25 deletions(-) commit 32feaf82621dbfeeedf3e17b81b7140a3f02b8ae Author: Sjoerd Simons Date: Sun Jun 13 12:50:23 2010 +0100 Turn on coding style checking configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 49a9539dc42da2ceb3266bee9e2a13bba51a6ae3 Merge: a676233 60800a4 Author: Will Thompson Date: Mon Jun 14 12:22:55 2010 +0100 Merge branch 'domain-validation' Reviewed-by: Sjoerd Simons commit 60800a465f33693ed9aeb42630974d60e6465bf8 Author: Will Thompson Date: Fri Jun 11 16:49:08 2010 +0100 Squash warnings about uninitialized GError *s wocky/wocky-jabber-auth.c | 6 ++---- wocky/wocky-sasl-auth.c | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) commit cba01d1776b8e2193ddd5dc0d3f741807bda61d8 Author: Will Thompson Date: Fri Jun 11 16:39:00 2010 +0100 Accept valid Unicode domains Previously we did not accept any non-ASCII domains, which meant we dropped perfectly valid messages from perfectly valid contacts. :o This patch accepts any non-ASCII characters in domains. This is still not right — for instance, the freshly-added test case demonstrates that spaces in domains are properly rejected, but non-breaking spaces are improperly accepted — but it's better than no validation at all (which was my previous attempt at fixing this) and avoids us dropping messages. tests/Makefile.am | 12 +++++++-- tests/wocky-jid-validation-test.c | 56 +++++++++++++++++++++++++++++++++++++++ wocky/wocky-utils.c | 17 ++++++++---- 3 files changed, 78 insertions(+), 7 deletions(-) commit 4cce83a850b1f1f950de9c3d8aa00d11875aacab Author: Will Thompson Date: Fri Jun 11 16:38:44 2010 +0100 Add missing include to test helper code. tests/wocky-test-helper.c | 2 ++ 1 file changed, 2 insertions(+) commit a676233d662dfd993cdb4f5183fd61cba990b9e3 Author: Will Thompson Date: Fri Jun 11 15:45:34 2010 +0100 Revert "Don't forbid valid non-ASCII domains." This reverts commit cc01b390f4c64c253d911da688e9c71cd7e026f1, which broke tests that check that invalid domains are rejected. I'll add slightly more than no validation. wocky/wocky-utils.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) commit cc01b390f4c64c253d911da688e9c71cd7e026f1 Author: Will Thompson Date: Fri Jun 11 15:17:46 2010 +0100 Don't forbid valid non-ASCII domains. Previously perfectly valid IDNs in their Unicode form (rather than their "xn--"-prefixed ASCII form) were rejected. Not only did this mean that users could not sign in with JIDs on IDN domains, it also meant that we rejected incoming messages from IDN-y JIDs. This patch corrects that, at the cost of performing no validation beyond checking that the string is non-empty. wocky/wocky-utils.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) commit 4c31c7003d554c18740e5a4c1aaf364c41b2f50b Merge: 642d874 d82d98f Author: Eitan Isaacson Date: Tue Jun 8 08:18:22 2010 -0700 Merge branch 'auth-is-secure' commit d82d98f0234a753a226ec18b0c7b065a61f8d3e0 Author: Eitan Isaacson Date: Tue May 25 12:11:12 2010 -0700 Properly use is_secure argument in wocky_auth_registry_start_auth_async. examples/connect.c | 4 ++-- tests/wocky-test-sasl-auth.c | 2 +- wocky/wocky-connector.c | 7 ++++--- wocky/wocky-jabber-auth.c | 6 +++++- wocky/wocky-jabber-auth.h | 1 + wocky/wocky-sasl-auth.c | 8 +++++--- wocky/wocky-sasl-auth.h | 1 + 7 files changed, 19 insertions(+), 10 deletions(-) commit 642d874431617fffa170c48cfdb8cabe5510041f Merge: 8158b75 1c9443b Author: Will Thompson Date: Thu Jun 3 19:33:02 2010 +0100 Merge remote branch 'maiku/install-headers' commit 8158b754bda64f123d804ba6700846b90f069ff3 Merge: ff03a5e 221d287 Author: Will Thompson Date: Thu Jun 3 19:00:48 2010 +0100 Merge branch 'muc' Reviewed-by: Sjoerd Simons commit ff03a5e7254c8586cf72016634a6b3a6c47eb492 Merge: 9cdcd09 1c16879 Author: Will Thompson Date: Thu Jun 3 19:00:36 2010 +0100 Merge branch 'coverity' Reviewed-by: Sjoerd Simons commit 1c9443b6c8d78d800f2e470d1b0431519eb29951 Author: Mike Ruprecht Date: Sun May 30 12:00:15 2010 -0500 Add wocky-tls.h to the list of handwritten headers. The wocky-tls.h file is used for both GnuTLS and OpenSSL options. Therefore there's no need to keep it separate from the main list of headers. Also, it wasn't being installed with the other headers. This patch moves it into the list of handwritten headers. wocky/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit aad3e48e1333bfe8659b2eb70c89081233856428 Author: Will Thompson Date: Mon Mar 22 15:37:29 2010 +0000 Add a configure switch to install headers Previously, Gabble hard-coded a list of Wocky headers to install if it was built with --enable-plugin-api. This is fragile in the face of the list of headers changing. With this patch, passing --with-installed-headers=/path/to/headers to Wocky's configure will cause `make install` to put headers there. I had to split BUILT_SOURCES and HANDWRITTEN_SOURCES into sources and headers, and lowercase them because FOO_HEADERS is magic in Automake. I took the liberty of sorting the lists while I was at it. configure.ac | 10 ++++ wocky/Makefile.am | 169 +++++++++++++++++++++++++++++------------------------- 2 files changed, 101 insertions(+), 78 deletions(-) commit 9cdcd094234ebfe40429d827c2ec2b6bb5d917a6 Author: Guillaume Desmottes Date: Mon May 24 15:50:48 2010 +0200 pep-service: discard suspicious event messsages (fdo #28232) For some reason recent ejabberd are sending 'error' messages when we publish to a PEP node. That's probably an ejabberd bug (EJAB-1239) but Wocky should ignore those rather than parsing them as actual PEP updates. wocky/wocky-pep-service.c | 11 +++++++++++ 1 file changed, 11 insertions(+) commit 51ee0b1e860c99ae8dbaa58909d247ab54d834c1 Author: Sjoerd Simons Date: Wed May 26 17:17:47 2010 +0100 Remove certificate re-creation rules, they tend to break The Makefile had some voodoo to re-create the various certificates used for testing if needed.. Unfortunately they tend to break. Also these rules will only be needed in 2037. If we're still using SSL and Wocky at that point, then figuring out how to update the certificates to be valid a little bit longer shouldn't be that much work :) tests/Makefile.am | 106 +----------------------------------------------------- 1 file changed, 1 insertion(+), 105 deletions(-) commit a9a52910d54c5d5f84bf9707eba7ab58192c2a07 Author: Eitan Isaacson Date: Fri May 21 15:10:10 2010 -0700 Unref reply stanza. wocky/wocky-sasl-auth.c | 1 + 1 file changed, 1 insertion(+) commit bfa6ed32139edb1b783f180219fbe933f12db625 Author: Eitan Isaacson Date: Fri May 21 15:09:34 2010 -0700 Unref auth registry on dispose. wocky/wocky-connector.c | 1 + 1 file changed, 1 insertion(+) commit 64b4f204238fbaf6247e0094810d92a3417abc67 Author: Eitan Isaacson Date: Fri May 21 11:35:17 2010 -0700 Be more linient towards 0 length and NULL GStrings in base64 encode/decode. wocky/wocky-sasl-auth.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) commit a217fd071742abf8ba3cd526e012dcd2bda6df4d Author: Mike Ruprecht Date: Mon May 24 05:16:47 2010 -0500 Make sure all sources are in tests/Makefile.am's check_c_sources. tests/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 8f1d78dea085447a237160c4a528a48cc699f31c Merge: 57e7d3a 89f115e Author: Eitan Isaacson Date: Wed May 19 10:39:23 2010 -0700 Merge branch 'more-auth-work' commit 89f115e5cfa8a3423bd085af3f611ac476c6705f Author: Eitan Isaacson Date: Wed May 19 10:33:24 2010 -0700 Changed wocky_implement_finish_void to work with g_simple_async_report_*. wocky/wocky-utils.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) commit d4482bd89440022d7fc25b485e50f3b01fa61066 Author: Eitan Isaacson Date: Tue May 18 10:29:57 2010 -0700 Added new API to gtk-doc index. docs/reference/wocky-docs.sgml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 6481be551052eec6661a40ef89f2bd917e699a23 Author: Eitan Isaacson Date: Mon May 17 12:06:22 2010 -0700 Added documentation to virtual functions. wocky/wocky-auth-registry.h | 52 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) commit 29e43824ab7b104ab8ad30e1a78505c30e09b47e Author: Eitan Isaacson Date: Mon May 17 11:47:10 2010 -0700 Use wocky_implement_finish_void macro in wocky_sasl_auth_authenticate_finish wocky/wocky-sasl-auth.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) commit a5b28c34ab43fb8d56ef808a62874a73d1f01e04 Author: Eitan Isaacson Date: Mon May 17 11:45:17 2010 -0700 Call wocky_auth_registry_failure in auth_fail functions and not in _finish. wocky/wocky-jabber-auth.c | 23 +++++++++-------------- wocky/wocky-sasl-auth.c | 16 +++++++++------- 2 files changed, 18 insertions(+), 21 deletions(-) commit d7134f06472b4db2b7857e4d5409866ef2615698 Author: Eitan Isaacson Date: Mon May 17 10:25:59 2010 -0700 made _finish functions virtual wocky/wocky-auth-registry.c | 55 +++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-auth-registry.h | 23 +++++++++++++++++++ 2 files changed, 78 insertions(+) commit 556fb4cce9618ae6ce21792ee01f73d267714099 Author: Eitan Isaacson Date: Mon May 17 10:07:06 2010 -0700 Allocate GAsyncResult in implementation. In essence, they are now public. wocky/wocky-auth-registry.c | 69 +++++++++++++++++++++++---------------------- wocky/wocky-auth-registry.h | 21 ++++++++------ 2 files changed, 48 insertions(+), 42 deletions(-) commit fa0ab5344f5469c64ce498f2e79de6bedff45322 Author: Eitan Isaacson Date: Thu May 13 11:46:53 2010 -0700 Added virtual public method wocky_auth_registry_failure wocky/wocky-auth-registry.c | 11 +++++++++++ wocky/wocky-auth-registry.h | 7 +++++++ wocky/wocky-jabber-auth.c | 12 +++++++++++- wocky/wocky-sasl-auth.c | 5 ++++- 4 files changed, 33 insertions(+), 2 deletions(-) commit 14bf70b7992cf868ce6a1a86f59ad84fb9b86ecd Author: Eitan Isaacson Date: Thu May 13 11:26:47 2010 -0700 allow NULL passwords wocky/wocky-connector.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) commit 0079e46ab973602c3030173327bb8f5c9d6e4977 Author: Eitan Isaacson Date: Thu May 13 10:17:37 2010 -0700 Moved g_string copy/free functions to wocky-utils wocky/wocky-auth-registry.c | 25 ++++--------------------- wocky/wocky-utils.c | 16 ++++++++++++++++ wocky/wocky-utils.h | 4 ++++ 3 files changed, 24 insertions(+), 21 deletions(-) commit b73f84bda27bcf9aaf0a6db581ee52f82bacb39c Author: Eitan Isaacson Date: Tue May 11 13:06:28 2010 -0700 Made new struct for holding initial auth data (mechanism and initial response). This further seals the base class and allows subclasses to override regardless of what obj->handler is pointing at. wocky/wocky-auth-registry.c | 74 ++++++++++++++++++++++++++++++--------------- wocky/wocky-auth-registry.h | 20 ++++++++++-- wocky/wocky-jabber-auth.c | 16 +++++----- wocky/wocky-sasl-auth.c | 14 ++++----- 4 files changed, 79 insertions(+), 45 deletions(-) commit a581c940cef08fb121fa142f5a689a6264c3fdc4 Author: Eitan Isaacson Date: Fri May 7 13:23:08 2010 -0700 Added private virtual functions to WockyAuthRegistry. wocky/wocky-auth-registry.c | 107 ++++++++++++++++++++++++++++++++++---------- wocky/wocky-auth-registry.h | 21 +++++++++ 2 files changed, 105 insertions(+), 23 deletions(-) commit 57e7d3a7a58bad9d8b3d5edbb8c8506a32a6fddd Author: Senko Rasic Date: Thu May 13 15:09:01 2010 +0200 adding wocky-ping-test .gitignore | 1 + tests/Makefile.am | 9 +++- tests/wocky-ping-test.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+), 1 deletion(-) commit 208826117cc8cc6fdda7509bd71038983b939750 Author: Senko Rasic Date: Thu May 13 15:07:44 2010 +0200 wocky-test-helper: support custom timeouts tests/wocky-test-helper.c | 8 +++++++- tests/wocky-test-helper.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) commit 7cbd4644294b974750c85da06f2c9fe0633f5e2c Author: Senko Rasic Date: Thu May 13 15:06:32 2010 +0200 wocky-test-helper: cancel timeouts after each test tests/wocky-test-helper.c | 4 ++-- tests/wocky-test-helper.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) commit 5aff834affadaa473b5c82082fa0ca8b44c83893 Author: Senko Rasic Date: Thu May 13 15:03:40 2010 +0200 wocky_test_input_stream_read: fixed 1-byte reads in COMBINE_SLICE mode tests/wocky-test-stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 372cfeecafd26191021768003c8341dd38dbb44d Author: Senko Rasic Date: Thu May 13 15:03:19 2010 +0200 adding WockyPing wocky/Makefile.am | 4 +- wocky/wocky-ping.c | 282 +++++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-ping.h | 69 +++++++++++++ 3 files changed, 354 insertions(+), 1 deletion(-) commit 0ee03b1e59ad2a1a2908409e94d692cafefc204c Author: Senko Rasic Date: Thu May 13 14:54:02 2010 +0200 adding "ping" debug flag wocky/wocky-debug.c | 3 ++- wocky/wocky-debug.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) commit 0e8c567439807f80cc90d376ceb5b8982163152a Author: Senko Rasic Date: Thu May 13 14:53:29 2010 +0200 adding "urn:xmpp:ping" to namespaces wocky/wocky-namespaces.h | 3 +++ 1 file changed, 3 insertions(+) commit e6bdcc7b9dc234bb64dffcd17641209831925116 Author: Senko Rasic Date: Thu May 13 14:52:30 2010 +0200 adding WockyPorter::sending signal wocky/wocky-porter.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) commit dcefd5d4c8cf1948a602f83fe29176abce74801e Merge: 543bb86 3fb3b76 Author: Eitan Isaacson Date: Fri May 7 13:54:03 2010 -0700 Merge branch 'jabber-auth-refactor' commit 3fb3b7626930d5ca94a54bb8394ee6d2d819a761 Author: Eitan Isaacson Date: Fri May 7 10:39:34 2010 -0700 Use wocky_xmpp_stream_error_from_node for parsing stream errors. wocky/wocky-jabber-auth.c | 27 ++++++++------------------- wocky/wocky-sasl-auth.c | 27 ++++++++------------------- 2 files changed, 16 insertions(+), 38 deletions(-) commit e33a9720af53312836d3e1be403a6402d6b7d203 Author: Eitan Isaacson Date: Wed May 5 14:32:21 2010 -0700 Make mechanism names preprocessor macros. wocky/wocky-auth-registry.c | 8 ++++---- wocky/wocky-auth-registry.h | 5 +++++ wocky/wocky-jabber-auth-digest.c | 2 +- wocky/wocky-jabber-auth-password.c | 2 +- wocky/wocky-jabber-auth.c | 6 ++---- wocky/wocky-sasl-digest-md5.c | 2 +- wocky/wocky-sasl-plain.c | 2 +- 7 files changed, 15 insertions(+), 12 deletions(-) commit e9cacbb7ce557fbcfc0d523eaaa50237ebfa3276 Author: Eitan Isaacson Date: Wed May 5 14:13:14 2010 -0700 Cleaned up stream_error in both wocky-sasl-auth.c wocky-jabber-auth.c. wocky/wocky-jabber-auth.c | 36 ++++++++++++++---------------------- wocky/wocky-sasl-auth.c | 36 ++++++++++++++---------------------- 2 files changed, 28 insertions(+), 44 deletions(-) commit 75d45bef817fc0236fb657604e526d6206473b54 Author: Eitan Isaacson Date: Wed May 5 13:36:07 2010 -0700 make WockyJabberAuthDigest a non-plain handler. wocky/wocky-jabber-auth-digest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 5928970c86a282de5350010068459801e4a8f002 Author: Eitan Isaacson Date: Tue May 4 22:11:44 2010 -0700 rename sasl debug flag to auth wocky/wocky-auth-registry.c | 2 +- wocky/wocky-debug.c | 2 +- wocky/wocky-debug.h | 2 +- wocky/wocky-jabber-auth-digest.c | 2 +- wocky/wocky-jabber-auth-password.c | 2 +- wocky/wocky-jabber-auth.c | 2 +- wocky/wocky-sasl-auth.c | 2 +- wocky/wocky-sasl-digest-md5.c | 2 +- wocky/wocky-sasl-plain.c | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) commit 78057813fccdd70f0a626687a406ae8e9898675a Author: Eitan Isaacson Date: Tue May 4 22:08:13 2010 -0700 rename DOMAIN_SASL to DOMAIN_AUTH tests/wocky-connector-test.c | 76 ++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 38 deletions(-) commit 7722fae294a23684c1e5559ce1d1cf038389d063 Author: Eitan Isaacson Date: Tue May 4 22:01:54 2010 -0700 Renamed WockySaslHandler to WockyAuthHandler tests/wocky-test-sasl-auth.c | 4 +- tests/wocky-test-sasl-handler.c | 14 ++--- wocky/Makefile.am | 4 +- wocky/wocky-auth-handler.c | 100 +++++++++++++++++++++++++++++++ wocky/wocky-auth-handler.h | 120 +++++++++++++++++++++++++++++++++++++ wocky/wocky-auth-registry.c | 30 +++++----- wocky/wocky-auth-registry.h | 6 +- wocky/wocky-jabber-auth-digest.c | 12 ++-- wocky/wocky-jabber-auth-digest.h | 2 +- wocky/wocky-jabber-auth-password.c | 12 ++-- wocky/wocky-jabber-auth-password.h | 2 +- wocky/wocky-jabber-auth.h | 4 +- wocky/wocky-sasl-auth.h | 4 +- wocky/wocky-sasl-digest-md5.c | 16 ++--- wocky/wocky-sasl-digest-md5.h | 2 +- wocky/wocky-sasl-handler.c | 100 ------------------------------- wocky/wocky-sasl-handler.h | 120 ------------------------------------- wocky/wocky-sasl-plain.c | 12 ++-- wocky/wocky-sasl-plain.h | 2 +- 19 files changed, 283 insertions(+), 283 deletions(-) commit 2b0b9262008ffdb6b0b1db44441cd4a27c17aca6 Author: Eitan Isaacson Date: Fri Apr 30 15:37:43 2010 -0700 Added WockyJabberAuth, WockyJabberAuthPassword and WockyJabberAuthDigest. tests/wocky-connector-test.c | 48 +-- tests/wocky-test-sasl-auth.c | 2 +- wocky/Makefile.am | 9 +- wocky/wocky-auth-registry.c | 22 +- wocky/wocky-auth-registry.h | 9 +- wocky/wocky-connector.c | 382 ++++----------------- wocky/wocky-connector.h | 5 - wocky/wocky-jabber-auth-digest.c | 171 ++++++++++ wocky/wocky-jabber-auth-digest.h | 51 +++ wocky/wocky-jabber-auth-password.c | 139 ++++++++ wocky/wocky-jabber-auth-password.h | 51 +++ wocky/wocky-jabber-auth.c | 672 +++++++++++++++++++++++++++++++++++++ wocky/wocky-jabber-auth.h | 88 +++++ wocky/wocky-sasl-auth.c | 4 +- 14 files changed, 1295 insertions(+), 358 deletions(-) commit 68af7efd6de961ab2512d4960c5c2a343ea12e8b Author: Eitan Isaacson Date: Wed May 5 13:31:05 2010 -0700 Don't g_assert on text node contents not being NULL. wocky/wocky-node.c | 1 - 1 file changed, 1 deletion(-) commit e66e40bdd6ee634b70d023af0575d493db46cf71 Author: Eitan Isaacson Date: Tue May 4 22:16:45 2010 -0700 unref auth_registry in WockySaslAuth dispose wocky/wocky-sasl-auth.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) commit 543bb86b6b7b130a27ed6e4153e47137c6fc43e6 Author: Will Thompson Date: Thu May 6 18:54:39 2010 +0100 Remove misleading full stop from xml debug message wocky/wocky-xmpp-writer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 438f0f35b8703390701b263d5d8668cf4348aa23 Author: Eitan Isaacson Date: Tue May 4 13:22:56 2010 -0700 Moved g_assert so it does a real sanity check. wocky/wocky-auth-registry.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 7d7bf0450c70c8d9d1fe78ee595bb2eab5e37d1d Merge: a844c4c 5450bf0 Author: Eitan Isaacson Date: Tue May 4 13:13:35 2010 -0700 Merge branch 'sasl-once-again' commit 5450bf0ac8524e95fadf62c998256f9303daa9eb Author: Eitan Isaacson Date: Mon May 3 12:11:58 2010 -0700 Removed wocky_auth_registry_failure_notify, will add when we implement. wocky/wocky-auth-registry.c | 5 ----- wocky/wocky-auth-registry.h | 3 --- 2 files changed, 8 deletions(-) commit cacf08c4de606512414550b32fa842bcc2c3604d Author: Eitan Isaacson Date: Mon May 3 12:08:03 2010 -0700 Use wocky_implement_finish_* macros in WockyAuthRegistry. Changed the flow of wocky_auth_registry_start_auth_finish to match the macros even though we cannot use any of them because we use two out params. wocky/wocky-auth-registry.c | 71 +++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 45 deletions(-) commit 27de8fd6dc7ea50919de1a71905cb2074a467e5d Author: Eitan Isaacson Date: Mon May 3 11:34:33 2010 -0700 Default WockyAuthRegistry upon construction. New WockyAuthRegistry arg in both wocky_connector_new() and wocky_sasl_auth_new(). If NULL is passed in either, the default WockyAuthRegisty is used. examples/connect.c | 8 ++------ examples/register.c | 2 +- examples/unregister.c | 2 +- tests/wocky-connector-test.c | 2 +- tests/wocky-test-sasl-auth.c | 6 +++--- wocky/wocky-connector.c | 17 +++++------------ wocky/wocky-connector.h | 3 ++- wocky/wocky-sasl-auth.c | 5 ++++- 8 files changed, 19 insertions(+), 26 deletions(-) commit f11a7a3774b1ce8204c421703210706b65ba984f Author: Eitan Isaacson Date: Mon May 3 10:56:42 2010 -0700 Initiaze GErrors to NULL. wocky/wocky-auth-registry.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit 64ace03b65515adb44117629ceffb4f1b123c712 Author: Eitan Isaacson Date: Thu Apr 29 16:27:06 2010 -0700 Added WockyAuthRegistry. WockyAuthRegistry selects the authentication mechanism based on it's available handlers, and arbitrates challenge/responses between the handler and the connector (via Wocky[Sasl|Jabber]Auth). Got rid of WOCKY_SASL_AUTH_ERROR* replaced with WOCKY_AUTH_ERROR examples/connect.c | 6 +- tests/wocky-connector-test.c | 36 ++-- tests/wocky-test-sasl-auth.c | 32 +-- tests/wocky-test-sasl-handler.c | 6 +- wocky/Makefile.am | 4 +- wocky/wocky-auth-registry.c | 374 +++++++++++++++++++++++++++++++++++ wocky/wocky-auth-registry.h | 122 ++++++++++++ wocky/wocky-connector.c | 39 +++- wocky/wocky-connector.h | 3 + wocky/wocky-sasl-auth.c | 427 ++++++++++++++++++++-------------------- wocky/wocky-sasl-auth.h | 31 +-- wocky/wocky-sasl-digest-md5.c | 71 +++---- wocky/wocky-sasl-handler.c | 12 +- wocky/wocky-sasl-handler.h | 12 +- wocky/wocky-sasl-plain.c | 17 +- 15 files changed, 847 insertions(+), 345 deletions(-) commit 221d2879fea6439429bd7d7384934eee49c9ca1b Author: Will Thompson Date: Tue May 4 13:11:35 2010 +0100 muc: rearrange handle_message I think this makes it easier to follow. wocky/wocky-muc.c | 45 ++++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 27 deletions(-) commit 9be6e6952c635788ff0cf5ac3ec0da8da05195dc Author: Will Thompson Date: Tue May 4 13:06:53 2010 +0100 muc: extract determining chat state wocky/wocky-muc.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) commit bc27c8c96c92b736fe649490cc4894b9685d5c4d Author: Will Thompson Date: Tue May 4 13:05:05 2010 +0100 muc: extract looking up message sender wocky/wocky-muc.c | 90 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 35 deletions(-) commit c4ff3d43f31db2328cb42f312e16192ed1e5e47a Author: Will Thompson Date: Tue May 4 12:56:11 2010 +0100 muc: don't drop backlog messages from former members If the message is from a full MUC JID, then we certainly do care about it, even if the sender isn't currently in the MUC, because it might be scrollback from someone no longer in the room. Fixes https://bugs.freedesktop.org/show_bug.cgi?id=27913 wocky/wocky-muc.c | 52 ++++++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 24 deletions(-) commit 47c13b5d97b470cb236c37e08641fcee94c22231 Author: Will Thompson Date: Tue May 4 12:30:39 2010 +0100 muc: refactor determining message type wocky/wocky-muc.c | 55 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 21 deletions(-) commit 87daf7313d6da0d6c0f61ed87b1be7d00a0e0f2e Author: Will Thompson Date: Tue May 4 12:24:40 2010 +0100 muc: refactor extracting timestamp from messages. wocky/wocky-muc.c | 61 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 25 deletions(-) commit ac48945876299a55a41976c4321ab38be8e0b7ec Author: Will Thompson Date: Tue May 4 01:18:01 2010 +0100 muc: Remove Google message-without-type kludge. So, looking at gabble's gabble_message_util_parse_incoming_message(), we see that offline messages from Google are assumed to have Telepathy type Normal, which corresponds to XMPP's type='chat'. So this kludge is wrong. In any case, Google's MUCs don't *have* scrollback! So let's just bin it. wocky/wocky-muc.c | 10 ---------- 1 file changed, 10 deletions(-) commit 6b6f09d97f91de66c11a4b6a7e28222e8dc911f6 Author: Will Thompson Date: Tue May 4 00:52:42 2010 +0100 muc: use GEnum to look up chat states wocky/wocky-muc.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) commit 2298c0b513a4a4f379ee42b65af16cb0bb275594 Author: Will Thompson Date: Tue May 4 00:48:38 2010 +0100 node: add helper to get the first child for a ns tests/wocky-xmpp-node-test.c | 35 +++++++++++++++++++++++++++++++++++ wocky/wocky-node.c | 31 ++++++++++++++++++++++++++++--- wocky/wocky-node.h | 2 ++ 3 files changed, 65 insertions(+), 3 deletions(-) commit 1c168790a9dbf9efcdb3272edcbaf0709af7dd2c Author: Will Thompson Date: Tue May 4 13:18:22 2010 +0100 muc: don't leak new_jid when we change our nick REPLACE_STR() does not take ownership of its second argument. Also, I expanded another use of REPLACE_STR because it seems stupid to diff the nicks twice in immediate succession. wocky/wocky-muc.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) commit d7a27bd3da61dcd8b612359dbaf2636dc412a816 Author: Will Thompson Date: Mon May 3 21:22:07 2010 +0100 muc: expunge 'gone' from the known chat states A client SHOULD ignore notifications received from other room occupants. — XEP-0045 §5.5 Use in Groupchat As and when Wocky handles chat states for anything other than MUC we can reinstate this and make MUC map Gone to None. wocky/wocky-muc.c | 1 - wocky/wocky-muc.h | 1 - 2 files changed, 2 deletions(-) commit 3065a6329f44e078243e12f2718b7f8cc978bc7f Author: Will Thompson Date: Mon May 3 20:59:50 2010 +0100 muc: don't fall through between properties in _set wocky/wocky-muc.c | 2 ++ 1 file changed, 2 insertions(+) commit 85a891fecb9cef18e1fd675543a9e9b5954772eb Author: Will Thompson Date: Tue May 4 13:44:03 2010 +0100 Document deliberate fall-throughs. Coverity picked these up as possible errors; they're not, but they should be marked as such. wocky/wocky-connector.c | 4 ++++ wocky/wocky-openssl.c | 6 ++++++ 2 files changed, 10 insertions(+) commit d61e85d691a93d326d0fb1f17c1b558e87c7aa91 Author: Will Thompson Date: Tue May 4 13:38:33 2010 +0100 openssl: die if we can't create BIOs As far as I can tell, failing to create these means OOM. So let's die properly, rather than logging a debug message and then crashing later in the function when we use them anyway. wocky/wocky-openssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 8994f5092dd11aa12cfb9b1a536546219a8e94f6 Author: Will Thompson Date: Tue May 4 13:35:40 2010 +0100 connector: assert that connect_to_service_finish() isn't broken. Coverity was upset because we dereferenced 'error' just before checking if it's NULL. I think it's right to be upset. But if g_socket_client_connect_to_service_finish() returned NULL, either it set 'error', or it's buggy, or we're buggy and called it inappropriately. So let's blow up if it's NULL in this case. wocky/wocky-connector.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) commit a9bc4ad499ae27ec354740f82a25386ec8614a01 Author: Will Thompson Date: Mon May 3 18:23:05 2010 +0100 connector: Clean up GSimpleAsyncResult usage • Don't use the op_res at all. If the operation failed, we always set an error. • Use _async functions as source tags, not _finish. • Remove weird spooky action at a distance to change the tag based on priv->reg_op. • Actually use a different source tag for _connect_async and _register_async. wocky/wocky-connector.c | 127 +++++++++++++++++++++++++----------------------- 1 file changed, 67 insertions(+), 60 deletions(-) commit 49eb9c93f363ab9a5f97445b977f7bdf758b48b3 Author: Will Thompson Date: Mon May 3 18:15:28 2010 +0100 Cry a little if CRYPTO_malloc_init() fails wocky/wocky-openssl.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) commit ccbddb5deb7b2eccf04c690c9266b4c0e4970e84 Author: Will Thompson Date: Mon May 3 18:10:42 2010 +0100 Check return value of SSL_CTX_set_default_verify_paths() wocky/wocky-openssl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) commit 98635423ec684d981a39f3dd852db8949099841b Author: Will Thompson Date: Mon May 3 18:01:45 2010 +0100 Sanity-check return of extract_stream_error wocky/wocky-porter.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) commit a844c4c65ffdc2f860fbecf263caee3efd53b943 Author: Sjoerd Simons Date: Thu Apr 29 12:40:02 2010 +0100 Plug some memory and refcounting leaks wocky/wocky-muc.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) commit 202699fdeabe15bc230a75ce211eff0762baa603 Author: Will Thompson Date: Wed Apr 28 20:38:54 2010 +0100 Revert "Add a configure switch to install headers" This reverts commit 9148378692967fbcc8b75ce8822a2ab58b3dee66, which didn't work because of broken Make dependencies that I can't figure out right now. configure.ac | 10 ---- wocky/Makefile.am | 142 +++++++++++++++++++++++++----------------------------- 2 files changed, 66 insertions(+), 86 deletions(-) commit 9148378692967fbcc8b75ce8822a2ab58b3dee66 Author: Will Thompson Date: Mon Mar 22 15:37:29 2010 +0000 Add a configure switch to install headers Previously, Gabble hard-coded a list of Wocky headers to install if it was built with --enable-plugin-api. This is fragile in the face of the list of headers changing. With this patch, passing --with-installed-headers=/path/to/headers to Wocky's configure will cause `make install` to put headers there. I had to split BUILT_SOURCES and HANDWRITTEN_SOURCES into sources and headers, and lowercase them because FOO_HEADERS is magic in Automake. I took the liberty of sorting the lists while I was at it. This patch originally didn't work, and was made to work by Mike Ruprecht , but his fixes languished waiting for me to review them for long enough that wocky/Makefile.am had changed so much that the patch needed rewriting. Sorry. :( configure.ac | 10 ++++ wocky/Makefile.am | 142 +++++++++++++++++++++++++++++------------------------- 2 files changed, 86 insertions(+), 66 deletions(-) commit 6ecfe095bb7178adea752d8a30d3f4a125f8f10f Author: Will Thompson Date: Thu Apr 22 23:31:34 2010 +0100 Return node trees from the distillery Previously all these functions were technically incorrect: they were calling wocky_porter_send_iq_finish(), and if it yielded a stanza, they'd grab a WockyNode * out of the stanza, *unref the stanza*, and then return the pointer to the caller. So, this relied on the stanza happening to stay alive long enough for the caller to frob the nodes. This makes some code a bit more verbose, but not much. wocky/wocky-pubsub-helpers.c | 28 +++++++++--------- wocky/wocky-pubsub-helpers.h | 6 ++-- wocky/wocky-pubsub-node.c | 46 +++++++++++++++++++---------- wocky/wocky-pubsub-service-protected.h | 2 +- wocky/wocky-pubsub-service.c | 53 ++++++++++++++++++++-------------- 5 files changed, 81 insertions(+), 54 deletions(-) commit 513d075b5bfbdb0dc1038c947b360912d3fd8e5d Author: Will Thompson Date: Thu Apr 22 23:12:06 2010 +0100 Deconstruct the PubSub distillery a bit. This exposes a function which accepts a stanza that you've already verified is an iq type=result, and pulls out a child node. Previously, if you weren't happy with wocky_pubsub_distill_iq_reply() and friends' conversion from an element to a GError, you had to re-do the breakdown, because these guts weren't exposed. wocky/wocky-pubsub-helpers.c | 98 +++++++++++++++++++++++++++++++++----------- wocky/wocky-pubsub-helpers.h | 7 ++++ 2 files changed, 81 insertions(+), 24 deletions(-) commit 58a14ddab2a60819050542ee2345473a1f2a5a9d Author: Mike Ruprecht Date: Fri Apr 23 23:46:26 2010 -0500 Fix example program listing for wocky_node_tree_new. wocky/wocky-node-tree.c | 1 - 1 file changed, 1 deletion(-) commit 3aeeababb953192e6846c01c81497f6e64daf2d2 Author: Will Thompson Date: Thu Apr 22 14:25:36 2010 +0100 Coding style: space after cast wocky/wocky-node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 04deb877174b42ccd19ec7473c523d5af8a49cfd Merge: efb168b 47b9aac Author: Will Thompson Date: Thu Apr 22 14:21:54 2010 +0100 Merge branch 'pubsub-modify-affiliates-and-node-config' Reviewed-by: Sjoerd Simons commit efb168b1eb7d20da6b83eacdf3a5a19398eed9ac Author: Sjoerd Simons Date: Tue Apr 20 17:14:05 2010 +0100 Document when we would have to fallback to a dummy namespace wocky/wocky-xmpp-reader.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 47b9aac9083fe57984822b94bdfa7e417100f194 Author: Will Thompson Date: Tue Apr 20 16:41:47 2010 +0100 Document WockyPubsubSubscriptionState wocky/wocky-pubsub-service.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) commit c2ecec40c3e82d44d34c7ff3cd50d8ee61f3b303 Author: Will Thompson Date: Mon Apr 19 19:41:15 2010 +0100 Refactor handling reply All the WockyPubsubNode helpers for handling replies start from a node you've retrieved (presumably with a _distill_ function). wocky_pubsub_service_handle_create_node_reply() did not; this patch brings it in line with the others. wocky/wocky-pubsub-service-protected.h | 3 +-- wocky/wocky-pubsub-service.c | 42 +++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 15 deletions(-) commit 3388359119c424236db9a4813b1a1d9a96c7abfb Author: Will Thompson Date: Mon Apr 19 17:30:32 2010 +0100 Implement retrieving a node's configuration tests/wocky-pubsub-node-test.c | 129 ++++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-node-protected.h | 5 ++ wocky/wocky-pubsub-node.c | 96 +++++++++++++++++++++++++++ wocky/wocky-pubsub-node.h | 11 +++ 4 files changed, 241 insertions(+) commit 8072b3d85b9f6ddd6729c0b18bcb1c869871dbcb Author: Will Thompson Date: Mon Apr 19 17:30:08 2010 +0100 Add a _finish macro that returns a copy of a pointer wocky/wocky-utils.h | 10 ++++++++++ 1 file changed, 10 insertions(+) commit 0b22a79a042f3ab3f1b284b52030b4c21231a399 Author: Will Thompson Date: Mon Apr 19 15:14:25 2010 +0100 Implement modifying affiliates tests/wocky-pubsub-node-test.c | 115 +++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-node-protected.h | 6 ++ wocky/wocky-pubsub-node.c | 122 ++++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-node.h | 12 ++++ 4 files changed, 255 insertions(+) commit 3aa9ac4cd18ecdce04bdd2ad3d528377c82284b7 Author: Sjoerd Simons Date: Tue Apr 20 15:45:29 2010 +0100 Update .gitignore .gitignore | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) commit e5b3f9dd089521582d652dda8fe442e066ec7bae Author: Sjoerd Simons Date: Tue Apr 20 15:20:56 2010 +0100 Can't have tags with spaces tests/wocky-node-tree-test.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) commit 871837f00a03a6b833430ae60f5b4677126395c7 Author: Sjoerd Simons Date: Tue Apr 20 15:19:26 2010 +0100 Fix wocky_node_tree_new example wocky/wocky-node-tree.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit abedf45b2cc49ef54a582a3547d94a42dddac9bf Author: Will Thompson Date: Mon Apr 19 15:25:07 2010 +0100 pubsub_affiliation_new: log more clearly if @node is NULL Ahem. wocky/wocky-pubsub-node.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) commit aa2858852d3c4496e0d3cf9a5ad3fdb328ce2377 Author: Will Thompson Date: Mon Apr 19 15:14:07 2010 +0100 Document WockyPubsubAffiliation and related methods. wocky/wocky-pubsub-node.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) commit cde08a5279cd9dad033a456a2043e70395375441 Author: Will Thompson Date: Mon Apr 19 13:38:41 2010 +0100 Generalize returning TRUE or an error from _finish() wocky/wocky-pubsub-node.c | 18 ++---------------- wocky/wocky-utils.h | 8 ++++++++ 2 files changed, 10 insertions(+), 16 deletions(-) commit 028f7ad09c8afe242acc9a30c0e32f741b2bcee0 Author: Will Thompson Date: Mon Apr 19 12:00:25 2010 +0100 PubsubNode: Generalize void IQ reply handler wocky/wocky-pubsub-node.c | 30 ++++-------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) commit df2d8f060ae37d2ced635b54407b944d64425673 Author: Sjoerd Simons Date: Tue Apr 20 14:42:51 2010 +0100 Add a test for wocky_node_add_node_tree tests/wocky-node-tree-test.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) commit 93459fda35b00a0be13e732ffcce90261c16d41b Author: Sjoerd Simons Date: Tue Apr 20 14:42:23 2010 +0100 Add API to insert a NodeTree under a node wocky/wocky-node-tree.h | 2 +- wocky/wocky-node.c | 20 ++++++++++++++++++++ wocky/wocky-node.h | 4 ++++ wocky/wocky-types.h | 1 + 4 files changed, 26 insertions(+), 1 deletion(-) commit 993ce5af20442183443594d09d467d53c9f3df45 Author: Sjoerd Simons Date: Mon Apr 19 18:18:41 2010 +0100 Add API to serialize node trees wocky/wocky-xmpp-writer.c | 64 ++++++++++++++++++++++++++++++++++++----------- wocky/wocky-xmpp-writer.h | 6 +++++ 2 files changed, 55 insertions(+), 15 deletions(-) commit 535645889d2c94673518da10282d1007eb9eac48 Author: Sjoerd Simons Date: Mon Apr 19 18:18:25 2010 +0100 Add debug helpers for node trees wocky/wocky-debug.c | 39 +++++++++++++++++++++++++++++++-------- wocky/wocky-debug.h | 10 ++++++++++ 2 files changed, 41 insertions(+), 8 deletions(-) commit 57a525b9032020ade15fa0311498997716f0a2ef Author: Sjoerd Simons Date: Mon Apr 19 17:48:26 2010 +0100 Add API to make new NodeTrees with copies of a given node tests/wocky-node-tree-test.c | 23 +++++++++++++++++++++++ wocky/wocky-node-tree.c | 18 ++++++++++++++++++ wocky/wocky-node-tree.h | 2 ++ 3 files changed, 43 insertions(+) commit f8b9994ad7b31b7b4d1e2df7603c2083e60932e1 Author: Sjoerd Simons Date: Mon Apr 19 17:42:08 2010 +0100 Add an internal node copy function wocky/Makefile.am | 1 + wocky/wocky-node-private.h | 33 +++++++++++++++++++++++++++++++++ wocky/wocky-node.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) commit 53e19d288d9d453d8c3df88b442495d22d7014af Author: Sjoerd Simons Date: Mon Apr 19 17:11:24 2010 +0100 Add a simple test for the nodetree building functions tests/Makefile.am | 7 ++++++ tests/wocky-node-tree-test.c | 54 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) commit 842b0082806d9ed928d19f59ae38b045d09f7dad Author: Sjoerd Simons Date: Mon Apr 19 16:46:56 2010 +0100 Add API to access the top node of a WockyNodeTree wocky/wocky-node-tree.c | 18 +++++++++++------- wocky/wocky-node-tree.h | 3 ++- wocky/wocky-stanza.c | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) commit 360d7e1a3183932dcc0198e4ec94fe553cdc4e97 Author: Sjoerd Simons Date: Mon Apr 19 16:43:33 2010 +0100 Add API to create node-trees wocky/wocky-node-tree.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-node-tree.h | 8 ++++++++ 2 files changed, 60 insertions(+) commit c22f6ccec7eeac006ca4cd1b85bffc6be7aa9bc2 Author: Sjoerd Simons Date: Mon Apr 19 15:58:20 2010 +0100 Disallow changing the namespace of a node As we assert that a node should always have a namespace allowing the API user to set it later doesn't make that much sense. Remove the API to set and add some utility API to make setting the correct namespace at node creation time easier. wocky/wocky-node.c | 72 ++++++++++++++++++++++++++++++++++-------------------- wocky/wocky-node.h | 11 ++++++--- 2 files changed, 54 insertions(+), 29 deletions(-) commit ba3be5104d9e30fb74d9d61fd992db7bb11e0c1d Author: Sjoerd Simons Date: Mon Apr 19 15:57:48 2010 +0100 Always directly set the namespace when adding children wocky/wocky-xmpp-error.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) commit 969a12f4e13a46f0ccef3f125232811a32b94aa0 Author: Sjoerd Simons Date: Mon Apr 19 15:39:23 2010 +0100 Require nodes to always have a namespace wocky/wocky-node.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) commit 4f0b7b2163b1b0e9666189ad9cddc90d52cba96b Author: Sjoerd Simons Date: Mon Apr 19 15:38:49 2010 +0100 Make sure nodes/stanzas we create always have a namespace tests/wocky-test-connector-server.c | 4 +++- tests/wocky-xmpp-node-test.c | 2 +- wocky/wocky-xmpp-reader.c | 11 ++++++++++- 3 files changed, 14 insertions(+), 3 deletions(-) commit 97268cafb36e19ca0b1fe21662ac6a36f444b26c Author: Sjoerd Simons Date: Fri Apr 16 19:04:58 2010 +0100 Add a top-node constuct time property to NodeTree wocky/wocky-node-tree.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-stanza.c | 5 +++-- 2 files changed, 58 insertions(+), 2 deletions(-) commit 4829c453b09a295d634bfff2bf152dbf0c1bca5a Author: Sjoerd Simons Date: Mon Apr 19 19:59:43 2010 +0100 Add a test for wocky_node_add_build tests/wocky-xmpp-node-test.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) commit a058dde837493cbf9fe3ae0923904e8ff77fd69e Author: Sjoerd Simons Date: Mon Apr 19 19:57:39 2010 +0100 Remove the first_tag argument from node_add_build Because of the first_tag argument we can't pass things on nicely to _build_va, but given that this is the same pattern as several other function leaving it out should be fine. wocky/wocky-node.c | 4 +--- wocky/wocky-node.h | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) commit af2c1fbf65edd1936a50e3cf89bd1270840f6ae5 Author: Sjoerd Simons Date: Mon Apr 19 19:10:42 2010 +0100 Let gtk-doc take care of building the sections file docs/reference/Makefile.am | 4 +- docs/reference/wocky-sections.txt | 833 -------------------------------------- 2 files changed, 2 insertions(+), 835 deletions(-) commit 3de8b93eee0c99e70af5795f253bf509aeb67ede Author: Sjoerd Simons Date: Mon Apr 19 19:10:10 2010 +0100 Documentation tweaks wocky/wocky-node.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) commit c33a0fc75ba253de97c69b0f462400b29ca01644 Author: Sjoerd Simons Date: Mon Apr 19 19:09:56 2010 +0100 g_quark_from_string is NULL safe wocky/wocky-node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit eddd4264a08422a72f88b1f70004a3062801d567 Author: Sjoerd Simons Date: Mon Apr 19 19:09:29 2010 +0100 Remove unimplemented functions wocky/wocky-node-tree.h | 5 ----- 1 file changed, 5 deletions(-) commit 125e505715d1f4d8a4148627d8d17c6c4dba0296 Author: Sjoerd Simons Date: Mon Apr 19 18:33:06 2010 +0100 Correct copyright years wocky/wocky-node-tree.c | 2 +- wocky/wocky-node-tree.h | 2 +- wocky/wocky-node.c | 2 +- wocky/wocky-node.h | 2 +- wocky/wocky-stanza.c | 2 +- wocky/wocky-stanza.h | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) commit 2f934083b56111eb99ff6039d876282d2f5b13da Author: Sjoerd Simons Date: Fri Apr 16 15:54:29 2010 +0100 Add documentation for wocky_node_add_build wocky/wocky-node.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) commit 9fb0f63eb4967cd0aa752b2ff70ac6ab84ee6006 Author: Sjoerd Simons Date: Fri Apr 16 15:50:34 2010 +0100 Fixup the documentation of wocky_stanza_build wocky/wocky-stanza.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) commit f3d7246436753078db1093e5ea5ad28946c01c77 Author: Sjoerd Simons Date: Thu Apr 15 14:56:13 2010 +0100 Update wocky-docs.sgml docs/reference/wocky-docs.sgml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit c9aaac580d008d7f1c0e110f5cdd8706741dc72f Author: Sjoerd Simons Date: Thu Apr 15 14:41:44 2010 +0100 Rename WockyXmppNode to WockyNode examples/connect.c | 14 +- tests/wocky-data-form-test.c | 28 +- tests/wocky-pep-service-test.c | 10 +- tests/wocky-porter-test.c | 20 +- tests/wocky-pubsub-node-test.c | 62 +- tests/wocky-pubsub-service-test.c | 42 +- tests/wocky-pubsub-test-helpers.c | 12 +- tests/wocky-pubsub-test-helpers.h | 2 +- tests/wocky-roster-test.c | 86 +-- tests/wocky-stanza-test.c | 2 +- tests/wocky-test-connector-server.c | 82 +-- tests/wocky-test-helper.h | 24 +- tests/wocky-test-sasl-auth-server.c | 22 +- tests/wocky-xmpp-node-test.c | 98 +-- tests/wocky-xmpp-readwrite-test.c | 28 +- wocky/Makefile.am | 4 +- wocky/wocky-connector.c | 58 +- wocky/wocky-data-form.c | 126 ++-- wocky/wocky-data-form.h | 8 +- wocky/wocky-debug.c | 2 +- wocky/wocky-muc.c | 98 +-- wocky/wocky-node-tree.c | 2 +- wocky/wocky-node-tree.h | 4 +- wocky/wocky-node.c | 1240 ++++++++++++++++++++++++++++++++ wocky/wocky-node.h | 206 ++++++ wocky/wocky-pep-service.c | 4 +- wocky/wocky-pep-service.h | 2 +- wocky/wocky-porter.c | 16 +- wocky/wocky-pubsub-helpers.c | 32 +- wocky/wocky-pubsub-helpers.h | 14 +- wocky/wocky-pubsub-node-protected.h | 26 +- wocky/wocky-pubsub-node.c | 90 +-- wocky/wocky-pubsub-node.h | 6 +- wocky/wocky-pubsub-service-protected.h | 12 +- wocky/wocky-pubsub-service.c | 70 +- wocky/wocky-roster.c | 52 +- wocky/wocky-sasl-auth.c | 34 +- wocky/wocky-stanza.c | 30 +- wocky/wocky-stanza.h | 4 +- wocky/wocky-xmpp-error.c | 46 +- wocky/wocky-xmpp-error.h | 12 +- wocky/wocky-xmpp-node.c | 1240 -------------------------------- wocky/wocky-xmpp-node.h | 206 ------ wocky/wocky-xmpp-reader.c | 16 +- wocky/wocky-xmpp-writer.c | 14 +- wocky/wocky.c | 6 +- 46 files changed, 2106 insertions(+), 2106 deletions(-) commit 7b4549cf87a279d157d09618f3b39f702ae475ce Author: Sjoerd Simons Date: Thu Apr 15 13:24:51 2010 +0100 Split out a base NodeTree object from Stanza Add a seperate NodeTree object as a parent to Stanza. This NodeTree object can later be used as a container for subtrees to copy out or into Stanzas Also move add_build* to WockyXmppNode as it can be useful in user code as well wocky/Makefile.am | 2 + wocky/wocky-node-tree.c | 85 ++++++++++++++++++++++++++++++++++++ wocky/wocky-node-tree.h | 73 +++++++++++++++++++++++++++++++ wocky/wocky-stanza.c | 114 ++---------------------------------------------- wocky/wocky-stanza.h | 18 ++------ wocky/wocky-xmpp-node.c | 105 ++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-node.h | 18 ++++++++ 7 files changed, 290 insertions(+), 125 deletions(-) commit 7487f34f12c940e332b52277098c59186f3a5eb5 Author: Sjoerd Simons Date: Thu Apr 15 12:40:20 2010 +0100 Check all tests for coding style and fix the style a bit tests/Makefile.am | 21 ++++++++++++++++++--- tests/wocky-contact-factory-test.c | 4 ++-- tests/wocky-stanza-test.c | 4 ++-- tests/wocky-tls-test.c | 4 ++-- 4 files changed, 24 insertions(+), 9 deletions(-) commit b596cd12bb602dd95e610de82b7a3c119fede879 Author: Sjoerd Simons Date: Thu Apr 15 12:38:01 2010 +0100 Use wocky_stanza_get_top_node instead of ->node examples/connect.c | 24 +++++++++++++------- tests/wocky-data-form-test.c | 43 +++++++++++++++++++++++------------- tests/wocky-pep-service-test.c | 4 ++-- tests/wocky-porter-test.c | 28 +++++++++++++---------- tests/wocky-pubsub-node-test.c | 2 +- tests/wocky-pubsub-service-test.c | 23 +++++++++---------- tests/wocky-roster-test.c | 32 +++++++++++++++------------ tests/wocky-stanza-test.c | 4 ++-- tests/wocky-test-connector-server.c | 26 ++++++++++++---------- tests/wocky-test-helper.c | 3 ++- tests/wocky-test-helper.h | 12 +++++----- tests/wocky-test-sasl-auth-server.c | 39 ++++++++++++++++++-------------- tests/wocky-xmpp-node-test.c | 35 ++++++++++++++++------------- tests/wocky-xmpp-readwrite-test.c | 11 ++++++---- wocky/wocky-connector.c | 25 ++++++++++++--------- wocky/wocky-debug.c | 3 ++- wocky/wocky-muc.c | 21 +++++++++++------- wocky/wocky-pep-service.c | 3 ++- wocky/wocky-porter.c | 20 ++++++++++------- wocky/wocky-pubsub-helpers.c | 3 ++- wocky/wocky-pubsub-service.c | 5 +++-- wocky/wocky-roster.c | 10 +++++---- wocky/wocky-sasl-auth.c | 44 ++++++++++++++++++++++--------------- wocky/wocky-stanza.c | 33 +++++++++++++++++----------- wocky/wocky-xmpp-node.c | 2 +- wocky/wocky-xmpp-writer.c | 2 +- 26 files changed, 271 insertions(+), 186 deletions(-) commit 71d195fd71886cdea3275dd9a2763ba26bbf6e6b Author: Sjoerd Simons Date: Wed Apr 14 14:19:18 2010 +0100 Add a namespace argument to wocky_stanza_new examples/connect.c | 3 +-- tests/wocky-test-connector-server.c | 14 +++++--------- tests/wocky-test-sasl-auth-server.c | 15 +++++---------- tests/wocky-xmpp-node-test.c | 2 +- wocky/wocky-connector.c | 3 +-- wocky/wocky-sasl-auth.c | 7 ++----- wocky/wocky-stanza.c | 7 +++---- wocky/wocky-stanza.h | 2 +- wocky/wocky-xmpp-node.c | 12 ++++++------ wocky/wocky-xmpp-node.h | 2 +- wocky/wocky-xmpp-reader.c | 9 +++++---- 11 files changed, 31 insertions(+), 45 deletions(-) commit 8368ca138c8b0a39cb07598a2001cbb83bff7228 Author: Sjoerd Simons Date: Wed Apr 14 14:08:42 2010 +0100 Add shorthand for testing (in)equality of stanzas tests/wocky-porter-test.c | 4 ++-- tests/wocky-pubsub-node-test.c | 2 +- tests/wocky-stanza-test.c | 14 +++++++------- tests/wocky-test-helper.h | 7 +++++++ tests/wocky-xmpp-node-test.c | 22 ++++++++++++---------- tests/wocky-xmpp-readwrite-test.c | 6 +++--- 6 files changed, 32 insertions(+), 23 deletions(-) commit a7ae4097134b1d2078689c192000f93e48e17aad Author: Sjoerd Simons Date: Wed Apr 14 13:56:46 2010 +0100 Introduce wocky_stanza_get_top_node wocky/wocky-stanza.c | 12 ++++++++++++ wocky/wocky-stanza.h | 4 +++- 2 files changed, 15 insertions(+), 1 deletion(-) commit 8c9b3ae6101cea9187741d6794ee984483275555 Author: Sjoerd Simons Date: Wed Apr 14 11:30:25 2010 +0100 Rename _stanzas_equal to _stanzas_equal_no_id tests/wocky-data-form-test.c | 2 +- tests/wocky-pubsub-node-test.c | 4 ++-- tests/wocky-pubsub-service-test.c | 2 +- tests/wocky-test-helper.h | 3 ++- 4 files changed, 6 insertions(+), 5 deletions(-) commit 3d6c227b84555e16a0fafea4839ef7debda1299e Author: Sjoerd Simons Date: Tue Apr 13 16:23:20 2010 +0100 Rename WockyXmppStanza to WockyStanza docs/reference/wocky-docs.sgml | 2 +- docs/reference/wocky-sections.txt | 38 +- examples/connect.c | 10 +- tests/Makefile.am | 8 +- tests/wocky-connector-test.c | 4 +- tests/wocky-data-form-test.c | 34 +- tests/wocky-pep-service-test.c | 22 +- tests/wocky-porter-test.c | 234 ++++++------ tests/wocky-pubsub-node-test.c | 62 ++-- tests/wocky-pubsub-service-test.c | 58 +-- tests/wocky-roster-test.c | 56 +-- tests/wocky-stanza-test.c | 579 +++++++++++++++++++++++++++++ tests/wocky-test-connector-server.c | 128 +++---- tests/wocky-test-helper.c | 8 +- tests/wocky-test-helper.h | 2 +- tests/wocky-test-sasl-auth-server.c | 36 +- tests/wocky-test-sasl-auth-server.h | 6 +- tests/wocky-test-sasl-auth.c | 4 +- tests/wocky-xmpp-connection-test.c | 32 +- tests/wocky-xmpp-node-test.c | 32 +- tests/wocky-xmpp-reader-test.c | 4 +- tests/wocky-xmpp-readwrite-test.c | 10 +- tests/wocky-xmpp-stanza-test.c | 579 ----------------------------- wocky/Makefile.am | 4 +- wocky/wocky-connector.c | 94 ++--- wocky/wocky-connector.h | 2 +- wocky/wocky-debug.c | 2 +- wocky/wocky-debug.h | 4 +- wocky/wocky-muc.c | 62 ++-- wocky/wocky-muc.h | 4 +- wocky/wocky-pep-service.c | 12 +- wocky/wocky-pep-service.h | 6 +- wocky/wocky-porter.c | 60 +-- wocky/wocky-porter.h | 18 +- wocky/wocky-pubsub-helpers.c | 16 +- wocky/wocky-pubsub-helpers.h | 6 +- wocky/wocky-pubsub-node-protected.h | 12 +- wocky/wocky-pubsub-node.c | 44 +-- wocky/wocky-pubsub-node.h | 2 +- wocky/wocky-pubsub-service-protected.h | 4 +- wocky/wocky-pubsub-service.c | 30 +- wocky/wocky-pubsub-service.h | 2 +- wocky/wocky-roster.c | 48 +-- wocky/wocky-sasl-auth.c | 18 +- wocky/wocky-sasl-auth.h | 4 +- wocky/wocky-sasl-handler.h | 2 +- wocky/wocky-stanza.c | 650 ++++++++++++++++++++++++++++++++ wocky/wocky-stanza.h | 147 ++++++++ wocky/wocky-xmpp-connection.c | 18 +- wocky/wocky-xmpp-connection.h | 6 +- wocky/wocky-xmpp-error.c | 2 +- wocky/wocky-xmpp-reader.c | 22 +- wocky/wocky-xmpp-reader.h | 6 +- wocky/wocky-xmpp-stanza.c | 652 --------------------------------- wocky/wocky-xmpp-stanza.h | 147 -------- wocky/wocky-xmpp-writer.c | 4 +- wocky/wocky-xmpp-writer.h | 4 +- 57 files changed, 2030 insertions(+), 2032 deletions(-) commit 9c489c118b7aa339d9a08cd7e749b486c412650c Author: Will Thompson Date: Tue Apr 13 15:58:45 2010 +0100 Use G_TYPE_INSTANCE_GET_PRIVATE() correctly. Rather than repeatedly calling that macro (which is reasonably expensive), it should be called once in the object's _init() function and stored in a pointer in the public structure. This patch changes the whole of Wocky to do this correctly! tests/wocky-test-connector-server.c | 73 +++++++++++++------------- tests/wocky-test-connector-server.h | 3 ++ tests/wocky-test-sasl-auth-server.c | 57 ++++++++++---------- tests/wocky-test-sasl-auth-server.h | 4 ++ wocky/wocky-bare-contact.c | 56 +++++++++----------- wocky/wocky-bare-contact.h | 3 ++ wocky/wocky-connector.c | 101 +++++++++++++++++------------------- wocky/wocky-connector.h | 2 + wocky/wocky-contact-factory.c | 27 +++++----- wocky/wocky-contact-factory.h | 2 + wocky/wocky-contact.c | 22 +++----- wocky/wocky-contact.h | 3 ++ wocky/wocky-data-form.c | 30 +++++------ wocky/wocky-data-form.h | 3 ++ wocky/wocky-muc.c | 54 +++++++++---------- wocky/wocky-muc.h | 2 + wocky/wocky-pep-service.c | 32 +++++------- wocky/wocky-pep-service.h | 4 ++ wocky/wocky-porter.c | 68 ++++++++++++------------ wocky/wocky-porter.h | 2 + wocky/wocky-pubsub-node.c | 48 +++++++---------- wocky/wocky-pubsub-node.h | 4 ++ wocky/wocky-pubsub-service.c | 46 +++++++--------- wocky/wocky-pubsub-service.h | 3 ++ wocky/wocky-resource-contact.c | 32 +++++------- wocky/wocky-resource-contact.h | 4 ++ wocky/wocky-roster.c | 54 ++++++++++--------- wocky/wocky-roster.h | 3 ++ wocky/wocky-sasl-auth.c | 35 ++++++------- wocky/wocky-sasl-auth.h | 4 ++ wocky/wocky-session.c | 34 +++++------- wocky/wocky-session.h | 4 ++ wocky/wocky-xmpp-connection.c | 56 ++++++++++---------- wocky/wocky-xmpp-connection.h | 3 ++ wocky/wocky-xmpp-reader.c | 49 ++++++++--------- wocky/wocky-xmpp-reader.h | 3 ++ wocky/wocky-xmpp-stanza.c | 14 +++-- wocky/wocky-xmpp-stanza.h | 4 ++ wocky/wocky-xmpp-writer.c | 35 ++++++------- wocky/wocky-xmpp-writer.h | 4 ++ 40 files changed, 480 insertions(+), 507 deletions(-) commit 2e47a76da94cc4945fc32fc6b8c2c56b99a156cf Merge: 970a4d6 ff4b9ff Author: Will Thompson Date: Tue Apr 13 15:59:52 2010 +0100 Merge branch 'dsl' Reviewed-by: Sjoerd Simons commit ff4b9ff64dc9af98ccd39d4d4a852d711cee271d Author: Will Thompson Date: Sat Apr 10 01:23:22 2010 +0100 Use ASCII mnemonics throughout. tests/wocky-data-form-test.c | 406 ++++++++++++++++++------------------ tests/wocky-pep-service-test.c | 40 ++-- tests/wocky-porter-test.c | 142 ++++++------- tests/wocky-pubsub-node-test.c | 230 ++++++++++---------- tests/wocky-pubsub-service-test.c | 198 +++++++++--------- tests/wocky-roster-test.c | 172 +++++++-------- tests/wocky-test-connector-server.c | 218 +++++++++---------- tests/wocky-test-sasl-auth-server.c | 2 +- tests/wocky-xmpp-connection-test.c | 10 +- tests/wocky-xmpp-node-test.c | 52 ++--- tests/wocky-xmpp-readwrite-test.c | 10 +- tests/wocky-xmpp-stanza-test.c | 276 ++++++++++++------------ wocky/wocky-connector.c | 66 +++--- wocky/wocky-muc.c | 6 +- wocky/wocky-pep-service.c | 24 +-- wocky/wocky-porter.c | 8 +- wocky/wocky-pubsub-helpers.c | 14 +- wocky/wocky-pubsub-service.c | 8 +- wocky/wocky-roster.c | 40 ++-- 19 files changed, 961 insertions(+), 961 deletions(-) commit 4e1c0ad275c1a7c3cb4f225e845cac73ab10ffb7 Author: Will Thompson Date: Sat Apr 10 01:18:31 2010 +0100 Use G_GNUC_NULL_TERMINATED for build spec-cy functions Unfortunately, the functions' previous signatures were awkward for NULL-termination: because the first tag in the specification was an explicit non-pointer argument, if you didn't actually want the stanza to have a body you had to say: wocky_xmpp_stanza_build_iq_result (..., WOCKY_STANZA_END, NULL); You couldn't use NULL in place of WOCKY_STANZA_END because WockyBuildTag isn't a pointer type; and you couldn't omit it because then the varargs aren't NULL-terminated. So, this patch removes the explicit first tag argument. While this may be slightly worse from a documentation point of view, I think it's better than having to document the special case above. tests/wocky-data-form-test.c | 16 ++-- tests/wocky-pep-service-test.c | 6 +- tests/wocky-porter-test.c | 146 ++++++++++++++++++------------------ tests/wocky-pubsub-node-test.c | 32 ++++---- tests/wocky-pubsub-service-test.c | 30 ++++---- tests/wocky-roster-test.c | 42 +++++------ tests/wocky-test-connector-server.c | 52 ++++++------- tests/wocky-test-sasl-auth-server.c | 2 +- tests/wocky-xmpp-connection-test.c | 12 +-- tests/wocky-xmpp-node-test.c | 16 ++-- tests/wocky-xmpp-readwrite-test.c | 2 +- tests/wocky-xmpp-stanza-test.c | 58 +++++++------- wocky/wocky-connector.c | 16 ++-- wocky/wocky-muc.c | 8 +- wocky/wocky-pep-service.c | 4 +- wocky/wocky-porter.c | 22 +++--- wocky/wocky-porter.h | 3 +- wocky/wocky-pubsub-helpers.c | 2 +- wocky/wocky-pubsub-service.c | 2 +- wocky/wocky-roster.c | 12 +-- wocky/wocky-xmpp-stanza.c | 39 ++++------ wocky/wocky-xmpp-stanza.h | 10 +-- 22 files changed, 258 insertions(+), 274 deletions(-) commit 6fb6e88edc7542a209e547796f5827a6af0af5be Author: Will Thompson Date: Tue Mar 16 22:11:05 2010 +0000 Permit ASCII mnemonics for stanza build specs wocky/wocky-xmpp-stanza.c | 18 ++++++++++++++++++ wocky/wocky-xmpp-stanza.h | 14 +++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) commit 244e55ba32a6ed4ad6b9709167332d671cc5e752 Author: Will Thompson Date: Tue Mar 16 22:04:44 2010 +0000 Detect (and fix) misbalanced stanza build specs tests/wocky-data-form-test.c | 1 + tests/wocky-pubsub-service-test.c | 14 ++++++++++---- tests/wocky-test-connector-server.c | 11 +++++++++-- tests/wocky-xmpp-node-test.c | 1 + wocky/wocky-xmpp-stanza.c | 17 +++++++++++++++++ 5 files changed, 38 insertions(+), 6 deletions(-) commit 970a4d6f9c2c2f59d78d9e6b8e347b31440d0088 Author: Will Thompson Date: Wed Apr 7 15:14:56 2010 +0100 Correctly scan generated code in out-of-tree builds docs/reference/Makefile.am | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) commit f2dc3d965438fb69fcb516a76926dbf2671d0fd3 Author: Will Thompson Date: Wed Apr 7 15:13:16 2010 +0100 Fix typoes and missing params in pubsub documentation wocky/wocky-pubsub-node.c | 24 +++++++++++++++++++----- wocky/wocky-pubsub-service.c | 10 ++++++---- 2 files changed, 25 insertions(+), 9 deletions(-) commit ec25e9372fd4fba4de419bffa6140b2861c0c17b Author: Will Thompson Date: Wed Apr 7 15:09:16 2010 +0100 Consistently use 'self' in DataForm, PubsubNode, PubsubService These classes sometimes used 'self' as the first parameter to object methods, and sometimes used 'form', 'node', 'service', etc. In some cases, the parameter name was different between the declaration and definition. This patch makes them always use 'self', and tweaks the gtkdoc comments to match (some of which matched the definition rather than the declaration, which makes gtkdoc cry). wocky/wocky-data-form.c | 52 ++++++++++++++++++++++---------------------- wocky/wocky-data-form.h | 16 +++++++------- wocky/wocky-pubsub-node.h | 8 +++---- wocky/wocky-pubsub-service.c | 4 ++-- wocky/wocky-pubsub-service.h | 16 +++++++------- 5 files changed, 48 insertions(+), 48 deletions(-) commit 6c18473e57612f9dc475ba79f5339b7f32a3bbfd Author: Will Thompson Date: Wed Apr 7 15:03:38 2010 +0100 Add a bunch of new symbols to wocky-sections.txt docs/reference/wocky-sections.txt | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) commit a3646b39d2a493ed8d818f55b23d6cc9cc4b5503 Author: Will Thompson Date: Wed Apr 7 15:00:05 2010 +0100 Remove non-existent sections from wocky-docs.sgml The WockyPubsubService enums are included in the WockyPubsubService section, and wocky-types.h doesn't have any documentation of its own. docs/reference/wocky-docs.sgml | 2 -- 1 file changed, 2 deletions(-) commit 6f5db6650014120076eff8e915a5ec666740ed6e Merge: 31ccb4e 8e6649d Author: Will Thompson Date: Tue Apr 6 19:53:32 2010 +0100 Merge branch 'pubsub-notifications-subscribers-affiliates' Conflicts: wocky/wocky-utils.c wocky/wocky-utils.h Reviewed-by: Simon McVittie commit 8e6649df9869c7db67e80136bca3d759c652c1ac Author: Will Thompson Date: Tue Apr 6 17:45:20 2010 +0100 Escape XMPP tags used in gtk-doc comments wocky/wocky-pubsub-helpers.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) commit 11a0b942304d367871606ccc3f3f929a3ba36155 Author: Will Thompson Date: Tue Apr 6 17:35:58 2010 +0100 Un-magic-number the number of pubsub events wocky/wocky-pubsub-node-protected.h | 3 ++- wocky/wocky-pubsub-node.c | 5 ++++- wocky/wocky-pubsub-service.c | 8 ++++---- 3 files changed, 10 insertions(+), 6 deletions(-) commit d4567f97cf4d99648281676c9b84fff59d33dbe8 Author: Will Thompson Date: Thu Apr 1 15:05:16 2010 +0100 Add API for retrieving affiliates to a node tests/wocky-pubsub-node-test.c | 125 ++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-node-protected.h | 9 +++ wocky/wocky-pubsub-node.c | 139 ++++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-node.h | 12 ++++ 4 files changed, 285 insertions(+) commit 817566a768ae00128d805e278c3a433599c085c8 Author: Will Thompson Date: Thu Apr 1 14:21:35 2010 +0100 Use GQueue in subscription-parsing code. This looks more obviously right than prepend-and-reverse code, and is shorter! wocky/wocky-pubsub-service.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) commit b9915ab9c21df0c5773cc1cd8f67524b1a237c21 Author: Will Thompson Date: Thu Apr 1 11:48:55 2010 +0100 Macro-ify implementing a simple _finish() function I've written this function tens of times. wocky/wocky-pubsub-node.c | 19 +++---------------- wocky/wocky-pubsub-service.c | 19 +++---------------- wocky/wocky-utils.h | 22 ++++++++++++++++++++++ 3 files changed, 28 insertions(+), 32 deletions(-) commit 3ab22ce66ab818fe6cfb58f121424110a65d63bc Author: Will Thompson Date: Thu Apr 1 11:33:56 2010 +0100 Add types representing pubsub affiliations wocky/Makefile.am | 2 ++ wocky/wocky-pubsub-node.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-node.h | 32 +++++++++++++++++++++++++ 3 files changed, 94 insertions(+) commit 198f445aa1aba6812cc5812e9419e3c0ee18fdaf Author: Will Thompson Date: Thu Apr 1 11:31:10 2010 +0100 Add a GList deep-copy convenience function wocky/wocky-pubsub-service.c | 8 ++------ wocky/wocky-utils.c | 15 +++++++++++++++ wocky/wocky-utils.h | 2 ++ 3 files changed, 19 insertions(+), 6 deletions(-) commit af5f25d61f36e18755570fdea82e198ba74fa3d7 Author: Will Thompson Date: Wed Mar 31 20:23:57 2010 +0100 Add API for listing subscribers to a node. tests/Makefile.am | 1 + tests/wocky-pubsub-node-test.c | 127 +++++++++++++++++++++++++++++++++++- wocky/wocky-pubsub-node-protected.h | 5 ++ wocky/wocky-pubsub-node.c | 109 +++++++++++++++++++++++++++++++ wocky/wocky-pubsub-node.h | 12 ++++ 5 files changed, 253 insertions(+), 1 deletion(-) commit f8db89859134b119413c37b5f95120350b1967a5 Author: Will Thompson Date: Wed Mar 31 20:22:31 2010 +0100 Extract test helper code for checking subscriptions This'll be needed in the node test in a moment... tests/Makefile.am | 1 + tests/wocky-pubsub-service-test.c | 47 ++++------------------------------ tests/wocky-pubsub-test-helpers.c | 54 +++++++++++++++++++++++++++++++++++++++ tests/wocky-pubsub-test-helpers.h | 24 +++++++++++++++++ 4 files changed, 84 insertions(+), 42 deletions(-) commit bd9ee1b6d58e3bec839a0abeb626d7bd3da68e94 Author: Will Thompson Date: Wed Mar 31 17:49:51 2010 +0100 Reduce code duplication in creating pubsub stanzas wocky/wocky-pubsub-helpers.c | 67 +++++++++++++++++++++++++++++++++----------- wocky/wocky-pubsub-helpers.h | 8 ++++++ wocky/wocky-pubsub-node.c | 54 +++++++++-------------------------- wocky/wocky-pubsub-service.c | 51 +++++++-------------------------- 4 files changed, 82 insertions(+), 98 deletions(-) commit ffbce9096ed2e437ce31100bc5bdb0c5af38887a Author: Will Thompson Date: Wed Mar 31 16:28:15 2010 +0100 Add signals for node deletion notifications tests/wocky-pubsub-node-test.c | 127 +++++++++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-node.c | 29 ++++++++++ wocky/wocky-pubsub-service.c | 33 +++++++++++ 3 files changed, 189 insertions(+) commit 40ece87dfbd7e0c68665bffaf9ae804a838217fb Author: Will Thompson Date: Wed Mar 31 16:43:49 2010 +0100 Make node event handlers return void They all just returned TRUE anyway, which is conceptually correct: even if they can't parse the stanza, they *are* handling it. And in any case the stanza handler in WockyPubsubService ignored their return value and returned TRUE too, for the same reason. wocky/wocky-pubsub-node-protected.h | 2 +- wocky/wocky-pubsub-node.c | 11 ++--------- 2 files changed, 3 insertions(+), 10 deletions(-) commit 420ba1b755ade33e612703e65f57a31f380eabef Author: Will Thompson Date: Wed Mar 31 16:41:32 2010 +0100 Move list of event handlers into WockyPubsubNode wocky/wocky-pubsub-node-protected.h | 20 +++++++++++--------- wocky/wocky-pubsub-node.c | 20 ++++++++++++++++---- wocky/wocky-pubsub-service.c | 37 +++++++++++++++++-------------------- 3 files changed, 44 insertions(+), 33 deletions(-) commit 1ffedc50a6d73dc2b8823b2da36e3f3a0c1a4360 Author: Will Thompson Date: Wed Mar 31 15:48:41 2010 +0100 Remove duplicated handlers for PubSub events Given that the WockyPubsubService has to match these events *anyway* to make the corresponding WockyPubsubNodes appear when necessary, there's really no point in the nodes registering higher-priority handlers and duplicating the stanza breakdown code. wocky/wocky-pubsub-node.c | 79 +---------------------------------------------- 1 file changed, 1 insertion(+), 78 deletions(-) commit 8b7ef53909e58bc5f4cbcc55ec6ca9afba5dfdbb Author: Will Thompson Date: Wed Mar 31 15:45:22 2010 +0100 Reduce repeated breakdown of event stanzas. wocky/wocky-pubsub-node-protected.h | 15 +++++++++---- wocky/wocky-pubsub-node.c | 43 +++++++++++++++++++++---------------- wocky/wocky-pubsub-service.c | 2 +- 3 files changed, 37 insertions(+), 23 deletions(-) commit f20b421e773a65a25dfdeb4f07c3cd0713e8c119 Author: Will Thompson Date: Wed Mar 31 13:43:52 2010 +0100 Generalize event propagation from PubsubService to Node wocky/wocky-pubsub-node-protected.h | 3 + wocky/wocky-pubsub-service.c | 129 +++++++++++++++++------------------- 2 files changed, 64 insertions(+), 68 deletions(-) commit 2a5f4f613af27951bd5f5833583e28a8ce1ec99d Author: Will Thompson Date: Tue Mar 30 20:42:52 2010 +0100 Add WockyPubsubService::subscription-state-changed This works just like event-received. The slight duplication in handler code between Service and Node bothers me a bit, as does the similarity between pubsub_service_handle_subscription_event and the one for items events. Maybe I'll extract some common code. tests/wocky-pubsub-node-test.c | 52 ++++++++++++++++++++--- wocky/wocky-pubsub-service.c | 93 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 135 insertions(+), 10 deletions(-) commit dd7d70d0a2475052246213e87d7f7aa361f79ca3 Author: Will Thompson Date: Tue Mar 30 20:20:42 2010 +0100 Add WockyPubsubNode::subscription-state-changed signal tests/wocky-pubsub-node-test.c | 102 ++++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-node-protected.h | 3 ++ wocky/wocky-pubsub-node.c | 99 ++++++++++++++++++++++++++++++++-- 3 files changed, 201 insertions(+), 3 deletions(-) commit 31ccb4e3fcf90786da915228a6b579a6b457f914 Merge: b1512ce f314881 Author: Simon McVittie Date: Tue Apr 6 15:52:56 2010 +0100 Merge branch 'trivia' Reviewed-by: Will Thompson commit f3148819fa97949461532ae37d603d10a28b6909 Author: Simon McVittie Date: Tue Apr 6 15:47:22 2010 +0100 Add missing bits of Wocky to sections.txt, docs.sgml docs/reference/wocky-docs.sgml | 24 ++++++++++++++++++++---- docs/reference/wocky-sections.txt | 29 +++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) commit 54499584f15f7609698d08cb152af6e603fd4ffa Author: Simon McVittie Date: Tue Apr 6 15:39:15 2010 +0100 Sort wocky-docs.sgml alphabetically by section, in the absence of any other obvious organisation docs/reference/wocky-docs.sgml | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) commit a4b03a44f568fd8cf33531bf65972ae056bb28a6 Author: Simon McVittie Date: Tue Apr 6 15:36:51 2010 +0100 Revert "docs: ignore internal headers" This reverts commit 50d58d7fc610fa884f849df6103b533400bed52b. Will tells me that *-protected.h are intended to be used in subclasses (potentially external to Wocky), and pubsub-helpers.h is public too. docs/reference/Makefile.am | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) commit b1512ce640bcd4eb23ba52b35457676378bea376 Merge: e55140b 2565916 Author: Simon McVittie Date: Tue Apr 6 15:28:44 2010 +0100 Merge branch 'oleavr-windows' Reviewed-by: Ole André Vadla Ravnås Reviewed-by: Sjoerd Simons commit 8ffde7f7b28635b308db32a35e316af33b0f4226 Author: Simon McVittie Date: Tue Apr 6 15:17:00 2010 +0100 docs: add more recent API unused.txt is now empty. docs/reference/wocky-sections.txt | 3 +++ 1 file changed, 3 insertions(+) commit 50d58d7fc610fa884f849df6103b533400bed52b Author: Simon McVittie Date: Tue Apr 6 15:15:21 2010 +0100 docs: ignore internal headers From usage, I infer that wocky-pubsub-helpers.h is probably meant to be internal? docs/reference/Makefile.am | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) commit 9d0ab4f57ecf752aedac931deb78f01fb66b5f14 Author: Simon McVittie Date: Tue Apr 6 15:14:31 2010 +0100 docs: add some of the recent API docs/reference/wocky-sections.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) commit 4bc0a267fec5864fca09bfcd31e0d1d2176b88ac Author: Simon McVittie Date: Tue Apr 6 15:14:11 2010 +0100 docs: adapt to WockyDataForm being singular docs/reference/wocky-sections.txt | 60 +++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 28 deletions(-) commit 16e729516b8f2a12e552a858005a70646497ee06 Author: Simon McVittie Date: Tue Apr 6 14:53:21 2010 +0100 Remove wocky_pubsub_node_new from documentation docs/reference/wocky-sections.txt | 1 - 1 file changed, 1 deletion(-) commit c0a5054d4ce403cd5fe8e8f97659da31fbf581cd Author: Simon McVittie Date: Tue Apr 6 14:48:14 2010 +0100 Don't distribute generated sources in the tarball wocky/Makefile.am | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit f4be843b46d8fd78008300005811517944623ca9 Author: Will Thompson Date: Mon Mar 29 19:19:50 2010 +0100 Rename handlers for We'll be handling other kinds of events soon, so these need less generic names. wocky/wocky-pubsub-node-protected.h | 2 +- wocky/wocky-pubsub-node.c | 10 +++++----- wocky/wocky-pubsub-service.c | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) commit e55140b3c4599221e3be9fa28bab21ae6ee22e21 Merge: f22cfb5 c05459d Author: Youness Alaoui Date: Wed Mar 31 18:03:05 2010 -0400 Merge branch 'master' of git+ssh://git.collabora.co.uk/git/wocky commit c05459dd72d0fbc2c1f26ca75bf38a7a4802c946 Author: Sjoerd Simons Date: Wed Mar 31 16:54:02 2010 +0100 Add debugging for the stream opening and closing we sent wocky/wocky-xmpp-writer.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) commit 2fb60d44bd9266d0847b99b0188ac3dbe461ebfa Author: Sjoerd Simons Date: Wed Mar 31 16:53:41 2010 +0100 Add debugging for the stream opening we receive wocky/wocky-xmpp-reader.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) commit fec294eab0b20b654616f4496c271f18679fb199 Author: Ole André Vadla Ravnås Date: Wed Mar 31 13:04:06 2010 +0200 Avoid redundant newlines in open stream stanza Openfire doesn't like them. wocky/wocky-xmpp-writer.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) commit f22cfb549c19eb25e6f027a626c2133f60494def Author: Youness Alaoui Date: Tue Mar 30 19:32:59 2010 -0400 Remove g_error_free after g_propagate_error. g_propagate_error doesn't copy the error, it just sets it from dst to src. So by freeing it here, it causes a double free later on which causes wocky to segfault. wocky/wocky-xmpp-connection.c | 1 - 1 file changed, 1 deletion(-) commit e9d31f1d3f075090dd3c18deda8112f7dca38cc2 Author: Youness Alaoui Date: Tue Mar 30 11:54:59 2010 -0400 Adding tests/wocky-data-form-test into .gitignore .gitignore | 1 + 1 file changed, 1 insertion(+) commit 01a69bedb2b77e31c60c9e489e99b625c59b7959 Merge: bc9ae90 9d70d77 Author: Will Thompson Date: Thu Mar 25 18:29:00 2010 +0000 Merge branch 'pubsub-create-delete-blind-form-submission' Reviewed-by: Simon McVittie commit 9d70d77cdb13aa56e989e52436cdc3dd9ba303e9 Author: Will Thompson Date: Thu Mar 25 18:01:53 2010 +0000 State that data form GValues are slice-allocated wocky/wocky-data-form.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit b557c4daeab438588d6f75b2ead63d0e52f71abc Author: Will Thompson Date: Thu Mar 25 17:59:45 2010 +0000 Correct over-zealous depluralizing of Data Forms tests/wocky-data-form-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 921370d18d5633282c6d2e872879de691c215f58 Author: Will Thompson Date: Thu Mar 25 15:01:51 2010 +0000 Add API for setting FORM_TYPE when blindly submitting tests/wocky-data-form-test.c | 25 +++++++++++++++++++++---- wocky/wocky-data-form.c | 37 +++++++++++++++++++++++++++++++++++++ wocky/wocky-data-form.h | 3 +++ 3 files changed, 61 insertions(+), 4 deletions(-) commit 74072d08ab03f6f70513542728d5b0fdbfe33229 Author: Will Thompson Date: Thu Mar 25 12:46:22 2010 +0000 Use get_content_from_child a bunch. I actually thought it would be useful in more places than this. Oh well. wocky/wocky-data-form.c | 36 ++++++++++-------------------------- wocky/wocky-muc.c | 18 ++++-------------- wocky/wocky-xmpp-error.c | 7 ++----- 3 files changed, 16 insertions(+), 45 deletions(-) commit e3b19005cc7512ae8bb37a6c949c08ce343b01ae Author: Will Thompson Date: Thu Mar 25 12:33:13 2010 +0000 Add helpers to get content from a child node. I've noticed a lot of code following this pattern: WockyXmppNode *foo_node; const gchar *foo = NULL; foo_node = wocky_xmpp_node_get_child (parent, "foo"); if (foo_node != NULL) foo = foo_node->content; These helpers reduce the above to one line. docs/reference/wocky-sections.txt | 2 ++ wocky/wocky-xmpp-node.c | 40 +++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-node.h | 8 ++++++++ 3 files changed, 50 insertions(+) commit f0d71429ea4111170f667868c3d161554da4a600 Author: Will Thompson Date: Wed Mar 24 21:18:18 2010 +0000 Make form field generation data-driven. It's safer to drive this based on the type of the GValue rather than the type of the field. If the API user messes up and sets a list of values rather than a boolean, then, well, the server will get upset and tell them they're wrong. wocky/wocky-data-form.c | 111 +++++++++++++++--------------------------------- 1 file changed, 34 insertions(+), 77 deletions(-) commit d9cb86374cf098863de68e25b3b29c899d1d3044 Author: Will Thompson Date: Wed Mar 24 20:36:16 2010 +0000 Add helpers to set data form fields' values Rootling around in a hash table to fish out the right struct and then replacing one of its members looked kind of strange. This is more obvious and easier. The API also supports filling in fields that the WockyDataForm object doesn't know about; this is to support blindly submitting forms with well-known fields (such as PubSub configuration) without having to first ask the server for the form. This patch also adds a test for such blind submission. tests/wocky-data-form-test.c | 123 +++++++++++++++++++++++++++++++------ tests/wocky-pubsub-service-test.c | 15 ++--- wocky/wocky-data-form.c | 124 +++++++++++++++++++++++++++++++++++--- wocky/wocky-data-form.h | 15 +++++ 4 files changed, 244 insertions(+), 33 deletions(-) commit e97bf5cba32d8b8bbb28a6be23c8f547d751129d Author: Will Thompson Date: Wed Mar 24 19:52:21 2010 +0000 Parse each form field using a node iterator. I think this makes the code a lot clearer. wocky/wocky-data-form.c | 59 +++++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 24 deletions(-) commit 6ab8b7622f8e00a0c100fa5a218b932f67530dd1 Author: Will Thompson Date: Wed Mar 24 19:08:57 2010 +0000 Allow fields' type to be unspecified when submitting. When we parse incoming forms, we never produce fields with unspecified type: if the XML doesn't specify the type, we default to text-single as specified by XEP-0004. This is not completely satisfactory: when parsing a form result, we should be able to pre-seed the WockyDataForm object with prior knowledge about the types of fields. But it'll do for now. When submitting a form, we allow fields to have unspecified type, and submit them with no type='' attribute. Quoth XEP-0004: > For data forms of type "submit", inclusion of the 'type' attribute is > OPTIONAL, since the form-processing entity is assumed to understand > the data types associated with forms that it processes. wocky/wocky-data-form.c | 38 ++++++++++++++++++++++++++++++++++++-- wocky/wocky-data-form.h | 1 + 2 files changed, 37 insertions(+), 2 deletions(-) commit 889fa983b3a959c15de2a24debb8457f783c1f11 Author: Will Thompson Date: Wed Mar 24 19:04:49 2010 +0000 Support parsing fields with no type='' XEP-0004 specifies that fields in forms of type='form' (that is, the form being presented to you by the server) which have no type='' attribute default to being text-single. tests/wocky-data-form-test.c | 18 ++++++++++++++++-- wocky/wocky-data-form.c | 14 ++++++++------ 2 files changed, 24 insertions(+), 8 deletions(-) commit 9499619a157cd9003491f355ff12e0df45d9a00d Author: Will Thompson Date: Wed Mar 24 16:09:25 2010 +0000 Rename WockyDataForms to WockyDataForm While XEP-0004 is plural, the class in Wocky represents a singular form. tests/Makefile.am | 8 +- tests/wocky-data-form-test.c | 712 +++++++++++++++++++++++++++++ tests/wocky-data-forms-test.c | 712 ----------------------------- tests/wocky-pubsub-service-test.c | 36 +- wocky/Makefile.am | 8 +- wocky/wocky-data-form.c | 811 +++++++++++++++++++++++++++++++++ wocky/wocky-data-form.h | 130 ++++++ wocky/wocky-data-forms.c | 811 --------------------------------- wocky/wocky-data-forms.h | 130 ------ wocky/wocky-debug.c | 2 +- wocky/wocky-debug.h | 2 +- wocky/wocky-pubsub-service-protected.h | 2 +- wocky/wocky-pubsub-service.c | 16 +- wocky/wocky-pubsub-service.h | 6 +- 14 files changed, 1693 insertions(+), 1693 deletions(-) commit f902b05fd579f30ed35114e95a5f60eeb1991646 Author: Will Thompson Date: Wed Mar 24 13:37:20 2010 +0000 Extract wocky_pubsub_node_make_delete_stanza() wocky/wocky-pubsub-node-protected.h | 4 ++++ wocky/wocky-pubsub-node.c | 36 ++++++++++++++++++++++++++++-------- 2 files changed, 32 insertions(+), 8 deletions(-) commit 2c7531fed7abf7ea154cf69ab7516d282f52ad3f Author: Will Thompson Date: Wed Mar 24 13:07:23 2010 +0000 Refactor the bulk of parsing create node replies This allows subclasses to reuse it. wocky/wocky-pubsub-service-protected.h | 7 +++ wocky/wocky-pubsub-service.c | 86 +++++++++++++++++++++------------- 2 files changed, 60 insertions(+), 33 deletions(-) commit 525126fe39bb4aa48e1546336d6d82f3dea29e3b Author: Will Thompson Date: Wed Mar 24 02:13:14 2010 +0000 Deal with empty replies to create_node() When you ask a pubsub server to create you a node, in some circumstances the IQ result contains , and in some circumstances it does not: • If you included a NodeID in your request, and the server did exactly as you asked and created that node, there's no need to include any information in the result's body as you already know what it would contain. (XEP-0060 actually goes further than this, and says that the result MUST NOT have a body in this case, which seems overzealous.) • If you included a NodeID in your request, but the server created a node with a different NodeID, then it MUST include a body in the result to tell you the node's actual ID. • If you did not include a NodeID in your request (to create an "instant node"), the server MUST include a body in the result to tell you the ID it decided to use. We previously assumed that the result contains a body, so the first case above wouldn't work with a fully-pedantic server. This patch fixes the tests to test that case, fixes the implementation to support that case, and adds a test for the second case. tests/wocky-pubsub-service-test.c | 76 ++++++++++++++++++++++++++++++++------- wocky/wocky-pubsub-service.c | 36 ++++++++++++++----- 2 files changed, 92 insertions(+), 20 deletions(-) commit f6f96522cc9ff0e7541f6087f254e62900454fbf Author: Will Thompson Date: Wed Mar 24 02:09:21 2010 +0000 Add and use new variants of pubsub_distill_iq_reply Often, you don't care at all about what the iq reply contains, only whether it's a result or an error. wocky_pubsub_distill_void_iq_reply() deals with that case more clearly than the caller passing three NULL arguments to wocky_pubsub_distill_iq_reply(). Additionally, there exist cases where you're interested in the reply's body if it's present, but the reply being empty is not an error. wocky_pubsub_distill_ambivalent_iq_reply() handles this case. They are all implemented in terms of a slightly enhanced version of the former body of wocky_pubsub_distill_iq_reply(). wocky/wocky-pubsub-helpers.c | 126 ++++++++++++++++++++++++++++++++++++++----- wocky/wocky-pubsub-helpers.h | 11 ++++ wocky/wocky-pubsub-node.c | 4 +- 3 files changed, 127 insertions(+), 14 deletions(-) commit ef53f61d5354999d0d934d4eacdc83d76fdde4ca Author: Will Thompson Date: Tue Mar 23 18:32:03 2010 +0000 Don't include empty when creating a node XEP-0060 §8.1.2 Create a Node With Default Configuration says we should just send if we don't want to deviate from the default configuration. wocky/wocky-pubsub-service.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) commit 1913db9081a8f3269d4287294f2ec45fedc8fba7 Author: Will Thompson Date: Tue Mar 23 18:29:25 2010 +0000 Extract a create_create_node_stanza() helper I'm so happy these helpers create complete stanzas rather than just WockyXmppNodes or the name would be ridiculous. wocky/wocky-pubsub-service-protected.h | 7 ++++++ wocky/wocky-pubsub-service.c | 43 ++++++++++++++++++++++++---------- 2 files changed, 38 insertions(+), 12 deletions(-) commit d9fa8f017ae22875a126b46d313b7bb097b509b9 Author: Will Thompson Date: Tue Mar 23 18:27:53 2010 +0000 Rename an internal PubsubService helper function create_node() clashed with a name I wanted to use for a WockyXmppNode * for a element. It is unfortunate that node means two things. :( wocky/wocky-pubsub-service.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit f03f7f02d34ed55e9c2d5dc56f5f606d064088a6 Author: Will Thompson Date: Tue Mar 23 17:59:02 2010 +0000 Properly initialize an out parameter wocky/wocky-pubsub-service.c | 3 +++ 1 file changed, 3 insertions(+) commit 256591691c38f7b6fa99c18e71fb4ec764373a84 Author: Simon McVittie Date: Tue Mar 23 15:17:34 2010 +0000 wocky_absolutize_path: check for errors and perhaps return NULL Both callers already check for NULL, so this is OK wocky/wocky-utils.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) commit 875970a858a8a3769af9e0266ac6db274fb49f74 Author: Simon McVittie Date: Tue Mar 23 15:10:42 2010 +0000 Replace uses of realpath() with a portable GFile-based version This doesn't resolve symlinks, because we don't really need to; it just makes the filename absolute. Loosely based on code from Ole André Vadla Ravnås on fd.o #27244. wocky/wocky-connector.c | 4 ++-- wocky/wocky-utils.c | 30 ++++++++++++++++++++++++++++-- wocky/wocky-utils.h | 2 ++ 3 files changed, 32 insertions(+), 4 deletions(-) commit 2dbbccf6744b448edda23b3f7acb666e70667a74 Author: Simon McVittie Date: Tue Mar 23 14:52:34 2010 +0000 Parse MUC timestamps using g_time_val_from_iso8601, for portability Windows doesn't have strptime. Based on code from Ole André Vadla Ravnås , and on code I wrote in a telepathy-gabble branch. wocky/wocky-muc.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) commit 5b4a65885d363e228c3a848407bfc1d6fb5664c4 Author: Simon McVittie Date: Tue Mar 23 14:35:23 2010 +0000 wocky-openssl: in error_to_string, remove casts made unnecessary by Ole Andre's patch wocky/wocky-openssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 224b568589a851924b6a2ee1a27065ae8d98e84e Author: Ole André Vadla Ravnås Date: Mon Mar 22 16:28:33 2010 +0100 Fix error_to_string() crash Declaring the static ssl_error array as const means that it may be read- only at runtime, which is not what you want in this case. Reviewed-by: Simon McVittie wocky/wocky-openssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit a4a5211f12699cf85ad43d839254d2dc97132a0f Author: Ole André Vadla Ravnås Date: Mon Mar 22 16:26:35 2010 +0100 Replace isXXX() with g_ascii_isXXX() to improve portability Reviewed-by: Simon McVittie wocky/wocky-openssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 1e370d3be9ea5e14f0b24464cec387c78c9977ab Author: Ole André Vadla Ravnås Date: Mon Mar 22 16:25:56 2010 +0100 Avoid C99 named initializers MSVC doesn't support C99. Reviewed-by: Simon McVittie wocky/wocky-sasl-handler.c | 19 ++++++++++--------- wocky/wocky-xmpp-reader.c | 37 ++++++++++++++++++++++++++++++++----- 2 files changed, 42 insertions(+), 14 deletions(-) commit 336bbbb4d1ca1dc04161307544939131c54e9f1e Author: Ole André Vadla Ravnås Date: Mon Mar 22 16:25:20 2010 +0100 Replace CA/CRL stat logic with g_file_test to improve portability Reviewed-by: Simon McVittie wocky/wocky-openssl.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) commit 2b974812dd00dac400db215c42b9dfa283ac56f8 Author: Ole André Vadla Ravnås Date: Mon Mar 22 16:24:08 2010 +0100 Fix OpenSSL include issue on Windows OpenSSL's Windows headers apparently require windows.h to be included before including them. Yikes. Reviewed-by: Simon McVittie wocky/wocky-openssl.c | 5 +++++ 1 file changed, 5 insertions(+) commit 4d8143fae323fd81331811024a694f855ff7ce30 Author: Ole André Vadla Ravnås Date: Mon Mar 22 16:21:14 2010 +0100 Fix warnings related to DEBUG() usage without arguments Reviewed-by: Simon McVittie wocky/wocky-openssl.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) commit b103a1940c2719123fff4e3ce79d4b76d21b70ce Author: Ole André Vadla Ravnås Date: Mon Mar 22 16:19:44 2010 +0100 Add a missing cast to make MSVC a bit happier warning-wise Reviewed-by: Simon McVittie wocky/wocky-muc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 5669b94e7d0f22e5b7b0df861368a5228723fda7 Author: Ole André Vadla Ravnås Date: Mon Mar 22 16:19:00 2010 +0100 Fix a trivial warning where guint was used instead of WockyTLSCertStatus Reviewed-by: Simon McVittie wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit fac774c5a3d09d51a16680eb7422f73b87bb86c2 Author: Simon McVittie Date: Tue Mar 23 14:32:33 2010 +0000 In the files touched by Ole Andre's patch, put headers in the preferred order * config.h first of all * header corresponding to the source next, to verify self-containedness * system headers next, followed by conditional system headers (with a bit more whitespace for clarity) * library and internal headers last wocky/wocky-bare-contact.c | 12 +++++++----- wocky/wocky-connector.c | 10 ++++++---- wocky/wocky-contact-factory.c | 8 +++++--- wocky/wocky-contact.c | 10 ++++++---- wocky/wocky-openssl.c | 7 ++++--- wocky/wocky-porter.c | 10 ++++++---- wocky/wocky-resource-contact.c | 10 ++++++---- wocky/wocky-session.c | 9 +++++---- wocky/wocky-xmpp-connection.c | 10 ++++++---- 9 files changed, 51 insertions(+), 35 deletions(-) commit a4747da6af62731cbb5b77261064bef212691f29 Author: Ole André Vadla Ravnås Date: Mon Mar 22 16:15:37 2010 +0100 Don't include unistd.h unless available Reviewed-by: Simon McVittie wocky/wocky-bare-contact.c | 6 ++++++ wocky/wocky-connector.c | 6 ++++++ wocky/wocky-contact-factory.c | 6 ++++++ wocky/wocky-contact.c | 6 ++++++ wocky/wocky-openssl.c | 6 ++++++ wocky/wocky-porter.c | 5 +++++ wocky/wocky-resource-contact.c | 6 ++++++ wocky/wocky-session.c | 6 ++++++ wocky/wocky-xmpp-connection.c | 5 +++++ 9 files changed, 52 insertions(+) commit a59c4bf130f689e60c8a9ec4ce5e987aa00b7d83 Author: Simon McVittie Date: Tue Mar 23 14:30:59 2010 +0000 configure.ac: check for unistd.h configure.ac | 1 + 1 file changed, 1 insertion(+) commit aeac3aa08def7fd47e1a432005706433ff281440 Author: Simon McVittie Date: Tue Mar 23 14:30:51 2010 +0000 configure.ac: work around mis-syntax-highlighting of apostrophe configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit bc9ae907cacffde000bb7daecaa4069cb00d5d83 Author: Will Thompson Date: Thu Mar 18 16:19:48 2010 +0000 Make multi-line variables consistent The right-aligned backslashes are great and all, but when you add a new header that's longer (as I did with wocky-pubsub-service-protected.h) you have to adjust the whole list or it becomes inconsistent. Also the wocky-muc.c entry had a whole bunch of tabs rather than spaces which made it not line up anyway. wocky/Makefile.am | 118 +++++++++++++++++++++++++++--------------------------- 1 file changed, 59 insertions(+), 59 deletions(-) commit 6fdcb861bd5d01093b0ce2c2d5998df0595410cb Author: Will Thompson Date: Tue Mar 16 19:32:16 2010 +0000 pep-service: don't crash on disconnect during retrieval If 'reply' is NULL, we shouldn't set it as the operation result with g_object_unref() as its destructor, since the latter doesn't like being passed NULL. I've checked other uses of g_simple_async_result_set_op_res_gpointer() in Wocky, and they're fine. Reviewed-by: Simon McVittie tests/wocky-pep-service-test.c | 33 +++++++++++++++++++++++++++++++-- wocky/wocky-pep-service.c | 5 ++++- 2 files changed, 35 insertions(+), 3 deletions(-) commit 9252f908ac24709e3b0486a5d6617d6f07a80eaf Merge: 8f2fc98 582b5bb Author: Will Thompson Date: Tue Mar 16 17:14:44 2010 +0000 Merge branch 'moar-pubsub' Reviewed-by: Guillaume Desmottes commit 8f2fc98a0f82ef29d26b59421299a121449ee70b Merge: c83b003 adf2974 Author: Simon McVittie Date: Mon Mar 15 16:42:09 2010 +0000 Merge branch 'trivia' Reviewed-by: Will Thompson commit adf29749f3e858df506cbe1cabcf1f4ca289352c Author: Simon McVittie Date: Mon Mar 15 16:37:17 2010 +0000 Ignore the distcheck working directory as well as the tarball .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 6eb4cfea44bf8d76325e4aa16dfe82cf5ba9481f Author: Simon McVittie Date: Mon Mar 15 16:35:53 2010 +0000 Distribute some missing files Adding summarise-tests.py fixes distcheck; the others might not be needed, but it's easier to add them than to think about whether they're desirable. This patch results in everything in git, except .gitignore, being distributed. Makefile.am | 2 ++ tests/Makefile.am | 3 +++ 2 files changed, 5 insertions(+) commit c83b0039e531eaf940a7fb458b6a2d7d02630ec4 Merge: a6a9213 bf6a955 Author: Simon McVittie Date: Mon Mar 15 16:22:16 2010 +0000 Merge branch 'docs' Reviewed-by: Will Thompson Bug: http://bugs.freedesktop.org/show_bug.cgi?id=24941 commit bf6a95513fa1d8b7e37a7cff7e87a7f786a270c4 Author: Simon McVittie Date: Mon Mar 15 14:42:32 2010 +0000 wocky_xmpp_node_each_child_func: use correct English Spotted during wjt's review wocky/wocky-xmpp-node.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 49b110c06e8fb005757820db1e9933ca6df186ef Author: Simon McVittie Date: Mon Mar 15 14:41:50 2010 +0000 WockyPorter: clarify refcounting/returns as per wjt's review wocky/wocky-porter.c | 3 ++- wocky/wocky-porter.h | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) commit 582b5bba4aa5e0fbc90c8f58178cc396712ccb14 Author: Will Thompson Date: Sat Mar 13 12:42:45 2010 +0000 Style: newline after return type in definition wocky/wocky-pubsub-service.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 2938044744c8ea032c505c4b8fcd620e0f49507d Author: Will Thompson Date: Sat Mar 13 12:42:32 2010 +0000 Document and sanity-check node_object_type wocky/wocky-pubsub-service.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) commit 28ef5c184ce86717f7ee4144ca75473e830e2768 Author: Will Thompson Date: Sat Mar 13 12:42:22 2010 +0000 Document WockyPubsubSubscription wocky/wocky-pubsub-service.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) commit 00e0984b208b6653baa50f804578b202d8c2a419 Author: Will Thompson Date: Tue Mar 9 15:42:45 2010 +0000 pubsub_distill_iq_reply(): understand empty replies A bunch of pubsub actions don't need to actually return you anything in the iq result if they succeed; making wocky_pubsub_distill_iq_reply() deal with this case allows me to delete even more code! Maybe WockyPubsubService should deal with this stuff, with a _send_action_async() method or something. wocky/wocky-pubsub-helpers.c | 13 +++++++------ wocky/wocky-pubsub-node.c | 29 +++++------------------------ 2 files changed, 12 insertions(+), 30 deletions(-) commit 126bb67ee3553542df79e178fe7edf825b18b108 Author: Will Thompson Date: Tue Mar 9 15:28:46 2010 +0000 Give WockyPubsub* subclasses access to porter wocky/wocky-pubsub-node-protected.h | 2 ++ wocky/wocky-pubsub-node.c | 8 ++++++++ wocky/wocky-pubsub-service-protected.h | 2 ++ wocky/wocky-pubsub-service.c | 8 ++++++++ 4 files changed, 20 insertions(+) commit ac2ffa3b9d07e874c58037a62c93d55308ab69fe Author: Will Thompson Date: Tue Mar 9 14:24:20 2010 +0000 _make_publish_stanza(): also return the node This brings it into line with the other make_foo_stanza() methods. tests/wocky-pubsub-node-test.c | 12 ++++++++---- wocky/wocky-pep-service.c | 2 +- wocky/wocky-pubsub-helpers.c | 8 +++++++- wocky/wocky-pubsub-helpers.h | 1 + wocky/wocky-pubsub-node.c | 3 ++- wocky/wocky-pubsub-node.h | 1 + 6 files changed, 20 insertions(+), 7 deletions(-) commit 9fe32f1815427ca3f118247a71d136b3f35192bc Author: Will Thompson Date: Mon Mar 8 17:58:05 2010 +0000 Support unsubscribing from PubSub nodes tests/wocky-pubsub-node-test.c | 110 ++++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-node-protected.h | 7 +++ wocky/wocky-pubsub-node.c | 105 ++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-node.h | 12 ++++ 4 files changed, 234 insertions(+) commit f1133390bfa38378f98e9dce38380cb083daf8f4 Author: Will Thompson Date: Mon Mar 8 17:49:16 2010 +0000 Generalize making a pubsub action for a node wocky/wocky-pubsub-node.c | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) commit 21f4cf4787b638d4117883853adbbc964d8dc5d4 Author: Will Thompson Date: Mon Mar 8 15:35:39 2010 +0000 Implement subscribing to nodes. tests/wocky-pubsub-node-test.c | 93 ++++++++++++++++++++++++++ wocky/wocky-pubsub-node-protected.h | 5 ++ wocky/wocky-pubsub-node.c | 126 ++++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-node.h | 11 ++++ 4 files changed, 235 insertions(+) commit 2f8b25b801abf2d644896beb38e12c0c576049e0 Author: Will Thompson Date: Fri Mar 5 19:53:43 2010 +0000 Allow _parse_subscription() to return an error wocky/wocky-pubsub-service-protected.h | 3 ++- wocky/wocky-pubsub-service.c | 29 ++++++++++++++++++++--------- 2 files changed, 22 insertions(+), 10 deletions(-) commit b3dcc54540cd156541ead7ab3701453bc9991ddc Author: Will Thompson Date: Fri Mar 5 18:36:33 2010 +0000 Expose parsing a node This will be needed by wocky_pubsub_node_subscribe, since a request returns a node. wocky/wocky-pubsub-service-protected.h | 5 ++ wocky/wocky-pubsub-service.c | 93 ++++++++++++++++++++-------------- 2 files changed, 60 insertions(+), 38 deletions(-) commit 1553b3db8841fb5b70b8bd1ab7687e06b2dc4e47 Author: Will Thompson Date: Fri Mar 5 00:57:16 2010 +0000 Allow PubsubService subclasses to use PubsubNode subclasses wocky/wocky-pubsub-service.c | 5 ++++- wocky/wocky-pubsub-service.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) commit a52dc2d83659da4d83447376c6fdb25561b4ba52 Author: Will Thompson Date: Fri Mar 5 00:38:06 2010 +0000 Remove wocky_pubsub_node_new() WockyPubsubNodes should only be made through wocky_pubsub_service_ensure_node(); otherwise you could end up with two objects for one node on a service, and only one of them would work. tests/wocky-pubsub-node-test.c | 4 ++-- wocky/wocky-pubsub-node.c | 10 ---------- wocky/wocky-pubsub-node.h | 3 --- wocky/wocky-pubsub-service.c | 5 ++++- 4 files changed, 6 insertions(+), 16 deletions(-) commit a7e722758ae4cc01817ca66f12d91d2265e88251 Author: Will Thompson Date: Thu Mar 4 17:56:29 2010 +0000 Return nodes from parse_subscriptions wocky/wocky-pubsub-service-protected.h | 3 ++- wocky/wocky-pubsub-service.c | 12 ++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) commit b6d5b2863eb3a20f46d4d4f47f0b5907879431b2 Author: Will Thompson Date: Thu Mar 4 16:12:00 2010 +0000 Make helpers for listing/parsing pubsub subscriptions The intention is that subclasses of WockyPubsubService that need to add and understand additional service-specific metadata for subscriptions can use these helpers to implement variations on the theme of _retrieve_subscriptions_async(). wocky/Makefile.am | 1 + wocky/wocky-pubsub-service-protected.h | 35 ++++++++++++++++++++++++++ wocky/wocky-pubsub-service.c | 46 ++++++++++++++++++++++++++-------- 3 files changed, 71 insertions(+), 11 deletions(-) commit 1be89ca78a495002a3ee4b7fa27bc25f736b34c8 Author: Will Thompson Date: Mon Mar 1 19:24:40 2010 +0000 Support retrieving pubsub subscriptions tests/wocky-pubsub-service-test.c | 268 ++++++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-service.c | 144 ++++++++++++++++++++ wocky/wocky-pubsub-service.h | 13 ++ 3 files changed, 425 insertions(+) commit f5218415dba8e876ef88855df13f3be85ecc85ea Author: Will Thompson Date: Mon Mar 1 19:24:27 2010 +0000 Add types representing PubSub subscriptions wocky/Makefile.am | 2 ++ wocky/wocky-pubsub-service.c | 69 ++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-service.h | 31 ++++++++++++++++++++ 3 files changed, 102 insertions(+) commit c480a70d0951ec143bda26013c47536ad8dfeec6 Author: Will Thompson Date: Mon Mar 1 14:02:51 2010 +0000 Add a test helper to compare two stanzas This is a slightly evil macro that asserts that two stanzas are equal, except if they differ only in that one has no id and the other has an id. It achieves this by, erm, copying the id onto the other stanza. Whatever, this is test code. tests/wocky-test-helper.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) commit 3ea6d54ec8f087dec2d36072f7addeee6df219db Author: Will Thompson Date: Mon Mar 1 11:38:31 2010 +0000 Refactor common pubsub reply-handling code wocky/wocky-pubsub-helpers.c | 81 ++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-helpers.h | 9 ++++ wocky/wocky-pubsub-service.c | 101 ++++++++++--------------------------------- 3 files changed, 112 insertions(+), 79 deletions(-) commit e15c0d1f633fe62f64a48a7b118ca4f5d8abf07a Author: Will Thompson Date: Sun Feb 28 15:05:52 2010 +0000 Add WockyPubsubService::event-received This signal proxies the corresponding signal on the node, so that clients that care about events on all nodes can just listen once to the service. tests/wocky-pubsub-node-test.c | 78 ++++++++++++++++++++++----- wocky/Makefile.am | 3 +- wocky/wocky-pubsub-node-protected.h | 29 ++++++++++ wocky/wocky-pubsub-node.c | 9 ++++ wocky/wocky-pubsub-service.c | 103 ++++++++++++++++++++++++++++++++++-- 5 files changed, 204 insertions(+), 18 deletions(-) commit cadd1057187cad127033db7bbf8d2942d56727de Merge: 7543638 a6a9213 Author: Simon McVittie Date: Tue Mar 9 17:44:33 2010 +0000 Merge remote branch 'origin/master' into docs commit 7543638c250da89b04531de68e7c3e3507f179d5 Author: Simon McVittie Date: Tue Mar 9 17:44:31 2010 +0000 wocky_xmpp_node_attribute_ns_get_prefix_from_quark: improve description of @ns wocky/wocky-xmpp-node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 6b16fa44543830f8359c9acfdecd3f5138ab45ca Author: Simon McVittie Date: Tue Mar 9 17:28:58 2010 +0000 Add WockyPubsubNode, WockyPubsubService to docs docs/reference/wocky-sections.txt | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) commit 6756c8bd458be280507ed93711b793d44e29df09 Author: Simon McVittie Date: Tue Mar 9 17:28:44 2010 +0000 Don't hide wocky_data_forms_get_instructions (etc.) in a docs/reference/wocky-sections.txt | 1 + 1 file changed, 1 insertion(+) commit c3c496e5e54fcdb623f0cfb087cbf671dbfffbf1 Author: Simon McVittie Date: Tue Mar 9 17:28:26 2010 +0000 Add misc missing stuff to wocky-sections docs/reference/wocky-sections.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) commit 4a10284ff6439933a9e6d9bfcb80b15b737e86f4 Author: Simon McVittie Date: Tue Mar 9 17:24:14 2010 +0000 docs: s/in case/if/ for better en_GB "In case" generally implies preparation for a future event that might break things if we don't prepare for it; that's not what's happening here. wocky/wocky-contact-factory.c | 4 ++-- wocky/wocky-sasl-handler.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) commit a6a921374deedb2446d27f81f2dbaf2fd5999ede Author: Cosimo Cecchi Date: Fri Nov 6 16:27:03 2009 +0100 Fix a typo. wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 94915ea0c31ab844f0182c03c39652c724e0267b Author: Cosimo Cecchi Date: Wed Nov 4 17:52:32 2009 +0100 Write gtk-doc entries for WockyBareContact. wocky/wocky-bare-contact.c | 82 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 4 deletions(-) commit be66d223e4368789176457f06aafedc0610d4b97 Author: Simon McVittie Date: Tue Mar 9 17:18:21 2010 +0000 wocky_porter_force_close_async: use pedantically-correct gtk-doc markup wocky/wocky-porter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit ea435c1231415ada3bf1a94a15c20f92a4bb71ef Author: Simon McVittie Date: Tue Mar 9 17:18:05 2010 +0000 Fix typo matchig -> matching as per my review wocky/wocky-porter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 230cfe7ec0ae458058eff969b1cc147dfad8c1f1 Author: Simon McVittie Date: Tue Mar 9 17:17:51 2010 +0000 WockyPorter::remote-error: clarify that the error domain is indeed a quark As per my review of cosimoc's branches wocky/wocky-porter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit af2e70ba023e176eb42dac2d16f9072f216264b5 Author: Simon McVittie Date: Tue Mar 9 17:17:26 2010 +0000 WockyContactFactory: make object ownership explicit, fix typo (an -> a) as per my review wocky/wocky-contact-factory.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) commit 04b0445c24a9dbccaa5fff514f8ba9e76946b221 Author: Simon McVittie Date: Tue Mar 9 17:09:47 2010 +0000 Misc doc fixes. (cherry picked from commit 76db761b404f8c2817e8d87fc07dce8645ac6e92) Conflicts: wocky/wocky-porter.c (wocky_porter_register_handler) wocky/wocky-utils.c (discarded cosimoc's change in favour of master) Merged: by smcv wocky/wocky-porter.c | 3 ++- wocky/wocky-xmpp-connection.c | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) commit 8762453c06e150161c952e15947a59263ee91df5 Author: Cosimo Cecchi Date: Fri Nov 6 16:27:03 2009 +0100 Fix a typo. (cherry picked from commit 0492a6e7ccd09d7f0ef3ece36c66619f602ed5e5) wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 10671c67412210b11d3e81eb0f16b134f7a80f86 Author: Simon McVittie Date: Tue Mar 9 17:04:00 2010 +0000 Add docs for WockyXmppNode. (cherry picked from commit 14e4892c3e53bf629c641bded38d70508b09b43c) Conflicts: wocky/wocky-xmpp-node.c wocky/wocky-xmpp-node.c | 301 +++++++++++++++++++++++++++++++++++++++++++++++- wocky/wocky-xmpp-node.h | 23 +++- 2 files changed, 319 insertions(+), 5 deletions(-) commit a8e1ce40d8ee132cd86ec2372a38ae4e3b3fb473 Merge: 158e7fd e1a9100 Author: Simon McVittie Date: Tue Mar 9 17:01:42 2010 +0000 Merge remote branch 'cosimoc/doc-contactfactory' into docs Conflicts: wocky/wocky-porter.c (wocky_porter_register_handler) commit 158e7fdeae13a42bfa3c386f3a4a18df4c5ae98a Merge: 4b94801 d79eac9 Author: Simon McVittie Date: Tue Mar 9 16:39:04 2010 +0000 Merge remote branch 'cosimoc/doc-barecontact' commit ec8d9c1d8fa0f9eda898ab5678369dea39a83c58 Author: Will Thompson Date: Sat Feb 27 16:54:56 2010 +0000 Fix leaks in PubsubService tests tests/wocky-pubsub-service-test.c | 9 +++++++++ 1 file changed, 9 insertions(+) commit 86a98d16d3ef721ff3e8b7d61cb627add84fcc8e Author: Will Thompson Date: Fri Feb 26 16:37:18 2010 +0000 Don't leak porters and test in PubsubNode test tests/wocky-pubsub-node-test.c | 3 +++ 1 file changed, 3 insertions(+) commit f5f0528f7b2bc3b680f4e909d23388130bb39618 Author: Will Thompson Date: Fri Feb 26 16:35:44 2010 +0000 Add WockyPubsubNode::event-received tests/wocky-pubsub-node-test.c | 2 ++ wocky/wocky-pubsub-node.c | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) commit 0da5ed9215c627f9152f91ebd12f01f54bac2c7c Author: Will Thompson Date: Fri Feb 26 16:18:32 2010 +0000 Add an event-received signal to WockyPubsubNode tests/wocky-pubsub-node-test.c | 106 +++++++++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-node.c | 74 ++++++++++++++++++++++++++-- 2 files changed, 176 insertions(+), 4 deletions(-) commit 395b194f25f9418a7f7a110991042166a0fe5c66 Author: Will Thompson Date: Fri Feb 26 12:43:16 2010 +0000 Add wocky_pubsub_node_make_publish_stanza() tests/wocky-pubsub-node-test.c | 61 ++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-node.c | 16 +++++++++-- wocky/wocky-pubsub-node.h | 4 +++ 3 files changed, 79 insertions(+), 2 deletions(-) commit 173c3b26217d7b4c4471b4f25193b5a593b40aa3 Author: Will Thompson Date: Thu Feb 25 14:49:16 2010 +0000 Extract publish stanza construction to a helper This will be useful in WockyPubsubNode as well as in WockyPepService. wocky/Makefile.am | 2 ++ wocky/wocky-pep-service.c | 14 ++------- wocky/wocky-pubsub-helpers.c | 70 ++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-helpers.h | 32 ++++++++++++++++++++ 4 files changed, 106 insertions(+), 12 deletions(-) commit 4b9480119aded3de3cf7d2e68f6eeb7c885289f7 Author: Simon McVittie Date: Wed Mar 3 19:57:12 2010 +0000 Correct typos detected by Lintian (separate, received) Reviewed-by: Youness Alaoui wocky/wocky-muc.c | 2 +- wocky/wocky-xmpp-connection.c | 2 +- wocky/wocky-xmpp-reader.c | 2 +- wocky/wocky-xmpp-writer.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) commit cd607211b1973b88e1683b762e22105618eab35f Author: Will Thompson Date: Mon Mar 1 16:27:53 2010 +0000 Don't crash on stanzas with type='error' but no Reviewed-by: Sjoerd Simons tests/wocky-xmpp-stanza-test.c | 20 +++++++++++++++++++- wocky/wocky-xmpp-stanza.c | 19 ++++++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) commit 8430bc66063c3dbcd26d23296e3c10cff7c25dd9 Merge: 6f2ee42 1a030af Author: Will Thompson Date: Fri Feb 26 12:40:32 2010 +0000 Merge branch 'trivia' Reviewed-by: Sjoerd Simons commit 6f2ee429d5a56122f8b37ab7d070cc8be4a72ab7 Merge: ef42dd2 54eac57 Author: Will Thompson Date: Fri Feb 26 11:18:22 2010 +0000 Merge branch 'pubsub' Reviewed-by: Sjoerd Simons Reviewed-by: Will Thompson commit 1a030afaf4f71c93b42a12f7eb5aca0b552f4ffa Author: Will Thompson Date: Thu Feb 25 15:42:17 2010 +0000 Use test_assert_nodes_[not_]equal() in tests This makes the assertion failures more useful tests/wocky-porter-test.c | 4 ++-- tests/wocky-test-helper.c | 2 +- tests/wocky-xmpp-node-test.c | 28 ++++++++++++++-------------- tests/wocky-xmpp-readwrite-test.c | 6 +++--- tests/wocky-xmpp-stanza-test.c | 10 +++++----- 5 files changed, 25 insertions(+), 25 deletions(-) commit 62508123b46ab8ed3e8fa9199a2ee63b219bc7d4 Author: Will Thompson Date: Thu Feb 25 15:37:20 2010 +0000 Add test_assert_nodes_not_equal() tests/wocky-test-helper.h | 9 +++++++++ 1 file changed, 9 insertions(+) commit f9a42286e5f376afd32f270ce28d51330284fee3 Author: Will Thompson Date: Thu Feb 25 15:34:50 2010 +0000 Move assert_nodes_equal to test-helper tests/wocky-test-helper.h | 9 +++++++++ tests/wocky-xmpp-stanza-test.c | 13 ++----------- 2 files changed, 11 insertions(+), 11 deletions(-) commit 99774c25e12869fa12a5ee49b306609f534e97bc Author: Will Thompson Date: Thu Feb 25 17:47:16 2010 +0000 Don't leave a porter_close_async() waiting tests/wocky-porter-test.c | 6 ++++++ 1 file changed, 6 insertions(+) commit ef42dd2a68567774cc970a4d6b1918f3f9a5a640 Merge: ef691f6 98d0bfa Author: Simon McVittie Date: Thu Feb 25 17:24:13 2010 +0000 Merge branch 'trivia' Reviewed-by: Sjoerd Simons commit 98d0bfa540b24083673126125339664ebf0ddd3e Author: Simon McVittie Date: Thu Feb 25 17:20:47 2010 +0000 wocky-connector-test: use g_get_current_dir instead of getcwd() PATH_MAX isn't defined on Hurd, so this was causing Gabble build failures on the Debian Hurd buildds. Similarly, use g_stat() and g_unlink() instead of plain stat() and unlink(), so that all of these consistently use the GLib filename encoding if/when Wocky is built on Windows. tests/wocky-connector-test.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) commit 014c1b70b252a5094dc51d3d4798e9b8245e894e Author: Simon McVittie Date: Thu Feb 25 17:14:08 2010 +0000 Don't try to include FIXME.out in git .gitignore | 2 ++ 1 file changed, 2 insertions(+) commit 93c6d27b0930a0f72e2de7bc824e74592fcfb657 Author: Simon McVittie Date: Thu Feb 25 17:13:48 2010 +0000 Fix various minor gtk-doc nits wocky/wocky-porter.h | 2 +- wocky/wocky-sasl-auth.c | 1 + wocky/wocky-sasl-handler.h | 12 +++++++++--- wocky/wocky-utils.c | 2 ++ wocky/wocky-xmpp-connection.c | 2 +- wocky/wocky-xmpp-connection.h | 2 +- wocky/wocky-xmpp-error.c | 4 ++-- wocky/wocky-xmpp-stanza.c | 8 +++++++- 8 files changed, 24 insertions(+), 9 deletions(-) commit 33ea2a8fc7baa62401820a9d73a57dff6f08be4b Author: Simon McVittie Date: Thu Feb 25 17:13:08 2010 +0000 wocky-docs.sgml: don't include XML for wocky-types, which is no longer of interest Everything in it is (almost by definition) documented somewhere else. docs/reference/wocky-docs.sgml | 1 - 1 file changed, 1 deletion(-) commit f0eced5cab2c84ade9739447409886477966989a Author: Simon McVittie Date: Thu Feb 25 17:12:36 2010 +0000 wocky-sections.txt: catch up with the current state of Wocky docs/reference/wocky-sections.txt | 270 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 257 insertions(+), 13 deletions(-) commit 5ea4b794e19c655f89c6717e6398ef513f003930 Author: Simon McVittie Date: Thu Feb 25 16:25:09 2010 +0000 autogen.sh: prefer Automake 1.11 if we have it Same process and rationale as for Gabble, tp-glib, etc. autogen.sh | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) commit d38daeeccafcf18eaf3857ac38875ea2efd19a6d Author: Simon McVittie Date: Wed Jan 13 18:22:04 2010 +0000 wocky-muc.h: don't include config.h config.h is not installed, so it's inappropriate to include it in public headers. wocky/wocky-muc.h | 2 -- 1 file changed, 2 deletions(-) commit 54eac5724786d8d2bb6fed491e95b44831ddea21 Author: Will Thompson Date: Thu Feb 25 14:20:15 2010 +0000 Correct _async/_finish implementations in WockyPubsub* Conventionally, the _async function is used as the source tag, not the _finish function. It is also valid for the _finish() function not to be called; the previous implementation of create_node would leak the WockyPubsubNode * in that case. wocky/wocky-pubsub-node.c | 12 ++++++------ wocky/wocky-pubsub-service.c | 24 +++++++++++++++--------- 2 files changed, 21 insertions(+), 15 deletions(-) commit d24be5005f34564de2f47eafa8c5e7b443d3b085 Author: Will Thompson Date: Wed Feb 24 18:58:32 2010 +0000 Document pubsub_service_{ensure,lookup}_node wocky/wocky-pubsub-service.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) commit 5056aca0697871f94cfc304b0bfcdaf0ac5220d4 Author: Will Thompson Date: Tue Feb 23 15:39:50 2010 +0000 Fix en_FR tests/wocky-pubsub-node-test.c | 2 +- tests/wocky-pubsub-service-test.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) commit 5999ed11d9bfbf6bcff572fc40f6425b16ab62ce Author: Guillaume Desmottes Date: Wed Sep 30 17:00:44 2009 +0100 test wocky_pubsub_node_delete_async tests/wocky-pubsub-node-test.c | 70 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) commit 50bf1002f93915d86045eb39d38bf974757630ef Author: Guillaume Desmottes Date: Wed Sep 30 17:00:30 2009 +0100 wocky-pubsub-node: add wocky_pubsub_node_delete_{async,finish} wocky/wocky-pubsub-node.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-node.h | 9 ++++++ 2 files changed, 86 insertions(+) commit d6b835bb6acc7ba29689efefed7f135bea0828c9 Author: Guillaume Desmottes Date: Wed Sep 30 16:59:30 2009 +0100 wocky-pubsub-node: get the service jid and the porter wocky/wocky-pubsub-node.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) commit 450508bf5c96c84c3e5deae6806ac8a8bcfe78e3 Author: Guillaume Desmottes Date: Wed Sep 30 15:56:15 2009 +0100 wocky-pubsub-service-test: create a node with configuration tests/wocky-pubsub-service-test.c | 142 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) commit 86223733beb7d98cfccc1fe6f17f578e56c05c60 Author: Guillaume Desmottes Date: Wed Sep 30 15:54:12 2009 +0100 wocky_pubsub_service_create_node_async: set config of the node if needed wocky/wocky-pubsub-service.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) commit 6e2bf9f6fb751f3a7ae7cd70eaa7c68d65e87605 Author: Guillaume Desmottes Date: Wed Sep 30 14:54:55 2009 +0100 wocky-pubsub-service-test: create an instant node tests/wocky-pubsub-service-test.c | 74 +++++++++++++++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 7 deletions(-) commit d8177462ee4aadc06eb12b0c897b60027cac63d8 Author: Guillaume Desmottes Date: Wed Sep 30 14:35:59 2009 +0100 wocky_pubsub_service_create_node_async: support instant node creation Instant nodes are created without specifying their name. So we need to parse the result stanza to get the name they received. tests/wocky-pubsub-service-test.c | 7 ++++++- wocky/wocky-pubsub-service.c | 43 +++++++++++++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 9 deletions(-) commit 75171c4b2fd1d87d938e64c5b9bf067d00ce0fcd Author: Guillaume Desmottes Date: Wed Sep 30 13:07:37 2009 +0100 create node IQ is a 'set', not a 'get' tests/wocky-pubsub-service-test.c | 2 +- wocky/wocky-pubsub-service.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) commit 31da79fdccf3980f6f35fa36aa1fc03f0086cdeb Author: Guillaume Desmottes Date: Tue Sep 29 17:47:22 2009 +0100 fix includes of Wocky files wocky/wocky-pubsub-node.c | 8 ++++---- wocky/wocky-pubsub-node.h | 7 ++++--- wocky/wocky-pubsub-service.c | 10 +++++----- wocky/wocky-pubsub-service.h | 9 +++++---- 4 files changed, 18 insertions(+), 16 deletions(-) commit 46f8b6856bb5ccec696b2b154ee284d09e163c9d Author: Guillaume Desmottes Date: Tue Sep 29 17:11:17 2009 +0100 wocky-pubsub-service-test: try to get default node conf and server returns a 'forbidden' error tests/wocky-pubsub-service-test.c | 62 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) commit 98ad3a56a2a8fd4742dd98b99077bc1d9e1f848c Author: Guillaume Desmottes Date: Tue Sep 29 17:10:48 2009 +0100 default_configuration_iq_cb: raise an error if server returned an error wocky/wocky-pubsub-service.c | 7 +++++++ 1 file changed, 7 insertions(+) commit 9e03ceafcc7c5cb61ae32ce4bcd14538657034d9 Author: Guillaume Desmottes Date: Tue Sep 29 16:57:16 2009 +0100 wocky-pubsub-service-test: factor out get_default_node_configuration_test tests/wocky-pubsub-service-test.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) commit 1efe4d57736eeb45605a9155c880f4f27a718c01 Author: Guillaume Desmottes Date: Tue Sep 29 16:47:58 2009 +0100 wocky-pubsub-service-test: try to create a node and server returns an 'unsupported' error tests/wocky-pubsub-service-test.c | 67 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) commit 14bac97ce3675b1559219a931ab078d86f66e79d Author: Guillaume Desmottes Date: Tue Sep 29 16:47:03 2009 +0100 create_node_iq_cb: raise an error if server returned an error wocky/wocky-pubsub-service.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) commit 89811fce9caeac315cc32c93b4d77d90284ef187 Author: Guillaume Desmottes Date: Tue Sep 29 16:46:12 2009 +0100 wocky-namespaces: add WOCKY_XMPP_NS_PUBSUB_ERRORS wocky/wocky-namespaces.h | 3 +++ 1 file changed, 3 insertions(+) commit 6819d046813de3e88e8ea0ea20f9c40a961c97d3 Author: Guillaume Desmottes Date: Tue Sep 29 16:26:29 2009 +0100 wocky-pubsub-service-test: factor out create_node_test tests/wocky-pubsub-service-test.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) commit f76c88c41da053a36924c6842a8bbf62ef8999f7 Author: Guillaume Desmottes Date: Tue Sep 29 16:02:00 2009 +0100 wocky-pubsub-service-test: test to create a node with default configuration tests/wocky-pubsub-service-test.c | 74 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) commit 60d677e16bbd056cb0ec531de6269f4acf3b48ae Author: Guillaume Desmottes Date: Tue Sep 29 16:01:29 2009 +0100 add wocky_pubsub_service_create_node_{async,finish} to create a new node wocky/wocky-pubsub-service.c | 94 ++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-service.h | 12 ++++++ 2 files changed, 106 insertions(+) commit a0c5ea4b8a677efc647bf9837a872bbc354844df Author: Guillaume Desmottes Date: Tue Sep 29 15:49:39 2009 +0100 wocky-pubsub-node: add wocky_pubsub_node_get_name tests/wocky-pubsub-node-test.c | 2 ++ wocky/wocky-pubsub-node.c | 8 ++++++++ wocky/wocky-pubsub-node.h | 2 ++ 3 files changed, 12 insertions(+) commit 689449298ceb08c82c5469296128d92acb5d2401 Author: Guillaume Desmottes Date: Tue Sep 29 14:22:50 2009 +0100 wocky-pubsub-service-test: test wocky_pubsub_service_get_default_node_configuration_async tests/wocky-pubsub-service-test.c | 101 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) commit 0730d29b7b42d0291f7262dd834c86dcde1b7ac2 Author: Guillaume Desmottes Date: Tue Sep 29 14:22:29 2009 +0100 add wocky_pubsub_service_get_default_node_configuration_{async,finish} wocky/wocky-pubsub-service.c | 114 +++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-service.h | 20 ++++++++ 2 files changed, 134 insertions(+) commit dd03536c9dbb1dc992d56d028426dc1c0daded14 Author: Guillaume Desmottes Date: Tue Sep 29 14:18:08 2009 +0100 wocky-pubsub-service: get the porter from the session wocky/wocky-pubsub-service.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 60ea8f5cc2cd4685f8fbdf30cffefd212f8c0040 Author: Guillaume Desmottes Date: Tue Sep 29 14:17:23 2009 +0100 wocky-namespaces.h: add NS_PUBSUB_OWNER and NS_PUBSUB_NODE_CONFIG wocky/wocky-namespaces.h | 6 ++++++ 1 file changed, 6 insertions(+) commit a7f5b70e57d420c0c1e5b8838d224ce0a35a95a2 Author: Guillaume Desmottes Date: Tue Sep 22 13:32:12 2009 +0100 test wocky_pubsub_service_ensure_node tests/wocky-pubsub-service-test.c | 50 +++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 5 deletions(-) commit 11cae978448ca2a080c5cb41699798b53fa1b1a5 Author: Guillaume Desmottes Date: Tue Sep 22 13:32:06 2009 +0100 add wocky_pubsub_service_{ensure,lookup}_node wocky/wocky-pubsub-service.c | 66 ++++++++++++++++++++++++++++++++++++++++++-- wocky/wocky-pubsub-service.h | 7 +++++ 2 files changed, 71 insertions(+), 2 deletions(-) commit 3289d40c3213ca725184fba2c6397ddcb86855f3 Author: Guillaume Desmottes Date: Tue Sep 22 11:48:06 2009 +0100 add wocky-pubsub-node-test.c .gitignore | 2 ++ tests/Makefile.am | 7 ++++++ tests/wocky-pubsub-node-test.c | 54 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) commit 426c96d4592cce2d967ed81677798e6a9076e6b4 Author: Guillaume Desmottes Date: Tue Sep 22 11:47:41 2009 +0100 add wocky-pubsub-node.[ch] wocky/Makefile.am | 4 +- wocky/wocky-pubsub-node.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-node.h | 64 +++++++++++++++ wocky/wocky-types.h | 1 + 4 files changed, 267 insertions(+), 1 deletion(-) commit f44b14786d2d55886896182967a796c1b5155156 Author: Guillaume Desmottes Date: Tue Sep 22 11:23:51 2009 +0100 add wocky-pubsub-service-test.c .gitignore | 2 +- tests/Makefile.am | 7 ++++++ tests/wocky-pubsub-service-test.c | 49 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) commit 8ea80a23dda679d8d4511762974b9d8af7d5b90b Author: Guillaume Desmottes Date: Tue Sep 22 11:23:08 2009 +0100 add wocky-pubsub-service.[ch] wocky/Makefile.am | 4 +- wocky/wocky-pubsub-service.c | 197 +++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-pubsub-service.h | 64 ++++++++++++++ 3 files changed, 264 insertions(+), 1 deletion(-) commit ef691f605ccbb7306963aae03da33c3958f87e87 Merge: 67c3401 1a12dad Author: Will Thompson Date: Wed Feb 24 18:07:27 2010 +0000 Merge branch 'dataforms' Reviewed-by: Will Thompson Reviewed-by: Guillaume Desmottes commit 93b16266d53a8b4f19e823f63a8b1e1e6861440d Author: Will Thompson Date: Wed Feb 24 15:33:34 2010 +0000 Ignore more vim swapfiles .gitignore | 1 + 1 file changed, 1 insertion(+) commit eaa9abf1e519919b1ec42979e701f5f2dfec06e8 Author: Will Thompson Date: Wed Feb 24 15:32:16 2010 +0000 Add a README for the tests tests/Makefile.am | 1 + tests/README | 14 ++++++++++++++ 2 files changed, 15 insertions(+) commit 811ea8c29de9bfc484b74f90dd779ee0733d520c Author: Will Thompson Date: Wed Feb 24 15:31:40 2010 +0000 Support passing arguments to tests when valgrinding tests/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 543454e457ee692ec34973ef0574c6756fab8e98 Author: Will Thompson Date: Wed Feb 24 15:20:25 2010 +0000 Don't leak a stanza in node iterator test tests/wocky-xmpp-node-test.c | 2 ++ 1 file changed, 2 insertions(+) commit 62d4fc906aedbee014b910d65a17423df410d394 Author: Will Thompson Date: Wed Feb 24 15:19:12 2010 +0000 Don't leak stanzas in the extract_errors test tests/wocky-xmpp-stanza-test.c | 4 ++++ 1 file changed, 4 insertions(+) commit 5cbc1c725ad60f059e3df869e6c71ad7a00644d7 Author: Will Thompson Date: Wed Feb 24 15:19:00 2010 +0000 Make valgrind suppressions work in out-of-tree builds tests/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 0238e9f74ef6220825d84f01db8fd52a90236f78 Author: Will Thompson Date: Wed Feb 24 15:18:06 2010 +0000 Import tp-glib and gabble's valgrind suppressions These include a lot of tp-glib- and gabble-specific suppressions, but also have really extensive suppressions for things in glib and gobject. I don't really feel like separating them out... :-) tests/Makefile.am | 5 +- tests/gabble.supp | 210 ++++++++++++++++++++++++++++++++++++++++++++ tests/tp-glib.supp | 250 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 464 insertions(+), 1 deletion(-) commit 11578da38fca331f62db359852fe23d61c715470 Author: Will Thompson Date: Tue Feb 23 19:54:24 2010 +0000 Correct a source tag tests/test-resolver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 727eca561d376c8a5ec4339b965ac16370f67c36 Author: Will Thompson Date: Tue Feb 23 19:54:07 2010 +0000 test-resolver: don't leak if _finish() aren't called tests/test-resolver.c | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) commit 9bec938e524236c43089e3b8aff05def5cfac957 Author: Will Thompson Date: Tue Feb 23 18:28:36 2010 +0000 PEP: don't leak if pep_service_get_finish() isn't called wocky/wocky-pep-service.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) commit 60d7a62d5f7a13d8786a768c6ee2e7ebd4d8dccf Author: Will Thompson Date: Tue Feb 23 18:12:42 2010 +0000 Don't leak the WockyMuc in the disco CB g_async_result_get_source_object () returns a new ref. wocky/wocky-muc.c | 2 ++ 1 file changed, 2 insertions(+) commit 67c34019bacaa8b0ae907dedca92ce5c23e95034 Author: Will Thompson Date: Tue Feb 23 17:51:30 2010 +0000 Fix coding style violations wocky/wocky-muc.c | 6 +++--- wocky/wocky-sasl-handler.h | 2 +- wocky/wocky-xmpp-node.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) commit f903a2add6f875356b59d2647ea700cf14d524e4 Author: Will Thompson Date: Tue Feb 23 17:46:28 2010 +0000 Generate FIXME.out Makefile.am | 8 ++++++++ 1 file changed, 8 insertions(+) commit 1a12dad94dce8207b2b17b0c176f94e3cd2bc152 Author: Will Thompson Date: Mon Feb 22 17:22:49 2010 +0000 Document wocky_data_forms_submit() wocky/wocky-data-forms.c | 8 ++++++++ 1 file changed, 8 insertions(+) commit 37b2f7b8e22c9689ccced93c95511bfa3e70c7ed Author: Will Thompson Date: Mon Feb 22 17:08:42 2010 +0000 Use iterators when parsing results wocky/wocky-data-forms.c | 69 +++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 36 deletions(-) commit aad59510b15685168cad5147dee3aa0d44b4f305 Author: Will Thompson Date: Mon Feb 22 16:46:11 2010 +0000 Use WockyXmppNodeIter in a couple of places. wocky/wocky-data-forms.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) commit 40107996ad14c16029474e21f5afa516be2307dc Author: Will Thompson Date: Mon Feb 22 16:36:29 2010 +0000 Use g_slist_foreach as appropriate. This makes the code clearer (there's less boilerplate clutter) and shorter! wocky/wocky-data-forms.c | 40 ++++++++++++---------------------------- 1 file changed, 12 insertions(+), 28 deletions(-) commit ee927a89e9c90e714a57890d92db3627230fd3f5 Author: Will Thompson Date: Mon Feb 22 16:11:15 2010 +0000 Use g_assert_cmpstr () in data forms test tests/wocky-data-forms-test.c | 83 +++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 46 deletions(-) commit 20e068bcbbd120ea93559f6535a37833dc36e562 Author: Will Thompson Date: Mon Feb 22 17:13:39 2010 +0000 Improve and correct documentation wocky/wocky-data-forms.c | 20 +++++++++++++++----- wocky/wocky-data-forms.h | 9 +++++---- 2 files changed, 20 insertions(+), 9 deletions(-) commit e5272a71e7f9f5be3c56e1fae618ec78708703da Author: Will Thompson Date: Mon Feb 22 14:58:56 2010 +0000 Use GEnum for WockyDataFormsFieldType This saves manually writing the code to (de)stringify them. Also, get rid of the unused INVALID member. wocky/Makefile.am | 10 +++--- wocky/wocky-data-forms.c | 85 ++++++++++-------------------------------------- wocky/wocky-data-forms.h | 11 ++++--- 3 files changed, 30 insertions(+), 76 deletions(-) commit 6fd4076b68e764b1481e8a12b6a2dfd15f93067d Author: Guillaume Desmottes Date: Tue Sep 29 17:42:19 2009 +0100 fix includes of Wocky files wocky/wocky-data-forms.c | 4 ++-- wocky/wocky-data-forms.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) commit 471c0a869338f4c3c20bae28c1e8ad79264b71f1 Author: Guillaume Desmottes Date: Tue Sep 29 14:38:13 2009 +0100 wocky_data_forms_new_from_form: set an error if data forms can't be created tests/wocky-data-forms-test.c | 27 +++++++++++++++++++-------- wocky/wocky-data-forms.c | 8 +++++++- wocky/wocky-data-forms.h | 3 ++- 3 files changed, 28 insertions(+), 10 deletions(-) commit 71fe96395e186c2e5a42845521469b930cd5abf7 Author: Guillaume Desmottes Date: Tue Sep 29 14:34:17 2009 +0100 rename WOCKY_DATA_FORMS_ERROR_NOT_RESULT error to WOCKY_DATA_FORMS_ERROR_WRONG_TYPE wocky/wocky-data-forms.c | 2 +- wocky/wocky-data-forms.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) commit 89c6ec74defc5036edb138a9268eb9d5c6bf7ac2 Author: Guillaume Desmottes Date: Tue Sep 29 12:38:02 2009 +0100 pass the owernship of the value and default value to wocky_data_forms_field_new wocky/wocky-data-forms.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) commit 96df75e4793267c5f995e3b3c164843d573e46f4 Author: Guillaume Desmottes Date: Tue Sep 29 12:23:08 2009 +0100 rename wocky_data_forms_field and wocky_data_forms_field_option to be camel-cased tests/wocky-data-forms-test.c | 18 ++++++++--------- wocky/wocky-data-forms.c | 46 +++++++++++++++++++++---------------------- wocky/wocky-data-forms.h | 6 +++--- 3 files changed, 35 insertions(+), 35 deletions(-) commit d9cbe8b6f245ca0e17eda91b184d2b10c59ac9ca Author: Guillaume Desmottes Date: Tue Sep 29 12:15:45 2009 +0100 fix typos wocky/wocky-data-forms.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit a02edf09d4d37a86bccb9c543274d9dd6e77641e Author: Guillaume Desmottes Date: Tue Sep 29 12:15:36 2009 +0100 support '1' and '0' has boolean values wocky/wocky-data-forms.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 806e012db9e6accc9e3ea7a6b042b45f7f3e660d Author: Guillaume Desmottes Date: Mon Sep 28 15:47:32 2009 +0100 wocky-data-forms-test: test wocky_data_forms_parse_result with a single result tests/wocky-data-forms-test.c | 68 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) commit 3eca00b5a1433ad529189c424c12a592b00a5288 Author: Guillaume Desmottes Date: Mon Sep 28 15:45:37 2009 +0100 wocky-data-forms: support result stanzas without item nodes If there is only one result, it can be reported as a child of the x node, without reported and item nodes. wocky/wocky-data-forms.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) commit 9c8ea2d5d9647ab7e689ff8b25bb6fad33e16e84 Author: Guillaume Desmottes Date: Mon Sep 28 14:57:41 2009 +0100 wocky-data-forms: foreach_item: don't leak the value wocky/wocky-data-forms.c | 2 ++ 1 file changed, 2 insertions(+) commit 52add0d77c63efd30ee649d6f0948951c78cf1d2 Author: Guillaume Desmottes Date: Mon Sep 28 14:57:23 2009 +0100 wocky-data-forms-test: test wocky_data_forms_parse_result tests/wocky-data-forms-test.c | 125 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) commit daeda3372cb764d9121c433641758d4c7982cdf4 Author: Guillaume Desmottes Date: Mon Sep 28 14:29:06 2009 +0100 wocky-data-forms-test: rename create_form_stanza to create_bot_creation_form_stanza tests/wocky-data-forms-test.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit d6de371dcc583c79245b5d9bfad423a7b58314b7 Author: Guillaume Desmottes Date: Mon Sep 28 13:58:14 2009 +0100 wocky-data-forms-test: test wocky_data_forms_submit tests/wocky-data-forms-test.c | 174 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) commit b1a520e7848cd7276d97fc0eaee77e24c0a73348 Author: Guillaume Desmottes Date: Mon Sep 28 12:31:44 2009 +0100 wocky-data-forms-test: factor out create_form_stanza tests/wocky-data-forms-test.c | 101 ++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 48 deletions(-) commit 2be4d00d5e02756aa4e59944df24fa8c8b5eb729 Author: Guillaume Desmottes Date: Mon Sep 28 12:28:45 2009 +0100 wocky-data-forms-test: set a default value to the boolean field tests/wocky-data-forms-test.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 5c0c968e5c3c94ce9636b6ad8cfce9f5ee506ad7 Author: Guillaume Desmottes Date: Mon Sep 28 12:15:56 2009 +0100 wocky-data-forms-test: add a jid-single field node in the form tests/wocky-data-forms-test.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) commit 35b316cc8a4c0a60a27fe4aa7aa1b103dfa53222 Author: Guillaume Desmottes Date: Mon Sep 28 12:09:00 2009 +0100 wocky-data-forms: fix style typo wocky/wocky-data-forms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 7f4a542db21d2e95bda64912bd0e2b9828934d21 Author: Guillaume Desmottes Date: Mon Sep 28 11:59:47 2009 +0100 wocky-data-forms-test: test wocky_data_forms_new_from_form tests/wocky-data-forms-test.c | 259 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 259 insertions(+) commit 0208279021b93783f651c7d5e75ad55380fec860 Author: Guillaume Desmottes Date: Mon Sep 28 11:20:59 2009 +0100 wocky_data_forms_field_new: set the description wocky/wocky-data-forms.c | 2 ++ 1 file changed, 2 insertions(+) commit 0c21af1956d6adfb4943f6d1063ac2d2aa83096c Author: Guillaume Desmottes Date: Mon Sep 28 11:19:04 2009 +0100 foreach_x_child: add the type of the field in the debug msg wocky/wocky-data-forms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 9ec21828b84654f4d7cb9d1de7122807d1d465c7 Author: Guillaume Desmottes Date: Mon Sep 28 10:49:11 2009 +0100 extract_value_list: add trailing NULL to the strings array wocky/wocky-data-forms.c | 3 +++ 1 file changed, 3 insertions(+) commit 367137bd68baf3f6c41159e082cda0c076407f38 Author: Guillaume Desmottes Date: Mon Sep 28 10:42:59 2009 +0100 extract_options_list: add debug option wocky/wocky-data-forms.c | 1 + 1 file changed, 1 insertion(+) commit 9a1b02f8c35d4a31a17f1f3b06e805758a35bf15 Author: Guillaume Desmottes Date: Fri Sep 25 16:22:45 2009 +0100 wocky-data-forms: fix a typo in str_to_type wocky/wocky-data-forms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit cdf71f869bd972db052744ecddf058e5f53a1708 Author: Guillaume Desmottes Date: Fri Sep 25 16:04:28 2009 +0100 wocky-data-forms: add wocky_data_forms_get_{title,instructions} wocky/wocky-data-forms.c | 16 ++++++++++++++++ wocky/wocky-data-forms.h | 4 ++++ 2 files changed, 20 insertions(+) commit 38f36dd907fdade1756cb1bb82f0a05b91092fe6 Author: Guillaume Desmottes Date: Fri Sep 25 16:02:58 2009 +0100 wocky-data-forms; transfer ownership of the fields to the list The hash table doesn't contain fixed fields (as they don't have a 'var' attribute). Transfer the ownership of the fields to the list so the fixed fields are properly freed. wocky/wocky-data-forms.c | 5 +++-- wocky/wocky-data-forms.h | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) commit 432db6d2df4d54606f267d94195d4ab3af09203d Author: Guillaume Desmottes Date: Fri Sep 25 15:52:50 2009 +0100 wocky-data-forms: check if var is NULL before adding the field to the hash table wocky/wocky-data-forms.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) commit 93cca1c0b5797487c512ea6c7987d4d3978bf768 Author: Guillaume Desmottes Date: Fri Sep 25 14:56:17 2009 +0100 add wocky-data-forms-test.c .gitignore | 1 + tests/Makefile.am | 8 +++++- tests/wocky-data-forms-test.c | 63 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) commit a00881f8d5ae67fef9230985bb44115b1447e272 Author: Guillaume Desmottes Date: Fri Sep 25 14:39:43 2009 +0100 build wocky-data-forms wocky/Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 7c0f242b6f61744689714b15d64202bd35959f6d Author: Guillaume Desmottes Date: Fri Sep 25 14:39:38 2009 +0100 wocky-data-forms: use wocky debug domain wocky/wocky-data-forms.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) commit 7e600fe989ce14dc8dcdd0c6a780bd13f3ad416c Author: Guillaume Desmottes Date: Fri Sep 25 14:39:20 2009 +0100 add dataforms debug domain wocky/wocky-debug.c | 1 + wocky/wocky-debug.h | 1 + 2 files changed, 2 insertions(+) commit 8c275b7c4f6a424a80c08b37417835fa02057705 Author: Guillaume Desmottes Date: Fri Sep 25 14:34:58 2009 +0100 import wocky-data-forms.[ch] from Gabble wocky/wocky-data-forms.c | 805 +++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-data-forms.h | 123 ++++++++ 2 files changed, 928 insertions(+) commit 2be5deaeac50cc6d5d42b268dd815cee3b31fefd Author: Sjoerd Simons Date: Tue Feb 16 11:59:02 2010 +0000 Make the added Jingle namespaces more correct and consistent wocky/wocky-namespaces.h | 16 +++++++--------- wocky/wocky-xmpp-node.c | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) commit b18c56f9e2b1ff27e5838d7a7afee9b0b03be7d5 Author: Sjoerd Simons Date: Tue Feb 16 11:58:13 2010 +0000 Document that name and namespace are allowed to be NULL wocky/wocky-xmpp-node.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit ee4b5cbcbf8f6db7d1d0cdf41f53b61a1de1c48a Author: Sjoerd Simons Date: Tue Feb 16 11:42:28 2010 +0000 Fix typo tests/wocky-xmpp-node-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 4732bab637b4d836e9c8a3c869374ba664428a14 Author: Sjoerd Simons Date: Mon Feb 15 14:57:36 2010 +0000 Add a node iteration test tests/wocky-xmpp-node-test.c | 94 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) commit 50dbea42a8002bd76aa6c368c06c739bef4fb5a3 Author: Sjoerd Simons Date: Mon Feb 15 14:56:50 2010 +0000 Add the note iterator stuff in the documentation docs/reference/wocky-sections.txt | 3 +++ 1 file changed, 3 insertions(+) commit e31b279f10e9b8a73bdeb66385f63dbdc35e475d Author: Sjoerd Simons Date: Mon Feb 15 14:56:32 2010 +0000 Add node iterator utility functions wocky/wocky-xmpp-node.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-node.h | 17 +++++++++++- 2 files changed, 85 insertions(+), 1 deletion(-) commit a8aef4efc124d2932301cd7634606ba505b53b77 Author: Sjoerd Simons Date: Mon Feb 15 14:54:57 2010 +0000 Add jingle namespaces wocky/wocky-namespaces.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) commit e70f6fc191bc3516dfeb9f7dedf28cb70bb5d3f7 Author: Sjoerd Simons Date: Fri Feb 12 19:18:28 2010 +0000 Add google jingle session namespaces for use in tests later wocky/wocky-namespaces.h | 6 ++++++ 1 file changed, 6 insertions(+) commit 83221b4b791d2e00fc286694d9912832cca8305e Merge: db56fa0 f6842a6 Author: Will Thompson Date: Mon Feb 15 13:06:43 2010 +0000 Merge branch 'error-wrangling' Reviewed-by: Sjoerd Simons commit f6842a68d853cf6b364fabc264a04b6d8193a0b1 Author: Will Thompson Date: Mon Feb 15 12:50:00 2010 +0000 Document assumption about _enum_from_nick's behaviour wocky/wocky-utils.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 533bbdcb916215dd38ff3573a1221e843d8d912a Author: Will Thompson Date: Mon Feb 15 12:45:37 2010 +0000 Consistently use "quark == 0" wocky/wocky-xmpp-error.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 33c6f6da5eeb13e7fdf591efc2cc9411e86051fe Author: Will Thompson Date: Wed Feb 3 15:10:54 2010 +0000 Reorder and better document wocky-xmpp-error.c This patch contains no code changes, but tries to make wocky-xmpp-error.c easier to understand by adding documentation and arranging the file to be roughly: • Core stanza errors, and parsing/production thereof; • Core stream errors, and parsing thereof; • Application-specific stanza errors. wocky/wocky-xmpp-error.c | 271 ++++++++++++++++++++++++++--------------------- 1 file changed, 153 insertions(+), 118 deletions(-) commit fe2b96bf50e47815c888167910e4e12cbcc46081 Author: Will Thompson Date: Wed Feb 3 14:44:00 2010 +0000 Improve documentation of new error-y functions wocky/wocky-xmpp-error.c | 25 +++++++++++++++++++++++++ wocky/wocky-xmpp-stanza.c | 20 ++++++++++++++++---- 2 files changed, 41 insertions(+), 4 deletions(-) commit fa9560b0ac44df71d048416cd64903900d3e84c2 Author: Will Thompson Date: Wed Feb 3 01:35:19 2010 +0000 Remove superseded error wrangling functions. The functionality of these functions has been subsumed and improved upon by wocky_stanza_error_to_node(), wocky_xmpp_error_extract() and wocky_xmpp_stream_error_from_node(). tests/wocky-xmpp-stanza-test.c | 28 ------------------------- wocky/wocky-xmpp-error.c | 29 -------------------------- wocky/wocky-xmpp-error.h | 4 ---- wocky/wocky-xmpp-stanza.c | 47 ------------------------------------------ wocky/wocky-xmpp-stanza.h | 1 - 5 files changed, 109 deletions(-) commit c05e22a652d6c2faa729edb2842f6cc36fb2b315 Author: Will Thompson Date: Wed Feb 3 01:23:06 2010 +0000 Add and use _stanza_extract_stream_error() By analogy to wocky_xmpp_stanza_extract_errors(), this function parses a stream error stanza, yielding an error in the WOCKY_XMPP_STANZA_ERROR domain. Note that the test for parsing stanza errors was wrong: was not in the correct namespace. tests/wocky-xmpp-stanza-test.c | 20 +++++++++++--------- wocky/wocky-connector.c | 19 +++---------------- wocky/wocky-porter.c | 2 +- wocky/wocky-xmpp-error.c | 26 ++++++++++++++++++-------- wocky/wocky-xmpp-error.h | 2 +- wocky/wocky-xmpp-stanza.c | 16 ++++++++++++++++ wocky/wocky-xmpp-stanza.h | 3 +++ 7 files changed, 53 insertions(+), 35 deletions(-) commit 814c778603c3c3ebcd8dca9f7bfcdf28e3bb6381 Author: Will Thompson Date: Wed Feb 3 01:06:48 2010 +0000 Use _stanza_extract_errors() not _stanza_to_gerror() wocky_xmpp_stanza_to_gerror() works on both stream errors and stanzas with type='error'. I think this is confusing, and unnecessary: there are no real situations where you don't know which of the two you have. wocky/wocky-muc.c | 2 +- wocky/wocky-roster.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) commit 5a2b25047722c8ffb4fac28941c2e4d55f26dc75 Author: Will Thompson Date: Wed Feb 3 00:59:27 2010 +0000 connector: use _extract_errors, not manual parsing wocky/wocky-connector.c | 74 ++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) commit 34265393559bf22073eda1f5fe784600bfaf8d10 Author: Will Thompson Date: Wed Feb 3 00:55:17 2010 +0000 Return gboolean from _stanza_extract_errors() This is probably more useful behaviour than having to explicitly check whether the stanza has type='error' before calling the function. tests/wocky-xmpp-stanza-test.c | 22 ++++++++++++++++++++-- wocky/wocky-xmpp-stanza.c | 12 ++++++++---- wocky/wocky-xmpp-stanza.h | 2 +- 3 files changed, 29 insertions(+), 7 deletions(-) commit 660aa9916918e71819b2e54a0f335f14477c3b28 Author: Will Thompson Date: Tue Feb 2 20:39:48 2010 +0000 Remove wocky_xmpp_error_unpack_node() Its functionality is subsumed by wocky_xmpp_error_extract (via wocky_xmpp_stanza_extract_errors). tests/wocky-xmpp-node-test.c | 182 ------------------------------------------- wocky/wocky-connector.c | 90 +++++++-------------- wocky/wocky-muc.c | 47 ++++------- wocky/wocky-xmpp-error.c | 100 +----------------------- wocky/wocky-xmpp-error.h | 9 --- 5 files changed, 46 insertions(+), 382 deletions(-) commit 27671766aa63e51ac4a31fb261f02e15e35ea14d Author: Will Thompson Date: Tue Feb 2 19:46:36 2010 +0000 Test wocky_stanza_error_to_node() tests/wocky-xmpp-stanza-test.c | 108 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) commit 70c50735ea77358f13b72551512089f0b9943eb7 Author: Will Thompson Date: Tue Feb 2 19:40:23 2010 +0000 Correctly namespace element in . wocky/wocky-xmpp-error.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) commit dba37a26dc50450b6ca88b42f2c7e9ad29bfaf6d Author: Will Thompson Date: Tue Feb 2 19:28:12 2010 +0000 Fix ordering of legacy error codes remote-server-timeout and service-unavailable are the only stanza errors with multiple old-style codes. The codes were listed in numerical order, but in both cases this conflicted with the suggested mapping in XEP-0086 §2. wocky/wocky-xmpp-error.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit d75437300e3a9bd093b277d13a9531d2218f8cd7 Author: Will Thompson Date: Tue Feb 2 16:07:35 2010 +0000 Add wocky_xmpp_stanza_extract_errors() tests/wocky-xmpp-stanza-test.c | 197 +++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-error.c | 90 +++++++++++++++++++ wocky/wocky-xmpp-error.h | 10 ++- wocky/wocky-xmpp-stanza.c | 35 ++++++++ wocky/wocky-xmpp-stanza.h | 6 ++ 5 files changed, 337 insertions(+), 1 deletion(-) commit e02c36e01765f020658592a879adf07f5f08ae4b Author: Will Thompson Date: Tue Feb 2 15:53:03 2010 +0000 Also guess error type for legacy error codes wocky/wocky-xmpp-error.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) commit 6ca7b814db6a11c9d7bffc1a56b324d6b5862c04 Author: Will Thompson Date: Tue Feb 2 13:20:24 2010 +0000 Extract parsing legacy error codes to a function wocky/wocky-xmpp-error.c | 61 ++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 28 deletions(-) commit b6847d202e5a850e47291d56ec47a90a28556ece Author: Will Thompson Date: Sun Jan 31 15:37:02 2010 +0000 Remove redundant fields of XmppErrorSpec This structure does need to be distinct from WockyXmppErrorSpecialization because it needs to include legacy error codes. However, errors' element names can be obtained from the enumeration, and all errors in this table are core stanza errors, in the stanzas namespace. wocky/wocky-xmpp-error.c | 102 ++++++++++++++--------------------------------- 1 file changed, 29 insertions(+), 73 deletions(-) commit dec2c87413b23453388baf4b61c23839a28cbaef Author: Will Thompson Date: Sun Jan 31 15:31:21 2010 +0000 Support converting GErrors to stanza errors wocky/wocky-xmpp-error.c | 98 ++++++++++++++++++++++++++++++++++++++++-------- wocky/wocky-xmpp-error.h | 3 ++ 2 files changed, 85 insertions(+), 16 deletions(-) commit 94763836b6eeae075deeb2a72d27528e6f8e47e4 Author: Will Thompson Date: Sun Jan 31 15:10:35 2010 +0000 Add wocky_xmpp_node_set_ns_q() wocky/wocky-xmpp-node.c | 8 +++++++- wocky/wocky-xmpp-node.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) commit 90ede56d63480021a572facb37c2c4c5545dd409 Author: Will Thompson Date: Fri Jan 29 23:59:31 2010 +0000 Register Jingle and SI error domains wocky/wocky-xmpp-error.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-error.h | 1 + 2 files changed, 79 insertions(+) commit 7dcdc9146c4283bec55e9272e438d4f87d2b9584 Author: Will Thompson Date: Fri Jan 29 23:34:25 2010 +0000 Update Jingle error codes to the current XEP wocky/wocky-xmpp-error.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit fd9c14279f4359b1e2bcb5e17f4fab2cabacbd5d Author: Will Thompson Date: Fri Jan 29 23:51:41 2010 +0000 Add a hook for registering new stanza error domains wocky/wocky-xmpp-error.c | 24 ++++++++++++++++++++++++ wocky/wocky-xmpp-error.h | 19 +++++++++++++++++++ wocky/wocky.c | 3 +++ 3 files changed, 46 insertions(+) commit 86490fc3bcf9c87b0b7be9d6eaadadbc9cbf1c01 Author: Will Thompson Date: Fri Jan 29 23:14:09 2010 +0000 Add and use WockyXmppErrorType tests/wocky-xmpp-node-test.c | 6 ++-- wocky/wocky-muc.c | 6 ++-- wocky/wocky-xmpp-error.c | 68 +++++++++++++++++++++++++------------------- wocky/wocky-xmpp-error.h | 11 ++++++- 4 files changed, 55 insertions(+), 36 deletions(-) commit 6788145886837957ce2ef404027257ae9c15ddc0 Author: Will Thompson Date: Fri Jan 29 19:36:00 2010 +0000 Look up stanza errors from GEnum We still need the fallback case for error numbers, but we don't need the "start at the end" stuff any more because WockyXmppError only contains the basic stanza errors (rather than having Jingle and SI smushed in at the end). wocky/wocky-xmpp-error.c | 18 ++++-------------- wocky/wocky-xmpp-error.h | 3 ++- 2 files changed, 6 insertions(+), 15 deletions(-) commit 4da39e6569b55ab29610e3f27c2de3ade4db5acd Author: Will Thompson Date: Fri Jan 29 19:30:26 2010 +0000 Generalize looking up error code from node and ns wocky/wocky-xmpp-error.c | 53 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 13 deletions(-) commit a028aac7a8e877d2062373f67a91ccb66e0382b8 Author: Will Thompson Date: Fri Jan 29 18:52:38 2010 +0000 Use XMPP namespaces for Xmpp[Stream]Error quark This involves changing a test which hardcodes the string corresponding to the stream error quark. I was surprised that it did so, but it's because you can't use the quark in a static table of test data. tests/wocky-connector-test.c | 16 ++++++++-------- wocky/wocky-xmpp-error.c | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) commit 5c88062e9470be54720a5bca1a4a3276f028e578 Author: Will Thompson Date: Fri Jan 29 17:32:03 2010 +0000 Remove non-stanza errors from WockyXmppError They belong in their own domains. wocky/wocky-xmpp-error.c | 77 ++++++++++++++---------------------------------- wocky/wocky-xmpp-error.h | 26 +++++++++++----- 2 files changed, 40 insertions(+), 63 deletions(-) commit d915abf0858f13c000203685bbfce8368803dd60 Author: Will Thompson Date: Fri Jan 29 17:08:36 2010 +0000 Convert to WockyXmppStreamError using GEnum wocky/wocky-xmpp-error.c | 56 ++++++++++-------------------------------------- wocky/wocky-xmpp-error.h | 1 + 2 files changed, 12 insertions(+), 45 deletions(-) commit a6fbbd4f2200563dde0fa9b26fcdc7390adf5435 Author: Will Thompson Date: Fri Jan 29 17:16:57 2010 +0000 Add wocky_xmpp_node_has_ns() and _has_ns_q() wocky/wocky-xmpp-node.c | 12 ++++++++++++ wocky/wocky-xmpp-node.h | 2 ++ 2 files changed, 14 insertions(+) commit 3cc413cf14ebb097b9a717eefd6020dc074bb004 Author: Will Thompson Date: Fri Jan 29 17:08:11 2010 +0000 Correct generation of GEnum nicknames wocky/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 67a3f5cb295b266dd40a61bcb9fe617c5191280b Author: Will Thompson Date: Fri Jan 29 16:34:31 2010 +0000 Add helpers to convert enums to/from nicks wocky/wocky-utils.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-utils.h | 3 +++ 2 files changed, 70 insertions(+) commit db56fa02c425d04ae12dd686942f5303d700fc15 Author: Sjoerd Simons Date: Mon Feb 1 15:10:02 2010 +0000 Signal our own presence when we receive it wocky/wocky-muc.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) commit 556c16b9fcf1f869e37622a043c0707d34e9e4c2 Author: Sjoerd Simons Date: Mon Feb 1 15:08:59 2010 +0000 Add an accessor for the state of the WockyMuc wocky/wocky-muc.c | 34 +++++++++++++++++----------------- wocky/wocky-muc.h | 10 ++++++++++ 2 files changed, 27 insertions(+), 17 deletions(-) commit c1044f07d71abd3df64337832ce489f390794140 Merge: 4abda60 d839ade Author: Sjoerd Simons Date: Wed Jan 27 14:27:56 2010 +0000 Merge branch 'auth-data-with-success' commit d839ade59a843b44ca65129df810f244cfe90d54 Author: Sjoerd Simons Date: Wed Jan 27 14:22:00 2010 +0000 Update documentation wocky/wocky-sasl-handler.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit 4abda602a728fdcf057cad9f759c746fd219007f Author: Will Thompson Date: Thu Jan 21 15:24:21 2010 +0000 Squash warnings about failing to normalise NULL recipient It's valid to send IQs with no recipient, so stanza_iq_handler_new() will often be called with recipient == NULL. Previously, it would try to normalize NULL, fail, emit a debug message, and fall back to using NULL; this patch stops it trying to normalize NULL in the first place. Reviewed-by: Sjoerd Simons wocky/wocky-porter.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) commit 6825ce8cd16843166d950779e32d1d15714377ff Author: Sjoerd Simons Date: Thu Jan 21 14:49:03 2010 +0000 More readme tweaks (actually buildbot testing) README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 9f6b8ec2a3dd2cb440a9f3dc8a1223d4b0e29d24 Author: Sjoerd Simons Date: Thu Jan 21 14:24:51 2010 +0000 Tweak the README README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 9d0e91c4a7fe6e88e0009a26f49e3b8866c2c2c1 Author: Vivek Dasmohapatra Date: Thu Jan 21 13:30:23 2010 +0000 Turn off OpenSSL SSLv2 supprt (this allows deflate compression to be negotiated) wocky/wocky-openssl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 5a515d7d52ad05c84e320787269fba6fa7913757 Author: Simon McVittie Date: Wed Jan 13 15:47:38 2010 +0000 Generate header guards for *-enumtypes.h properly Reviewed-by: Vivek Dasmohapatra wocky/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit b0989e5f85f8982de112fa89993dc1b12de4a02d Author: Simon McVittie Date: Wed Jan 13 15:20:32 2010 +0000 Tighten up rule for generating *-enumtypes.h It turns out that an implicit rule for %-enumtypes.h can be a bad idea - % matches slashes, so when the equivalent of this code in src/ runs, it can be run with /home/smcv/.../wocky/wocky-foo-enumtypes.h as target, resulting in highly undesirable action-at-a-distance. Since we require GNU make already, use static pattern rules to avoid that sort of thing. Reviewed-by: Vivek Dasmohapatra wocky/Makefile.am | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) commit 58079b010d3bd3e192c5317e68e2b0d42efcb4e5 Merge: 8d9008c 28a8d7e Author: Simon McVittie Date: Wed Jan 13 13:21:00 2010 +0000 Merge branch 'misc' Reviewed-by: Vivek Dasmohapatra commit 28a8d7e17d7d8624f89f0cfdd3378c28dc92f261 Author: Simon McVittie Date: Wed Jan 13 13:14:31 2010 +0000 wocky/Makefile.am: fix generation of *-enumtypes.h Previously, if foo-enumtypes.h was built as a result of a dependency from another directory, we'd try to use the full path (/home/smcv/.../wocky/foo) in the macro names, which is both syntactically invalid and not what we want. The GNU make $(notdir) operator fixes this. Also, the previous rule was somewhat illegible; factoring out the string manipulation into temporary variables improves this, I think. wocky/Makefile.am | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) commit bb3195e5540313ab46bcc2f890a0accf648e9ce7 Author: Simon McVittie Date: Wed Jan 13 13:11:27 2010 +0000 .gitignore: add more cruft .gitignore | 2 ++ 1 file changed, 2 insertions(+) commit 165cf4a0d7439d439f9d3890791af40ab78279d3 Author: Simon McVittie Date: Wed Jan 13 13:10:24 2010 +0000 wocky_xmpp_stanza_build: adjust docstring so gtkdoc will work wocky/wocky-xmpp-stanza.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) commit ad9071dabf2c1ab771e54097f283b2893129a692 Author: Sjoerd Simons Date: Mon Jan 11 13:40:48 2010 +0000 Make the handling of additional data with success generic When receiving initial data with success from the server we pass it to the normal auth data handler for checking. If this was indeed the final data the handler will not give us a response to the server, otherwise the server is doing it wrong. wocky/wocky-sasl-auth.c | 32 +++++++++++++++++++----------- wocky/wocky-sasl-digest-md5.c | 46 ++++++++----------------------------------- wocky/wocky-sasl-handler.c | 3 +-- wocky/wocky-sasl-handler.h | 4 ++-- 4 files changed, 32 insertions(+), 53 deletions(-) commit eeca31c3e40727f8e8e5ba9ea9bc7db17e3dfb86 Author: Sjoerd Simons Date: Mon Jan 11 13:36:22 2010 +0000 Use an auth data function instead of the challenge function Instead of the old challenge function, have an auth data function which can return an *optional* response and directly gets the data that's interesting for sasl instead of the complete stanza. Specifically if the server sends correct final authentication data the handler must not set a response, but should return successfull wocky/wocky-sasl-auth.c | 51 ++++++++--------------- wocky/wocky-sasl-digest-md5.c | 95 ++++++++++++++++++++++++------------------- wocky/wocky-sasl-handler.c | 18 ++++---- wocky/wocky-sasl-handler.h | 27 +++++++----- 4 files changed, 99 insertions(+), 92 deletions(-) commit 1bde461e90aa2f3bf616d4ee96781f9732192283 Author: Sjoerd Simons Date: Mon Jan 11 13:33:32 2010 +0000 Generalize the failure handling tests/wocky-test-sasl-handler.c | 12 ------------ wocky/wocky-sasl-auth.c | 41 ++++++++++++++++++++++++++++++++--------- wocky/wocky-sasl-digest-md5.c | 28 +--------------------------- wocky/wocky-sasl-handler.c | 10 ---------- wocky/wocky-sasl-handler.h | 16 ---------------- wocky/wocky-sasl-plain.c | 28 ---------------------------- 6 files changed, 33 insertions(+), 102 deletions(-) commit 1a9e10ab4c014408b75160a311bc133b6e8620a6 Author: Sjoerd Simons Date: Mon Jan 11 12:41:33 2010 +0000 Add a default implementation for the success handler tests/wocky-test-sasl-handler.c | 12 ------------ wocky/wocky-sasl-handler.c | 9 +++++++-- wocky/wocky-sasl-plain.c | 12 ------------ 3 files changed, 7 insertions(+), 26 deletions(-) commit b77b321c393935426791c0d22f96c030e57aec55 Author: Sjoerd Simons Date: Mon Jan 11 12:36:19 2010 +0000 Use the new initial response function API tests/wocky-test-sasl-handler.c | 19 +++++++++++-------- wocky/wocky-sasl-auth.c | 8 +++----- wocky/wocky-sasl-digest-md5.c | 5 ----- wocky/wocky-sasl-plain.c | 38 ++++++++++++++++++-------------------- 4 files changed, 32 insertions(+), 38 deletions(-) commit fac1d18fa5b9e61c8f65f9b1c585ca575fbb1bb2 Author: Sjoerd Simons Date: Mon Jan 11 12:32:56 2010 +0000 Add a seperate function to get an initial response Split out the function to get the initial response so that we don't have to special case stanza == NULL in every challenge handler. Also allow a mechanism to not implement a challenge handler, for mechanisms that only use initial data. wocky/wocky-sasl-handler.c | 32 ++++++++++++++++++++++++++++++-- wocky/wocky-sasl-handler.h | 30 +++++++++++++++++++++--------- 2 files changed, 51 insertions(+), 11 deletions(-) commit aa5d2aab1dfccdfc026b1d9e7564807fe68dcc81 Author: Sjoerd Simons Date: Sun Jan 10 15:40:46 2010 +0000 Test final auth data in success for md5 tests/wocky-test-sasl-auth.c | 3 +++ 1 file changed, 3 insertions(+) commit afd61e84ce0ab39e23519c5ece11ee7dca721aab Author: Sjoerd Simons Date: Sun Jan 10 15:40:10 2010 +0000 Add support for the sasl test server to put the final auth data in success tests/wocky-test-sasl-auth-server.c | 30 +++++++++++++++++++----------- tests/wocky-test-sasl-auth-server.h | 3 +++ 2 files changed, 22 insertions(+), 11 deletions(-) commit 34ae0ca0ecbe917fa593fb3372a90d952132a500 Author: Sjoerd Simons Date: Sun Jan 10 15:39:18 2010 +0000 Cope with final auth data in success for digest-md5 wocky/wocky-sasl-digest-md5.c | 78 ++++++++++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 24 deletions(-) commit 0d2135c2bdb54074fda36f44c2e3f6b22bc6c274 Author: Sjoerd Simons Date: Sun Jan 10 15:37:37 2010 +0000 Change the success handler signature so it retuns a boolean tests/wocky-test-sasl-handler.c | 5 +++-- wocky/wocky-sasl-digest-md5.c | 8 +++++--- wocky/wocky-sasl-handler.c | 4 ++-- wocky/wocky-sasl-handler.h | 6 +++--- wocky/wocky-sasl-plain.c | 5 +++-- 5 files changed, 16 insertions(+), 12 deletions(-) commit 8d9008cdb052c437f0a38b1b17b3e419a784a035 Author: Sjoerd Simons Date: Thu Jan 7 15:58:42 2010 +0000 Slice allocate wocky muc members wocky/wocky-muc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) commit 64434b0de131ebd0bbbe87085d67929c926c6925 Author: Sjoerd Simons Date: Thu Jan 7 15:57:23 2010 +0000 Use the from jid and not the nick to get leaving members wocky/wocky-muc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) commit b4f660754626a374feed054d204875951cb9d737 Author: Sjoerd Simons Date: Thu Jan 7 15:55:59 2010 +0000 Streamline some code wocky/wocky-muc.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) commit 5a4477045d01180d078d577a50bedaab8a55fb4b Author: Sjoerd Simons Date: Thu Jan 7 15:54:43 2010 +0000 Correct the signal marshaller signatures wocky/wocky-muc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 5b8bce9d97a0537c50474d3e936dcbbbe601e200 Author: Sjoerd Simons Date: Thu Jan 7 15:52:01 2010 +0000 Keep track of the last presence stanza for each member wocky/wocky-muc.c | 9 +++++++++ wocky/wocky-muc.h | 1 + 2 files changed, 10 insertions(+) commit 20ce01944ba6fcde5c28f42669afd7007195778e Author: Sjoerd Simons Date: Thu Jan 7 15:51:18 2010 +0000 Fix reference counting and unregister handlers on dispose wocky/wocky-muc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) commit d2954fcfd6235d43f4895324ba8a755ec7c87d3d Author: Sjoerd Simons Date: Wed Jan 6 16:18:50 2010 +0000 Don't be anal about having in muc presences wocky/wocky-muc.c | 5 ----- 1 file changed, 5 deletions(-) commit 129fcf4abc5223186b161883f099f2238b43cea7 Author: Sjoerd Simons Date: Mon Jan 4 13:01:27 2010 +0100 Only allow setting status directly when sending an unavailable presence wocky/wocky-muc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) commit 6e9b58f106702ca5c2298328c218261a5043ca30 Author: Sjoerd Simons Date: Mon Jan 4 13:00:52 2010 +0100 Add a signal to allow other components to add presence information wocky/wocky-muc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) commit a0382c282bc21aa155a3a975ddce4767c9443279 Author: Sjoerd Simons Date: Mon Jan 4 11:12:19 2010 +0100 When emitting a signal, use the right arguments wocky/wocky-muc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 5f00c4d2ce5801797897fcd19e6b6a6d35041377 Author: Sjoerd Simons Date: Mon Jan 4 11:08:03 2010 +0100 Use GSimpleAsyncResult instead of inventing a pointless callback type wocky/wocky-muc.c | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) commit 2508b0faa488f23af68a08e60a22ff4b439590d1 Author: Sjoerd Simons Date: Mon Jan 4 11:06:18 2010 +0100 Don't disco mucs when joining them wocky/wocky-muc.c | 99 +++++-------------------------------------------------- 1 file changed, 8 insertions(+), 91 deletions(-) commit f9bdc0a2b3cbb20e55018fa05a02d40c2d5d3116 Author: Sjoerd Simons Date: Mon Jan 4 11:05:47 2010 +0100 Keep track of members by their full muc jid wocky/wocky-muc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit 1308247b8e6819877438bcfc7c35d78b64e13cea Author: Sjoerd Simons Date: Mon Jan 4 11:04:56 2010 +0100 A presence is of type presence, not of type iq wocky/wocky-muc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 84059726e5a9a9ca37c0458b842fc8a44756c6c7 Author: Sjoerd Simons Date: Mon Jan 4 11:04:21 2010 +0100 Fix definition of various signals and properties wocky/wocky-muc.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) commit a26a191f0c4bd37654e4be31bd95719267c46dc2 Author: Sjoerd Simons Date: Mon Jan 4 11:02:23 2010 +0100 Build various enumtypes wocky/Makefile.am | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) commit b0e38741d6b75edb8f9e139950f53bd3c3c374ed Author: Sjoerd Simons Date: Mon Jan 4 11:01:32 2010 +0100 When putting the resource in the jid, do not put in the domain wocky/wocky-utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 37638d53e361f0349d5795161ba2a7b456909331 Merge: 25c2e26 ffbe1a9 Author: Sjoerd Simons Date: Tue Dec 29 14:49:59 2009 +0100 Merge remote branch 'vivek/muc' into muc commit 25c2e26d2b20d9f58495f8871452f8d51bdc65d5 Author: Will Thompson Date: Mon Dec 28 18:11:12 2009 +0000 Correctly ship test certificates in out-of-tree builds Previously the wildcards were matching no files, because they were being applied to the builddir (where the Makefile is) rather than the srcdir. I tried to do someting fancy involving $(CERTS), but $(CERTS) contains absolute paths (for reasonably good reasons: they're passed as #defines into a test binary) so then I tried mangling them back into relative paths in $(EXTRA_DIST) but then I decided this was clearer. Including directories in $(EXTRA_DIST) is discouraged by the Automake documentation, and is unnecessary in this case because the contents of certs/cas and certs/crl that we want are in $(EXTRA_DIST) anyway. tests/Makefile.am | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) commit ffbe1a90049cd609fc57fa8f98b9cb59617dad66 Author: Vivek Dasmohapatra Date: Sun Dec 27 19:41:58 2009 +0000 First stab at implementing muc support for gabble. wocky/wocky-muc.c | 573 ++++++++++++++++++++++++++++++++++++++++-------------- wocky/wocky-muc.h | 50 +++-- 2 files changed, 466 insertions(+), 157 deletions(-) commit 04680884a563b0d4e2e7b6d1f3d6fd57dae19e75 Author: Vivek Dasmohapatra Date: Sun Dec 27 19:41:30 2009 +0000 Add some missing MUC related XMPP namespaces. wocky/wocky-namespaces.h | 6 ++++++ 1 file changed, 6 insertions(+) commit 97682078013710c7ad6e02d5b0c6fcfa9b241e01 Author: Will Thompson Date: Tue Dec 22 12:02:52 2009 +0000 Rename verification level variable from 'flags' It's no longer a set of flags, it's a single enum member. wocky/wocky-openssl.c | 8 ++++---- wocky/wocky-tls.c | 4 ++-- wocky/wocky-tls.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) commit c5342b10ab9067b975edebaa02d57ef9fbdfe964 Author: Will Thompson Date: Tue Dec 22 11:57:39 2009 +0000 Correctly fall back to VERIFY_STRICT. wocky/wocky-openssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 2a63eaf938da05886758f46d2c5f83811d649a8d Author: Sjoerd Simons Date: Mon Dec 21 11:58:44 2009 +0000 Use a simple enum for the tls verification level wocky/wocky-openssl.c | 6 ++++-- wocky/wocky-tls.c | 8 +++++--- wocky/wocky-tls.h | 11 +++++++---- 3 files changed, 16 insertions(+), 9 deletions(-) commit 5d494cc07923b0b1da09aaa95b53180889cebda6 Author: Sjoerd Simons Date: Sun Dec 20 17:51:40 2009 +0000 Use wocky's debugging in the more traditional way tests/wocky-test-connector-server.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit 0505ac47351f59dd962cdfa502fb54823d7a284e Author: Sjoerd Simons Date: Sun Dec 20 17:49:13 2009 +0000 Don't use a temporary variable just in DEBUG wocky/wocky-connector.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 255c63eeffe1ae3d223b8959152dcc71783f8ac0 Author: Sjoerd Simons Date: Sun Dec 20 17:48:44 2009 +0000 Don't call wocky_debug if debugging isn't enabled wocky/wocky-xmpp-writer.c | 2 ++ 1 file changed, 2 insertions(+) commit dc1918699e06befa204b458a8f6eb07c42c72018 Author: Sjoerd Simons Date: Sun Dec 20 17:47:38 2009 +0000 only define hdesc_to_string when debugging is enabled wocky/wocky-tls.c | 2 ++ 1 file changed, 2 insertions(+) commit 7987cc80119759523561cb7d60595b9d96e426cd Author: Sjoerd Simons Date: Fri Dec 18 14:01:55 2009 +0000 Don't summarize if python isn't there tests/Makefile.am | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) commit e7ccc4314201ca7cb84c89753ee08e7e5702d31a Author: Sjoerd Simons Date: Fri Dec 18 14:01:36 2009 +0000 Don't assume python is in /usr/bin tests/summarise-tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit dbe94b97a0117b92a2146f77b5ade4aa28918b25 Author: Sjoerd Simons Date: Fri Dec 18 13:04:00 2009 +0000 Various improvements to the python summary Let the python summary cope with skipped and restarted tests and in case of failures print the cases that failed. tests/summarise-tests.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) commit 4d89d5a2bee0e2cab0095aa9cee7e842538318f4 Author: Will Thompson Date: Thu Dec 17 13:41:08 2009 +0000 Reimplement summarize-tests in Python This lets us use a real XML parser, and makes the whole thing shorter and more legible. tests/Makefile.am | 6 +-- tests/summarise-tests.py | 46 +++++++++++++++++++++ tests/summarise-tests.sh | 104 ----------------------------------------------- 3 files changed, 49 insertions(+), 107 deletions(-) commit 4a29668ca4fd8500fa2e59d7a593a8fc49904207 Author: Sjoerd Simons Date: Fri Dec 18 10:50:33 2009 +0000 Rethink iq cancellation to ensure we don't use freed memory Some valgrind testing on gabble indicated that quite often the StanzaIqHandlers were used after being freed. This redoes the handling in such a way that the handlers get removed when there was a result _and_ the send operation has finished. wocky/wocky-porter.c | 147 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 86 insertions(+), 61 deletions(-) commit 4fff9be936824e6c5b4e61768db1332e2fd3b164 Author: Will Thompson Date: Thu Dec 17 15:43:36 2009 +0000 Use G_G[S]SIZE_FORMAT for g[s]size in printf These aren't both %ld on all platforms. wocky/wocky-openssl.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) commit 0bd6d0dd44ba5a880f3fdb5679aa200af41fc3c1 Author: Will Thompson Date: Thu Dec 17 13:40:06 2009 +0000 Fix coding style checks in out-of-tree builds. This is already fixed in Gabble's copy of the script; this just updates Wocky's copy to match. tools/check-coding-style.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 440fd94bf01530163ada2b247fbbb56e59904286 Author: Will Thompson Date: Thu Dec 17 13:28:28 2009 +0000 test-sasl-auth-server: fix no-libsasl compilation tests/wocky-test-sasl-auth-server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 2dae85b150264b60b9b4b3e12939288078a6ca30 Author: Will Thompson Date: Wed Dec 16 20:39:41 2009 +0000 connector-test: include wocky-utils for _strdiff. This is only used on the no-libsasl path, hence why it compiles for everyone working on it! tests/wocky-connector-test.c | 1 + 1 file changed, 1 insertion(+) commit 76cb2dcae9697bd246b1faa562d4a795712ea7a5 Author: Will Thompson Date: Wed Dec 16 19:09:26 2009 +0000 Document wocky_xmpp_stanza_build wocky/wocky-xmpp-stanza.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) commit a02011ab948ad57ee5eff23e05293e4dd3898555 Author: Will Thompson Date: Wed Dec 16 19:09:07 2009 +0000 Fix out-of-tree compilation with OpenSSL wocky/wocky-openssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 1298577c5a25f38054fa8262b9ecaf8c3a75f115 Author: Vivek Dasmohapatra Date: Thu Dec 17 16:51:41 2009 +0000 Remove wocky-openssl.h, no headers use the USING_OPENSSL #define (or config.h) tests/wocky-test-connector-server.c | 4 -- wocky/Makefile.am | 2 +- wocky/wocky-connector.h | 6 --- wocky/wocky-openssl.c | 4 +- wocky/wocky-openssl.h | 102 ------------------------------------ wocky/wocky-tls.c | 21 +++++++- wocky/wocky-tls.h | 19 +++---- 7 files changed, 31 insertions(+), 127 deletions(-) commit 999d81c4ab30d11ae2d8a9fd684c21e8a83d21ce Author: Vivek Dasmohapatra Date: Tue Dec 8 15:49:38 2009 +0000 Missing include for wocky_strdiff prototype. wocky/wocky-xmpp-error.c | 1 + 1 file changed, 1 insertion(+) commit b04504d5a128295c3f00580a2128a34b10254a87 Author: Vivek Dasmohapatra Date: Tue Dec 8 15:49:11 2009 +0000 Initial implementation of MUC wocky/Makefile.am | 2 + wocky/wocky-muc.c | 1366 +++++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-muc.h | 189 ++++++++ 3 files changed, 1557 insertions(+) commit ce72fdaedee70dc717da2851f82d8c6dcf7c5aec Author: Vivek Dasmohapatra Date: Tue Dec 8 15:48:50 2009 +0000 Add MUC namespaces. wocky/wocky-namespaces.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) commit 9b827aa71552d051bf28ac60d8bb66181d200063 Author: Vivek Dasmohapatra Date: Tue Nov 24 17:45:32 2009 +0000 wocky_xmpp_node_unpack_error -> wocky_xmpp_error_unpack_node Function renamed and moved because it now needs definitions from both wocky-xmpp-node.h and wocky-xmpp-error.h in its signature. This allows the function to extract the WockyXmppError enum value matching the error stanza as well, which means users can switch() on the canonical enum value rather than wocky_strdiff()ing the error. tests/wocky-xmpp-node-test.c | 8 +++-- wocky/wocky-connector.c | 77 +++++++++++++++++++++++++-------------- wocky/wocky-xmpp-error.c | 86 ++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-error.h | 9 +++++ wocky/wocky-xmpp-node.c | 81 ----------------------------------------- wocky/wocky-xmpp-node.h | 8 ----- 6 files changed, 150 insertions(+), 119 deletions(-) commit e468cb3f562ba0298863dd323f25785ff288237c Author: Vivek Dasmohapatra Date: Fri Nov 13 19:17:00 2009 +0000 Make sure the lowest handler id returned by wocky_porter_register_handler is 1. wocky/wocky-porter.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) commit e0231c9df2264a6d182efd9485e3fa5070bf8838 Author: Vivek Dasmohapatra Date: Thu Nov 12 20:33:03 2009 +0000 Document wocky_porter_register_handler as it is subtle. We depend on the bare-jid-matches-all-resources behaviour, as do other parts of wocky and/or gabble, so make sure it is recorded explicitly in the docs. wocky/wocky-porter.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) commit 9de9e9e066e9f30a934fbf821962458c4442cec9 Author: Vivek Dasmohapatra Date: Tue Dec 8 14:38:51 2009 +0000 Indentation trivia. tests/wocky-tls-test.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) commit 64f7c3b7390d9362f06de42019ff486a583b6f1b Author: Vivek Dasmohapatra Date: Tue Dec 8 14:34:37 2009 +0000 Elide comments which no longer apply as we no longer use SSL_ pending/peek. wocky/wocky-openssl.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) commit ba418e28897c300eb569d39dc94ba745f70f4c64 Author: Vivek Dasmohapatra Date: Tue Dec 8 14:25:38 2009 +0000 Fix an infinite io pseudo-read case in the OpenSSL backend. wocky/wocky-openssl.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) commit 8205a202f384717e84ae0673bb9e3565d08c5343 Author: Vivek Dasmohapatra Date: Tue Dec 8 14:25:02 2009 +0000 Write 5 records and alternate the payloads, to catch the SSL_peek infinite loop. tests/wocky-tls-test.c | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) commit b656cea75f64b9668608196f9743a06c9dcbde74 Author: Vivek Dasmohapatra Date: Mon Dec 7 16:57:39 2009 +0000 Tweak result error/gssize setting logic slightly. wocky/wocky-openssl.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) commit 702cf932702d80950b41ae1c5566e0f253477b2d Author: Vivek Dasmohapatra Date: Mon Dec 7 15:56:03 2009 +0000 Unnecessary error == NULL test removed, use g_set_error. wocky/wocky-openssl.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) commit 5e835ee2b717c467e6a639a69e6cb26ec423f61e Author: Vivek Dasmohapatra Date: Mon Dec 7 15:50:29 2009 +0000 There are, in fact, no errors we want to ignore/retry in _ready_ready. wocky/wocky-openssl.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) commit f939baf19d6a8954f75c6be72991715a0639f3a2 Author: Vivek Dasmohapatra Date: Mon Dec 7 15:28:12 2009 +0000 Move code from _result_boolean to _try_operation, reduce logic duplication. wocky/wocky-openssl.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) commit 0277c07727561f56e8e2f8c7e7920cb5f78d3f4a Author: Vivek Dasmohapatra Date: Mon Dec 7 15:17:34 2009 +0000 Detect renegotiation attempts when trying SSL_peek as well as SSL_read. wocky/wocky-openssl.c | 86 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 32 deletions(-) commit dec48abfe9390655299a8f717b3510c6c8632923 Author: Sjoerd Simons Date: Mon Dec 7 12:36:07 2009 +0000 Make the openssl test not be openssl specific Change the test to use the new modes in the WockyTestStream to force the way the openssl backend reads in the various records. This allows us to mostly use the test in case we're using the GnuTLS backend as well Also test for that the operation actually completes asynchronously. tests/Makefile.am | 15 +- tests/wocky-openssl-test.c | 225 ----- tests/wocky-test-openssl-server.c | 1915 ------------------------------------- tests/wocky-test-openssl-server.h | 123 --- tests/wocky-tls-test.c | 266 ++++++ 5 files changed, 271 insertions(+), 2273 deletions(-) commit d80a5a003aa42122fb5fea973c4e07596a925bf8 Author: Sjoerd Simons Date: Mon Dec 7 12:23:30 2009 +0000 Don't reimplement g_simple_async_result_is_valid wocky/wocky-openssl.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) commit e725b215f4490b04035b33dcf8ea171a88940213 Author: Sjoerd Simons Date: Mon Dec 7 12:22:47 2009 +0000 If there is data to read directly make sure we still return asynchronously wocky/wocky-openssl.c | 52 +++++++++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 22 deletions(-) commit 5c349ed383080afbf634a8322e3aba56b94ef7f0 Author: Sjoerd Simons Date: Mon Dec 7 12:17:07 2009 +0000 Add API to enable different reading modes tests/wocky-test-stream.c | 47 ++++++++++++++++++++++++++++++++++++----------- tests/wocky-test-stream.h | 13 +++++++++++++ 2 files changed, 49 insertions(+), 11 deletions(-) commit 9546b329c81630a8e20c016ea1ae63642a2cf50f Author: Sjoerd Simons Date: Mon Dec 7 12:10:48 2009 +0000 Fix the logic for detecting when there is more to read tests/wocky-test-stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit b5a514d57985f4b3ed9fd8bce39cca5695eef952 Author: Sjoerd Simons Date: Mon Dec 7 12:05:13 2009 +0000 Add the ability to cork input streams tests/wocky-test-stream.c | 16 ++++++++++++++++ tests/wocky-test-stream.h | 2 ++ 2 files changed, 18 insertions(+) commit 5fbaccae83d908a434aca9c9b90a88ac1748fe52 Author: Sjoerd Simons Date: Mon Dec 7 11:58:35 2009 +0000 Force close the porter after cancelling close tests/wocky-porter-test.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) commit 890c40f40b37064b8b28d2c417e9a3aedddb4bdf Author: Vivek Dasmohapatra Date: Fri Dec 4 14:31:56 2009 +0000 Test for 1.x records buffered n+1 records buffered edge cases for OpenSSL. tests/Makefile.am | 13 + tests/wocky-openssl-test.c | 225 +++++ tests/wocky-test-openssl-server.c | 1915 +++++++++++++++++++++++++++++++++++++ tests/wocky-test-openssl-server.h | 123 +++ 4 files changed, 2276 insertions(+) commit 382e4218dc82c669f430b5f1c5fae15c9a9ddd75 Author: Vivek Dasmohapatra Date: Fri Dec 4 01:58:58 2009 +0000 SSL_pending is unreliable: Use SSL_peek instead. wocky/wocky-openssl.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) commit 7a34217b5e011ee189978ea19b7cd020f4127bb1 Author: Vivek Dasmohapatra Date: Wed Dec 2 15:26:32 2009 +0000 Clean up OpenSSL/gio error handling logic (misc bugs). wocky/wocky-openssl.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 8 deletions(-) commit a5dd54410e64ad76eabcf19f0ca42c17bb81fd05 Author: Vivek Dasmohapatra Date: Wed Dec 2 15:22:41 2009 +0000 OpenSSL BIO's may have records left after SSL_read, detect to avoid blocking. wocky/wocky-openssl.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) commit d2d7917c673fbe0f10cc54a3f3876dd4d41b285b Author: Vivek Dasmohapatra Date: Thu Nov 26 17:34:59 2009 +0000 Implement close_fn class method for openssl based tls conn as well as gnutls. wocky/wocky-openssl.c | 10 ++++++++++ 1 file changed, 10 insertions(+) commit 3852a8a1076453800aa3ee8d46cfae3a1e1d01e3 Author: Vivek Dasmohapatra Date: Thu Nov 26 17:33:54 2009 +0000 Detect async EOF conditions as well as read errors (gssize of 0 => EOF). wocky/wocky-openssl.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) commit 7bf33fafd29360523bb51405f85dceb3be3ac9ca Author: Vivek Dasmohapatra Date: Wed Nov 25 18:24:30 2009 +0000 Generated DH parameter functions need protos to stop a -Werror failure. wocky/wocky-openssl-dh1024.c | 1 + wocky/wocky-openssl-dh2048.c | 1 + wocky/wocky-openssl-dh4096.c | 1 + wocky/wocky-openssl-dh512.c | 1 + 4 files changed, 4 insertions(+) commit eeef0d2e4c27228316c6c1b7c163c96d328dc5a1 Author: Sjoerd Simons Date: Mon Dec 7 11:36:14 2009 +0000 Check for the right definition wocky/wocky-xmpp-reader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 5e662895f7c0249f58fb2f8dd4082c721426522c Author: Vivek Dasmohapatra Date: Fri Nov 27 16:21:02 2009 +0000 Remove unused cancellable support in callback, rename according to convention. tests/wocky-porter-test.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) commit e8c90f37dff8e7a0a4627c3357256cf1d2219bc2 Author: Vivek Dasmohapatra Date: Fri Nov 27 15:40:17 2009 +0000 Debug should contain expected JID as well as the mismatched JID we actually got. wocky/wocky-porter.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit a561b6587ffc3a8e55048fe5d8a115249fba54e7 Author: Vivek Dasmohapatra Date: Fri Nov 27 14:55:55 2009 +0000 Normalise handler's copy of the 'to' JID and the 'from' JID we compare it to. wocky/wocky-porter.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) commit 83fe481855f9e4eb891ea4077aa7ba8d11972362 Author: Vivek Dasmohapatra Date: Fri Nov 27 14:52:49 2009 +0000 Test the iq-recipient/sender-JIDs-are-not-normalised case. tests/wocky-porter-test.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) commit 4a157c055d645bb2b975250b3386c5506c7024e4 Author: Vivek Dasmohapatra Date: Fri Nov 27 14:51:37 2009 +0000 wocky_normalise_jid implemented in -utils. wocky/wocky-utils.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-utils.h | 2 ++ 2 files changed, 52 insertions(+) commit 195db67317d726d6d14c8e5c07056bd877dc17b4 Author: Vivek Dasmohapatra Date: Wed Nov 25 17:32:54 2009 +0000 Style trivia flagged by check. wocky/wocky-sasl-digest-md5.h | 2 +- wocky/wocky-sasl-plain.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) commit d56ba71a576a08f6dda5a1c18081e7d61367b08f Author: Vivek Dasmohapatra Date: Wed Nov 25 17:18:52 2009 +0000 Cope with alternate format on test failure, exit 1 if any tests failed. The gtester report contains a transition in between each failed test and subsequent tests. Cope with that when generating the summary. Exit with non-zero status of any tests failed so make can pick up on the error. tests/summarise-tests.sh | 86 +++++++++++++++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 30 deletions(-) commit 6efb1dd1650c20723a8f57445be96b5e427cc648 Author: Vivek Dasmohapatra Date: Wed Nov 25 16:27:35 2009 +0000 Summarise test results at end (to help catch early failures). tests/Makefile.am | 3 ++ tests/summarise-tests.sh | 78 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) commit 13fe3ce29b5dab130ef3a79fdaa2e0e1c9e9cd1e Author: Sjoerd Simons Date: Tue Nov 24 22:03:44 2009 +0000 Never chain up to the real resolver, tests shouldn't hit the network tests/test-resolver.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) commit 52068812840405391668f201d81bc1103c084ce7 Author: Sjoerd Simons Date: Mon Nov 23 17:40:52 2009 +0000 Don't assert that there is no error when there should be errors tests/wocky-xmpp-reader-test.c | 2 -- 1 file changed, 2 deletions(-) commit 64271a34056ce93014c07bdcb903a44c869071d2 Author: Sjoerd Simons Date: Mon Nov 23 17:07:31 2009 +0000 Reset the authentication status before calling the callback We can't rely on the user to call our _finish method, so depending on that for resetting is wrong. Also at the point when the operation has finished the object should always be in the same state, ready to authenticate again (Not useful for the success case, but good for consistency) wocky/wocky-sasl-auth.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) commit 145c376a5e3d9c288722af37a7b8cb9a3afa519d Author: Sjoerd Simons Date: Mon Nov 23 17:06:37 2009 +0000 Remove unused state member wocky/wocky-sasl-auth.c | 11 ----------- 1 file changed, 11 deletions(-) commit 88834a8539c975d97b441a0a2d95742c2f3834a9 Author: Sjoerd Simons Date: Mon Nov 23 17:04:12 2009 +0000 Remove api to get the used sasl mechanism As it stands this API was broken, but futhermore it's not useful for a client to check after the fact which mechanism was used. wocky/wocky-connector.c | 18 ------------------ wocky/wocky-connector.h | 2 -- wocky/wocky-sasl-auth.c | 18 ++---------------- wocky/wocky-sasl-auth.h | 3 --- 4 files changed, 2 insertions(+), 39 deletions(-) commit da9fdc7d053e562a1470f0861c98280e77367e0d Author: Sjoerd Simons Date: Mon Nov 23 16:57:26 2009 +0000 The bind should always succeed immediately as SO_REUSEADDR is set tests/wocky-connector-test.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) commit 17a33a93fc761199c61e246c73901a1776c70d51 Author: Sjoerd Simons Date: Mon Nov 23 16:56:54 2009 +0000 Check the mechanism from what went on the wire, not what the connector thinks tests/wocky-connector-test.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) commit 9eeb7a6db8d412545cab7aa9ce7bb6d57bfc868b Author: Sjoerd Simons Date: Mon Nov 23 16:50:18 2009 +0000 Add API to get the last used SASL mechanism from the test server tests/wocky-test-connector-server.c | 14 ++++++++++++++ tests/wocky-test-connector-server.h | 2 ++ 2 files changed, 16 insertions(+) commit f8aa7c3656204929620a8fc07011f5568655ab27 Author: Sjoerd Simons Date: Mon Nov 23 16:49:36 2009 +0000 Add API to get the last selected mechanism from the Sasl server tests/wocky-test-sasl-auth-server.c | 21 +++++++++++++++++---- tests/wocky-test-sasl-auth-server.h | 2 ++ 2 files changed, 19 insertions(+), 4 deletions(-) commit ed0c55901d06448223f841b301ec12f5dc5934b7 Author: Sjoerd Simons Date: Mon Nov 23 16:27:36 2009 +0000 Run the test server in process tests/wocky-connector-test.c | 121 ++++++++++++++++++++----------------------- 1 file changed, 57 insertions(+), 64 deletions(-) commit 16f32f490409f9bf27882ae4c21211f6f31144fa Author: Sjoerd Simons Date: Mon Nov 23 16:20:25 2009 +0000 Add an async teardown server to the server tests/wocky-connector-test.c | 2 +- tests/wocky-test-connector-server.c | 261 +++++++++++++++++++++++++++++++----- tests/wocky-test-connector-server.h | 10 +- 3 files changed, 239 insertions(+), 34 deletions(-) commit b176b4aec466773e9c85e67a26737bd9dc999672 Author: Sjoerd Simons Date: Mon Nov 23 15:58:21 2009 +0000 Make the ssl handshaking async tests/wocky-test-connector-server.c | 95 +++++++++++++++++++++---------------- 1 file changed, 54 insertions(+), 41 deletions(-) commit 97ae8fb5f40ab45aa0641fda49044b2a70fa3223 Author: Sjoerd Simons Date: Mon Nov 23 15:40:04 2009 +0000 Also complete the auth operation on failure The _finish operation should probably return an operation if the authentication failed, but nothing currently checks this and the test connector server would be unhappy if we start doing this. Should be refactored at some point though. tests/wocky-test-sasl-auth-server.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) commit c5d3ffcb64e12762df6d73b4ec4667f0aa317f7f Author: Sjoerd Simons Date: Mon Nov 23 15:38:46 2009 +0000 Make the sasl completion race free tests/wocky-test-sasl-auth-server.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) commit 4fa140cc5943bd7368b40a5dc39d308ef758e23c Author: Sjoerd Simons Date: Mon Nov 23 15:07:23 2009 +0000 Let _start take a cancellable and weave it through tests/wocky-test-connector-server.c | 5 ++++- tests/wocky-test-sasl-auth-server.c | 38 ++++++++++++++++++++++++------------- tests/wocky-test-sasl-auth-server.h | 8 ++++++-- 3 files changed, 35 insertions(+), 16 deletions(-) commit 27db2fdc7865d1cbfe0320ac6671c06be5ff4178 Author: Sjoerd Simons Date: Mon Nov 23 15:05:45 2009 +0000 Warn if we have an outstanding result on dispose tests/wocky-test-sasl-auth-server.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) commit 79f36bfbe8c21750763759fcd1f05be7471faa95 Author: Sjoerd Simons Date: Mon Nov 23 15:03:47 2009 +0000 Implement the close virtual function wocky/wocky-tls.c | 11 +++++++++++ 1 file changed, 11 insertions(+) commit b3857a610ec0e0fd62f46675ea9133857867ba9b Author: Sjoerd Simons Date: Mon Nov 23 15:03:20 2009 +0000 warn if there are outstanding input or output operations when disposing wocky/wocky-xmpp-connection.c | 3 +++ 1 file changed, 3 insertions(+) commit 426167511e8bcc82350ccfd8748098bc0aa8ec97 Author: Sjoerd Simons Date: Fri Nov 20 12:19:18 2009 +0000 Fix coding style tests/wocky-test-sasl-handler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit be827a7aae280daf91d5a9b81debef16316f3a22 Author: Sjoerd Simons Date: Fri Nov 20 12:19:06 2009 +0000 This is not python, there is no == for strings tests/wocky-connector-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 7ec6eb82587f414677cbb438d897bbd0b5d99d0a Author: Sjoerd Simons Date: Fri Nov 20 11:57:08 2009 +0000 Fix typo in documentation wocky/wocky-sasl-handler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit f52707f94ecf18df1f559dc6b1b034c2261fb32e Merge: 822cb9c 2ce5d30 Author: Sjoerd Simons Date: Tue Nov 24 17:53:44 2009 +0000 Merge remote branch 'daf/sasl' commit 822cb9c779e34884774be12600779e21325586e6 Author: Vivek Dasmohapatra Date: Mon Nov 23 20:15:25 2009 +0000 Change g_message to DEBUG, explain number logged is DH bit size. wocky/wocky-tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 2f61ae80679071a9eeae699d3b9f20754313a974 Author: Vivek Dasmohapatra Date: Mon Nov 23 19:40:14 2009 +0000 Cache DH parameters on generation (for each valid DH param size) This speeds up setup of subsequent wocky TLS server sessions significantly. (GnuTLS only, OpenSSL can't generate DH params on the fly and so uses a completely static set of DH parameters for servers anyway). Has no effect whatsoever on wocky TLS clients. wocky/wocky-tls.c | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) commit 2ce5d30c5914780c41e0fe62d32613e82ee65ea5 Author: Dafydd Harries Date: Thu Nov 19 14:11:04 2009 -0500 give SASL handlers a plain flag and skip handlers based on it tests/wocky-test-sasl-handler.c | 1 + wocky/wocky-sasl-auth.c | 3 +++ wocky/wocky-sasl-digest-md5.c | 1 + wocky/wocky-sasl-handler.c | 6 ++++++ wocky/wocky-sasl-handler.h | 6 ++++++ wocky/wocky-sasl-plain.c | 1 + 6 files changed, 18 insertions(+) commit 661aba6e06097ca073acdf157159befb00251bbf Author: Dafydd Harries Date: Thu Nov 19 14:02:57 2009 -0500 document how handler/mechanism selection works wocky/wocky-sasl-auth.c | 6 ++++++ 1 file changed, 6 insertions(+) commit 867ff3daca3abe47a0d602dffe5fe776ebfa8e05 Author: Dafydd Harries Date: Thu Nov 19 13:58:04 2009 -0500 simplify SASL handler error logic wocky/wocky-sasl-auth.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) commit 89640d31d00746407d552e5f694e544a5f878e38 Author: Dafydd Harries Date: Thu Nov 19 13:49:36 2009 -0500 put "Server send" into the past tense where appropriate wocky/wocky-sasl-auth.c | 4 ++-- wocky/wocky-sasl-auth.h | 2 +- wocky/wocky-sasl-digest-md5.c | 10 +++++----- wocky/wocky-sasl-plain.c | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) commit 6a51d50816f6d7b987437905351195b202b76b07 Author: Dafydd Harries Date: Thu Nov 19 13:45:07 2009 -0500 add some documentation for the WockySaslHandler interface wocky/wocky-sasl-handler.h | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) commit da936335d0919445a7ef9830d9c135ae4f592918 Author: Dafydd Harries Date: Thu Nov 19 13:25:35 2009 -0500 use wocky_strdiff instead of strcmp tests/wocky-test-sasl-auth-server.c | 10 +++++----- wocky/wocky-sasl-auth.c | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) commit 78885334038f201e9a4dbaf1bd04d004fd35b32a Author: Dafydd Harries Date: Tue Nov 17 20:02:22 2009 -0500 allow adding extra handlers to WockySaslAuth instances tests/Makefile.am | 2 ++ tests/wocky-test-sasl-auth-server.c | 44 ++++++++++++++--------- tests/wocky-test-sasl-auth.c | 15 ++++++++ tests/wocky-test-sasl-handler.c | 70 +++++++++++++++++++++++++++++++++++++ tests/wocky-test-sasl-handler.h | 42 ++++++++++++++++++++++ wocky/wocky-sasl-auth.c | 35 +++++++++++++++++++ wocky/wocky-sasl-auth.h | 3 ++ 7 files changed, 194 insertions(+), 17 deletions(-) commit 9dfc9defae7aa003a8ce4a49338fab710c7f6ce0 Author: Dafydd Harries Date: Tue Nov 17 20:03:04 2009 -0500 allow SASL handler failure callbacks to not set errors wocky/wocky-sasl-auth.c | 8 ++++++++ 1 file changed, 8 insertions(+) commit c4fa4828be9e33528a23a3ece6238ee60f7e47aa Author: Dafydd Harries Date: Tue Nov 17 20:02:52 2009 -0500 double check SASL test results tests/wocky-test-sasl-auth.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) commit 81ea6725fb69b09be86e5e0412b2cd893a52613a Author: Dafydd Harries Date: Tue Nov 17 15:55:12 2009 -0500 factor out SASL handler selection wocky/wocky-sasl-auth.c | 50 +++++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 18 deletions(-) commit 82af20ab6aabc3c4fe8571496534b3f3b8779879 Author: Dafydd Harries Date: Tue Nov 17 11:56:46 2009 -0500 declare WockySaslHandlerIface properly wocky/wocky-sasl-handler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 71b215e0b41f78efef67f35160fb8e256ac8b2ad Author: Dafydd Harries Date: Fri Nov 13 02:00:36 2009 -0500 make WockySaslHandler a GInterface Make WockySaslDigestMd5 and WockySaslPlain implementations of it. wocky/Makefile.am | 4 + wocky/wocky-sasl-auth.c | 532 +--------------------------------------- wocky/wocky-sasl-digest-md5.c | 556 ++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-sasl-digest-md5.h | 53 ++++ wocky/wocky-sasl-handler.c | 58 +++-- wocky/wocky-sasl-handler.h | 40 +-- wocky/wocky-sasl-plain.c | 214 ++++++++++++++++ wocky/wocky-sasl-plain.h | 50 ++++ 8 files changed, 939 insertions(+), 568 deletions(-) commit 7a1cd447ce46b11912019466c23c06b3100ee193 Author: Dafydd Harries Date: Thu Nov 12 20:52:46 2009 -0500 generalize provision of initial response By which I mean the response sent with the authentication initiation, as per the SASL RFC. The digest MD5 code also refers to an initial response but it means the response to the first challenge from the server. The RFC term is poor, but probably best to follow it. wocky/wocky-sasl-auth.c | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) commit 79c31ca8cda88a553f550858731e86718e09d378 Author: Dafydd Harries Date: Thu Nov 12 20:27:32 2009 -0500 give SASL handlers independent private state wocky/wocky-sasl-auth.c | 137 ++++++++++++++++++++++++++++++--------------- wocky/wocky-sasl-auth.h | 3 + wocky/wocky-sasl-handler.c | 5 +- wocky/wocky-sasl-handler.h | 2 + 4 files changed, 102 insertions(+), 45 deletions(-) commit 3c058fc7756dac85f1414d35cf987b777327046b Author: Dafydd Harries Date: Thu Nov 12 20:14:45 2009 -0500 remove code for impossible case wocky/wocky-sasl-auth.c | 9 --------- 1 file changed, 9 deletions(-) commit 378e38877dd72b5108811ea857992ddbfb222fe9 Author: Dafydd Harries Date: Thu Nov 12 20:13:48 2009 -0500 auth_reset(): free and clear handler wocky/wocky-sasl-auth.c | 6 ++++++ 1 file changed, 6 insertions(+) commit 561db1c2b0d1981b38aba6a65a9a543eb5e48ee1 Author: Dafydd Harries Date: Thu Nov 12 18:25:57 2009 -0500 make WockySaslChallengeFunc return the response to send wocky/wocky-sasl-auth.c | 88 +++++++++++++++++++++++++++------------------- wocky/wocky-sasl-handler.c | 4 +-- wocky/wocky-sasl-handler.h | 4 +-- 3 files changed, 56 insertions(+), 40 deletions(-) commit 1634e77b712036d82f3d0080b466cc93dd2b5523 Author: Dafydd Harries Date: Sun Nov 8 10:24:54 2009 -0500 introduce WockySaslHandler abstraction and use it in WockySaslAuth wocky/Makefile.am | 2 + wocky/wocky-sasl-auth.c | 141 ++++++++++++++++++++++++--------------------- wocky/wocky-sasl-auth.h | 1 + wocky/wocky-sasl-handler.c | 58 +++++++++++++++++++ wocky/wocky-sasl-handler.h | 64 ++++++++++++++++++++ 5 files changed, 200 insertions(+), 66 deletions(-) commit 50c2bd9a0d0d2091ad71e9c6ee541cc42f0e1e1f Author: Dafydd Harries Date: Tue Nov 10 18:32:18 2009 -0500 factor out setting mechanism name on stanza wocky/wocky-sasl-auth.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) commit 87be0be5449ab592db1688c2034bab6f8431de14 Author: Dafydd Harries Date: Mon Nov 9 15:28:35 2009 -0500 call auth_succeeded implicitly if success handler didn't return an error wocky/wocky-sasl-auth.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) commit b65faa10d8de11feb00c4bf2196f76c7f7e2bf90 Author: Dafydd Harries Date: Mon Nov 9 15:12:03 2009 -0500 replace usage of auth_failed with GErrors wocky/wocky-sasl-auth.c | 90 ++++++++++++++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 35 deletions(-) commit 4ba6a316ac5ecfa6b2f408bc7aba6500e2e38a66 Author: Dafydd Harries Date: Mon Nov 9 14:03:07 2009 -0500 use string instead of enum to identify SASL mechanisms tests/wocky-connector-test.c | 183 +++++++++++++++++++++---------------------- wocky/wocky-connector.c | 9 ++- wocky/wocky-connector.h | 2 +- wocky/wocky-sasl-auth.c | 86 +++++++++++--------- wocky/wocky-sasl-auth.h | 8 +- 5 files changed, 149 insertions(+), 139 deletions(-) commit 6f4a02d6c9856445b33b166a778116e94675fa25 Author: Dafydd Harries Date: Mon Nov 9 12:09:33 2009 -0500 factor out generation of initial SASL PLAIN response wocky/wocky-sasl-auth.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) commit 197d5d733dfebf66d823c2996a71463595535c8a Author: Will Thompson Date: Tue Nov 17 14:33:28 2009 +0000 Don't explicitly define the "all" debug flag g_parse_debug_string () does this for us: > If string is equal to "all", all flags are set. If string is equal to > "help", all the available keys in keys are printed out to standard > error. wocky/wocky-debug.c | 1 - 1 file changed, 1 deletion(-) commit 0dff81f9c868bb1801ba8bfa36bbd78bfa90e275 Author: Sjoerd Simons Date: Fri Nov 13 18:14:57 2009 +0000 nprefix should be gchar * wocky/wocky-xmpp-node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit bdbf0c690a3f10f6549b04003521cf95709d1541 Author: Sjoerd Simons Date: Thu Nov 12 16:09:22 2009 +0000 Make it easier to debug incoming/outgoing stanzas Use the stanza debugging function when the xmpp debug flag is used. This is a lot more readable then the non-pretty printed data that comes over the network. To see the raw network data, use the net debug flag instead wocky/wocky-xmpp-reader.c | 6 ++++-- wocky/wocky-xmpp-writer.c | 8 ++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) commit 3eef43e7d584f87e6eb5912f5b75912e3186b339 Author: Sjoerd Simons Date: Thu Nov 12 16:05:58 2009 +0000 Actually implement wocky_debug_stanza wocky/wocky-debug.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) commit f134d2374df47ccc5389224d69763e219dbbbda6 Author: Sjoerd Simons Date: Thu Nov 12 15:59:11 2009 +0000 Make the stanza to string conversion not be xml The stanza to string utility function is meant to be used for debugging purposes. Make it be unlike XML so it can't be confused with the data that's actually send over the wire. wocky/wocky-xmpp-node.c | 73 ++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 41 deletions(-) commit dafa5824563b3bcaa4d7a8ea3d6c0662a5174cad Merge: e1fe6a1 81898f6 Author: Dafydd Harries Date: Thu Nov 12 12:26:14 2009 -0500 Merge branch 'misc' Reviewed-by: Vivek Dasmohapatra commit 81898f6a98a668f8ecf7c6247498c9cb76a7bbc4 Author: Dafydd Harries Date: Thu Nov 12 12:11:09 2009 -0500 use AC_HELP_STRING for --with-tls configure option configure.ac | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit b0a93575dad899e1fa71b144ae7773f3cec8648d Author: Dafydd Harries Date: Wed Nov 11 21:11:29 2009 -0500 use g_assert_no_error() tests/wocky-connector-test.c | 2 +- tests/wocky-test-sasl-auth.c | 2 +- tests/wocky-xmpp-reader-test.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) commit de59db1f75b7c1f54009f7d3e65c720893a7393a Author: Dafydd Harries Date: Wed Nov 11 21:13:55 2009 -0500 configure.ac: override official release logic Because the current version, 0.0.0.0, ends in a zero, it's assumed that this is a release version, so -Werror is disabled. For now, just declare that it's not a release. Possibly an explicit release flag would be better than nano version which are always 0 or 1. configure.ac | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) commit 56c29352f61a95090b6bbe87dea0e8a388fbce54 Author: Dafydd Harries Date: Tue Nov 3 14:01:25 2009 -0500 test SASL server: pass cancellable to _recv_stanza This avoids a memory leak where the connection is closed while a message receive is pending. tests/wocky-test-sasl-auth-server.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) commit e1a9100ec4e4de9bb1cfde9dc4e759608f50a2c9 Author: Cosimo Cecchi Date: Thu Nov 5 15:45:24 2009 +0100 Expand docs for WockyContactFactory wocky/wocky-contact-factory.c | 59 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) commit ea6276c3ed46d69ef4da3f2d43babfcb904c4ac1 Author: Cosimo Cecchi Date: Wed Nov 4 18:21:16 2009 +0100 Fix some typos and missing refs in the WockyPorter doc. wocky/wocky-porter.c | 43 ++++++++++++++++++++++--------------------- wocky/wocky-porter.h | 4 ++-- 2 files changed, 24 insertions(+), 23 deletions(-) commit 756952ce4c7443ae3e97ee2f131a08d820904d58 Author: Guillaume Desmottes Date: Wed Aug 26 11:11:30 2009 +0100 document the WockyPorter struct wocky/wocky-porter.h | 6 ++++++ 1 file changed, 6 insertions(+) commit f4f42983f3acad26df1a54777790a034893d210a Author: Guillaume Desmottes Date: Wed Aug 26 11:10:47 2009 +0100 porter: document stanza handlers wocky/wocky-porter.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-porter.h | 11 +++++++++++ 2 files changed, 62 insertions(+) commit b5bbe72bfb05803c571da6802bbbd46f6fed9e29 Author: Guillaume Desmottes Date: Tue Aug 25 17:46:38 2009 +0100 porter: document close methods wocky/wocky-porter.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) commit d5a099b4aa86ca64e66d24510131bca84d52af57 Author: Guillaume Desmottes Date: Tue Aug 25 17:12:32 2009 +0100 porter: document stanza sending functions wocky/wocky-porter.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) commit c1caea0c9fc86296c93864ddba81eb4bf17313a8 Author: Guillaume Desmottes Date: Tue Aug 25 16:20:57 2009 +0100 document WockyPorterError wocky/wocky-porter.h | 11 +++++++++++ 1 file changed, 11 insertions(+) commit e5ceb1a3ee07d569e74e82b4caf750f818c14aaa Author: Guillaume Desmottes Date: Tue Aug 25 16:13:41 2009 +0100 porter: document property and signals wocky/wocky-porter.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) commit d79eac9089777fb52279ecca81f73b609814beb7 Author: Cosimo Cecchi Date: Wed Nov 4 17:52:32 2009 +0100 Write gtk-doc entries for WockyBareContact. wocky/wocky-bare-contact.c | 82 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 4 deletions(-) commit e1fe6a1a8ca841efca7c9f7bd409f4a76e68d65a Author: Cosimo Cecchi Date: Wed Nov 4 17:04:38 2009 +0100 Fix some typos in the gtk-doc annotations. wocky/wocky-xmpp-reader.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) commit d02987e47e4a4a9e967365a06799449c85f43ec9 Author: Vivek Dasmohapatra Date: Tue Nov 3 15:59:14 2009 +0000 Expand + comment the \ escape parsing logic for " quoted SASL challenge values. wocky/wocky-sasl-auth.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) commit 6727760976ff85623cbf19c1f10bcbaff94a8cb5 Author: Vivek Dasmohapatra Date: Tue Nov 3 15:21:42 2009 +0000 Handle \ escapes in quoted SASL challenge parameters. wocky/wocky-sasl-auth.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit 1eac8915ae3dea0d8134a75aac29282828b13686 Author: Vivek Dasmohapatra Date: Tue Nov 3 15:08:29 2009 +0000 Test for \ escapes in " quoted challenge values. tests/wocky-test-sasl-auth-server.c | 70 +++++++++++++++++++++++++++++++++++++ tests/wocky-test-sasl-auth-server.h | 1 + tests/wocky-test-sasl-auth.c | 13 ++++--- 3 files changed, 79 insertions(+), 5 deletions(-) commit 65ec8f42aa1d59c06cfe6ef5c0659666d9132b2a Author: Vivek Dasmohapatra Date: Mon Nov 2 18:17:11 2009 +0000 Implement server-adds-wacky-whitespace-to-challenge problem, test SASL with it. tests/wocky-test-sasl-auth-server.c | 103 +++++++++++++++++++++++++++++++++++- tests/wocky-test-sasl-auth-server.h | 1 + tests/wocky-test-sasl-auth.c | 7 ++- 3 files changed, 108 insertions(+), 3 deletions(-) commit 59c6a1d57893ccebebf1e410f12c4c3b21df01e7 Author: Vivek Dasmohapatra Date: Mon Nov 2 15:37:50 2009 +0000 SASL challenge tokens may be separated by optional whitespace, cope with these. wocky/wocky-sasl-auth.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) commit 69679f560c5490668840f29c582d946bd7f0ee70 Author: Vivek Dasmohapatra Date: Thu Oct 22 17:49:22 2009 +0100 Comments explaining the new avoid-double-close test. tests/wocky-porter-test.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) commit 5a80eeac888503d53b5569e173269d4b32f9573c Author: Vivek Dasmohapatra Date: Thu Oct 22 16:19:08 2009 +0100 Comment explaining the importance of the timing of when remote_closed is set. wocky/wocky-porter.c | 3 +++ 1 file changed, 3 insertions(+) commit 1cba28f9b5cdb45fa98acee8c5f75f13e81bf939 Author: Vivek Dasmohapatra Date: Thu Oct 22 15:56:28 2009 +0100 Test for the double-force-close on remote-error case. tests/wocky-porter-test.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) commit 871b439aa9de4f4ed5f837352f88756f8164423d Author: Vivek Dasmohapatra Date: Tue Oct 20 19:54:32 2009 +0100 Fixes calls to wocky_xmpp_connection_force_close_async. DEBUG gives file+line. Never put more than 1 wocky_xmpp_connection_force_close_async in flight for a given connection. g_object_ref the wocky porter passed in as the user_data to the call so that it is guaranteed to still be alive when the callback happens. Report an error in idle if we try to force a shutdown twice. DEBUG gives file + line now. wocky/wocky-debug.h | 3 ++- wocky/wocky-porter.c | 56 +++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 49 insertions(+), 10 deletions(-) commit 3ac75cc16227e4dc39aecd9d9fa659c5d5cf1698 Author: Vivek Dasmohapatra Date: Wed Oct 21 12:21:40 2009 +0100 Put some actual aborted-iq-node info in the debug output. wocky/wocky-porter.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) commit 1f2e07aab5c7d57d6aa3021a529376125dab2912 Author: Vivek Dasmohapatra Date: Wed Oct 21 12:19:27 2009 +0100 Value tested in if condition clause is a pointer, not a boolean. wocky/wocky-porter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 3ab69e056517fac671e3f1db06f4973538c42584 Author: Vivek Dasmohapatra Date: Wed Oct 21 12:18:04 2009 +0100 'forget' the stashed async result earlier, use the local copy i nthe callback. wocky/wocky-porter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit dfc0e61089f9db3946aa53251d7fe5745b202712 Author: Vivek Dasmohapatra Date: Wed Oct 21 12:14:58 2009 +0100 Flag should be set _before_ the signal is fired or some callbacks may not fire. wocky/wocky-porter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 62d54ca0a6e338987f363f0ef979b00e8b6a6a99 Author: Vivek Dasmohapatra Date: Tue Oct 20 19:54:32 2009 +0100 Remove handlers as we abort IQs, and check iq handlers before invoking them. NULL out each handler->result after freeing it. Check handler and/or handler->result before using them. Remove handler form the hash when we abort all pending IQs. wocky/wocky-porter.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) commit 04c77df70f46ecf1386d2d9b24f273d43c953a00 Author: Vivek Dasmohapatra Date: Mon Oct 19 15:17:38 2009 +0100 Certs should not be removed on distclean anymore: nothing to do on clean-local tests/Makefile.am | 4 ---- 1 file changed, 4 deletions(-) commit a7d02c2a6b9811fe63e80bc681933cf52ce0ea25 Author: Vivek Dasmohapatra Date: Mon Oct 19 13:08:38 2009 +0100 Turn openpgp cert support back off. wocky/wocky-tls.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) commit 774eeec1ba1933537897d6d6da4ca14754000924 Author: Vivek Dasmohapatra Date: Fri Oct 16 16:48:08 2009 +0100 Comments explaining gnutls default protocol options we use. wocky/wocky-tls.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) commit 3cfb88f8e8cb76f54b11bab6bd8dde9b798a3c81 Author: Vivek Dasmohapatra Date: Fri Oct 16 15:58:53 2009 +0100 Activate deflate compression, openpgp certs and secure (slow) crypto by default. wocky/wocky-tls.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) commit 3f65748a178c5b7445f58ea21cf38bb2f09646a0 Author: Vivek Dasmohapatra Date: Fri Oct 16 15:44:08 2009 +0100 Fix gnutls session protocol detail setup. Don't set the details then immediately set them back to the defaults. Complain if we can't set the various session options. Complain if we can't set the session credentials. Allow default options to be set via an environment variable. Prio_cache storage not used anymore, using gnutls_priority_set_direct. wocky/wocky-tls.c | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) commit 42441d6581b8eccb0cd81bf080c60b9336d72edd Author: Vivek Dasmohapatra Date: Mon Oct 5 18:24:39 2009 +0100 Overriding gnutls autodetection to use openssl was broken. configure.ac | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 1f0a57f6dd8b75c97eb1087e0ff0d7b966fbff8b Author: Vivek Dasmohapatra Date: Thu Oct 1 19:45:31 2009 +0100 Don't check certtool/datefudge until actually needed to generate a certificate. tests/Makefile.am | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) commit 1beb3ec922476241462ea046ece2acfad0d09234 Author: Vivek Dasmohapatra Date: Mon Oct 5 15:46:57 2009 +0100 Ship openssl files in dist tarball even when building w gnutls and vice versa. wocky/Makefile.am | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) commit 03787b9f06af91ac0acd8f6b52e0b7783fc794d7 Author: Vivek Dasmohapatra Date: Mon Oct 5 15:07:14 2009 +0100 Typos: environnement -> environment; updated doc section title. wocky/wocky-openssl.c | 2 +- wocky/wocky-tls.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) commit 65b6b5fb802c884120428021bbf74edf88758c4b Author: Vivek Dasmohapatra Date: Mon Oct 5 14:48:15 2009 +0100 Comment around SSL_CTX_set_cipher_list explaining how to use it if we want to. wocky/wocky-openssl.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) commit 1e6461d57cc555b087111873cbce46e6a36644ac Author: Vivek Dasmohapatra Date: Mon Oct 5 14:12:33 2009 +0100 Coding style fix. wocky/wocky-openssl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit e2ba67289c6711fe84fe137e97ec9d0df80ed185 Author: Vivek Dasmohapatra Date: Mon Oct 5 13:10:08 2009 +0100 Reduce debugging unless WOCKY_TLS_DEBUG_LEVEL exceeds the async detail level. wocky/wocky-openssl.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) commit 258c62ea0b95c43fabe9c1777d64dfc76280a1cc Author: Vivek Dasmohapatra Date: Mon Oct 5 12:41:26 2009 +0100 Comment explaining arcane reasons behind structure of error_to_string() wocky/wocky-openssl.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) commit 69e631b51d7a812d4d0d04dd7e9164d752e74847 Author: Vivek Dasmohapatra Date: Fri Oct 2 16:35:46 2009 +0100 Removed tmp comments tagging functions for review, warn if BIO alloc fails. wocky/wocky-openssl.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) commit e3fb29ad6a586bfcb2fa8006d66024dde466631e Author: Vivek Dasmohapatra Date: Thu Oct 1 19:05:33 2009 +0100 Check in cert dir copies of certs as well as the openssl hash symlinks thereto. .gitignore | 4 ++-- tests/Makefile.am | 4 +++- tests/certs/cas/a7481a9e.0 | 1 + tests/certs/cas/bb7d74ae.0 | 1 + tests/certs/cas/c5d5c0da.0 | 1 + tests/certs/cas/ca-0-cert.pem | 23 +++++++++++++++++++++++ tests/certs/cas/ca-1-cert.pem | 23 +++++++++++++++++++++++ tests/certs/cas/ca-2-cert.pem | 23 +++++++++++++++++++++++ tests/certs/crl/c5d5c0da.r0 | 1 + tests/certs/crl/ca-0-crl.pem | 13 +++++++++++++ 10 files changed, 91 insertions(+), 3 deletions(-) commit d0977e8aed68ec2169534c35e396b6be0df4146c Author: Vivek Dasmohapatra Date: Thu Oct 1 18:32:48 2009 +0100 Example connect program was missing wocky_init() call, prevented testing. examples/connect.c | 2 ++ 1 file changed, 2 insertions(+) commit 2d5e141cd3030077a5d532d3becd7562f844b760 Author: Vivek Dasmohapatra Date: Thu Oct 1 18:31:39 2009 +0100 Use WOCKY_TEST_SERVER_DEBUG env var to control test server debug independently. tests/wocky-connector-test.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 6325c54e019d535495f59c4a29b9864f0ae16c11 Author: Vivek Dasmohapatra Date: Thu Oct 1 18:30:34 2009 +0100 Pick one of gnutls and openssl automatically, unless the user choose explicitly. configure.ac | 24 ++++++++++++++++++++++-- tests/Makefile.am | 5 +++-- tests/wocky-test-connector-server.c | 6 ++++++ wocky/Makefile.am | 20 +++++++++++++++----- wocky/wocky-connector.h | 7 +++++++ 5 files changed, 53 insertions(+), 9 deletions(-) commit f57076bcd5865e39b4ccc61881b539dec0689175 Author: Vivek Dasmohapatra Date: Thu Oct 1 18:25:15 2009 +0100 WockyTLSSession et al based on OpenSSL (in addition to existing gnutls version) wocky/wocky-openssl-dh1024.c | 30 + wocky/wocky-openssl-dh2048.c | 41 + wocky/wocky-openssl-dh4096.c | 62 ++ wocky/wocky-openssl-dh512.c | 25 + wocky/wocky-openssl.c | 1698 ++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-openssl.h | 102 +++ 6 files changed, 1958 insertions(+) commit bc04e13d7fb4a48b291e0117fef24f220620e6b9 Author: Vivek Dasmohapatra Date: Wed Sep 30 13:04:06 2009 +0100 certtool/datefudge errors should be warnings, tweaked warning messages. tests/Makefile.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit f9601a319d69fd59124c68a0f8be57d4399df0da Author: Guillaume Desmottes Date: Tue Sep 29 17:21:31 2009 +0100 wocky-pep-service: fix include of Wocky files wocky/wocky-pep-service.c | 8 ++++---- wocky/wocky-pep-service.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) commit 198e665a5b8bce4bdfac9cadcaf0eb0f054046d7 Author: Jonny Lamb Date: Fri Sep 25 12:39:16 2009 +0100 Make building the marshal.list quieter. Signed-off-by: Jonny Lamb wocky/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit d0146e0d3e3e295b9711ab9681c81d05e3224f93 Author: Jonny Lamb Date: Thu Sep 24 19:45:00 2009 +0100 Move from shave to automake 1.11's silent rules system. Signed-off-by: Jonny Lamb .gitignore | 5 +-- autogen.sh | 9 ----- configure.ac | 8 ++-- m4/Makefile.am | 3 +- m4/shave.m4 | 102 -------------------------------------------------- shave-libtool.in | 109 ------------------------------------------------------ shave.in | 109 ------------------------------------------------------ tools/Makefile.am | 1 - tools/shave.mk | 1 - wocky/Makefile.am | 9 ++--- 10 files changed, 9 insertions(+), 347 deletions(-) commit b90ce738c61f084ca4854709cda3103c9ef7eff6 Author: Guillaume Desmottes Date: Mon Sep 21 17:48:00 2009 +0100 test wocky_pep_service_make_publish_stanza tests/wocky-pep-service-test.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) commit bd958bdb099057e25dcfcdf0cf4997fdc2c9693b Author: Guillaume Desmottes Date: Mon Sep 21 17:40:12 2009 +0100 test wocky_pep_service_get_async tests/wocky-pep-service-test.c | 90 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) commit e1c1d273cca722b280e7cc41969a82e78dcf4d3a Author: Guillaume Desmottes Date: Mon Sep 21 17:28:30 2009 +0100 wocky-pep-service-test: test 'changed' signal tests/wocky-pep-service-test.c | 83 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) commit 2223be661d6a5e1d015f5ba9d08b94a2a2d9e911 Author: Guillaume Desmottes Date: Mon Sep 21 17:17:31 2009 +0100 wocky-pep-service: add a debug msg wocky/wocky-pep-service.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) commit a75a44766c6451b3789b7ec3461efa1d1d32d3b9 Author: Guillaume Desmottes Date: Thu Sep 17 15:13:54 2009 +0100 add pubsub debug flag wocky/wocky-debug.c | 1 + wocky/wocky-debug.h | 1 + 2 files changed, 2 insertions(+) commit a0c102d5ff551eaca0b96de0584dd69f129da036 Author: Guillaume Desmottes Date: Mon Sep 21 16:14:20 2009 +0100 add wocky-pep-service-test.c .gitignore | 1 + tests/Makefile.am | 7 +++++++ tests/wocky-pep-service-test.c | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) commit 853f1f634e40a2a2b72b9409036ebf90e54368ea Author: Guillaume Desmottes Date: Mon Sep 21 16:09:25 2009 +0100 build wocky-pep-service wocky/Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 2974927e81d77dc2223e31dbc04edb05feeadaf2 Author: Guillaume Desmottes Date: Mon Sep 21 16:09:15 2009 +0100 wocky-pep-service: use Wocky's signal marshallers wocky/wocky-pep-service.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) commit 2274057dbb094016e86a42fcd2c4d47f91d14807 Author: Guillaume Desmottes Date: Fri Sep 25 10:34:27 2009 +0100 import wocky-pep-service.[ch] from Gabble wocky/wocky-pep-service.c | 362 ++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-pep-service.h | 80 ++++++++++ 2 files changed, 442 insertions(+) commit 76cf91722c1e1826750b9e396e119caddd675311 Author: Guillaume Desmottes Date: Thu Sep 24 18:07:23 2009 +0100 factor out common code of test_wait_iq_reply_close and test_wait_iq_reply_force_close to a function tests/wocky-porter-test.c | 80 +++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 47 deletions(-) commit b54f1004fa279e184162130834d1609cce5791b0 Author: Guillaume Desmottes Date: Thu Sep 24 18:00:05 2009 +0100 rename complete_pending_send_iq to abort_pending_iqs wocky/wocky-porter.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit 7ececb0027aa22b504b81917caaf51b6bc2024dc Author: Guillaume Desmottes Date: Thu Sep 24 17:53:46 2009 +0100 rename WOCKY_PORTER_ERROR_FORCE_CLOSING to WOCKY_PORTER_ERROR_FORCIBLY_CLOSED tests/wocky-porter-test.c | 8 +++++--- wocky/wocky-porter.c | 4 ++-- wocky/wocky-porter.h | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) commit 6903df4c7c6b3545101b6d879134c4cb6d515684 Author: Guillaume Desmottes Date: Thu Sep 24 15:49:05 2009 +0100 wocky_porter_force_close_async: re-use the same GError to set the error on all the results wocky/wocky-porter.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) commit 03d2273f68a9bf49746740a959f10b940eb50570 Author: Guillaume Desmottes Date: Thu Sep 24 15:47:57 2009 +0100 error code when terminating send operations because of a force closing should be WOCKY_PORTER_ERROR_FORCE_CLOSING tests/wocky-porter-test.c | 2 +- wocky/wocky-porter.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) commit c8f08025cda5419be3c011c5b338cbbc8841900e Author: Guillaume Desmottes Date: Thu Sep 24 15:43:47 2009 +0100 test that pending send IQ operation are complete when we force the closing of our porter tests/wocky-porter-test.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) commit 8eef61f1f410763625904ba419b47ce79727d785 Author: Guillaume Desmottes Date: Thu Sep 24 15:42:33 2009 +0100 complete pending send IQ operations when we force the closing of the porter wocky/wocky-porter.c | 5 +++++ 1 file changed, 5 insertions(+) commit 3fbce0242bfe600227e77d1edfd4402426dd5be6 Author: Guillaume Desmottes Date: Thu Sep 24 15:42:07 2009 +0100 factor out complete_pending_send_iq wocky/wocky-porter.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) commit 104bae4b182ade5d2942bfcd18511f7eb927572d Author: Guillaume Desmottes Date: Thu Sep 24 15:14:48 2009 +0100 pass the reason of the disconnection to the send IQ callback tests/wocky-porter-test.c | 3 ++- wocky/wocky-porter.c | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) commit 481054a85e50a0c5b584d2a6e95b2fff33ccb604 Author: Guillaume Desmottes Date: Thu Sep 24 15:08:44 2009 +0100 complete send IQ operations before signalling the closing of the remote connection wocky/wocky-porter.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) commit 7a91dcc4b4f9a39c99d839b72745ee367c97719e Author: Guillaume Desmottes Date: Thu Sep 24 14:58:50 2009 +0100 test that pending send IQ operation are complete when the remote connection is closed tests/wocky-porter-test.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) commit 340cb5a7d92bbc91b186597827ad9b92c25fa5cf Author: Guillaume Desmottes Date: Thu Sep 24 14:57:12 2009 +0100 porter: complete pending send IQ operations when the remote connection is closed We won't be able to receive the IQ reply so we have to complete the operation. wocky/wocky-porter.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) commit a797ccc3b304be3a662e349189896dab2777fa31 Merge: 16ce7be 76a008f Author: Dafydd Harries Date: Wed Sep 23 22:05:25 2009 +0100 Merge branch 'cosmetics' Reviewed-by: Sjoerd Simons commit 76a008fd90eeb1f5ca92f866c76029ed9650449c Author: Dafydd Harries Date: Wed Sep 23 18:29:48 2009 +0100 cosmetics: remove adscititious newlines tests/wocky-test-connector-server.c | 24 ++++++++++++------------ wocky/wocky-connector.c | 6 +++--- wocky/wocky-porter.c | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) commit 16ce7be592b94c5f50c3ca4010f90247ef1d48f4 Author: Guillaume Desmottes Date: Tue Sep 22 17:08:36 2009 +0100 copy wocky_g_value_slice_* helpers from telepathy-glib wocky/wocky-utils.c | 331 ++++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-utils.h | 22 ++++ 2 files changed, 353 insertions(+) commit 9b3de37e9b99af2abaf4cee045ba42a548d970b2 Author: Vivek Dasmohapatra Date: Mon Sep 21 16:21:17 2009 +0100 Make sure we include the username in the jabber auth iq get stanza. tests/wocky-test-connector-server.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) commit 252c938262d0ddab12fff62c226700354a8f11cf Author: Vivek Dasmohapatra Date: Mon Sep 21 16:16:07 2009 +0100 Include ... in jabber auth iq get stanza. (Bug #24013) Not required by XEP 0078 but required by some implementations. Not forbidden by XEP 0078. Conforms to Gabble 0.8.x behaviour. wocky/wocky-connector.c | 3 +++ 1 file changed, 3 insertions(+) commit a2ec0dbefa807527190dd46bd5d5044f1eb2d09e Merge: 7b80feb b30b339 Author: Vivek Dasmohapatra Date: Mon Sep 21 17:31:43 2009 +0100 Merge build-system-fixes branch (certtool, sasl.h dependency fixes) commit b30b3398e687918114dfa9fe37b47c230782d8e9 Author: Vivek Dasmohapatra Date: Mon Sep 21 17:19:52 2009 +0100 Deleted blank lines undeleted. tests/wocky-test-sasl-auth-server.c | 3 +++ 1 file changed, 3 insertions(+) commit 1d291e099d4798f4894b8f3b1e3250ee16a4210a Author: Vivek Dasmohapatra Date: Mon Sep 21 12:41:12 2009 +0100 CA and CRL directories should also be prerequisites of the connector test suite. tests/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 242830f3765fecd9d7d8000b29069fa0cc965ca2 Author: Vivek Dasmohapatra Date: Mon Sep 21 12:37:40 2009 +0100 challenge is not free()d, so need not be assigned from g_strdup(). tests/wocky-test-sasl-auth-server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit e00fc6ee1e51ada35f07ec44796a3c0454630a4e Author: Vivek Dasmohapatra Date: Mon Sep 21 12:35:51 2009 +0100 Remove #warnings about missing libsasl2, use g_message instead. tests/wocky-connector-test.c | 7 ++++++- tests/wocky-test-sasl-auth-server.c | 1 - 2 files changed, 6 insertions(+), 2 deletions(-) commit 8cf3f5ddaf64c4548b769f4fec4405796892b069 Author: Vivek Dasmohapatra Date: Mon Sep 21 11:44:08 2009 +0100 Git ignore wocky dist tarball. .gitignore | 2 ++ 1 file changed, 2 insertions(+) commit 4a3b664a89db37d7826784da8d5fb5a465cca9b8 Author: Vivek Dasmohapatra Date: Fri Sep 18 18:20:04 2009 +0100 Add certs/cas dir to variable to keep distcheck happy. tests/Makefile.am | 1 + 1 file changed, 1 insertion(+) commit 9be3ec00e4abbdf349286073bd9aed5da47af3c0 Author: Vivek Dasmohapatra Date: Fri Sep 18 18:16:56 2009 +0100 fake PLAIN SASL and ignore other mechs when libsasl2 is unavailable. tests/wocky-connector-test.c | 15 ++++++++ tests/wocky-test-sasl-auth-server.c | 68 +++++++++++++++++++++++++++++++++---- 2 files changed, 77 insertions(+), 6 deletions(-) commit cd2defdc0dceb507f1a7cbf209ce300c329a3a69 Author: Vivek Dasmohapatra Date: Fri Sep 18 18:16:15 2009 +0100 sasl/sasl.h not needed here. tests/wocky-test-connector-server.c | 2 -- 1 file changed, 2 deletions(-) commit 4194158aca737f2b19995355399fb822d40b6626 Author: Vivek Dasmohapatra Date: Fri Sep 18 18:15:51 2009 +0100 Patterns must match both short and full qualified paths. This is down to use of @abs_top_srcdir@ conflicting with distcheck. tests/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 767530fcf1e4bbcb5ea3605c782060ad599e3427 Author: Vivek Dasmohapatra Date: Fri Sep 18 18:02:56 2009 +0100 Populate the CA certificates and CRL subdirectories correctly. tests/Makefile.am | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) commit d0507e7471660f7cf73ef7ed37e8cb45dd882309 Author: Vivek Dasmohapatra Date: Fri Sep 18 17:44:30 2009 +0100 More Makefile.am fixes to cope now that certificates are preserved by default. .PRECIOUS rule simplified to all PEM files Binary check deps converted to order only prerequisites (to avoid rebuilding certs just because we re-ran the certtool/datefudge binary checks) Don't delete CRLs or PEM files at all. tests/Makefile.am | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) commit ddc8177f5514685505121d51f9d02d9df1bdb6b8 Author: Vivek Dasmohapatra Date: Fri Sep 18 14:35:17 2009 +0100 Update make system to preserve generated certificates. Ability to generate certificates remains, but may depend on availability of gnutls certtool and/or datefudge, which are checked for at runtime. tests/Makefile.am | 47 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 15 deletions(-) commit c2cbc5346062e9260ab30e7c67bebc4a8f5460e3 Author: Vivek Dasmohapatra Date: Fri Sep 18 14:14:00 2009 +0100 Check in generated certs as we preserve these now. Note that this will all fall apart in 2037 some time; This change means downstream won't need to include the cert generation tools just to run the test suite. .gitignore | 34 ++++++++++++++-------------- tests/certs/ca-0-cert.pem | 30 ++++++++++++------------- tests/certs/ca-0-crl.pem | 13 +++++++++++ tests/certs/ca-0-key.pem | 50 +++++++++++++++++++++--------------------- tests/certs/ca-1-cert.pem | 23 +++++++++++++++++++ tests/certs/ca-1-key.pem | 27 +++++++++++++++++++++++ tests/certs/ca-2-cert.pem | 23 +++++++++++++++++++ tests/certs/ca-2-key.pem | 27 +++++++++++++++++++++++ tests/certs/exp-cert.pem | 30 ++++++++++++------------- tests/certs/exp-key.pem | 27 +++++++++++++++++++++++ tests/certs/new-cert.pem | 30 ++++++++++++------------- tests/certs/new-key.pem | 27 +++++++++++++++++++++++ tests/certs/rev-cert.pem | 24 ++++++++++++++++++++ tests/certs/rev-key.pem | 27 +++++++++++++++++++++++ tests/certs/ss-cert.pem | 24 ++++++++++++++++++++ tests/certs/ss-key.pem | 27 +++++++++++++++++++++++ tests/certs/tls-cert.pem | 24 ++++++++++++++++++++ tests/certs/tls-key.pem | 27 +++++++++++++++++++++++ tests/certs/unknown-ca-key.pem | 27 +++++++++++++++++++++++ tests/certs/unknown-cert.pem | 25 +++++++++++++++++++++ tests/certs/unknown-key.pem | 27 +++++++++++++++++++++++ 21 files changed, 487 insertions(+), 86 deletions(-) commit 81f9f5c01fa2de1b8e18a94095dc9fa14422e66f Author: Vivek Dasmohapatra Date: Fri Sep 18 14:10:22 2009 +0100 Certificates last "forever" now, extend their expiry in the config templates. tests/certs/ca-0-crl.cfg | 2 +- tests/certs/ca-1-cert.cfg | 2 +- tests/certs/ca-2-cert.cfg | 2 +- tests/certs/rev-cert.cfg | 2 +- tests/certs/ss-cert.cfg | 2 +- tests/certs/tls-cert.cfg | 2 +- tests/certs/unknown-ca-cert.cfg | 2 +- tests/certs/unknown-cert.cfg | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) commit 450b8108b718e406e2b34669f1b24e9aad48ee3f Author: Vivek Dasmohapatra Date: Fri Sep 18 14:08:54 2009 +0100 Typo: temporary DEBUG2 macro no longer exists. tests/wocky-test-connector-server.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) commit 7c4e232f11cdb0bc0b5c1900a6d16e1d3698365e Author: Vivek Dasmohapatra Date: Fri Sep 18 14:07:36 2009 +0100 Permit server initialiasation without an x509 certificate/key pair. wocky/wocky-tls.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) commit f07d5bdfb587b2941265e29878b6d70d66b38868 Author: Vivek Dasmohapatra Date: Fri Sep 18 14:03:51 2009 +0100 Now preserving generated certs, so don't check for certtool at configure time. configure.ac | 6 ------ 1 file changed, 6 deletions(-) commit 0974c93aef7b46caee9552350d6ca0aa4d29912e Author: Vivek Dasmohapatra Date: Thu Sep 17 17:32:44 2009 +0100 Add check for gnutls certtool in configure.ac configure.ac | 6 ++++++ 1 file changed, 6 insertions(+) commit 42e9edd8c5ee54203fed2fec384a465403e470f6 Author: Vivek Dasmohapatra Date: Thu Sep 17 16:46:11 2009 +0100 Check for sasl/sasl.h as well as libsasl2.so (no .pc, so no pkg-config) configure.ac | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) commit 7b80feb0be0daf92e3e14079082c019bfc1386ab Author: Guillaume Desmottes Date: Mon Sep 21 15:55:19 2009 +0100 run wocky-connector-test last as it takes age to run tests/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 230ec0678e0fb55aeb30678f103ff89d37e56a1a Author: Guillaume Desmottes Date: Thu Sep 17 15:14:11 2009 +0100 wocky-namespaces: add WOCKY_XMPP_NS_PUBSUB_EVENT wocky/wocky-namespaces.h | 3 +++ 1 file changed, 3 insertions(+) commit 3822ffd5739951a48f18b0cfa4f7892418227084 Author: Sjoerd Simons Date: Sun Sep 20 12:44:47 2009 +0100 Namespace wocky-debug header file #ifdef wocky/wocky-debug.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 5ae3040a2eefcde286c60af9afc40e075ccd6c8e Author: Sjoerd Simons Date: Sun Sep 20 11:59:38 2009 +0100 Remove debug message that make the logging less useful Unfortunately wocky only has one debug level. Outputting two lines for every node in the tree completely overwhelms everything else, so remove these for now. wocky/wocky-xmpp-reader.c | 19 ------------------- 1 file changed, 19 deletions(-) commit 9f7b18408dab61b0e35810719f1edfa86c9d4b5f Author: Sjoerd Simons Date: Sun Sep 20 11:38:53 2009 +0100 Set G_LOG_DOMAIN to wocky wocky/Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit f2973853cb582547505bd1284cf261d064f6db97 Merge: e249ed8 c20db39 Author: Vivek Dasmohapatra Date: Tue Sep 15 17:50:50 2009 +0100 Merge branch 'keep-old-new-test-certs' commit c20db39f0c6d71bd895c9e17bc14001ad9bb1e04 Author: Vivek Dasmohapatra Date: Tue Sep 15 17:42:55 2009 +0100 Temporary debug target 'moose' in Makefile.am shouldn't have been checked in. tests/Makefile.am | 3 --- 1 file changed, 3 deletions(-) commit f79654645ae0f3a314f8d6f4ea6e86bc22f3eaf5 Author: Vivek Dasmohapatra Date: Tue Sep 15 17:15:38 2009 +0100 Preserve inactive, expired (and CA cert for same) to avoid datefudge build dep. .gitignore | 23 ++++++++++++++++++++++- tests/Makefile.am | 21 +++++++++++++-------- tests/certs/ca-0-cert.cfg | 2 +- tests/certs/ca-0-cert.pem | 23 +++++++++++++++++++++++ tests/certs/ca-0-key.pem | 27 +++++++++++++++++++++++++++ tests/certs/exp-cert.pem | 24 ++++++++++++++++++++++++ tests/certs/new-cert.pem | 24 ++++++++++++++++++++++++ 7 files changed, 134 insertions(+), 10 deletions(-) commit e249ed86915cf38663abbbcd328f6ad1321ef4c8 Author: Guillaume Desmottes Date: Tue Sep 15 11:04:33 2009 +0100 configure.ac: don't call GTK_DOC_CHECK twice (fd.o #23943) configure.ac | 3 --- 1 file changed, 3 deletions(-) commit 1a9e13714a4758eb5e73fe166aa42632feb2bad8 Author: Vivek Dasmohapatra Date: Mon Sep 14 15:21:06 2009 +0100 Update docstring with corrected canonical locations for CA certificates. wocky/wocky-connector.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) commit 95aec41185e17f0f7b59ef3a7cf1f2b775617e88 Author: Vivek Dasmohapatra Date: Mon Sep 14 13:29:15 2009 +0100 git ignore generated test CRLs. .gitignore | 1 + 1 file changed, 1 insertion(+) commit 3736688c6a71db7185722e41ef6404a7156a6ab3 Author: Vivek Dasmohapatra Date: Mon Sep 14 12:59:57 2009 +0100 Make distcheck happy again (generated test crls weren't handled properly) tests/Makefile.am | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) commit cc335c30eacf0c5f28974a6d319651d1e23f0658 Author: Vivek Dasmohapatra Date: Fri Sep 11 20:05:52 2009 +0100 Add tests for CRL verification. tests/wocky-connector-test.c | 49 +++++++++++++++++++++++++++++++++++++ tests/wocky-test-connector-server.c | 1 + tests/wocky-test-connector-server.h | 3 ++- 3 files changed, 52 insertions(+), 1 deletion(-) commit 2a4f18eafb29eba0137d2286cf5fe8d80006f22a Author: Vivek Dasmohapatra Date: Fri Sep 11 20:04:45 2009 +0100 Generate revoked certificate + crl for tests. tests/Makefile.am | 27 +++++++++++++-- tests/certs/ca-0-crl.cfg | 1 + tests/certs/rev-cert.cfg | 89 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 2 deletions(-) commit 2708fc257679324f67445963319d2bcaa88ced5e Author: Vivek Dasmohapatra Date: Fri Sep 11 18:45:58 2009 +0100 Update example connect program to new API for adding CAs. examples/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit b657eaa0861e64cc428adce99fa611e16ce0f763 Author: Vivek Dasmohapatra Date: Fri Sep 11 18:45:31 2009 +0100 Update tests to new API (CAs not added in constructor any more). tests/wocky-connector-test.c | 3 ++- tests/wocky-test-connector-server.c | 15 +++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) commit 1c6b431e6fbc2413f1e2c7557caf15a02048d399 Author: Vivek Dasmohapatra Date: Fri Sep 11 18:44:52 2009 +0100 CA and CRL lists not properties any more: added via public method instead. wocky/wocky-connector.c | 111 ++++++++++++++++++++++++------- wocky/wocky-connector.h | 6 ++ wocky/wocky-tls.c | 173 ++++++++++++++++++++---------------------------- wocky/wocky-tls.h | 14 ++-- 4 files changed, 174 insertions(+), 130 deletions(-) commit fd244a61ae5c6b58759978de49f7960e071f76de Author: Vivek Dasmohapatra Date: Fri Sep 11 16:02:52 2009 +0100 Catch more cert verification failures from gnutls and alter return accordingly. wocky/wocky-tls.c | 34 ++++++++++++++++++++++++++++++++-- wocky/wocky-tls.h | 3 +++ 2 files changed, 35 insertions(+), 2 deletions(-) commit 96aa57b55afbb0c39920eb9f9a0f6c55438dd4d6 Author: Vivek Dasmohapatra Date: Fri Sep 11 16:01:56 2009 +0100 Wocky specific error on TLS handshake failure, don't propagate the gnutls one. wocky/wocky-connector.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 00d906384defb0b283ea05c8fbb00e8853780368 Author: Vivek Dasmohapatra Date: Fri Sep 11 15:47:32 2009 +0100 git ignore multi-ca certs built by tests. .gitignore | 1 + 1 file changed, 1 insertion(+) commit 6cfab2cec199cfe88585ee3781b9ad63c91c1437 Author: Vivek Dasmohapatra Date: Thu Sep 10 18:52:09 2009 +0100 Typo, missing arg in last checkin. wocky/wocky-tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit b8d2ee6f6975374984551b2bf3f8bdf6ed9a1206 Author: Vivek Dasmohapatra Date: Thu Sep 10 18:50:10 2009 +0100 Update tests to include loading multiple ca certs from a directory. tests/Makefile.am | 41 ++++++++++++-------- tests/certs/ca-0-cert.cfg | 89 ++++++++++++++++++++++++++++++++++++++++++++ tests/certs/ca-1-cert.cfg | 89 ++++++++++++++++++++++++++++++++++++++++++++ tests/certs/ca-2-cert.cfg | 89 ++++++++++++++++++++++++++++++++++++++++++++ tests/certs/ca-cert.cfg | 89 -------------------------------------------- tests/wocky-connector-test.c | 19 +++++++++- 6 files changed, 310 insertions(+), 106 deletions(-) commit 98039f72a3edacf48a40cf60f39a6075f4ebc108 Author: Vivek Dasmohapatra Date: Thu Sep 10 18:48:43 2009 +0100 Debugging now reports total certs loaded from dir. wocky/wocky-tls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit dc0f398d347e0c3f6520b36b84a2fa5f8b830010 Author: Vivek Dasmohapatra Date: Thu Sep 10 17:57:16 2009 +0100 Abort with GError with wockytls-cert-error quark on cert verification problem. tests/wocky-connector-test.c | 25 +++++++++++++------------ wocky/wocky-connector.c | 7 +++++-- 2 files changed, 18 insertions(+), 14 deletions(-) commit 6a8e5b48efe481ff0462259c8edd5a6e9193cb25 Author: Vivek Dasmohapatra Date: Thu Sep 10 17:31:59 2009 +0100 Define tls cert status quark. wocky/wocky-tls.c | 11 +++++++++++ wocky/wocky-tls.h | 3 +++ 2 files changed, 14 insertions(+) commit 56ceea3886aa5633bbdecff225fd85ae988e0c9c Author: Vivek Dasmohapatra Date: Thu Sep 10 14:57:44 2009 +0100 { } around if in for loop (only statement in loop) (starttls) tests/wocky-test-connector-server.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) commit c61df5036b33b67136d168efef456ced5405231d Author: Vivek Dasmohapatra Date: Thu Sep 10 14:56:08 2009 +0100 { } around if (only statement in for loop) (handle_starttls). tests/wocky-test-connector-server.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) commit e5c5aaff32ce3774468de790ef9e938270699ada Author: Vivek Dasmohapatra Date: Thu Sep 10 14:52:45 2009 +0100 DEBUG when stat of candidate ca/crl file or dir fails. wocky/wocky-tls.c | 3 +++ 1 file changed, 3 insertions(+) commit e57f5c4f29c753e64b48f19fd4cb5c2a3e23b725 Author: Vivek Dasmohapatra Date: Thu Sep 10 14:44:38 2009 +0100 Change signature to specifically be WockyTLSCertStatus *, not guint *. wocky/wocky-tls.c | 8 ++++---- wocky/wocky-tls.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) commit d030e836b5e10fd661f9a2b23b443ad3aa9242ac Author: Vivek Dasmohapatra Date: Thu Sep 10 14:38:24 2009 +0100 Follow gnio style for wocky-tls (code borrowed from there) wocky/wocky-tls.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) commit 142bcfcc27a32db2833640e2fa3df582a56e5841 Author: Vivek Dasmohapatra Date: Thu Sep 10 14:36:58 2009 +0100 Tweak "$binary not installed" make error message. tests/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit b8b76837f273ff1d40d3e71eb916e25f6ae19466 Author: Vivek Dasmohapatra Date: Thu Sep 10 14:16:11 2009 +0100 Tests for certificate strict/lenient verification. tests/wocky-connector-test.c | 308 +++++++++++++++++++++++++++++++++++- tests/wocky-test-connector-server.c | 53 ++++++- tests/wocky-test-connector-server.h | 13 +- 3 files changed, 363 insertions(+), 11 deletions(-) commit 6264c62f742834361fdf5030fb6358a212293e26 Author: Vivek Dasmohapatra Date: Thu Sep 10 14:15:35 2009 +0100 Update example to conform to new wocky_tls_session_new API. examples/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 5a2f92a47b18fb1402c5f7b07c2677b3b23af88e Author: Vivek Dasmohapatra Date: Thu Sep 10 14:14:40 2009 +0100 Support certificate verification via wocky_tls_session new API for wocky_tls_session_new used correctly handle results of wocky_tls_session_verify_peer when lenient/strict wocky/wocky-connector.c | 60 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 4 deletions(-) commit a9d71475175ec7dbcbd088036dd3e2d429171a8c Author: Vivek Dasmohapatra Date: Thu Sep 10 14:12:34 2009 +0100 wocky_tls_sessions can now do cert verification. debugging tweaks to make wocky-tls debugging tunable via WOCKY_TLS_DEBUG_LEVEL extra parameters to wocky_tls_session_new (ca and crl files/dirs) variable named stat -> _stat (conflict with stat(2)) tweak WOCKY_TLS_VERIFY_NORMAL flags (subject to review anyway) wocky/wocky-tls.c | 167 +++++++++++++++++++++++++++++++++++++++++++----------- wocky/wocky-tls.h | 8 ++- 2 files changed, 141 insertions(+), 34 deletions(-) commit 7b6b176e957745e5786c490a1f7888613f9417ce Author: Vivek Dasmohapatra Date: Thu Sep 10 14:05:48 2009 +0100 Generate extra invalid certs for testing. tests/Makefile.am | 89 +++++++++++++++++++++++++++++++---------- tests/certs/exp-cert.cfg | 89 +++++++++++++++++++++++++++++++++++++++++ tests/certs/new-cert.cfg | 89 +++++++++++++++++++++++++++++++++++++++++ tests/certs/ss-cert.cfg | 89 +++++++++++++++++++++++++++++++++++++++++ tests/certs/unknown-ca-cert.cfg | 89 +++++++++++++++++++++++++++++++++++++++++ tests/certs/unknown-cert.cfg | 89 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 512 insertions(+), 22 deletions(-) commit 07dbdd3dad71d7739b32c94aae0d0dfbaadc6944 Author: Vivek Dasmohapatra Date: Wed Sep 9 14:49:08 2009 +0100 Build helper programs in all target. Filter out the cert generation bits noise. tests/Makefile.am | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) commit b6122b7bc81f97da438c8e11cf2f2445f227e963 Author: Vivek Dasmohapatra Date: Wed Sep 9 12:32:07 2009 +0100 Tidy up the cert verification error selection code. wocky/wocky-tls.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) commit f0c194cb25e28172f0c12531ac425ab9d3ecfcb8 Author: Vivek Dasmohapatra Date: Tue Sep 8 19:46:53 2009 +0100 Basic server cert verification tests (more to follow) tests/wocky-connector-test.c | 100 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) commit 2cb3c8694ab690bd410efd05b34a15d13cd47ee6 Author: Vivek Dasmohapatra Date: Tue Sep 8 19:46:28 2009 +0100 Use the new certificate cerification function to check the server cert. wocky/wocky-connector.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) commit 47f24d6387c3968cac25b80134e6d2ad4cb44291 Author: Vivek Dasmohapatra Date: Tue Sep 8 19:46:04 2009 +0100 Add a certificate verification function (checks expiry, peer name etc) wocky/wocky-tls.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-tls.h | 35 ++++++++++++++++++++++- 2 files changed, 119 insertions(+), 1 deletion(-) commit 1346b9cca915c16a095dfbe92172cdf2d151fb00 Author: Guillaume Desmottes Date: Tue Sep 8 11:48:31 2009 +0100 wocky-connector-test: check the right error code now that decode_jis is actually smarter tests/wocky-connector-test.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) commit 07938cf687762add30978d72bf3623e8e8d5a320 Author: Guillaume Desmottes Date: Tue Sep 8 11:13:01 2009 +0100 sync wocky_decode_jid implementation with Gabble wocky_decode_jid now does some validity checks on the JID. wocky/wocky-utils.c | 135 +++++++++++++++++++++++++++++++++++----------------- wocky/wocky-utils.h | 2 +- 2 files changed, 92 insertions(+), 45 deletions(-) commit 47a91ac7e2ddaee74532f10f8e2ba51511e2a5ba Author: Guillaume Desmottes Date: Thu Sep 3 13:39:15 2009 +0100 add WOCKY_XMPP_NS_PUBSUB wocky/wocky-namespaces.h | 3 +++ 1 file changed, 3 insertions(+) commit f6ff602880d07de6df6e6dac66574b44f580ccf5 Author: Guillaume Desmottes Date: Wed Sep 2 15:45:45 2009 +0100 Don't create a WockyRoster in WockySession for now. We don't want to create it automatically for now as Gabble isn't ported to use WockyRoster yet. This reverts commit 74288a9802e56cf3404c95d9c3a28603d0b1bf41 and 438140e5c05da82c030fc53b08d8fa9d43779d84. tests/wocky-roster-test.c | 7 ++++--- tests/wocky-session-test.c | 17 ----------------- wocky/wocky-session.c | 23 ----------------------- wocky/wocky-session.h | 3 --- 4 files changed, 4 insertions(+), 46 deletions(-) commit 5b9839ebe93637a4a6e72c18b3683ad8ec9d449c Author: Sjoerd Simons Date: Wed Sep 2 14:54:51 2009 +0100 Remove unnecessary gnio dependency wocky/wocky-uninstalled.pc.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 438140e5c05da82c030fc53b08d8fa9d43779d84 Author: Guillaume Desmottes Date: Tue Sep 1 18:20:28 2009 +0100 wocky-roster-test: use the roster created by the session tests/wocky-roster-test.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) commit 74288a9802e56cf3404c95d9c3a28603d0b1bf41 Author: Guillaume Desmottes Date: Tue Sep 1 18:18:32 2009 +0100 session: create a roster object tests/wocky-session-test.c | 17 +++++++++++++++++ wocky/wocky-session.c | 23 +++++++++++++++++++++++ wocky/wocky-session.h | 3 +++ 3 files changed, 43 insertions(+) commit acd9668386046417eca0ca2ab14de495326f8f5e Author: Guillaume Desmottes Date: Tue Sep 1 18:15:09 2009 +0100 fix identation wocky/wocky-session.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) commit da1782aa17377b086aa69a1eead10de7b9a97a48 Author: Guillaume Desmottes Date: Tue Sep 1 18:13:13 2009 +0100 porter: don't create a contact factory anymore That's the job of the session now. wocky/wocky-porter.c | 18 ------------------ 1 file changed, 18 deletions(-) commit ba9d1ee743fa8a8b79871bcae928c18eb43dd453 Author: Guillaume Desmottes Date: Tue Sep 1 18:11:55 2009 +0100 pass a session instead of a porter to wocky_roster_new tests/wocky-roster-test.c | 17 +++++++++-------- wocky/wocky-roster.c | 47 ++++++++++++++++++++++++++--------------------- wocky/wocky-roster.h | 3 +-- 3 files changed, 36 insertions(+), 31 deletions(-) commit 899770c4f5e2455e1e299ea577c0ef68c770009d Author: Guillaume Desmottes Date: Tue Sep 1 18:11:03 2009 +0100 instantiate wocky sessions in tests tests/wocky-porter-test.c | 4 ++-- tests/wocky-test-helper.c | 15 +++++++++------ tests/wocky-test-helper.h | 3 +++ 3 files changed, 14 insertions(+), 8 deletions(-) commit 2dd8e98031a100437a1d2e95845b6641082cab1e Author: Guillaume Desmottes Date: Tue Sep 1 18:09:08 2009 +0100 add wocky_session_start wocky/wocky-session.c | 7 +++++++ wocky/wocky-session.h | 2 ++ 2 files changed, 9 insertions(+) commit 569176a4df56da2e8dda637d1a3e5f39a1549f47 Author: Guillaume Desmottes Date: Tue Sep 1 17:07:29 2009 +0100 wocky-session: create a contact-factory tests/wocky-session-test.c | 17 +++++++++++++++++ wocky/wocky-session.c | 24 ++++++++++++++++++++++-- wocky/wocky-session.h | 3 +++ 3 files changed, 42 insertions(+), 2 deletions(-) commit 0b71b1ad5eefb26b3bb1bc8dfcc41f8c63f6ccfd Author: Guillaume Desmottes Date: Tue Sep 1 17:00:42 2009 +0100 session: create a Porter for the connection tests/wocky-session-test.c | 17 +++++++++++++++++ wocky/wocky-session.c | 24 ++++++++++++++++++++++++ wocky/wocky-session.h | 3 +++ 3 files changed, 44 insertions(+) commit c901bceb51ccb818d7ce4e793d1432cf46bdfa16 Author: Guillaume Desmottes Date: Tue Sep 1 16:51:27 2009 +0100 add wocky-session-test.c .gitignore | 1 + tests/Makefile.am | 9 ++++++++- tests/wocky-session-test.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) commit 6b7ea9560ccc670ebe7b1deacc9cc814541c4010 Author: Guillaume Desmottes Date: Tue Sep 1 16:50:58 2009 +0100 add wocky-session.[ch] wocky/Makefile.am | 4 +- wocky/wocky-session.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-session.h | 63 +++++++++++++++++ wocky/wocky-types.h | 1 + 4 files changed, 253 insertions(+), 1 deletion(-) commit 86beae82d585b7aa9cfdbce7b9b905108f57760a Author: Jonny Lamb Date: Mon Aug 31 15:53:11 2009 +0100 codegen: only touch wocky-signals-marshal.list if it's actually changed Previously, if you edit any file in $(HANDWRITTEN_SOURCES), then wocky-signals-marshal.list would be recreated, meaning wocky-signals-marshal.{c,h} would also be recreated, meaning half of wocky would be rebuilt. This is not cool. Signed-off-by: Jonny Lamb wocky/Makefile.am | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) commit 99bfadba1b0c35afffb58c7191e5a053c46e56de Author: Guillaume Desmottes Date: Fri Aug 28 17:30:08 2009 +0100 contact-factory: fire signal when contacts are added tests/wocky-contact-factory-test.c | 30 ++++++++++++++++++++++++++++++ wocky/wocky-contact-factory.c | 20 ++++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) commit 3d7e98a1731ef40cc316b448dacff2a296ac8104 Author: Guillaume Desmottes Date: Fri Aug 28 16:10:54 2009 +0100 Create the contact factory in the porter instead of the roster The factory should probably be created in a top-level object (as WockySession or something) but for now the Porter is the best candidate as it's used by most components. wocky/wocky-porter.c | 20 +++++++++++++++++++- wocky/wocky-roster.c | 11 +++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) commit ec18c467014369b5fd358a67f26db1a42e73c8a8 Author: Guillaume Desmottes Date: Fri Aug 28 12:23:05 2009 +0100 wocky-docs.sgml: add WockyResourceContact and WockyContactFactory docs/reference/wocky-docs.sgml | 2 ++ 1 file changed, 2 insertions(+) commit 22d14329604378c093b7baa00d9674b903b7511d Author: Guillaume Desmottes Date: Fri Aug 28 12:22:44 2009 +0100 add missing symbols to wocky-sections.txt docs/reference/wocky-sections.txt | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) commit 4a59204d21a0a69dc23bffa9c37eabd5c44bc9b5 Author: Guillaume Desmottes Date: Fri Aug 28 12:01:53 2009 +0100 run wocky-connector-test last as it takes the age of the universe to run tests/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit c7f37782d54100a90e64c84b076bff4756e18e98 Author: Guillaume Desmottes Date: Fri Aug 28 12:00:00 2009 +0100 don't assert if both contacts are NULL in equal functions wocky/wocky-bare-contact.c | 2 -- wocky/wocky-resource-contact.c | 2 -- 2 files changed, 4 deletions(-) commit 2648e92b077a9222328b8178cf3f7b8148f3d198 Author: Guillaume Desmottes Date: Fri Aug 28 11:57:59 2009 +0100 merge resource_contact_disposed_cb and bare_contact_disposed_cb together wocky/wocky-contact-factory.c | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) commit bdb453ee77012ab9d3a8c527f6e405cf3bb7d30b Author: Guillaume Desmottes Date: Thu Aug 27 17:41:23 2009 +0100 wocky_contact_factory_ensure_resource_contact: associate the new resource with the bare contact tests/wocky-contact-factory-test.c | 14 +++++++++++--- wocky/wocky-contact-factory.c | 2 ++ 2 files changed, 13 insertions(+), 3 deletions(-) commit 4915edf114c4e6d59e939c55dcf5b9035c946814 Author: Guillaume Desmottes Date: Thu Aug 27 17:33:16 2009 +0100 test wocky_bare_contact_get_resources and wocky_bare_contact_add_resource tests/wocky-bare-contact-test.c | 44 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) commit 46dad8e0d967afbe42dd08442bb8ea509a4e7a7c Author: Guillaume Desmottes Date: Thu Aug 27 17:32:59 2009 +0100 bare-contact: keep a list of the WockyResourceContact associated with this bare contact wocky/wocky-bare-contact.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- wocky/wocky-bare-contact.h | 7 +++++++ 2 files changed, 50 insertions(+), 2 deletions(-) commit 86391664f8e35c4e8235117502ba288c57e15f48 Author: Guillaume Desmottes Date: Thu Aug 27 17:07:07 2009 +0100 test wocky_contact_factory_lookup_resource_contact tests/wocky-contact-factory-test.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) commit 0652d1d15bb58efa924c016942d8980b798aca6e Author: Guillaume Desmottes Date: Thu Aug 27 17:06:57 2009 +0100 add wocky_contact_factory_lookup_resource_contact wocky/wocky-contact-factory.c | 9 +++++++++ wocky/wocky-contact-factory.h | 4 ++++ 2 files changed, 13 insertions(+) commit 514ba77365eca0b98d1502a233414c927092a2f6 Author: Guillaume Desmottes Date: Thu Aug 27 16:49:28 2009 +0100 roster: use the contact factory to create bare contacts wocky/wocky-bare-contact.c | 4 ++-- wocky/wocky-roster.c | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) commit bd32e4b5890bfb89348daccd563c908f9b60c5d1 Author: Guillaume Desmottes Date: Thu Aug 27 16:17:50 2009 +0100 test wocky_contact_factory_ensure_resource_contact tests/wocky-contact-factory-test.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) commit 0bb46b877364cea6ca8536e397c35cd18b31f42c Author: Guillaume Desmottes Date: Thu Aug 27 16:17:08 2009 +0100 test wocky_resource_contact_equal tests/wocky-resource-contact-test.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) commit 290d7c19352ec88d113be42772107894343db48f Author: Guillaume Desmottes Date: Thu Aug 27 16:15:42 2009 +0100 add wocky_resource_contact_equal wocky/wocky-resource-contact.c | 17 +++++++++++++++++ wocky/wocky-resource-contact.h | 3 +++ 2 files changed, 20 insertions(+) commit cf4f136dfd09d9dcab342483d07633b260da7913 Author: Guillaume Desmottes Date: Thu Aug 27 15:55:39 2009 +0100 add wocky_contact_factory_ensure_resource_contact wocky/wocky-contact-factory.c | 55 +++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-contact-factory.h | 5 ++++ 2 files changed, 60 insertions(+) commit a6da9047512845872e0ad7a041ab93245c79975c Author: Guillaume Desmottes Date: Thu Aug 27 15:30:38 2009 +0100 fix wocky_contact_factory_lookup_bare_contact style wocky/wocky-contact-factory.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) commit 27a673970917f4fd9814be8a9bfb6a5cfb26cff6 Author: Guillaume Desmottes Date: Thu Aug 27 13:11:53 2009 +0100 test wocky_contact_factory_lookup_bare_contact tests/wocky-contact-factory-test.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) commit 7b32de66252ed864860ee86653d2238c002ff962 Author: Guillaume Desmottes Date: Thu Aug 27 13:11:45 2009 +0100 add wocky_contact_factory_lookup_bare_contact wocky/wocky-contact-factory.c | 10 ++++++++++ wocky/wocky-contact-factory.h | 4 ++++ 2 files changed, 14 insertions(+) commit 085c06d29ae59e05515b285eeaea160fcf17a9c2 Author: Guillaume Desmottes Date: Thu Aug 27 13:05:56 2009 +0100 contact-factory: keep a weak ref on bare contact objects That way they are removed from the factory as soon other components stopped to use them. wocky/wocky-contact-factory.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) commit 103b34419f9cdf09478dec1eb3f9b16b8cbe9a3b Author: Guillaume Desmottes Date: Thu Aug 27 12:39:33 2009 +0100 test wocky_contact_factory_ensure_bare_contact tests/wocky-contact-factory-test.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) commit 7ab7e8ba3db05e74f4e92cb25d7b223e007bf313 Author: Guillaume Desmottes Date: Thu Aug 27 12:38:37 2009 +0100 add wocky_contact_factory_ensure_bare_contact wocky/wocky-contact-factory.c | 19 +++++++++++++++++++ wocky/wocky-contact-factory.h | 6 +++++- 2 files changed, 24 insertions(+), 1 deletion(-) commit bef77130d6a6eea1ee94dbefc1cb777642bf19a4 Author: Guillaume Desmottes Date: Thu Aug 27 11:59:10 2009 +0100 add wocky_bare_contact_new tests/wocky-bare-contact-test.c | 6 +++++- wocky/wocky-bare-contact.c | 8 ++++++++ wocky/wocky-bare-contact.h | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) commit 70e7ef61ac52cbf9d235cc63911e4485296e93d4 Author: Guillaume Desmottes Date: Thu Aug 27 11:43:53 2009 +0100 add wocky-contact-factory-test.c .gitignore | 1 + tests/Makefile.am | 9 ++++++++- tests/wocky-contact-factory-test.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) commit 678a68e813cc43267b286c9224e09fc2f22a1e27 Author: Guillaume Desmottes Date: Thu Aug 27 11:24:12 2009 +0100 add wocky-contact-factory.[ch] wocky/Makefile.am | 4 +- wocky/wocky-contact-factory.c | 167 ++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-contact-factory.h | 63 ++++++++++++++++ 3 files changed, 233 insertions(+), 1 deletion(-) commit 16df0d82689c0d916c1657ca987a7265eddf7eb8 Author: Guillaume Desmottes Date: Thu Aug 27 13:24:05 2009 +0100 add and test wocky_resource_contact_get_bare_contact tests/wocky-resource-contact-test.c | 20 ++++++++++++++++++++ wocky/wocky-resource-contact.c | 8 ++++++++ wocky/wocky-resource-contact.h | 3 +++ 3 files changed, 31 insertions(+) commit 0e35b89efafb1f8f7c9cac4110fd348bfcafa285 Author: Guillaume Desmottes Date: Thu Aug 27 13:21:19 2009 +0100 add and test wocky_resource_contact_get_resource tests/wocky-resource-contact-test.c | 20 ++++++++++++++++++++ wocky/wocky-resource-contact.c | 8 ++++++++ wocky/wocky-resource-contact.h | 3 +++ 3 files changed, 31 insertions(+) commit 0fed93aa2df5d8c514b2108023351892b7ee875d Author: Guillaume Desmottes Date: Thu Aug 27 11:00:44 2009 +0100 add wocky-resource-contact-test.c .gitignore | 1 + tests/Makefile.am | 9 ++++++- tests/wocky-resource-contact-test.c | 52 +++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) commit 7b873034f33f7828ab5bec0bdadefab26b6d2ff8 Author: Guillaume Desmottes Date: Thu Aug 27 10:59:52 2009 +0100 add wocky-resource-contact.[ch] wocky/Makefile.am | 2 + wocky/wocky-resource-contact.c | 219 +++++++++++++++++++++++++++++++++++++++++ wocky/wocky-resource-contact.h | 66 +++++++++++++ wocky/wocky-types.h | 1 + 4 files changed, 288 insertions(+) commit 53d9184bc0a332a02c7c1c47ee697d9da67c1a89 Author: Guillaume Desmottes Date: Wed Aug 26 14:37:39 2009 +0100 wocky-bare-contact: wrap some big lines wocky/wocky-bare-contact.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) commit 63cafe6e56b1369fd38f6048e08e5fb40771b3de Author: Guillaume Desmottes Date: Wed Aug 26 14:21:05 2009 +0100 add missing WokcyRoster methods to wocky-sections.txt docs/reference/wocky-sections.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) commit f0f0b39ccf729203d5eebbefd09601334825e1f6 Author: Guillaume Desmottes Date: Wed Aug 26 14:13:36 2009 +0100 add wocky-contact symbols to wocky-sections.txt docs/reference/wocky-sections.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) commit 642c27dcd500fd1887568b8a47e3523daa79c078 Author: Guillaume Desmottes Date: Wed Aug 26 14:09:40 2009 +0100 fix WockyBareContact doc and add missing symbols docs/reference/wocky-docs.sgml | 1 + docs/reference/wocky-sections.txt | 39 +++++++++++++++++++++++---------------- 2 files changed, 24 insertions(+), 16 deletions(-) commit a0fa9d9ebe90d5644c6c1b7adc1de6e0e75d5432 Author: Guillaume Desmottes Date: Wed Aug 26 13:56:54 2009 +0100 wocky-bare-contact-test: test instantiation tests/wocky-bare-contact-test.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) commit 7cc87a65bf4ebcf177f738d5d514db08482f321c Author: Guillaume Desmottes Date: Wed Aug 26 13:53:17 2009 +0100 WockyBareContact is now a subclass of WockyContact wocky/wocky-bare-contact.c | 2 +- wocky/wocky-bare-contact.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) commit ffa7dac943af0bba37420f1d4df1d23f80daa734 Author: Guillaume Desmottes Date: Wed Aug 26 12:47:32 2009 +0100 add WockyContact which will be used as a base class for all contact objects wocky/Makefile.am | 2 + wocky/wocky-contact.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-contact.h | 60 +++++++++++++++++++ wocky/wocky-types.h | 1 + 4 files changed, 221 insertions(+) commit 7b9bff7159e5fdb9b7e8e7032d9d8073a03c05df Author: Guillaume Desmottes Date: Wed Aug 26 12:46:51 2009 +0100 wocky-bare-contact: fix doc section wocky/wocky-bare-contact.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit c2cadffcb73b9869cd3439ba3fd7bcd63675f5ad Author: Guillaume Desmottes Date: Wed Aug 26 12:35:18 2009 +0100 rename WockyContact to WockyBareContact tests/wocky-bare-contact-test.c | 138 ++++++++++++------------- tests/wocky-roster-test.c | 160 ++++++++++++++--------------- wocky/wocky-bare-contact.c | 216 ++++++++++++++++++++-------------------- wocky/wocky-bare-contact.h | 76 +++++++------- wocky/wocky-roster.c | 86 ++++++++-------- wocky/wocky-roster.h | 10 +- wocky/wocky-types.h | 2 +- 7 files changed, 344 insertions(+), 344 deletions(-) commit 803cd9cc6bc424871f949b7d11a83a832967ef06 Author: Guillaume Desmottes Date: Wed Aug 26 12:28:54 2009 +0100 rename wocky-contact-test.c to wocky-bare-contact-test.c .gitignore | 2 +- tests/Makefile.am | 8 +- tests/wocky-bare-contact-test.c | 317 ++++++++++++++++++++++++++++++++++++++++ tests/wocky-contact-test.c | 317 ---------------------------------------- 4 files changed, 322 insertions(+), 322 deletions(-) commit 5659b40c747817bcdf841ea1d6e208da6382758b Author: Guillaume Desmottes Date: Wed Aug 26 12:26:06 2009 +0100 rename wocky-contact.[ch] to wocky-bare-contact.[ch] tests/wocky-contact-test.c | 2 +- tests/wocky-roster-test.c | 2 +- wocky/Makefile.am | 4 +- wocky/wocky-bare-contact.c | 618 +++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-bare-contact.h | 93 +++++++ wocky/wocky-contact.c | 618 --------------------------------------------- wocky/wocky-contact.h | 93 ------- wocky/wocky-roster.c | 2 +- 8 files changed, 716 insertions(+), 716 deletions(-) commit 9a5e32f52df7712faef82edf929d14f6b1db0c9a Merge: 69ec13a f72e909 Author: Guillaume Desmottes Date: Fri Aug 28 11:03:18 2009 +0100 Merge branch 'roster+edit+flying' commit f72e9099378fca8821869e6c406e090f7394f5d7 Author: Guillaume Desmottes Date: Fri Aug 28 10:32:52 2009 +0100 test_roster_add_contact: call add_contact with an existing contact but different details tests/wocky-roster-test.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) commit 30f1a723266c6555369c8c8d48eb7f4e982c25e5 Author: Guillaume Desmottes Date: Fri Aug 28 10:31:24 2009 +0100 wocky_roster_add_contact_async: replace current details if needed When we have an add contact and the contact is already on the roster, we should check the details are the same, and if they are not, update the contact, _replacing_ the current details (name, group) with those from the add call. wocky/wocky-roster.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) commit 475c9104cf7a9d875141d25a205f4f1293f51f32 Author: Guillaume Desmottes Date: Fri Aug 28 10:15:48 2009 +0100 roster: fix a typo wocky/wocky-roster.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit d368de837f1acdf4087f776cf52cee95c95d0b62 Author: Guillaume Desmottes Date: Fri Aug 28 10:14:36 2009 +0100 test_contact_copy: fix a comment tests/wocky-contact-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit d77e579856adc2f30bb7410613a4b4ca8f7720a6 Author: Guillaume Desmottes Date: Thu Aug 27 17:54:02 2009 +0100 change_roster_iq_cb: remove FIXME about upgrade stanza and explain the rational wocky/wocky-roster.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) commit 69ec13a5764686c3eb1e42a5c5c10f661ea3ede3 Author: Vivek Dasmohapatra Date: Thu Aug 27 14:56:16 2009 +0100 Add missing gtk-doc markup, note when args can be NULL to ignore. wocky/wocky-connector.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) commit b079d8b3c45ab865a52864becb11bdac830ee3cd Author: Vivek Dasmohapatra Date: Thu Aug 27 13:21:52 2009 +0100 Add missing connector entry in sgml file. docs/reference/wocky-docs.sgml | 1 + 1 file changed, 1 insertion(+) commit 8296dc56b00369e4fbe30fa64b2ea8f3ca34c47e Author: Vivek Dasmohapatra Date: Thu Aug 27 13:13:37 2009 +0100 Returns markup needs to be last in a function doc. wocky/wocky-connector.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) commit 07a6ff240df931f1d3af5319e1e8eb59c580f3c1 Author: Vivek Dasmohapatra Date: Wed Aug 26 18:05:47 2009 +0100 Documentation fixes and gtk-doc-bug workarounds. Documented remaining WockyConnectorError enum values Names of args in header file must match names in doc string: C file signatures are ignored for this: Make header file names match C file arg names to avoid confusion and make gtk-doc shut up. Code flow diagram should be treated as a code example by gtk-doc. wocky/wocky-connector.c | 4 ++++ wocky/wocky-connector.h | 44 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 38 insertions(+), 10 deletions(-) commit d2b1dc9ae9139877f6aa93dd4470bd76c075fbe7 Author: Vivek Dasmohapatra Date: Wed Aug 26 17:59:52 2009 +0100 Minor doc whitespace, typo and content fixes. wocky/wocky-connector.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) commit f1662d06e093a94eb5bf3aab2f8e7320f649536b Author: Vivek Dasmohapatra Date: Wed Aug 26 16:12:44 2009 +0100 Docs added for wocky-connector.c wocky/wocky-connector.c | 193 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 188 insertions(+), 5 deletions(-) commit aa19dda9e0a91139c3042828d1cd096a62ca2bff Author: Guillaume Desmottes Date: Wed Aug 26 15:07:07 2009 +0100 wocky-xmpp-connection: add missing arg in the doc of some functions wocky/wocky-xmpp-connection.c | 3 +++ 1 file changed, 3 insertions(+) commit 84eba0b981557f364e4b9718fbcfa808b9ca2406 Author: Guillaume Desmottes Date: Wed Aug 26 15:00:04 2009 +0100 fix wocky_decode_jid doc wocky/wocky-utils.c | 1 + 1 file changed, 1 insertion(+) commit 3e5c7bc73425720b4ecee04bdb7c1c08e97fad4a Author: Guillaume Desmottes Date: Wed Aug 26 14:50:47 2009 +0100 fix WockyRosterError doc wocky/wocky-roster.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit 213032b24421c9ab2244a44ba7e4977f48a8c572 Author: Guillaume Desmottes Date: Wed Aug 26 14:55:04 2009 +0100 fix wocky_tls_session_server_new doc wocky/wocky-tls.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) commit c524818f6f93b1b0fb5ec85553e4e8c6c4c8a7e4 Author: Guillaume Desmottes Date: Wed Aug 26 14:51:43 2009 +0100 fix wocky_xmpp_node_unpack_error doc wocky/wocky-xmpp-node.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) commit 027daab444c52cdb8c4c6deedbebc8c9166ee2b7 Author: Guillaume Desmottes Date: Wed Aug 26 14:28:49 2009 +0100 add Class to wocky-sections.txt docs/reference/wocky-sections.txt | 8 ++++++++ 1 file changed, 8 insertions(+) commit efa42b0a4e2505307dfa88a2219e57c83da89cac Author: Guillaume Desmottes Date: Wed Aug 19 14:38:51 2009 +0100 wocky-roster-test: add test_add_contact_twice tests/wocky-roster-test.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) commit 612e04824c25069688878e68f47d71ff94d7f2b5 Author: Guillaume Desmottes Date: Wed Aug 19 14:23:07 2009 +0100 roster_update: print added contact in debug info wocky/wocky-roster.c | 3 +++ 1 file changed, 3 insertions(+) commit 9c61c83e61785959687e804ec97d0716c6f060a1 Author: Guillaume Desmottes Date: Wed Aug 19 14:22:47 2009 +0100 add wocky_contact_debug_print wocky/wocky-contact.c | 14 ++++++++++++++ wocky/wocky-contact.h | 2 ++ 2 files changed, 16 insertions(+) commit fe3f868bb5acedc676e7fa770e04867f906872f7 Author: Guillaume Desmottes Date: Wed Aug 19 14:19:29 2009 +0100 make wocky_roster_subscription_to_string public. That can be useful for debugging print wocky/wocky-roster.c | 6 +++--- wocky/wocky-roster.h | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) commit 9ab532ddb545a6454c1ec51fe2f04063da4c796f Author: Guillaume Desmottes Date: Wed Aug 19 14:14:11 2009 +0100 wocky-roster-test: add test_remove_two_groups tests/wocky-roster-test.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) commit f0018d788796cae5c0ec386f7af2ab7e55950ce5 Author: Guillaume Desmottes Date: Wed Aug 19 12:47:10 2009 +0100 wocky-roster-test: add test_add_two_groups tests/wocky-roster-test.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) commit 513f7188aabe1ba440cda3f968d94ab886847ce4 Author: Guillaume Desmottes Date: Wed Aug 19 12:28:57 2009 +0100 factor out pending_operation_has_changes wocky/wocky-roster.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) commit 817e9ad57283dcbe656c9249f6b2400972e6ce6b Author: Guillaume Desmottes Date: Wed Aug 19 12:06:25 2009 +0100 wocky-roster-test: add test_change_name_remove_add tests/wocky-roster-test.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) commit ebe66f894d4c92ad89bc10ef4ba0d6c2c128c809 Author: Guillaume Desmottes Date: Wed Aug 19 11:48:04 2009 +0100 wocky-roster-test: add test_remove_contact_twice tests/wocky-roster-test.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) commit 275fe5abe2faa5e0fe070fc026738c5cb34e0616 Author: Guillaume Desmottes Date: Wed Aug 19 11:47:34 2009 +0100 build_iq_for_pending: if there is no contact, check first if we want to remove it wocky/wocky-roster.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) commit b62f77a4ea3eb402b55ed162f4e95d013b022c89 Author: Guillaume Desmottes Date: Wed Aug 19 11:33:36 2009 +0100 wocky-roster-test: add test_change_name_twice tests/wocky-roster-test.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) commit 025d7d82bad9a1ff580270f1be8d6081615ec746 Author: Guillaume Desmottes Date: Tue Aug 18 18:56:20 2009 +0100 wocky-roster-test: add test_edit_contact_remove tests/wocky-roster-test.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) commit d8628e8b1cd47349eb670dbebf94b5606e70b22f Author: Guillaume Desmottes Date: Tue Aug 18 18:55:59 2009 +0100 wocky_roster_remove_contact_async: queue operation if another one is flying wocky/wocky-roster.c | 71 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 55 insertions(+), 16 deletions(-) commit 51632617b791c9c4daf6e65edc2b19965bf8414a Author: Guillaume Desmottes Date: Tue Aug 18 16:07:53 2009 +0100 test_multi_contact_edit: try to re-add a group we just removed tests/wocky-roster-test.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) commit 2128425835d244bdbb4bb35b5aecdbcec465f118 Author: Guillaume Desmottes Date: Tue Aug 18 16:07:37 2009 +0100 pending_operation_add_group: remove group from groups_to_remove if needed wocky/wocky-roster.c | 1 + 1 file changed, 1 insertion(+) commit a2bfdca62f52b860ae44627b2dcdaf16fa14bc8e Author: Guillaume Desmottes Date: Tue Aug 18 16:01:30 2009 +0100 test_multi_contact_edit: use Juliet instead of Romeo as example She has 2 groups so allow us to test more stuffs tests/wocky-roster-test.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) commit ecfcfb3c912be2c0e28d1868870dab427e6af1a9 Author: Guillaume Desmottes Date: Tue Aug 18 15:55:00 2009 +0100 test_multi_contact_edit: remove a group we just added tests/wocky-roster-test.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) commit 11df25b03403979b4a628d8ba8f0667baeab7132 Author: Guillaume Desmottes Date: Tue Aug 18 15:51:28 2009 +0100 wocky_roster_contact_remove_group_async: queue operation if another one is flying wocky/wocky-roster.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) commit 213986f24589a3392de19a25fef2e1751e22ffed Author: Guillaume Desmottes Date: Tue Aug 18 14:23:13 2009 +0100 wocky-roster-test: add test_multi_contact_edit tests/wocky-roster-test.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) commit a6026abaebfd850ebdc6a6446fd2b66daa57291e Author: Guillaume Desmottes Date: Tue Aug 18 15:41:24 2009 +0100 wocky_roster_contact_add_group_async: queue operation if another one is flying wocky/wocky-roster.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) commit 37dc05e30aa4f0a0e96f2b7c55879d886d423737 Author: Guillaume Desmottes Date: Tue Aug 18 15:22:47 2009 +0100 use hash tables to store groups_to_add and groups_to_remove wocky/wocky-roster.c | 50 +++++++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 19 deletions(-) commit 2e274f18860854781215976d52192f49dbd0e148 Author: Guillaume Desmottes Date: Tue Aug 18 14:18:02 2009 +0100 wocky-roster-test: factor out check_edit_roster_stanza tests/wocky-roster-test.c | 58 ++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 26 deletions(-) commit fe22244e7c306cb482dab17ec56619aca4cb9a18 Author: Guillaume Desmottes Date: Tue Aug 18 13:25:15 2009 +0100 wocky-roster-test: add test_remove_contact_edit tests/wocky-roster-test.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) commit ded5f82bd7761b97cc91d9175f3216695f627bfb Author: Guillaume Desmottes Date: Tue Aug 18 13:24:58 2009 +0100 wocky_roster_change_contact_name_async: queue operation if another one is flying wocky/wocky-roster.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) commit 7682ff097d5d720412d3beb54300864a4cc18aab Author: Guillaume Desmottes Date: Tue Aug 18 13:24:20 2009 +0100 implement waiting_operations_completed wocky/wocky-roster.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) commit 4b962cb33bd77b5bc9a27899fcd8ff4b5d8189a7 Author: Guillaume Desmottes Date: Tue Aug 18 13:23:53 2009 +0100 build_iq_for_pending: set WOCKY_ROSTER_ERROR_NOT_IN_ROSTER if contact is not roster anymore and there is no add action pending wocky/wocky-roster.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) commit 00884eb5679df8f46a9f7dca0974bb7c7f4477f6 Author: Guillaume Desmottes Date: Tue Aug 18 10:57:59 2009 +0100 add test_remove_contact_re_add tests/wocky-roster-test.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) commit ad29eac246b9c4dc2b0b26fcef81b2b72d8cb546 Author: Guillaume Desmottes Date: Tue Aug 18 10:57:28 2009 +0100 start to implement flying requests support wocky/wocky-roster.c | 422 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 375 insertions(+), 47 deletions(-) commit 21299f70699e597119ea48394d05bb40866b90ad Author: Guillaume Desmottes Date: Mon Aug 17 18:28:28 2009 +0100 wocky-roster-test: factor out check_add_contact_stanza tests/wocky-roster-test.c | 49 +++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 19 deletions(-) commit a2a5d2752142c773a7b277cb9cffcd6c4b72a8d3 Author: Guillaume Desmottes Date: Mon Aug 17 18:11:07 2009 +0100 wocky-roster-test: factor out check_remove_contact_stanza tests/wocky-roster-test.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) commit 301fb4bb31cba1ce5f2013878109736edd6fe8d0 Author: Guillaume Desmottes Date: Mon Aug 17 18:03:16 2009 +0100 wocky-roster-test: factor out ack_iq tests/wocky-roster-test.c | 90 +++++++++++++---------------------------------- 1 file changed, 25 insertions(+), 65 deletions(-) commit 0c00e45ab0033b8153631778637ac3e9e63fa0c1 Author: Guillaume Desmottes Date: Mon Aug 17 17:04:47 2009 +0100 test wocky_contact_copy tests/wocky-contact-test.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) commit 87ea543caf3779e810c64d5d2ef37cbcf65edd1a Author: Guillaume Desmottes Date: Mon Aug 17 17:02:23 2009 +0100 add wocky_contact_copy wocky/wocky-contact.c | 11 +++++++++++ wocky/wocky-contact.h | 2 ++ 2 files changed, 13 insertions(+) commit f9cf534a227831fa76dacdb46b088ef7d3d0db4d Author: Guillaume Desmottes Date: Mon Aug 17 12:23:19 2009 +0100 wocky-roster-test: add comments for each section of tests tests/wocky-roster-test.c | 4 ++++ 1 file changed, 4 insertions(+) commit 7a095da184600d39dde570ce5dcffbac6166da50 Author: Guillaume Desmottes Date: Fri Aug 14 17:50:50 2009 +0100 pass jid, name and groups to wocky_roster_add_contact_async instead of a WockyContact object WockyContact will be renamed to WockyRosterContact at some point and user shouldn't have to create one just to add a contact to the roster. tests/wocky-roster-test.c | 9 +++++---- wocky/wocky-roster.c | 25 ++++++++++++++++++------- wocky/wocky-roster.h | 4 +++- 3 files changed, 26 insertions(+), 12 deletions(-) commit 15cab9324466a7cbff0f9bf07f3ad61daee00ed3 Author: Guillaume Desmottes Date: Fri Aug 14 15:41:30 2009 +0100 test_roster_remove_contact: try to remove twice the same contact tests/wocky-roster-test.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) commit 60601de354886a4a0762d801145189f6688554de Author: Guillaume Desmottes Date: Fri Aug 14 15:41:14 2009 +0100 wocky_roster_remove_contact_async: don't raise an error if contact is not in roster wocky/wocky-roster.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) commit 5bffa35f8194c7d2645c2cfe219c7a1dff7a47c1 Author: Guillaume Desmottes Date: Fri Aug 14 15:31:41 2009 +0100 test_roster_add_contact: try to add twice the same contact tests/wocky-roster-test.c | 7 +++++++ 1 file changed, 7 insertions(+) commit cb0b24ba21ff4963e16f6a7da061c9ec64870d59 Author: Guillaume Desmottes Date: Fri Aug 14 15:31:24 2009 +0100 wocky_roster_add_contact_async: don't raise an error if contact is already in the roster wocky/wocky-roster.c | 13 +++++++------ wocky/wocky-roster.h | 1 - 2 files changed, 7 insertions(+), 7 deletions(-) commit 7b64e80e2c66ae9610f12444d32eb48fcf43ca70 Author: Guillaume Desmottes Date: Fri Aug 14 15:25:51 2009 +0100 wocky_roster_add_contact_async: contacts are garanteed to have a jid wocky/wocky-roster.c | 8 +------- wocky/wocky-roster.h | 1 - 2 files changed, 1 insertion(+), 8 deletions(-) commit 8fe120e8ded8415c81583b063640ed94c2cb5a98 Author: Guillaume Desmottes Date: Fri Aug 14 15:23:59 2009 +0100 wocky_contact_constructed: assert that a jid has been defined It doesn't make sense to create a contact without a jid wocky/wocky-contact.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 67a93b68a4c224b8d16c13a0fe6ec541cd93d992 Author: Guillaume Desmottes Date: Fri Aug 14 12:40:26 2009 +0100 wocky-contact-test: test_remove_group: test with a contact having no group defined tests/wocky-contact-test.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) commit 3c3690615b1227bfd5b8b8cf9cfac1417905d138 Author: Guillaume Desmottes Date: Fri Aug 14 12:39:58 2009 +0100 wocky-contact-test: test with a contact having no group defined tests/wocky-contact-test.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) commit 275e8125a16c5f973d3f089a17cfc41a2a9eed4c Author: Guillaume Desmottes Date: Fri Aug 14 12:32:24 2009 +0100 wocky-contact-test: test_add_group: test with a contact having no group defined tests/wocky-contact-test.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) commit 8e33b30b7678c9280a6a90bc484a9b619875ec13 Author: Guillaume Desmottes Date: Fri Aug 14 16:05:56 2009 +0100 wocky-roster-test: test wocky_roster_contact_remove_group_async tests/wocky-roster-test.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) commit e10d996b2b32014bf2899e3375e95fc8d64e0f64 Author: Guillaume Desmottes Date: Fri Aug 14 12:05:23 2009 +0100 add wocky_roster_contact_remove_group_async wocky/wocky-roster.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-roster.h | 11 ++++++++ 2 files changed, 88 insertions(+) commit 873f687f88876f78d0adb6a5f48f386f23e82d9c Author: Guillaume Desmottes Date: Fri Aug 14 11:45:05 2009 +0100 wocky-contact-test: test wocky_contact_remove_group tests/wocky-contact-test.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) commit e95e242ccb9431bf8226ef08e93f7f6c4ad548e7 Author: Guillaume Desmottes Date: Fri Aug 14 11:44:26 2009 +0100 add wocky_contact_remove_group wocky/wocky-contact.c | 30 ++++++++++++++++++++++++++++++ wocky/wocky-contact.h | 3 +++ 2 files changed, 33 insertions(+) commit aa712d91f9a5fb0e6b2fc1afbd11c0f7e960770d Author: Guillaume Desmottes Date: Fri Aug 14 16:06:37 2009 +0100 wocky-roster-test: test wocky_roster_contact_add_group_async tests/wocky-roster-test.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) commit 2dd8b3d97507535ec469c0dc1f327d3d232f0099 Author: Guillaume Desmottes Date: Fri Aug 14 11:32:09 2009 +0100 add wocky_roster_contact_add_group_async wocky/wocky-roster.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-roster.h | 11 +++++++++ 2 files changed, 74 insertions(+) commit 1752e147afde625fc6c701a2cc84c1ff991f0ac2 Author: Guillaume Desmottes Date: Fri Aug 14 11:29:33 2009 +0100 wocky-contact-test: test wocky_contact_in_group tests/wocky-contact-test.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) commit a96e072994339344181fb2193574ad13649be1b6 Author: Guillaume Desmottes Date: Fri Aug 14 11:29:16 2009 +0100 add wocky_contact_in_group wocky/wocky-contact.c | 19 +++++++++++++++++++ wocky/wocky-contact.h | 3 +++ 2 files changed, 22 insertions(+) commit 0d37ced42ef8da8e18c28403a3b18addceb9962f Author: Guillaume Desmottes Date: Fri Aug 14 11:09:57 2009 +0100 wocky-contact-test: test wocky_contact_add_group tests/wocky-contact-test.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) commit c393cc0f62299f1cab865dfb05657c50c6ebf84b Author: Guillaume Desmottes Date: Fri Aug 14 11:09:35 2009 +0100 add wocky_contact_add_group wocky/wocky-contact.c | 40 ++++++++++++++++++++++++++++++++++++++++ wocky/wocky-contact.h | 3 +++ 2 files changed, 43 insertions(+) commit fd1f44cf1355f8a2af12780c2d4cdaddef1c99aa Author: Guillaume Desmottes Date: Fri Aug 14 16:07:21 2009 +0100 wocky-roster-test: add test_roster_change_name tests/wocky-roster-test.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) commit a1261a0950fd12b180d3291f179e033e4b4f4117 Author: Guillaume Desmottes Date: Thu Aug 13 17:43:59 2009 +0100 add wocky_roster_change_contact_name_async wocky/wocky-roster.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-roster.h | 11 ++++++++++ 2 files changed, 72 insertions(+) commit d2621a79329c1545c1f2e3f2cb572175d479a06c Author: Guillaume Desmottes Date: Thu Aug 13 17:43:34 2009 +0100 build_iq_for_contact: include subscription wocky/wocky-roster.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) commit 21c6363251fa1ad57096b477e6974003cec6dd00 Author: Guillaume Desmottes Date: Thu Aug 13 17:40:24 2009 +0100 wocky-roster-test: ensure that the 'add contact' request doesn't have a subscription attribute tests/wocky-roster-test.c | 1 + 1 file changed, 1 insertion(+) commit b608e6957f20f3a4f4126fb885f3178bf1ddf57a Author: Guillaume Desmottes Date: Thu Aug 13 17:17:02 2009 +0100 roster: merge roster_add_contact_cb and roster_remove_contact_cb to change_roster_iq_cb There is no point to have 2 different callbacks containing exactly the same code. Merge them in a single callback. wocky/wocky-roster.c | 36 ++++++++---------------------------- 1 file changed, 8 insertions(+), 28 deletions(-) commit 1e2124fe8e3c5a7e8fbc1c20d06fc047512f45d9 Author: Guillaume Desmottes Date: Thu Aug 13 17:04:10 2009 +0100 factor out build_iq_for_contact wocky/wocky-roster.c | 72 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 26 deletions(-) commit b566e746aed0937a17f2813029850a80a7e81244 Author: Guillaume Desmottes Date: Thu Aug 13 16:46:23 2009 +0100 fix typo in code wocky/wocky-roster.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit c45f5a884028df38851a234021228bf21ca5076f Author: Guillaume Desmottes Date: Thu Aug 13 15:40:20 2009 +0100 wocky-roster-test: add test_roster_remove_contact tests/wocky-roster-test.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) commit b292d3f827aca059def10203820141fdf5cb62bb Author: Guillaume Desmottes Date: Thu Aug 13 15:39:38 2009 +0100 add wocky_roster_remove_contact_async wocky/wocky-roster.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-roster.h | 11 +++++++ 2 files changed, 95 insertions(+) commit 047055d94343f212a1241178cec58066c0646b32 Author: Guillaume Desmottes Date: Thu Aug 13 15:38:23 2009 +0100 roster: factor out change_roster_operation_complete wocky/wocky-roster.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) commit 72ab4a40163dc836c84743e41396bc465046cc73 Author: Guillaume Desmottes Date: Wed Aug 12 12:40:47 2009 +0100 wocky-roster-test: add test_roster_add_contact tests/wocky-roster-test.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) commit e3ca343bacd5d3d49a56d7b3aa82ca9cdc0fe37f Author: Guillaume Desmottes Date: Wed Aug 12 12:39:48 2009 +0100 add wocky_roster_add_contact_async wocky/wocky-roster.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-roster.h | 12 +++++ 2 files changed, 135 insertions(+) commit 24f57602a015802dc426dd6371912c088bffee63 Author: Guillaume Desmottes Date: Tue Aug 25 15:19:48 2009 +0100 s/SURPRESSIONS/SUPPRESSIONS tests/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 24dd62085abd4c2a2d897f2925e87b2abd089ccc Author: Guillaume Desmottes Date: Fri Aug 21 13:58:10 2009 +0100 Ship generated certificats and keys There is no real point to generate them on each machine and that confuse distcheck. tests/Makefile.am | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) commit 17af558c331cee49550590e61871d0115d4d3e88 Author: Guillaume Desmottes Date: Fri Aug 21 13:53:30 2009 +0100 add test-report.xml and sasl-test.db to CLEANFILES tests/Makefile.am | 3 +++ 1 file changed, 3 insertions(+) commit b2fd687cc698d7e2a6b6a1b67986d055e32f8d6b Author: Guillaume Desmottes Date: Fri Aug 21 14:01:10 2009 +0100 tests/Makefile.am: keys and certs are actually in top_srcdir tests/Makefile.am | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) commit 1cbaad1503cac313dcae262fa089e4f48bbff528 Author: Guillaume Desmottes Date: Fri Aug 21 13:52:51 2009 +0100 define DISTCHECK_CONFIGURE_FLAGS as distcheck has to build with --enable-gtk-doc Makefile.am | 2 ++ 1 file changed, 2 insertions(+) commit 909e2d097ce5e672cb7a485f5d90d527b3f90eab Author: Guillaume Desmottes Date: Fri Aug 21 12:19:54 2009 +0100 tests/Makefile.am: add WOCKY_CFLAGS to AM_CFLAGS This allow to build examples when running distcheck. tests/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 92d8ae8bcc3ca80dee96b5db7d1795af984959a6 Author: Guillaume Desmottes Date: Fri Aug 21 12:19:17 2009 +0100 examples/Makefile.am: add WOCKY_CFLAGS to AM_CFLAGS This allow to build examples when running distcheck. examples/Makefile.am | 1 + 1 file changed, 1 insertion(+) commit 2a8edcd50f8548e02e5382bb66459df35ca4c41d Author: Guillaume Desmottes Date: Fri Aug 21 12:19:01 2009 +0100 configure.ac: define WOCKY_CFLAGS which will be used to build tests and examples configure.ac | 4 ++++ 1 file changed, 4 insertions(+) commit f4464e4b0f3deb0e5b8f26a046d7eb9fefa84076 Author: Guillaume Desmottes Date: Fri Aug 21 12:10:06 2009 +0100 include wocky-xmpp-reader.h: include "wocky-xmpp-stanza.h" instead of This is what other header files do and make distcheck happier. wocky/wocky-xmpp-reader.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 9fb456482fc5869d1fc3233ae4e344780188b069 Author: Guillaume Desmottes Date: Fri Aug 21 11:58:29 2009 +0100 add certs/ca-cert.cfg and certs/tls-cert.cfg to EXTRA_DIST tests/Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 9736949f6c51260bd5a30d365acce6cbed07ea92 Author: Guillaume Desmottes Date: Fri Aug 21 10:59:42 2009 +0100 add wocky-types.h to wocky/Makefile.am wocky/Makefile.am | 1 + 1 file changed, 1 insertion(+) commit 39fe8324a21e88fb1bff31c079f13264b37f5b05 Author: Guillaume Desmottes Date: Fri Aug 21 10:58:30 2009 +0100 remove tabs wocky/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 73e60fbcecca2db717379d653c15af0c7375a6db Author: Guillaume Desmottes Date: Thu Aug 20 12:40:56 2009 +0100 add wocky.types to gitignore as we generate it now .gitignore | 1 + 1 file changed, 1 insertion(+) commit 2110a2b2e2ab09d3746c8a5e57f5fac1287c1bf3 Author: Guillaume Desmottes Date: Thu Aug 20 12:39:48 2009 +0100 add wocky-overrides.txt This file can be used to manually override scanned declarations. docs/reference/wocky-overrides.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) commit 847bd927bda1ab2b00c50f11bf382c9a166c6908 Author: Guillaume Desmottes Date: Thu Aug 20 12:39:06 2009 +0100 add generated wocky-sections.txt This file is supposed to be generated once and then manually edited. docs/reference/wocky-sections.txt | 375 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 375 insertions(+) commit 87ee84c6126e73578219b8a8451dfc90da644a0c Author: Guillaume Desmottes Date: Thu Aug 20 12:37:14 2009 +0100 tweak wocky-docs.sgml a bit - Remove releaseinfo section, doc is not uploaded anywhere atm - Set main chapter's title to "API Reference" - Remove Glossary docs/reference/wocky-docs.sgml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) commit 0b330f21ad19a3ef89c481cd4061515f2c996078 Author: Guillaume Desmottes Date: Thu Aug 20 12:33:15 2009 +0100 add generated wocky-docs.sgml This file is supposed to be generated once and then manually edited. docs/reference/wocky-docs.sgml | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) commit 31c7a20ff0c37c3304462d01422c4bedab2e37ba Merge: bfe67ce 51742b0 Author: Guillaume Desmottes Date: Tue Aug 25 13:06:07 2009 +0100 Merge branch 'tls-handshake-async' Conflicts: configure.ac commit bfe67ce54111082c5c60f66dffe2654ad79181cf Author: Guillaume Desmottes Date: Thu Aug 20 15:44:32 2009 +0100 depend on gio 2.21.x as we use gnio configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 868cb53ce2895b4eb674fb6318fb76663920ab52 Author: Guillaume Desmottes Date: Thu Aug 20 12:19:52 2009 +0100 remove wocky.types from git as it's now generated when building doc docs/reference/wocky.types | 11 ----------- 1 file changed, 11 deletions(-) commit 8035a9fe05321eaad4f104a349e5ee90bf08a3ae Author: Guillaume Desmottes Date: Thu Aug 20 12:19:16 2009 +0100 docs/reference/Makefile.am: pass magic option to SCAN_OPTIONS to generate the types file docs/reference/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit aa757890431d07d93e848d902a50c96bf845df2b Author: Guillaume Desmottes Date: Thu Aug 20 11:40:25 2009 +0100 add generated doc files to gitignore .gitignore | 15 +++++++++++++++ 1 file changed, 15 insertions(+) commit 51742b08e3b58ad9e563a138f6e545762ad87d57 Author: Guillaume Desmottes Date: Wed Aug 19 18:35:48 2009 +0100 wocky-tls: document WOCKY_TLS_DEBUG_LEVEL wocky/wocky-tls.c | 11 +++++++++++ 1 file changed, 11 insertions(+) commit 4e991acf6e66e7033211989a48457cd2fdd54316 Author: Guillaume Desmottes Date: Wed Aug 19 15:31:40 2009 +0100 re-implement error_to_string using gnutls_strerror_name wocky/wocky-tls.c | 121 +++--------------------------------------------------- 1 file changed, 6 insertions(+), 115 deletions(-) commit d81e3e2465b83bba927febed814684dd6d208e9b Author: Guillaume Desmottes Date: Wed Aug 19 15:08:10 2009 +0100 style fixes wocky/wocky-tls.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit f8a20b929d45cbbcce568d42113416c536c596a5 Author: Guillaume Desmottes Date: Wed Aug 19 15:00:00 2009 +0100 wocky-tls: DON'T SHOUT IN DEBUG MESSAGES wocky/wocky-tls.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) commit aa74587f0022690b318fdb06def841cd91d534b4 Author: Vivek Dasmohapatra Date: Mon Aug 17 18:44:05 2009 +0100 gnutls async handshake bug was actually fixed in 2.8.2 configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit b3cc7012ddc5ba141c01b3db279c558b3b328004 Author: Vivek Dasmohapatra Date: Mon Aug 17 16:19:02 2009 +0100 Whitespace fixes. wocky/wocky-connector.c | 2 +- wocky/wocky-tls.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) commit dc7dd80b7e088014a8ed7fa6811cdd84ff65b339 Author: Vivek Dasmohapatra Date: Mon Aug 17 12:14:07 2009 +0100 Make old ssl connect async as well. wocky/wocky-connector.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) commit e9e96b4d2761468615283e675d6a12400a314d2b Author: Vivek Dasmohapatra Date: Thu Aug 6 12:26:13 2009 +0100 DEBUG to let us see the endpoint of sync as well as async handshakes. wocky/wocky-tls.c | 3 +++ 1 file changed, 3 insertions(+) commit e704fcc7497bb2f04e90ba4517eae0281ea9d870 Author: Vivek Dasmohapatra Date: Thu Aug 6 12:22:25 2009 +0100 Adapt starttls_handshake_cb so that it can be the endpoint of both old-style SSL and new TLS encryption negotiation. wocky/wocky-connector.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) commit f1deece9af1930ca1b3ca9fbe554daf114c6ebcd Author: Guillaume Desmottes Date: Wed Aug 19 15:10:43 2009 +0100 wocky-connector: call wocky_tls_session_handshake_async with a high priority wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 6ac2973ab54340318d05284b128fca4de8f7519a Author: Guillaume Desmottes Date: Wed Aug 19 15:10:07 2009 +0100 wocky-tls debugging via DEBUG wocky/wocky-connector.c | 2 +- wocky/wocky-debug.c | 1 + wocky/wocky-debug.h | 1 + wocky/wocky-tls.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 179 insertions(+), 7 deletions(-) commit 1bb89abf346c3da438005d17a32956fc6dac728d Author: Vivek Dasmohapatra Date: Wed Aug 5 12:02:31 2009 +0100 Make the TLS handshake use the async calls (possible deadlock found in tests). wocky/wocky-connector.c | 47 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 15 deletions(-) commit dee4e5d56916f60b4ff047dd2dd7e4a05a19251c Author: Guillaume Desmottes Date: Wed Aug 19 14:14:56 2009 +0100 wocky-test-helper: increase timeout to 3 seconds 2 seconds isn't enough when valgriding some complex tests. tests/wocky-test-helper.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit cb691cbbdd05f738768ac04ded40d2ed8cf76a94 Author: Guillaume Desmottes Date: Wed Aug 19 18:45:53 2009 +0100 rebuild gtk-doc when source files are changed docs/reference/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 122bf6f738a52d57b275acf00ce51f9c052e1c1a Author: Guillaume Desmottes Date: Mon Aug 17 16:02:32 2009 +0100 wocky-contact-test: fix a typo tests/wocky-contact-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit ca2ed687b63d8e7b702d36cbba91b8b632b2f171 Author: Guillaume Desmottes Date: Mon Aug 17 16:00:28 2009 +0100 wocky-roster-test: unref contacts returned by wocky_roster_get_all_contacts tests/wocky-roster-test.c | 4 ++++ 1 file changed, 4 insertions(+) commit 5682af540b6bcb86064a8b45285e28a0f25cb7cc Author: Guillaume Desmottes Date: Mon Aug 17 15:59:31 2009 +0100 wocky_roster_get_all_contacts ref the contacts Contacts could be unreffed by an async op while user still use the GSList. wocky/wocky-roster.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 9d4406fb86a8bc97478a6e41644fa193dc30f976 Author: Guillaume Desmottes Date: Fri Aug 14 17:18:52 2009 +0100 wocky_contact_set_subscription: fix type check ordering wocky/wocky-contact.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit bc39d1e285d025511a3a0aff7bdffdff4253ade5 Author: Guillaume Desmottes Date: Fri Aug 14 17:13:05 2009 +0100 wocky-contact-test: test_contact_equal: add regression test for buggy old group comparaison algorithm tests/wocky-contact-test.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) commit 70a08d897b2ca2e825e9995c6bd0620fd8198d5b Author: Guillaume Desmottes Date: Fri Aug 14 17:12:40 2009 +0100 wocky-contact: fix groups_equal wocky/wocky-contact.c | 57 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 22 deletions(-) commit c44ec1644338ebe3102867f02dc3d51c86c90e78 Author: Guillaume Desmottes Date: Fri Aug 14 16:13:05 2009 +0100 wocky_contact_set_name: fix type check ordering There is no point to check that the contact is actually a WockyContact object *after* calling WOCKY_CONTACT_GET_PRIVATE. wocky/wocky-contact.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 29dd25c6120e05e02207df6c1b422c7652746b3a Author: Guillaume Desmottes Date: Fri Aug 14 12:31:48 2009 +0100 wocky-contect-test: test_contact_equal: test with a contact having not group defined tests/wocky-contact-test.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) commit 77c3cd8fbaddffec2dfb403d74f908971efa0cc2 Author: Guillaume Desmottes Date: Fri Aug 14 12:29:53 2009 +0100 wocky-contact: groups_equal: deal with groups being NULL wocky/wocky-contact.c | 6 ++++++ 1 file changed, 6 insertions(+) commit 15dbdce5f095efadc584a5bbf9c56e7a0984e941 Author: Guillaume Desmottes Date: Wed Aug 12 12:43:28 2009 +0100 rename WOCKY_ROSTER_INVALID_STANZA to WOCKY_ROSTER_ERROR_INVALID_STANZA wocky/wocky-roster.c | 2 +- wocky/wocky-roster.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) commit aca82a6c5db3ef600eceeaec8ac84027e006778e Author: Guillaume Desmottes Date: Wed Aug 12 11:44:29 2009 +0100 wocky-roster-test: factor out send_roster_update tests/wocky-roster-test.c | 149 +++++++++++++++++----------------------------- 1 file changed, 56 insertions(+), 93 deletions(-) commit ae09b98ec9ff7a7f0617d4b22a07bffc74e6bd13 Author: Guillaume Desmottes Date: Tue Aug 11 16:48:26 2009 +0100 wocky-roster-test: add test_roster_upgrade_change tests/wocky-roster-test.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) commit 387f02a68ad659e8272834d9015dc0d347e9f055 Author: Guillaume Desmottes Date: Tue Aug 11 16:47:39 2009 +0100 wocky-contact: fire notify change when a property is changed wocky/wocky-contact.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) commit c8446d78ac6ede0f0cea4e268f2e1ee77b03c916 Author: Guillaume Desmottes Date: Tue Aug 11 16:41:00 2009 +0100 wocky-contact: factor out groups_equal wocky/wocky-contact.c | 67 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 26 deletions(-) commit d30780ae4836830a730d88107c33eb040b42eeee Author: Guillaume Desmottes Date: Tue Aug 11 16:05:01 2009 +0100 Simplify wocky_contact_set_* setters They are supposed to be simple wocky-only setters, so they shouldn't fail. wocky/wocky-contact.c | 43 ++++++++++++------------------------------- wocky/wocky-contact.h | 10 ++++------ wocky/wocky-roster.c | 7 +++---- 3 files changed, 19 insertions(+), 41 deletions(-) commit 54fd7625c3e7d1effdb493b110ebb8b63ff03e47 Author: Guillaume Desmottes Date: Tue Aug 11 15:25:58 2009 +0100 wocky-roster-test: add test_roster_upgrade_remove tests/wocky-roster-test.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) commit 91ced7648bbc8273463a05798e1c872a97651b32 Author: Guillaume Desmottes Date: Tue Aug 11 15:23:53 2009 +0100 roster: fire the 'removed' signal when a contact is removed from the roster wocky/wocky-roster.c | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) commit df074b890151ca1c9200df8a04f5c954cb4de55a Author: Guillaume Desmottes Date: Tue Aug 11 15:03:41 2009 +0100 roster_update: don't fire the added signal when fetching the roster wocky/wocky-roster.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) commit e0d0284048126aae2f3e696247ebb1b86a8e5cb6 Author: Guillaume Desmottes Date: Tue Aug 11 14:34:23 2009 +0100 wocky-roster-test: add test_roster_upgrade_add tests/wocky-roster-test.c | 119 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 114 insertions(+), 5 deletions(-) commit 66dfe096026869dad4247443cc59b8dd9cae3b1b Author: Guillaume Desmottes Date: Tue Aug 11 14:33:47 2009 +0100 roster.c: fire 'added' signal when a contact is added wocky/wocky-roster.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) commit c9adc573007df14e2a9da72882c3e0dd9ba1ccfc Author: Guillaume Desmottes Date: Tue Aug 11 14:33:20 2009 +0100 roster_iq_handler_set_cb: ack the IQ wocky/wocky-roster.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) commit 9ffe3b8cbe7923cc3d40273170632f6b8108fb3d Author: Guillaume Desmottes Date: Tue Aug 11 13:19:39 2009 +0100 test wocky_roster_get_all_contacts tests/wocky-roster-test.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) commit 102310d622e5d34f3a3c95a524b2507e1414de32 Author: Guillaume Desmottes Date: Tue Aug 11 13:19:31 2009 +0100 add wocky_roster_get_all_contacts wocky/wocky-roster.c | 17 +++++++++++++++++ wocky/wocky-roster.h | 2 ++ 2 files changed, 19 insertions(+) commit 7879703b3efd70e31689fcb41e370ffe8f350ac4 Author: Guillaume Desmottes Date: Tue Aug 11 11:57:11 2009 +0100 fetch_roster_reply_cb: test to send more than one contact tests/wocky-roster-test.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) commit 26511487953c847f37adfe7ce245395b0b44e98f Author: Guillaume Desmottes Date: Tue Aug 11 11:54:33 2009 +0100 fetch_roster_reply_roster_cb: use wocky_contact_equal to check contact tests/wocky-roster-test.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) commit 18b4ae6dcda5ebab64de8bde4df58e9375678e57 Author: Guillaume Desmottes Date: Tue Aug 11 11:48:52 2009 +0100 add wocky-contact-test.c to test wocky_contact_equal .gitignore | 1 + tests/Makefile.am | 9 ++++- tests/wocky-contact-test.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 1 deletion(-) commit fed52b8d0021c293617a592d3a59966c75edf459 Author: Guillaume Desmottes Date: Tue Aug 11 11:48:21 2009 +0100 add wocky_contact_equal wocky/wocky-contact.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-contact.h | 3 +++ 2 files changed, 62 insertions(+) commit 5da9be52405a5ff215c1f660b57dfc3824fcc601 Author: Guillaume Desmottes Date: Tue Aug 11 10:51:51 2009 +0100 wocky-roster-test: test if the contact fetched is the right one tests/wocky-roster-test.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) commit 82330ddba30e267eccf614fc0cb94115c764120a Author: Guillaume Desmottes Date: Tue Aug 11 10:51:04 2009 +0100 roster_update: fix parsing of groups wocky/wocky-roster.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) commit 0bf8a01eec2b93d4177e68be0b203287e2f12a09 Author: Guillaume Desmottes Date: Tue Aug 11 10:24:37 2009 +0100 add wocky_roster_get_contact wocky/wocky-roster.c | 9 +++++++++ wocky/wocky-roster.h | 4 ++++ 2 files changed, 13 insertions(+) commit a953e9743647991653eab2d80340ffabdf9b630e Author: Guillaume Desmottes Date: Tue Aug 11 10:24:19 2009 +0100 move WockyContact definition to a newly created wocky-types.h to avoid circular includes wocky/wocky-contact.h | 2 +- wocky/wocky-types.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) commit d68f0b29c5333fa89b54f5b9b31515bd85eaa221 Author: Guillaume Desmottes Date: Mon Aug 10 17:25:39 2009 +0100 roster_fetch_roster_cb: unref the IQ reply once we're done with it wocky/wocky-roster.c | 3 +++ 1 file changed, 3 insertions(+) commit b1b095eea2c31c6bffb10c696bb477d40c126070 Author: Guillaume Desmottes Date: Mon Aug 10 17:14:57 2009 +0100 test_fetch_roster_send_iq: call wocky_roster_fetch_roster_finish to free to memory used by the fetch call tests/wocky-roster-test.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) commit 8104c0654a11e26dccd96149eb7088c41aabf173 Author: Guillaume Desmottes Date: Mon Aug 10 17:14:36 2009 +0100 wocky-roster-test: unref the roster when tests are done tests/wocky-roster-test.c | 2 ++ 1 file changed, 2 insertions(+) commit 30748490b45b002ca2746dd4ffceb2df998def61 Author: Guillaume Desmottes Date: Mon Aug 10 17:13:43 2009 +0100 wocky_contact_set_property: copy the groups array wocky/wocky-contact.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit f7a69bb212a572e68e005726ba2b65049089bec4 Author: Guillaume Desmottes Date: Mon Aug 10 16:43:59 2009 +0100 wocky-roster-test.c: use test_init and test_deinit tests/wocky-roster-test.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) commit 9eaaaf74a922cbb008e79242b3c6096d645946d2 Author: Guillaume Desmottes Date: Mon Aug 10 16:42:54 2009 +0100 roster_update: use a temporary GPtrArray to store groups for easier memory management wocky/wocky-roster.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) commit ef080800a739d969e324ef0bba1a48d472104319 Author: Guillaume Desmottes Date: Mon Aug 10 16:40:36 2009 +0100 wocky_roster_fetch_roster_async: don't leak the IQ wocky/wocky-roster.c | 1 + 1 file changed, 1 insertion(+) commit dd11d5db67a56c23284ce0f137f3849adad86e7f Author: Guillaume Desmottes Date: Mon Aug 10 16:24:36 2009 +0100 wocky-roster-test.c: add a small comment describing each test tests/wocky-roster-test.c | 4 ++++ 1 file changed, 4 insertions(+) commit 6c1088ffce48ce101fadaae6801057054dc03f08 Author: Guillaume Desmottes Date: Mon Aug 10 16:20:25 2009 +0100 wocky-roster: add some TODO/FIXME wocky/wocky-roster.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit e0ae09791c0c9aef1a702f744b3568cc0627b4e0 Author: Guillaume Desmottes Date: Mon Aug 10 16:18:31 2009 +0100 wocky_roster_fetch_roster_async: store the result as an object variable and raise an error if another operation is pending wocky/wocky-roster.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) commit 210319918ffb27538b3aa91729963b3ef23882d4 Author: Guillaume Desmottes Date: Mon Aug 10 16:01:06 2009 +0100 change WockyRosterSubscriptionType to WockyRosterSubscriptionFlags wocky/wocky-contact.c | 10 +++++----- wocky/wocky-contact.h | 4 ++-- wocky/wocky-roster.c | 2 +- wocky/wocky-roster.h | 13 +++++++------ 4 files changed, 15 insertions(+), 14 deletions(-) commit e13f16ee2d9fcd14ef6616289a2a742fd7e5beb1 Author: Guillaume Desmottes Date: Mon Aug 10 15:42:30 2009 +0100 use g_set_error_literal instead of g_error_new_literal wocky/wocky-roster.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 9973bd9feed4cbb95803203dd8c268715effa59b Author: Guillaume Desmottes Date: Mon Aug 10 15:21:56 2009 +0100 wocky_roster_dispose: unregister the handler when disposing wocky/wocky-roster.c | 6 ++++++ 1 file changed, 6 insertions(+) commit 9ff0b89bd2122f59bd5131c890e2fecbee020a40 Author: Guillaume Desmottes Date: Mon Aug 10 15:20:10 2009 +0100 wocky-roster: document the items hash table wocky/wocky-roster.c | 1 + 1 file changed, 1 insertion(+) commit a1732efd732b1fc31613ce5beab35680e818af6a Author: Guillaume Desmottes Date: Mon Aug 10 15:16:09 2009 +0100 No need to pass the WockyXmppConnection to the Roster object; the Porter is enough tests/wocky-roster-test.c | 6 +++--- wocky/wocky-roster.c | 25 ++----------------------- wocky/wocky-roster.h | 3 +-- 3 files changed, 6 insertions(+), 28 deletions(-) commit c05e29dbdc0ec697ecf650bdbc9f1ff1d8bddeaf Author: Jonny Lamb Date: Tue Jul 14 16:32:57 2009 +0100 Add fetch-roster-reply test. Signed-off-by: Jonny Lamb tests/wocky-roster-test.c | 91 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 87 insertions(+), 4 deletions(-) commit ee5dd26f5d0b700cad280dd3037f576c032c32e5 Author: Jonny Lamb Date: Sat Jul 11 19:28:56 2009 +0100 Set new information on an existing roster item on update. Signed-off-by: Jonny Lamb wocky/wocky-roster.c | 75 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 32 deletions(-) commit b801a14a8197b52dd7e1b6f18ffe669154665dc5 Author: Jonny Lamb Date: Sat Jul 11 19:27:13 2009 +0100 Implement several functions of WockyContact and document them. Signed-off-by: Jonny Lamb wocky/wocky-contact.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++++- wocky/wocky-contact.h | 8 ++- 2 files changed, 188 insertions(+), 6 deletions(-) commit 4f80c17ed6819b922339f4ebe6d511087891354b Author: Jonny Lamb Date: Sat Jul 11 18:49:52 2009 +0100 Implement partial roster stanza parsing and creating WockyContacts. Signed-off-by: Jonny Lamb wocky/wocky-roster.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 123 insertions(+), 8 deletions(-) commit 2bcac6bd59e90647752569b6819e8e2e3e4a4ca5 Author: Jonny Lamb Date: Sat Jul 11 18:47:42 2009 +0100 Free data held by WockyContact on finalize. Signed-off-by: Jonny Lamb wocky/wocky-contact.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) commit 556dd7f5fa2c4a41b7d0ac358f4cf4e82faaa55e Author: Jonny Lamb Date: Sat Jul 11 15:37:26 2009 +0100 Updated WockyContact to include some properties. Signed-off-by: Jonny Lamb wocky/wocky-contact.c | 109 +++++++++++++++++++++++++++++++++++++------------- wocky/wocky-contact.h | 15 ++++--- 2 files changed, 91 insertions(+), 33 deletions(-) commit 89e5c9af51f98e98a9eea7c06a5cf4e71aef15d7 Author: Jonny Lamb Date: Sat Jul 11 14:12:59 2009 +0100 Added WockyRosterSubscriptionType enum. Signed-off-by: Jonny Lamb wocky/wocky-roster.h | 9 +++++++++ 1 file changed, 9 insertions(+) commit 6cf6fb79510acd9428e3262922e1163d0bd36b06 Author: Jonny Lamb Date: Sat Jul 4 17:31:18 2009 +0100 Add roster error quark function. Signed-off-by: Jonny Lamb wocky/wocky-roster.c | 18 ++++++++++++++++++ wocky/wocky-roster.h | 19 +++++++++++++++++++ 2 files changed, 37 insertions(+) commit d8d833bca6744719834b074193e41d70ecb5b039 Author: Jonny Lamb Date: Fri Jul 3 14:53:12 2009 +0100 Make the reply from roster fetch or set IQ call the same code. Signed-off-by: Jonny Lamb wocky/wocky-roster.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) commit 7282e0a939947a23ba82c2e3e232c6aad1268c10 Author: Jonny Lamb Date: Fri Jul 3 14:37:50 2009 +0100 Make wocky_roster_fetch_roster an async function. Signed-off-by: Jonny Lamb tests/wocky-roster-test.c | 2 +- wocky/wocky-roster.c | 39 +++++++++++++++++++++++++++++++++------ wocky/wocky-roster.h | 7 ++++++- 3 files changed, 40 insertions(+), 8 deletions(-) commit 511b139ef99e7f342007d6a42c9c0f0b0e25241c Author: Jonny Lamb Date: Fri Jul 3 12:47:13 2009 +0100 Only listen to set IQs in the roster. Signed-off-by: Jonny Lamb wocky/wocky-roster.c | 36 ++++++------------------------------ 1 file changed, 6 insertions(+), 30 deletions(-) commit 59fb09db7ff67aa9d18b11ea5a5a59b14534118a Author: Jonny Lamb Date: Thu Jul 2 20:54:55 2009 +0100 Implement more of roster IQ stanza handler. Signed-off-by: Jonny Lamb wocky/wocky-roster.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) commit 36fa7099d59eafe8ac755907c20d3ac171437e9f Author: Jonny Lamb Date: Thu Jul 2 19:32:38 2009 +0100 Add test for fetch-roster. Signed-off-by: Jonny Lamb tests/wocky-roster-test.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) commit 292875acf870942e33373ee96bfc35485edffe77 Author: Jonny Lamb Date: Thu Jul 2 18:53:18 2009 +0100 test_initialisation: unref the porter after use. Signed-off-by: Jonny Lamb tests/wocky-roster-test.c | 1 + 1 file changed, 1 insertion(+) commit b5cf9e934faa7af8825eb317da18939a44a092b2 Author: Jonny Lamb Date: Thu Jul 2 18:51:27 2009 +0100 Keep references to the connection and porter in the roster. Signed-off-by: Jonny Lamb wocky/wocky-roster.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit cc123321ef6259f03ee6da25c9c5d7118cb4b009 Author: Jonny Lamb Date: Thu Jul 2 18:38:07 2009 +0100 from attribute is not needed when fetching roster. Signed-off-by: Jonny Lamb wocky/wocky-roster.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) commit 3017de1df49b227248416778ab384cebc5d2331f Author: Jonny Lamb Date: Thu Jul 2 18:27:30 2009 +0100 Add back wocky_roster_fetch_roster function. Signed-off-by: Jonny Lamb wocky/wocky-roster.c | 71 ++++++++++++++++++++++++++++++---------------------- wocky/wocky-roster.h | 2 ++ 2 files changed, 43 insertions(+), 30 deletions(-) commit 8857fd536b518a65adb419af8304d02bffe379e3 Author: Jonny Lamb Date: Thu Jul 2 18:22:30 2009 +0100 Use the porter to send the iq instead of the connection. Signed-off-by: Jonny Lamb wocky/wocky-roster.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) commit f7850d4ade0cc7dc413e423490f3565ef2ec0601 Author: Jonny Lamb Date: Thu Jul 2 17:23:09 2009 +0100 Add properties to roster GObject. Signed-off-by: Jonny Lamb wocky/wocky-roster.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) commit 140813d13cdd2cba63286efc5268926236803040 Author: Jonny Lamb Date: Thu Jul 2 17:22:17 2009 +0100 Add wocky-roster-test. Signed-off-by: Jonny Lamb .gitignore | 2 +- tests/Makefile.am | 8 +++++++- tests/wocky-roster-test.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) commit 37c0160e97b8e0f76f756cc45166d3aeb3841b2e Author: Jonny Lamb Date: Thu Jul 2 16:35:42 2009 +0100 Move recv_items into constructed. Signed-off-by: Jonny Lamb wocky/wocky-roster.c | 67 ++++++++++++++++++++++------------------------------ wocky/wocky-roster.h | 2 -- 2 files changed, 28 insertions(+), 41 deletions(-) commit b0de5c42576571b75fc6c406e0cb9b54e833c7f4 Author: Jonny Lamb Date: Thu Jul 2 16:29:33 2009 +0100 Initial WockyRoster implementation. Signed-off-by: Jonny Lamb wocky/Makefile.am | 4 +- wocky/wocky-roster.c | 248 +++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-roster.h | 69 ++++++++++++++ 3 files changed, 320 insertions(+), 1 deletion(-) commit c5c649f6c06178cd33c5404b0bed9603f6404a85 Author: Jonny Lamb Date: Thu Jul 2 14:49:58 2009 +0100 wocky-namespaces: Add jabber:iq:roster. Signed-off-by: Jonny Lamb wocky/wocky-namespaces.h | 3 +++ 1 file changed, 3 insertions(+) commit 966a248237c6c3e419201f0548746e2592ae26b0 Author: Jonny Lamb Date: Wed Jul 1 17:55:50 2009 +0100 Add barebones of WockyContact class. Signed-off-by: Jonny Lamb wocky/Makefile.am | 4 +- wocky/wocky-contact.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-contact.h | 72 ++++++++++++++++++++ wocky/wocky-debug.c | 1 + wocky/wocky-debug.h | 1 + 5 files changed, 261 insertions(+), 1 deletion(-) commit 3173cb6db6e21367e46fe0ee5af088360adadf54 Author: Guillaume Desmottes Date: Thu Aug 13 10:22:49 2009 +0100 stream_error_abort: ignore non stream errors wocky_xmpp_stanza_to_gerror is not limited to stream errors anymore. Ignore the others error as this function is supposed to detect stream errors only. Code could be improved to gain use of the new functionnality of wocky_xmpp_stanza_to_gerror, I added a FIXME about that. wocky/wocky-connector.c | 9 +++++++++ 1 file changed, 9 insertions(+) commit ecb54ef69ced7750dc3b1eb0936adc909146b34a Author: Guillaume Desmottes Date: Wed Aug 12 17:10:23 2009 +0100 stream_error_to_gerror: use wocky_xmpp_stream_error_from_node wocky/wocky-xmpp-stanza.c | 51 ++--------------------------------------------- 1 file changed, 2 insertions(+), 49 deletions(-) commit 9db920ee913f7871011eaf5928b6065bea9bd252 Author: Guillaume Desmottes Date: Wed Aug 12 17:09:59 2009 +0100 wocky-xmpp-error: add wocky_xmpp_stream_error_from_node wocky/wocky-xmpp-error.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-error.h | 2 ++ 2 files changed, 56 insertions(+) commit 6ef54efa1f0ca88b214269a80cbdab6ec71def49 Author: Guillaume Desmottes Date: Wed Aug 12 16:54:52 2009 +0100 move stream errors definition to wocky-xmpp-stanza.h tests/wocky-connector-test.c | 1 + tests/wocky-porter-test.c | 1 + wocky/wocky-connector.c | 1 + wocky/wocky-xmpp-error.c | 18 ++++++++++++++++++ wocky/wocky-xmpp-error.h | 37 +++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-stanza.c | 18 ------------------ wocky/wocky-xmpp-stanza.h | 37 ------------------------------------- 7 files changed, 58 insertions(+), 55 deletions(-) commit 889a445498ee8c96e545008d12d997f2227b2155 Author: Guillaume Desmottes Date: Wed Aug 12 16:51:12 2009 +0100 wocky-xmpp-error: fix style wocky/wocky-xmpp-error.c | 4 ++-- wocky/wocky-xmpp-error.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) commit 2fa6f6f43ecd53b75bebda9f617e008015d7ec95 Author: Guillaume Desmottes Date: Wed Aug 12 16:47:18 2009 +0100 rename XMPP_ERROR_* to WOCKY_XMPP_ERROR_* tests/wocky-xmpp-stanza-test.c | 2 +- wocky/wocky-xmpp-error.c | 31 +++++++++++----------- wocky/wocky-xmpp-error.h | 58 +++++++++++++++++++++--------------------- wocky/wocky-xmpp-stanza.c | 4 +-- 4 files changed, 48 insertions(+), 47 deletions(-) commit 28ee115f4d09d0f1d357dd45f039e21adb8086f2 Author: Guillaume Desmottes Date: Wed Aug 12 16:40:38 2009 +0100 wocky-xmpp-stanza-test: add test_xmpp_error_to_gerror Based on test_message_get_xmpp_error from Gibber tests suite. tests/wocky-xmpp-stanza-test.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) commit b1d4161c28db9b4b7ea7d6a235299472616c6031 Author: Guillaume Desmottes Date: Wed Aug 12 16:37:13 2009 +0100 merge functionnality of wocky_message_get_xmpp_error to wocky_xmpp_stanza_to_gerror wocky/wocky-xmpp-error.c | 40 ---------------------------------------- wocky/wocky-xmpp-error.h | 1 - wocky/wocky-xmpp-stanza.c | 24 +++++++++++++++++++++++- 3 files changed, 23 insertions(+), 42 deletions(-) commit b7a549aba4706f85c12ff1f0268ac56db3774a15 Author: Guillaume Desmottes Date: Wed Aug 12 16:22:37 2009 +0100 import wocky-xmpp-error.[ch] from Gibber wocky/Makefile.am | 2 + wocky/wocky-xmpp-error.c | 481 +++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-error.h | 86 +++++++++ 3 files changed, 569 insertions(+) commit 1dacc6a83cc9930d0fe8b13e2d6816cd73c8f48b Author: Guillaume Desmottes Date: Wed Aug 12 15:15:52 2009 +0100 wocky-xmpp-stanza-test: improve test descriptions and rename test_to_gerror to test_stream_error_to_gerror tests/wocky-xmpp-stanza-test.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) commit 652da3fa35d72a9e8bfd5a5e4041b1cea59efa60 Author: Guillaume Desmottes Date: Wed Aug 12 15:11:19 2009 +0100 wocky_xmpp_stanza_to_gerror: factor out stream_error_to_gerror wocky/wocky-xmpp-stanza.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) commit 2e43ec8790a7d542c0d9493583e04fb6c8ac6412 Author: Vivek Dasmohapatra Date: Thu Aug 13 13:25:15 2009 +0100 Convert attr ns prefix system to hash tables: add init/deinit functions. Also added a comment explaining the auto-generation of prefixes. wocky/wocky-xmpp-node.c | 136 +++++++++++++++++++++++++++++++++++------------- wocky/wocky-xmpp-node.h | 3 ++ wocky/wocky.c | 3 ++ 3 files changed, 105 insertions(+), 37 deletions(-) commit 6d7d0f0863154c2545f43369ebe4c2f7f0e8a906 Author: Vivek Dasmohapatra Date: Wed Aug 12 18:07:19 2009 +0100 g_slice_new0 instead of g_new0 in ns_prefix_new. wocky/wocky-xmpp-node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 4b67c1a0300f9ca71e15c26689b2e377f7d26be6 Author: Vivek Dasmohapatra Date: Wed Aug 12 18:06:44 2009 +0100 Missing function return type. tests/wocky-xmpp-node-test.c | 1 + 1 file changed, 1 insertion(+) commit bed46ad061870307443b2b9bcc452a7fcefcc79d Author: Vivek Dasmohapatra Date: Wed Aug 12 17:05:01 2009 +0100 Adapt tests to new API. tests/wocky-xmpp-node-test.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit 808f44a807c1b1fe05d98a4adc5ac3453f1d10ff Author: Vivek Dasmohapatra Date: Wed Aug 12 17:04:51 2009 +0100 Split get_prefix functions into from_quark and from_urn versions. Move common functionality into static helper functions to tidy up code. Add comments describing what each stage does. wocky/wocky-xmpp-node.c | 87 ++++++++++++++++++++++++++++++++++--------------- wocky/wocky-xmpp-node.h | 6 ++-- 2 files changed, 63 insertions(+), 30 deletions(-) commit e456e3cfef20403446bfce9838d3ace2e74b246a Author: Vivek Dasmohapatra Date: Wed Aug 12 15:22:46 2009 +0100 Whitespace cleanup. wocky/wocky-connector.c | 1 - 1 file changed, 1 deletion(-) commit 3f863c7918ffc18e868329b6250a29504b6a87d0 Author: Vivek Dasmohapatra Date: Wed Aug 12 13:05:59 2009 +0100 Stray debugging #include removed. wocky/wocky-xmpp-node.c | 1 - 1 file changed, 1 deletion(-) commit bc93f3f07cc33165c7709a7a212e8bf835ffbbcb Author: Vivek Dasmohapatra Date: Wed Aug 12 13:05:40 2009 +0100 Improve test coverage of new namespaced attribute support. tests/wocky-xmpp-node-test.c | 53 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) commit 3306f6f71dd534c8622e27e79eb33cff385dac49 Author: Vivek Dasmohapatra Date: Tue Aug 11 19:31:11 2009 +0100 Adjust the API so that attribute namespace prefixes are automatically assigned. Users can override attribute namespace prefixes if they so desire, and there is a built-in list of pre-assigned prefixes. tests/wocky-xmpp-node-test.c | 18 ++++--- tests/wocky-xmpp-readwrite-test.c | 2 +- wocky/wocky-sasl-auth.c | 2 +- wocky/wocky-xmpp-node.c | 101 +++++++++++++++++++++++++++++++++++--- wocky/wocky-xmpp-node.h | 10 ++-- wocky/wocky-xmpp-reader.c | 10 +++- 6 files changed, 124 insertions(+), 19 deletions(-) commit a1cbb8be19ccd619cff7cd176b1c48f883f539aa Author: Vivek Dasmohapatra Date: Thu Jul 30 14:30:56 2009 +0100 Test namespaced attributes (creating, changing and readwrite tests) tests/wocky-xmpp-node-test.c | 102 ++++++++++++++++++++++++++++++++++++++ tests/wocky-xmpp-readwrite-test.c | 28 +++++++++++ 2 files changed, 130 insertions(+) commit 313ce82cdc630ce71a6ddc83c2e6935abf7150fb Author: Vivek Dasmohapatra Date: Thu Jul 30 12:35:04 2009 +0100 Make Google JID Domain Discovery always-on. tests/wocky-connector-test.c | 17 ----------------- wocky/wocky-connector.c | 17 ----------------- wocky/wocky-sasl-auth.c | 21 +++------------------ 3 files changed, 3 insertions(+), 52 deletions(-) commit 0d24e00092482693993dad0e7923ff34eee928e7 Author: Vivek Dasmohapatra Date: Thu Jul 30 11:52:05 2009 +0100 Stray // comment removed. wocky/wocky-xmpp-node.c | 2 -- 1 file changed, 2 deletions(-) commit b2fdf23244935e8ff426f67d7a64778e06b7f85a Author: Vivek Dasmohapatra Date: Wed Jul 29 19:37:59 2009 +0100 Test new google JID domain discovery quirk support. tests/wocky-connector-test.c | 42 +++++++++++++++++++++++++++++++++++++ tests/wocky-test-connector-server.h | 1 - tests/wocky-test-sasl-auth-server.c | 24 +++++++++++++++++++++ tests/wocky-test-sasl-auth-server.h | 2 ++ 4 files changed, 68 insertions(+), 1 deletion(-) commit 74e93063095a99bd2b7946be0cb167ff4a1b928a Author: Vivek Dasmohapatra Date: Wed Jul 29 19:37:05 2009 +0100 Expose google-domain-discovery sasl feature through a wocky-connector property. wocky/wocky-connector.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) commit fed88a33ef1550e667164b78f9cf473075995504 Author: Vivek Dasmohapatra Date: Tue Jul 28 17:27:52 2009 +0100 Google JID domain-discovery extension, controlled by a property. wocky/wocky-namespaces.h | 3 +++ wocky/wocky-sasl-auth.c | 22 +++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) commit d78e7101e154613c5904fdf1b20ed32fa57068f7 Author: Vivek Dasmohapatra Date: Tue Jul 28 17:04:37 2009 +0100 Fix (I think) namespaced attribute handling in wocky-xmpp-* There was no way to specify the PREFIX in a xmlns:PREFIX="URI" PREFIX:tag="value" node attribute: the existing code just duplicated the tag. wocky/wocky-xmpp-node.c | 30 +++++++++++++++++++++--------- wocky/wocky-xmpp-node.h | 6 +++--- wocky/wocky-xmpp-reader.c | 8 +++++--- wocky/wocky-xmpp-writer.c | 5 +++-- 4 files changed, 32 insertions(+), 17 deletions(-) commit 3204163c0d770aedfcb222588aea868b45b43c97 Author: Vivek Dasmohapatra Date: Wed Aug 12 17:39:53 2009 +0100 Async result should have ...connect_finish as the finish func for XEP77_SIGNUP. wocky/wocky-connector.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) commit 4aa07be0eb70d58ee265f4e0f197b98a07bbb448 Merge: ba584a1 f5e4e4f Author: Vivek Dasmohapatra Date: Wed Aug 12 15:05:11 2009 +0100 Merge branch 'master' of git+ssh://git.collabora.co.uk/git/wocky commit ba584a1241063fb0e3a57de4b83a60611ad041eb Author: Vivek Dasmohapatra Date: Wed Aug 12 14:51:24 2009 +0100 Comment explaining WockyConnectorXEP77Op enum and usage in priv struct. wocky/wocky-connector.c | 5 +++++ 1 file changed, 5 insertions(+) commit 0cf7b439ce469df9218affc78e23ce6dc86aa3a9 Author: Vivek Dasmohapatra Date: Wed Aug 12 14:46:59 2009 +0100 Record the correct finish function in the async result when registering. wocky/wocky-connector.c | 2 ++ 1 file changed, 2 insertions(+) commit b27393f1892ae27e3c033aff6fc3ab31010d5f35 Author: Vivek Dasmohapatra Date: Wed Aug 12 14:35:22 2009 +0100 Amended XEP77/cancel comment. Will email standards list for clarification. Code as written worka when cancelling an account on a real (ejabberd) server. wocky/wocky-connector.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit a2f855841e72f3d9ef389696e47ead6eff7cd97d Author: Vivek Dasmohapatra Date: Wed Aug 12 14:31:13 2009 +0100 Add DEBUG statements to track path through connector code. wocky/wocky-connector.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) commit 439157469da2b6bfe44fbaad722750f7e0e02002 Author: Vivek Dasmohapatra Date: Tue Aug 11 14:46:42 2009 +0100 Ignore individual example programmes explicitly (ie not with globbing) .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 37bef919cf4e11bfc750ba1af6c6294a715b0182 Author: Vivek Dasmohapatra Date: Tue Aug 11 14:45:07 2009 +0100 Whitespace cleanup. wocky/wocky-namespaces.h | 2 -- 1 file changed, 2 deletions(-) commit b56f2fad002cb673425694a45ccf3303f7c43bd8 Author: Vivek Dasmohapatra Date: Tue Aug 11 14:40:03 2009 +0100 Add prop set/get test for new property. tests/wocky-connector-test.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit 7a174fe38e0f0b52c7d60defa8da556304f4b43d Author: Vivek Dasmohapatra Date: Tue Aug 11 14:39:44 2009 +0100 Eliminate mem leak in dummy resolver when the server has to abort for a test. tests/test-resolver.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 6ff06cff74afee70d9a5defc0e41ae4d6f86d371 Author: Vivek Dasmohapatra Date: Mon Aug 10 20:38:48 2009 +0100 XEP 0077 Registration/Cancellation tests. tests/wocky-connector-test.c | 353 ++++++++++++++++++++++++++++++++++-- tests/wocky-test-connector-server.c | 265 ++++++++++++++++++++++++++- tests/wocky-test-connector-server.h | 19 ++ 3 files changed, 608 insertions(+), 29 deletions(-) commit c7645384313de5b6778a031c0d393d0bf2cc5ba6 Author: Vivek Dasmohapatra Date: Mon Aug 10 20:38:10 2009 +0100 Add some DEBUG (); renamed namespace constant according to existing pattern. wocky/wocky-connector.c | 18 +++++++++++++----- wocky/wocky-namespaces.h | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) commit 76f18c05ef5eb7532c10eb9414e0dfdf0e830588 Author: Vivek Dasmohapatra Date: Mon Aug 10 20:36:44 2009 +0100 Ignore the test-generated sasl DB file. .gitignore | 1 + 1 file changed, 1 insertion(+) commit 93046cc5bf62143763130623bb4f1f0cdbcecce0 Author: Vivek Dasmohapatra Date: Thu Aug 6 12:27:45 2009 +0100 Typo fixed, leaks in xep77_signup_send fixed (from cassidy). wocky/wocky-connector.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) commit b1b2bebf688d407cd942c06a6c739d389d51ef35 Author: Vivek Dasmohapatra Date: Wed Aug 5 16:56:04 2009 +0100 Make email a settable parameter in the connector instead of a mandatory param. examples/register.c | 5 +++-- wocky/wocky-connector.c | 37 ++++++++++++++++++++++++++++++++----- wocky/wocky-connector.h | 7 ++++++- 3 files changed, 41 insertions(+), 8 deletions(-) commit b3a50f94445aaf504d45d04294aed7fbf2cbbbed Author: Vivek Dasmohapatra Date: Wed Aug 5 12:12:19 2009 +0100 Don't care about contents, presence or absence of "instructions" tag for now. XEP0077 implies that the "instructions" tag must always be present in the reply to the jabber:iq:register iq get request, but unless we are supporting redirection-based registration (which we are not, at present) we don't care about its presence: We only care about tags that are _not_ "instructions". wocky/wocky-connector.c | 8 -------- 1 file changed, 8 deletions(-) commit 4b473dfbeb39f96702db35148e3e473ba191a09b Author: Vivek Dasmohapatra Date: Tue Aug 4 19:07:27 2009 +0100 Ignore the example binaries for vcs purposes. .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit c51cc014131ccf6018debbf4fe42c23b466f1d2b Author: Vivek Dasmohapatra Date: Tue Aug 4 19:05:51 2009 +0100 Example registration and unregistration binaries. examples/Makefile.am | 15 +++++++++- examples/register.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++ examples/unregister.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+), 1 deletion(-) commit 6ab62ee512532ff31bc387bed87a1a6c5744be3d Author: Vivek Dasmohapatra Date: Tue Aug 4 19:05:26 2009 +0100 Implement XEP0077 In-Band Registration/Cancellation wocky/wocky-connector.c | 583 ++++++++++++++++++++++++++++++++++++++++++++++- wocky/wocky-connector.h | 22 ++ wocky/wocky-namespaces.h | 5 + 3 files changed, 598 insertions(+), 12 deletions(-) commit f5e4e4f4ace88a66e56fae13dd2993c15fd77275 Author: Guillaume Desmottes Date: Wed Jul 22 12:06:06 2009 +0100 test wocky_xmpp_node_append_content_n tests/wocky-xmpp-node-test.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) commit d8d3beaa745297ea45e24708138c4235bca89ba2 Author: Jonny Lamb Date: Tue Jul 14 14:15:37 2009 +0100 The "from" attribute is also not required for a reply IQ to be built. Signed-off-by: Jonny Lamb wocky/wocky-xmpp-stanza.c | 1 - 1 file changed, 1 deletion(-) commit 0c320e2d6fa1106276fdbc4394156ef686d889b0 Author: Guillaume Desmottes Date: Wed Aug 5 17:27:05 2009 +0100 add test_close_force_after_close_sent tests/wocky-porter-test.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) commit 9f39944bc339634d36c6695c730113bdeed43d35 Author: Guillaume Desmottes Date: Wed Aug 5 17:23:53 2009 +0100 wocky_porter_force_close_async: check if the receive_cancellable is NULL before raising the CLOSED error local_closed could have been set to TRUE because our close stanza has been set but we were still waiting for the close from the peer. In such case, we shouldn't raise an error and allow user to call force_close. wocky/wocky-porter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 2a35a4062da27417b4bf22d640d6621eee4d6b90 Author: Guillaume Desmottes Date: Wed Jul 29 12:27:30 2009 +0100 test_close_force: test that the closing signal is not fired more than once tests/wocky-porter-test.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) commit 87cfff5986e1329eca880a637e1c19f8e55a5fe3 Author: Guillaume Desmottes Date: Wed Jul 29 12:27:13 2009 +0100 wocky_porter_force_close_async: don't fire the closing signal twice wocky/wocky-porter.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) commit e43eb2ab2fbadfeca5adeb3c172b0412e7344f30 Author: Guillaume Desmottes Date: Wed Jul 29 12:22:15 2009 +0100 porter: use WOCKY_PORTER_ERROR_CLOSING when completing a close operation because of a forced close tests/wocky-porter-test.c | 2 +- wocky/wocky-porter.c | 2 +- wocky/wocky-porter.h | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) commit dc1d27b9c2e7394f3b74d31941ae54acf4be09f6 Author: Guillaume Desmottes Date: Wed Jul 29 12:18:44 2009 +0100 wocky_porter_force_close_async: set the right error domain when raising G_IO_ERROR_PENDING wocky/wocky-porter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit b2a8ae6c49a37eb317d0639b5608d030e125db5b Author: Vivek Dasmohapatra Date: Tue Aug 4 15:14:21 2009 +0100 Default xmpp-port property value should be 0, not 5222. This allows us to distinguish between explicit user parameters (which imply SRV records should be ignored) and unspecified values (which mean "do the right thing"). wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 45699bd0090984bf0dfd5de617c873c2de4cb197 Author: Vivek Dasmohapatra Date: Tue Aug 4 15:14:21 2009 +0100 Default xmpp-port property value should be 0, not 5222. This allows us to distinguish between explicit user parameters (which imply SRV records should be ignored) and unspecified values (which mean "so the right thing"). wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 3a705cc906e154a3e77fabd55c16f42ae11191a6 Author: Guillaume Desmottes Date: Tue Aug 4 14:02:19 2009 +0100 use test_init and test_deinit in tests so memory is properly freed and valgrind is happy tests/Makefile.am | 11 +++++++++++ tests/wocky-connector-test.c | 10 ++++++---- tests/wocky-porter-test.c | 10 ++++++---- tests/wocky-test-sasl-auth.c | 11 ++++++----- tests/wocky-xmpp-connection-test.c | 10 ++++++---- tests/wocky-xmpp-node-test.c | 11 +++++++---- tests/wocky-xmpp-reader-test.c | 12 ++++++++---- tests/wocky-xmpp-readwrite-test.c | 11 +++++++---- tests/wocky-xmpp-stanza-test.c | 13 ++++++++----- 9 files changed, 65 insertions(+), 34 deletions(-) commit fd61e2ac48113b5eb5b9f60f1ef83564be7788a2 Author: Guillaume Desmottes Date: Tue Aug 4 14:01:28 2009 +0100 add test_init and test_deinit helpers tests/wocky-test-helper.c | 17 +++++++++++++++++ tests/wocky-test-helper.h | 5 +++++ 2 files changed, 22 insertions(+) commit ac511b43ae9f37ef33fc0fe5fdf7029c8e354bce Author: Guillaume Desmottes Date: Tue Jul 28 11:54:13 2009 +0100 add wocky_init and wocky_deinit wocky/Makefile.am | 2 ++ wocky/wocky.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky.h | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) commit 50201f619f1b75d8df9bec106d5e91fe22b1f91b Author: Guillaume Desmottes Date: Tue Aug 4 12:30:25 2009 +0100 connector: 'legacy' and 'old-ssl' properties shouldn't be construct only wocky/wocky-connector.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 5dd031fd5f4408e39d232e35317fdd8d3d423b8c Author: Vivek Dasmohapatra Date: Wed Jul 29 18:06:28 2009 +0100 Use local wocky_tls_* instead of g_tls_* and gio instead of gnio. examples/connect.c | 10 +++++----- tests/wocky-test-connector-server.c | 19 ++++++++++--------- tests/wocky-test-connector-server.h | 2 +- tests/wocky-test-sasl-auth-server.c | 2 +- tests/wocky-test-sasl-auth-server.h | 2 +- tests/wocky-test-stream.h | 2 +- wocky/wocky-connector.c | 12 ++++++------ wocky/wocky-connector.h | 2 +- wocky/wocky-sasl-auth.h | 2 +- wocky/wocky-xmpp-connection.h | 3 +-- 10 files changed, 28 insertions(+), 28 deletions(-) commit b9ee8409f1ecbd1c28b79754ca5b45ffdf4a5738 Author: Vivek Dasmohapatra Date: Wed Jul 29 18:05:42 2009 +0100 Remove gnio from package deps, add gnutls and gio. configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit fdad53d43d9c7edcd24db0c69108b689b7b05847 Author: Vivek Dasmohapatra Date: Wed Jul 29 18:04:51 2009 +0100 Add wocky-tls to build list, exclude from style check as it is a gnio import. wocky/Makefile.am | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) commit 18d70158bf35f91165adde167a8d7c20fe296d0e Author: Vivek Dasmohapatra Date: Wed Jul 29 18:03:22 2009 +0100 Check in copy of gnio TLS support + collabora patches to add server side TLS. wocky/wocky-tls.c | 1230 +++++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-tls.h | 68 +++ 2 files changed, 1298 insertions(+) commit 9d73236146ea2846a380f59090b249d6e7a35280 Author: Vivek Dasmohapatra Date: Fri Jul 31 17:44:25 2009 +0100 Bogus goto, should have just been a label. wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit fa985c20e28fd1aae2b9bfd49550cbebbee177ae Author: Vivek Dasmohapatra Date: Fri Jul 31 17:39:04 2009 +0100 Stanza memory leaks on error bailouts. wocky/wocky-connector.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) commit 3213cfa55bc654779602866f991efdd2a1fc3730 Author: Vivek Dasmohapatra Date: Thu Jul 30 11:29:29 2009 +0100 Bogus if condition removed. tests/wocky-xmpp-node-test.c | 1 - 1 file changed, 1 deletion(-) commit 79f3f6482a6594c6175401909698d2fad1c649ce Author: Vivek Dasmohapatra Date: Wed Jul 29 16:36:06 2009 +0100 Minor (english) syntax changes in doc string. wocky/wocky-xmpp-node.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit d22b1d9004f622ba58f4f71352631a4587ea7e86 Author: Vivek Dasmohapatra Date: Wed Jul 29 16:32:09 2009 +0100 Test the wocky_xmpp_node_unpack_error function. tests/wocky-xmpp-node-test.c | 184 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) commit 54f204acb753f3081c0082382c3522d30e7fc165 Author: Vivek Dasmohapatra Date: Wed Jul 29 16:31:16 2009 +0100 Extract the stanza error type. Make sure unset original stanza => NULL result. wocky/wocky-xmpp-node.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) commit 34f6d59f1f87794e67ff3837d06edf9d92e62df0 Author: Vivek Dasmohapatra Date: Tue Jul 28 18:08:51 2009 +0100 Document wocky_xmpp_node_unpack_error. wocky/wocky-xmpp-node.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) commit f28d0fb657f9371b59e41bcc064d06e85b4abe1a Author: Vivek Dasmohapatra Date: Tue Jul 28 17:49:51 2009 +0100 Session ID property not writable anymore. wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit aa7ab0ce93f7219e51a9e063251f174b6dc77eca Author: Vivek Dasmohapatra Date: Tue Jul 28 17:49:19 2009 +0100 Cleanup some old DEBUG we don't need any more. tests/wocky-test-connector-server.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) commit 6ba3953607660c70aa4ddaadb8b1fc742c8a362e Author: Vivek Dasmohapatra Date: Tue Jul 28 17:39:35 2009 +0100 Memory leak in example connect.c program. examples/connect.c | 1 + 1 file changed, 1 insertion(+) commit 327326a9e1d0cf60e7a1d8d1a51daacfae860756 Author: Vivek Dasmohapatra Date: Tue Jul 28 12:05:11 2009 +0100 Duplicate applicable XMPP+TLS tests for the XMPP+SSL code path(s). tests/wocky-connector-test.c | 334 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 334 insertions(+) commit 0a9d76b1be294fc26ac097f59935c45cdf0c923a Author: Vivek Dasmohapatra Date: Tue Jul 28 12:04:07 2009 +0100 Tweak the timing of some of the server-death tests (also, sleep not needed) tests/wocky-test-connector-server.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) commit 266f6c74fd2d258c6bdda4e3ea08ff50e080abdb Author: Vivek Dasmohapatra Date: Tue Jul 28 11:32:40 2009 +0100 Removed some stray empty comments + a couple of tests were misnamed tests/wocky-connector-test.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) commit 245cb4099a141cf7dd084628281706a13f671108 Author: Vivek Dasmohapatra Date: Mon Jul 27 20:50:03 2009 +0100 TLS_REQUIRED/PLAINTEXT_OK vs TRUE/FALSE. More old-SSL tests. tests/wocky-connector-test.c | 538 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 426 insertions(+), 112 deletions(-) commit ceda37cbc1092ed8d28d656876b2c029042f2c10 Author: Vivek Dasmohapatra Date: Mon Jul 27 19:56:57 2009 +0100 Fix comment describing test-spec structure. Use PLAIN/DIGEST vs TRUE/FALSE. tests/wocky-connector-test.c | 114 +++++++++++++++++++++---------------------- 1 file changed, 57 insertions(+), 57 deletions(-) commit d4604ea3b0ad904eff471639e72caafe6fda0413 Author: Vivek Dasmohapatra Date: Mon Jul 27 19:42:26 2009 +0100 First batch of old-style SSL tests tests/wocky-connector-test.c | 205 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 203 insertions(+), 2 deletions(-) commit c33e6c778fc5dfa2ca8d7c2426a5d26e9fcd5636 Author: Vivek Dasmohapatra Date: Mon Jul 27 19:39:52 2009 +0100 Implement old-style SSL in test XMPP server. tests/wocky-test-connector-server.c | 51 +++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 5 deletions(-) commit 54582866d61c9a8ea7900ff8b7ab87fc546ca8ff Author: Vivek Dasmohapatra Date: Mon Jul 27 19:39:02 2009 +0100 Old style SSL (ie immediately on TCP connection established) wocky/wocky-connector.c | 75 +++++++++++++++++++++++++++++++++++++++++++------ wocky/wocky-connector.h | 1 + 2 files changed, 67 insertions(+), 9 deletions(-) commit 865cb935844292e9d7c1207dc0abd3238749bfbb Author: Vivek Dasmohapatra Date: Mon Jul 27 12:59:28 2009 +0100 Update flow-control description comment at start of wocky-connector.c wocky/wocky-connector.c | 58 +++++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 23 deletions(-) commit 3d765ebdd873a390fde19b1c13e6d903c8e11ba5 Author: Vivek Dasmohapatra Date: Fri Jul 24 19:46:47 2009 +0100 Improve test coverage in corner cases. tests/wocky-connector-test.c | 66 +++++++++++++++++++++++++++++++++++++ tests/wocky-test-connector-server.c | 20 +++++++++++ tests/wocky-test-connector-server.h | 16 +++++---- 3 files changed, 95 insertions(+), 7 deletions(-) commit c585552ad207a2194d306d9b9211859d535e3436 Author: Vivek Dasmohapatra Date: Fri Jul 24 18:45:24 2009 +0100 Memory leak: free old session id string when the session re-initialises wocky/wocky-connector.c | 1 + 1 file changed, 1 insertion(+) commit 1741f0b8e19e0234bd72fba3ee04cfc4fa4c00f1 Author: Vivek Dasmohapatra Date: Fri Jul 24 16:51:35 2009 +0100 Split connector-problems into smaller logical groups Problem flags sometimes need to be ORable together, but we had exceeded 32 of them, so have split the problems into logical groups to prevent problems as the enm size might be exceeded on some platforms otherwise, aiui. tests/wocky-connector-test.c | 230 ++++++++++++++++++++---------------- tests/wocky-test-connector-server.c | 126 ++++++++++---------- tests/wocky-test-connector-server.h | 108 +++++++++++------ 3 files changed, 260 insertions(+), 204 deletions(-) commit fb7d680d68048ca3f0db4c58d01d7156d7140760 Author: Vivek Dasmohapatra Date: Thu Jul 23 20:00:05 2009 +0100 Typo in comment. wocky/wocky-sasl-auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit d1620c44db2ba34a369de12bdbe1fdc445d569e0 Author: Vivek Dasmohapatra Date: Thu Jul 23 19:49:27 2009 +0100 Old style jabber-auth tests. tests/wocky-connector-test.c | 148 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 147 insertions(+), 1 deletion(-) commit 86acf37b4089ef1f472bb929fdf19daa2ca501ba Author: Vivek Dasmohapatra Date: Thu Jul 23 19:41:55 2009 +0100 Miscellaneous mem leak/uninitialised var/debug fixes session_id free()d in cleanup. DEBUG("") messages so we can track progress assignment + declaration for variable declared in switch block wasn't working, assign separately from declaration. Make sure jabber auth stanzas have IDs wocky/wocky-connector.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) commit f9cac60bdb9f0dfc6d4f7337a275fd058f60efe1 Author: Vivek Dasmohapatra Date: Thu Jul 23 19:32:33 2009 +0100 Implement old-style jabber auth in the test server. tests/wocky-test-connector-server.c | 267 ++++++++++++++++++++++++++++++++++-- tests/wocky-test-connector-server.h | 8 ++ wocky/wocky-namespaces.h | 3 + 3 files changed, 263 insertions(+), 15 deletions(-) commit 27e2f0fc175a73661d6bdb603ea9b3e5bac987ec Author: Vivek Dasmohapatra Date: Wed Jul 22 12:18:57 2009 +0100 Comment explaining why we proceed to "establish_session" after a successful old-style jabber auth exchange. wocky/wocky-connector.c | 5 +++++ 1 file changed, 5 insertions(+) commit 51b0ebb58d27dd6fb7a011a851b2b5ecfce6fb93 Author: Vivek Dasmohapatra Date: Tue Jul 21 19:25:38 2009 +0100 Old-style jabber auth implementation. wocky/wocky-connector.c | 343 ++++++++++++++++++++++++++++++++++++++++++++++- wocky/wocky-connector.h | 5 + wocky/wocky-namespaces.h | 4 + 3 files changed, 348 insertions(+), 4 deletions(-) commit cb635f6af447c0444d5832cb58a81e9e57ba7afe Author: Vivek Dasmohapatra Date: Tue Jul 21 19:24:53 2009 +0100 Util method to extract stanza error details wocky/wocky-xmpp-node.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-node.h | 8 ++++++++ 2 files changed, 61 insertions(+) commit 8ce7c458e0b6a2ef5f568a6e10a0e08ac6c866ae Author: Vivek Dasmohapatra Date: Tue Jul 21 19:24:18 2009 +0100 Comment typos. wocky/wocky-sasl-auth.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 3d415b6806790622086d3df10b562c484af35230 Author: Vivek Dasmohapatra Date: Tue Jul 21 19:15:44 2009 +0100 Add ID paramater to stream open methods (needed for server stream open) examples/connect.c | 6 +++--- tests/wocky-test-connector-server.c | 2 +- tests/wocky-test-helper.c | 2 +- tests/wocky-test-sasl-auth-server.c | 4 ++-- tests/wocky-test-sasl-auth.c | 4 ++-- tests/wocky-xmpp-connection-test.c | 10 +++++----- tests/wocky-xmpp-readwrite-test.c | 2 +- wocky/wocky-xmpp-connection.c | 3 ++- wocky/wocky-xmpp-connection.h | 1 + wocky/wocky-xmpp-writer.c | 10 ++++++++++ wocky/wocky-xmpp-writer.h | 1 + 11 files changed, 29 insertions(+), 16 deletions(-) commit 75fc9f5fc79dad7a325d2e9bab366879bdf5389d Author: Vivek Dasmohapatra Date: Mon Jul 20 16:02:54 2009 +0100 Store and return the XMPP Stream Session ID The XMPP Session ID from the server stream open is needed for some client actions (including old-style Jabber auth): Make it a standard connector return item. examples/connect.c | 17 ++++++++++++---- tests/wocky-connector-test.c | 27 +++++++++++++++++++++---- tests/wocky-test-connector-server.c | 2 +- tests/wocky-test-helper.c | 2 +- tests/wocky-test-sasl-auth-server.c | 4 ++-- tests/wocky-test-sasl-auth.c | 4 ++-- tests/wocky-xmpp-connection-test.c | 15 ++++++++------ wocky/wocky-connector.c | 40 +++++++++++++++++++++++++++++++++---- wocky/wocky-connector.h | 3 ++- wocky/wocky-xmpp-connection.c | 8 +++++++- wocky/wocky-xmpp-connection.h | 1 + wocky/wocky-xmpp-reader.c | 29 ++++++++++++++++++++++----- 12 files changed, 121 insertions(+), 31 deletions(-) commit 3d2b6bb99615703fd9ccf6daa086396db3468040 Author: Guillaume Desmottes Date: Wed Jul 29 12:10:45 2009 +0100 stanza_received_cb: unref ourself at the end of the function It's not safe to unref ourself and then use the priv pointer wocky/wocky-porter.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 3569d70d19a50e49379c0c112c5ab31db0d13ed7 Author: Guillaume Desmottes Date: Wed Jul 29 12:00:46 2009 +0100 wocky_porter_force_close_async: add a comment explaining why it's safe to release the ref at this stage wocky/wocky-porter.c | 2 ++ 1 file changed, 2 insertions(+) commit 9df6395ca9d6660c660878849458ae8b0da91b78 Author: Guillaume Desmottes Date: Wed Jul 22 16:41:48 2009 +0100 wocky_porter_force_close_async: unref ourself once the async result has been created wocky/wocky-porter.c | 2 ++ 1 file changed, 2 insertions(+) commit d473cecb3164ebac975e491e0050d4dd67a68c20 Author: Guillaume Desmottes Date: Wed Jul 22 16:41:04 2009 +0100 connection_force_close_cb: unref the receive_cancellable once the connection has been closed wocky/wocky-porter.c | 6 ++++++ 1 file changed, 6 insertions(+) commit 18e690252a2fcc5090504ecdf05787a558077cfe Author: Guillaume Desmottes Date: Wed Jul 22 16:07:08 2009 +0100 wocky-porter-test: add test_close_force_after_error tests/wocky-porter-test.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) commit 0b6dd9bf0b3cfb7dc3f195506e2ef9e86171e97d Author: Guillaume Desmottes Date: Wed Jul 22 16:06:29 2009 +0100 test_close_force: we have to wait for 3 events, not 2 Three callbacks have to called: - test_close_force_stanza_sent_cb - test_close_force_closed_cb - test_close_force_force_closed_cb tests/wocky-porter-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 8595ff413485eb81824817b7c52ac21e886d4584 Author: Guillaume Desmottes Date: Wed Jul 22 15:51:55 2009 +0100 wocky_porter_force_close_async: close XMPP connection right away if remote is already closed wocky/wocky-porter.c | 9 +++++++++ 1 file changed, 9 insertions(+) commit c721b6614add94cb84af4987c1a9848a7330377c Author: Guillaume Desmottes Date: Wed Jul 22 15:23:21 2009 +0100 wocky-porter-test: test to call force_close in the remote-error callback tests/wocky-porter-test.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) commit f51bffd3593d0911267ed419df706a4c08d9d192 Author: Guillaume Desmottes Date: Wed Jul 22 15:21:22 2009 +0100 stanza_received_cb: complete the force close operation, if any, if handling the stanza closed the remote connection wocky/wocky-porter.c | 8 ++++++++ 1 file changed, 8 insertions(+) commit ac8d9edd90936efe938f6f1998b3bbe90cf4f534 Author: Guillaume Desmottes Date: Wed Jul 22 14:58:43 2009 +0100 wocky_porter_close_async: raise an error if there is a force close operation running wocky/wocky-porter.c | 8 ++++++++ 1 file changed, 8 insertions(+) commit 79ebc9f3819541656d5239c09cff7968be626e63 Author: Guillaume Desmottes Date: Wed Jul 22 14:52:33 2009 +0100 wocky-porter: add some debug messages wocky/wocky-porter.c | 9 +++++++++ 1 file changed, 9 insertions(+) commit 1af25e22869aaa484972bff9cea51eea0bdffcfe Author: Guillaume Desmottes Date: Fri Jul 17 17:24:47 2009 +0100 test wocky_porter_force_close_async tests/wocky-porter-test.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) commit 1f68ed348b2a9a90fd803a2b74e1ecd52af4325c Author: Guillaume Desmottes Date: Mon Jul 20 14:08:58 2009 +0100 add wocky_porter_force_close_async wocky/wocky-porter.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++-- wocky/wocky-porter.h | 10 ++++ 2 files changed, 150 insertions(+), 4 deletions(-) commit 5569ae92c24541e8db3f525008c91d7789d85106 Author: Guillaume Desmottes Date: Mon Jul 20 12:31:10 2009 +0100 test wocky_xmpp_connection_force_close_async tests/wocky-xmpp-connection-test.c | 41 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) commit 8cff0b3f4ea9aaa4caa995a48754fc2817d34852 Author: Guillaume Desmottes Date: Mon Jul 20 12:31:03 2009 +0100 add wocky_xmpp_connection_force_close_async wocky/wocky-xmpp-connection.c | 64 +++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-connection.h | 10 +++++++ 2 files changed, 74 insertions(+) commit 637f9631cb50ed80656f9e479fa2670e1f8290f0 Author: Guillaume Desmottes Date: Wed Jul 22 12:07:14 2009 +0100 wocky-connector: xmpp_features_cb: don't leak our previous reference on priv->features if any wocky/wocky-connector.c | 2 ++ 1 file changed, 2 insertions(+) commit c16e59035a26f04d3d766fd6c19e7dec74dbc9a0 Author: Guillaume Desmottes Date: Tue Jul 21 13:54:28 2009 +0100 wocky-connector: use WockyXmppStreamError errors instead of a generic one tests/wocky-connector-test.c | 9 +++++---- wocky/wocky-connector.c | 3 +-- wocky/wocky-connector.h | 1 - 3 files changed, 6 insertions(+), 7 deletions(-) commit bee972c1d0b5036a25980f84d3f9f761f2937389 Author: Guillaume Desmottes Date: Tue Jul 21 13:44:50 2009 +0100 wocky-connector: factor out abort_connect wocky/wocky-connector.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) commit 369848c9f5191f78c7bf01628acae7dc1f50f0a6 Author: Guillaume Desmottes Date: Mon Jul 20 16:19:36 2009 +0100 wocky_xmpp_stanza_to_gerror: set a default message if there is no text node tests/wocky-xmpp-stanza-test.c | 4 ++-- wocky/wocky-xmpp-stanza.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) commit 316ef2a8e1443ac98c71d37801515b92ab505900 Author: Guillaume Desmottes Date: Mon Jul 20 11:59:15 2009 +0100 stanza_received_cb: don't wait for the next stanza if an error has been detected while handling the stanza wocky/wocky-porter.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) commit 200c886a7425aef4f09f138f56c5b8cc2cfeb0bd Author: Guillaume Desmottes Date: Fri Jul 17 14:28:45 2009 +0100 wocky-porter-test.c: add test_stream_error tests/wocky-porter-test.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) commit 74877dc48a787d5a58d9e2348a3b23786c906307 Author: Guillaume Desmottes Date: Fri Jul 17 14:29:39 2009 +0100 wocky-porter: fire the remote-error signal when a stream error is received wocky/wocky-porter.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) commit 0d32ff5a1af807728b26aaf868f601d057ca910d Author: Guillaume Desmottes Date: Fri Jul 17 14:29:24 2009 +0100 wocky-porter: factor out remote_connection_closed function wocky/wocky-porter.c | 90 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 34 deletions(-) commit 8776e27eb1d20cab9d8f96b34cb9689f9661735d Author: Guillaume Desmottes Date: Mon Jul 20 16:02:26 2009 +0100 wocky-connector: stream_error_abort: use wocky_xmpp_stanza_to_gerror instead of parsing the stanza manually wocky/wocky-connector.c | 42 +++++++++--------------------------------- 1 file changed, 9 insertions(+), 33 deletions(-) commit 57df600754da4db32b5a0728cc303266f252ba49 Author: Guillaume Desmottes Date: Mon Jul 20 15:57:24 2009 +0100 test wocky_xmpp_stanza_to_gerror tests/wocky-xmpp-stanza-test.c | 75 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) commit c250be88f8047e1132cfa6c03cbaea93eafeed7b Author: Guillaume Desmottes Date: Fri Jul 17 14:27:19 2009 +0100 add wocky_xmpp_stanza_to_gerror wocky/wocky-xmpp-stanza.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-stanza.h | 39 ++++++++++++++++++++++ 2 files changed, 122 insertions(+) commit 8f1148a0bf8d5635079c5e405adb22c720566d14 Author: Guillaume Desmottes Date: Mon Jul 20 10:24:37 2009 +0100 iq_sent_cb: remove useless \n in debug message wocky/wocky-porter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 76b4b99e7be774de2ede7b2c1d7313de9ab66ffe Author: Vivek Dasmohapatra Date: Thu Jul 16 18:43:04 2009 +0100 Removed extra / in resource string. tests/wocky-test-connector-server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit d2a2f185dbcc1d75ede4e774dce8661455289709 Author: Vivek Dasmohapatra Date: Thu Jul 16 17:06:37 2009 +0100 Elided unnecessary includes (added for stream error support, now elsewhere) wocky/wocky-xmpp-connection.c | 2 -- 1 file changed, 2 deletions(-) commit 5e5bdd67f38c0b1100257c82c84f285df87ba9de Author: Vivek Dasmohapatra Date: Thu Jul 16 17:06:01 2009 +0100 WockyConnectorPrivate->result was overwritten while potentially unsafe priv->result is not necessarily safe to access/write after a g_simple_async_result_complete has been called on it: If the result held the last ref to its parent connector object, the priv->result slot will have been freed by the time we return. wocky/wocky-connector.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) commit 74b2945aa8e9d0dc68f9aa95b0c6e2558f259abb Author: Vivek Dasmohapatra Date: Thu Jul 16 16:48:29 2009 +0100 Handle stream errors/disconnects in the sasl module. wocky/wocky-sasl-auth.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++- wocky/wocky-sasl-auth.h | 4 ++++ 2 files changed, 58 insertions(+), 1 deletion(-) commit 7516fb14e42095eaf0838ee1c8c3f939ed2e9786 Author: Vivek Dasmohapatra Date: Thu Jul 16 15:26:42 2009 +0100 Extend test coverage to a few more corner cases. tests/wocky-connector-test.c | 12 +++++++++ tests/wocky-test-connector-server.c | 49 +++++++++++++++++++++++-------------- tests/wocky-test-connector-server.h | 31 +++++++++++------------ 3 files changed, 59 insertions(+), 33 deletions(-) commit 37ee90aca57cfed830ad5bc6877d854bad1bace6 Author: Vivek Dasmohapatra Date: Wed Jul 15 19:43:31 2009 +0100 Ignore valgrind log files .gitignore | 1 + 1 file changed, 1 insertion(+) commit 87dd13fd7bf319a3f4e3f46f6233b309ef180f4a Author: Vivek Dasmohapatra Date: Thu Jul 16 13:42:40 2009 +0100 set the encoding on coverage html reports to UTF-8 (hardwired in lcov, so have to post-process) rules/lcov.mak | 2 ++ 1 file changed, 2 insertions(+) commit 0b0701d559d64086f972bfcf87f0c56757342444 Author: Vivek Dasmohapatra Date: Wed Jul 15 19:43:31 2009 +0100 Handle XMPP stream errors in the connector. Tests which trigger XMPP stream errors at the key stages of connection. tests/wocky-connector-test.c | 49 +++++++++++++++++++++++++++++++++- wocky/wocky-connector.c | 61 ++++++++++++++++++++++++++++++++++++++++++- wocky/wocky-connector.h | 1 + wocky/wocky-namespaces.h | 3 +++ wocky/wocky-xmpp-connection.c | 2 ++ 5 files changed, 114 insertions(+), 2 deletions(-) commit d1060b610d802dc789e862b711aded98682e3735 Author: Vivek Dasmohapatra Date: Wed Jul 15 19:30:37 2009 +0100 Implement XMPP errors at the various stages where we receive a stanza. tests/wocky-test-connector-server.c | 63 ++++++++++++++++++++++++++++++++----- tests/wocky-test-connector-server.h | 4 +++ 2 files changed, 60 insertions(+), 7 deletions(-) commit 6e6492cce4999ba85b02c16de023568f4e077676 Author: Guillaume Desmottes Date: Fri Jul 17 16:00:47 2009 +0100 wocky-porter-test: check that the 'closing' signal is fired tests/wocky-porter-test.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) commit 68db52832b9a2a16cc89034a75f282c762cd328c Author: Guillaume Desmottes Date: Fri Jul 17 16:00:30 2009 +0100 wocky-porter.c: fire closing signal when starting to close the Porter wocky/wocky-porter.c | 9 +++++++++ 1 file changed, 9 insertions(+) commit 7122422739e62e4354a392a9d22975b965c7c226 Author: Guillaume Desmottes Date: Wed Jul 15 18:07:35 2009 +0100 add test_cancel_iq_closing tests/wocky-porter-test.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) commit 777375f681cc91c86b5653bac7dbd5df97f1ab82 Author: Guillaume Desmottes Date: Wed Jul 15 18:05:39 2009 +0100 wocky_porter_send_iq_async: early return if the porter is closing There is no point to go further as the sending will fail any way. wocky/wocky-porter.c | 9 +++++++++ 1 file changed, 9 insertions(+) commit 636063aa2d431265a1db48f67c587b0e7484dc63 Author: Guillaume Desmottes Date: Wed Jul 15 18:04:47 2009 +0100 iq_sent_cb: display a debug message if sending failed wocky/wocky-porter.c | 1 + 1 file changed, 1 insertion(+) commit b761642931b2500d18af0c418abdd7037c9eb6e4 Author: Guillaume Desmottes Date: Wed Jul 15 18:03:01 2009 +0100 wocky-connector.c: establish_session: set priv->result to NULL before unreffing This avoid to try to unref it a second time if the result was owning the last ref on the connector. wocky/wocky-connector.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 46e93878e86290a2fc1ce3b703f8d8ccb201569c Author: Guillaume Desmottes Date: Wed Jul 15 12:51:29 2009 +0100 wocky-porter-test: add test_close_error tests/wocky-porter-test.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) commit 15f00e5c93a64f148a6910804ed20569fd81cf95 Author: Guillaume Desmottes Date: Wed Jul 15 12:50:11 2009 +0100 stanza_received_cb: complete the close operation if our sent has been sent and the connection is broken wocky/wocky-porter.c | 9 +++++++++ 1 file changed, 9 insertions(+) commit 5b63b6b7495923fa0925848856bd73934b7aa7c6 Author: Guillaume Desmottes Date: Wed Jul 15 12:48:28 2009 +0100 wocky_test_input_stream_set_read_error: if there is a pending read operation, complete it with an error tests/wocky-test-stream.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) commit f5a6b2438988af2ccfa93dd21ab27861de40c146 Author: Vivek Dasmohapatra Date: Wed Jul 15 11:26:58 2009 +0100 NULL out priv members after unref()ing them. wocky/wocky-connector.c | 4 ++++ 1 file changed, 4 insertions(+) commit ee645a6b78742638b860ca3824ba0246f034a069 Author: Vivek Dasmohapatra Date: Tue Jul 14 19:31:45 2009 +0100 Missing _unref()s of simple async results. wocky/wocky-connector.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) commit 015fdc8bdc6ee550f5d3b648aa90aa6bad0da86d Author: Vivek Dasmohapatra Date: Tue Jul 14 19:28:15 2009 +0100 priv->conn should never be set if we ask for a new one. wocky/wocky-connector.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) commit f318666d2e9b3b74a0639620330dd5e0aef21470 Author: Vivek Dasmohapatra Date: Tue Jul 14 19:25:08 2009 +0100 unref the channel, not the socket in the test. Use the JID slicing function from wocky_utils Amend the Invalid JID test sincw the behaviour of the JID slicer is different to naive @ slicing (arguably it needs to be less tolerant, but right now it isn't which means we fail in a different place with a different error than we did before). tests/wocky-connector-test.c | 10 +++++---- wocky/wocky-connector.c | 53 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 47 insertions(+), 16 deletions(-) commit d34f32ab570abb131e69316c58bd9a5a9c35da4e Author: Vivek Dasmohapatra Date: Tue Jul 14 17:37:59 2009 +0100 Break out long if condition. tests/wocky-connector-test.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) commit 8853540bce12d438b5fe440dbdcf160ed5409813 Author: Vivek Dasmohapatra Date: Tue Jul 14 17:33:11 2009 +0100 Minor leak in the test suite. tests/wocky-connector-test.c | 2 ++ 1 file changed, 2 insertions(+) commit da8fa0de237bbd1d3ccf12fcc9b51cc01d32a23d Author: Vivek Dasmohapatra Date: Tue Jul 14 15:52:35 2009 +0100 The SASL object was getting unref'd too early in sasl_auth_stanza_received, hold a ref to it while we pass it out to any handlers so that this does not happen. wocky/wocky-sasl-auth.c | 7 +++++++ 1 file changed, 7 insertions(+) commit 621212acade5aa4abd28aaa6a7a3ae385acc50a3 Author: Vivek Dasmohapatra Date: Tue Jul 14 15:05:53 2009 +0100 Casting style (whitespace) Move the sleep() after a bind() failure to a nested if, it shouldn't happen unless we enter the second iteration of the loop but the optimiser decided it should happen anyway (I think). Speeds up tests a bit. tests/wocky-connector-test.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) commit ea0a271654d179cf7b734628be3557bacee4a7bf Author: Vivek Dasmohapatra Date: Tue Jul 14 14:41:04 2009 +0100 Store, check and free the returned jid. Typo in comment. Check return value of listen() as well as bind. tests/wocky-connector-test.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) commit 75e0df17da3165f57528dd10655d0c5c1bb7ec08 Author: Vivek Dasmohapatra Date: Tue Jul 14 14:36:16 2009 +0100 Memory leak in digest_md5 handling. wocky/wocky-sasl-auth.c | 1 + 1 file changed, 1 insertion(+) commit a83dbe6538d42b02864058752501a84be9671856 Author: Vivek Dasmohapatra Date: Tue Jul 14 13:17:23 2009 +0100 Memory leak in DEBUG/state_message use. wocky/wocky-connector.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) commit e5ab24aa23dfa23d98297ad9a34623dcbd29877d Author: Vivek Dasmohapatra Date: Tue Jul 14 13:02:05 2009 +0100 Add brief comments desribing first block of test cases. tests/wocky-connector-test.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) commit 3eb6ca60feb2265aada49d17d4354933881a8c1a Author: Vivek Dasmohapatra Date: Tue Jul 14 12:15:41 2009 +0100 Kick off the test in a g_idle… - this prevents a race where a very early return via callback from the connector can happen before the mainloop has started (since an idle can by definition only happen in a running mainloop). tests/wocky-connector-test.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) commit 7809a0341d4544ce92d6b5375fd68b03148dd5f0 Author: Vivek Dasmohapatra Date: Tue Jul 14 11:59:47 2009 +0100 Delete any __db. BDB tmp/lock files, they cause SASL deadlocks in subsequent tests. tests/wocky-connector-test.c | 11 +++++++++++ 1 file changed, 11 insertions(+) commit f2339277d9b0511c2ad24285d8bcb060681aaec2 Author: Vivek Dasmohapatra Date: Tue Jul 14 11:38:11 2009 +0100 Wait for the server process (if any) to exit before proceeding to the next test. tests/wocky-connector-test.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) commit b4717962c54aa386576c53ec366f2d1820291418 Author: Vivek Dasmohapatra Date: Tue Jul 14 11:14:54 2009 +0100 Style typo. Add comment explaining why stderr is redirected in this case. tests/wocky-connector-test.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) commit be29dd08fb5a6be8508931c42b089f135d50ad84 Author: Vivek Dasmohapatra Date: Mon Jul 13 20:03:53 2009 +0100 Mask an error from the dummy xmpp server in the TLS-failed test. tests/wocky-connector-test.c | 92 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 2 deletions(-) commit b7040f801c6c7ad6d6373c4f6f9533d8cc22977b Author: Vivek Dasmohapatra Date: Mon Jul 13 18:48:51 2009 +0100 All the test binaries should depend on libwocky.la, which should in turn be located via $(top_builddir) tests/Makefile.am | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) commit db684838101af4957e96ff1c309270eab9cb7b8a Author: Vivek Dasmohapatra Date: Mon Jul 13 18:48:02 2009 +0100 Need to pause a little longer when the bind fails before retrying. tests/wocky-connector-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit d3ab888b24925ed57721724815b639f0a704accb Author: Vivek Dasmohapatra Date: Mon Jul 13 18:17:23 2009 +0100 remove #if/#endif used to comment tests out during test development. tests/wocky-connector-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit fb0b8461f88d12fffe7315ec3198bc8ac31c57ec Author: Vivek Dasmohapatra Date: Mon Jul 13 18:15:44 2009 +0100 Comment to explain exit w/o error reporting in the dummy XMPP server. (we're already past the point at which errors are interesting). tests/wocky-test-connector-server.c | 3 +++ 1 file changed, 3 insertions(+) commit bdbdcd5a1a1d8da7d82b7d64da8340cbba71fe97 Author: Vivek Dasmohapatra Date: Mon Jul 13 17:33:25 2009 +0100 Make a couple of repeat attempts to bind in case the last test hasn't relinquished the test server listen socket yet. tests/wocky-connector-test.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) commit 2ba19bdc3688021b32bd7bd710b794b97032d20d Author: Vivek Dasmohapatra Date: Mon Jul 13 17:32:21 2009 +0100 Mismerge. tests/wocky-test-connector-server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 02a21ef1f5e042a9c69eb73e6d397bc574962e4e Author: Sjoerd Simons Date: Thu Jul 2 19:44:32 2009 +0100 Add a servername argument tests/wocky-test-connector-server.c | 4 ++-- tests/wocky-test-sasl-auth-server.c | 5 +++-- tests/wocky-test-sasl-auth-server.h | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) commit f3924655e7690080c06e21800c02efa1d285ff5f Author: Sjoerd Simons Date: Thu Jul 2 19:47:31 2009 +0100 Cope with a null byte in the A1 hash wocky/wocky-sasl-auth.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) commit 94991a5d4fa0de22e446c1884ce283e976c3da2a Author: Sjoerd Simons Date: Thu Jul 2 19:46:22 2009 +0100 Test if the sasl auth copes with a null byte in the A1 MD5 hash Allow the test cases to define username, password and servername for the various testcases and add a test where the username, password and servername generates a null byte in the hash tests/wocky-test-sasl-auth.c | 63 +++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 24 deletions(-) commit 5da6c6d306a96d36921835f4afa5a62ee561c8b1 Author: Vivek Dasmohapatra Date: Mon Jul 13 17:00:13 2009 +0100 Free items fetched vie g_object_get in tests. tests/wocky-connector-test.c | 5 +++++ 1 file changed, 5 insertions(+) commit 9c6a1c3f29b943b93f6a012481ea03de7748da6c Author: Vivek Dasmohapatra Date: Mon Jul 13 13:59:27 2009 +0100 Change declaration style of wocky_connector_connect_finish wocky/wocky-connector.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) commit 1d707beec95ba76b2f2d42506a81fc201b667b94 Author: Vivek Dasmohapatra Date: Mon Jul 13 13:58:09 2009 +0100 Fail tests if we can't get the port we want for the dummy XMPP server: Either something else is already listening there or we have even bigger problems. tests/wocky-connector-test.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) commit 6cffb03ff8a6acf4c1ad7e069ea6d643f432725f Author: Vivek Dasmohapatra Date: Thu Jul 9 18:59:48 2009 +0100 whitespace typo. wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit eefabf3a68a80da5976d32a3f04f2d1e9cacae49 Author: Vivek Dasmohapatra Date: Thu Jul 9 18:58:09 2009 +0100 Server sudden-death tests + TLS negotiation error test. tests/wocky-connector-test.c | 67 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 3 deletions(-) commit d514cbadbeb84094637ac91445c1ecfb0d6cf843 Author: Vivek Dasmohapatra Date: Thu Jul 9 18:57:32 2009 +0100 More verbose debug message: which stage exactly did we bail out in? wocky/wocky-connector.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 75f7818af12f79ac1f94504e10f7ec4a4d8e609d Author: Vivek Dasmohapatra Date: Thu Jul 9 18:56:55 2009 +0100 Dummy server sudden-death conditions + TLS negotiation error implemented. tests/wocky-test-connector-server.c | 39 ++++++++++++++++++++++++++++--------- tests/wocky-test-connector-server.h | 5 +++++ 2 files changed, 35 insertions(+), 9 deletions(-) commit 557ae61ab6842b1be39a11c99a4d5e18733843d4 Author: Vivek Dasmohapatra Date: Thu Jul 9 17:41:51 2009 +0100 Tests for session error conditions/sessionless xmpp. Improve coverage of wocky-connector.c tests/wocky-connector-test.c | 139 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 137 insertions(+), 2 deletions(-) commit 657ffb95e2bd8f7a0edf9bff514424e2fd09f1f2 Author: Vivek Dasmohapatra Date: Thu Jul 9 17:41:04 2009 +0100 Stomp on some memory leaks. Add a missing break; Remove set_prop cases for unsettable properties. wocky/wocky-connector.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) commit 0f3c1cc97b29fd9257656d86dbeed0ea59f47b11 Author: Vivek Dasmohapatra Date: Thu Jul 9 17:39:51 2009 +0100 Implement session related error conditions. (and sessionless xmpp) tests/wocky-test-connector-server.c | 97 ++++++++++++++++++++++++++----------- tests/wocky-test-connector-server.h | 28 ++++++----- 2 files changed, 87 insertions(+), 38 deletions(-) commit 474b23cb4e81866ef0bc423aad47694eb28e949d Author: Vivek Dasmohapatra Date: Wed Jul 8 20:16:19 2009 +0100 Implement tests for error conditions. tests/wocky-connector-test.c | 78 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 6 deletions(-) commit 0868311be468b45d86dc5eef546b27b82324be44 Author: Vivek Dasmohapatra Date: Wed Jul 8 20:15:16 2009 +0100 Implement problems in dummy server. tests/wocky-test-connector-server.c | 92 +++++++++++++++++++++++++++++++------ tests/wocky-test-connector-server.h | 18 ++++++-- 2 files changed, 90 insertions(+), 20 deletions(-) commit e50dfa60adb743113a0bfa73d8a4bf361065533f Author: Vivek Dasmohapatra Date: Wed Jul 8 17:55:06 2009 +0100 More symbolic declararions in the test definitions to help with readability. Implement XMPP bad version and Bad feature stanza tests. Unlinking sasl db every time seems to cause sasl to fail unpredictably. Work around SASL problems in bad-user and bad-pass tests a differnet way. Unlink sasl DB just once at the start of the test. tests/wocky-connector-test.c | 236 +++++++++++++++++++++++++------------------ 1 file changed, 140 insertions(+), 96 deletions(-) commit d8049ff8c43fa96374fc240d8bb2872b4a3c0653 Author: Vivek Dasmohapatra Date: Wed Jul 8 17:52:15 2009 +0100 Allow user to set XMPP version in dummy server. Implement bad features and tls refused conditions. tests/wocky-test-connector-server.c | 23 +++++++++++++++++------ tests/wocky-test-connector-server.h | 2 ++ 2 files changed, 19 insertions(+), 6 deletions(-) commit 5aea3723697ad15a45be199696b2da9451705977 Author: Vivek Dasmohapatra Date: Wed Jul 8 17:46:13 2009 +0100 Initialise a couple of pointers to NULL. Log feature stanza version in DEBUG. wocky/wocky-connector.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit 02134164ac9436fcd2a2c3856688b50c1008ae54 Author: Vivek Dasmohapatra Date: Wed Jul 8 15:20:06 2009 +0100 TLS refused and bad-JID tests added. Fixed race condition in run_test. Changed way in which TLS support in the test server was turned on/off. tests/wocky-connector-test.c | 70 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 9 deletions(-) commit 8cb784f04101a107d50607323d810d70efa5bf2a Author: Vivek Dasmohapatra Date: Wed Jul 8 15:13:23 2009 +0100 Connector problems can now be ORed toegether. Implement TLS refused condition. tests/wocky-test-connector-server.c | 75 ++++++++++++++++++++++++++++--------- tests/wocky-test-connector-server.h | 8 ++-- 2 files changed, 62 insertions(+), 21 deletions(-) commit 89dca400878606b1926f3159e60b365bd163862c Author: Vivek Dasmohapatra Date: Tue Jul 7 19:53:30 2009 +0100 Clean up the sasl-db to make sure our bad password tests will pass. Add SASL tests. tests/wocky-connector-test.c | 74 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 3 deletions(-) commit 926d3dea455d54432c87c9bad95492d2a7faaf88 Author: Vivek Dasmohapatra Date: Tue Jul 7 17:39:54 2009 +0100 Another block of tests. All 48 basic connecion/auth tests against a correctly functioning XMPP server now pass. tests/wocky-connector-test.c | 139 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 136 insertions(+), 3 deletions(-) commit b04f5031ffaa0144aabf0d570562c91416eef240 Author: Vivek Dasmohapatra Date: Tue Jul 7 17:25:30 2009 +0100 More tests. Make test declarations more symbolic so they are a bit easier to interpret. Test for correct auth mechanism used. tests/wocky-connector-test.c | 324 ++++++++++++++++++++++++++++++++----------- 1 file changed, 242 insertions(+), 82 deletions(-) commit 9da297ee487904298d72cf1c61c9ca5f3c7d0a81 Author: Vivek Dasmohapatra Date: Tue Jul 7 16:08:00 2009 +0100 Remember and expose the sasl auth mechanism actually used via the wock sasl and connector APIs. unref the sasl object when we are done with it. wocky/wocky-connector.c | 16 ++++++++++++++-- wocky/wocky-connector.h | 3 +++ wocky/wocky-sasl-auth.c | 13 +++++++------ wocky/wocky-sasl-auth.h | 9 +++++++++ 4 files changed, 33 insertions(+), 8 deletions(-) commit e878d844f3f0aba7462c3a1e298898131f8b5428 Author: Vivek Dasmohapatra Date: Fri Jul 3 17:54:27 2009 +0100 Whitespace fix. Compiler warning about type of test_func. tests/wocky-connector-test.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) commit 04fa73cd6aaf998ab30e3d06f43ffc4f69bad34f Author: Vivek Dasmohapatra Date: Fri Jul 3 17:49:33 2009 +0100 First block of 24 basic tests that check the connectors logic wrt SRV rcords vs A records vs user-specified hosts is sound. tests/wocky-connector-test.c | 362 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 335 insertions(+), 27 deletions(-) commit 7a067167711901a56de1d40bdc63989c3ba2bd56 Author: Vivek Dasmohapatra Date: Fri Jul 3 17:48:37 2009 +0100 typo. tests/connector-test-plan.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 84cd0e1527ca8e2594cff8666209f45da52f276d Author: Vivek Dasmohapatra Date: Fri Jul 3 17:26:21 2009 +0100 Do not fall back to A records if there is a SRV record but we failed to connect to the spcified host. Silence a "discarding qualifiers" warning. wocky/wocky-connector.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) commit 6eacf17c3f9f69aa822688c9ff88e86acd284658 Author: Vivek Dasmohapatra Date: Fri Jul 3 17:23:40 2009 +0100 Update test plan with new expected outcomes. tests/connector-test-plan.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) commit a47f813adfcee2010c1bcd5d578b9836594c9edd Author: Vivek Dasmohapatra Date: Fri Jul 3 17:23:06 2009 +0100 If libwocky.la has been rebuilt, wocky-connector-test also needs rebuilding tests/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 0e83d2a65b74be44a3327df5b538e0b6fde4ad40 Author: Vivek Dasmohapatra Date: Fri Jul 3 15:00:21 2009 +0100 Ignore the SRV record (if any) if _either_ HOST or PORT is supplied. wocky/wocky-connector.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) commit 5fa9d1bfa829d5233303f04c0c7ddfb6e30407d2 Author: Vivek Dasmohapatra Date: Fri Jul 3 14:59:32 2009 +0100 Copyright date corrected. Kill the server if the stanza is NULL after a receive in xmpp_handler. tests/wocky-test-connector-server.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) commit e023a31e8f3aaea915eb13f6f2a4eaa1248d618e Author: Vivek Dasmohapatra Date: Fri Jul 3 14:58:12 2009 +0100 Register DEBUG_CONNECTOR so WOCKY_DEBUG can be used to set it on its own wocky/wocky-debug.c | 1 + 1 file changed, 1 insertion(+) commit 6bc6da0bf0f9bf2e6f1da6840394e8c4df0bf11f Author: Vivek Dasmohapatra Date: Thu Jul 2 11:52:30 2009 +0100 Slight screw-up in conflict resolution, lines doubled up. tests/Makefile.am | 3 --- 1 file changed, 3 deletions(-) commit ccb9cb7410115bbf1eb023ad6bc67416303e211b Author: Guillaume Desmottes Date: Thu Jul 2 10:47:35 2009 +0100 test_sasl_auth_server_new: ref the stream as we keep our own ref on it tests/wocky-test-sasl-auth-server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 0011d1ef50b99232b14304c36d62426efb5928b9 Author: Vivek Dasmohapatra Date: Wed Jul 1 18:22:11 2009 +0100 Clean up generated pem files. Bail out iwht an error if certtool is not installed. tests/Makefile.am | 7 +++++++ 1 file changed, 7 insertions(+) commit f7b03e95eb6bb399a6b4f38405f28d301f4aa93c Author: Vivek Dasmohapatra Date: Wed Jul 1 17:25:26 2009 +0100 Add loopback IP address to cert config. tests/certs/tls-cert.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit ac33f6850cf1e6fb4de9c964393b73c6b1cb4e4e Author: Vivek Dasmohapatra Date: Wed Jul 1 17:25:02 2009 +0100 Need to use abspath, not realpath, files might not exist yet. tests/Makefile.am | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) commit 4c439506aa436b146bb600eb8892deacc45d9482 Author: Vivek Dasmohapatra Date: Wed Jul 1 17:06:32 2009 +0100 Generate x509 key and cert PEM files automatically. Use generated PEM files in connector tests. Ignore PEM files in git. .gitignore | 2 + tests/Makefile.am | 40 ++++++++++++++++- tests/certs/ca-cert.cfg | 89 +++++++++++++++++++++++++++++++++++++ tests/certs/tls-cert.cfg | 89 +++++++++++++++++++++++++++++++++++++ tests/wocky-test-connector-server.c | 12 ++--- 5 files changed, 224 insertions(+), 8 deletions(-) commit 37e4a629ea89b01d744c73b5ead5b4886e0334a2 Author: Vivek Dasmohapatra Date: Wed Jul 1 17:05:05 2009 +0100 Remove noisy debug messsage. tests/wocky-connector-test.c | 2 -- 1 file changed, 2 deletions(-) commit 70a7d400fb89c83ef680cc1a2b96b0faca756af0 Author: Vivek Dasmohapatra Date: Wed Jul 1 16:12:00 2009 +0100 Wrong constant used for property. wocky/wocky-connector.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit d72b9ccf7a0cc8408d6f28264b288137a7bac1e0 Author: Vivek Dasmohapatra Date: Wed Jul 1 11:51:25 2009 +0100 Removed header signature for dead function wocky_connector_new_full Allow resource to be set in wocky_connector_new as it is CONSTRUCT_ONLY now. Update example connect,c to match new API. examples/connect.c | 2 +- wocky/wocky-connector.c | 9 +++++++-- wocky/wocky-connector.h | 11 +---------- 3 files changed, 9 insertions(+), 13 deletions(-) commit 152fe152ab7ccb0bdff1ef3b3b3fbdbbe52a5502 Author: Vivek Dasmohapatra Date: Tue Jun 30 19:36:21 2009 +0100 Remove obsolete error codes now that we propagate low level errors up the chain wocky/wocky-connector.h | 5 ----- 1 file changed, 5 deletions(-) commit 39a38ad6ba2f19605ce08d8c317f4fe76d6526cb Author: Vivek Dasmohapatra Date: Tue Jun 30 19:31:46 2009 +0100 Split abort_connect into two cases: abort_connect_error for lower level GErrors propagating up, and abort_c for errors originating in the connector. wocky/wocky-connector.c | 107 ++++++++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 49 deletions(-) commit 3955e98dedd1ef01f7a46c72c467a1e9b9cab735 Author: Vivek Dasmohapatra Date: Tue Jun 30 17:49:00 2009 +0100 Sprinkle DEBUG statments liberally through the code so we can see what's going on while working on it. wocky/wocky-connector.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) commit 0636a92e94bd3bea4c76f7bc290663bcedfc97e5 Author: Vivek Dasmohapatra Date: Tue Jun 30 16:31:23 2009 +0100 Change the way the error *tag is assigned. strdup the node name when storing it as it is a temporary value. wocky/wocky-connector.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) commit 64935e950f299bdbfe4b3040983746e5dd9166fa Author: Vivek Dasmohapatra Date: Tue Jun 30 16:27:55 2009 +0100 Change the way the ... section is added to the bind iq stanza. wocky/wocky-connector.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) commit 1f51b19483ca88bcf4293618292e4e045c33ef87 Author: Vivek Dasmohapatra Date: Tue Jun 30 16:18:14 2009 +0100 stanza is mandatory at this point. wocky/wocky-connector.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) commit 20be1e4e14d5af05c91353db9e0a348630738336 Author: Vivek Dasmohapatra Date: Tue Jun 30 16:16:04 2009 +0100 Cast of object first in function. wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 36a31c8b4c6ccec4f990522adb3245ca8f3c68e2 Author: Vivek Dasmohapatra Date: Tue Jun 30 16:15:04 2009 +0100 Amended error message on missing/bogus feature stanza. wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 99fdb845fe6b029b1861443101d3b6fb9e030c51 Author: Vivek Dasmohapatra Date: Tue Jun 30 16:13:41 2009 +0100 Password must be set (but it can be empty). Emit a warning if it is NULL, and set it to "". wocky/wocky-connector.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) commit b63d235a96c9dbf926447e0b8d866043517bbb3a Author: Vivek Dasmohapatra Date: Tue Jun 30 16:05:38 2009 +0100 resource is construct only resource must be non-empty as well as non-NULL wocky/wocky-connector.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) commit ffb1ed9ced0574675fb61ef45af2486e6a4d65d4 Author: Vivek Dasmohapatra Date: Tue Jun 30 15:23:01 2009 +0100 remove time(NULL) component from random resource. wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 299f755966af70a37d948a25bc0d6328460c05a8 Author: Vivek Dasmohapatra Date: Tue Jun 30 15:21:27 2009 +0100 g_strdup_printf in make_resource. wocky/wocky-connector.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) commit 5d7ef8477ca16fe62bbf75e77a053086470f8d35 Author: Vivek Dasmohapatra Date: Tue Jun 30 15:19:02 2009 +0100 Change to state_message + comment from review. wocky/wocky-connector.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) commit 4cd1069dcf04677cc2e426d45dbe6dc2a6c91a8f Author: Vivek Dasmohapatra Date: Tue Jun 30 15:12:26 2009 +0100 Change base for auto-generated resources. wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 353c15fc1df8c6b8d8f7c0749d85a97a149f0cd9 Author: Vivek Dasmohapatra Date: Tue Jun 30 15:11:11 2009 +0100 Add ids to the iq set stanzas for bind and session wocky/wocky-connector.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) commit 65ca5081880dc5a730f4b6e51cf74dcdfcf79255 Author: Vivek Dasmohapatra Date: Tue Jun 30 14:54:35 2009 +0100 Implement bind/session feature advert support + handle iqs for same. tests/wocky-test-connector-server.c | 194 +++++++++++++++++++++++++++++++++--- 1 file changed, 181 insertions(+), 13 deletions(-) commit a0a44e8a21f49493d620a61bfe2a8101ac74b145 Author: Vivek Dasmohapatra Date: Tue Jun 30 14:53:37 2009 +0100 follow _async/_finish convention, allow SASL test server to hand back control so that the connector test server can re-use the SASL implementation. tests/wocky-test-sasl-auth-server.c | 62 ++++++++++++++++++++++++++++++------- tests/wocky-test-sasl-auth-server.h | 8 +++-- 2 files changed, 57 insertions(+), 13 deletions(-) commit 990e0d82901923632adc68815b6a5c754517a8dd Author: Vivek Dasmohapatra Date: Tue Jun 30 14:51:55 2009 +0100 Initialise char * to NULL. tests/wocky-connector-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit fd4eccc6d775244b4eede451142666d062cbff31 Author: Vivek Dasmohapatra Date: Mon Jun 29 16:01:49 2009 +0100 Unref the feature stanza in the dispose handler. wocky/wocky-connector.c | 1 + 1 file changed, 1 insertion(+) commit adc3b5dbc45050f02eb06edde48e2c8773f13ea2 Author: Vivek Dasmohapatra Date: Mon Jun 29 14:22:18 2009 +0100 Establish an XMPP session if required by the server. wocky/wocky-connector.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++- wocky/wocky-connector.h | 4 ++ wocky/wocky-namespaces.h | 3 ++ 3 files changed, 135 insertions(+), 1 deletion(-) commit eaabec09df985b62acad3795a9b5e5c9145af8bc Author: Vivek Dasmohapatra Date: Mon Jun 29 13:24:34 2009 +0100 Connector test partially modified to match API changes. Test does not work yet as test server does not advertise/support resource binding, in progress. tests/wocky-connector-test.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) commit f0a4777ef61874bb09135806cc17fad4ec18ac00 Author: Vivek Dasmohapatra Date: Mon Jun 29 13:15:06 2009 +0100 Specific error for TLS negotiation failure wocky/wocky-connector.c | 2 +- wocky/wocky-connector.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) commit 1c9b71771d8ff8ef4cd873113bf6877a7841f891 Author: Vivek Dasmohapatra Date: Mon Jun 29 13:14:30 2009 +0100 xmpp_init re-used every time we (re-)initialise the stream insteadt of calling wocky_xmpp_connection_send_open_async directly. Added features property to cache XMPP features stanza Erase cached features whenever we (re-)initialise the stream. wocky/wocky-connector.c | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) commit fa79d6a25d06f990719087fbf433836a72ddb140 Author: Vivek Dasmohapatra Date: Fri Jun 26 18:15:02 2009 +0100 Return jid received from server in _finish call. Update example code for new _finish signature. examples/connect.c | 6 ++++-- wocky/wocky-connector.c | 10 +++++++++- wocky/wocky-connector.h | 3 ++- 3 files changed, 15 insertions(+), 4 deletions(-) commit 89ed5c796e8828b56adb4febcc872c36e12e67fa Author: Vivek Dasmohapatra Date: Fri Jun 26 17:53:58 2009 +0100 Correct description of XMPP login flow at top of file. Add extra section to end of login process to handle XMPP resource binding. wocky/wocky-connector.c | 217 ++++++++++++++++++++++++++++++++++++++++------- wocky/wocky-connector.h | 8 +- wocky/wocky-namespaces.h | 3 + 3 files changed, 194 insertions(+), 34 deletions(-) commit 0150ab7df5d7694aca126b51db803f8e9317c044 Author: Vivek Dasmohapatra Date: Fri Jun 26 17:53:00 2009 +0100 Fix style issues in wocky_xmpp_node_get_first_child wocky/wocky-xmpp-node.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit edeae35e5f457801eba4b3f7105086e7ac487f74 Author: Vivek Dasmohapatra Date: Fri Jun 26 17:48:55 2009 +0100 Add core, TAGS *report.xml to gitignore .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 779a995a4488b1d6d1fbb54e7a899cd2094206bd Author: Vivek Dasmohapatra Date: Fri Jun 26 17:32:00 2009 +0100 Utility function: get first node child. wocky/wocky-xmpp-node.c | 8 ++++++++ wocky/wocky-xmpp-node.h | 2 ++ 2 files changed, 10 insertions(+) commit 03663c6d95a5a6fe8c20391798a401965724075d Author: Vivek Dasmohapatra Date: Thu Jun 25 18:59:51 2009 +0100 Fixed abort_connect infrastructure to be more in-line with normal usage. Addressed various mem leaks on calls to abort_connect. wocky/wocky-connector.c | 182 +++++++++++++++++++++++++++--------------------- 1 file changed, 103 insertions(+), 79 deletions(-) commit d85c65c5c1acd81ce6f9a09bbfa279eef4b6e201 Author: Vivek Dasmohapatra Date: Thu Jun 25 18:56:49 2009 +0100 Update example to match new API signatures. examples/connect.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) commit 5ebbcbc5c82bc1372919e9f454c07a3b459cd397 Author: Vivek Dasmohapatra Date: Thu Jun 25 14:47:33 2009 +0100 Style, whitespace, naming convention and function signature changes from review. wocky/wocky-connector.c | 413 ++++++++++++++++++++++-------------------------- wocky/wocky-connector.h | 39 ++--- 2 files changed, 213 insertions(+), 239 deletions(-) commit 30563d5d57753139d23747302e9a9070c5c50a57 Author: Vivek Dasmohapatra Date: Thu Jun 25 14:46:38 2009 +0100 Typo in .gitignore .gitignore | 1 + 1 file changed, 1 insertion(+) commit aa4d242f886e01522142b80be255209a496a8f5d Author: Vivek Dasmohapatra Date: Wed Jun 24 14:28:59 2009 +0100 ifdef out the fakedns debugging, pretty sure it's working as advertised. tests/test-resolver.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) commit 897887f5e5b10905ce2b4d514216b2af7e06741a Author: Vivek Dasmohapatra Date: Wed Jun 24 14:19:33 2009 +0100 Duff header file entry removed. tests/Makefile.am | 1 - 1 file changed, 1 deletion(-) commit 6a6920e91b10e0cf1814f8797fddd7f9d8fe23c2 Author: Vivek Dasmohapatra Date: Wed Jun 24 14:19:13 2009 +0100 Style & whitespace fixes. tests/test-resolver.c | 11 ++++++----- tests/wocky-connector-test.c | 10 +++++----- tests/wocky-test-sasl-auth-server.c | 4 ++-- 3 files changed, 13 insertions(+), 12 deletions(-) commit 04f7f9f13c980aac1969290464027befd23c8468 Author: Vivek Dasmohapatra Date: Wed Jun 24 14:09:33 2009 +0100 Add new connector test suite (only first test so far) Let Makefile.am know about new connector test Pattern rule to allow individual test-suites to be run. tests/Makefile.am | 20 +++- tests/wocky-connector-test.c | 235 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 254 insertions(+), 1 deletion(-) commit 0793348f6af655869a4f232637b402d85ceabb84 Author: Vivek Dasmohapatra Date: Wed Jun 24 14:07:42 2009 +0100 More DEBUG statements. Check more internal members for NULL before unrefing. Only free the xml stanza in the handler dispatcher if we didn't find a suitable handler, otherwise it's the handler's job to clean it up. tests/wocky-test-connector-server.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) commit 27a5d96a4c08f8051a50c74a8f9d6e500939832f Author: Vivek Dasmohapatra Date: Wed Jun 24 14:05:54 2009 +0100 Check the error member is set before unrefing it. wocky/wocky-connector.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 340d86988a4ed892eb42d160549de270ecb6b31c Author: Vivek Dasmohapatra Date: Wed Jun 24 14:04:58 2009 +0100 Check some priv-> members for NULL before unrefing them. tests/wocky-test-sasl-auth-server.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) commit 92517034b508caece0ebe13ca7ff253d3e07985e Author: Vivek Dasmohapatra Date: Fri Jun 19 18:35:11 2009 +0100 Resolver class that lets us patch in fake SRV and A records for a domain on the fly. Needed for the connector tests. tests/test-resolver.c | 325 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/test-resolver.h | 68 +++++++++++ 2 files changed, 393 insertions(+) commit 3dd3b2e7b83081d6cffb5c8631493efd04f55de4 Author: Vivek Dasmohapatra Date: Fri Jun 19 17:46:52 2009 +0100 Check in test plan for connector. tests/connector-test-plan.txt | 77 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) commit 88702faf56df2a1683eb21bb651085fe09d0b494 Author: Vivek Dasmohapatra Date: Tue Jun 16 19:32:33 2009 +0100 Reference use of new test-connector-server code. tests/wocky-dummy-xmpp-server.c | 103 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) commit f7d9bcd29eb61ab08099fb8225995d8a273e6c3a Author: Vivek Dasmohapatra Date: Tue Jun 16 19:31:38 2009 +0100 Implement a simplistic TLS/SASL capable server for use in tests. (Implementation of problem conditions not implemented yet, to be added). tests/wocky-test-connector-server.c | 89 ++++++++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 26 deletions(-) commit 025f94637f7ea5c277cccd55d4ba04db97460251 Author: Vivek Dasmohapatra Date: Tue Jun 16 19:29:31 2009 +0100 Test for xml stanza validity was reversed. DEBUG the host/port connect details. wocky/wocky-connector.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 32cd7a984868ba704ba618acf7d374ee8d2f7664 Author: Vivek Dasmohapatra Date: Tue Jun 16 19:19:17 2009 +0100 Use new wocky_connector_new constructor. Minor debugging tidyups. examples/connect.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) commit 7d32a1aac743733aacb95dc95ae88e880f4f9a4c Author: Vivek Dasmohapatra Date: Mon Jun 15 14:20:15 2009 +0100 g_object_new needs its arglist to be NULL terminated. wocky/wocky-connector.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit cf4b65601d09f81821f8ee726d567eeeff52626f Author: Vivek Dasmohapatra Date: Thu Jun 11 18:49:50 2009 +0100 1 arg per line in function signatures. tests/wocky-test-connector-server.c | 20 ++++++++++++++------ tests/wocky-test-connector-server.h | 7 +++++-- 2 files changed, 19 insertions(+), 8 deletions(-) commit 3084eae34c36f0aca0e5f08fcdcccb62b0d6e652 Author: Vivek Dasmohapatra Date: Thu Jun 11 18:41:12 2009 +0100 Removed 'tls' node variable from xmpp_features_cb wocky/wocky-connector.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) commit 8b39bee9a61c3a276fe3877e723fa33943814399 Author: Vivek Dasmohapatra Date: Thu Jun 11 18:36:16 2009 +0100 Function signatures reformatted to be 1 arg per line. wocky/wocky-connector.c | 36 ++++++++++++++++++++++++++---------- wocky/wocky-connector.h | 6 ++++-- 2 files changed, 30 insertions(+), 12 deletions(-) commit 6fde7bb9a614c86a9c8d240d22e57cedc3cde941 Author: Vivek Dasmohapatra Date: Thu Jun 11 18:29:04 2009 +0100 Rename error constant more accurately. Abort on connect_async if our state indicates we are already underway. wocky/wocky-connector.c | 10 +++++++++- wocky/wocky-connector.h | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) commit caa4950f376eb6287d9747aa627500c375737681 Author: Vivek Dasmohapatra Date: Thu Jun 11 18:13:45 2009 +0100 g_assert_not_reached + explanatory comment in xmpp_init_recv_cb minor whitespace cleanup. wocky/wocky-connector.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) commit f26489168df374fca73918673f7fd8b7616c0350 Author: Vivek Dasmohapatra Date: Thu Jun 11 18:06:18 2009 +0100 Comments explaining the logic by which we choose XMPP server hosts to talk to. wocky/wocky-connector.c | 7 +++++++ 1 file changed, 7 insertions(+) commit f6350456ab3a76aa6cbfa2138064b55e96c2d3df Author: Vivek Dasmohapatra Date: Thu Jun 11 17:59:30 2009 +0100 Renamed finalise to match incorrect spelling in glib standard. wocky/wocky-connector.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit 357e3a1591e123a267d13814f8235d2bcc4e131c Author: Vivek Dasmohapatra Date: Thu Jun 11 17:58:11 2009 +0100 Define _new and _new_full constructors as per review. wocky/wocky-connector.c | 33 ++++++++++++++++++++++++++++++++- wocky/wocky-connector.h | 11 +++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) commit 597f870b6028156c9dd0d533eace2ae46b535149 Author: Vivek Dasmohapatra Date: Thu Jun 11 16:50:55 2009 +0100 Style cleanups. Use new server-side starttls support to initialise TLS upon receipt of client request. Hand over to sasl auth server on receipt of Date: Thu Jun 11 16:46:53 2009 +0100 Finish modifying wocky-test-sasl-auth-server.c so that it can take over an existing WockyXmppConnection at the point where an Date: Thu Jun 11 16:02:57 2009 +0100 Unnecessary if () removed. wocky/wocky-connector.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) commit 883038030d8ea49fd1c7f238de9f7a351603ff54 Author: Vivek Dasmohapatra Date: Thu Jun 11 16:02:18 2009 +0100 whitespace cleanup. examples/connect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 2b9277ba2d080219e5ef3e1343841cad48aceed7 Author: Vivek Dasmohapatra Date: Thu Jun 11 15:07:02 2009 +0100 Begin modification of wocky-test-sasl-auth… et al to allow its funcitonality to be shared by wocky-test-connector… and any other tests that need it: Exposed feature sasl mechanism population to externl users, altered test_sasl_auth_server_new so it does not immediately try to take over the test XMPP connection. tests/wocky-test-sasl-auth-server.c | 103 ++++++++++++++++++++++-------------- tests/wocky-test-sasl-auth-server.h | 8 ++- tests/wocky-test-sasl-auth.c | 4 +- 3 files changed, 73 insertions(+), 42 deletions(-) commit 9c44590b67848d35a65fe72b9542a97b32fd5bdd Author: Vivek Dasmohapatra Date: Thu Jun 11 12:06:07 2009 +0100 Renamed next_state to more descriptive xmpp_init, added comments describing XMPP stream init stages therein. tests/wocky-test-connector-server.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) commit 38e422bae84cec26e0259c0fe49890160bbd0356 Author: Vivek Dasmohapatra Date: Wed Jun 10 18:57:20 2009 +0100 Dummy XMPP Server for Connector tests (not complete yet) Will eventually absorb the sasl server, which will provide the sasl portion of the tests, but will no longer need to do the rest of the stream open etc. tests/Makefile.am | 2 + tests/wocky-test-connector-server.c | 308 ++++++++++++++++++++++++++++++++++++ tests/wocky-test-connector-server.h | 74 +++++++++ 3 files changed, 384 insertions(+) commit 23d996360c91b43b182158a3a81dde97d0c23e11 Author: Vivek Dasmohapatra Date: Wed Jun 10 18:54:57 2009 +0100 Add debug flag for connector Last round of cleanups introduced a couple of build warnings/breakages. Fixed. wocky/wocky-connector.c | 12 ++++++++++-- wocky/wocky-debug.h | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) commit 6c45f6736242b19d86d03b33bc4b2dce685309c4 Author: Vivek Dasmohapatra Date: Tue Jun 9 18:24:32 2009 +0100 abort_connect uses g_simple_async_result_complete_in_idle now. wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 965083217bffc0ed9a91e7f382200b43f31ed484 Author: Vivek Dasmohapatra Date: Tue Jun 9 18:21:30 2009 +0100 DEBUG preferred over g_warning wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 177d9677564f0de019152bfbef0f4fe9e7ad2881 Author: Vivek Dasmohapatra Date: Tue Jun 9 18:20:29 2009 +0100 Stray whitespace. wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 87b723a54bc7be661e3fd1cfa54c6290d2b64b79 Author: Vivek Dasmohapatra Date: Tue Jun 9 18:18:58 2009 +0100 wocky_strdiff preferred over strcmp wocky/wocky-connector.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) commit d9402fe39326b7ee330a5ad19a6545a5ce6124e8 Author: Vivek Dasmohapatra Date: Tue Jun 9 18:07:24 2009 +0100 Explicit test for ptr == NULL wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit a2eef74bdb45c4ed1c58d0e0e2148a5921956388 Author: Vivek Dasmohapatra Date: Tue Jun 9 18:06:15 2009 +0100 Removed domain and numeric code from error messages (per review). wocky/wocky-connector.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) commit 19e4414a6d3addae37c2bebfa225ea5730688956 Author: Vivek Dasmohapatra Date: Tue Jun 9 18:02:26 2009 +0100 DEBUG preferred over g_message wocky/wocky-connector.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit 452146fc1d6052b8156d761a4c72d5fb7b0b77b6 Author: Vivek Dasmohapatra Date: Tue Jun 9 18:01:15 2009 +0100 Comment explaining 'host' in wocky_connector_connect_async wocky/wocky-connector.c | 7 +++++++ 1 file changed, 7 insertions(+) commit e6dcb5a2ef999c158c82e72117312205017d6c52 Author: Vivek Dasmohapatra Date: Tue Jun 9 17:59:45 2009 +0100 Typo in comment. Moved gfree() calls to finalise method (from dispose). wocky/wocky-connector.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) commit 9c16b186fa774ec0b1c45bd9565093db7c77c4e5 Author: Vivek Dasmohapatra Date: Tue Jun 9 17:47:08 2009 +0100 More style changes per review. wocky/wocky-connector.c | 101 +++++++++++++++++++++++++----------------------- 1 file changed, 52 insertions(+), 49 deletions(-) commit 382ef04cb5fd1af9e0535c68c4207b67e300a467 Author: Vivek Dasmohapatra Date: Tue Jun 9 17:33:47 2009 +0100 Explain WOCKY_CONNECTOR_CHOOSE_BY_STATE macro. wocky/wocky-connector.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) commit 858060449b818bb8f4223a28a4c9fdcd53f821e6 Author: Vivek Dasmohapatra Date: Tue Jun 9 17:26:28 2009 +0100 Use g_object_new now that wocky_connector_new is gone. examples/connect.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 8c98ef4cd5c1378c33004a6d48e987fc72fe14e2 Author: Vivek Dasmohapatra Date: Tue Jun 9 17:26:05 2009 +0100 finalise and dispose methods should be static. wocky/wocky-connector.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit a5ff119131f8309691635742af685861be799e14 Author: Vivek Dasmohapatra Date: Tue Jun 9 17:25:36 2009 +0100 Style changes from review, unexport a couple of functions which should have been private. Remove wocky_connector_new as per review. wocky/wocky-connector.h | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) commit 6c0b35c2c0fa0c194ccb4abc1cbefcec9dbf6cc8 Author: Vivek Dasmohapatra Date: Thu Jun 4 19:14:15 2009 +0100 Add command line parameter to choose 'raw' vs 'connector' XMPP connect. Add code for 'connector' XMPP connect using wocky connector object. examples/connect.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) commit 3790fb59b23c02299339ff73e767a318fbc9b919 Author: Vivek Dasmohapatra Date: Thu Jun 4 19:12:51 2009 +0100 Fix wocky_connector_new to correctly call g_object_new Fix xmpp_features_cb logic for case when we have already starttls'd password/jid property overwrite bug fixed default XMPP port set to 5222 wocky/wocky-connector.c | 42 +++++++++++++++++++++++++++++------------- wocky/wocky-connector.h | 3 ++- 2 files changed, 31 insertions(+), 14 deletions(-) commit cfcb2772dcba0c227ecf11ee247f179030fd1b1b Author: Vivek Dasmohapatra Date: Thu Jun 4 13:43:20 2009 +0100 First (working?) draft of connector with standard async/finish connect mechanism and updated exmaple connect script. examples/connect.c | 51 +++++++++++--- wocky/wocky-connector.c | 172 ++++++++++++++++++++++++++---------------------- wocky/wocky-connector.h | 7 +- 3 files changed, 142 insertions(+), 88 deletions(-) commit 475d37909db72097cfec759b2b01d43a77c88af2 Author: Vivek Dasmohapatra Date: Wed Jun 3 19:57:20 2009 +0100 Use standard gasync callback mechanism for aborts, with GErrors check in header file for connector Add to makefile. Nearly working. wocky/Makefile.am | 2 + wocky/wocky-connector.c | 542 ++++++++++++++++++++++++++++++------------------ wocky/wocky-connector.h | 113 ++++++++++ 3 files changed, 458 insertions(+), 199 deletions(-) commit 7ff5c9dd7fbe707a53d060c3c7654b1c4ff0a98c Author: Vivek Dasmohapatra Date: Tue Jun 2 11:33:43 2009 +0100 Add the quark for connector's error domain. wocky/wocky-connector.c | 3 +++ 1 file changed, 3 insertions(+) commit c5a2627ea66a7f4ef9f5107d5e67577e6dc3de49 Author: Vivek Dasmohapatra Date: Mon Jun 1 16:48:03 2009 +0100 Fix conditionals to be explicit comparisons for non booleans, except where prior examples indicate this is not house style. More paren style fixups. wocky/wocky-connector.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) commit 2e845740d5053db97c35cc9ac5e26e4a00b8d527 Author: Vivek Dasmohapatra Date: Mon Jun 1 16:06:48 2009 +0100 Typo, missing member in LHS of assignment. wocky/wocky-connector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 19c37059f9831ff2a43fe6152fef3d8558217002 Author: Vivek Dasmohapatra Date: Mon Jun 1 15:56:43 2009 +0100 Whitespace cleanup. Paren style cleanup. wocky/wocky-connector.c | 292 ++++++++++++++++++++++++------------------------ 1 file changed, 146 insertions(+), 146 deletions(-) commit a9b92bc922f94e33f06d6ca9f195a4471a3f515a Author: Vivek Dasmohapatra Date: Mon Jun 1 15:29:18 2009 +0100 comment style // → /* */ removed WOCKY_CONNECTOR_UNPACK macro. wocky/wocky-connector.c | 117 +++++++++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 52 deletions(-) commit 36c461f9c3da62b179e5581cc8e8262eff88e8ec Author: Vivek Dasmohapatra Date: Mon Jun 1 11:23:46 2009 +0100 Rough (almost complete) draft of wocky connector. wocky/wocky-connector.c | 608 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 608 insertions(+) commit b16a9a948ce8086aa9aeec9c14ccbb1762cce335 Author: Guillaume Desmottes Date: Tue Jul 14 17:20:51 2009 +0100 add test_close_simultanously tests/wocky-porter-test.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) commit af30ecf5fad7d8f975ec24fa8f0d051454e0c4fd Author: Guillaume Desmottes Date: Tue Jul 14 17:20:06 2009 +0100 Don't complete close operation if the close stanza has not been sent yet wocky/wocky-porter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 1e02cd7bdc0536dba4402c67663963484bacd819 Author: Guillaume Desmottes Date: Tue Jul 14 17:18:37 2009 +0100 complete_close: set close_result to NULL before unreffing it If the result owns the last reference on the porter, it will be destroyed and the dispose function will try to unref it too. wocky/wocky-porter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) commit 38bee928e048f9d5fd5d04590a52a06f2a05c7e7 Author: Guillaume Desmottes Date: Mon Jul 13 15:00:48 2009 +0100 wocky-porter-test: add test_unref_when_closed tests/wocky-porter-test.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) commit 52b07eda1b27c3d77dda2ed233e321497081e510 Author: Guillaume Desmottes Date: Tue Jul 14 11:57:38 2009 +0100 stanza_received_cb: ensure that the porter stays alive during the treatment of the error or stanza wocky/wocky-porter.c | 7 +++++++ 1 file changed, 7 insertions(+) commit 91bfd7438e4f14ee8f7859d58e38b2be5a6c9d45 Author: Guillaume Desmottes Date: Mon Jul 13 14:49:25 2009 +0100 teardown_test: check if porters have already been unreffed tests/wocky-test-helper.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit bc8c40454043b536867fb763148897f309ea8076 Author: Jonny Lamb Date: Tue Jul 14 12:07:17 2009 +0100 Test sending an reply to an IQ with no "to" attribute. Signed-off-by: Jonny Lamb tests/wocky-xmpp-stanza-test.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) commit 9d815d0d07ffa2f4bec084e41999e6980928b4a9 Author: Jonny Lamb Date: Tue Jul 14 12:01:04 2009 +0100 It's fine for IQs to have no "to" attribute. Signed-off-by: Jonny Lamb wocky/wocky-xmpp-stanza.c | 1 - 1 file changed, 1 deletion(-) commit 43ddc3fbc7e02c7905361d749ae9c606cc944a70 Author: Guillaume Desmottes Date: Thu Jul 2 17:23:14 2009 +0100 test_send_iq: test sending a reply without id tests/wocky-porter-test.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) commit d436196deca91660702aca5d3d4930e4ff17290a Author: Guillaume Desmottes Date: Thu Jul 2 17:23:01 2009 +0100 handle_iq_reply: ignore reply without id wocky/wocky-porter.c | 6 ++++++ 1 file changed, 6 insertions(+) commit 5b472f2cc0ec48664702b067981bc06cfd97fe4d Author: Guillaume Desmottes Date: Thu Jul 2 14:46:35 2009 +0100 add test_send_iq_server tests/wocky-porter-test.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) commit b96a2e212eefacbd0faf77d9beb795aece37000a Author: Guillaume Desmottes Date: Thu Jul 2 14:46:23 2009 +0100 Allow to send IQ without a recipient wocky/wocky-porter.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) commit 75ac0432ad2d6cab23607eaa2b087569bc74401b Author: Guillaume Desmottes Date: Thu Jul 2 12:34:16 2009 +0100 test_send_invalid_iq: sending an IQ without a recipient is actually valid tests/wocky-porter-test.c | 10 ---------- 1 file changed, 10 deletions(-) commit 4717b4ea04f5e4c17b71ff8a6c1960d737fc0803 Author: Sjoerd Simons Date: Thu Jul 2 15:03:03 2009 +0100 Ignore warnings from the parser wocky/wocky-xmpp-reader.c | 6 ++++++ 1 file changed, 6 insertions(+) commit 3419d60c7e3dc24dd2b6f6c77d0155c6f65c990d Author: Sjoerd Simons Date: Thu Jul 2 14:49:33 2009 +0100 Add a test for parsing the vcard namespace tests/wocky-xmpp-reader-test.c | 46 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) commit fa10cb3d750f503492aace17320761f95202aa26 Author: Jonny Lamb Date: Thu Jul 2 14:57:31 2009 +0100 wocky_xmpp_stanza_build's spec argument should be of type WockyBuildTag, not guint. Signed-off-by: Jonny Lamb wocky/wocky-xmpp-stanza.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 33e5bf5b1f9597322b671761d6d2bd79f09e43b7 Author: Jonny Lamb Date: Thu Jul 2 12:52:25 2009 +0100 Updated .gitignore. Signed-off-by: Jonny Lamb .gitignore | 1 + 1 file changed, 1 insertion(+) commit e27678c589afa336366bfa02dd15679285648ba3 Author: Jonny Lamb Date: Thu Jul 2 12:09:14 2009 +0100 Add some porter tests to test handling unset from attribute stanzas. Signed-off-by: Jonny Lamb tests/wocky-porter-test.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) commit c6dc106c85ea2931b52d426e81ce2e9db7244bf7 Author: Jonny Lamb Date: Thu Jul 2 11:10:07 2009 +0100 Don't discard the stanza if the from attribute is missing. Signed-off-by: Jonny Lamb wocky/wocky-porter.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) commit 43d8fcaae57d93ea2fb3dc0a8939dce0b068d392 Author: Guillaume Desmottes Date: Thu Jul 2 11:39:04 2009 +0100 send_cancelled_cb: gio convention is to complete cancel callback in idle wocky/wocky-porter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit bf24846fa5d8220cdfe5b451c97ffe5cf808f628 Merge: 2f77013 9d41bac Author: Guillaume Desmottes Date: Wed Jul 1 15:36:14 2009 +0100 Merge branch 'master' of git+ssh://git.collabora.co.uk/git/wocky commit 2f77013fb3f9a56b7d698969dcfffa8e3d4f14ea Author: Guillaume Desmottes Date: Wed Jul 1 14:35:33 2009 +0100 wocky_porter_send_iq_finish returns a reffed stanza tests/wocky-porter-test.c | 1 + wocky/wocky-porter.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) commit 9d41bac3ef7bc2932cf0b6b6c7fa47615362d7d4 Author: Jonny Lamb Date: Wed Jul 1 15:16:16 2009 +0100 Add flymake rules to wocky Makefiles. Signed-off-by: Jonny Lamb tools/Makefile.am | 3 ++- tools/flymake.mk | 4 ++++ wocky/Makefile.am | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) commit 8828e61ed4d33c48ba8457c9de296b783de865dc Author: Jonny Lamb Date: Sat Apr 25 15:22:28 2009 +0100 Shave wocky's build. Signed-off-by: Jonny Lamb .gitignore | 3 ++ autogen.sh | 9 +++++ configure.ac | 4 ++ m4/Makefile.am | 3 +- m4/shave.m4 | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++ shave-libtool.in | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ shave.in | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/Makefile.am | 3 +- tools/shave.mk | 1 + wocky/Makefile.am | 12 +++--- 10 files changed, 348 insertions(+), 7 deletions(-) commit 356c1ab206aa8a84e2635d170ca9ba2bb3e7a433 Author: Guillaume Desmottes Date: Tue Jun 30 17:49:00 2009 +0100 wocky-xmpp-connection-test: add test_recv_simple_message_in_one_chunk tests/wocky-xmpp-connection-test.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) commit 32395928ff99abc56083896e7d6ac8d0d4e743a7 Author: Guillaume Desmottes Date: Wed Jul 1 10:24:03 2009 +0100 use input_is_closed function instead of the priv->input_closed variable wocky/wocky-xmpp-connection.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) commit 3f2743e4a0e799765ab99ba413ab9b0e9ddc6ff0 Author: Guillaume Desmottes Date: Tue Jun 30 17:32:04 2009 +0100 wocky_xmpp_connection_recv_stanza_async: succeed immediately if there is already a stanza ready wocky/wocky-xmpp-connection.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) commit 84198bf2e9198ecd864a8c334ad145f5edeea513 Author: Guillaume Desmottes Date: Mon Jun 29 13:40:51 2009 +0100 add FIXME about g_cancellable_disconnect wocky/wocky-porter.c | 2 ++ 1 file changed, 2 insertions(+) commit 371ad0e3356de514c5f780b407e94716cc0d5552 Author: Sjoerd Simons Date: Sat Jun 27 19:41:26 2009 +0100 Implement async writing to prevent race conditions tests/wocky-test-stream.c | 73 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 21 deletions(-) commit eb76a78ad499aa6a513fc567b9abd053e8a5c481 Author: Guillaume Desmottes Date: Mon Jun 29 13:34:57 2009 +0100 wocky_porter_send_async: don't connect the cancelled signal if we just sent the stanza wocky/wocky-porter.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) commit 2f32243f9db6cc4e75aec29ff1e75ee9b9fc6081 Author: Guillaume Desmottes Date: Mon Jun 29 13:29:13 2009 +0100 Use g_cancellable_connect We don't use g_cancellable_disconnect for now because it raises a deadlock in our code (#587300) wocky/wocky-porter.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) commit 569fb339bf8cfa772aae53e72c51f2c7ae24734f Author: Guillaume Desmottes Date: Mon Jun 29 12:33:57 2009 +0100 test_cancel_sent_stanza_cancelled: wocky_porter_send_finish returns success if the stanza was actually sent tests/wocky-porter-test.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) commit d34c92758323300164afd5b09a22932cc1823ae4 Author: Guillaume Desmottes Date: Mon Jun 29 12:32:02 2009 +0100 send_head_stanza: delegate the handling of the cancellable to lower layer when we start sending the stanza wocky/wocky-porter.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) commit 63fb71126dc28e35acfe30a6fa6dd09d4a19a597 Author: Guillaume Desmottes Date: Mon Jun 29 12:34:48 2009 +0100 rename WockyXmppScheduler to WockyPorter .gitignore | 2 +- tests/Makefile.am | 6 +- tests/wocky-porter-test.c | 1596 +++++++++++++++++++++++++++++++++++++ tests/wocky-test-helper.c | 20 +- tests/wocky-test-helper.h | 10 +- tests/wocky-xmpp-scheduler-test.c | 1596 ------------------------------------- wocky/Makefile.am | 4 +- wocky/wocky-debug.c | 2 +- wocky/wocky-debug.h | 2 +- wocky/wocky-porter.c | 1115 ++++++++++++++++++++++++++ wocky/wocky-porter.h | 141 ++++ wocky/wocky-xmpp-scheduler.c | 1115 -------------------------- wocky/wocky-xmpp-scheduler.h | 141 ---- 13 files changed, 2875 insertions(+), 2875 deletions(-) commit ddaea75f12183945f9ecf545d96fa644c9a82c3a Author: Guillaume Desmottes Date: Thu Jun 25 17:56:40 2009 +0100 update gitignore .gitignore | 1 + 1 file changed, 1 insertion(+) commit 1da8026c90d86494ded5cb1d50f8fb5023296d4a Author: Guillaume Desmottes Date: Thu Jun 25 17:56:19 2009 +0100 generate wocky/wocky-uninstalled.pc configure.ac | 1 + 1 file changed, 1 insertion(+) commit 8599e4f0b48f75ae8030bdd01eb1095e4a186c03 Author: Guillaume Desmottes Date: Thu Jun 25 17:56:10 2009 +0100 add wocky-uninstalled.pc.in wocky/wocky-uninstalled.pc.in | 12 ++++++++++++ 1 file changed, 12 insertions(+) commit d1f37075cb7104cedb21fdcfa81ac807d881b4e9 Author: Guillaume Desmottes Date: Thu Jun 25 17:37:20 2009 +0100 configure.ac: fix version configure.ac | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) commit bcba747e07b1f425bbd505222e80a3f1d7902a97 Author: Guillaume Desmottes Date: Fri Jun 26 10:13:13 2009 +0100 rename wocky_xmpp_scheduler_send_full_finish to wocky_xmpp_scheduler_send_finish tests/wocky-xmpp-scheduler-test.c | 14 +++++++------- wocky/wocky-xmpp-scheduler.c | 8 ++++---- wocky/wocky-xmpp-scheduler.h | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) commit 24ce2601032a498a9d87c9e0bde9cbc89f3be9ec Author: Guillaume Desmottes Date: Thu Jun 25 12:01:25 2009 +0100 add test_send_invalid_iq tests/wocky-xmpp-scheduler-test.c | 68 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) commit ac3ce92c60f34ef3a7e21cdf4260dc3615af7021 Author: Guillaume Desmottes Date: Thu Jun 25 12:01:20 2009 +0100 wocky_xmpp_scheduler_send_iq_async: check the recipient before the ID so we won't leak it if recipient is invalid wocky/wocky-xmpp-scheduler.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) commit e2145cf38054ae1ba6089a0c7dabfb472e22539a Author: Guillaume Desmottes Date: Thu Jun 25 11:44:42 2009 +0100 add test_handler_filter tests/wocky-xmpp-scheduler-test.c | 80 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) commit 946cfd90a9726928b5750c7836fc540a353263be Author: Guillaume Desmottes Date: Thu Jun 25 11:44:30 2009 +0100 handlers now return TRUE if they actually handled the stanza tests/wocky-xmpp-scheduler-test.c | 42 ++++++++++++++++++++++++++------------- wocky/wocky-xmpp-scheduler.c | 13 ++++++------ wocky/wocky-xmpp-scheduler.h | 2 +- 3 files changed, 36 insertions(+), 21 deletions(-) commit e4a63e4c97552204c4709ae756809784c7114e3b Author: Guillaume Desmottes Date: Thu Jun 25 11:23:07 2009 +0100 register the IQ reply handler as a normal handler wocky/wocky-xmpp-scheduler.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) commit 0af1eccebdb8d550970794db0db1d5fc6cbe1ee6 Author: Guillaume Desmottes Date: Thu Jun 25 11:15:15 2009 +0100 add some handler priority presets wocky/wocky-xmpp-scheduler.h | 4 ++++ 1 file changed, 4 insertions(+) commit 3c49a7e075450f6a9370cd2b03dfd17b8f1da2c0 Author: Guillaume Desmottes Date: Thu Jun 25 14:29:01 2009 +0100 wocky_xmpp_scheduler_send_iq_async: ignore preset ID attribute if there is one wocky/wocky-xmpp-scheduler.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) commit 7b3542c17531cbfc2c55f4456b63f6bf6f7a30c8 Author: Guillaume Desmottes Date: Thu Jun 25 12:11:52 2009 +0100 wocky_xmpp_scheduler_send_iq_async: check if ID isn't used yet wocky/wocky-xmpp-scheduler.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) commit 328690baea6ccb5da08fa1d48c19f4252e87968c Author: Guillaume Desmottes Date: Thu Jun 25 12:08:22 2009 +0100 use wocky_xmpp_connection_new_id instead of generating the ID in the scheduler wocky/wocky-xmpp-scheduler.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) commit 9b929be645f1578df04300b0b225e7c895968dc6 Author: Guillaume Desmottes Date: Thu Jun 25 12:05:01 2009 +0100 iq_sent_cb: check the error code instead of relying of the presence of the iq handler in the hash table wocky/wocky-xmpp-scheduler.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) commit 6222ddbc595eddbd1670371bb2df5833b171b8e4 Author: Guillaume Desmottes Date: Thu Jun 25 10:56:55 2009 +0100 test_send_iq: send an IQ without ID tests/wocky-xmpp-scheduler-test.c | 1 - 1 file changed, 1 deletion(-) commit 21be24c2d4f8f3635fca9cb42398222d55c79dbf Author: Guillaume Desmottes Date: Thu Jun 25 10:56:40 2009 +0100 wocky_xmpp_scheduler_send_iq_async: generate an ID if the IQ doesn't have one yet wocky/wocky-xmpp-scheduler.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) commit 4e7cefbf56f54a340821e4deec8a12a9b98deb63 Author: Guillaume Desmottes Date: Thu Jun 25 10:49:00 2009 +0100 test_send_iq: rely on the type of IQ instead of its id to check if we cancel it or not tests/wocky-xmpp-scheduler-test.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) commit 1e0e3a4a8fd20074f9238d584c28ff9a3c0b770a Author: Guillaume Desmottes Date: Wed Jun 24 15:13:04 2009 +0100 test that spoofed IQ replies are ignored tests/wocky-xmpp-scheduler-test.c | 8 ++++++++ 1 file changed, 8 insertions(+) commit 8cb93b4f85eb15e954bf7b11426dbaf32acfae1d Author: Guillaume Desmottes Date: Wed Jun 24 15:12:48 2009 +0100 prevent IQ reply spoofing wocky/wocky-xmpp-scheduler.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) commit 545c2dfec60df7d649d371242c5aa6a95ab47887 Author: Guillaume Desmottes Date: Wed Jun 24 15:02:41 2009 +0100 Use only the IQ ID as handler IQ key wocky/wocky-xmpp-scheduler.c | 79 ++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 51 deletions(-) commit 8bc8965e10b1fbf7c5d1fa5a29e1919fb60549ed Author: Guillaume Desmottes Date: Wed Jun 24 14:31:58 2009 +0100 add test_send_iq_error tests/wocky-xmpp-scheduler-test.c | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) commit ddc3d553cd3fd4537be871bb1c8a60551cee128c Author: Guillaume Desmottes Date: Wed Jun 24 14:31:48 2009 +0100 wocky_xmpp_scheduler_send_iq_async: raise an error if sending goes wrong wocky/wocky-xmpp-scheduler.c | 46 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) commit 109d9abcb38bad4e37003afd2129cea4263bc4fc Author: Guillaume Desmottes Date: Mon Jun 22 18:37:36 2009 +0200 test_send_iq: test cancelling an already sent IQ tests/wocky-xmpp-scheduler-test.c | 43 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) commit 4ec779993857867d868a8a6d2e5ebc5ffd91056a Author: Guillaume Desmottes Date: Mon Jun 22 18:35:34 2009 +0200 remove the iq handler when its cancellable is cancelled wocky/wocky-xmpp-scheduler.c | 47 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) commit 2b01e589b85efc858b507fe6a85a719ffcdf0278 Author: Guillaume Desmottes Date: Mon Jun 22 18:33:59 2009 +0200 handle_iq_reply: don't leak the handler_id if there is no handler wocky/wocky-xmpp-scheduler.c | 1 + 1 file changed, 1 insertion(+) commit 4610c7de8fcd5db2f91fa9cd1e5e9eed9e2e8959 Author: Guillaume Desmottes Date: Mon Jun 22 17:45:06 2009 +0200 wocky_xmpp_scheduler_send_iq_async: use a GAsyncReadyCallback as reply callback tests/wocky-xmpp-scheduler-test.c | 48 +++++++----------------------------- wocky/wocky-xmpp-scheduler.c | 51 +++++++++++++++++++++++++-------------- wocky/wocky-xmpp-scheduler.h | 12 ++++----- 3 files changed, 47 insertions(+), 64 deletions(-) commit 96b1a7ae77f5925d062f755368d6f236f66664b8 Author: Guillaume Desmottes Date: Mon Jun 22 15:04:04 2009 +0200 rename wocky_xmpp_scheduler_send_with_reply_async to wocky_xmpp_scheduler_send_iq_async tests/wocky-xmpp-scheduler-test.c | 22 +++++++++++----------- wocky/wocky-xmpp-scheduler.c | 2 +- wocky/wocky-xmpp-scheduler.h | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) commit c1bd573248240028c76a80ba1bbe5a2566c992b2 Author: Guillaume Desmottes Date: Mon Jun 22 12:05:19 2009 +0200 test to cancel an IQ reply cb tests/wocky-xmpp-scheduler-test.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) commit 721b0b8ccbcff5e2c4a7e119a9a6ce6da30f5281 Author: Guillaume Desmottes Date: Mon Jun 22 12:03:25 2009 +0200 Don't call the IQ reply callback if it has been cancelled wocky/wocky-xmpp-scheduler.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) commit f62c98d0a19a8adf497c5f8c8340f5dcbd284a60 Author: Guillaume Desmottes Date: Thu Jun 18 17:20:13 2009 +0100 add test_send_with_reply tests/wocky-xmpp-scheduler-test.c | 97 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) commit 483aaf0df8f1ab497eb542252e254c9f94f2111c Author: Guillaume Desmottes Date: Thu Jun 18 17:29:14 2009 +0100 Implement wocky_xmpp_scheduler_send_with_reply_async wocky/wocky-xmpp-scheduler.c | 134 +++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-scheduler.h | 14 +++++ 2 files changed, 148 insertions(+) commit 484ce52850f6600d52074110ccebb2640564438a Author: Guillaume Desmottes Date: Thu Jun 25 14:23:36 2009 +0100 add test_set_attribute tests/wocky-xmpp-node-test.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) commit f52003a111d3b82d8e63b0eef88e0507f5f39cba Author: Guillaume Desmottes Date: Thu Jun 25 14:23:30 2009 +0100 wocky_xmpp_node_set_attribute_n_ns: remove old attribute if needed wocky/wocky-xmpp-node.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) commit 110567f60b21ce9edb85d4e5897ddb3e9bb65374 Author: Guillaume Desmottes Date: Thu Jun 25 14:22:43 2009 +0100 wocky-xmpp-node: factor out attribute_free wocky/wocky-xmpp-node.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) commit 933bc0eae3bd039207dd33a1e6c4e8144f391aab Author: Guillaume Desmottes Date: Thu Jun 25 14:01:31 2009 +0100 test_node_equal: remove useless parenthesis tests/wocky-xmpp-node-test.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit a9f0ba9ddf5bebbe3603425ed73c002be6be0332 Author: Guillaume Desmottes Date: Thu Jun 25 13:56:42 2009 +0100 fix typo in test name tests/wocky-xmpp-node-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit a786cdf413f3c8c850520d7fee4b2886bb7c3f0b Author: Guillaume Desmottes Date: Wed Jun 24 13:21:11 2009 +0100 test_cancel_sent_stanza_cancelled: don't leak the error tests/wocky-xmpp-scheduler-test.c | 1 + 1 file changed, 1 insertion(+) commit 974ff9956518fabd858bb9d70b95491ef6139339 Author: Guillaume Desmottes Date: Wed Jun 24 13:18:05 2009 +0100 wocky-xmpp-scheduler-test: add test_writing_error tests/wocky-xmpp-scheduler-test.c | 43 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) commit 482f36297ffbc2f513ded8ca56cbd59a6445f1ef Author: Guillaume Desmottes Date: Wed Jun 24 13:17:44 2009 +0100 add wocky_test_output_stream_set_write_error to emulate writing errors tests/wocky-test-stream.c | 21 ++++++++++++++++++++- tests/wocky-test-stream.h | 2 ++ 2 files changed, 22 insertions(+), 1 deletion(-) commit a19964c4403fdcc697f84105afc9be17e3967bab Author: Guillaume Desmottes Date: Tue Jun 23 15:10:44 2009 +0200 test wocky_xmpp_stanza_build_iq_error tests/wocky-xmpp-stanza-test.c | 59 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) commit 3a22650fa8a8055f917667089d3589c90b74a13d Author: Guillaume Desmottes Date: Tue Jun 23 15:10:24 2009 +0200 add wocky_xmpp_stanza_build_iq_error wocky/wocky-xmpp-stanza.c | 15 +++++++++++++++ wocky/wocky-xmpp-stanza.h | 3 +++ 2 files changed, 18 insertions(+) commit a3e685ea6c29d6724936835bfef48a5a54ef39bc Author: Guillaume Desmottes Date: Tue Jun 23 14:17:46 2009 +0200 test wocky_xmpp_stanza_build_iq_result tests/wocky-xmpp-stanza-test.c | 59 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) commit 892c0350e3ab8aea585da29e10bb236d7cda5754 Author: Guillaume Desmottes Date: Tue Jun 23 15:39:47 2009 +0200 add wocky-xmpp-stanza-test to tests suite .gitignore | 1 + tests/Makefile.am | 6 +++++- tests/wocky-xmpp-stanza-test.c | 19 +++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) commit c144f9005696014e325c316a8d9f3eb19d9e6126 Author: Guillaume Desmottes Date: Tue Jun 23 14:15:14 2009 +0200 add wocky_xmpp_stanza_build_iq_result wocky/wocky-xmpp-stanza.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-stanza.h | 3 +++ 2 files changed, 50 insertions(+) commit 39f0cb5ed4afff87264210d3df7af85dccc278ea Author: Guillaume Desmottes Date: Tue Jun 23 14:48:21 2009 +0200 add a regression test for wocky_xmpp_node_equal tests/wocky-xmpp-node-test.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) commit ac1e6e749cc1d7fd110b7a0506f4e31c31f344e4 Author: Guillaume Desmottes Date: Tue Jun 23 14:46:02 2009 +0200 wocky_xmpp_node_equal: check if nodes have the same number of attributes Checking if node1 has all the attributes of node0 is not enough. The nodes are different if node1 contains more attributes than node0. wocky/wocky-xmpp-node.c | 3 +++ 1 file changed, 3 insertions(+) commit 3a728b81379631f9627037e6e13a78d333361d00 Author: Guillaume Desmottes Date: Tue Jun 23 14:33:19 2009 +0200 add wocky-xmpp-node-test to tests suite .gitignore | 1 + tests/Makefile.am | 6 +++++- tests/wocky-xmpp-node-test.c | 19 +++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) commit 750c8d1db07544dc9d16e6fa13e21de4fca2adec Author: Guillaume Desmottes Date: Tue Jun 23 10:19:13 2009 +0200 add a regression test: test_cancel_sent_stanza tests/wocky-xmpp-scheduler-test.c | 60 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) commit e5feb9d157d9a4c9e2d25109b2098516da41dabf Author: Guillaume Desmottes Date: Tue Jun 23 10:16:44 2009 +0200 send_stanza_cb: elem can be NULL if the sending operation has been cancelled elem is removed from the queue when the cancellable is cancelled. So, if the user cancels the sending operation when the stanza has been sent but before send_stanza_cb is called, then elem won't be in the queue anymore. wocky/wocky-xmpp-scheduler.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) commit f52286df5a3cfe0a9304ff948e20b7a512b539f8 Author: Guillaume Desmottes Date: Mon Jun 22 18:53:53 2009 +0200 wocky-xmpp-scheduler-test: use test->cancellable tests/wocky-xmpp-scheduler-test.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) commit 909c3e39a9153c228428aec5c495e7a9c54da3f2 Author: Guillaume Desmottes Date: Mon Jun 22 18:31:53 2009 +0200 add a cancellable to test_data_t tests/wocky-test-helper.c | 3 +++ tests/wocky-test-helper.h | 1 + 2 files changed, 4 insertions(+) commit 54630fde66560b0f651e95f051adc941f7c1ae07 Author: Guillaume Desmottes Date: Tue Jun 23 10:25:07 2009 +0200 Increase the test timer 1 second was too short and timer was generally fired when running tests with valgrind. tests/wocky-test-helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 861dbe33d1b09dd9577fc952d3cca0120702f6e5 Author: Guillaume Desmottes Date: Tue Jun 23 10:22:14 2009 +0200 add myself to AUTHORS AUTHORS | 1 + 1 file changed, 1 insertion(+) commit d1ba44aa011221559143bdd54b72eaaac0dfcf0b Author: Guillaume Desmottes Date: Thu Jun 18 17:02:52 2009 +0100 close_sent_cb: check if close operation hasn't be completed yet If we receive the other side close before we finished to send yours, the close operation would be already completed. wocky/wocky-xmpp-scheduler.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) commit 706f10f27c2c78b3998ca94a00ae712d95221a79 Author: Guillaume Desmottes Date: Thu Jun 18 16:58:11 2009 +0100 add test_close_both_schedulers test helper tests/wocky-test-helper.c | 12 ++++++++++++ tests/wocky-test-helper.h | 2 ++ 2 files changed, 14 insertions(+) commit c802c013650643d3c8a9ce45906a70a6694dbdb4 Author: Guillaume Desmottes Date: Thu Jun 18 17:35:08 2009 +0100 unref the stanza in test_expected_stanza_received tests/wocky-test-helper.c | 1 + tests/wocky-xmpp-scheduler-test.c | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) commit e8d0683759fc59c4d834797c68bbc5d1f0073689 Author: Guillaume Desmottes Date: Wed Jun 17 14:30:24 2009 +0100 add test_handler_stanza tests/wocky-xmpp-scheduler-test.c | 135 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) commit 6e3d2a45d156e8a84cb850783fd48500fc49e432 Author: Guillaume Desmottes Date: Wed Jun 17 14:30:09 2009 +0100 check if stanzas match with the one passed when registering the handler wocky/wocky-xmpp-scheduler.c | 25 ++++++++++++++++++++----- wocky/wocky-xmpp-scheduler.h | 2 +- 2 files changed, 21 insertions(+), 6 deletions(-) commit 253d6a320965c178613bddb916aac86d63f88fbe Author: Guillaume Desmottes Date: Wed Jun 17 14:24:55 2009 +0100 add wocky_xmpp_node_is_superset wocky/wocky-xmpp-node.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-node.h | 3 +++ 2 files changed, 65 insertions(+) commit a14a3ab158be85b34a2aea39fadfbdb8079b2eeb Author: Guillaume Desmottes Date: Thu Jun 18 10:56:24 2009 +0100 add wocky_xmpp_stanza_build_va wocky/wocky-xmpp-stanza.c | 19 +++++++++++++++++-- wocky/wocky-xmpp-stanza.h | 9 +++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) commit a46e6125d19b7f9d7e83cc4fab1ed199e5b0a43b Author: Guillaume Desmottes Date: Wed Jun 17 15:34:10 2009 +0100 rename wocky_decode_jid arguments according to RFC's names wocky/wocky-xmpp-scheduler.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) commit fab1c3bc2ccab10d4cdc07b4ac3ade3b8b335a63 Author: Guillaume Desmottes Date: Tue Jun 16 17:47:50 2009 +0100 add test_handler_full_jid tests/wocky-xmpp-scheduler-test.c | 49 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) commit 38ed0c782d3946dfc0b644119a50ee1297c32558 Author: Guillaume Desmottes Date: Tue Jun 16 17:44:08 2009 +0100 add test_handler_bare_jid tests/wocky-xmpp-scheduler-test.c | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) commit 28731a6d72e78550918634f36070e65cd38e1f92 Author: Guillaume Desmottes Date: Tue Jun 16 17:41:36 2009 +0100 handle_stanza: filter using the from attribute if needed wocky/wocky-xmpp-scheduler.c | 53 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 4 deletions(-) commit 82e48db5f9cee80956e0e4a6248032f5c582e336 Author: Guillaume Desmottes Date: Tue Jun 16 17:48:13 2009 +0100 add expected arg to send_stanza tests/wocky-xmpp-scheduler-test.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) commit 9633251d39656ccd0dcda7093362d10b629f73b5 Merge: 1d3c7fe 0ecde94 Author: Guillaume Desmottes Date: Wed Jun 17 15:31:07 2009 +0100 Merge branch 'handlers+test-refactoring+remove' commit 1d3c7fe760dad7e5f45bcfe213b6bc96b62511f3 Merge: e79b6eb 6463811 Author: Guillaume Desmottes Date: Wed Jun 17 15:28:43 2009 +0100 Merge branch 'decode-jid' commit 6463811f41a7f96602d43f2cbd195aa4524a0851 Author: Guillaume Desmottes Date: Wed Jun 17 15:13:10 2009 +0100 wocky_decode_jid: assert that at least one output arg is not NULL wocky/wocky-utils.c | 1 + 1 file changed, 1 insertion(+) commit 790b68f5f611fb0eeb2ba0d41119d5e8d4ed9003 Author: Guillaume Desmottes Date: Wed Jun 17 15:12:22 2009 +0100 wocky_decode_jid: rename args according to RFC's names wocky/wocky-utils.c | 38 +++++++++++++++++++------------------- wocky/wocky-utils.h | 6 +++--- 2 files changed, 22 insertions(+), 22 deletions(-) commit 0ecde940fd71d366474c4f8a7033877149a0c037 Author: Guillaume Desmottes Date: Wed Jun 17 15:05:22 2009 +0100 wocky_xmpp_scheduler_unregister_handler: raise a warning if the handler is not registered tests/wocky-xmpp-scheduler-test.c | 4 +--- wocky/wocky-xmpp-scheduler.c | 8 +++++--- wocky/wocky-xmpp-scheduler.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) commit e79b6ebd998d4ee3a5142db09fadf4219730c2cc Merge: 72f1aaa 9228ca5 Author: Guillaume Desmottes Date: Wed Jun 17 14:44:46 2009 +0100 Merge branch 'handlers+test-refactoring' commit 72f1aaa92475e068851cb05363dad94a2b07bbaa Merge: f811427 1ee88a7 Author: Guillaume Desmottes Date: Wed Jun 17 14:42:14 2009 +0100 Merge branch 'handlers' commit f8114271ed5c26f1837b787c0fba3823ff45ef04 Author: Guillaume Desmottes Date: Tue Jun 16 12:42:43 2009 +0100 wocky-xmpp-scheduler: remove unused priv->sending wocky/wocky-xmpp-scheduler.c | 1 - 1 file changed, 1 deletion(-) commit 1ee88a7058f987ea4b26a6e54632c3f7989aa50e Author: Guillaume Desmottes Date: Tue Jun 16 17:53:12 2009 +0100 handle_stanza: move wocky_xmpp_stanza_get_type_info out of the for loop wocky/wocky-xmpp-scheduler.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) commit 85ea3206514c56d3262bb74ec2e75b848cb65c81 Author: Guillaume Desmottes Date: Tue Jun 16 16:47:16 2009 +0100 import wocky_decode_jid from Gabble wocky/wocky-utils.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-utils.h | 5 +++ 2 files changed, 93 insertions(+) commit 04e0f71576b6f01906ebee414f3f1b009623be83 Author: Guillaume Desmottes Date: Tue Jun 16 16:30:39 2009 +0100 add test_unregister_handler tests/wocky-xmpp-scheduler-test.c | 58 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) commit 36e3d4f7d6a1508e70dc0160dd4833d1fbc23d01 Author: Guillaume Desmottes Date: Tue Jun 16 16:30:03 2009 +0100 add wocky_xmpp_scheduler_unregister_handler wocky/wocky-xmpp-scheduler.c | 16 ++++++++++++++++ wocky/wocky-xmpp-scheduler.h | 3 +++ 2 files changed, 19 insertions(+) commit 9228ca515a7f4379c5655c8d9aab923834d8e648 Author: Guillaume Desmottes Date: Tue Jun 16 16:08:22 2009 +0100 use test_expected_stanza_received tests/wocky-xmpp-scheduler-test.c | 38 ++++---------------------------------- 1 file changed, 4 insertions(+), 34 deletions(-) commit 9ff3329b355ff03e05f951f481c5f9e737dce776 Author: Guillaume Desmottes Date: Tue Jun 16 16:07:57 2009 +0100 add test_expected_stanza_received helper tests/wocky-test-helper.c | 14 ++++++++++++++ tests/wocky-test-helper.h | 3 +++ 2 files changed, 17 insertions(+) commit 185494031ae6cf60687e652638ff00130a0be120 Author: Guillaume Desmottes Date: Tue Jun 16 16:01:29 2009 +0100 factor out send_stanza tests/wocky-xmpp-scheduler-test.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) commit ce3e2b3d4130d048ea3de65525c484ed868fe136 Author: Guillaume Desmottes Date: Tue Jun 16 15:43:17 2009 +0100 use test_close_scheduler tests/wocky-xmpp-scheduler-test.c | 41 ++++----------------------------------- 1 file changed, 4 insertions(+), 37 deletions(-) commit 3867344f20babf7920151b906eb736e7f05f23d4 Author: Guillaume Desmottes Date: Tue Jun 16 15:40:13 2009 +0100 add test_close_scheduler helper tests/wocky-test-helper.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++ tests/wocky-test-helper.h | 2 ++ 2 files changed, 56 insertions(+) commit 8ec9912ef59216ffcc871dc9f1f7e85250b067d2 Author: Guillaume Desmottes Date: Tue Jun 16 15:14:24 2009 +0100 add test_handler_priority tests/wocky-xmpp-scheduler-test.c | 113 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) commit 191a714037406c7bfa5cce73089865ced4a15d97 Author: Guillaume Desmottes Date: Tue Jun 16 14:53:56 2009 +0100 test_filter: use new API and re-enable test tests/wocky-xmpp-scheduler-test.c | 36 +++++++----------------------------- 1 file changed, 7 insertions(+), 29 deletions(-) commit 690e7579e63f8abaeef7736b48bef1852aaaf021 Author: Guillaume Desmottes Date: Tue Jun 16 14:49:36 2009 +0100 test_receive: use new API and re-enable test tests/wocky-xmpp-scheduler-test.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) commit a2d057bdbd77e02f297e1a5430fb7ddaf0f51a82 Author: Guillaume Desmottes Date: Tue Jun 16 14:54:24 2009 +0100 start to implement new handlers API wocky/wocky-xmpp-scheduler.c | 122 ++++++++++++++++++++++++++++++++++++++++++- wocky/wocky-xmpp-scheduler.h | 10 ++++ 2 files changed, 131 insertions(+), 1 deletion(-) commit 1fd895c4b547ee3c55b881491052306fa437ae95 Author: Guillaume Desmottes Date: Tue Jun 16 12:54:31 2009 +0100 rename WockyXmppSchedulerStanzaCallbackFunc to WockyXmppSchedulerHandlerFunc wocky/wocky-xmpp-scheduler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 88f4be67d489a370b81886df0bf44dc2ad9690b5 Author: Guillaume Desmottes Date: Tue Jun 16 12:42:43 2009 +0100 wocky-xmpp-scheduler: remove unused priv->sending wocky/wocky-xmpp-scheduler.c | 1 - 1 file changed, 1 deletion(-) commit ca9a5ee4fb36d2d06fb20848d298c714bdf09ab3 Author: Guillaume Desmottes Date: Tue Jun 16 12:42:05 2009 +0100 Remove old stanza filters code and disable its tests for now tests/wocky-xmpp-scheduler-test.c | 10 ++++-- wocky/wocky-xmpp-scheduler.c | 73 +-------------------------------------- wocky/wocky-xmpp-scheduler.h | 10 ------ 3 files changed, 9 insertions(+), 84 deletions(-) commit dfd4ad4f6ee9434bd53294184f9085adbf070a55 Author: Guillaume Desmottes Date: Tue Jun 16 11:53:18 2009 +0100 rename wocky_xmpp_scheduler_send_full to wocky_xmpp_scheduler_send_async tests/wocky-xmpp-scheduler-test.c | 20 ++++++++++---------- wocky/wocky-xmpp-scheduler.c | 4 ++-- wocky/wocky-xmpp-scheduler.h | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) commit 76de9c85a2245126be45dcbf3940c7cda987e4cb Author: Guillaume Desmottes Date: Tue Jun 16 11:51:03 2009 +0100 rename wocky_xmpp_scheduler_close to wocky_xmpp_scheduler_close_async tests/wocky-xmpp-scheduler-test.c | 28 ++++++++++++++-------------- wocky/wocky-xmpp-scheduler.c | 2 +- wocky/wocky-xmpp-scheduler.h | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) commit 6578ce681d98c131c768917f446ef212d6e67dee Author: Guillaume Desmottes Date: Tue Jun 9 17:13:09 2009 +0100 test sending a stanza throught a closing scheduler tests/wocky-xmpp-scheduler-test.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) commit 9fbbbcd49e1a67603cb0e73fe8719e8b82d83536 Author: Guillaume Desmottes Date: Tue Jun 9 17:07:32 2009 +0100 wocky_xmpp_scheduler_send_full: raise an error if scheduler is closing wocky/wocky-xmpp-scheduler.c | 9 +++++++++ wocky/wocky-xmpp-scheduler.h | 1 + 2 files changed, 10 insertions(+) commit 13eb2944d8880757b399a4699a19c96653723b03 Author: Guillaume Desmottes Date: Mon Jun 8 17:17:17 2009 +0100 Test if the right error is raised when trying to send a stanza through a closed scheduler tests/wocky-xmpp-scheduler-test.c | 52 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) commit 18f277e55b4cce729e3a25b018560c9c20a60b9b Author: Guillaume Desmottes Date: Tue Jun 16 11:37:55 2009 +0100 replace wocky_test_stream_read_error by wocky_test_input_stream_set_read_error tests/wocky-test-stream.c | 8 +++++--- tests/wocky-test-stream.h | 2 +- tests/wocky-xmpp-scheduler-test.c | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) commit b820dd0721ba4329f68cffea436df45a0d91db72 Author: Guillaume Desmottes Date: Mon Jun 8 17:06:41 2009 +0100 test if the remote-error signal is properly fired tests/wocky-xmpp-scheduler-test.c | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) commit ca3944ed0da521d610add494ceea597fcc276656 Author: Guillaume Desmottes Date: Tue Jun 16 11:30:18 2009 +0100 add wocky_test_stream_read_error to simulate a read error tests/wocky-test-stream.c | 18 ++++++++++++++++++ tests/wocky-test-stream.h | 2 ++ 2 files changed, 20 insertions(+) commit 7c1db745323573c073f360258296f399bf86315d Author: Guillaume Desmottes Date: Wed Jun 10 10:40:53 2009 +0100 wocky-xmpp-reader-test: use g_assert_error tests/wocky-xmpp-reader-test.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) commit 9ea7ecc262b401ee4e70816316a06c157daccad9 Author: Guillaume Desmottes Date: Wed Jun 10 10:39:52 2009 +0100 wocky-test-sasl-auth: use g_assert_error tests/wocky-test-sasl-auth.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit 6afd22825552cb8c2a22a186041f011f0cb6dad6 Author: Guillaume Desmottes Date: Wed Jun 10 10:39:01 2009 +0100 wocky-test-sasl-auth-server: use g_assert_error tests/wocky-test-sasl-auth-server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 4e59a279a10698e3bba38bb355d1d652db3a109c Author: Guillaume Desmottes Date: Wed Jun 10 10:38:10 2009 +0100 wocky-xmpp-connection-test: use g_assert_error tests/wocky-xmpp-connection-test.c | 54 +++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 27 deletions(-) commit 317733282354de459ccfa7180c979d47629a2bee Author: Guillaume Desmottes Date: Wed Jun 10 10:35:11 2009 +0100 use G_IO_ERROR_PENDING instead of WOCKY_XMPP_CONNECTION_ERROR_PENDING tests/wocky-xmpp-connection-test.c | 15 +++++---------- wocky/wocky-xmpp-connection.c | 15 +++++---------- wocky/wocky-xmpp-connection.h | 3 --- 3 files changed, 10 insertions(+), 23 deletions(-) commit c628264ae27860a76b4382170c5270b613f25b9f Author: Sjoerd Simons Date: Fri Jun 12 16:00:28 2009 +0100 tweak the close_sent_cb function for better readability wocky/wocky-xmpp-scheduler.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) commit dc0d4c95a99cf1c0ba1b9654ad4a224c398f310c Author: Guillaume Desmottes Date: Thu Jun 11 10:48:17 2009 +0100 close_sent_cb: add some comments wocky/wocky-xmpp-scheduler.c | 2 ++ 1 file changed, 2 insertions(+) commit 8081866e9583452f11695ba05467865e27ef74ab Author: Guillaume Desmottes Date: Thu Jun 11 10:45:15 2009 +0100 priv->close_result is never supposed to be NULL in close_sent_cb wocky/wocky-xmpp-scheduler.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) commit 10a60da5e5b478bc4e79015ad76aa5292b504705 Author: Guillaume Desmottes Date: Thu Jun 11 10:43:02 2009 +0100 factor out complete_close wocky/wocky-xmpp-scheduler.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) commit 8b1062aa7b4254d5cebb2e2ec6a6ec53b74961b5 Author: Guillaume Desmottes Date: Wed Jun 10 10:27:41 2009 +0100 close_sent_cb: don't complete the result twice if it has been cancelled and there was an error during sending wocky/wocky-xmpp-scheduler.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) commit d5a9b421174f769bafb8e05b917e8efb5769b07f Author: Guillaume Desmottes Date: Wed Jun 10 10:24:50 2009 +0100 close_sent_cb: no need to complete in idle wocky/wocky-xmpp-scheduler.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit dae06ab93eeb484238d50ed35d90702eec5d85d2 Author: Guillaume Desmottes Date: Tue Jun 9 17:46:45 2009 +0100 cancelling a wocky_xmpp_scheduler_close operation doesn't cancel the send_close_async We can't know if the close has been sent or not when cancelling. Don't allow to cancel it to avoid to put the scheduler in an inconsistent state. tests/wocky-xmpp-scheduler-test.c | 9 ++------- wocky/wocky-xmpp-scheduler.c | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 10 deletions(-) commit 4360ebaa119cca75152f66c0a3fe7853f2e9f0f3 Author: Guillaume Desmottes Date: Tue Jun 9 16:49:37 2009 +0100 wocky_xmpp_scheduler_dispose: tweak g_warning message wocky/wocky-xmpp-scheduler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit da3dae5f23ed9d547b18660d7141b4a3367c50c2 Author: Guillaume Desmottes Date: Tue Jun 9 16:44:45 2009 +0100 use G_IO_ERROR_PENDING instead of WOCKY_XMPP_SCHEDULER_ERROR_PENDING tests/wocky-xmpp-scheduler-test.c | 3 +-- wocky/wocky-xmpp-scheduler.c | 4 ++-- wocky/wocky-xmpp-scheduler.h | 1 - 3 files changed, 3 insertions(+), 5 deletions(-) commit c061b7df5cfa41e1df25e2c0bc05e79532f53434 Author: Guillaume Desmottes Date: Tue Jun 9 15:39:01 2009 +0100 close_sent_cb: remove useless async result temp variables wocky/wocky-xmpp-scheduler.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) commit 9d181c22ba4111142e7e169958176523f321f180 Author: Guillaume Desmottes Date: Mon Jun 8 15:02:28 2009 +0100 test cancelling wocky_xmpp_scheduler_close tests/wocky-xmpp-scheduler-test.c | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) commit d9346747d32c8b770f8893ac7a3965454862bee3 Author: Guillaume Desmottes Date: Mon Jun 8 17:02:17 2009 +0100 don't set local_closed if the cancel operation has been closed wocky/wocky-xmpp-scheduler.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit cf77235237b1533019a38f6a804c1da619c21f81 Author: Guillaume Desmottes Date: Mon Jun 8 15:01:35 2009 +0100 wocky_xmpp_scheduler_close: add cancellable support wocky/wocky-xmpp-scheduler.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) commit 07f6bb04555518c8e5d96952677dad06f14eeaef Author: Guillaume Desmottes Date: Mon Jun 8 15:00:52 2009 +0100 close_sent_cb: don't leak the result if wocky_xmpp_connection_send_close_finish failed wocky/wocky-xmpp-scheduler.c | 1 + 1 file changed, 1 insertion(+) commit 9559b315189e16c4a11300cc99db6f3b44cc2994 Author: Guillaume Desmottes Date: Mon Jun 8 14:26:40 2009 +0100 close_sent_cb: propagate error wocky/wocky-xmpp-scheduler.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) commit b4a1e557d0d778013a355763c0126bef73905b10 Author: Guillaume Desmottes Date: Mon Jun 8 14:22:15 2009 +0100 test_close_twice: try to call wocky_xmpp_scheduler_close once the scheduler has been closed tests/wocky-xmpp-scheduler-test.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) commit e2f131deb2bd55b4e0964fd66ae521384281cd10 Author: Guillaume Desmottes Date: Mon Jun 8 14:21:50 2009 +0100 wocky_xmpp_scheduler_close: raise an error if already closed wocky/wocky-xmpp-scheduler.c | 14 ++++++++++++-- wocky/wocky-xmpp-scheduler.h | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) commit 5ee041e5a80d9d9e1e417efdc05e46afe900ae7d Author: Guillaume Desmottes Date: Mon Jun 8 14:06:42 2009 +0100 test if wocky_xmpp_scheduler_close can be closed after the remote connection has been closed tests/wocky-xmpp-scheduler-test.c | 5 +++++ 1 file changed, 5 insertions(+) commit a8366339ae38cc591713f15f16beca83d9b95c64 Author: Guillaume Desmottes Date: Mon Jun 8 14:11:06 2009 +0100 wocky_xmpp_scheduler_close: don't wait for other side's closing if it has already been closed wocky/wocky-xmpp-scheduler.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) commit 16fe7d66d331c02fff883a4168543ffa75f72f85 Author: Guillaume Desmottes Date: Mon Jun 8 13:07:25 2009 +0100 add priv->remote_closed telling us if the remote connection has been closed wocky/wocky-xmpp-scheduler.c | 2 ++ 1 file changed, 2 insertions(+) commit 8068686bbf5a093c5743c9eb07ff7b2e4b8cad78 Author: Guillaume Desmottes Date: Mon Jun 8 12:44:41 2009 +0100 test remote-closed signal tests/wocky-xmpp-scheduler-test.c | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) commit f9328d93da37d679e5f464369cf391abd3117306 Author: Guillaume Desmottes Date: Mon Jun 8 12:28:49 2009 +0100 Fire remote-error signal when something goes wrong when receiving stanza wocky/wocky-xmpp-scheduler.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) commit 6419950e848c165a429ebe178fc336ae3f9f9db9 Author: Guillaume Desmottes Date: Mon Jun 8 12:13:17 2009 +0100 fire remote-closed signal when peer closed his XMPP connection wocky/wocky-xmpp-scheduler.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) commit b45709b2fddefed7eb534247d445ca6c8120484c Author: Guillaume Desmottes Date: Mon Jun 8 12:04:08 2009 +0100 wocky_xmpp_scheduler_start: don't assert if sched has already been started wocky/wocky-xmpp-scheduler.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit b44a76804e7af23cdc11bf23ed58cf7351733bd1 Author: Guillaume Desmottes Date: Mon Jun 8 11:40:27 2009 +0100 send_stanza_cb: cancel all pending sending operations if sending failed wocky/wocky-xmpp-scheduler.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) commit 063a4d203093d14d95b0a3f2c56e22d0d0accc59 Author: Guillaume Desmottes Date: Mon Jun 8 11:28:27 2009 +0100 wocky_xmpp_scheduler_finalize: assert than the queue is empty Queue elements have a ref on the scheduler so it shouldn't be destroyed while the queue is not empty. wocky/wocky-xmpp-scheduler.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) commit b14c17a79d993e42ec1301c28f6c1e6e30e87282 Author: Guillaume Desmottes Date: Mon Jun 8 10:34:43 2009 +0100 display a warning when disposing a not closed scheduler wocky/wocky-xmpp-scheduler.c | 1 + 1 file changed, 1 insertion(+) commit 866e4c2d586e1f439a1aa1ab57661103369704c5 Author: Guillaume Desmottes Date: Mon Jun 8 10:32:29 2009 +0100 unref and set to NULL receive_cancellable as soon we stop reading wocky/wocky-xmpp-scheduler.c | 6 ++++++ 1 file changed, 6 insertions(+) commit d77c713f7435de9465a34e261125c007848fa3cb Author: Guillaume Desmottes Date: Fri Jun 5 17:00:45 2009 +0100 test if the right error is raised when trying to close the scheduler twice tests/wocky-xmpp-scheduler-test.c | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) commit e1fadaf363890ea429665fe01ecd5449a40052ed Author: Guillaume Desmottes Date: Fri Jun 5 17:00:23 2009 +0100 raise an error if wocky_xmpp_scheduler_close is called twice wocky/wocky-xmpp-scheduler.c | 12 +++++++++--- wocky/wocky-xmpp-scheduler.h | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) commit d5774f48d3636ac3203a650da681fc8727a7cfd6 Author: Guillaume Desmottes Date: Fri Jun 5 16:36:30 2009 +0100 test if the right error is raised when trying to close a not started scheduler tests/wocky-xmpp-scheduler-test.c | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) commit a344fbd5dc64b192b2993bfcb8f2e398fec05fa3 Author: Guillaume Desmottes Date: Fri Jun 5 16:33:03 2009 +0100 wocky_xmpp_scheduler_close: raise an error if scheduler has not been started wocky/wocky-xmpp-scheduler.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) commit 23dd4eae609c6d50a102086ab127a156b10e4ac1 Author: Guillaume Desmottes Date: Fri Jun 5 16:31:56 2009 +0100 add WOCKY_XMPP_SCHEDULER_ERROR wocky/wocky-xmpp-scheduler.c | 18 ++++++++++++++++++ wocky/wocky-xmpp-scheduler.h | 14 ++++++++++++++ 2 files changed, 32 insertions(+) commit 06fccf9b94869a4df5651cf63b948526886c63e9 Author: Guillaume Desmottes Date: Fri Jun 5 16:17:54 2009 +0100 create receive_cancellable when scheduler is started Calling _start more than once doesn't make sense and that way we can use the cancellable to check if the scheduler has been started or not. wocky/wocky-xmpp-scheduler.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit e9329271e5b7d95c7eaf9d083b9751d837c89d99 Author: Guillaume Desmottes Date: Fri Jun 5 15:57:19 2009 +0100 test if the send queue is flushed before closing the connection tests/wocky-xmpp-scheduler-test.c | 87 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) commit 4fd21899a087a3b165ea7f19596f759adf861985 Author: Guillaume Desmottes Date: Fri Jun 5 15:56:56 2009 +0100 flush the sending queue before closing the connection wocky/wocky-xmpp-scheduler.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) commit fc32475f8cbc9941762d70bfec77eb879b3dbb54 Author: Guillaume Desmottes Date: Fri Jun 5 15:53:55 2009 +0100 xmpp-scheduler: include wocky-debug.h wocky/wocky-xmpp-scheduler.c | 3 +++ 1 file changed, 3 insertions(+) commit 189b3e115f656d3858b4970aa779e60f7690a8b9 Author: Guillaume Desmottes Date: Fri Jun 5 15:51:06 2009 +0100 add xmpp-scheduler debug domain wocky/wocky-debug.c | 1 + wocky/wocky-debug.h | 1 + 2 files changed, 2 insertions(+) commit c3aa6ef4804fd7a074fa933b3891b2403b0ea471 Author: Guillaume Desmottes Date: Tue Jun 9 15:21:42 2009 +0100 stanza_received_cb: no need to store the async result in a temp variable wocky/wocky-xmpp-scheduler.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) commit 9f4ce3ea9fcdad4b0460b0210523f0a35c93496f Author: Guillaume Desmottes Date: Fri Jun 5 12:16:57 2009 +0100 test filters tests/wocky-xmpp-scheduler-test.c | 103 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) commit cc92cf455aaf6f5f3ab9e9c4d1fc87bbf99d00c4 Author: Guillaume Desmottes Date: Fri Jun 5 12:01:05 2009 +0100 test_receive: close the connections tests/wocky-xmpp-scheduler-test.c | 67 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) commit 17a75b1c0be207e69b37f4ba762e932a59e7d339 Author: Guillaume Desmottes Date: Fri Jun 5 12:00:33 2009 +0100 Implement simple and incomplete wocky_xmpp_scheduler_close wocky/wocky-xmpp-scheduler.c | 76 +++++++++++++++++++++++++++++++++++++++++++- wocky/wocky-xmpp-scheduler.h | 10 ++++++ 2 files changed, 85 insertions(+), 1 deletion(-) commit 6d74ea1811f57ce2cab7f2501998c489da8996c3 Author: Guillaume Desmottes Date: Fri Jun 5 11:57:34 2009 +0100 add test_open_both_connections() helper tests/wocky-test-helper.c | 33 ++++++++++++++++++++++++++++----- tests/wocky-test-helper.h | 2 ++ 2 files changed, 30 insertions(+), 5 deletions(-) commit cd841cc83f95d52b9516181ea4ee98191a079d41 Author: Guillaume Desmottes Date: Tue Jun 2 18:19:22 2009 +0100 test stanza receiving tests/wocky-xmpp-scheduler-test.c | 50 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) commit 13ed721929cebc8bf2ce93ae0caf6953d831b18f Author: Guillaume Desmottes Date: Tue Jun 2 18:19:07 2009 +0100 xmpp-scheduler: implement receiving wocky/wocky-xmpp-scheduler.c | 137 +++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-scheduler.h | 17 ++++++ 2 files changed, 154 insertions(+) commit 7f1b7c2605ebec8634685b73ec9673c39d5d92d5 Author: Guillaume Desmottes Date: Thu Jun 4 10:46:09 2009 +0100 wocky-xmpp-connection-test: test cancelling wocky_xmpp_connection_recv_stanza_async tests/wocky-xmpp-connection-test.c | 46 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) commit 0607cf05c67c16e7ff4d1017f6008d904767a864 Author: Guillaume Desmottes Date: Thu Jun 4 10:45:43 2009 +0100 implement cancellable support in wocky_test_input_stream_read_async tests/wocky-test-stream.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) commit 6da1de42742ad4ed326a9d9f92f73dd348bcc4da Author: Guillaume Desmottes Date: Thu Jun 4 17:28:29 2009 +0100 rename wocky_test_input_stream_data_available to _try_read and use it in _read_async tests/wocky-test-stream.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) commit 279ce500d54bb707c0d195d83ef546081891c80b Author: Guillaume Desmottes Date: Thu Jun 4 17:14:02 2009 +0100 wocky_test_stream_init: pass associated input_stream to output_data_written_cb tests/wocky-test-stream.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) commit 19eda286d9a31a7d97d8471558ffb2cd8ec007d8 Author: Guillaume Desmottes Date: Wed Jun 3 15:17:03 2009 +0100 TestStream: call wocky_test_input_stream_data_available when the OutputStream has written data tests/wocky-test-stream.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) commit 36b6a164f22272b8e830d5da7c405fa63ace641a Author: Guillaume Desmottes Date: Wed Jun 3 15:16:29 2009 +0100 TestInputStream: implement async reading tests/wocky-test-stream.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) commit fcdf24ef1cdcb16fffef6c85e0f20dceade85153 Author: Guillaume Desmottes Date: Wed Jun 3 15:14:51 2009 +0100 wocky-test-stream: add data-written signal on the TestOutputStream object tests/wocky-test-stream.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) commit ccf96d2734dc8a18ed9df3c4abc9b5e1ddb7c505 Author: Guillaume Desmottes Date: Wed Jun 3 15:53:47 2009 +0100 wait_close_cb: use g_assert_error tests/wocky-test-helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit f91e267758d7d2e8e0bc42a50033c16dfde8554f Author: Guillaume Desmottes Date: Wed Jun 3 14:55:09 2009 +0100 wocky-xmpp-scheduler-test: send one more stanza when testing sending This will ensure that all and the pending sending operations have been completed before calling test_close_connection(). tests/wocky-xmpp-scheduler-test.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) commit e280d1387a3b1b1eddce038f01fbc0d4d1e5e86e Author: Guillaume Desmottes Date: Wed Jun 3 14:05:38 2009 +0100 test_send_simple_message: use test_{open,close}_connection tests/wocky-xmpp-connection-test.c | 85 +++++++------------------------------- 1 file changed, 14 insertions(+), 71 deletions(-) commit b1d67eb9a573d2f960b93252967cc523992eb246 Author: Guillaume Desmottes Date: Wed Jun 3 13:55:29 2009 +0100 wocky-xmpp-scheduler-test: use test_{open,from}_connection from test helper tests/wocky-xmpp-scheduler-test.c | 92 +-------------------------------------- 1 file changed, 2 insertions(+), 90 deletions(-) commit 2757eb6990a14f335ad05b742057746ee5db489f Author: Guillaume Desmottes Date: Wed Jun 3 13:55:06 2009 +0100 add test_{open,close}_connection to test-helper tests/wocky-test-helper.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++ tests/wocky-test-helper.h | 4 +++ 2 files changed, 92 insertions(+) commit 8bd7be587eab9fa3de0f8037a40db0a5bd41d5fe Author: Guillaume Desmottes Date: Wed Jun 3 13:49:46 2009 +0100 wocky-xmpp-connection-test: use test helper tests/wocky-xmpp-connection-test.c | 56 ++------------------------------------ 1 file changed, 2 insertions(+), 54 deletions(-) commit 57ba9e784df0a446a22899fb189b696b0fceea5f Author: Guillaume Desmottes Date: Wed Jun 3 13:49:27 2009 +0100 wocky-xmpp-scheduler-test: use test helper tests/wocky-xmpp-scheduler-test.c | 67 +-------------------------------------- 1 file changed, 1 insertion(+), 66 deletions(-) commit 93a6e922356bffa109a3972771f40e943ed1bf07 Author: Guillaume Desmottes Date: Wed Jun 3 13:49:00 2009 +0100 add wocky-test-helper.[ch] tests/Makefile.am | 2 ++ tests/wocky-test-helper.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++ tests/wocky-test-helper.h | 32 ++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) commit 881ba77b4d37fea577be5c5c26106d3438226d84 Author: Guillaume Desmottes Date: Tue Jun 2 18:34:55 2009 +0100 wocky-xmpp-scheduler-test: factor out close_connection() tests/wocky-xmpp-scheduler-test.c | 98 +++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 40 deletions(-) commit 9794e11ccb9db7e300ee5a816be0022b5d56beba Author: Guillaume Desmottes Date: Tue Jun 2 17:28:56 2009 +0100 wocky-xmpp-scheduler-test: factor out open_connection() tests/wocky-xmpp-scheduler-test.c | 105 +++++++++++++++++++++----------------- 1 file changed, 59 insertions(+), 46 deletions(-) commit df77c35236f9131f1a51e048a939354f963058c9 Author: Guillaume Desmottes Date: Tue Jun 2 16:22:43 2009 +0100 store the self pointer in sending_queue_elem That way we don't have to use another struct as callback data when connecting the cancelled signal. wocky/wocky-xmpp-scheduler.c | 45 +++++++++++--------------------------------- 1 file changed, 11 insertions(+), 34 deletions(-) commit 03eb19c97cdf48766bea07263f91ebb3561d38fc Author: Guillaume Desmottes Date: Tue Jun 2 16:20:15 2009 +0100 send_cancelled_cb: use remove instead of remove_all as the same elem isn't expected to be more than once in the queue wocky/wocky-xmpp-scheduler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 16ca9b6e59e7a2ec770dc83fa42e1f3d915bd64c Author: Guillaume Desmottes Date: Tue Jun 2 16:07:42 2009 +0100 send_received_open_cb: use g_assert instead of g_assert_not_reached tests/wocky-xmpp-scheduler-test.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) commit 189ffc2a988d4642a486e662606709d1aab0f2ab Author: Guillaume Desmottes Date: Tue Jun 2 16:06:38 2009 +0100 check that we receive the right error when waiting for the disconnection tests/wocky-xmpp-scheduler-test.c | 3 +++ 1 file changed, 3 insertions(+) commit e74d11f7d165fdea8accc4554afd61c49139c097 Author: Guillaume Desmottes Date: Tue Jun 2 16:04:21 2009 +0100 wocky-xmpp-scheduler-test.c: move misleading comment tests/wocky-xmpp-scheduler-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 8f03cf617138cd1929fe0045c04e34fc0125a828 Author: Guillaume Desmottes Date: Tue Jun 2 16:00:10 2009 +0100 wocky_xmpp_scheduler_send_full_finish: check if result is valid wocky/wocky-xmpp-scheduler.c | 3 +++ 1 file changed, 3 insertions(+) commit 251b9f66cd0408e7c74c2389b4b180385fd24630 Author: Guillaume Desmottes Date: Tue Jun 2 15:54:52 2009 +0100 rename sending_queue_elt to sending_queue_elem wocky/wocky-xmpp-scheduler.c | 87 ++++++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 43 deletions(-) commit 418af4933a5d9ca2e819188b399707f3eb4e4a82 Author: Guillaume Desmottes Date: Tue Jun 2 14:53:16 2009 +0100 send_stanza_cb: check wocky_xmpp_connection_send_stanza_finish return value wocky/wocky-xmpp-scheduler.c | 8 ++++++++ 1 file changed, 8 insertions(+) commit 637da6dcc942c231d5d2049c8906052d122998ac Author: Guillaume Desmottes Date: Tue Jun 2 14:13:09 2009 +0100 test cancelling a stanza before it has been sent tests/wocky-xmpp-scheduler-test.c | 46 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) commit 477ad45c3d9f9d73c91949f5e03dce85b5137417 Author: Guillaume Desmottes Date: Tue Jun 2 14:12:40 2009 +0100 Remove stanza from the queue and cancel its sending if its cancellable is cancelled wocky/wocky-xmpp-scheduler.c | 54 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) commit 9c4069b2210c00a1dffbcd4e75598d4f0ddd0505 Author: Guillaume Desmottes Date: Tue Jun 2 11:22:11 2009 +0100 assert that we received all the expected stanzas when disposing the test tests/wocky-xmpp-scheduler-test.c | 3 +++ 1 file changed, 3 insertions(+) commit 7c7baecba968d6cc7754d135c48200dbd4daa265 Author: Guillaume Desmottes Date: Mon Jun 1 17:12:11 2009 +0100 test wocky_xmpp_scheduler_send tests/wocky-xmpp-scheduler-test.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) commit f7e7b6053cb6d464ccf42663d11d493027f4254a Author: Guillaume Desmottes Date: Mon Jun 1 17:12:00 2009 +0100 add wocky_xmpp_scheduler_send wocky/wocky-xmpp-scheduler.c | 7 +++++++ wocky/wocky-xmpp-scheduler.h | 3 +++ 2 files changed, 10 insertions(+) commit 9ab57f9b94265c493c3af98cbb7fd3fc9a9823c8 Author: Guillaume Desmottes Date: Mon Jun 1 15:54:53 2009 +0100 test wocky_xmpp_scheduler_send_full tests/wocky-xmpp-scheduler-test.c | 206 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) commit c490b404e407b8e1851ee847b4e41cfd200050ef Author: Guillaume Desmottes Date: Mon Jun 1 15:45:23 2009 +0100 Implement wocky_xmpp_scheduler_send_full wocky/wocky-xmpp-scheduler.c | 134 +++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-scheduler.h | 12 ++++ 2 files changed, 146 insertions(+) commit d8b252ece382d077e0aa98a2e49881e7251ccc76 Author: Guillaume Desmottes Date: Mon Jun 1 12:53:46 2009 +0100 add tests/wocky-xmpp-scheduler-test to .gitignore .gitignore | 1 + 1 file changed, 1 insertion(+) commit b308b15a7aac4ef0152198cb31f8cd24ddbca5c3 Author: Guillaume Desmottes Date: Mon Jun 1 12:53:00 2009 +0100 add wocky-xmpp-scheduler-test.c and test instantion of the scheduler tests/Makefile.am | 7 ++++++- tests/wocky-xmpp-scheduler-test.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) commit f0bc7751b1d5648ed16543f4511ef85f50e99adc Author: Guillaume Desmottes Date: Mon Jun 1 12:37:43 2009 +0100 add skeleton of wocky-xmpp-scheduler.[ch] wocky/Makefile.am | 4 +- wocky/wocky-xmpp-scheduler.c | 187 +++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-scheduler.h | 64 +++++++++++++++ 3 files changed, 254 insertions(+), 1 deletion(-) commit 511cfe3be6d61fc643807858a3619498e387cc4a Author: Guillaume Desmottes Date: Tue Jun 2 14:23:48 2009 +0100 Ignore lcov generated files .gitignore | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) commit 897aaa49cd6487a463ea99a6b04712130d44742b Author: Sjoerd Simons Date: Tue Jun 2 10:53:28 2009 +0100 Fix typo in comments tests/wocky-test-sasl-auth-server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit f5101174008ec502a2a053c832e6389fb3ca71dc Author: Sjoerd Simons Date: Tue Jun 2 10:51:28 2009 +0100 free the decoded response in all cases tests/wocky-test-sasl-auth-server.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit e6996af331116e2b595f52ce0ed2205c49faec1b Author: Sjoerd Simons Date: Mon Jun 1 19:22:47 2009 +0100 Propertify the sasl auth user, password, server and connection parameters The username-requested and password-requested were usually just annoying for users of the API and didn't help much as the only authentication mechanisms that are currently implemented always need a username/password anyway. Also moved server and connection up into the constructor as they should be static anyway. examples/connect.c | 15 +--- tests/wocky-test-sasl-auth.c | 22 ++---- wocky/wocky-sasl-auth.c | 158 ++++++++++++++++++++++++++++++------------- wocky/wocky-sasl-auth.h | 7 +- 4 files changed, 122 insertions(+), 80 deletions(-) commit 0f7cd832532ed56cf1d30c965ae371b05a56dbaa Author: Sjoerd Simons Date: Mon Jun 1 18:31:42 2009 +0100 Test Sasl authentication using the wrong username/password tests/wocky-test-sasl-auth-server.c | 65 +++++++++++++++++++++++++++++++++++-- tests/wocky-test-sasl-auth-server.h | 2 ++ tests/wocky-test-sasl-auth.c | 27 ++++++++++++--- 3 files changed, 86 insertions(+), 8 deletions(-) commit 80d03b583a10815518b8310f4be448e1c04c32c2 Author: Sjoerd Simons Date: Fri May 22 18:37:50 2009 +0100 Remove unused wocky_debug_stanza wocky/wocky-debug.c | 26 -------------------------- 1 file changed, 26 deletions(-) commit a3a7af80578032f008fead5f8af9fc63c1e91a60 Author: Sjoerd Simons Date: Fri May 22 18:36:59 2009 +0100 small coding style fix wocky/wocky-debug.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit df4225f312414e5c3033ac613f2577703eeeacd5 Author: Sjoerd Simons Date: Fri May 22 18:35:29 2009 +0100 Move SaslAuth to a more gio like API examples/connect.c | 37 ++++++------- tests/wocky-test-sasl-auth.c | 54 ++++++++----------- wocky/wocky-sasl-auth.c | 121 +++++++++++++++++++++++++------------------ wocky/wocky-sasl-auth.h | 18 ++++--- 4 files changed, 122 insertions(+), 108 deletions(-) commit 24ac60b3cc10c80135e9893445d14506c7f4f2dd Author: Sjoerd Simons Date: Mon May 18 17:20:58 2009 +0100 Make the example work with the latest glib/gio versions examples/connect.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) commit d00206a4b16948abfbd9f21a370963fedbd4e3bd Author: Sjoerd Simons Date: Mon May 18 17:20:31 2009 +0100 Make the example a bit more friendly to use examples/connect.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) commit d920590317e61e13d326bf01f480c0fce8521378 Author: Sjoerd Simons Date: Fri May 15 17:35:37 2009 +0100 Add ability to generate code coverage statistics Makefile.am | 3 +++ configure.ac | 13 +++++++++++++ 2 files changed, 16 insertions(+) commit 2790b407dca4bfa39a3a4ffe2819a2cf09311694 Author: Sjoerd Simons Date: Fri May 15 17:33:15 2009 +0100 Output all output of genhtml The output of genhtml doesn't follow a standard format, so don't try to grep into it for details. As it is, the output is pretty small and reasonably useful, so it doesn't win anything anyway rules/lcov.mak | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) commit 25098ed1acc86e0ed962f3f1f9f03418ba46dd08 Author: Emanuele Aina Date: Fri Jul 6 07:31:48 2007 +0000 Removed a redundant rule in lcov.mak 20070706073148-f974e-45ecdef81918d4d9926bd6a5faba0e09de35c82e.gz rules/lcov.mak | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) commit 44de7acc851cc1307d99f2423de5c85226fc7ecb Author: Emanuele Aina Date: Thu Jul 5 21:54:06 2007 +0000 rules/lcov.mak: remove the need for the LCOV_PATH variable 20070705215406-f974e-087116fe59a3b2f01f4e12ef470ecd5698eb638a.gz rules/lcov.mak | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) commit d0baefd87779c8a426fd21595257e0e238bd79d6 Author: Emanuele Aina Date: Tue Jul 3 19:30:08 2007 +0000 Do not use the internal copy of lcov if we cannot use the system one The history has been edited and the internal copy of lcov introduced in the "Add coverage and valgrind support for tests" patch has been deleted. Yay for using textual patches to store the history! 20070703193008-f974e-d2322b04e4566dd2b12e5b6d15a35197343ffb9c.gz rules/lcov.mak | 5 +++++ 1 file changed, 5 insertions(+) commit 6c4bb604de9f165b98cf8812774d913e33311cb9 Author: Emanuele Aina Date: Mon Jun 25 17:35:12 2007 +0000 Streamline the coverage output printed to screen to make it more useful 20070625173512-f974e-f1613c3b485bb04b984114493735cf40331a7382.gz rules/lcov.mak | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) commit 15b11ff887fae57729d1020de0cfd1010e8f7ee1 Author: Emanuele Aina Date: Mon Jun 25 09:39:16 2007 +0000 Use the variable instead of calling make directly 20070625093916-f974e-a951f658ae1ad2ae4198505fcc9a57e164d1924d.gz rules/lcov.mak | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) commit 62678cb1604cd3617072cfe5718256695e901ed6 Author: Emanuele Aina Date: Sun Jun 24 22:57:53 2007 +0000 Put the lcov output in coverage/ instead of lcov/ 20070624225753-f974e-5f129404f14e68f686a38231fddd432678232421.gz rules/lcov.mak | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) commit 6b058337d0aa472495a62e1f95ed40cf47952912 Author: Emanuele Aina Date: Sun Jun 24 21:57:11 2007 +0000 Add coverage and valgrind support for tests 20070624215711-f974e-565c5019028294ac2c333e9e863af6699abfb83f.gz rules/lcov.mak | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) commit dfcb0b2b8ca9704b6d6e571f18c4da7eeaaf38b2 Author: Emanuele Aina Date: Tue Jul 3 19:30:08 2007 +0000 Do not use the internal copy of lcov if we cannot use the system one The history has been edited and the internal copy of lcov introduced in the "Add coverage and valgrind support for tests" patch has been deleted. Yay for using textual patches to store the history! 20070703193008-f974e-d2322b04e4566dd2b12e5b6d15a35197343ffb9c.gz m4/wocky-lcov.m4 | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) commit 5f881517714b1a0b4b504174379d773749231a7e Author: Emanuele Aina Date: Tue Jun 26 13:21:54 2007 +0000 Fixed the valgrind and coverage compile options reorganizing the macro inclusion 20070626132154-f974e-1c612eaa640fd535b4ebb5b8bfc40695ff9819f5.gz m4/wocky-gcov.m4 | 57 ++++++++++++++++++++++++++++++-------------------------- m4/wocky-lcov.m4 | 12 ++++++++---- 2 files changed, 39 insertions(+), 30 deletions(-) commit 88bc0fe9e1019025221ed0849417bfcb14999568 Author: Emanuele Aina Date: Mon Jun 25 09:13:47 2007 +0000 Print 'no' when checking for the lcov executable 20070625091347-f974e-685d07ee25031df4129e60f9df4eb6fdd5ba0e84.gz m4/wocky-lcov.m4 | 1 + 1 file changed, 1 insertion(+) commit 0c314b851edc62ddff813580517b0b2dd6b4e3bf Author: Emanuele Aina Date: Mon Jun 25 09:13:06 2007 +0000 Corrected the HAVE_GCOV variable name 20070625091306-f974e-cf057c7c9978d567f3eb46a56e476f5cf4afcc75.gz m4/wocky-gcov.m4 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 75643a4870f1d97423a5006aa6768b386b0d6c2e Author: Emanuele Aina Date: Mon Jun 25 07:57:42 2007 +0000 Split the command line settings from the detection of libraries and utilities 20070625075742-f974e-6695a3b35627caa5a09411094577c68d34a60d1e.gz m4/wocky-gcov.m4 | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ m4/wocky-lcov.m4 | 22 ++++++++++++++++++++++ 2 files changed, 70 insertions(+) commit b84438c2c653c085a5acd6f5f8826e555d81a350 Author: Sjoerd Simons Date: Fri May 15 15:24:52 2009 +0100 free errors after usage tests/wocky-xmpp-connection-test.c | 11 +++++++++++ 1 file changed, 11 insertions(+) commit 3b9af1cc237749d5b375d696cd00b128a2648f89 Author: Sjoerd Simons Date: Fri May 15 15:19:08 2009 +0100 Mark the input stream as closed when the reader is in CLOSED or ERROR state wocky/wocky-xmpp-connection.c | 5 +++++ 1 file changed, 5 insertions(+) commit fb292e99a3a70fba491bdfb7685de1f100663e7c Author: Sjoerd Simons Date: Fri May 15 15:10:28 2009 +0100 Remove useles empty line wocky/wocky-xmpp-connection.c | 1 - 1 file changed, 1 deletion(-) commit ded1c661557dae3b6da5c66cc00dc0804b043154 Author: Sjoerd Simons Date: Fri May 15 15:10:12 2009 +0100 Implement WOCKY_XMPP_CONNECTION_ERROR_{IS_CLOSED,IS_OPEN} error reporting wocky/wocky-xmpp-connection.c | 213 +++++++++++++++++++++++++++++------------- 1 file changed, 148 insertions(+), 65 deletions(-) commit 4fc485ff6b62487fa4c6cbf777f6197356fa73a1 Author: Sjoerd Simons Date: Fri May 15 15:08:55 2009 +0100 Add WOCKY_XMPP_CONNECTION_ERROR_{IS_CLOSED,IS_OPEN} wocky/wocky-xmpp-connection.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) commit 2d8b9ebc2de3dcc2fcbcb9d129f56ebde0132cb1 Author: Sjoerd Simons Date: Fri May 15 13:06:46 2009 +0100 Add test for _IS_CLOSED and _IS_OPEN errors from the XmppConnection tests/wocky-xmpp-connection-test.c | 247 +++++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) commit 4dae728e05ed4e7f75872323879bfb5e3e58a780 Author: Sjoerd Simons Date: Fri May 15 12:25:41 2009 +0100 Implement reporting of WOCKY_XMPP_CONNECTION_ERROR_NOT_OPEN wocky/wocky-xmpp-connection.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) commit ac98e1b3a12500e7180f18ceba288941016619e7 Author: Sjoerd Simons Date: Mon Apr 27 22:39:43 2009 +0100 Add test for WOCKY_XMPP_CONNECTION_ERROR_NOT_OPEN tests/wocky-xmpp-connection-test.c | 84 +++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) commit dbdadf768558077acae49bf7431105ac71ad1078 Author: Sjoerd Simons Date: Fri May 15 11:47:09 2009 +0100 Correctly count outstanding operation in the simple message test tests/wocky-xmpp-connection-test.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) commit ebfe07410fa3f4a832872d3518e02aab30e51f63 Author: Sjoerd Simons Date: Fri May 15 11:44:25 2009 +0100 On write errors use the correct AsyncResult wocky/wocky-xmpp-connection.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit e9295ce2d6a9c0e133c335e430153d10e7a312e5 Author: Sjoerd Simons Date: Fri May 15 11:43:31 2009 +0100 Chain up dispose to the right parent class tests/wocky-test-stream.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) commit 1697164be513289ae8ade35f389ab3ab33f35601 Author: Sjoerd Simons Date: Fri May 15 11:43:00 2009 +0100 Remove useless finalize tests/wocky-test-stream.c | 9 --------- 1 file changed, 9 deletions(-) commit 80e8d2e23db228df1bd813fb56a686882688f924 Author: Sjoerd Simons Date: Fri May 15 11:42:07 2009 +0100 GIOStream is now a base-class instead of an interface GIOStream got merged into glib as a base-class instead of an interface. Make WockyTestIOStream implement the basic functionality of this class and also move the ownership of the input and output streams from WockyTestStream to WockyTestIoStream for more correct refcounting tests/wocky-test-stream.c | 52 ++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 28 deletions(-) commit 4118cbe69438eaf43e61fccf9be4a7ec16a1c169 Author: Sjoerd Simons Date: Fri May 15 11:11:11 2009 +0100 get_{input,output}_stream no longer return refs wocky/wocky-xmpp-connection.c | 4 ---- 1 file changed, 4 deletions(-) commit 993b66dca1bc78ea1c2d08ba49a53a51fc97b8b6 Author: Sjoerd Simons Date: Mon Apr 27 22:27:07 2009 +0100 Implementing WockyXmppConnection pending error reporting wocky/wocky-xmpp-connection.c | 45 +++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-connection.h | 8 ++++---- 2 files changed, 49 insertions(+), 4 deletions(-) commit f5e5186be62cdf5f48a42ac021a47f1340507413 Author: Sjoerd Simons Date: Mon Apr 27 20:57:09 2009 +0200 First propagate errors, then assert validity wocky/wocky-xmpp-connection.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) commit a85cd2dfb6c6165baaa3d164a8e6ce0db362526c Author: Sjoerd Simons Date: Mon Apr 27 20:49:23 2009 +0200 Add test for WOCKY_XMPP_CONNECTION_ERROR_PENDING tests/wocky-xmpp-connection-test.c | 275 ++++++++++++++++++++++++++++++++++++- 1 file changed, 274 insertions(+), 1 deletion(-) commit a720f4473a9af3159d106fa7f8d21567bfb5075a Author: Sjoerd Simons Date: Mon Apr 27 20:48:49 2009 +0200 Add new error messages wocky/wocky-xmpp-connection.h | 9 +++++++++ 1 file changed, 9 insertions(+) commit 66cd832b07843202288ad90380d8bb436332df28 Author: Sjoerd Simons Date: Mon Apr 27 19:19:23 2009 +0200 Factor out some common test setup tests/wocky-xmpp-connection-test.c | 90 +++++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 40 deletions(-) commit bbb959af3b34fafa7a1e37e2c16b459f7d3a6453 Author: Sjoerd Simons Date: Sat Apr 25 00:56:22 2009 +0200 Get rid of the WockyXmppConnectionFlags wocky/wocky-xmpp-connection.c | 50 ++++++++++++++++++++++++++++--------------- wocky/wocky-xmpp-connection.h | 13 ----------- 2 files changed, 33 insertions(+), 30 deletions(-) commit be9bbfa3fdf7ccb9ce4902663f297b947babb3d9 Author: Sjoerd Simons Date: Sat Apr 25 00:52:36 2009 +0200 only send stanza after sending the opening has finished tests/wocky-xmpp-connection-test.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) commit 6bcae39e85b1d512a0590b7dbc7675d98d381204 Author: Sjoerd Simons Date: Mon Apr 27 15:05:40 2009 +0200 Fixed documentation style issues wocky/wocky-xmpp-connection.c | 87 ++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 43 deletions(-) commit 0848c5e67c9ef3ba999517b9d6a07cfbc940aa8f Author: Sjoerd Simons Date: Fri Apr 24 18:54:11 2009 +0100 Initial documentation for WockyXmppConnection wocky/wocky-xmpp-connection.c | 165 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 164 insertions(+), 1 deletion(-) commit 0b84315d26880bf5bd38229c99903b20b2246469 Author: Sjoerd Simons Date: Fri Apr 24 10:56:00 2009 +0100 Tweak the WockyXmppConnectionError documentation wocky/wocky-xmpp-connection.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit 7085d1caccfd7c9077e027701447fa8cf5edd100 Author: Sjoerd Simons Date: Mon Apr 27 14:21:10 2009 +0200 Fix coding style examples/connect.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) commit 97e52a67cb4b6332f09820e34e02132f4957ea60 Author: Sjoerd Simons Date: Mon Apr 27 14:20:54 2009 +0200 Run coding style checks on the example examples/Makefile.am | 5 +++++ 1 file changed, 5 insertions(+) commit c83d762891efb99196acb92d9f56baeb7d9fb2ff Author: Sjoerd Simons Date: Mon Apr 27 14:20:19 2009 +0200 Remove the useless constructor override in WockyXmppConnection wocky/wocky-xmpp-connection.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) commit ffe6fc959326b27d982143d84a1694ec6bf67856 Author: Sjoerd Simons Date: Fri Apr 24 19:27:11 2009 +0100 Fix some coding style issues wocky/wocky-xmpp-connection.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) commit d05e3a23d8f1e4da63b0ea137d003d4857b04895 Author: Sjoerd Simons Date: Thu Apr 23 18:22:30 2009 +0100 Port the connect exampe to the new XmppConnection API examples/connect.c | 350 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 228 insertions(+), 122 deletions(-) commit f8b084781a77bed4dfab9f8ffa96dbb870a1821b Author: Sjoerd Simons Date: Thu Apr 23 18:06:17 2009 +0100 Correct wocky_xmpp_connection_recv_open_finish prototype wocky/wocky-xmpp-connection.c | 8 ++++---- wocky/wocky-xmpp-connection.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) commit 34514ca4062838df213eca20ac7d3b3a1b889a40 Author: Sjoerd Simons Date: Thu Apr 23 15:54:31 2009 +0100 style tweak tests/wocky-test-stream.c | 1 - 1 file changed, 1 deletion(-) commit 7beb1c240936d32b5116d9f1b078f7e9c58bf548 Author: Sjoerd Simons Date: Thu Apr 23 14:58:26 2009 +0100 Port test-sasl-auth to new WockyXmppConnection api tests/wocky-test-sasl-auth-server.c | 207 +++++++++++++++++++++++++++++++----- 1 file changed, 178 insertions(+), 29 deletions(-) commit c8e54f29607ef3210f67e67c06094c2fcaf6a7df Author: Sjoerd Simons Date: Thu Apr 23 14:57:48 2009 +0100 Finish porting WockySaslAuth to new XmppConnection api wocky/wocky-sasl-auth.c | 52 ++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 24 deletions(-) commit 93067ea7fef23a1f5621136e40dc854413ba6734 Author: Sjoerd Simons Date: Thu Apr 23 13:31:08 2009 +0100 Finish porting wocky-test-sasl-auth to the new XmppConnection api tests/wocky-test-sasl-auth.c | 173 +++++++++++++++++++++++++++++++------------ 1 file changed, 125 insertions(+), 48 deletions(-) commit b6ea317ecfea560b16202465703f24900227d4f7 Author: Sjoerd Simons Date: Thu Apr 23 16:18:50 2009 +0100 Add _reset function to WockyXmppConnection wocky/wocky-xmpp-connection.c | 14 ++++++++++++++ wocky/wocky-xmpp-connection.h | 2 ++ 2 files changed, 16 insertions(+) commit b33584cb42de7d4a8f692d5b70a85189ec9446a8 Author: Sjoerd Simons Date: Thu Apr 23 16:18:35 2009 +0100 Rename wocky_xmpp_connection_send_stanza_async_finish to wocky_xmpp_connection_send_stanza_finish tests/wocky-xmpp-connection-test.c | 2 +- wocky/wocky-xmpp-connection.c | 8 ++++---- wocky/wocky-xmpp-connection.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) commit 9a8816e5cf4dee267f8c2135001749fca207fb7b Author: Sjoerd Simons Date: Wed Apr 22 13:33:32 2009 +0100 All async operation should have callbacks calling finish tests/wocky-xmpp-connection-test.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) commit 09feab449fef01e09d81cf6d2837a7bd8a399aa0 Author: Sjoerd Simons Date: Wed Apr 22 13:26:32 2009 +0100 Implement reading side of WockyXmppConnection wocky/wocky-xmpp-connection.c | 171 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 161 insertions(+), 10 deletions(-) commit f02177dd6e6e344fa2eb1afc0de7a1edac2803f7 Author: Sjoerd Simons Date: Wed Apr 22 13:25:24 2009 +0100 Send close from the input connection instead of output tests/wocky-xmpp-connection-test.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 9465c4813c86665627c6a37274cd0e9df7f46793 Author: Sjoerd Simons Date: Fri Apr 17 17:38:34 2009 +0100 Add a simple message sending test to the connection test tests/wocky-xmpp-connection-test.c | 105 ++++++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) commit e3b1514009d78478bb050f1096db8c37b856524f Author: Sjoerd Simons Date: Fri Apr 17 17:01:11 2009 +0100 Implemented the reading side of WockyXmppConnection wocky/wocky-xmpp-connection.c | 390 ++++++++++++++++++------------------------ wocky/wocky-xmpp-connection.h | 2 - 2 files changed, 171 insertions(+), 221 deletions(-) commit 7dc6e67d8972463b8732c208a6ab5f90b4a6529b Author: Sjoerd Simons Date: Fri Apr 17 16:59:48 2009 +0100 More noddy ports to the new XmppConnection api tests/wocky-test-sasl-auth-server.c | 24 +++++++++++++++++------- tests/wocky-test-sasl-auth.c | 20 +++++++++++++++----- 2 files changed, 32 insertions(+), 12 deletions(-) commit 53abbaef35d5821b8a8284824c6681f041f62793 Author: Sjoerd Simons Date: Fri Apr 17 16:59:04 2009 +0100 Port the WockyXmppConnection tests to the new API tests/wocky-xmpp-connection-test.c | 79 +++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 31 deletions(-) commit c9c3e51b010523ad1081bb61e8f3d1d97c0e163b Author: Sjoerd Simons Date: Fri Apr 17 16:58:29 2009 +0100 Noddy port of WockySaslAuth to the new API wocky/wocky-sasl-auth.c | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) commit 25b94703af119d614d9e4622632de91c3fbff31e Author: Sjoerd Simons Date: Fri Apr 17 16:56:46 2009 +0100 Add a WockyXmppConnection error domain and various codes wocky/wocky-xmpp-connection.c | 18 ++++++++++++++++++ wocky/wocky-xmpp-connection.h | 21 +++++++++++++++++++++ 2 files changed, 39 insertions(+) commit a55fb89ee72f9c18757ba776a27152bcfe4433d1 Author: Sjoerd Simons Date: Fri Apr 10 12:50:10 2009 +0100 Redo the XmppConnection API in a more push/pull manner Start of the refactored API for xmpp connection. The intention is that the XmppConnection is a very thin layer over GIOStream and the XMPP reader/writers. The actual scheduling of stanzas and a more advanced API for adding filters etc will be part of a higher level object. This patch has stubs for all the new methods with the old ones commented out so tests can compile and run but fail. wocky/wocky-xmpp-connection.c | 217 ++++++++++++++++++++++++++++++++---------- wocky/wocky-xmpp-connection.h | 74 ++++++++++---- 2 files changed, 227 insertions(+), 64 deletions(-) commit 98242d24c638f02758e7c7cbd022ccba54832f99 Author: Guillaume Desmottes Date: Fri Apr 17 15:20:54 2009 +0100 update .gitignore .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) commit 503b2ae6b7097232b81608c97ac640d6fb6862d5 Author: Sjoerd Simons Date: Fri Apr 17 15:47:14 2009 +0100 Fixed typo in documentation (availble -> available) wocky/wocky-xmpp-reader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 6ecdea5f71e7ba723896c580f08befda4526aa87 Author: Sjoerd Simons Date: Thu Apr 16 17:27:16 2009 +0100 Document that _pop_stanza transfer ownership of the stanza to the caller wocky/wocky-xmpp-reader.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit a117f2e59663d2592d9892627a3459ce5ee65df2 Author: Sjoerd Simons Date: Thu Apr 16 17:22:12 2009 +0100 test whether the reader handles a stream with no stanzas correctly Add a test to see whether the reader correctly handles a stream which doesn't include any stanzas, just open and close. At the same time test that _peek_stanza and _pop_stanza have no effect on the state changes tests/wocky-xmpp-reader-test.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) commit 02dd8e89a315b07dc7273c5057aa363c8c79415a Author: Sjoerd Simons Date: Thu Apr 16 17:21:55 2009 +0100 Also exercise wocky_xmpp_reader_peek_stanza in tests tests/wocky-xmpp-reader-test.c | 6 ++++++ 1 file changed, 6 insertions(+) commit a501050e971d32b24b8e01e572f9ce3a5be258b7 Author: Sjoerd Simons Date: Thu Apr 16 16:18:06 2009 +0100 add wocky_xmpp_reader_peek_stanza function Add a function to see if there are stanzas available from the xmpp reader. wocky/wocky-xmpp-reader.c | 19 +++++++++++++++++++ wocky/wocky-xmpp-reader.h | 1 + 2 files changed, 20 insertions(+) commit 3455033f67d333207d33abf4a92521b7bd4f8755 Author: Sjoerd Simons Date: Mon Apr 13 16:54:28 2009 +0100 Fix style issues found by coding style checker tests/wocky-test-sasl-auth.c | 2 +- tests/wocky-test-stream.h | 4 ++-- tests/wocky-xmpp-reader-test.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) commit 083a0cb3edc72c853100a3efd0c3d39c5f08be61 Author: Sjoerd Simons Date: Mon Apr 13 16:52:08 2009 +0100 Add coding style checks fo the tests tests/Makefile.am | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) commit 179db666c83486c1039e6d0f5e7b6797ec0617eb Author: Sjoerd Simons Date: Mon Apr 13 16:35:22 2009 +0100 Actuall let /xmpp-sasl/no-plain do what was intended tests/wocky-test-sasl-auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 8296cf03e838adfbbf264f8bd23efb5df7bb2c8a Author: Sjoerd Simons Date: Mon Apr 13 16:34:58 2009 +0100 Add test to refuse plain auth when that's the only one available tests/wocky-test-sasl-auth.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) commit e50dc5ba5b0f457067695e510cf3511d69defc2c Author: Sjoerd Simons Date: Mon Apr 13 16:34:17 2009 +0100 Use one test case per test tests/wocky-test-sasl-auth.c | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) commit 7a6eb9b3be535dcab90483ab77677495f8317790 Author: Sjoerd Simons Date: Mon Apr 13 16:03:17 2009 +0100 Port to gtester testing and GIO tests/wocky-test-sasl-auth.c | 74 +++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 43 deletions(-) commit 1bfe8ba0ff3652a61b2f942159d2e7d684eb13f9 Author: Sjoerd Simons Date: Mon Apr 13 16:01:46 2009 +0100 Link and build sasl tests against wocky-test-stream tests/Makefile.am | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit 4566cd7dc6c77a85467e1f09009585cb5c245f27 Author: Sjoerd Simons Date: Mon Apr 13 16:01:14 2009 +0100 Port from GibberTransport to GIOStream tests/wocky-test-sasl-auth-server.c | 7 ++++--- tests/wocky-test-sasl-auth-server.h | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) commit 8776899c3ab71cd849b96d383d7706ee241e4497 Author: Sjoerd Simons Date: Mon Apr 13 15:58:49 2009 +0100 Write the close tag to the output stream as well wocky/wocky-xmpp-connection.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) commit 5c6efc7e87382905d7e17631ba9403a83e0b16a6 Author: Sjoerd Simons Date: Mon Apr 13 15:34:16 2009 +0100 Correctly pass version point to get_object_get wocky/wocky-xmpp-connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit d53e4a2a9e3f535d67b3cf04125559313573ad77 Author: Sjoerd Simons Date: Mon Apr 13 15:32:36 2009 +0100 Correctly check connection status bitfield wocky/wocky-xmpp-connection.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 7e83807aa0a84dd83889c660619a64327fb5925d Author: Sjoerd Simons Date: Fri Apr 10 15:09:53 2009 +0100 build the sasl tests configure.ac | 14 ++++++++++++++ tests/Makefile.am | 14 ++++++++++++++ 2 files changed, 28 insertions(+) commit 36b170b45e6f305fdf88d3c3ef9ed07038c64356 Author: Guillaume Desmottes Date: Mon Dec 15 12:33:00 2008 +0000 wocky-test-sasl-auth-server: fix coding style tests/wocky-test-sasl-auth-server.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) commit 00a47a2239891bc7fa3ab2ea5146a152a7f9efcf Author: Guillaume Desmottes Date: Sat Dec 13 17:25:58 2008 +0000 wocky-test-sasl-auth: fix static functions and multi declarations tests/wocky-test-sasl-auth.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) commit a8411ef267c1c7b03a3a246e69dac6bf10f0e0e6 Author: Guillaume Desmottes Date: Mon Dec 8 14:20:01 2008 +0000 wocky-test-sasl-auth.c: workaround missing g_set_error_literal tests/wocky-test-sasl-auth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit b7e252cd7cd7874d63e1e3a09b955d3ec474204e Author: Sjoerd Simons Date: Wed Jun 4 11:31:58 2008 +0000 Coding style updates 20080604113158-93b9a-6c2078534b174e0730dfb45389ee2fbca53827a8.gz tests/wocky-test-sasl-auth-server.c | 392 +++++++++++++++++++----------------- tests/wocky-test-sasl-auth-server.h | 20 +- tests/wocky-test-sasl-auth.c | 168 +++++++++------- 3 files changed, 312 insertions(+), 268 deletions(-) commit ab2c23c715e876004869e370e098514a94a82651 Author: Sjoerd Simons Date: Wed Jun 4 10:19:29 2008 +0000 Convert tests to telepathy coding style 20080604101929-93b9a-7480a8b55e1a75d9a1797bf42412944f31513e20.gz tests/wocky-test-sasl-auth-server.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) commit 1d2ca3485c2facd14de350faa5fde2c43ee580bf Author: Sjoerd Simons Date: Mon Jul 2 07:57:48 2007 +0000 Correctly restart the xmpp connection after the auth was successfull 20070702075748-b58c9-213277df2d2cb5e38c824542ea6356c1b80f0c0a.gz tests/wocky-test-sasl-auth.c | 1 + 1 file changed, 1 insertion(+) commit e14d42ff4858dd16302e74c898cb6a41ec5e5873 Author: Emanuele Aina Date: Sun Jul 1 14:13:34 2007 +0000 Fix a memleak in the WockySaslAuth test 20070701141334-f974e-cf2e6f47799a9e6abb864d32ffa13a3ac9a8a52e.gz tests/wocky-test-sasl-auth.c | 1 + 1 file changed, 1 insertion(+) commit 1971aee01ad9e27314ecf94caead0bd5b6486827 Author: Emanuele Aina Date: Sun Jul 1 14:08:36 2007 +0000 Fix two memleaks in TestSaslAuthServer 20070701140836-f974e-f6fc59db3a7309773cc92cf5699405169e342aaf.gz tests/wocky-test-sasl-auth-server.c | 3 +++ 1 file changed, 3 insertions(+) commit 323871a91984219797f928e0e75e4eb8e6f849c3 Author: Emanuele Aina Date: Thu Jun 21 20:52:14 2007 +0000 Ported the SASL test to Check using its looping tests support 20070621205214-f974e-39f1ea943fea106ca043b43e82f42748e7031ede.gz tests/wocky-test-sasl-auth.c | 198 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) commit aa65b1798f0b1b4bef0662b5f49ee76dc57c6213 Author: Sjoerd Simons Date: Sat Mar 17 21:20:49 2007 +0000 Use sasl-test.db as filename for the sasl test 20070317212049-93b9a-74efbb70d1aab22bb0d48f5a7c69eaf2ea35bb8f.gz tests/wocky-test-sasl-auth-server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit ca6d85ec64db6d370f581c53b5b14ebf4a658810 Author: Sjoerd Simons Date: Sat Feb 17 22:10:01 2007 +0000 TestSaslAuthServer: Handle PLAIN correctly and add the possibility to simulate problems 20070217221001-93b9a-517090543e2208cdc45dec534e3a99e0eaed1096.gz tests/wocky-test-sasl-auth-server.c | 122 ++++++++++++++++++++---------------- tests/wocky-test-sasl-auth-server.h | 9 ++- 2 files changed, 77 insertions(+), 54 deletions(-) commit e021c54b3504bb3332afc8a2b8d77c0500eed964 Author: Sjoerd Simons Date: Sat Feb 17 17:06:05 2007 +0000 Add start of a sasl auth test 20070217170605-93b9a-9af2313bab57fb9611f352d47bd5cd08af3eb92d.gz tests/wocky-test-sasl-auth-server.c | 411 ++++++++++++++++++++++++++++++++++++ tests/wocky-test-sasl-auth-server.h | 64 ++++++ 2 files changed, 475 insertions(+) commit 3f75f90a58986d75e894e0600339c9ec5b37d4b0 Author: Sjoerd Simons Date: Mon Apr 13 14:50:05 2009 +0100 Small style tweaks and typo fixed to the documentation wocky/wocky-xmpp-reader.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) commit 4db621ed08f20fabb8fcd20a341aa2dc8172a100 Author: Sjoerd Simons Date: Mon Apr 13 14:17:49 2009 +0100 fix typo tests/wocky-xmpp-readwrite-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 16bc40ed81aaf2534fac9fa87e71300ed8c271a7 Author: Sjoerd Simons Date: Mon Apr 13 14:12:45 2009 +0100 Fix some small style issues tests/wocky-xmpp-readwrite-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit d2f51cb31a340fd94225c24a0d17d97357d5676e Author: Sjoerd Simons Date: Mon Apr 13 12:55:18 2009 +0100 Add a comment to clarify wocky_xmpp_reader_check_eos wocky/wocky-xmpp-reader.c | 4 ++++ 1 file changed, 4 insertions(+) commit 621da979f7488e53e6ad03a9cae3bc80a8133943 Author: Sjoerd Simons Date: Fri Apr 10 12:28:43 2009 +0100 Don't hardcode the path to valgrind tests/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit c530c1297b6decaf2f044251f4ac21e3561f8e76 Author: Sjoerd Simons Date: Fri Apr 10 11:16:35 2009 +0100 Add valgrind surpression for glib leaking tls tests/Makefile.am | 5 +++++ tests/threadlocal.supp | 8 ++++++++ 2 files changed, 13 insertions(+) commit c357dc2c1c2ec3f8ee2efb93f4ec670f0666485c Author: Sjoerd Simons Date: Thu Apr 9 19:39:35 2009 +0100 unref the input, output and cancel objects on dispose wocky/wocky-xmpp-connection.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) commit 86766769cef5c956d44edea151bc65f6dc56c181 Author: Sjoerd Simons Date: Thu Apr 9 19:39:11 2009 +0100 Don't forget to free errors tests/wocky-xmpp-reader-test.c | 3 +++ 1 file changed, 3 insertions(+) commit 9e3cbb657c7930330fcf1f6f3ceae5f9dcfcc017 Author: Sjoerd Simons Date: Thu Apr 9 19:38:55 2009 +0100 Set all the stream variables to NULL after unreffing tests/wocky-test-stream.c | 11 +++++++++++ 1 file changed, 11 insertions(+) commit fa1c63910c72c3a565da344fa90b1861f536e267 Author: Sjoerd Simons Date: Thu Apr 9 19:38:27 2009 +0100 Clear out the stanza that's in progress when disposing wocky/wocky-xmpp-reader.c | 9 +++++++++ 1 file changed, 9 insertions(+) commit ca9bc4a1918815d0d1a7383685c8d256a7b99404 Author: Sjoerd Simons Date: Thu Apr 9 19:08:56 2009 +0100 Add valgrind test targets tests/Makefile.am | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) commit af573f72676bb2b79c5acfe460ba9abc6f15ae7b Author: Sjoerd Simons Date: Thu Apr 9 18:00:42 2009 +0100 Document various enums and quarks wocky/wocky-xmpp-reader.c | 7 +++++++ wocky/wocky-xmpp-reader.h | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+) commit d54d07bad698c63c2f4fa3e1ea8ab203484581ee Author: Sjoerd Simons Date: Thu Apr 9 18:00:05 2009 +0100 Generate GObject enums wocky/Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 990176ddd27647bc73fadefbf355a0829c6b7dc7 Author: Sjoerd Simons Date: Thu Apr 9 17:23:58 2009 +0100 Document the methods wocky/wocky-xmpp-reader.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) commit d00aa6ae721c0214db3705acb2cddea1fcb951a1 Author: Sjoerd Simons Date: Thu Apr 9 17:10:30 2009 +0100 Tweak comment so gtk-doc doesn't pick it up wocky/wocky-xmpp-stanza.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 6b6f3164f2935cc7556484e7be36ac3bcddbb722 Author: Sjoerd Simons Date: Mon Apr 6 17:25:43 2009 +0100 Update copyright headers wocky/wocky-xmpp-reader.c | 4 ++-- wocky/wocky-xmpp-reader.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) commit c62484cd570c8f0903ff33e19986f92fa26848d2 Author: Sjoerd Simons Date: Mon Apr 6 17:05:34 2009 +0100 Don't reset the reader state in non-streaming mode after parsing a chunk The API user should explicitely reset the xml parser after it got the chunks it wanted out. Thus the parser shouldn't be reset after parsing a chunk of data in non-streaming mode. Fixes a bug when parsing one message in seperate chunks. wocky/wocky-xmpp-reader.c | 6 ------ 1 file changed, 6 deletions(-) commit 0eb0b3600d7c9a8377f4da24202af0616714daba Author: Sjoerd Simons Date: Mon Apr 6 17:05:02 2009 +0100 Add a test for reader states when parsing chunks tests/wocky-xmpp-reader-test.c | 43 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) commit 09b9556d682c7abab64814af9419577d0b65532a Author: Sjoerd Simons Date: Mon Apr 6 16:57:38 2009 +0100 Assert that the reader state stays open after a full stanza is parsed For consistenty, even in non-streaming mode, the reader state should stay open untill the stanza is popped. Assert this in the tests as well tests/wocky-xmpp-readwrite-test.c | 3 +++ 1 file changed, 3 insertions(+) commit 33c81ba85a4376e89ce7a4aa706110e18dfbfa81 Author: Sjoerd Simons Date: Fri Apr 3 18:58:50 2009 +0100 Fix some object leaks tests/wocky-xmpp-readwrite-test.c | 5 +++++ 1 file changed, 5 insertions(+) commit 0a86a9b15a52ce5f2858a12631ff5bec64b17e55 Author: Sjoerd Simons Date: Fri Apr 3 18:52:48 2009 +0100 Check if the queue has ended after popping the next stanza wocky/wocky-xmpp-reader.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 76910891ff10c669770facac0b7040901f0bf12e Author: Sjoerd Simons Date: Fri Apr 3 18:51:58 2009 +0100 Add some more checks tests/wocky-xmpp-readwrite-test.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) commit 67fba3d1c47b7fdd86b152e12484842b02ad7a81 Author: Sjoerd Simons Date: Fri Apr 3 18:21:44 2009 +0100 Correctly return GErrors wocky/wocky-xmpp-reader.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) commit 67b87e93fb445aed88049d05480711627f8b1759 Author: Sjoerd Simons Date: Fri Apr 3 17:00:36 2009 +0100 Add a pure reader test tests/Makefile.am | 7 ++- tests/wocky-xmpp-reader-test.c | 100 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 1 deletion(-) commit ea73a3b3457d369e845a6521fc30308a5793140c Author: Sjoerd Simons Date: Fri Apr 3 18:16:44 2009 +0100 Define an error domain for WockyXmppReader wocky/wocky-xmpp-reader.c | 12 +++++++++++- wocky/wocky-xmpp-reader.h | 8 ++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) commit 9f5b3abe87aa2eb601eeab823d9288103f6b6a01 Author: Sjoerd Simons Date: Fri Apr 3 16:39:25 2009 +0100 rename the reader state enum to WOCKY_XMPP_READER_STATE_* tests/wocky-xmpp-readwrite-test.c | 16 ++++++++++------ wocky/wocky-xmpp-connection.c | 6 +++--- wocky/wocky-xmpp-reader.c | 14 +++++++------- wocky/wocky-xmpp-reader.h | 8 ++++---- 4 files changed, 24 insertions(+), 20 deletions(-) commit 94ff0ea84b8ff022b0de84925b126e1632c5e0e3 Author: Sjoerd Simons Date: Fri Apr 3 14:35:35 2009 +0100 Remove double include tests/wocky-xmpp-readwrite-test.c | 1 - 1 file changed, 1 deletion(-) commit 0dd3acfd18f33646deeab0fb32d638ae96d16303 Author: Sjoerd Simons Date: Fri Apr 3 14:28:01 2009 +0100 g_return_if_fail if pushing bytes when the reader has closed wocky/wocky-xmpp-reader.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 485238b4180fdbf3efd312b9cf43388118ef2542 Author: Sjoerd Simons Date: Fri Apr 3 14:27:34 2009 +0100 Let the read-write test send multiple messages tests/wocky-xmpp-readwrite-test.c | 47 +++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 14 deletions(-) commit 2189612f80620c8dd9dca22216f876ba0fb9b387 Author: Sjoerd Simons Date: Fri Apr 3 13:29:09 2009 +0100 Add support for opening streams with a default language set tests/wocky-xmpp-readwrite-test.c | 5 ++--- wocky/wocky-xmpp-connection.c | 4 ++-- wocky/wocky-xmpp-reader.c | 19 +++++++++++++++++++ wocky/wocky-xmpp-writer.c | 18 ++++++++++++++++-- wocky/wocky-xmpp-writer.h | 8 ++++++-- 5 files changed, 45 insertions(+), 9 deletions(-) commit 531a7092e1daab286bb4dd3e6d209dd93a610dae Author: Sjoerd Simons Date: Fri Apr 3 13:08:52 2009 +0100 Make the WockyXmppReader API more synchronous Parsing XML is a synchronous event, blobs of data get pushed in stanzas come out. The async API that emits signals doesn't really reflect this nature and made using the reader more tedious then needed. The API is now synchronous, data gets pushed in by one function, stanzas get pulled out by another one and state is checked afterwards by another function. tests/wocky-xmpp-readwrite-test.c | 105 ++++++---------- wocky/wocky-xmpp-connection.c | 85 ++++++------- wocky/wocky-xmpp-reader.c | 253 ++++++++++++++++++++++++++------------ wocky/wocky-xmpp-reader.h | 22 +++- 4 files changed, 268 insertions(+), 197 deletions(-) commit 49ec6757939543b86f65df9ee651986cdabeee85 Author: Sjoerd Simons Date: Thu Apr 2 17:08:19 2009 +0100 Fix wording wocky/wocky-xmpp-writer.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) commit 485f5b0131d9c00a065748a56acd85cb52387967 Author: Sjoerd Simons Date: Thu Apr 2 14:01:31 2009 +0100 Convert to new coding style wocky/wocky-xmpp-writer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 6e1b39873e86498c052d5a3410fbf2dc134c631c Author: Sjoerd Simons Date: Thu Apr 2 12:48:46 2009 +0100 Document WockyXmppWriter wocky/wocky-xmpp-writer.c | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) commit e2d28e439a488a3364d6449a6ba0b193dbdbe6df Author: Sjoerd Simons Date: Thu Apr 2 12:38:16 2009 +0100 Don't return errors from wocky_xmpp_write_stanza In practise wocky_xmpp_write_stanza never returns an error. Change the function signature to reflect this and not act like it could return errors wocky/wocky-xmpp-connection.c | 6 +----- wocky/wocky-xmpp-writer.c | 5 ++--- wocky/wocky-xmpp-writer.h | 7 ++++--- 3 files changed, 7 insertions(+), 11 deletions(-) commit 7db9bf17fecd67651f5e0207f7a3601d2da77b8d Author: Sjoerd Simons Date: Wed Apr 1 19:49:45 2009 +0100 Start of documentation for xmpp-writer wocky/wocky-xmpp-writer.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) commit 72f69804e5341f983c7c1f81fb49318e0f1e5eed Author: Sjoerd Simons Date: Thu Apr 2 13:07:34 2009 +0100 Rename wocky_xmpp_node_compare to wocky_xmpp_node_equal tests/wocky-xmpp-readwrite-test.c | 4 ++-- wocky/wocky-xmpp-node.c | 4 ++-- wocky/wocky-xmpp-node.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) commit 177774e8edc054604ee214f10b72f318c399e5a0 Author: Sjoerd Simons Date: Thu Apr 2 13:02:22 2009 +0100 Unref all objects used in the test tests/wocky-xmpp-readwrite-test.c | 8 ++++++++ 1 file changed, 8 insertions(+) commit bcdad3efc3dbf1313289fc816e4e89507e089686 Author: Sjoerd Simons Date: Thu Apr 2 13:00:16 2009 +0100 Remove left-over debugging code tests/wocky-xmpp-readwrite-test.c | 2 -- 1 file changed, 2 deletions(-) commit ff9c11bb7c7de67c289dea8368e8f5becf6edf5e Author: Sjoerd Simons Date: Thu Apr 2 12:56:39 2009 +0100 Use g_strcmp0 to implement wocky_strdiff wocky/wocky-utils.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) commit 2f859786fa03aaf8b78a4df546eeb670c6fc443b Author: Sjoerd Simons Date: Thu Apr 2 12:55:45 2009 +0100 Fix coding style wocky/wocky-utils.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 0b48e635e73f93d86250915002e3480239f82d31 Author: Sjoerd Simons Date: Wed Apr 1 19:17:37 2009 +0100 Assert that open and close aren't called when not in streaming mode wocky/wocky-xmpp-writer.c | 5 +++++ 1 file changed, 5 insertions(+) commit c3157c668b7c39f799b69c2516ac700ef2a10ce1 Author: Sjoerd Simons Date: Wed Apr 1 19:17:08 2009 +0100 Add function to compare to node trees wocky/wocky-xmpp-node.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-node.h | 4 ++++ 2 files changed, 56 insertions(+) commit 92e882f8c126fb0e53c9bdb244f5a0e4f8cabe2e Author: Sjoerd Simons Date: Wed Apr 1 19:16:14 2009 +0100 If a new child doesn't have a specified namespace, use the parent namespace wocky/wocky-xmpp-node.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) commit 821d4248f8778e4dbe1f0286f4146eaa53110774 Author: Sjoerd Simons Date: Wed Apr 1 19:15:22 2009 +0100 Fix typo wocky/wocky-xmpp-writer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 8a4e1fa27082fef9bfd9ef53cdf3a900b29f538e Author: Sjoerd Simons Date: Wed Apr 1 19:14:18 2009 +0100 Set namespaces for all stanza types wocky/wocky-xmpp-stanza.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) commit 748d7a750638a9a94ad3eeaef6cc7fc5fa674df9 Author: Sjoerd Simons Date: Wed Apr 1 19:13:41 2009 +0100 Add jabber:client namespace wocky/wocky-namespaces.h | 3 +++ 1 file changed, 3 insertions(+) commit e8480c3bb2150032594b5f4fce327f76e59b6548 Author: Sjoerd Simons Date: Wed Apr 1 19:12:45 2009 +0100 Add a small test just to test the reader and the writer tests/Makefile.am | 5 +- tests/wocky-xmpp-readwrite-test.c | 159 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+), 1 deletion(-) commit 60aa14017e59c6d4a6a6a8b38084df7d4401e436 Author: Sjoerd Simons Date: Wed Apr 1 19:11:58 2009 +0100 Add some utilities wocky/Makefile.am | 2 ++ wocky/wocky-utils.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-utils.h | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) commit fe48d0aa1516fc2923c162073bfc6d2e195d1fed Author: Sjoerd Simons Date: Tue Mar 31 20:11:57 2009 +0100 Add streaming-mode construct time property wocky/wocky-xmpp-writer.c | 78 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 69 insertions(+), 9 deletions(-) commit 83a2c296c787e2512834ed56b21f29639208e4c8 Author: Sjoerd Simons Date: Wed Apr 1 13:58:28 2009 +0100 Fallback to connecting to the server directly on port 5222 if srv resolving fails examples/connect.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 9 deletions(-) commit 635f92483e9ce1b965b759af2ee6c4b1f27bd5b2 Author: Sjoerd Simons Date: Tue Mar 31 18:49:53 2009 +0100 Add gtkdoc infrastructure Makefile.am | 2 +- autogen.sh | 2 + configure.ac | 4 ++ docs/Makefile.am | 1 + docs/reference/Makefile.am | 94 ++++++++++++++++++++++++++++++++++++++++++++++ docs/reference/wocky.types | 11 ++++++ 6 files changed, 113 insertions(+), 1 deletion(-) commit 19a946d9e9346b3ee751d9f4091f5525eed61b3c Author: Sjoerd Simons Date: Mon Mar 30 12:48:52 2009 +0100 Add LGPL 2.1 as COPYING file COPYING | 510 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 510 insertions(+) commit 68b661d09d36e9e4a87523625f69c29cbefcb561 Author: Sjoerd Simons Date: Mon Mar 30 12:45:07 2009 +0100 Add a basic gitignore file .gitignore | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) commit 906848ae00fe8be9871aac376c3b4be24c6424a2 Author: Sjoerd Simons Date: Fri Mar 27 15:36:29 2009 +0000 Ignore eof and cancelled callbacks wocky/wocky-xmpp-connection.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) commit e1ab4307a71d28a83c5762d335a7faaba8fbe98d Author: Sjoerd Simons Date: Fri Mar 27 14:40:28 2009 +0000 unref the connection the stream tests/wocky-xmpp-connection-test.c | 3 +++ 1 file changed, 3 insertions(+) commit 66935908eb1fc342fdd24b8d8089ed8583059d2a Author: Sjoerd Simons Date: Fri Mar 27 14:38:16 2009 +0000 Ref the async queue in both input and output and end the stream when the writing end is disposed tests/wocky-test-stream.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) commit c19b402c8320e60a0035d1c019eb94c18bbaef95 Author: Sjoerd Simons Date: Fri Mar 27 12:49:58 2009 +0000 Unref objects after usage tests/wocky-xmpp-connection-test.c | 5 +++++ 1 file changed, 5 insertions(+) commit 0eeadab870129450d8930f3522536c40f1eecba7 Author: Sjoerd Simons Date: Fri Mar 27 12:20:30 2009 +0000 Add missing space tests/wocky-test-stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit e59f23eed6f8021e175abf5f78b8f3c9c19c596f Author: Sjoerd Simons Date: Thu Mar 26 18:59:12 2009 +0000 Use gtester and generate test resports tests/Makefile.am | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) commit 1469bdcce4b6d788b7d1a1c116cc5106926b8e15 Author: Sjoerd Simons Date: Thu Mar 26 18:58:52 2009 +0000 put libwocky.la in LDADD instead of AM_LDFLAGS tests/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 65b84717f074344a57a6d7599fe64757428c22f3 Author: Sjoerd Simons Date: Thu Mar 26 18:57:23 2009 +0000 Use a hardcoded message and add a timeout tests/wocky-xmpp-connection-test.c | 102 +++++++++++++++---------------------- 1 file changed, 40 insertions(+), 62 deletions(-) commit b0acae0cc7d82cf023b0c8a516ee9d63a70f4f90 Author: Sjoerd Simons Date: Thu Mar 26 16:52:00 2009 +0000 Port to WockTestStream tests/wocky-xmpp-connection-test.c | 52 ++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 19 deletions(-) commit 537f300bc4ce02322b805689d108cd1b9d4ef883 Author: Sjoerd Simons Date: Thu Mar 26 16:50:48 2009 +0000 Implement a test stream tests/Makefile.am | 3 +- tests/wocky-test-stream.c | 356 ++++++++++++++++++++++++++++++++++++++++++++++ tests/wocky-test-stream.h | 69 +++++++++ 3 files changed, 427 insertions(+), 1 deletion(-) commit 7ac2ea742ac94923973854ef46b29aa8c0222700 Author: Sjoerd Simons Date: Thu Mar 26 16:50:00 2009 +0000 Compile against libwocky tests/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit a16675a5f38148f4d0cffe1da8d5217b3946dd6e Author: Sjoerd Simons Date: Thu Mar 26 16:49:16 2009 +0000 Define test programs tests/Makefile.am | 1 + 1 file changed, 1 insertion(+) commit 2da6b78091d5a947ee37523ce55aacbe3c061d34 Author: Sjoerd Simons Date: Thu Mar 26 11:11:30 2009 +0000 Remove usueless debugging wocky/wocky-xmpp-connection.c | 2 -- 1 file changed, 2 deletions(-) commit 1fac6a540b046c7f3e9292a758813682df05c8a3 Author: Sjoerd Simons Date: Tue Mar 24 17:02:01 2009 +0000 Move to GTest tests/wocky-xmpp-connection-test.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) commit d7407e5cc8b2d3916904cf27a778fb4ebaf1f89b Author: Sjoerd Simons Date: Tue Mar 24 17:01:35 2009 +0000 Build the xmpp connection test Makefile.am | 2 +- configure.ac | 1 + tests/Makefile.am | 9 +++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) commit 449e09a23fda76464cc52d2c1077d8c0a15b3ca9 Author: Guillaume Desmottes Date: Mon Dec 15 12:34:01 2008 +0000 wocky-xmpp-connection-test: fix coding style tests/wocky-xmpp-connection-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit e1e3f1b4b64280d2df246b41666e8a1ece8e31b4 Author: Guillaume Desmottes Date: Sat Dec 13 15:22:36 2008 +0000 wocky-xmpp-connection-test: fix static functions tests/wocky-xmpp-connection-test.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) commit 0e69cdef0ef37d3818f7bdcd7373c33963f3b763 Author: Sjoerd Simons Date: Wed Jun 4 10:19:29 2008 +0000 Convert tests to telepathy coding style 20080604101929-93b9a-7480a8b55e1a75d9a1797bf42412944f31513e20.gz tests/wocky-xmpp-connection-test.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) commit d8879f17e446f72b2f34260575eb9959a05c3a8b Author: Emanuele Aina Date: Mon Jul 2 16:49:18 2007 +0000 Fix a memleak in the WockyXmppConnection test 20070702164918-f974e-d961a1edd7f9d983588abecbc339095b1ab43e67.gz tests/wocky-xmpp-connection-test.c | 1 + 1 file changed, 1 insertion(+) commit 263548eb95b7ab382f6c99c8368131de1ef60f0b Author: Emanuele Aina Date: Wed Jun 27 13:03:05 2007 +0000 Use the $srcdir env var to obtain the input files to make 'make distcheck' happy 20070627130305-f974e-abafbea1da144e4822c77f4c5529a1e84b7c42fe.gz tests/wocky-xmpp-connection-test.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) commit a1a3cfb3c6028eca9a188509caa4aa3e349c6298 Author: Sjoerd Simons Date: Fri Jun 22 23:00:21 2007 +0000 The main test runs g_type_init, no need to do it again in indiviual tests 20070622230021-b58c9-b0670ceb4a1c2e27d4b7815421409a7410197d4a.gz tests/wocky-xmpp-connection-test.c | 4 ---- 1 file changed, 4 deletions(-) commit ab3a9206ca001b0e6bd414f04915f6a2d68ce682 Author: Sjoerd Simons Date: Fri Jun 22 22:59:37 2007 +0000 Add destructor for the file chunker 20070622225937-b58c9-b293278434eaacc2671e4bf79cf4abc5b7278033.gz tests/wocky-xmpp-connection-test.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) commit 0672214f17623d23b1e101bbe29eb11dfe35d1be Author: Emanuele Aina Date: Wed Jun 13 16:16:40 2007 +0000 Replaced two variables used as constants with thei values 20070613161640-f974e-df65a86b4479e120293d77316801459df704d0dc.gz tests/wocky-xmpp-connection-test.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) commit 3dfc9142f411a14a363d31b42e2c9ecc9838e664 Author: Emanuele Aina Date: Wed Jun 13 16:13:24 2007 +0000 Factored the file chunking code out of the test 20070613161324-f974e-d62367f7adbd4db10479b8e9078b1be0cb45a2e9.gz tests/wocky-xmpp-connection-test.c | 51 +++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 9 deletions(-) commit ea65e79738efeb5a35741345bc4b026879c2cb02 Author: Emanuele Aina Date: Wed Jun 13 15:36:14 2007 +0000 Check the parsing of a valid message 20070613153614-f974e-8c309a7855465643f05f322e1366640a9656f2c6.gz tests/wocky-xmpp-connection-test.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) commit c9038d2b29279027889021bc952c34165e36e306 Author: Emanuele Aina Date: Wed Jun 13 14:02:35 2007 +0000 Add a testcase for WockyXmppConnection and check its istantiation 20070613140235-f974e-38a23919dc403a05ad6852760c6b13bd9ad2e6f5.gz tests/wocky-xmpp-connection-test.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) commit 0638057a6768d8120ef7e65c44fa7eb30d0c08a4 Author: Sjoerd Simons Date: Tue Mar 24 14:35:48 2009 +0000 Coding style fix wocky/wocky-sasl-auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 4d074ec8e8c8b0bf24f5869cef0a55e5287c2e53 Author: Sjoerd Simons Date: Thu Mar 26 11:05:13 2009 +0000 Add fixmes to catch erros when writing things out wocky/wocky-xmpp-connection.c | 2 ++ 1 file changed, 2 insertions(+) commit d5cd67ff979bcb36c611699867701ad4964e5bcc Author: Sjoerd Simons Date: Thu Mar 26 11:03:38 2009 +0000 Don't locally define the xmpp namespace wocky/wocky-xmpp-connection.c | 1 - wocky/wocky-xmpp-reader.c | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) commit 383751f5111fc1d22c3ba7b2d585d7d04597b057 Author: Sjoerd Simons Date: Thu Mar 26 11:00:07 2009 +0000 Don't use C++ style comments wocky/wocky-xmpp-connection.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) commit 438382f8318d6af57d95886b04e43375690476b1 Author: Sjoerd Simons Date: Tue Mar 24 11:55:12 2009 +0000 Update copyright headers wocky/wocky-sasl-auth.c | 4 ++-- wocky/wocky-xmpp-connection.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) commit 529fc7a6fa74e31b4979422e641f556c502c48e6 Author: Sjoerd Simons Date: Mon Mar 23 18:16:23 2009 +0000 Remove dead code examples/connect.c | 55 ------------------------------------------------------ 1 file changed, 55 deletions(-) commit 1ece255bbf5d98a66ffa0575f74910a525b172df Author: Sjoerd Simons Date: Mon Mar 23 18:11:18 2009 +0000 Hook in sasl helper examples/connect.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) commit bb31d5438d401d51b703977c612475fcf8c77bc9 Author: Sjoerd Simons Date: Mon Mar 23 17:07:32 2009 +0000 Add sasl authenticator helper module wocky/Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 3c84c10fcea898a73e25a8b06f0b2f2625157fd7 Author: Sjoerd Simons Date: Mon Mar 23 17:07:11 2009 +0000 Port to GLibs md5 checksum functionality wocky/wocky-sasl-auth.c | 60 ++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 26 deletions(-) commit 4b75598e43920219416dec5028f8c349a6441370 Author: Guillaume Desmottes Date: Mon Dec 15 12:14:10 2008 +0000 wocky-sasl-auth: fix coding style wocky/wocky-sasl-auth.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) commit 26ab880096b9782311ff127a1331a3638bb00387 Author: Guillaume Desmottes Date: Fri Dec 12 17:54:08 2008 +0000 update includes to use wocky-signals-marshal.h instead of signals-marshal.h wocky/wocky-sasl-auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 7a542ab51b8aeab8187ac09af99f8954e0403180 Author: Guillaume Desmottes Date: Fri Dec 12 16:20:20 2008 +0000 wocky_sasl_auth_start_mechanism: fix a declaration wocky/wocky-sasl-auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 8465322a802554fca237d5879737732f0669615b Author: Guillaume Desmottes Date: Fri Dec 12 16:18:29 2008 +0000 wocky_sasl_auth_has_mechanism has to be static wocky/wocky-sasl-auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 6da185773de26ceee59b96fc0673ce0bd5f7295c Author: Sjoerd Simons Date: Wed Jun 4 09:28:40 2008 +0000 Make wocky conform to telepathy coding style 20080604092840-93b9a-aee2061241cb08f169ce5b8e9834aaf1ab65cf9a.gz wocky/wocky-sasl-auth.c | 865 +++++++++++++++++++++++++----------------------- wocky/wocky-sasl-auth.h | 23 +- 2 files changed, 470 insertions(+), 418 deletions(-) commit dccf0da6a9ff31acd71d47144989d1ec53f11716 Author: Emanuele Aina Date: Sun Jul 1 13:55:50 2007 +0000 Fix two small memleak in WockySaslAuth 20070701135550-f974e-01e921aff6b722104ea1262ac39980d2dbef55b5.gz wocky/wocky-sasl-auth.c | 2 ++ 1 file changed, 2 insertions(+) commit 082b548788f9c72e790d176d7dafa756876ad013 Author: Simon McVittie Date: Mon Jul 2 10:48:55 2007 +0000 wocky/: generate all signal marshallers together. Generate them by grepping source code to see which marshallers are needed, avoiding the need for .list files. 20070702104855-53eee-56259e92f01b710c85025a8f1bad923288f12ba5.gz wocky/wocky-sasl-auth.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) commit 1829e57b45fe1e8ef8464316a3c20e55e0a707e7 Author: Sjoerd Simons Date: Sat Feb 17 17:03:28 2007 +0000 WockySaslAuth: Remove spurious arguments to a debug statement 20070217170328-93b9a-59bd06add72df19d2f3edd1a28886a22e9c9d10b.gz wocky/wocky-sasl-auth.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) commit 6109871d6c280863d3ed226db6dc28bea69755e4 Author: Sjoerd Simons Date: Sat Feb 17 17:02:55 2007 +0000 WockySaslAuth: Cope with empty challenges (which are invalid) 20070217170255-93b9a-22ca1a043a082b8e1632749d468c8540e0b7958b.gz wocky/wocky-sasl-auth.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) commit 0565c2c4b1d52cadc6d066dfccb76cead3a1a48e Author: Sjoerd Simons Date: Fri Feb 16 11:19:50 2007 +0000 WockySaslAuth: Generate a 256 bit random cnonce instead of using a hardcoded one 20070216111950-93b9a-6ec73801d3febe68b79942103981dc68edc5efc0.gz wocky/wocky-sasl-auth.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) commit ecea718f8c6b34d768e7cc4804c8b083cee9bb3c Author: Sjoerd Simons Date: Thu Feb 15 19:55:10 2007 +0000 WockySaslAuth: Add support for the PLAIN auth mechanism 20070215195510-93b9a-40b76ba500725cb5f704c9d8a305494e5adb5604.gz wocky/wocky-sasl-auth.c | 130 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 112 insertions(+), 18 deletions(-) commit 5459d59a5a62c8a08394e9cfd122abc0c5f863e3 Author: Sjoerd Simons Date: Thu Feb 15 16:06:10 2007 +0000 WockySaslAuth: Rename the error quak from salut_wocky_auth_failed to wocky_sasl_auth_error 20070215160610-93b9a-5677d3a6fca4f248e779c043fdb6e8c7199fda77.gz wocky/wocky-sasl-auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 3f6b5451a209d3ddc4c28e3d3c9158e49de2a431 Author: Sjoerd Simons Date: Thu Feb 15 10:55:01 2007 +0000 Added SASL authentication helper for wocky (just digest-md5 for now) 20070215105501-93b9a-f19f851129b23241b015579541e73f827e5ff373.gz wocky/wocky-sasl-auth.c | 700 ++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-sasl-auth.h | 94 +++++++ 2 files changed, 794 insertions(+) commit d9c0e2f1cbf30d7607f796e5eb9105b572f2dfed Author: Sjoerd Simons Date: Mon Mar 23 12:20:49 2009 +0000 Add an connection example Makefile.am | 2 +- configure.ac | 9 +- examples/Makefile.am | 14 +++ examples/connect.c | 280 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 300 insertions(+), 5 deletions(-) commit 38ea6f4656a637bc1d6e063a72ab14e8ef36c1f7 Author: Sjoerd Simons Date: Mon Mar 23 12:19:23 2009 +0000 Define ENABLE_DEBUG if it's not disabled configure.ac | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) commit a6eebde4700395e4f0916fc6d4bf8fd4ded25373 Author: Sjoerd Simons Date: Mon Mar 23 12:18:13 2009 +0000 First noddy port to GNIO wocky/wocky-xmpp-connection.c | 129 ++++++++++++++++++++++++++++-------------- wocky/wocky-xmpp-connection.h | 11 ++-- 2 files changed, 91 insertions(+), 49 deletions(-) commit 9558d23edc3f2a6354987af77880ca58ed778724 Author: Sjoerd Simons Date: Mon Mar 23 12:16:30 2009 +0000 Add wocky-namespaces to the build wocky/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 131ee48f74d8e45dafd154bb2dd79d0f5aec06ee Author: Alban Crequy Date: Mon Nov 24 12:37:06 2008 +0000 lib/wocky/wocky-namespaces.h: Fix double #define from the merge wocky/wocky-namespaces.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) commit dbbbc6cbd707b008e37a32f353bfb754826852b4 Author: Alban Crequy Date: Wed Oct 8 15:48:33 2008 +0100 lib/wocky/wocky-namespaces.h: Remove all the uneeded casts wocky/wocky-namespaces.h | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) commit 0a3a8450df6ffa7a659d2cadfd08dca06a538e99 Author: Alban Crequy Date: Thu Oct 2 18:44:45 2008 +0100 Caps: Add SalutPresenceCache and SalutDisco wocky/wocky-namespaces.h | 6 ++++++ 1 file changed, 6 insertions(+) commit 766e1f7d619466203299a2a2c766a58e1b95cd09 Author: Alban Crequy Date: Wed Oct 1 15:35:01 2008 +0100 Caps: publish the right caps in txt records after the caps changed with SetSelfCapabilities wocky/wocky-namespaces.h | 3 +++ 1 file changed, 3 insertions(+) commit 64099c646a8bea927b66c9228d7825a6c25cd7f7 Author: Sjoerd Simons Date: Thu Oct 30 19:33:52 2008 +0000 Add jabber:x:event namespace wocky/wocky-namespaces.h | 3 +++ 1 file changed, 3 insertions(+) commit a728d5057f38610fa87f270e84865ae095a35abe Author: Jonny Lamb Date: Tue Jul 15 18:56:36 2008 +0000 Added Marco's file transfer code. 20080715185636-8ed0e-06775a31a2c94b716db41375af32db8248b9e8d3.gz wocky/wocky-namespaces.h | 6 ++++++ 1 file changed, 6 insertions(+) commit e21e96c193e92eb2f507bea48e6c054415c4dea4 Author: Simon McVittie Date: Fri Nov 2 15:53:16 2007 +0000 Use new Clique namespace to represent the Clique protocol (XMPP-like messages over a reliable multicast protocol) 20071102155316-53eee-fa026748eb7cdb35c32fdc4e523d3cc2a2fc1866.gz wocky/wocky-namespaces.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 57319116ef5bfefa47a73290a2766709211149d7 Author: Guillaume Desmottes Date: Fri Oct 19 16:08:52 2007 +0000 add WOCKY_TELEPATHY_NS_RMULTICAST namespace and use it in bytestream-muc 20071019160852-7fe3f-a8289e1842f7371947c6aab5e2f0764297970f2f.gz wocky/wocky-namespaces.h | 3 +++ 1 file changed, 3 insertions(+) commit f0f1ac83fd9a864adb6d3428332b5627ba476d98 Author: Guillaume Desmottes Date: Wed Oct 17 14:51:15 2007 +0000 add jingle errors NS 20071017145115-7fe3f-9045aaae3cf2efbd008ef6dd4b968e73cf609ad9.gz wocky/wocky-namespaces.h | 3 +++ 1 file changed, 3 insertions(+) commit 9a91b49d1d4f43b846b8f5aa61b94799e40dba3f Author: Guillaume Desmottes Date: Tue Oct 16 14:59:08 2007 +0000 add OOB NS 20071016145908-7fe3f-0bd6e603b25b2c9a6718107e4302764b63bbdd24.gz wocky/wocky-namespaces.h | 3 +++ 1 file changed, 3 insertions(+) commit 25cdbf39b7dcb7d76693a7b3c5fb85e5fec8d783 Author: Guillaume Desmottes Date: Tue Oct 16 11:52:09 2007 +0000 wocky-namespaces.h: add SI related NS 20071016115209-7fe3f-88728f8ee5e1723c5c876fe7eb77f0d837c8c99c.gz wocky/wocky-namespaces.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) commit fef054f9cd513e15106ccbadd702890321fdf850 Author: Guillaume Desmottes Date: Fri Aug 17 14:34:51 2007 +0000 wocky-namespaces.h: add WOCKY_TELEPATHY_NS_OLPC_ACTIVITY_PROPS 20070817143451-7fe3f-b9a78518ce007308ca2f1f3f5b8df4a44dda2563.gz wocky/wocky-namespaces.h | 3 +++ 1 file changed, 3 insertions(+) commit 38e80b8f903f8800e6c3f4b9f910cfdc900c71ef Author: Guillaume Desmottes Date: Wed Aug 1 14:08:53 2007 +0000 fix IBB NS 20070801140853-7fe3f-6e410e615a9619db3b6b62bd7f0aa763ab2a715e.gz wocky/wocky-namespaces.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 79388f1807076e7d7528102e11d11e0024ff9db1 Author: Guillaume Desmottes Date: Fri Jun 15 11:55:34 2007 +0000 wocky-namespaces.h: add tubes NS 20070615115534-7fe3f-bc808f4784fbc66fb160f25de84058a26800d4ea.gz wocky/wocky-namespaces.h | 3 +++ 1 file changed, 3 insertions(+) commit 9c760087f91329c7c88a6b51bc9a16eb6435e12b Author: Guillaume Desmottes Date: Wed Jun 13 17:10:56 2007 +0000 add IBB and AMP NS 20070613171056-7fe3f-42a9b52794f2a1ddab3aec7d9e65c68fc4f1c5f9.gz wocky/wocky-namespaces.h | 6 ++++++ 1 file changed, 6 insertions(+) commit 89c3f9080a667721a0a051d6cdecadd1f8fa3c04 Author: Guillaume Desmottes Date: Tue Jun 12 14:24:34 2007 +0000 wocky-namespaces.h: add #define test to protect against multi inclusion 20070612142434-7fe3f-09ccbc7bd36ab724a53220376d1e7c46c842b4f8.gz wocky/wocky-namespaces.h | 5 +++++ 1 file changed, 5 insertions(+) commit cfc80a8794b405ccc2127fe6fa52100fe5cfcdfd Author: Sjoerd Simons Date: Fri Mar 16 21:26:30 2007 +0000 Add xhtml-im and w3c xhtml namespace 20070316212630-93b9a-bcdbd042585561b0f20076b5e7f5f1c41c1e2867.gz wocky/wocky-namespaces.h | 5 +++++ 1 file changed, 5 insertions(+) commit 4a364f0b3f688edf5370d375f2f44b5e077e857a Author: Sjoerd Simons Date: Mon Feb 19 22:52:17 2007 +0000 wocky-namespaces.h: Add TLS namespace 20070219225217-93b9a-a939a12c3ca9cc6a087d08e9e3b045b0a2568f60.gz wocky/wocky-namespaces.h | 3 +++ 1 file changed, 3 insertions(+) commit 43811d80edd39543cce3e65e011fc93d10d94edb Author: Sjoerd Simons Date: Sat Feb 17 12:35:57 2007 +0000 wocky-namespaces: Add the jabber stream namespace 20070217123557-93b9a-2efee7ed7fe5077289e66078c13d9480f975e699.gz wocky/wocky-namespaces.h | 4 ++++ 1 file changed, 4 insertions(+) commit 08820023c0787959fd6c746d6e7a04784d5692e3 Author: Sjoerd Simons Date: Thu Feb 15 10:55:01 2007 +0000 Added SASL authentication helper for wocky (just digest-md5 for now) 20070215105501-93b9a-f19f851129b23241b015579541e73f827e5ff373.gz wocky/wocky-namespaces.h | 3 +++ 1 file changed, 3 insertions(+) commit 952f5bd31390e6d0e291e95e7035628e5e6f8ee9 Author: Sjoerd Simons Date: Tue Mar 17 19:41:23 2009 +0000 Add basic build infrastructure AUTHORS | 1 + ChangeLog | 0 Makefile.am | 10 ++++ NEWS | 1 + autogen.sh | 31 +++++++++++++ configure.ac | 108 ++++++++++++++++++++++++++++++++++++++++++++ m4/Makefile.am | 2 + m4/as-compiler-flag.m4 | 33 ++++++++++++++ m4/tp-compiler-flag.m4 | 36 +++++++++++++++ m4/tp-compiler-warnings.m4 | 40 ++++++++++++++++ tools/Makefile.am | 5 ++ tools/check-c-style.sh | 56 +++++++++++++++++++++++ tools/check-coding-style.mk | 17 +++++++ tools/check-misc.sh | 13 ++++++ tools/check-whitespace.sh | 17 +++++++ wocky/Makefile.am | 78 ++++++++++++++++++++++++++++++++ 16 files changed, 448 insertions(+) commit 467cc8de580acb2fd89a7e0f827c75408aadf526 Author: Will Thompson Date: Sun Jan 11 17:50:48 2009 +0000 Define stub DEBUG macros when !ENABLE_DEBUG Defining DEBUG(...) to expand to nothing trips warnings for code like this: if (foo) DEBUG(...); It could be worked around by using {}s, but better to fix the macros wocky/wocky-debug.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) commit c86b788131b5e4bb0090e6f2517cf8077bad5265 Author: Will Thompson Date: Sun Jan 11 17:04:07 2009 +0000 Compare strictly to WOCKY_STANZA_TYPE_NONE in several functions. In check_sub_type, sub_type can legitimately be NONE, but the compiler spuriously warns if we check it's non-negative (see previous commit). All other comparisons were equally correct if they didn't accept WOCKY_STANZA_TYPE_NONE. wocky/wocky-xmpp-stanza.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) commit 7e41eb5e7042eeb9f01828f0e811cff27994a176 Author: Will Thompson Date: Sun Jan 11 15:42:23 2009 +0000 Remove an unused label. All references to it were removed in "use assertions instead of wocky_goto_if_fail and wocky_goto_if_reached". wocky/wocky-xmpp-stanza.c | 4 ---- 1 file changed, 4 deletions(-) commit fb8e0aab248612fd02e702e4a6f9ba5931ce5148 Author: Guillaume Desmottes Date: Wed Jan 7 11:56:25 2009 +0000 wocky-debug.c: don't build code if debug is disabled wocky/wocky-debug.c | 4 ++++ 1 file changed, 4 insertions(+) commit 3b6d233e8e6cccc4f4186fc2690ff15b62aa71aa Author: Guillaume Desmottes Date: Wed Jan 7 11:55:48 2009 +0000 wocky-debug.h: G_BEGIN_DECLS has to be outside the #ifdef ENABLE_DEBUG wocky/wocky-debug.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) commit 8862f970f5194430e8cff9902e774bcdff2e34e5 Author: Guillaume Desmottes Date: Wed Jan 7 11:53:42 2009 +0000 use assertions instead of wocky_goto_if_fail and wocky_goto_if_reached wocky/wocky-xmpp-stanza.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) commit 4bd74bfd5c424baa2b206a12e4790620e0c698c5 Author: Guillaume Desmottes Date: Wed Jan 7 11:53:14 2009 +0000 wocky-debug.h: remove wocky_goto_if_reached and wocky_goto_if_fail as they don't really make sense wocky/wocky-debug.h | 22 ---------------------- 1 file changed, 22 deletions(-) commit 15b3424d3c7e4f4f6bb968e9c7bc23aea9674e9a Author: Guillaume Desmottes Date: Mon Dec 15 12:13:11 2008 +0000 wocky-xmpp-node: fix coding style wocky/wocky-xmpp-node.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) commit 4c007a2f5caba03babd121d98beb6834b5d813e0 Author: Guillaume Desmottes Date: Mon Dec 15 12:12:59 2008 +0000 wocky-xmpp-reader: fix coding style wocky/wocky-xmpp-reader.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) commit 8a76c2fc4f2761c7ae36aa30358ccf6bbb05b1a0 Author: Guillaume Desmottes Date: Mon Dec 15 12:12:50 2008 +0000 wocky-xmpp-writer: fix coding style wocky/wocky-xmpp-writer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) commit 5ab277188ce4101b89473630a7e8952f1a647de2 Author: Guillaume Desmottes Date: Fri Dec 12 17:54:08 2008 +0000 update includes to use wocky-signals-marshal.h instead of signals-marshal.h wocky/wocky-xmpp-connection.c | 2 +- wocky/wocky-xmpp-reader.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) commit 7b4cd5daeb003f91876794f69e58493a6016da12 Author: Guillaume Desmottes Date: Fri Dec 12 16:00:41 2008 +0000 wocky-xmpp-writer: _write_attr and _write_child have to be static wocky/wocky-xmpp-writer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 3ccd5c9e9edf633210211778b54feb4a59063a9d Author: Guillaume Desmottes Date: Fri Dec 12 15:58:36 2008 +0000 add wocky_xmpp_connection_new_no_stream prototype wocky/wocky-xmpp-connection.h | 3 +++ 1 file changed, 3 insertions(+) commit 4f3e118fda6d886e91a0fe1eededbe0f57068ed8 Author: Guillaume Desmottes Date: Fri Dec 12 15:57:00 2008 +0000 wocky-debug.h: fix wocky_debug_set_flags_from_env prototype wocky/wocky-debug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit ff1ba290ce71cc2c49273c730865b032459e63d2 Author: Sjoerd Simons Date: Thu Oct 30 19:06:31 2008 +0000 Push new stanza at the tail of the queue, so they are popped in the right order later on wocky/wocky-xmpp-reader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 77cad2cef33f3152fd47464b73f9e36bffb1ec74 Author: Jonny Lamb Date: Tue Jul 15 18:56:36 2008 +0000 Added Marco's file transfer code. 20080715185636-8ed0e-06775a31a2c94b716db41375af32db8248b9e8d3.gz wocky/wocky-debug.c | 1 + wocky/wocky-debug.h | 1 + 2 files changed, 2 insertions(+) commit e2aebb5710e8fb6fb6f2b32e006dad2292ae1921 Author: Sjoerd Simons Date: Wed Jun 4 09:28:40 2008 +0000 Make wocky conform to telepathy coding style 20080604092840-93b9a-aee2061241cb08f169ce5b8e9834aaf1ab65cf9a.gz wocky/wocky-debug.c | 4 +- wocky/wocky-debug.h | 4 +- wocky/wocky-xmpp-connection.c | 314 ++++++++++++++++---------------- wocky/wocky-xmpp-connection.h | 40 ++--- wocky/wocky-xmpp-node.c | 320 +++++++++++++++++---------------- wocky/wocky-xmpp-node.h | 128 ++++++------- wocky/wocky-xmpp-reader.c | 405 +++++++++++++++++++++++------------------- wocky/wocky-xmpp-reader.h | 24 +-- wocky/wocky-xmpp-stanza.c | 6 +- wocky/wocky-xmpp-stanza.h | 19 +- wocky/wocky-xmpp-writer.c | 306 ++++++++++++++++--------------- wocky/wocky-xmpp-writer.h | 38 ++-- 12 files changed, 848 insertions(+), 760 deletions(-) commit 51742d045364acce563136414a8bdd1465873f37 Author: Simon McVittie Date: Fri Oct 19 15:08:41 2007 +0000 Add WOCKY_NODE_ASSIGN_TO opcode to wocky_xmpp_stanza_build 20071019150841-53eee-c6180e5eccfd5d5819a0d12b881444be3bfc90d9.gz wocky/wocky-xmpp-stanza.c | 9 +++++++++ wocky/wocky-xmpp-stanza.h | 1 + 2 files changed, 10 insertions(+) commit 0dd7b754a7991f9420b0ea84a2eeaa75a5e15bc8 Author: Guillaume Desmottes Date: Wed Jul 11 09:19:19 2007 +0000 fix WOCKY_XMPP_CONNECTION_CLOSE_FULLY_CLOSED flag 20070711091919-7fe3f-6ef819ed805180f8c37574ff13147a9955a711e2.gz wocky/wocky-xmpp-connection.h | 1 + 1 file changed, 1 insertion(+) commit e0e3927117928acc24bfa4209fe4b0f53888ed05 Author: Guillaume Desmottes Date: Tue Jul 10 08:46:59 2007 +0000 wocky-xmpp-connection.c: add CLOSE flags 20070710084659-7fe3f-4ae9b76c8176493817626c6725f61aa7ea3c90d3.gz wocky/wocky-xmpp-connection.c | 4 ++++ wocky/wocky-xmpp-connection.h | 17 +++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) commit 24fd6b222d0eb8e755a288ae71e3a1760fb7bda5 Author: Sjoerd Simons Date: Mon Jul 2 07:56:29 2007 +0000 Add flags to indicate which way the stream opening has been sent 20070702075629-b58c9-caba73719213896652eca8671e7606bb09c7792f.gz wocky/wocky-xmpp-connection.c | 22 +++++++++++----------- wocky/wocky-xmpp-connection.h | 9 ++++++++- 2 files changed, 19 insertions(+), 12 deletions(-) commit a471b048c6269470b2b26499e031c9adadc8e1d1 Author: Simon McVittie Date: Mon Jul 2 10:48:55 2007 +0000 lib/wocky/: generate all signal marshallers together. Generate them by grepping source code to see which marshallers are needed, avoiding the need for .list files. 20070702104855-53eee-56259e92f01b710c85025a8f1bad923288f12ba5.gz wocky/wocky-xmpp-connection.c | 4 ++-- wocky/wocky-xmpp-reader.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) commit 4bc73e5c0936180cfaab2e5267916f4eb702e4c7 Author: Guillaume Desmottes Date: Thu Jun 28 14:06:46 2007 +0000 xmpp-stanza: assert stanza->node != NULL 20070628140646-7fe3f-6e9a2388bc757c87c00addad2f36c7d9a917d420.gz wocky/wocky-xmpp-stanza.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) commit dfa38e4d0e9e3f2d82e79f16bc62fc94c8753878 Author: Guillaume Desmottes Date: Thu Jun 28 13:57:42 2007 +0000 xmpp-stanza: factor out (sub) type name -> WockyStanza(Sub)Type to simplify code 20070628135742-7fe3f-63c98e9add085256738a6d841354e8ac4a5d7366.gz wocky/wocky-xmpp-stanza.c | 90 ++++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 44 deletions(-) commit 316afe222f71d36bcae05b66f0878972bb966cc7 Author: Guillaume Desmottes Date: Thu Jun 28 13:39:32 2007 +0000 rename LAST_WOCKY_STANZA_(SUB_)TYPE to NUM_WOCKY_STANZA_(SUB_)TYPE 20070628133932-7fe3f-12f50c87a912fdcaf632cbd2496162fdb95d6019.gz wocky/wocky-xmpp-stanza.c | 26 +++++++++++++------------- wocky/wocky-xmpp-stanza.h | 4 ++-- 2 files changed, 15 insertions(+), 15 deletions(-) commit 0721a4a4a39f59f97a112dcfeebb307a1f0e24d2 Author: Guillaume Desmottes Date: Thu Jun 28 12:44:49 2007 +0000 add wocky_xmpp_stanza_get_type_info 20070628124449-7fe3f-7ce76716162f4ef37a00cfaf0135f998fe684df0.gz wocky/wocky-xmpp-stanza.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-stanza.h | 4 +++ 2 files changed, 67 insertions(+) commit 0be3da65c21240e3c9b514b1468734af101603a2 Author: Guillaume Desmottes Date: Thu Jun 28 11:52:15 2007 +0000 add WOCKY_STANZA_TYPE_UNKNOWN and WOCKY_STANZA_SUB_TYPE_UNKNOWN 20070628115215-7fe3f-b1554b27ca4159ccabfb0440253f4511dd2cd9f6.gz wocky/wocky-xmpp-stanza.c | 3 +++ wocky/wocky-xmpp-stanza.h | 2 ++ 2 files changed, 5 insertions(+) commit fba5b3d743d2ef44fce54ae7dae2eee1fe84c3ab Author: Guillaume Desmottes Date: Wed Jun 27 15:40:13 2007 +0000 xmpp writer: wocky_xmpp_writer_write_stanza: properly end the XML document if we opened it 20070627154013-7fe3f-4531ab5c3ffdc7098d6a7cb10cbf53b1fbd4ae9f.gz wocky/wocky-xmpp-writer.c | 3 +++ 1 file changed, 3 insertions(+) commit 144379b5082f74b2f2683c9fdc2d5d2b8d72d261 Author: Guillaume Desmottes Date: Wed Jun 27 15:29:50 2007 +0000 xmpp-reader: fix parser leak 20070627152950-7fe3f-66c9308c55f88482fc97277bf40d24a9f382e6fc.gz wocky/wocky-xmpp-reader.c | 3 +++ 1 file changed, 3 insertions(+) commit 5d185bb1b41e4b6b2682ef51d4c9c66832935aa1 Author: Guillaume Desmottes Date: Wed Jun 13 09:21:29 2007 +0000 resolve conflicts 20070613092129-7fe3f-2b6baa02dcd135f33a8f7b8a9c02d8453d962d23.gz wocky/wocky-debug.c | 2 ++ wocky/wocky-debug.h | 3 +++ 2 files changed, 5 insertions(+) commit bf1eee65708b2e3be575896ab2be6efc0f1478ad Author: Guillaume Desmottes Date: Mon Jun 11 10:14:31 2007 +0000 add bytestream flag in wocky-debug 20070611101431-7fe3f-d1f9d74df54bc1e246ab75826b931d6bd9695999.gz wocky/wocky-debug.c | 1 - wocky/wocky-debug.h | 1 - 2 files changed, 2 deletions(-) commit f73827190c938dfa875964636794db7e33e535d2 Author: Guillaume Desmottes Date: Fri Jun 22 09:50:36 2007 +0000 wocky-xmpp-reader: don't leak the nodes queue 20070622095036-7fe3f-38a0c4ea6789444c6b04a1f6df11e6ef84f99c0e.gz wocky/wocky-xmpp-reader.c | 1 + 1 file changed, 1 insertion(+) commit fa04537b90306f15562cd2312dffe695a803015b Author: Guillaume Desmottes Date: Thu Jun 21 13:45:17 2007 +0000 wocky-xmpp-connection.c: generate an id for stanza who doesn't have one before sending 20070621134517-7fe3f-74190255a1c13b53ffe1d07aac675e0e925c58e6.gz wocky/wocky-xmpp-connection.c | 9 +++++++++ 1 file changed, 9 insertions(+) commit dc6c99e3e6d00e41832b4794c6c50262588c05d9 Author: Guillaume Desmottes Date: Thu Jun 21 13:39:08 2007 +0000 add wocky_xmpp_connection_new_id public method[3~ 20070621133908-7fe3f-086b66767bad06086b6f74f8dc19bc04d6fa01e6.gz wocky/wocky-xmpp-connection.c | 20 +++++++++++++++++++- wocky/wocky-xmpp-connection.h | 3 +++ 2 files changed, 22 insertions(+), 1 deletion(-) commit 2652b052605d50f9b5487c0d427dbddd85b508f8 Author: Sjoerd Simons Date: Tue Jun 19 03:27:15 2007 +0000 Initialize the debugging flags if that wasn't done yet 20070619032715-b58c9-173cdbd3f369494cf1a519097bc9fbab3ad39215.gz wocky/wocky-debug.c | 2 ++ 1 file changed, 2 insertions(+) commit 51712116dd763988f32a75293f1ed88e169df039 Author: Sjoerd Simons Date: Tue Jun 19 12:01:26 2007 +0000 Format type fixes from misc@mandriva.org 20070619120126-b58c9-44b9271200324439d74cb1969dc22f6f661c4de8.gz wocky/wocky-xmpp-reader.c | 2 +- wocky/wocky-xmpp-writer.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) commit 50412b9c566bb63a06137c8f4977092f56481865 Author: Guillaume Desmottes Date: Fri Jun 15 12:30:45 2007 +0000 reimplement wocky_debug_stanza to use wocky_xmpp_node_to_string 20070615123045-7fe3f-bb91394e6454c0d035256c299c86aab08d365e06.gz wocky/wocky-debug.c | 77 +++++------------------------------------------------ 1 file changed, 7 insertions(+), 70 deletions(-) commit 4055ba7ff34b23a10e4cd62af03cd633d03acd9a Author: Guillaume Desmottes Date: Fri Jun 15 12:23:06 2007 +0000 add wocky_xmpp_node_to_string 20070615122306-7fe3f-2f268e618ce79a7d8d06c310612a3a596f74a327.gz wocky/wocky-xmpp-node.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-node.h | 4 +++ 2 files changed, 76 insertions(+) commit d73925be92098f822a484ce132ffd3db50d82ba2 Author: Guillaume Desmottes Date: Wed Jun 13 16:19:06 2007 +0000 wocky-xmpp-stanza.c: fix an argument error in wocky_xmpp_stanza_build documentation 20070613161906-7fe3f-3c14588a9ea94511993588092993b6629aaf7e8a.gz wocky/wocky-xmpp-stanza.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit cdaecd0c999362ca02137967d6977064bb06f6b5 Author: Sjoerd Simons Date: Fri Jun 15 11:40:07 2007 +0000 remove some trailing spaces 20070615114007-93b9a-2338f688e7b0ce01c5070bac8708adb0aaff78d5.gz wocky/wocky-xmpp-node.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 6f6380896a97a822e02fab3b8aa5e74282859b41 Author: Sjoerd Simons Date: Fri Jun 15 11:39:49 2007 +0000 Use g_return_val_if_fail in wocky_xmpp_node_get_language when a NULL node is passed 20070615113949-93b9a-775a9a54736ba1c8f382daf936a060760e78b9df.gz wocky/wocky-xmpp-node.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 4918b36bcf360b27a8e50fa921f48821ca8ccdb4 Author: Emanuele Aina Date: Sat Jun 9 09:19:16 2007 +0000 Tested wocky_xmpp_node_set_language_n() and fixed wocky_xmpp_node_set_language() with a NULL lang 20070609091916-f974e-25d6e0593963b0bd7c33fce670639d08b476bf55.gz wocky/wocky-xmpp-node.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) commit 15e31a547272ad0f1f5093b4cd94f763b45df2f5 Author: Emanuele Aina Date: Sat Jun 9 08:52:06 2007 +0000 Test and fix wocky_xmpp_node_get_language() with a NULL node 20070609085206-f974e-1b61af2304ed7605d44148e95e77f6ebad7707aa.gz wocky/wocky-xmpp-node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit b360f8d3554c2ae6d65c5045a9068e8a3b13d06a Author: Guillaume Desmottes Date: Wed Jun 13 09:17:55 2007 +0000 don't create the stanza if there is an error during build argument parsing 20070613091755-7fe3f-802a0d76f1fb50a69a28468b181192d7841358ad.gz wocky/wocky-xmpp-stanza.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) commit 72b18fc647a588cf1f3ac7159ae5602283863ffc Author: Guillaume Desmottes Date: Wed Jun 13 08:50:15 2007 +0000 wocky-xmpp-stanza.c: use wocky_goto_if_reached and wocky_goto_if_fail during stanza build parsing to fix a leak 20070613085015-7fe3f-6959e93f20bab7ce55761ba4a19d5cba606925ad.gz wocky/wocky-xmpp-stanza.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) commit da9aa5559cd85df763e99c67290793739c1473d9 Author: Guillaume Desmottes Date: Wed Jun 13 08:49:50 2007 +0000 wocky-debug: add wocky_goto_if_reached and wocky_goto_if_fail macros 20070613084950-7fe3f-279be93f5843f3e83cf19c8ea065266813e27e44.gz wocky/wocky-debug.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) commit 8508e9c7dc3520fb7c58a9d83770af0d3a69f76c Author: Guillaume Desmottes Date: Wed Jun 13 08:21:06 2007 +0000 wocky-xmpp-stanza.c: use g_return_if_reached instead of g_assert_not_reached during stanza_build args parsing 20070613082106-7fe3f-fea96904e7c8341ec782ef7adb4010051b54c1fd.gz wocky/wocky-xmpp-stanza.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 3e06b80331181dbd51db8b558c05413055c273eb Author: Guillaume Desmottes Date: Wed Jun 13 08:18:50 2007 +0000 wocky-xmpp-stanza: typedef WockyBuildTag 20070613081850-7fe3f-de42e6fe3365b02f563fea147bcf931159d0b0fc.gz wocky/wocky-xmpp-stanza.c | 9 +++++---- wocky/wocky-xmpp-stanza.h | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) commit 17057f079cb009d328a6d15ff055d60dc6123365 Author: Guillaume Desmottes Date: Tue Jun 12 16:37:54 2007 +0000 wocky-xmpp-stanza.c: use type_names array to find the optionnal NS associated with a type 20070612163754-7fe3f-a3af4d83860cdfabecfcad53976adf601434aa4b.gz wocky/wocky-xmpp-stanza.c | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) commit b6d570618ea9607824a4b791e7016be9fee826a9 Author: Guillaume Desmottes Date: Tue Jun 12 16:26:37 2007 +0000 wocky-xmpp-stanza.c: use the sub_type_names array instead of a switch to check if sub types belong to the right type 20070612162637-7fe3f-955ab74a038aad6251a18cdcaff5de5851137ef9.gz wocky/wocky-xmpp-stanza.c | 122 ++++++++++++++++++++-------------------------- 1 file changed, 54 insertions(+), 68 deletions(-) commit f8a66555b6d9653604179cc64c09357bcdad7940 Author: Guillaume Desmottes Date: Tue Jun 12 13:23:50 2007 +0000 wocky-xmpp-stanza.c: properly handle STREAM types 20070612132350-7fe3f-7d209e6f707c34287d5bf777d569184ae06e8204.gz wocky/wocky-xmpp-stanza.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) commit ca2e030db5c297c8add2e35b0be9c5c149fae7a3 Author: Guillaume Desmottes Date: Tue Jun 12 13:03:45 2007 +0000 ibber-xmpp-stanza.c: use static array instead of big switch to find subtype's name 20070612130345-7fe3f-876077a1161eb2518338057adbe44bc465fd5591.gz wocky/wocky-xmpp-stanza.c | 92 +++++++++++++++++++---------------------------- wocky/wocky-xmpp-stanza.h | 2 +- 2 files changed, 37 insertions(+), 57 deletions(-) commit 8f6dfc96eda50ab3c4dd38fd85e8dbae7930ca15 Author: Guillaume Desmottes Date: Tue Jun 12 12:42:10 2007 +0000 wocky-xmpp-stanza.c: use static array instead of big switch to find type's name 20070612124210-7fe3f-09e3c49ea8a4d1d3c76d1b7474082e771cf75bab.gz wocky/wocky-xmpp-stanza.c | 65 ++++++++++++++++++++--------------------------- wocky/wocky-xmpp-stanza.h | 2 +- 2 files changed, 28 insertions(+), 39 deletions(-) commit 866769bc8214c2edc50bf3f9a0e2ab8408e5a8f5 Author: Guillaume Desmottes Date: Tue Jun 12 11:33:57 2007 +0000 wocky-xmpp-stanza.c: use g_slist_delete_link instead of 4 instructions doing exactly that 20070612113357-7fe3f-d5ec9f715c4648b185b34189b65e2fcf5981818b.gz wocky/wocky-xmpp-stanza.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) commit 4ecc416de40fd54b4cca41aef2811200117fe606 Author: Guillaume Desmottes Date: Tue Jun 12 11:18:15 2007 +0000 wocky-xmpp-stanza.c: remove useless case WOCKY_STANZA_END in wocky_xmpp_stanza_build parsing 20070612111815-7fe3f-4cc369ea682244bda2023a2139e745de97de32dc.gz wocky/wocky-xmpp-stanza.c | 4 ---- 1 file changed, 4 deletions(-) commit 67d33ef83577620b9f2032ac277a30efa8983e7a Author: Guillaume Desmottes Date: Tue Jun 12 11:02:56 2007 +0000 wocky-debug.c: fix a leak in wocky_debug_stanza 20070612110256-7fe3f-877bb91429285528b2850f12fa6de368b8abc29d.gz wocky/wocky-debug.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) commit fadd12766cf9429859d28fb98ded3c01a8c1bef7 Author: Guillaume Desmottes Date: Tue Jun 12 10:13:18 2007 +0000 wocky-xmpp-stanza: implement wocky_xmpp_stanza_build 20070612101318-7fe3f-b362200f7804bace88b1c37e219a7c2a6dfd6b5e.gz wocky/wocky-xmpp-stanza.c | 307 +++++++++++++++++++++++++++++++++++++++++++++- wocky/wocky-xmpp-stanza.h | 54 +++++++- 2 files changed, 359 insertions(+), 2 deletions(-) commit 2cfc4be419d9c1945ffab0934f322f596bae0adb Author: Guillaume Desmottes Date: Mon Jun 11 18:17:48 2007 +0000 move DEBUG_STANZA to wocky-debug 20070611181748-7fe3f-e4fe05a3b32cde8da6bbafc991d35af099fd2f4f.gz wocky/wocky-debug.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-debug.h | 11 +++++++ 2 files changed, 95 insertions(+) commit 059efc894984d1b42a42bce38dddd12ca1b699c9 Author: Sjoerd Simons Date: Tue Jun 12 16:09:01 2007 +0000 Move SalutMucConnection to wocky as WockyMucConnection 20070612160901-93b9a-3c886d3735de02ed4b8193747040b2d2aff41ae0.gz wocky/wocky-debug.c | 1 + wocky/wocky-debug.h | 1 + 2 files changed, 2 insertions(+) commit bac62f2a52fc7011fd8a4735d28ac519cdead593 Author: Sjoerd Simons Date: Mon Jun 11 13:01:12 2007 +0000 Fix some silly memleaks in wocky-xmpp-node, spotted by Marco Barisione and Mikael Hallendal 20070611130112-93b9a-24d1d091e1c29656fbb77310229ac46ab8a6a646.gz wocky/wocky-xmpp-node.c | 4 ++++ 1 file changed, 4 insertions(+) commit cc004e9082a0b6cc0041eccd029269621d6a614d Author: Sjoerd Simons Date: Sat Jun 9 12:01:06 2007 +0000 Streaming property no long exists 20070609120106-b58c9-591196b73410755f9547fcba3db24a3ee42d6236.gz wocky/wocky-xmpp-connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit bb496013e58ed3c9fdd189be4c332cbe2ebc3d23 Author: Sjoerd Simons Date: Fri Jun 8 20:55:58 2007 +0000 Remove non-streaming mode 20070608205558-b58c9-1f43c402d842d1568296e44f0d45dc6028af7ffc.gz wocky/wocky-xmpp-connection.c | 83 ++++--------------------------------------- wocky/wocky-xmpp-connection.h | 3 -- 2 files changed, 7 insertions(+), 79 deletions(-) commit 88842e2845cbfd917540158bb9a7d1f7ec42a430 Author: Sjoerd Simons Date: Mon Jun 4 06:53:29 2007 +0000 wocky-debug: Add a specific rmulticast debugging category 20070604065329-b58c9-068df8879b1a105a2989f236df4bb093276a8e9e.gz wocky/wocky-debug.c | 1 + wocky/wocky-debug.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) commit 0add488b22c20aa4ab5a8cc818b378cf1d77fa80 Author: Sjoerd Simons Date: Mon May 21 11:51:57 2007 +0000 Add debug category for the multicast sender 20070521115157-93b9a-2300e537dcec6524cef474128ad490b38999bea5.gz wocky/wocky-debug.c | 17 +++++++++-------- wocky/wocky-debug.h | 13 +++++++------ 2 files changed, 16 insertions(+), 14 deletions(-) commit 10968df7be60c30b6f4f4690a71992380fdfbf31 Author: Sjoerd Simons Date: Tue Mar 13 18:43:38 2007 +0000 WockyXmppConnection: Compile fixes 20070313184338-93b9a-5922970bfa5ca6805d2a89777d47dd5d02dba8e5.gz wocky/wocky-xmpp-connection.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) commit 808e37792b31f6491d5536aaff325a665d709b8f Author: Sjoerd Simons Date: Tue Mar 13 12:59:15 2007 +0000 WockyXmppConnection: Add a non-streaming mode 20070313125915-93b9a-da87a011ed0cb9e681d3912fb1a7620ab3850548.gz wocky/wocky-xmpp-connection.c | 123 +++++++++++++++++++++++++++++++++++++----- wocky/wocky-xmpp-connection.h | 4 ++ 2 files changed, 113 insertions(+), 14 deletions(-) commit 790bba519b03494265255886c8c1b9b4695f3467 Author: Sjoerd Simons Date: Tue Mar 13 11:58:10 2007 +0000 WockyXmppConnection: Allow the connection to be created without an underlying transport 20070313115810-93b9a-3e0ad2e51ba1732a87de2d306e29d803871c35d4.gz wocky/wocky-xmpp-connection.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 4d27720ab917b387ae8fa39da9c43874eeec11a6 Author: Sjoerd Simons Date: Thu Mar 1 14:49:17 2007 +0000 wocky-debug.h: Fix typo in __DEBUG_H__ define 20070301144917-93b9a-28b4ed528b50e24b899889e30576e620069476aa.gz wocky/wocky-debug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit a0c600b9c07cb0681ca1bb2333e1065bfe3dd11f Author: Sjoerd Simons Date: Mon Feb 19 22:53:07 2007 +0000 WockyXmppConnection: Add functions to disengage the connection from the transport and re-engage it on top of a new transport 20070219225307-93b9a-dad771f4cc6e83f618d5e41d3ef3171df3148d71.gz wocky/wocky-xmpp-connection.c | 27 ++++++++++++++++++++++----- wocky/wocky-xmpp-connection.h | 5 +++++ 2 files changed, 27 insertions(+), 5 deletions(-) commit 7b44ac78160a88adf50edee43259669ce24474d8 Author: Sjoerd Simons Date: Sat Feb 17 22:07:03 2007 +0000 WockyXmppConnection: Mark stream as closed after calling connection_restart 20070217220703-93b9a-e72fce05b9ca351dc6500cb684edd735e26ad680.gz wocky/wocky-xmpp-connection.c | 1 + 1 file changed, 1 insertion(+) commit 660cfd64118d30b5b7c846db3a2cde8e610e1b49 Author: Sjoerd Simons Date: Sat Feb 17 17:05:05 2007 +0000 WockyXmppConnection: Add function to restart the stream, which allows the other side to reopen the connection (After say a sasl authentication) 20070217170505-93b9a-15e939bb4095cee5e33b12455685e8349929a3c6.gz wocky/wocky-xmpp-connection.c | 9 +++++++++ wocky/wocky-xmpp-connection.h | 6 ++++++ 2 files changed, 15 insertions(+) commit 5f6902411d555f942f906a6adc9948c64834860a Author: Sjoerd Simons Date: Sat Feb 17 12:34:45 2007 +0000 WockyXmppReader: Make wocky_xmpp_reader_push reentrant 20070217123445-93b9a-e4981edf60f86e15232a86156acb3ff36d8843b6.gz wocky/wocky-xmpp-reader.c | 74 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 23 deletions(-) commit f7a9270d556a5e7da4219574d3cfd1ed4a20b813 Author: Sjoerd Simons Date: Fri Feb 16 10:35:42 2007 +0000 WockyXmppConnection: Only reset after we reopen our own stream, not after the other side has opened their stream 20070216103542-93b9a-7b716672297079528284236d21f1d4549b4263b4.gz wocky/wocky-xmpp-connection.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) commit 474568cb7bd70ae27943eca403780f16ab8fa3e6 Author: Sjoerd Simons Date: Thu Feb 15 19:54:17 2007 +0000 WockyXmppConnection: If the stream is re-opened reset the xml reader 20070215195417-93b9a-36e408dd62df217b236f334913da992957612110.gz wocky/wocky-xmpp-connection.c | 10 ++++++++++ 1 file changed, 10 insertions(+) commit 28098b62916ff654251334f9200b738ffbeea57d Author: Sjoerd Simons Date: Thu Feb 15 19:53:41 2007 +0000 WockyXmppWriter: Turn of indenting of the output stream for now 20070215195341-93b9a-06a6024612b2c75cf254a05be028c776e605a2f9.gz wocky/wocky-xmpp-writer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit e4328fefd92299a312323722b173a0e44189ae1b Author: Sjoerd Simons Date: Thu Feb 15 19:50:36 2007 +0000 WockyXmppReader: Add ability to reset the reader when needed 20070215195036-93b9a-101186da1a23a1456991feb9e5e9ac6312856eac.gz wocky/wocky-xmpp-reader.c | 26 +++++++++++++++++++++++--- wocky/wocky-xmpp-reader.h | 1 + 2 files changed, 24 insertions(+), 3 deletions(-) commit b8565f2e2f4dc54cf7edd79eacafb243a9dab3bc Author: Sjoerd Simons Date: Thu Feb 15 16:06:33 2007 +0000 Implement an SSL transport for wocky 20070215160633-93b9a-bbb1468c182c157f593dcf07ef21d5bed09e8f7f.gz wocky/wocky-debug.c | 1 + wocky/wocky-debug.h | 1 + 2 files changed, 2 insertions(+) commit 825318c597fe94d083534de7c34b9b42eb6d1f50 Author: Sjoerd Simons Date: Thu Feb 15 10:55:01 2007 +0000 Added SASL authentication helper for wocky (just digest-md5 for now) 20070215105501-93b9a-f19f851129b23241b015579541e73f827e5ff373.gz wocky/wocky-debug.c | 1 + wocky/wocky-debug.h | 1 + 2 files changed, 2 insertions(+) commit 9c1ca9bc99f8339ac39ec2f640660ac85f62658e Author: Sjoerd Simons Date: Tue Feb 13 15:51:44 2007 +0000 SalutXmppWriter: Add debugging to stream open and close 20070213155144-93b9a-8fa834e31dda7628e45ca7cfcce8dcf34fccbca3.gz wocky/wocky-xmpp-writer.c | 3 +++ 1 file changed, 3 insertions(+) commit de5327a61f7ffbd4b8bf0bd3800ca11851d30408 Author: Sjoerd Simons Date: Tue Feb 13 13:26:33 2007 +0000 Push received transport data through handler functions instead of signals 20070213132633-93b9a-25678d8680408e6e7ecb88289afd577cb1163734.gz wocky/wocky-debug.c | 1 + wocky/wocky-debug.h | 7 ++++--- wocky/wocky-xmpp-connection.c | 21 +++++++++++---------- 3 files changed, 16 insertions(+), 13 deletions(-) commit eaa86572f2ee3c1f283577e4747749bef79265ac Author: Sjoerd Simons Date: Tue Feb 13 10:05:59 2007 +0000 WockyXmppNode: Assert that attribute values are !NULL 20070213100559-93b9a-407f99a9c26a5769c78345098b0bc53a6a44eb19.gz wocky/wocky-xmpp-node.c | 1 + 1 file changed, 1 insertion(+) commit 9c139ce0b8eadf1b44ed5790cb0ebc1da409aaf9 Author: Sjoerd Simons Date: Tue Feb 13 10:05:08 2007 +0000 WockyXmppWriter: Add debugging 20070213100508-93b9a-82ec00ac21ed4b0b4094ab1b5dfbcc35784c8c67.gz wocky/wocky-xmpp-writer.c | 5 +++++ 1 file changed, 5 insertions(+) commit ec14381d7e181456e515fef019d77b118a65ccb5 Author: Sjoerd Simons Date: Thu Feb 8 15:47:08 2007 +0000 Reinitialize the parser after each chunk when not in stream mode 20070208154708-93b9a-7f92d7d174ea5da1ba624838e3a94e6b54306391.gz wocky/wocky-xmpp-reader.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) commit c6f178501aaadebdd1ab6dcdd21725c739853239 Author: Sjoerd Simons Date: Thu Feb 8 15:46:31 2007 +0000 Add debugging 20070208154631-93b9a-fb77ac76d5b324196b2b84a8f57077cadc6ec14e.gz wocky/wocky-xmpp-reader.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) commit af18cf0a81cd75e41ef0cc311d0e195d5991d465 Author: Sjoerd Simons Date: Thu Feb 8 15:45:34 2007 +0000 Add xmpp debugging categories 20070208154534-93b9a-be8e1257a1ccf376fd7134229d62d5187219f7cb.gz wocky/wocky-debug.c | 6 +++++- wocky/wocky-debug.h | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) commit 456ea6b3c19601fdbacf438596aca68c46000adb Author: Sjoerd Simons Date: Fri Feb 2 13:48:00 2007 +0000 Fix conflicts in libwocky 20070202134800-93b9a-accfe9e4ec5f2ac7d7d4360889743b8e09d9ca4b.gz wocky/wocky-xmpp-reader.c | 8 ++++---- wocky/wocky-xmpp-reader.h | 6 ++++-- wocky/wocky-xmpp-writer.c | 8 ++++---- wocky/wocky-xmpp-writer.h | 3 ++- 4 files changed, 14 insertions(+), 11 deletions(-) commit 11e8272e8ad14c1eeac8ba162227c3626fedf11f Author: Sjoerd Simons Date: Wed Jan 24 23:10:56 2007 +0000 If not in stream mode, clear the parser for every new buffer 20070124231056-93b9a-a17e06fc79026e8dca6cf50db26c9f18eb112397.gz wocky/wocky-xmpp-reader.c | 3 +++ 1 file changed, 3 insertions(+) commit 4cc6811422ef30741f9c61bf51fa335d93a515be Author: Sjoerd Simons Date: Wed Jan 24 22:54:24 2007 +0000 Xmpp stanza end on depth 1 in stream mode and depth 0 in non-streaming mode 20070124225424-93b9a-0169f09b6155c007c04c7dc66d453bd600291ee8.gz wocky/wocky-xmpp-reader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 48a09308f5782730a8b77fef7f8f45fdc5da2336 Author: Sjoerd Simons Date: Wed Jan 24 22:09:34 2007 +0000 Let the xmpp reader provide a non-stream mode 20070124220934-93b9a-b436df2985b6622eb18b66a2116af4ed6375c65f.gz wocky/wocky-xmpp-reader.c | 18 +++++++++++++++--- wocky/wocky-xmpp-reader.h | 4 ++-- 2 files changed, 17 insertions(+), 5 deletions(-) commit 238939565225f060e327b4fcd100eccd85575806 Author: Sjoerd Simons Date: Wed Jan 24 22:09:05 2007 +0000 Provide a non-stream mode 20070124220905-93b9a-4d27e82d447907538d5b5e9215583bc4fb6fa0f9.gz wocky/wocky-xmpp-writer.c | 15 +++++++++++++++ wocky/wocky-xmpp-writer.h | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) commit 37f2ef26d25198ac6f39d5122d91f2da66995413 Author: Sjoerd Simons Date: Tue Jan 23 12:02:45 2007 +0000 Only recognize the standard stream namespaces after a stream open 20070123120245-93b9a-78aa5121c17e4668e8fdf11b6a0a66d5848751ce.gz wocky/wocky-xmpp-writer.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) commit ef14dec7c25700a1ada1436a41610154a6e2dc10 Author: Sjoerd Simons Date: Fri Feb 2 13:37:11 2007 +0000 Refactor xmpp magic into it's own seperate library 20070202133711-93b9a-4dec550fce51511f5f452fa5e1c2158049fdc2f6.gz wocky/wocky-debug.c | 55 ++++++++ wocky/wocky-debug.h | 49 +++++++ wocky/wocky-xmpp-connection.c | 275 +++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-connection.h | 73 ++++++++++ wocky/wocky-xmpp-node.c | 281 ++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-node.h | 131 ++++++++++++++++++ wocky/wocky-xmpp-reader.c | 310 ++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-reader.h | 63 +++++++++ wocky/wocky-xmpp-stanza.c | 99 ++++++++++++++ wocky/wocky-xmpp-stanza.h | 62 +++++++++ wocky/wocky-xmpp-writer.c | 271 ++++++++++++++++++++++++++++++++++++ wocky/wocky-xmpp-writer.h | 76 +++++++++++ 12 files changed, 1745 insertions(+) commit d3816f063f3902037b69763d91e57738d7e781e5 Author: Sjoerd Simons Date: Tue Mar 17 18:52:43 2009 +0000 Initial commit README | 1 + 1 file changed, 1 insertion(+) telepathy-gabble-0.18.3/lib/ext/wocky/NEWS0000644000175000017500000000002511544576223021403 0ustar00cassidycassidy00000000000000No news is good news telepathy-gabble-0.18.3/lib/ext/wocky/ltmain.sh0000644000175000017500000105152212332443661022530 0ustar00cassidycassidy00000000000000 # libtool (GNU libtool) 2.4.2 # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, # 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool 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. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, # or obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Usage: $progname [OPTION]... [MODE-ARG]... # # Provide generalized library-building support services. # # --config show all configuration variables # --debug enable verbose shell tracing # -n, --dry-run display commands without modifying any files # --features display basic configuration information and exit # --mode=MODE use operation mode MODE # --preserve-dup-deps don't remove duplicate dependency libraries # --quiet, --silent don't print informational messages # --no-quiet, --no-silent # print informational messages (default) # --no-warn don't display warning messages # --tag=TAG use configuration variables from tag TAG # -v, --verbose print more informational messages than default # --no-verbose don't print the extra informational messages # --version print version information # -h, --help, --help-all print short, long, or detailed help message # # MODE must be one of the following: # # clean remove files from the build directory # compile compile a source file into a libtool object # execute automatically set library path, then run a program # finish complete the installation of libtool libraries # install install libraries or executables # link create a library or an executable # uninstall remove libraries from an installed directory # # MODE-ARGS vary depending on the MODE. When passed as first option, # `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. # Try `$progname --help --mode=MODE' for a more detailed description of MODE. # # When reporting a bug, please describe a test case to reproduce it and # include the following information: # # host-triplet: $host # shell: $SHELL # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) # $progname: (GNU libtool) 2.4.2 # automake: $automake_version # autoconf: $autoconf_version # # Report bugs to . # GNU libtool home page: . # General help using GNU software: . PROGRAM=libtool PACKAGE=libtool VERSION=2.4.2 TIMESTAMP="" package_revision=1.3337 # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # NLS nuisances: We save the old values to restore during execute mode. lt_user_locale= lt_safe_locale= for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${$lt_var+set}\" = set; then save_$lt_var=\$$lt_var $lt_var=C export $lt_var lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" fi" done LC_ALL=C LANGUAGE=C export LANGUAGE LC_ALL $lt_unset CDPATH # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath="$0" : ${CP="cp -f"} test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} : ${Xsed="$SED -e 1s/^X//"} # Global variables: EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. exit_status=$EXIT_SUCCESS # Make sure IFS has a sensible default lt_nl=' ' IFS=" $lt_nl" dirname="s,/[^/]*$,," basename="s,^.*/,," # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_dirname may be replaced by extended shell implementation # func_basename file func_basename () { func_basename_result=`$ECHO "${1}" | $SED "$basename"` } # func_basename may be replaced by extended shell implementation # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` } # func_dirname_and_basename may be replaced by extended shell implementation # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # func_strip_suffix prefix name func_stripname () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname may be replaced by extended shell implementation # These SED scripts presuppose an absolute path with a trailing slash. pathcar='s,^/\([^/]*\).*$,\1,' pathcdr='s,^/[^/]*,,' removedotparts=':dotsl s@/\./@/@g t dotsl s,/\.$,/,' collapseslashes='s@/\{1,\}@/@g' finalslash='s,/*$,/,' # func_normal_abspath PATH # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. # value returned in "$func_normal_abspath_result" func_normal_abspath () { # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` while :; do # Processed it all yet? if test "$func_normal_abspath_tpath" = / ; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result" ; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_relative_path SRCDIR DSTDIR # generates a relative path from SRCDIR to DSTDIR, with a trailing # slash if non-empty, suitable for immediately appending a filename # without needing to append a separator. # value returned in "$func_relative_path_result" func_relative_path () { func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=${func_dirname_result} if test "x$func_relative_path_tlibdir" = x ; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test "x$func_stripname_result" != x ; then func_relative_path_result=${func_relative_path_result}/${func_stripname_result} fi # Normalisation. If bindir is libdir, return empty string, # else relative path ending with a slash; either way, target # file name can be directly appended. if test ! -z "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result/" func_relative_path_result=$func_stripname_result fi } # The name of this program: func_dirname_and_basename "$progpath" progname=$func_basename_result # Make sure we have an absolute path for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=$func_dirname_result progdir=`cd "$progdir" && pwd` progpath="$progdir/$progname" ;; *) save_IFS="$IFS" IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS="$save_IFS" test -x "$progdir/$progname" && break done IFS="$save_IFS" test -n "$progdir" || progdir=`pwd` progpath="$progdir/$progname" ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='s/\([`"$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' # Sed substitution that converts a w32 file name or path # which contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-`\' parameter expansions in output of double_quote_subst that were # `\'-ed in input to the same. If an odd number of `\' preceded a '$' # in input to double_quote_subst, that '$' was protected from expansion. # Since each input `\' is now two `\'s, look for any number of runs of # four `\'s followed by two `\'s and then a '$'. `\' that '$'. bs='\\' bs2='\\\\' bs4='\\\\\\\\' dollar='\$' sed_double_backslash="\ s/$bs4/&\\ /g s/^$bs2$dollar/$bs&/ s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g s/\n//g" # Standard options: opt_dry_run=false opt_help=false opt_quiet=false opt_verbose=false opt_warning=: # func_echo arg... # Echo program name prefixed message, along with the current mode # name if it has been set yet. func_echo () { $ECHO "$progname: ${opt_mode+$opt_mode: }$*" } # func_verbose arg... # Echo program name prefixed message in verbose mode only. func_verbose () { $opt_verbose && func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_error arg... # Echo program name prefixed message to standard error. func_error () { $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 } # func_warning arg... # Echo program name prefixed warning message to standard error. func_warning () { $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 # bash bug again: : } # func_fatal_error arg... # Echo program name prefixed message to standard error, and exit. func_fatal_error () { func_error ${1+"$@"} exit $EXIT_FAILURE } # func_fatal_help arg... # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { func_error ${1+"$@"} func_fatal_error "$help" } help="Try \`$progname --help' for more information." ## default # func_grep expression filename # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $GREP "$1" "$2" >/dev/null 2>&1 } # func_mkdir_p directory-path # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { my_directory_path="$1" my_dir_list= if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then # Protect directory names starting with `-' case $my_directory_path in -*) my_directory_path="./$my_directory_path" ;; esac # While some portion of DIR does not yet exist... while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` done my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` save_mkdir_p_IFS="$IFS"; IFS=':' for my_dir in $my_dir_list; do IFS="$save_mkdir_p_IFS" # mkdir can fail with a `File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$my_dir" 2>/dev/null || : done IFS="$save_mkdir_p_IFS" # Bail out if we (or some other process) failed to create a directory. test -d "$my_directory_path" || \ func_fatal_error "Failed to create \`$1'" fi } # func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, STRING is the basename for that directory. func_mktempdir () { my_template="${TMPDIR-/tmp}/${1-$progname}" if test "$opt_dry_run" = ":"; then # Return a directory name, but don't create it in dry-run mode my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` if test ! -d "$my_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race my_tmpdir="${my_template}-${RANDOM-0}$$" save_mktempdir_umask=`umask` umask 0077 $MKDIR "$my_tmpdir" umask $save_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$my_tmpdir" || \ func_fatal_error "cannot create temporary directory \`$my_tmpdir'" fi $ECHO "$my_tmpdir" } # func_quote_for_eval arg # Aesthetically quote ARG to be evaled later. # This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT # is double-quoted, suitable for a subsequent eval, whereas # FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters # which are still active within double quotes backslashified. func_quote_for_eval () { case $1 in *[\\\`\"\$]*) func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; *) func_quote_for_eval_unquoted_result="$1" ;; esac case $func_quote_for_eval_unquoted_result in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and and variable # expansion for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" ;; *) func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" esac } # func_quote_for_expand arg # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { case $1 in *[\\\`\"]*) my_arg=`$ECHO "$1" | $SED \ -e "$double_quote_subst" -e "$sed_double_backslash"` ;; *) my_arg="$1" ;; esac case $my_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") my_arg="\"$my_arg\"" ;; esac func_quote_for_expand_result="$my_arg" } # func_show_eval cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$my_cmd" my_status=$? if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_show_eval_locale cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$lt_user_locale $my_cmd" my_status=$? eval "$lt_safe_locale" if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_tr_sh # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_version # Echo version message to standard output and exit. func_version () { $opt_debug $SED -n '/(C)/!b go :more /\./!{ N s/\n# / / b more } :go /^# '$PROGRAM' (GNU /,/# warranty; / { s/^# // s/^# *$// s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ p }' < "$progpath" exit $? } # func_usage # Echo short help message to standard output and exit. func_usage () { $opt_debug $SED -n '/^# Usage:/,/^# *.*--help/ { s/^# // s/^# *$// s/\$progname/'$progname'/ p }' < "$progpath" echo $ECHO "run \`$progname --help | more' for full usage" exit $? } # func_help [NOEXIT] # Echo long help message to standard output and exit, # unless 'noexit' is passed as argument. func_help () { $opt_debug $SED -n '/^# Usage:/,/# Report bugs to/ { :print s/^# // s/^# *$// s*\$progname*'$progname'* s*\$host*'"$host"'* s*\$SHELL*'"$SHELL"'* s*\$LTCC*'"$LTCC"'* s*\$LTCFLAGS*'"$LTCFLAGS"'* s*\$LD*'"$LD"'* s/\$with_gnu_ld/'"$with_gnu_ld"'/ s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/ s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/ p d } /^# .* home page:/b print /^# General help using/b print ' < "$progpath" ret=$? if test -z "$1"; then exit $ret fi } # func_missing_arg argname # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $opt_debug func_error "missing argument for $1." exit_cmd=exit } # func_split_short_opt shortopt # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. func_split_short_opt () { my_sed_short_opt='1s/^\(..\).*$/\1/;q' my_sed_short_rest='1s/^..\(.*\)$/\1/;q' func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` } # func_split_short_opt may be replaced by extended shell implementation # func_split_long_opt longopt # Set func_split_long_opt_name and func_split_long_opt_arg shell # variables after splitting LONGOPT at the `=' sign. func_split_long_opt () { my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' my_sed_long_arg='1s/^--[^=]*=//' func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` } # func_split_long_opt may be replaced by extended shell implementation exit_cmd=: magic="%%%MAGIC variable%%%" magic_exe="%%%MAGIC EXE variable%%%" # Global variables. nonopt= preserve_args= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "${1}=\$${1}\${2}" } # func_append may be replaced by extended shell implementation # func_append_quoted var value # Quote VALUE and append to the end of shell variable VAR, separated # by a space. func_append_quoted () { func_quote_for_eval "${2}" eval "${1}=\$${1}\\ \$func_quote_for_eval_result" } # func_append_quoted may be replaced by extended shell implementation # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "${@}"` } # func_arith may be replaced by extended shell implementation # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` } # func_len may be replaced by extended shell implementation # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` } # func_lo2o may be replaced by extended shell implementation # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` } # func_xform may be replaced by extended shell implementation # func_fatal_configuration arg... # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func_error ${1+"$@"} func_error "See the $PACKAGE documentation for more information." func_fatal_error "Fatal configuration error." } # func_config # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # Display the features supported by this script. func_features () { echo "host: $host" if test "$build_libtool_libs" = yes; then echo "enable shared libraries" else echo "disable shared libraries" fi if test "$build_old_libs" = yes; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag tagname # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname="$1" re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf="/$re_begincf/,/$re_endcf/p" # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Option defaults: opt_debug=: opt_dry_run=false opt_config=false opt_preserve_dup_deps=false opt_features=false opt_finish=false opt_help=false opt_help_all=false opt_silent=: opt_warning=: opt_verbose=: opt_silent=false opt_verbose=false # Parse options once, thoroughly. This comes as soon as possible in the # script to make things like `--version' happen as quickly as we can. { # this just eases exit handling while test $# -gt 0; do opt="$1" shift case $opt in --debug|-x) opt_debug='set -x' func_echo "enabling shell trace mode" $opt_debug ;; --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) opt_config=: func_config ;; --dlopen|-dlopen) optarg="$1" opt_dlopen="${opt_dlopen+$opt_dlopen }$optarg" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) opt_features=: func_features ;; --finish) opt_finish=: set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help_all=: opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_mode="$optarg" case $optarg in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_silent=false func_append preserve_args " $opt" ;; --no-warning|--no-warn) opt_warning=false func_append preserve_args " $opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $opt" ;; --silent|--quiet) opt_silent=: func_append preserve_args " $opt" opt_verbose=false ;; --verbose|-v) opt_verbose=: func_append preserve_args " $opt" opt_silent=false ;; --tag) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_tag="$optarg" func_append preserve_args " $opt $optarg" func_enable_tag "$optarg" shift ;; -\?|-h) func_usage ;; --help) func_help ;; --version) func_version ;; # Separate optargs to long options: --*=*) func_split_long_opt "$opt" set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-n*|-v*) func_split_short_opt "$opt" set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) break ;; -*) func_fatal_help "unrecognized option \`$opt'" ;; *) set dummy "$opt" ${1+"$@"}; shift; break ;; esac done # Validate options: # save first non-option argument if test "$#" -gt 0; then nonopt="$opt" shift fi # preserve --debug test "$opt_debug" = : || func_append preserve_args " --debug" case $host in *cygwin* | *mingw* | *pw32* | *cegcc*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then func_fatal_configuration "not configured to build any kind of library" fi # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test "$opt_mode" != execute; then func_error "unrecognized option \`-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$progname --help --mode=$opt_mode' for more information." } # Bail if the options were screwed $exit_cmd $EXIT_FAILURE } ## ----------- ## ## Main. ## ## ----------- ## # func_lalib_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null \ | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_unsafe_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if `file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case "$lalib_p_line" in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test "$lalib_p" = yes } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { func_lalib_p "$1" } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $opt_debug save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$save_ifs eval cmd=\"$cmd\" func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. func_source () { $opt_debug case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case "$lt_sysroot:$1" in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result="=$func_stripname_result" ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $opt_debug if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with \`--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=${1} if test "$build_libtool_libs" = yes; then write_lobj=\'${2}\' else write_lobj=none fi if test "$build_old_libs" = yes; then write_oldobj=\'${3}\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$lt_sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $opt_debug # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result="" if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result" ; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $opt_debug if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $opt_debug # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $opt_debug if test -z "$2" && test -n "$1" ; then func_error "Could not determine host file name corresponding to" func_error " \`$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result="$1" fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $opt_debug if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " \`$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result="$3" fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $opt_debug case $4 in $1 ) func_to_host_path_result="$3$func_to_host_path_result" ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via `$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $opt_debug $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $opt_debug case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result="$1" } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result="$func_convert_core_msys_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via `$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $opt_debug if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd="func_convert_path_${func_stripname_result}" fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $opt_debug func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result="$1" } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_msys_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_mode_compile arg... func_mode_compile () { $opt_debug # Get the compilation command and the source file. base_compile= srcfile="$nonopt" # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg="$arg" arg_mode=normal ;; target ) libobj="$arg" arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify \`-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs="$IFS"; IFS=',' for arg in $args; do IFS="$save_ifs" func_append_quoted lastarg "$arg" done IFS="$save_ifs" func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg="$srcfile" srcfile="$arg" ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with \`-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj="$func_basename_result" } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from \`$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name \`$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname="$func_basename_result" xdir="$func_dirname_result" lobj=${xdir}$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test "$suppress_opt" = yes; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test "$compiler_c_o" = yes; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test "$need_locks" != no; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test "$opt_mode" = compile && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a \`.o' file suitable for static linking -static only build a \`.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode \`$opt_mode'" ;; esac echo $ECHO "Try \`$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test "$opt_help" = :; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | sed -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | sed '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $opt_debug # The first argument is the command name. cmd="$nonopt" test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "\`$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "\`$file' was not linked with \`-export-dynamic'" continue fi func_dirname "$file" "" "." dir="$func_dirname_result" if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir="$func_dirname_result" ;; *) func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file="$progdir/$program" elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if test "X$opt_dry_run" = Xfalse; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS fi } test "$opt_mode" = execute && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $opt_debug libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "\`$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument \`$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and \`=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_silent && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the \`-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the \`$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the \`$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test "$opt_mode" = finish && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $opt_debug # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" func_append install_prog "$func_quote_for_eval_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=yes ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test "x$prev" = x-m && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" func_append install_prog " $func_quote_for_eval_result" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi func_append install_shared_prog " $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the \`$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_for_eval "$install_override_mode" func_append install_shared_prog " -m $func_quote_for_eval_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else func_dirname_and_basename "$dest" "" "." destdir="$func_dirname_result" destname="$func_basename_result" # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "\`$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "\`$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir="$func_dirname_result" func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking \`$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname="$1" shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme="$stripme" case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme="" ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try `ln -sf' first, because the `ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib="$destdir/$realname" func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name="$func_basename_result" instname="$dir/$name"i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest="$destfile" destfile= ;; *) func_fatal_help "cannot copy a libtool object to \`$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script \`$wrapper'" finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then func_warning "\`$lib' has not been installed in \`$libdir'" finalize=no fi done relink_command= func_source "$wrapper" outputname= if test "$fast_install" = no && test -n "$relink_command"; then $opt_dry_run || { if test "$finalize" = yes; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file="$func_basename_result" outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_silent || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink \`$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file="$outputname" else func_warning "cannot relink \`$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name="$func_basename_result" # Set up the ranlib parameters. oldlib="$destdir/$name" func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $tool_oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run \`$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test "$opt_mode" = install && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $opt_debug my_outputname="$1" my_originator="$2" my_pic_p="${3-no}" my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms="${my_outputname}S.c" else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${my_outputname}.nm" func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then func_verbose "generating symbol list for \`$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$outputname.exp" $opt_dry_run || { $RM $export_symbols eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from \`$dlprefile'" func_basename "$dlprefile" name="$func_basename_result" case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename="" if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname" ; then func_basename "$dlprefile_dlname" dlprefile_dlbasename="$func_basename_result" else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename" ; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[]; LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = {\ { \"$my_originator\", (void *) 0 }," case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) if test "X$my_pic_p" != Xno; then pic_flag_for_symtable=" $pic_flag" fi ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' # Transform the symbol file into the correct name. symfileobj="$output_objdir/${my_outputname}S.$objext" case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for \`$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $opt_debug win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s,.*,import, p q } }'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $opt_debug sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $opt_debug match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive which possess that section. Heuristic: eliminate # all those which have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $opt_debug if func_cygming_gnu_implib_p "$1" ; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1" ; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result="" fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $opt_debug f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" if test "$lock_old_archive_extraction" = yes; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test "$lock_old_archive_extraction" = yes; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $opt_debug my_gentop="$1"; shift my_oldlibs=${1+"$@"} my_oldobjs="" my_xlib="" my_xabs="" my_xdir="" for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib="$func_basename_result" my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir="$my_gentop/$my_xlib_u" func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` darwin_base_archive=`basename "$darwin_archive"` darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches ; do func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" func_extract_an_archive "`pwd`" "${darwin_base_archive}" cd "$darwin_curdir" $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result="$my_oldobjs" } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory in which it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=\"$qECHO\" fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ which is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options which match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { case \" \$* \" in *\\ --lt-*) for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done ;; esac func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include /* declarations of non-ANSI functions */ #if defined(__MINGW32__) # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined(__CYGWIN__) # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined (other platforms) ... */ #endif /* portability defines, excluding path handling macros */ #if defined(_MSC_VER) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC # ifndef _INTPTR_T_DEFINED # define _INTPTR_T_DEFINED # define intptr_t int # endif #elif defined(__MINGW32__) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined(__CYGWIN__) # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined (other platforms) ... */ #endif #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) #if defined(LT_DEBUGWRAPPER) static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; int tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined (HAVE_DOS_BASED_FILE_SYSTEM) } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = q - p; p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (strcmp (str, pat) == 0) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else int len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { int orig_value_len = strlen (orig_value); int add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ int len = strlen (new_value); while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[len-1] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -n -e ' s/^\(.\{79\}\)\(..*\)/\1\ \2/ h s/\([\\"]\)/\\\1/g s/$/\\n/ s/\([^\n]*\).*/ fputs ("\1", f);/p g D' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $opt_debug case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_mode_link arg... func_mode_link () { $opt_debug case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module="${wl}-single_module" func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir="$arg" prev= continue ;; dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" test -f "$arg" \ || func_fatal_error "symbol file \`$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file \`$arg' does not exist" fi arg=$save_arg prev= continue ;; precious_regex) precious_files_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds="$arg" prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "\`-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between \`-L' and \`$1'" else func_fatal_error "need path for \`-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of \`$dir'" dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test "X$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module="${wl}-multi_module" continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "\`-no-install' is ignored for $host" func_warning "assuming \`-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-flto*|-fwhopr*|-fuse-linker-plugin) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test "$prev" = dlfiles; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the \`$prevarg' option requires an argument" if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname="$func_basename_result" libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" func_dirname "$output" "/" "" output_objdir="$func_dirname_result$objdir" func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps ; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test "$linkmode,$pass" = "lib,link"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs="$tmp_deplibs" fi if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi if test "$linkmode,$pass" = "lib,dlpreopen"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs="$dlprefiles" fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then func_warning "\`-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test "$linkmode" = lib; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no func_dirname "$lib" "" "." ladir="$func_dirname_result" lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l *.ltframework) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "\`-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=no case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi ;; pass_all) valid_a_lib=yes ;; esac if test "$valid_a_lib" != yes; then echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." else echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" fi # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "\`$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir="$func_dirname_result" dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" elif test "$linkmode" != prog && test "$linkmode" != lib; then func_fatal_error "\`$lib' is not a convenience library" fi tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test "$prefer_static_libs" = yes || test "$prefer_static_libs,$installed" = "built,no"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib="$l" done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then func_fatal_error "cannot -dlopen a convenience library: \`$lib'" fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of \`$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir="$ladir" fi ;; esac func_basename "$lib" laname="$func_basename_result" # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library \`$lib' was moved." dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$lt_sysroot$libdir" absdir="$lt_sysroot$libdir" fi test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir="$ladir" absdir="$abs_ladir" # Remove this search path later func_append notinst_path " $abs_ladir" else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir" && test "$linkmode" = prog; then func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" fi case "$host" in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { { test "$prefer_static_libs" = no || test "$prefer_static_libs,$installed" = "built,yes"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. case "$temp_rpath:" in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test "$use_static_libs" = built && test "$installed" = yes; then use_static_libs=no fi if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test "$installed" = no; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule="" for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule="$dlpremoduletest" break fi done if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then echo if test "$linkmode" = prog; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname="$1" shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc*) func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" func_basename "$soroot" soname="$func_basename_result" func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from \`$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for \`$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$opt_mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; *-*-sysv4*uw2*) add_dir="-L$dir" ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we can not # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null ; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library" ; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add="$dir/$old_library" fi elif test -n "$old_library"; then add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$absdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && test "$hardcode_minus_L" != yes && test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$opt_mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system can not link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs="$temp_deplibs" fi func_append newlib_search_path " $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path="$deplib" ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of \`$dir'" absdir="$dir" fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl" ; then depdepl="$absdir/$objdir/$depdepl" darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" path= fi fi ;; *) path="-L$absdir/$objdir" ;; esac else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "\`$deplib' seems to be moved" path="-L$absdir" fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test "$pass" = link; then if test "$linkmode" = "prog"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" fi if test "$linkmode" = prog || test "$linkmode" = lib; then dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "\`-R' is ignored for archives" test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "\`-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "\`-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test "$module" = no && \ func_fatal_help "libtool library \`$output' must begin with \`lib'" if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test "$dlself" != no && \ func_warning "\`-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test "$#" -gt 1 && \ func_warning "ignoring multiple \`-rpath's for a libtool library" install_libdir="$1" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "\`-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 shift IFS="$save_ifs" test -n "$7" && \ func_fatal_help "too many parameters to \`-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$1" number_minor="$2" number_revision="$3" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|qnx|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_minor" lt_irix_increment=no ;; esac ;; no) current="$1" revision="$2" age="$3" ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT \`$current' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION \`$revision' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE \`$age' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE \`$age' is greater than the current interface number \`$current'" func_fatal_error "\`$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current" ;; irix | nonstopux) if test "X$lt_irix_increment" = "Xno"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring:${iface}.0" done # Make executables depend on our current version. func_append verstring ":${current}.0" ;; qnx) major=".$current" versuffix=".$current" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; *) func_fatal_configuration "unknown library version type \`$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then func_warning "undefined symbols not allowed in $host shared libraries" build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi func_generate_dlsyms "$libname" "$libname" "yes" func_append libobjs " $symfileobj" test "X$libobjs" = "X " && libobjs= if test "$opt_mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) if test "X$precious_files_regex" != "X"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test "X$deplibs_check_method" = "Xnone"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs="$new_libs" # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then # Remove ${wl} instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$opt_mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname="$1" shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi lib="$output_objdir/$realname" linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols="$output_objdir/$libname.uexp" func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile if test "x`$SED 1q $export_symbols`" != xEXPORTS; then # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols="$export_symbols" export_symbols= always_export_symbols=yes fi fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs="$IFS"; IFS='~' for cmd1 in $cmds; do IFS="$save_ifs" # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test "$try_normal_branch" = yes \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=${output_objdir}/${output_la}.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS="$save_ifs" if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test "$compiler_needs_object" = yes && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test "X$skipped_export" != "X:" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then output=${output_objdir}/${output_la}.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test "$compiler_needs_object" = yes; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-${k}.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test "X$objlist" = X || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-${k}.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\${concat_cmds}$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi if ${skipped_export-false}; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi fi test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi if ${skipped_export-false}; then if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi fi libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "\`-R' is ignored for objects" test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for objects" test -n "$release" && \ func_warning "\`-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object \`$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec and hope we can get by with # turning comma into space.. wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` else gentop="$output_objdir/${obj}x" func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" # Create the old-style object. reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for programs" test -n "$release" && \ func_warning "\`-release' is ignored for programs" test "$preload" = yes \ && test "$dlopen_support" = unknown \ && test "$dlopen_self" = unknown \ && test "$dlopen_self_static" = unknown && \ func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test "$tagname" = CXX ; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " ${wl}-bind_at_load" func_append finalize_command " ${wl}-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs="$new_libs" func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" "no" # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=yes case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=no ;; *cygwin* | *mingw* ) if test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; *) if test "$need_relink" = no || test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; esac if test "$wrappers_required" = no; then # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.${objext}"; then func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' fi exit $exit_status fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" func_warning "this platform does not like uninstalled shared libraries" func_warning "\`$output' will be relinked during installation" else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource="$output_path/$objdir/lt-$output_name.c" cwrapper="$output_path/$output_name.exe" $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host" ; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save $symfileobj" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" if test "$preload" = yes && test -f "$symfileobj"; then func_append oldobjs " $symfileobj" fi fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase="$func_basename_result" case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name="$func_basename_result" func_resolve_sysroot "$deplib" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles="$newdlprefiles" fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test "x$bindir" != x ; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that can not go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } { test "$opt_mode" = link || test "$opt_mode" = relink; } && func_mode_link ${1+"$@"} # func_mode_uninstall arg... func_mode_uninstall () { $opt_debug RM="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) func_append RM " $arg"; rmforce=yes ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir="$func_dirname_result" if test "X$dir" = X.; then odir="$objdir" else odir="$dir/$objdir" fi func_basename "$file" name="$func_basename_result" test "$opt_mode" = uninstall && odir="$dir" # Remember odir for removal later, being careful to avoid duplicates if test "$opt_mode" = clean; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case "$opt_mode" in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test "$pic_object" != none; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test "$non_pic_object" != none; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test "$opt_mode" = clean ; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name" ; then func_append rmfiles " $odir/lt-${noexename}.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } { test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && func_mode_uninstall ${1+"$@"} test -z "$opt_mode" && { help="$generic_help" func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode \`$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: # vi:sw=2 telepathy-gabble-0.18.3/lib/ext/wocky/wocky/0000775000175000017500000000000012332445273022041 5ustar00cassidycassidy00000000000000telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-xmpp-writer.c0000664000175000017500000003427012212322440025626 0ustar00cassidycassidy00000000000000/* * wocky-xmpp-writer.c - Source for WockyXmppWriter * Copyright (C) 2006-2009 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** * SECTION: wocky-xmpp-writer * @title: WockyXmppWriter * @short_description: Xmpp stanza to XML serializer * * The #WockyXmppWriter serializes #WockyStanzas and XMPP stream opening * and closing to raw XML. The various functions provide a pointer to an * internal buffer, which remains valid until the next call to the writer. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "wocky-xmpp-writer.h" G_DEFINE_TYPE (WockyXmppWriter, wocky_xmpp_writer, G_TYPE_OBJECT) #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_XMPP_WRITER #include "wocky-debug-internal.h" /* properties */ enum { PROP_STREAMING_MODE = 1, }; /* private structure */ struct _WockyXmppWriterPrivate { gboolean dispose_has_run; xmlTextWriterPtr xmlwriter; GQuark current_ns; GQuark stream_ns; gboolean stream_mode; xmlBufferPtr buffer; }; static void wocky_xmpp_writer_init (WockyXmppWriter *self) { WockyXmppWriterPrivate *priv; self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_XMPP_WRITER, WockyXmppWriterPrivate); priv = self->priv; priv->current_ns = 0; priv->stream_ns = 0; priv->buffer = xmlBufferCreate (); priv->xmlwriter = xmlNewTextWriterMemory (priv->buffer, 0); priv->stream_mode = TRUE; /* xmlTextWriterSetIndent (priv->xmlwriter, 1); */ } static void wocky_xmpp_writer_dispose (GObject *object); static void wocky_xmpp_writer_finalize (GObject *object); static void wocky_xmpp_write_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec); static void wocky_xmpp_write_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec); static void wocky_xmpp_writer_class_init (WockyXmppWriterClass *wocky_xmpp_writer_class) { GObjectClass *object_class = G_OBJECT_CLASS (wocky_xmpp_writer_class); GParamSpec *param_spec; g_type_class_add_private (wocky_xmpp_writer_class, sizeof (WockyXmppWriterPrivate)); object_class->dispose = wocky_xmpp_writer_dispose; object_class->finalize = wocky_xmpp_writer_finalize; object_class->set_property = wocky_xmpp_write_set_property; object_class->get_property = wocky_xmpp_write_get_property; param_spec = g_param_spec_boolean ("streaming-mode", "streaming-mode", "Whether the xml to be written is one big stream or separate documents", TRUE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_STREAMING_MODE, param_spec); } void wocky_xmpp_writer_dispose (GObject *object) { WockyXmppWriter *self = WOCKY_XMPP_WRITER (object); WockyXmppWriterPrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; /* release any references held by the object here */ if (G_OBJECT_CLASS (wocky_xmpp_writer_parent_class)->dispose) G_OBJECT_CLASS (wocky_xmpp_writer_parent_class)->dispose (object); } void wocky_xmpp_writer_finalize (GObject *object) { WockyXmppWriter *self = WOCKY_XMPP_WRITER (object); WockyXmppWriterPrivate *priv = self->priv; /* free any data held directly by the object here */ xmlFreeTextWriter (priv->xmlwriter); xmlBufferFree (priv->buffer); G_OBJECT_CLASS (wocky_xmpp_writer_parent_class)->finalize (object); } static void wocky_xmpp_write_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyXmppWriter *writer = WOCKY_XMPP_WRITER (object); WockyXmppWriterPrivate *priv = writer->priv; switch (property_id) { case PROP_STREAMING_MODE: priv->stream_mode = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_xmpp_write_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyXmppWriter *writer = WOCKY_XMPP_WRITER (object); WockyXmppWriterPrivate *priv = writer->priv; switch (property_id) { case PROP_STREAMING_MODE: g_value_set_boolean (value, priv->stream_mode); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } /** * wocky_xmpp_writer_new * * Convenience function to create a new #WockyXmppWriter. * * Returns: a new #WockyXmppWriter */ WockyXmppWriter * wocky_xmpp_writer_new (void) { return g_object_new (WOCKY_TYPE_XMPP_WRITER, NULL); } /** * wocky_xmpp_writer_new_no_stream * * Convenience function to create a new #WockyXmppWriter that has streaming * mode disabled. * * Returns: a new #WockyXmppWriter in non-streaming mode */ WockyXmppWriter * wocky_xmpp_writer_new_no_stream (void) { return g_object_new (WOCKY_TYPE_XMPP_WRITER, "streaming-mode", FALSE, NULL); } /** * wocky_xmpp_writer_stream_open: * @writer: a WockyXmppWriter * @to: the target of the stream opening (usually the xmpp server name) * @from: the sender of the stream opening (usually the jid of the client) * @version: XMPP version * @lang: default XMPP stream language * @id: XMPP Stream ID, if any, or NULL * @data: location to store a pointer to the data buffer * @length: length of the data buffer * * Create the XML opening header of an XMPP stream. The result is available in * the @data buffer. The buffer is only valid until the next call to a function * the writer. * * This function can only be called in streaming mode. */ void wocky_xmpp_writer_stream_open (WockyXmppWriter *writer, const gchar *to, const gchar *from, const gchar *version, const gchar *lang, const gchar *id, const guint8 **data, gsize *length) { WockyXmppWriterPrivate *priv = writer->priv; g_assert (priv->stream_mode); xmlBufferEmpty (priv->buffer); xmlTextWriterWriteString (priv->xmlwriter, (xmlChar *) "\n" \ "xmlwriter, (xmlChar *)" to=\""); xmlTextWriterFlush (priv->xmlwriter); xmlAttrSerializeTxtContent (priv->buffer, NULL, NULL, (xmlChar *) to); xmlTextWriterWriteString (priv->xmlwriter, (xmlChar *)"\""); } if (from != NULL) { xmlTextWriterWriteString (priv->xmlwriter, (xmlChar *)" from=\""); xmlTextWriterFlush (priv->xmlwriter); xmlAttrSerializeTxtContent (priv->buffer, NULL, NULL, (xmlChar *) from); xmlTextWriterWriteString (priv->xmlwriter, (xmlChar *)"\""); } if (version != NULL) { xmlTextWriterWriteString (priv->xmlwriter, (xmlChar *)" version=\""); xmlTextWriterFlush (priv->xmlwriter); xmlAttrSerializeTxtContent (priv->buffer, NULL, NULL, (xmlChar *) version); xmlTextWriterWriteString (priv->xmlwriter, (xmlChar *)"\""); } if (lang != NULL) { xmlTextWriterWriteString (priv->xmlwriter, (xmlChar *)" xml:lang=\""); xmlTextWriterFlush (priv->xmlwriter); xmlAttrSerializeTxtContent (priv->buffer, NULL, NULL, (xmlChar *) lang); xmlTextWriterWriteString (priv->xmlwriter, (xmlChar *)"\""); } if (id != NULL) { xmlTextWriterWriteString (priv->xmlwriter, (xmlChar *)" id=\""); xmlTextWriterFlush (priv->xmlwriter); xmlAttrSerializeTxtContent (priv->buffer, NULL, NULL, (xmlChar *) id); xmlTextWriterWriteString (priv->xmlwriter, (xmlChar *)"\""); } xmlTextWriterWriteString (priv->xmlwriter, (xmlChar *) ">\n"); xmlTextWriterFlush (priv->xmlwriter); *data = (const guint8 *)priv->buffer->content; *length = priv->buffer->use; /* Set the magic known namespaces */ priv->current_ns = g_quark_from_string ("jabber:client"); priv->stream_ns = g_quark_from_string ("http://etherx.jabber.org/streams"); DEBUG ("Writing stream opening: %.*s", (int) *length, *data); } /** * wocky_xmpp_writer_stream_close: * @writer: a WockyXmppWriter * @data: location to store a pointer to the data buffer * @length: length of the data buffer * * Create the XML closing footer of an XMPP stream . The result is available * in the @data buffer. The buffer is only valid until the next call to a * function * * This function can only be called in streaming mode. */ void wocky_xmpp_writer_stream_close (WockyXmppWriter *writer, const guint8 **data, gsize *length) { WockyXmppWriterPrivate *priv = writer->priv; static const guint8 *close = (const guint8 *)"\n"; g_assert (priv->stream_mode); *data = close; *length = strlen ((gchar *) close); DEBUG ("Writing stream close: %.*s", (int) *length, *data); } static void _xml_write_node (WockyXmppWriter *writer, WockyNode *node); static gboolean _write_attr (const gchar *key, const gchar *value, const gchar *prefix, const gchar *ns, gpointer user_data) { WockyXmppWriter *self = WOCKY_XMPP_WRITER (user_data); WockyXmppWriterPrivate *priv = self->priv; GQuark attrns = 0; if (ns != NULL) { attrns = g_quark_from_string (ns); } if (attrns == 0 || attrns == priv->current_ns) { xmlTextWriterWriteAttribute (priv->xmlwriter, (const xmlChar *)key, (const xmlChar *)value); } else if (attrns == priv->stream_ns) { xmlTextWriterWriteAttributeNS (priv->xmlwriter, (const xmlChar *)"stream", (const xmlChar *)key, (const xmlChar *)NULL, (const xmlChar *)value); } else { xmlTextWriterWriteAttributeNS (priv->xmlwriter, (const xmlChar *)prefix, (const xmlChar *)key, (const xmlChar *)ns, (const xmlChar *)value); } return TRUE; } static gboolean _write_child (WockyNode *node, gpointer user_data) { _xml_write_node (WOCKY_XMPP_WRITER (user_data), node); return TRUE; } static void _xml_write_node (WockyXmppWriter *writer, WockyNode *node) { const gchar *l; GQuark oldns; WockyXmppWriterPrivate *priv = writer->priv; oldns = priv->current_ns; if (node->ns == 0 || oldns == node->ns) { /* Another element in the current namespace */ xmlTextWriterStartElement (priv->xmlwriter, (const xmlChar*) node->name); } else if (node->ns == priv->stream_ns) { xmlTextWriterStartElementNS(priv->xmlwriter, (const xmlChar *) "stream", (const xmlChar *) node->name, NULL); } else { priv->current_ns = node->ns; xmlTextWriterStartElementNS (priv->xmlwriter, NULL, (const xmlChar *) node->name, (const xmlChar *) wocky_node_get_ns (node)); } wocky_node_each_attribute (node, _write_attr, writer); l = wocky_node_get_language (node); if (l != NULL) { xmlTextWriterWriteAttributeNS(priv->xmlwriter, (const xmlChar *)"xml", (const xmlChar *)"lang", NULL, (const xmlChar *)l); } wocky_node_each_child (node, _write_child, writer); if (node->content != NULL) { xmlTextWriterWriteString (priv->xmlwriter, (const xmlChar*)node->content); } xmlTextWriterEndElement (priv->xmlwriter); priv->current_ns = oldns; } static void _write_node_tree (WockyXmppWriter *writer, WockyNodeTree *tree, const guint8 **data, gsize *length) { WockyXmppWriterPrivate *priv = writer->priv; xmlBufferEmpty (priv->buffer); DEBUG_NODE_TREE (tree, "Serializing tree:"); if (!priv->stream_mode) { xmlTextWriterStartDocument (priv->xmlwriter, "1.0", "utf-8", NULL); } _xml_write_node (writer, wocky_node_tree_get_top_node (tree)); if (!priv->stream_mode) { xmlTextWriterEndDocument (priv->xmlwriter); } xmlTextWriterFlush (priv->xmlwriter); *data = (const guint8 *)priv->buffer->content; *length = priv->buffer->use; #ifdef ENABLE_DEBUG wocky_debug (WOCKY_DEBUG_NET, "Writing xml: %.*s", (int)*length, *data); #endif } /** * wocky_xmpp_writer_write_stanza: * @writer: a WockyXmppWriter * @stanza: the stanza to serialize * @data: location to store a pointer to the data buffer * @length: length of the data buffer * * Serialize the @stanza to XML. The result is available in the * @data buffer. The buffer is only valid until the next call to a function */ void wocky_xmpp_writer_write_stanza (WockyXmppWriter *writer, WockyStanza *stanza, const guint8 **data, gsize *length) { _write_node_tree (writer, WOCKY_NODE_TREE (stanza), data, length); } /** * wocky_xmpp_writer_write_node_tree: * @writer: a WockyXmppWriter * @tree: the node tree to serialize * @data: location to store a pointer to the data buffer * @length: length of the data buffer * * Serialize the @tree to XML. The result is available in the * @data buffer. The buffer is only valid until the next call to a function. * This function may only be called in non-streaming mode. */ void wocky_xmpp_writer_write_node_tree (WockyXmppWriter *writer, WockyNodeTree *tree, const guint8 **data, gsize *length) { *data = NULL; *length = 0; g_return_if_fail (!writer->priv->stream_mode); _write_node_tree (writer, tree, data, length); } /** * wocky_xmpp_writer_flush: * @writer: a WockyXmppWriter * * Flushes and frees the internal data buffer */ void wocky_xmpp_writer_flush (WockyXmppWriter *writer) { WockyXmppWriterPrivate *priv = writer->priv; xmlBufferFree (priv->buffer); priv->buffer = xmlBufferCreate (); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-tls-handler.c0000664000175000017500000002704412212322440025546 0ustar00cassidycassidy00000000000000/* * wocky-tls-handler.c - Source for WockyTLSHandler * Copyright (C) 2010 Collabora Ltd. * @author Cosimo Cecchi * @author Vivek Dasmohapatra * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "wocky-tls-handler.h" #include "wocky-utils.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_TLS #include "wocky-debug-internal.h" static void real_verify_async (WockyTLSHandler *self, WockyTLSSession *tls_session, const gchar *peername, GStrv extra_identities, GAsyncReadyCallback callback, gpointer user_data); static gboolean real_verify_finish (WockyTLSHandler *self, GAsyncResult *result, GError **error); G_DEFINE_TYPE (WockyTLSHandler, wocky_tls_handler, G_TYPE_OBJECT) enum { PROP_TLS_INSECURE_OK = 1, }; struct _WockyTLSHandlerPrivate { gboolean ignore_ssl_errors; GSList *cas; GSList *crl; }; static void wocky_tls_handler_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyTLSHandler *self = WOCKY_TLS_HANDLER (object); switch (property_id) { case PROP_TLS_INSECURE_OK: g_value_set_boolean (value, self->priv->ignore_ssl_errors); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_tls_handler_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyTLSHandler *self = WOCKY_TLS_HANDLER (object); switch (property_id) { case PROP_TLS_INSECURE_OK: self->priv->ignore_ssl_errors = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_tls_handler_finalize (GObject *object) { WockyTLSHandler *self = WOCKY_TLS_HANDLER (object); if (self->priv->cas != NULL) { g_slist_foreach (self->priv->cas, (GFunc) g_free, NULL); g_slist_free (self->priv->cas); } if (self->priv->crl != NULL) { g_slist_foreach (self->priv->crl, (GFunc) g_free, NULL); g_slist_free (self->priv->crl); } G_OBJECT_CLASS (wocky_tls_handler_parent_class)->finalize (object); } static void wocky_tls_handler_class_init (WockyTLSHandlerClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); GParamSpec *pspec; g_type_class_add_private (klass, sizeof (WockyTLSHandlerPrivate)); klass->verify_async_func = real_verify_async; klass->verify_finish_func = real_verify_finish; oclass->get_property = wocky_tls_handler_get_property; oclass->set_property = wocky_tls_handler_set_property; oclass->finalize = wocky_tls_handler_finalize; /** * WockyTLSHandler:ignore-ssl-errors: * * Whether to ignore recoverable SSL errors (certificate * insecurity/expiry etc). */ pspec = g_param_spec_boolean ("ignore-ssl-errors", "ignore-ssl-errors", "Whether recoverable TLS errors should be ignored", FALSE, (G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_TLS_INSECURE_OK, pspec); } static void wocky_tls_handler_init (WockyTLSHandler *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_TLS_HANDLER, WockyTLSHandlerPrivate); #ifdef GTLS_SYSTEM_CA_CERTIFICATES wocky_tls_handler_add_ca (self, GTLS_SYSTEM_CA_CERTIFICATES); #endif } static void real_verify_async (WockyTLSHandler *self, WockyTLSSession *tls_session, const gchar *peername, GStrv extra_identities, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *result; glong flags = WOCKY_TLS_VERIFY_NORMAL; WockyTLSCertStatus status = WOCKY_TLS_CERT_UNKNOWN_ERROR; const gchar *verify_peername = NULL; GStrv verify_extra_identities = NULL; result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_tls_handler_verify_async); /* When ignore_ssl_errors is true, don't check the peername. Otherwise: * - Under legacy SSL, the connect hostname is the preferred peername; * - Under STARTTLS, we check the domain regardless of the connect server. */ if (self->priv->ignore_ssl_errors) { flags = WOCKY_TLS_VERIFY_LENIENT; } else { verify_peername = peername; verify_extra_identities = extra_identities; } DEBUG ("Verifying certificate (peername: %s)", (verify_peername == NULL) ? "-" : verify_peername); wocky_tls_session_verify_peer (tls_session, verify_peername, verify_extra_identities, flags, &status); if (status != WOCKY_TLS_CERT_OK) { gboolean ok_when_lenient = FALSE; const gchar *msg = NULL; switch (status) { case WOCKY_TLS_CERT_NAME_MISMATCH: msg = "SSL Certificate does not match name '%s'"; break; case WOCKY_TLS_CERT_REVOKED: msg = "SSL Certificate for %s has been revoked"; break; case WOCKY_TLS_CERT_SIGNER_UNKNOWN: ok_when_lenient = TRUE; msg = "SSL Certificate for %s is insecure (unknown signer)"; break; case WOCKY_TLS_CERT_SIGNER_UNAUTHORISED: msg = "SSL Certificate for %s is insecure (unauthorised signer)"; break; case WOCKY_TLS_CERT_INSECURE: msg = "SSL Certificate for %s is insecure (weak crypto)"; break; case WOCKY_TLS_CERT_NOT_ACTIVE: msg = "SSL Certificate for %s not active yet"; break; case WOCKY_TLS_CERT_EXPIRED: msg = "SSL Certificate for %s expired"; break; case WOCKY_TLS_CERT_INVALID: msg = "SSL Certificate for %s invalid"; ok_when_lenient = TRUE; break; /* Handle UNKNOWN_ERROR and any other unexpected values equivalently */ case WOCKY_TLS_CERT_UNKNOWN_ERROR: default: msg = "SSL Certificate Verification Error for %s"; } if (!(self->priv->ignore_ssl_errors && ok_when_lenient)) { GError *cert_error = NULL; cert_error = g_error_new (WOCKY_TLS_CERT_ERROR, status, msg, peername); g_simple_async_result_set_from_error (result, cert_error); g_error_free (cert_error); g_simple_async_result_complete_in_idle (result); g_object_unref (result); return; } else { gchar *err; err = g_strdup_printf (msg, peername); DEBUG ("Cert error: '%s', but ignore-ssl-errors is set", err); g_free (err); } } g_simple_async_result_complete_in_idle (result); g_object_unref (result); } static gboolean real_verify_finish (WockyTLSHandler *self, GAsyncResult *result, GError **error) { wocky_implement_finish_void (self, wocky_tls_handler_verify_async); } void wocky_tls_handler_verify_async (WockyTLSHandler *self, WockyTLSSession *session, const gchar *peername, GStrv extra_identities, GAsyncReadyCallback callback, gpointer user_data) { WockyTLSHandlerClass *klass = WOCKY_TLS_HANDLER_GET_CLASS (self); klass->verify_async_func (self, session, peername, extra_identities, callback, user_data); } gboolean wocky_tls_handler_verify_finish (WockyTLSHandler *self, GAsyncResult *res, GError **error) { WockyTLSHandlerClass *klass = WOCKY_TLS_HANDLER_GET_CLASS (self); return klass->verify_finish_func (self, res, error); } WockyTLSHandler * wocky_tls_handler_new (gboolean ignore_ssl_errors) { return g_object_new (WOCKY_TYPE_TLS_HANDLER, "ignore-ssl-errors", ignore_ssl_errors, NULL); } /** * wocky_tls_handler_add_ca: * @self: a #WockyTLSHandler instance * @path: a path to a directory or file containing PEM encoded CA certificates * * Adds a single CA certificate, or directory full of CA certificates, to the * set used to check certificates. By default, Wocky will check the system-wide * certificate directory (as determined at compile time), so you need only add * additional CA paths if you want to trust additional CAs. * * Returns: %TRUE if @path could be resolved to an absolute path. Note that * this does not indicate that there was actually a file or directory there or * that any CAs were actually found. The CAs won't actually be loaded until * just before the TLS session setup is attempted. */ gboolean wocky_tls_handler_add_ca (WockyTLSHandler *self, const gchar *path) { gchar *abspath = wocky_absolutize_path (path); if (abspath != NULL) self->priv->cas = g_slist_prepend (self->priv->cas, abspath); return abspath != NULL; } /** * wocky_tls_handler_forget_cas: * @self: a #WockyTLSHandler instance * * Removes all known locations for CA certificates, including the system-wide * certificate directory and any paths added by previous calls to * wocky_tls_handler_add_ca(). This is only useful if you want Wocky to * distrust your system CAs for some reason. */ void wocky_tls_handler_forget_cas (WockyTLSHandler *self) { g_slist_free_full (self->priv->cas, g_free); self->priv->cas = NULL; } /** * wocky_tls_handler_add_crl: * @self: a #WockyTLSHandler instance * @path: a path to a directory or file containing PEM encoded CRL certificates * * Adds a single certificate revocation list file, or a directory of CRLs, to * the set used to check certificates. Unlike for CA certificates, there is * typically no good default path, so no CRLs are used by default. The path to * use depends on the CRL-management software you use; `dirmngr` * (for example) will cache CRLs in `/var/cache/dirmngr/crls.d`. * * Returns: %TRUE if @path could be resolved to an absolute path. Note that * this does not indicate that there was actually a file or directory there or * that any CRLs were actually found. The CRLs won't actually be loaded until * just before the TLS session setup is attempted. */ gboolean wocky_tls_handler_add_crl (WockyTLSHandler *self, const gchar *path) { gchar *abspath = wocky_absolutize_path (path); if (abspath != NULL) self->priv->crl = g_slist_prepend (self->priv->crl, abspath); return abspath != NULL; } /** * wocky_tls_handler_get_cas: * @self: a #WockyTLSHandler instance * * Gets the CA certificate search path, including any extra paths added with * wocky_tls_handler_add_ca(). * * Returns: (transfer none) (element-type utf8): the paths to search for CA certificates. */ GSList * wocky_tls_handler_get_cas (WockyTLSHandler *self) { g_assert (WOCKY_IS_TLS_HANDLER (self)); return self->priv->cas; } /** * wocky_tls_handler_get_crl: * @self: a #WockyTLSHandler instance * * Gets the CRL search path, consisting of all paths added with * wocky_tls_handler_add_crl(). * * Returns: (transfer none) (element-type utf8): the CRL search path. */ GSList * wocky_tls_handler_get_crl (WockyTLSHandler *self) { g_assert (WOCKY_IS_TLS_HANDLER (self)); return self->priv->crl; } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-sasl-utils.h0000644000175000017500000000241411544576223025447 0ustar00cassidycassidy00000000000000/* * wocky-sasl-utils.h - Some sasl helper functions * Copyright (C) 2006-2010 Collabora Ltd. * @author Sjoerd Simons * Copyright (C) 2010 Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __WOCKY_SASL_UTILS_H__ #define __WOCKY_SASL_UTILS_H__ #include #define WOCKY_SHA1_BLOCK_SIZE 64 #define WOCKY_SHA1_DIGEST_SIZE 20 gchar * sasl_generate_base64_nonce (void); GByteArray * sasl_calculate_hmac_sha1 (guint8 *key, gsize key_len, guint8 *text, gsize text_len); #endif /* __WOCKY_SASL_UTILS_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jingle-info-internal.h0000664000175000017500000000224612212322440027346 0ustar00cassidycassidy00000000000000/* * wocky-jingle-info-internal.h - internal types for WockyJingleInfo * Copyright © 2012 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_COMPILATION) # error "This is an internal header." #endif #ifndef WOCKY_JINGLE_INFO_INTERNAL_H #define WOCKY_JINGLE_INFO_INTERNAL_H typedef enum { WOCKY_STUN_SERVER_USER_SPECIFIED, WOCKY_STUN_SERVER_DISCOVERED, WOCKY_STUN_SERVER_FALLBACK } WockyStunServerSource; #endif /* WOCKY_JINGLE_INFO_INTERNAL_H */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-caps-hash.c0000664000175000017500000002616312212322440025201 0ustar00cassidycassidy00000000000000/* * wocky-caps-hash.c - Computing verification string hash (XEP-0115 v1.5) * Copyright (C) 2008-2011 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** * SECTION: wocky-caps-hash * @title: WockyCapsHash * @short_description: Utilities for computing verification string hash * * Computes verification string hashes according to XEP-0115 v1.5 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-caps-hash.h" #include #include #include "wocky-disco-identity.h" #include "wocky-utils.h" #include "wocky-data-form.h" #include "wocky-namespaces.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_PRESENCE #include "wocky-debug-internal.h" static gint char_cmp (gconstpointer a, gconstpointer b) { gchar *left = *(gchar **) a; gchar *right = *(gchar **) b; return strcmp (left, right); } static gint identity_cmp (gconstpointer a, gconstpointer b) { WockyDiscoIdentity *left = *(WockyDiscoIdentity **) a; WockyDiscoIdentity *right = *(WockyDiscoIdentity **) b; return wocky_disco_identity_cmp (left, right); } static gint dataforms_cmp (gconstpointer a, gconstpointer b) { WockyDataForm *left = *(WockyDataForm **) a; WockyDataForm *right = *(WockyDataForm **) b; WockyDataFormField *left_type, *right_type; left_type = g_hash_table_lookup (left->fields, "FORM_TYPE"); right_type = g_hash_table_lookup (right->fields, "FORM_TYPE"); if (left_type == NULL && right_type == NULL) return 0; else if (left_type == NULL && right_type != NULL) return -1; else if (left_type != NULL && right_type == NULL) return 1; else /* left_type != NULL && right_type != NULL */ { const gchar *left_value = NULL, *right_value = NULL; if (left_type->raw_value_contents != NULL) left_value = left_type->raw_value_contents[0]; if (right_type->raw_value_contents != NULL) right_value = right_type->raw_value_contents[0]; return g_strcmp0 (left_value, right_value); } } static GPtrArray * ptr_array_copy (GPtrArray *old) { GPtrArray *new = g_ptr_array_sized_new (old->len); guint i; for (i = 0 ; i < old->len ; i++) g_ptr_array_add (new, g_ptr_array_index (old, i)); return new; } /* see qsort(3) */ static int cmpstringp (const void *p1, const void *p2) { /* The actual arguments to this function are "pointers to pointers to char", but strcmp(3) arguments are "pointers to char", hence the following cast plus dereference */ return strcmp (* (char * const *) p1, * (char * const *) p2); } /** * wocky_caps_hash_compute_from_lists: * @features: a #GPtrArray of strings of features * @identities: a #GPtrArray of #WockyDiscoIdentity structures * @dataforms: a #GPtrArray of #WockyDataForm objects, or %NULL * * Compute the hash as defined by the XEP-0115 from a list of * features, identities and dataforms. * * Returns: a newly allocated string of the caps hash which should be * freed using g_free() */ gchar * wocky_caps_hash_compute_from_lists ( GPtrArray *features, GPtrArray *identities, GPtrArray *dataforms) { GChecksum *checksum; guint8 *sha1; guint i; gchar *encoded = NULL; gsize sha1_buffer_size; GHashTable *form_names; GPtrArray *features_sorted, *identities_sorted, *dataforms_sorted; g_return_val_if_fail (features != NULL, NULL); g_return_val_if_fail (identities != NULL, NULL); /* not a deep copy, we only need to sort */ features_sorted = ptr_array_copy (features); identities_sorted = ptr_array_copy (identities); if (dataforms != NULL) dataforms_sorted = ptr_array_copy (dataforms); else dataforms_sorted = g_ptr_array_new (); g_ptr_array_sort (identities_sorted, identity_cmp); g_ptr_array_sort (features_sorted, char_cmp); g_ptr_array_sort (dataforms_sorted, dataforms_cmp); checksum = g_checksum_new (G_CHECKSUM_SHA1); form_names = g_hash_table_new (g_str_hash, g_str_equal); /* okay go and actually create this caps hash */ for (i = 0 ; i < identities_sorted->len ; i++) { const WockyDiscoIdentity *identity = g_ptr_array_index (identities_sorted, i); gchar *str = g_strdup_printf ("%s/%s/%s/%s", identity->category, identity->type, identity->lang ? identity->lang : "", identity->name ? identity->name : ""); g_checksum_update (checksum, (guchar *) str, -1); g_checksum_update (checksum, (guchar *) "<", 1); g_free (str); } for (i = 0 ; i < features_sorted->len ; i++) { g_checksum_update (checksum, (guchar *) g_ptr_array_index (features_sorted, i), -1); g_checksum_update (checksum, (guchar *) "<", 1); } for (i = 0; i < dataforms_sorted->len; i++) { WockyDataForm *dataform = g_ptr_array_index (dataforms_sorted, i); WockyDataFormField *field; GSList *fields, *l; const gchar *form_name; field = g_hash_table_lookup (dataform->fields, "FORM_TYPE"); if (field == NULL) { DEBUG ("Data form is missing FORM_TYPE field; ignoring form and " "moving onto next one"); continue; } if (field->type != WOCKY_DATA_FORM_FIELD_TYPE_HIDDEN) { DEBUG ("FORM_TYPE field is not hidden; " "ignoring form and moving onto next one"); continue; } if (field->raw_value_contents == NULL || g_strv_length (field->raw_value_contents) != 1) { DEBUG ("FORM_TYPE field does not have exactly one value; failing"); goto cleanup; } form_name = field->raw_value_contents[0]; if (g_hash_table_lookup (form_names, form_name) != NULL) { DEBUG ("error: there are multiple data forms with the " "same form type: %s", form_name); goto cleanup; } g_hash_table_insert (form_names, (gpointer) form_name, (gpointer) form_name); g_checksum_update (checksum, (guchar *) form_name, -1); g_checksum_update (checksum, (guchar *) "<", 1); /* we need to make a shallow copy to sort the fields */ fields = g_slist_copy (dataform->fields_list); fields = g_slist_sort (fields, (GCompareFunc) wocky_data_form_field_cmp); for (l = fields; l != NULL; l = l->next) { GStrv values = NULL; GStrv tmp; field = l->data; if (field->var == NULL) { DEBUG ("can't hash form '%s': it has an anonymous field", form_name); g_slist_free (fields); goto cleanup; } if (!wocky_strdiff (field->var, "FORM_TYPE")) continue; g_checksum_update (checksum, (guchar *) field->var, -1); g_checksum_update (checksum, (guchar *) "<", 1); if (field->raw_value_contents == NULL || field->raw_value_contents[0] == NULL) { DEBUG ("could not get field %s value", field->var); g_slist_free (fields); goto cleanup; } /* make a copy so we can sort it */ values = g_strdupv (field->raw_value_contents); qsort (values, g_strv_length (values), sizeof (gchar *), cmpstringp); for (tmp = values; tmp != NULL && *tmp != NULL; tmp++) { g_checksum_update (checksum, (guchar *) *tmp, -1); g_checksum_update (checksum, (guchar *) "<", 1); } g_strfreev (values); } g_slist_free (fields); } sha1_buffer_size = g_checksum_type_get_length (G_CHECKSUM_SHA1); sha1 = g_new0 (guint8, sha1_buffer_size); g_checksum_get_digest (checksum, sha1, &sha1_buffer_size); encoded = g_base64_encode (sha1, sha1_buffer_size); g_free (sha1); cleanup: g_checksum_free (checksum); g_hash_table_unref (form_names); g_ptr_array_unref (identities_sorted); g_ptr_array_unref (features_sorted); g_ptr_array_unref (dataforms_sorted); return encoded; } /** * wocky_caps_hash_compute_from_node: * @node: a #WockyNode * * Compute the hash as defined by the XEP-0115 from a received * #WockyNode. * * @node should be the top-level node from a disco response such as * the example given in XEP-0115 §5.3 "Complex Generation Example". * * Returns: the hash. The called must free the returned hash with * g_free(). */ gchar * wocky_caps_hash_compute_from_node (WockyNode *node) { GPtrArray *features = g_ptr_array_new_with_free_func ( (GDestroyNotify) g_free); GPtrArray *identities = wocky_disco_identity_array_new (); GPtrArray *dataforms = g_ptr_array_new_with_free_func ( (GDestroyNotify) g_object_unref); gchar *str = NULL; GSList *c; WockyNodeIter iter; WockyNode *x_node = NULL; for (c = node->children; c != NULL; c = c->next) { WockyNode *child = c->data; if (g_str_equal (child->name, "identity")) { const gchar *category; const gchar *name; const gchar *type; const gchar *xmllang; WockyDiscoIdentity *identity; category = wocky_node_get_attribute (child, "category"); name = wocky_node_get_attribute (child, "name"); type = wocky_node_get_attribute (child, "type"); xmllang = wocky_node_get_language (child); if (NULL == category) continue; if (NULL == name) name = ""; if (NULL == type) type = ""; if (NULL == xmllang) xmllang = ""; identity = wocky_disco_identity_new (category, type, xmllang, name); g_ptr_array_add (identities, identity); } else if (g_str_equal (child->name, "feature")) { const gchar *var; var = wocky_node_get_attribute (child, "var"); if (NULL == var) continue; g_ptr_array_add (features, g_strdup (var)); } } wocky_node_iter_init (&iter, node, "x", WOCKY_XMPP_NS_DATA); while (wocky_node_iter_next (&iter, &x_node)) { GError *error = NULL; WockyDataForm *dataform = wocky_data_form_new_from_node (x_node, &error); if (error != NULL) { DEBUG ("Failed to parse data form: %s\n", error->message); g_clear_error (&error); goto out; } g_ptr_array_add (dataforms, dataform); } str = wocky_caps_hash_compute_from_lists (features, identities, dataforms); out: wocky_disco_identity_array_free (identities); g_ptr_array_unref (features); g_ptr_array_unref (dataforms); return str; } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jingle-media-rtp.h0000664000175000017500000001037512212322440026465 0ustar00cassidycassidy00000000000000/* * wocky-jingle-media-rtp.h - Header for WockyJingleMediaRtp * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __JINGLE_MEDIA_RTP_H__ #define __JINGLE_MEDIA_RTP_H__ #include #include "wocky-jingle-content.h" #include "wocky-jingle-types.h" G_BEGIN_DECLS typedef struct _WockyJingleMediaRtpClass WockyJingleMediaRtpClass; GType wocky_jingle_media_rtp_get_type (void); /* TYPE MACROS */ #define WOCKY_TYPE_JINGLE_MEDIA_RTP \ (wocky_jingle_media_rtp_get_type ()) #define WOCKY_JINGLE_MEDIA_RTP(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_JINGLE_MEDIA_RTP, \ WockyJingleMediaRtp)) #define WOCKY_JINGLE_MEDIA_RTP_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_JINGLE_MEDIA_RTP, \ WockyJingleMediaRtpClass)) #define WOCKY_IS_JINGLE_MEDIA_RTP(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_JINGLE_MEDIA_RTP)) #define WOCKY_IS_JINGLE_MEDIA_RTP_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_JINGLE_MEDIA_RTP)) #define WOCKY_JINGLE_MEDIA_RTP_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_JINGLE_MEDIA_RTP, \ WockyJingleMediaRtpClass)) struct _WockyJingleMediaRtpClass { WockyJingleContentClass parent_class; }; typedef struct _WockyJingleMediaRtpPrivate WockyJingleMediaRtpPrivate; struct _WockyJingleMediaRtp { WockyJingleContent parent; WockyJingleMediaRtpPrivate *priv; }; typedef struct { guint id; gchar *name; guint clockrate; guint channels; GHashTable *params; guint trr_int; GList *feedback_msgs; } WockyJingleCodec; typedef struct { gchar *type; gchar *subtype; } WockyJingleFeedbackMessage; typedef struct { guint id; WockyJingleContentSenders senders; gchar *uri; } WockyJingleRtpHeaderExtension; typedef struct { GList *codecs; GList *hdrexts; guint trr_int; GList *feedback_msgs; } WockyJingleMediaDescription; void jingle_media_rtp_register (WockyJingleFactory *factory); gboolean jingle_media_rtp_set_local_media_description ( WockyJingleMediaRtp *self, WockyJingleMediaDescription *md, gboolean ready, GError **error); WockyJingleMediaDescription *wocky_jingle_media_rtp_get_remote_media_description ( WockyJingleMediaRtp *self); WockyJingleCodec * jingle_media_rtp_codec_new (guint id, const gchar *name, guint clockrate, guint channels, GHashTable *params); void jingle_media_rtp_codec_free (WockyJingleCodec *p); void jingle_media_rtp_free_codecs (GList *codecs); GList * jingle_media_rtp_copy_codecs (GList *codecs); gboolean jingle_media_rtp_compare_codecs (GList *old, GList *new, GList **changed, GError **e); WockyJingleMediaDescription *wocky_jingle_media_description_new (void); void wocky_jingle_media_description_free (WockyJingleMediaDescription *md); WockyJingleMediaDescription *wocky_jingle_media_description_copy ( WockyJingleMediaDescription *md); WockyJingleRtpHeaderExtension *wocky_jingle_rtp_header_extension_new (guint id, WockyJingleContentSenders senders, const gchar *uri); void wocky_jingle_rtp_header_extension_free (WockyJingleRtpHeaderExtension *hdrext); WockyJingleFeedbackMessage *wocky_jingle_feedback_message_new (const gchar *type, const gchar *subtype); void wocky_jingle_feedback_message_free (WockyJingleFeedbackMessage *fb); void wocky_jingle_media_description_simplify (WockyJingleMediaDescription *md); G_END_DECLS #endif /* __JINGLE_MEDIA_RTP_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-muc.c0000664000175000017500000013502612212322440024115 0ustar00cassidycassidy00000000000000/* * wocky-muc.c - Source for WockyMuc * Copyright © 2009 Collabora Ltd. * @author Vivek Dasmohapatra * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** * SECTION: wocky-muc * @title: WockyMuc * @short_description: multi-user chat rooms * @include: wocky/wocky.h * * Represents a multi-user chat room. Because the MUC protocol is so terrible, * you will find yourself consulting XEP-0045 and shedding * more than a few tears while using this class. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_MUC_CONNECTION #include "wocky-debug-internal.h" #include "wocky-muc.h" #include "wocky-namespaces.h" #include "wocky-utils.h" #include "wocky-signals-marshal.h" #include "wocky-xmpp-error.h" typedef enum { SIG_NICK_CHANGE, SIG_PERM_CHANGE, SIG_PRESENCE, SIG_OWN_PRESENCE, SIG_PRESENCE_ERROR, SIG_JOINED, SIG_PARTED, SIG_LEFT, SIG_MSG, SIG_MSG_ERR, SIG_FILL_PRESENCE, SIG_NULL } WockyMucSig; static guint signals[SIG_NULL] = { 0 }; typedef struct { const gchar *ns; WockyMucFeature flag; } feature; static const feature feature_map[] = { { WOCKY_NS_MUC, WOCKY_MUC_MODERN }, { WOCKY_NS_MUC "#register", WOCKY_MUC_FORM_REGISTER }, { WOCKY_NS_MUC "#roomconfig", WOCKY_MUC_FORM_ROOMCONFIG }, { WOCKY_NS_MUC "#roominfo", WOCKY_MUC_FORM_ROOMINFO }, { "muc_hidden", WOCKY_MUC_HIDDEN }, { "muc_membersonly", WOCKY_MUC_MEMBERSONLY }, { "muc_moderated", WOCKY_MUC_MODERATED }, { "muc_nonanonymous", WOCKY_MUC_NONANONYMOUS }, { "muc_open", WOCKY_MUC_OPEN }, { "muc_passwordprotected", WOCKY_MUC_PASSWORDPROTECTED }, { "muc_persistent", WOCKY_MUC_PERSISTENT }, { "muc_public", WOCKY_MUC_PUBLIC }, { "muc_rooms", WOCKY_MUC_ROOMS }, { "muc_semianonymous", WOCKY_MUC_SEMIANONYMOUS }, { "muc_temporary", WOCKY_MUC_TEMPORARY }, { "muc_unmoderated", WOCKY_MUC_UNMODERATED }, { "muc_unsecured", WOCKY_MUC_UNSECURED }, { "gc-1.0", WOCKY_MUC_OBSOLETE }, { NULL, 0 } }; static void wocky_muc_class_init (WockyMucClass *klass); /* create MUC object */ G_DEFINE_TYPE (WockyMuc, wocky_muc, G_TYPE_OBJECT); /* private methods */ static void wocky_muc_dispose (GObject *object); static void wocky_muc_finalize (GObject *object); static void wocky_muc_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec); static void wocky_muc_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec); /* private functions */ static gboolean handle_presence (WockyPorter *porter, WockyStanza *stanza, gpointer data); static gboolean handle_message (WockyPorter *porter, WockyStanza *stanza, gpointer data); enum { PROP_JID = 1, PROP_USER, PROP_PORTER, PROP_SERVICE, PROP_ROOM, PROP_DESC, PROP_NICK, PROP_RNICK, PROP_PASS, PROP_STATUS, PROP_ROOM_TYPE, PROP_ID_CATEGORY, PROP_ID_TYPE, PROP_ID_NAME, PROP_ROLE, PROP_AFFILIATION, }; struct _WockyMucPrivate { /* properties */ WockyPorter *porter; gchar *user; /* full JID of user */ gchar *jid; /* room@service/nick */ gchar *service; /* service */ gchar *room; /* room */ gchar *rjid; /* room@service */ gchar *nick; /* nick */ gchar *rnick; /* reserved nick, if any */ gchar *id_category; /* eg "conference" */ gchar *id_type; /* eg "text" */ gchar *id_name; gchar *desc; /* long room description */ gchar *pass; /* password or NULL */ gchar *status; /* status message */ guint room_type; /* ORed WockyMucFeature flags */ /* not props */ gboolean dispose_has_run; GHashTable *members; WockyMucState state; WockyMucRole role; WockyMucAffiliation affiliation; guint pres_handler; guint mesg_handler; GSimpleAsyncResult *join_cb; }; static void free_member (gpointer data) { WockyMucMember *member = data; if (member->presence_stanza != NULL) g_object_unref (member->presence_stanza); g_free (member->from); g_free (member->jid); g_free (member->nick); g_free (member->status); g_slice_free (WockyMucMember, member); } static gpointer alloc_member (void) { return g_slice_new0 (WockyMucMember); } static void wocky_muc_init (WockyMuc *muc) { muc->priv = G_TYPE_INSTANCE_GET_PRIVATE (muc, WOCKY_TYPE_MUC, WockyMucPrivate); muc->priv->members = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_member); } static void wocky_muc_dispose (GObject *object) { WockyMuc *muc = WOCKY_MUC (object); WockyMucPrivate *priv = muc->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; if (priv->pres_handler != 0) wocky_porter_unregister_handler (priv->porter, priv->pres_handler); priv->pres_handler = 0; if (priv->mesg_handler != 0) wocky_porter_unregister_handler (priv->porter, priv->mesg_handler); priv->mesg_handler = 0; if (priv->porter != NULL) g_object_unref (priv->porter); priv->porter = NULL; if (priv->members != NULL) g_hash_table_unref (priv->members); priv->members = NULL; if (G_OBJECT_CLASS (wocky_muc_parent_class )->dispose) G_OBJECT_CLASS (wocky_muc_parent_class)->dispose (object); } #define GFREE_AND_FORGET(x) g_free (x); x = NULL; static void wocky_muc_finalize (GObject *object) { WockyMuc *muc = WOCKY_MUC (object); WockyMucPrivate *priv = muc->priv; GFREE_AND_FORGET (priv->user); GFREE_AND_FORGET (priv->jid); GFREE_AND_FORGET (priv->service); GFREE_AND_FORGET (priv->room); GFREE_AND_FORGET (priv->rjid); GFREE_AND_FORGET (priv->nick); GFREE_AND_FORGET (priv->rnick); GFREE_AND_FORGET (priv->id_category); GFREE_AND_FORGET (priv->id_type); GFREE_AND_FORGET (priv->id_name); G_OBJECT_CLASS (wocky_muc_parent_class)->finalize (object); } static void wocky_muc_class_init (WockyMucClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); GType ctype = G_OBJECT_CLASS_TYPE (klass); GParamSpec *spec; g_type_class_add_private (klass, sizeof (WockyMucPrivate)); oclass->get_property = wocky_muc_get_property; oclass->set_property = wocky_muc_set_property; oclass->dispose = wocky_muc_dispose; oclass->finalize = wocky_muc_finalize; spec = g_param_spec_string ("jid", "jid", "Full room@service/nick JID of the MUC room", NULL, G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS); g_object_class_install_property (oclass, PROP_JID, spec); spec = g_param_spec_string ("user", "user", "Full JID of the user (node@domain/resource) who is connecting", NULL, (G_PARAM_CONSTRUCT_ONLY|G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_USER, spec); spec = g_param_spec_object ("porter", "porter", "The WockyPorter instance doing all the actual XMPP interaction", WOCKY_TYPE_PORTER, (G_PARAM_CONSTRUCT_ONLY|G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_PORTER, spec); spec = g_param_spec_string ("service", "service", "The service (domain) part of the MUC JID", NULL, (G_PARAM_READABLE|G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_SERVICE, spec); spec = g_param_spec_string ("room", "room", "The node part of the MUC room JID", NULL, (G_PARAM_READABLE|G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_ROOM, spec); spec = g_param_spec_string ("description", "desc", "The long description oof the room", NULL, (G_PARAM_READABLE|G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_DESC, spec); spec = g_param_spec_string ("nickname", "nick", "The user's in-room nickname", NULL, (G_PARAM_READABLE|G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_NICK, spec); spec = g_param_spec_string ("reserved-nick", "reserved-nick", "The user's reserved in-room nickname, if any", NULL, (G_PARAM_READABLE|G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_RNICK, spec); spec = g_param_spec_string ("password", "password", "User's MUC room password", NULL, (G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_PASS, spec); spec = g_param_spec_string ("status-message", "status", "User's MUC status message", NULL, (G_PARAM_READABLE|G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_STATUS, spec); spec = g_param_spec_ulong ("muc-flags", "muc-flags", "ORed set of WockyMucFeature MUC property flags", 0, G_MAXULONG, 0, (G_PARAM_READABLE|G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_ROOM_TYPE, spec); spec = g_param_spec_string ("category", "category", "Category of the MUC, usually \"conference\"", NULL, (G_PARAM_READABLE|G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_ID_CATEGORY, spec); spec = g_param_spec_string ("type", "type", "Type of the MUC, eg \"text\"", NULL, (G_PARAM_READABLE|G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_ID_TYPE, spec); spec = g_param_spec_string ("name", "name", "The human-readable name of the room (usually a short label)", NULL, (G_PARAM_READABLE|G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_ID_NAME, spec); spec = g_param_spec_uint ("role", "role", "The role (WockyMucRole) of the user in the MUC room", WOCKY_MUC_ROLE_NONE, WOCKY_MUC_ROLE_MODERATOR, WOCKY_MUC_ROLE_NONE, (G_PARAM_READABLE|G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_ROLE, spec); spec = g_param_spec_enum ("affiliation", "affiliation", "The affiliation of the user with the MUC room", WOCKY_TYPE_MUC_AFFILIATION, WOCKY_MUC_AFFILIATION_NONE, (G_PARAM_READABLE|G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_AFFILIATION, spec); signals[SIG_NICK_CHANGE] = g_signal_new ("nick-change", ctype, G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__POINTER_UINT, G_TYPE_NONE, 2, WOCKY_TYPE_STANZA, G_TYPE_UINT); signals[SIG_PRESENCE] = g_signal_new ("presence", ctype, G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT_UINT_POINTER, G_TYPE_NONE, 3, WOCKY_TYPE_STANZA, G_TYPE_UINT, G_TYPE_POINTER); signals[SIG_OWN_PRESENCE] = g_signal_new ("own-presence", ctype, G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT_UINT, G_TYPE_NONE, 2, WOCKY_TYPE_STANZA, G_TYPE_UINT); /** * WockyMuc::joined: * @muc: the MUC * @stanza: the presence stanza * @codes: bitwise OR of %WockyMucStatusCode flags with miscellaneous * information about the MUC * * Emitted when the local user successfully joins @muc. */ signals[SIG_JOINED] = g_signal_new ("joined", ctype, G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__POINTER_UINT, G_TYPE_NONE, 2, WOCKY_TYPE_STANZA, G_TYPE_UINT); /** * WockyMuc::error: * @muc: the MUC * @stanza: the presence stanza * @error_type: the type of error * @error: an error in domain #WOCKY_XMPP_ERROR, whose message (if not %NULL) * is a human-readable message from the server * * Emitted when a presence error is received from the MUC, which is generally * in response to trying to join the MUC. */ signals[SIG_PRESENCE_ERROR] = g_signal_new ("error", ctype, G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT_ENUM_BOXED, G_TYPE_NONE, 3, WOCKY_TYPE_STANZA, WOCKY_TYPE_XMPP_ERROR_TYPE, G_TYPE_ERROR); /** * WockyMuc::permissions: * @muc: the muc * @stanza: the presence stanza heralding the change * @codes: bitwise OR of %WockyMucStatusCode flags * @actor_jid: the JID of the user who changed our permissions, or %NULL * @reason: a human-readable reason for the change, or %NULL * * Emitted when our permissions within the MUC are changed. */ signals[SIG_PERM_CHANGE] = g_signal_new ("permissions", ctype, G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__POINTER_UINT_POINTER_POINTER, G_TYPE_NONE, 4, WOCKY_TYPE_STANZA, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING); /** * WockyMuc::parted: * @muc: the MUC * @stanza: the presence stanza * @codes: bitwise OR of %WockyMucStatusCode flags describing why the user * left the MUC * @actor: if the user was removed from the MUC by another participant, that * participant's JID * @reason: if the user was removed from the MUC by another participant, a * human-readable reason given by that participant * @message: a parting message we provided to other participants, or %NULL * * Emitted when the local user leaves the MUC, whether by choice or by force. */ signals[SIG_PARTED] = g_signal_new ("parted", ctype, G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT_UINT_STRING_STRING_STRING, G_TYPE_NONE, 5, WOCKY_TYPE_STANZA, G_TYPE_UINT, G_TYPE_STRING, /* actor jid */ G_TYPE_STRING, /* reason */ G_TYPE_STRING); /* message: usually none, but allowed by spec */ /** * WockyMuc::left: * @muc: the MUC * @stanza: the presence stanza * @codes: bitwise OR of %WockyMucStatusCode flags describing why @member * left the MUC * @member: the (now ex-)member of the MUC who left * @actor: if @member was removed from the MUC by another participant, that * participant's JID * @reason: if @member was removed from the MUC by another participant, a * human-readable reason given by that participant * @message: a parting message provided by @member, or %NULL * * Emitted when another participant leaves, or is kicked from, the MUC */ signals[SIG_LEFT] = g_signal_new ("left", ctype, G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT_UINT_POINTER_STRING_STRING_STRING, G_TYPE_NONE, 6, WOCKY_TYPE_STANZA, G_TYPE_UINT, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); /** * WockyMuc::message: * @muc: the MUC * @stanza: the incoming message stanza * @message_type: the message's type * @id: the stanza's identifier (which may be %NULL if neither the sender nor * the MUC specified one) * @timestamp: for messages received as scrollback when joining the MUC, the * time the message was sent; %NULL for messages received while in the MUC * @sender: a %WockyMucMember struct describing the sender of the message * @body: the body of the message, or %NULL * @subject: the new subject for the MUC, or %NULL * @state: whether @sender is currently typing. * * Emitted when a non-error message stanza is received. This may indicate: * * * if @body is not %NULL, a message sent by @sender to the * MUC; * or, if @subject is not %NULL, @sender changed the subject of the * MUC; * additionally, that @sender is typing, or maybe stopped typing, * depending on @state. * */ signals[SIG_MSG] = g_signal_new ("message", ctype, G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT_ENUM_STRING_LONG_POINTER_STRING_STRING_ENUM, G_TYPE_NONE, 8, WOCKY_TYPE_STANZA, WOCKY_TYPE_MUC_MSG_TYPE, G_TYPE_STRING, G_TYPE_DATE_TIME, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING, WOCKY_TYPE_MUC_MSG_STATE); /** * WockyMuc::message-error: * @muc: the MUC * @stanza: the incoming %WOCKY_STANZA_SUB_TYPE_ERROR message * @message_type: the type of the message which was rejected * @id: the identifier for the original message and this error (which may be * %NULL) * @timestamp: the timestamp attached to the original message, which is * probably %NULL because timestamps are only attached to scrollback messages * @member: a %WockyMucMember struct describing the sender of the original * message (which is, we presume, us) * @body: the body of the message which failed to send * @error_type: the type of error * @error: an error in domain %WOCKY_XMPP_ERROR, whose message (if not %NULL) * is a human-readable message from the server * * Emitted when we receive an error from the MUC in response to sending a * message stanza to the MUC. */ signals[SIG_MSG_ERR] = g_signal_new ("message-error", ctype, G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT_ENUM_STRING_LONG_POINTER_STRING_ENUM_BOXED, G_TYPE_NONE, 8, WOCKY_TYPE_STANZA, WOCKY_TYPE_MUC_MSG_TYPE, G_TYPE_STRING, G_TYPE_DATE_TIME, G_TYPE_POINTER, G_TYPE_STRING, WOCKY_TYPE_XMPP_ERROR_TYPE, G_TYPE_ERROR); signals[SIG_FILL_PRESENCE] = g_signal_new ("fill-presence", ctype, G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT, G_TYPE_NONE, 1, WOCKY_TYPE_STANZA); } static void wocky_muc_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyMuc *muc = WOCKY_MUC (object); WockyMucPrivate *priv = muc->priv; switch (property_id) { case PROP_PORTER: priv->porter = g_value_dup_object (value); break; case PROP_JID: g_free (priv->jid); g_free (priv->service); g_free (priv->room); g_free (priv->nick); g_free (priv->rjid); priv->jid = g_value_dup_string (value); wocky_decode_jid (priv->jid, &(priv->room), &(priv->service), &(priv->nick)); priv->rjid = g_strdup_printf ("%s@%s", priv->room, priv->service); break; case PROP_NICK: g_free (priv->nick); priv->nick = g_value_dup_string (value); if (priv->jid != NULL && priv->nick != NULL) { g_free (priv->jid); priv->jid = g_strdup_printf ("%s@%s/%s", priv->room, priv->service, priv->nick); } break; case PROP_RNICK: g_free (priv->rnick); priv->rnick = g_value_dup_string (value); break; case PROP_PASS: g_free (priv->pass); priv->pass = g_value_dup_string (value); break; case PROP_USER: g_free (priv->user); priv->user = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_muc_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyMuc *muc = WOCKY_MUC (object); WockyMucPrivate *priv = muc->priv; switch (property_id) { case PROP_PORTER: g_value_set_object (value, priv->porter); break; case PROP_JID: g_value_set_string (value, priv->jid); break; case PROP_SERVICE: g_value_set_string (value, priv->service); break; case PROP_ROOM: g_value_set_string (value, priv->room); break; case PROP_DESC: g_value_set_string (value, priv->desc); break; case PROP_NICK: g_value_set_string (value, priv->nick); break; case PROP_PASS: g_value_set_string (value, priv->pass); break; case PROP_STATUS: g_value_set_string (value, priv->status); break; case PROP_RNICK: g_value_set_string (value, priv->rnick); break; case PROP_USER: g_value_set_string (value, priv->user); break; case PROP_ROOM_TYPE: g_value_set_uint (value, priv->room_type); break; case PROP_ID_CATEGORY: g_value_set_string (value, priv->id_category); break; case PROP_ID_TYPE: g_value_set_string (value, priv->id_type); break; case PROP_ID_NAME: g_value_set_string (value, priv->id_name); break; case PROP_ROLE: g_value_set_uint (value, priv->role); break; case PROP_AFFILIATION: g_value_set_enum (value, priv->affiliation); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static guint status_code_to_muc_flag (guint64 code) { switch (code) { case 100: return WOCKY_MUC_CODE_ONYMOUS; case 101: return WOCKY_MUC_CODE_AF_CHANGE_OOB; case 102: return WOCKY_MUC_CODE_CFG_SHOW_UNAVAILABLE; case 103: return WOCKY_MUC_CODE_CFG_HIDE_UNAVAILABLE; case 104: return WOCKY_MUC_CODE_CFG_NONPRIVACY; case 110: return WOCKY_MUC_CODE_OWN_PRESENCE; case 170: return WOCKY_MUC_CODE_CFG_LOGGING_ENABLED; case 171: return WOCKY_MUC_CODE_CFG_LOGGING_DISABLED; case 172: return WOCKY_MUC_CODE_CFG_ONYMOUS; case 173: return WOCKY_MUC_CODE_CFG_SEMIONYMOUS; case 174: return WOCKY_MUC_CODE_CFG_ANONYMOUS; case 201: return WOCKY_MUC_CODE_NEW_ROOM; case 210: return WOCKY_MUC_CODE_NICK_CHANGE_FORCED; case 301: return WOCKY_MUC_CODE_BANNED; case 303: return WOCKY_MUC_CODE_NICK_CHANGE_USER; case 307: return WOCKY_MUC_CODE_KICKED; case 321: return WOCKY_MUC_CODE_KICKED_AFFILIATION; case 322: return WOCKY_MUC_CODE_KICKED_ROOM_PRIVATISED; case 332: return WOCKY_MUC_CODE_KICKED_SHUTDOWN; } return WOCKY_MUC_CODE_UNKNOWN; } static gboolean store_muc_disco_info_x (WockyNode *field, gpointer data) { WockyMucPrivate *priv = data; const gchar *var = NULL; if (wocky_strdiff (field->name, "field")) return TRUE; var = wocky_node_get_attribute (field, "var"); if (wocky_strdiff (var, "muc#roominfo_description")) return TRUE; priv->desc = g_strdup ( wocky_node_get_content_from_child (field, "value")); return TRUE; } static gboolean store_muc_disco_info (WockyNode *feat, gpointer data) { WockyMucPrivate *priv = data; if (!wocky_strdiff (feat->name, "feature")) { guint i; const gchar *thing = wocky_node_get_attribute (feat, "var"); if (thing == NULL) return TRUE; for (i = 0; feature_map[i].ns != NULL; i++) if (!wocky_strdiff (thing, feature_map[i].ns)) { priv->room_type |= feature_map[i].flag; break; } return TRUE; } if (!wocky_strdiff (feat->name, "x")) wocky_node_each_child (feat, store_muc_disco_info_x, priv); return TRUE; } static void muc_disco_info (GObject *source, GAsyncResult *res, gpointer data) { WockyMuc *muc; WockyMucPrivate *priv; GError *error = NULL; WockyStanza *iq; WockyStanzaType type; WockyStanzaSubType sub; GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (data); muc = WOCKY_MUC (g_async_result_get_source_object (G_ASYNC_RESULT (result))); priv = muc->priv; iq = wocky_porter_send_iq_finish (priv->porter, res, &error); priv->room_type = 0; g_free (priv->id_name); g_free (priv->id_type); g_free (priv->id_category); priv->id_name = NULL; priv->id_type = NULL; priv->id_category = NULL; if (error != NULL) goto out; if (iq == NULL) goto out; wocky_stanza_get_type_info (iq, &type, &sub); if (type != WOCKY_STANZA_TYPE_IQ) { error = g_error_new (WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_UNDEFINED_CONDITION, "Bizarre response: Not an IQ"); goto out; } switch (sub) { WockyNode *query; WockyNode *node; case WOCKY_STANZA_SUB_TYPE_RESULT: query = wocky_node_get_child_ns ( wocky_stanza_get_top_node (iq), "query", WOCKY_NS_DISCO_INFO); if (query == NULL) { error = g_error_new (WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_UNDEFINED_CONDITION, "Malformed IQ reply"); goto out; } node = wocky_node_get_child (query, "identity"); if (node == NULL) { error = g_error_new (WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_UNDEFINED_CONDITION, "Malformed IQ reply: No Identity"); goto out; } else { const gchar *attr; attr = wocky_node_get_attribute (node, "category"); g_free (priv->id_category); priv->id_category = g_strdup (attr); attr = wocky_node_get_attribute (node, "name"); g_free (priv->id_name); priv->id_name = g_strdup (attr); attr = wocky_node_get_attribute (node, "type"); g_free (priv->id_type); priv->id_type = g_strdup (attr); } wocky_node_each_child (query, store_muc_disco_info, priv); if (priv->state < WOCKY_MUC_INITIATED) priv->state = WOCKY_MUC_INITIATED; break; case WOCKY_STANZA_SUB_TYPE_ERROR: wocky_stanza_extract_errors (iq, NULL, &error, NULL, NULL); break; default: break; } out: if (error != NULL) { g_simple_async_result_set_from_error (result, error); g_error_free (error); } g_simple_async_result_complete (result); g_object_unref (result); g_object_unref (muc); if (iq != NULL) g_object_unref (iq); } gboolean wocky_muc_disco_info_finish (WockyMuc *muc, GAsyncResult *res, GError **error) { GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (res); if (g_simple_async_result_propagate_error (result, error)) return FALSE; return TRUE; } void wocky_muc_disco_info_async (WockyMuc *muc, GAsyncReadyCallback callback, GCancellable *cancel, gpointer data) { WockyMucPrivate *priv = muc->priv; GSimpleAsyncResult *result; WockyStanza *iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, priv->user, priv->jid, '(', "query", ':', WOCKY_NS_DISCO_INFO, ')', NULL); result = g_simple_async_result_new (G_OBJECT (muc), callback, data, wocky_muc_disco_info_async); wocky_porter_send_iq_async (priv->porter, iq, cancel, muc_disco_info, result); } /* ask for MUC member list */ WockyStanza * wocky_muc_create_presence (WockyMuc *muc, WockyStanzaSubType type, const gchar *status) { WockyMucPrivate *priv = muc->priv; WockyStanza *stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_PRESENCE, type, priv->user, priv->jid, NULL); WockyNode *presence = wocky_stanza_get_top_node (stanza); /* There should be separate API to leave a room, but atm there isn't... so * only allow the status to be set directly when making a presence to leave * the muc */ g_assert (status == NULL || type == WOCKY_STANZA_SUB_TYPE_UNAVAILABLE); if (status != NULL) { wocky_node_add_child_with_content (presence, "status", status); } else { g_signal_emit (muc, signals[SIG_FILL_PRESENCE], 0, stanza); } return stanza; } static void register_presence_handler (WockyMuc *muc) { WockyMucPrivate *priv = muc->priv; if (priv->pres_handler == 0) priv->pres_handler = wocky_porter_register_handler_from (priv->porter, WOCKY_STANZA_TYPE_PRESENCE, WOCKY_STANZA_SUB_TYPE_NONE, priv->rjid, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, handle_presence, muc, NULL); } static void register_message_handler (WockyMuc *muc) { WockyMucPrivate *priv = muc->priv; if (priv->mesg_handler == 0) priv->mesg_handler = wocky_porter_register_handler_from (priv->porter, WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, priv->rjid, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, handle_message, muc, NULL); } static guint extract_status_codes (WockyNode *x) { guint codes = 0; WockyNodeIter iter; WockyNode *node; wocky_node_iter_init (&iter, x, "status", NULL); while (wocky_node_iter_next (&iter, &node)) { const gchar *code; WockyMucStatusCode cnum; code = wocky_node_get_attribute (node, "code"); if (code == NULL) continue; cnum = status_code_to_muc_flag (g_ascii_strtoull (code, NULL, 10)); codes |= cnum; /* OWN_PRESENCE is a SHOULD * * CHANGE_FORCED is a MUST which * * implies OWN_PRESENCE */ /* 201 (NEW_ROOM) also implies OWN_PRESENCE */ if (cnum == WOCKY_MUC_CODE_NICK_CHANGE_FORCED) codes |= WOCKY_MUC_CODE_OWN_PRESENCE; if (cnum == WOCKY_MUC_CODE_NEW_ROOM) codes |= WOCKY_MUC_CODE_OWN_PRESENCE; } return codes; } static void presence_features ( WockyMucPrivate *priv, guint codes) { if ((codes & WOCKY_MUC_CODE_CFG_ONYMOUS) != 0) { priv->room_type |= WOCKY_MUC_NONANONYMOUS; priv->room_type &= ~WOCKY_MUC_SEMIANONYMOUS; } else if ((codes & WOCKY_MUC_CODE_CFG_SEMIONYMOUS) != 0) { priv->room_type |= WOCKY_MUC_SEMIANONYMOUS; priv->room_type &= ~WOCKY_MUC_NONANONYMOUS; } else if ((codes & WOCKY_MUC_CODE_CFG_ANONYMOUS) != 0) { priv->room_type &= ~(WOCKY_MUC_NONANONYMOUS|WOCKY_MUC_SEMIANONYMOUS); } } #define REPLACE_STR(place,val) \ if (wocky_strdiff (place, val)) \ { \ g_free (place); \ place = g_strdup (val); \ } static void handle_self_presence (WockyMuc *muc, WockyStanza *stanza, const gchar *nick, WockyMucRole role, WockyMucAffiliation aff, const gchar *actor, const gchar *why, const gchar *status, guint codes) { gboolean nick_update = FALSE; gboolean permission_update = FALSE; WockyMucPrivate *priv = muc->priv; DEBUG ("Received our own presence"); if (wocky_strdiff (priv->nick, nick)) { nick_update = TRUE; g_free (priv->nick); priv->nick = g_strdup (nick); } /* we already know if we changed our own status, so no signal for that */ REPLACE_STR (priv->status, status); permission_update = ((priv->role != role) || (priv->affiliation != aff)); priv->role = role; priv->affiliation = aff; presence_features (priv, codes); if (nick_update) { gchar *new_jid = g_strdup_printf ("%s@%s/%s", priv->room, priv->service, priv->nick); g_free (priv->jid); priv->jid = new_jid; g_signal_emit (muc, signals[SIG_NICK_CHANGE], 0, stanza, codes); } if (permission_update) g_signal_emit (muc, signals[SIG_PERM_CHANGE], 0, stanza, codes, actor, why); } static gboolean handle_user_presence (WockyMuc *muc, WockyStanza *stanza, const gchar *from, const gchar *jid, const gchar *nick, WockyMucRole role, WockyMucAffiliation aff, const gchar *actor, const gchar *why, const gchar *status, guint codes) { WockyMucPrivate *priv = muc->priv; WockyMucMember *member = NULL; if (nick == NULL) return FALSE; member = g_hash_table_lookup (priv->members, from); if (member == NULL) { DEBUG ("New presence from %s, %s (state: %d)", from, nick, priv->state); member = alloc_member (); g_hash_table_insert (priv->members, g_strdup (from), member); } else { } REPLACE_STR (member->from, from); REPLACE_STR (member->jid, jid); REPLACE_STR (member->nick, nick); REPLACE_STR (member->status, status); member->role = role; member->affiliation = aff; if (member->presence_stanza != NULL) g_object_unref (member->presence_stanza); member->presence_stanza = g_object_ref (stanza); if (priv->state >= WOCKY_MUC_JOINED) g_signal_emit (muc, signals[SIG_PRESENCE], 0, stanza, codes, member); return TRUE; } static WockyMucRole string_to_role (const gchar *role) { if (!wocky_strdiff (role, "visitor")) return WOCKY_MUC_ROLE_VISITOR; if (!wocky_strdiff (role, "participant")) return WOCKY_MUC_ROLE_PARTICIPANT; if (!wocky_strdiff (role, "moderator")) return WOCKY_MUC_ROLE_MODERATOR; return WOCKY_MUC_ROLE_NONE; } static WockyMucAffiliation string_to_aff (const gchar *aff) { if (!wocky_strdiff (aff, "outcast")) return WOCKY_MUC_AFFILIATION_OUTCAST; if (!wocky_strdiff (aff, "member")) return WOCKY_MUC_AFFILIATION_MEMBER; if (!wocky_strdiff (aff, "admin")) return WOCKY_MUC_AFFILIATION_ADMIN; if (!wocky_strdiff (aff, "owner")) return WOCKY_MUC_AFFILIATION_OWNER; return WOCKY_MUC_AFFILIATION_NONE; } static gboolean handle_presence_standard (WockyMuc *muc, WockyStanza *stanza, WockyStanzaSubType type, const gchar *resource) { WockyNode *node = wocky_stanza_get_top_node (stanza); WockyNode *x = wocky_node_get_child_ns (node, "x", WOCKY_NS_MUC_USER); WockyNode *item = NULL; const gchar *from = wocky_stanza_get_from (stanza); const gchar *pjid = NULL; const gchar *pnic = NULL; const gchar *role = NULL; const gchar *aff = NULL; guint codes = 0; const gchar *ajid = NULL; const gchar *why = NULL; WockyMucPrivate *priv = muc->priv; WockyMucRole r = WOCKY_MUC_ROLE_NONE; WockyMucAffiliation a = WOCKY_MUC_AFFILIATION_NONE; gboolean self_presence = FALSE; const gchar *msg = NULL; msg = wocky_node_get_content_from_child (node, "status"); if (x == NULL) return FALSE; item = wocky_node_get_child (x, "item"); if (item != NULL) { WockyNode *actor = NULL; WockyNode *cause = NULL; pjid = wocky_node_get_attribute (item, "jid"); pnic = wocky_node_get_attribute (item, "nick"); role = wocky_node_get_attribute (item, "role"); aff = wocky_node_get_attribute (item, "affiliation"); actor = wocky_node_get_child (item, "actor"); cause = wocky_node_get_child (item, "reason"); r = string_to_role (role); a = string_to_aff (aff); if (actor != NULL) ajid = wocky_node_get_attribute (actor, "jid"); if (cause != NULL) why = cause->content; } /* if this was not in the item, set it from the envelope: */ if (pnic == NULL) pnic = resource; codes = extract_status_codes (x); /* belt and braces: it is possible OWN_PRESENCE is not set, as it is * * only a SHOULD in the RFC: check the 'from' stanza attribute and the * * jid item node attribute against the MUC jid and the users full jid * * respectively to see if this is our own presence */ if (!wocky_strdiff (priv->jid, from) || !wocky_strdiff (priv->user, pjid) ) codes |= WOCKY_MUC_CODE_OWN_PRESENCE; self_presence = (codes & WOCKY_MUC_CODE_OWN_PRESENCE) != 0; /* ok, we've extracted all the presence stanza data we should need: * * if this was a presence notification, deal with it: */ if (type == WOCKY_STANZA_SUB_TYPE_NONE) { /* if this was the first time we got our own presence it also means * * we successfully joined the channel, so update our internal state * * and emit the channel-joined signal */ if (self_presence) { handle_self_presence (muc, stanza, pnic, r, a, ajid, why, msg, codes); if (priv->state < WOCKY_MUC_JOINED) { priv->state = WOCKY_MUC_JOINED; if (priv->join_cb != NULL) { g_simple_async_result_complete (priv->join_cb); g_object_unref (priv->join_cb); priv->join_cb = NULL; } g_signal_emit (muc, signals[SIG_JOINED], 0, stanza, codes); } else g_signal_emit (muc, signals[SIG_OWN_PRESENCE], 0, stanza, codes); /* Allow other handlers to run for this stanza. */ return FALSE; } /* if this is someone else's presence, update internal member list */ else { return handle_user_presence (muc, stanza, from, /* room@service/nick */ pjid, /* jid attr from item */ pnic, /* nick attr from item or /res from envelope 'from' */ r, a, ajid, why, msg, codes); } } else if (type == WOCKY_STANZA_SUB_TYPE_UNAVAILABLE) { if (self_presence) { priv->state = WOCKY_MUC_ENDED; priv->role = WOCKY_MUC_ROLE_NONE; g_signal_emit (muc, signals[SIG_PARTED], 0, stanza, codes, ajid, why, msg); return TRUE; } else { WockyMucMember *member = g_hash_table_lookup (priv->members, from); if (member == NULL) { DEBUG ("Someone not in the muc left!?"); return FALSE; } g_signal_emit (muc, signals[SIG_LEFT], 0, stanza, codes, member, ajid, why, msg); g_hash_table_remove (priv->members, from); return TRUE; } } return FALSE; } static gboolean handle_presence_error (WockyMuc *muc, WockyStanza *stanza) { gboolean ok = FALSE; WockyMucPrivate *priv = muc->priv; WockyXmppErrorType type; GError *error = NULL; wocky_stanza_extract_errors (stanza, &type, &error, NULL, NULL); if (priv->state >= WOCKY_MUC_JOINED) { DEBUG ("presence error after joining; not handled"); DEBUG (" %s: %s", wocky_xmpp_error_string (error->code), error->message); } g_signal_emit (muc, signals[SIG_PRESENCE_ERROR], 0, stanza, type, error); g_clear_error (&error); return ok; } static gboolean handle_presence (WockyPorter *porter, WockyStanza *stanza, gpointer data) { WockyMuc *muc = WOCKY_MUC (data); WockyStanzaSubType subtype; gboolean handled = FALSE; wocky_stanza_get_type_info (stanza, NULL, &subtype); switch (subtype) { case WOCKY_STANZA_SUB_TYPE_NONE: case WOCKY_STANZA_SUB_TYPE_UNAVAILABLE: { gchar *resource; /* If the JID is unparseable, discard the stanza. The porter shouldn't * even give us such stanzas. */ if (!wocky_decode_jid (wocky_stanza_get_from (stanza), NULL, NULL, &resource)) return TRUE; handled = handle_presence_standard (muc, stanza, subtype, resource); g_free (resource); break; } case WOCKY_STANZA_SUB_TYPE_ERROR: handled = handle_presence_error (muc, stanza); break; default: DEBUG ("unexpected stanza sub-type: %d", subtype); break; } return handled; } /* Looks up the sender of a message. If they're not currently a MUC member, * then a temporary structure is created, and @member_is_temporary is set to * %TRUE; the caller needs to free the returned value when they're done with * it. */ static WockyMucMember * get_message_sender (WockyMuc *muc, const gchar *from, gboolean *member_is_temporary) { WockyMucPrivate *priv = muc->priv; WockyMucMember *who = g_hash_table_lookup (priv->members, from); if (who != NULL) { *member_is_temporary = FALSE; return who; } /* Okay, it's from someone not currently in the MUC. We'll have to * fake up a structure. */ *member_is_temporary = TRUE; who = alloc_member (); who->from = wocky_normalise_jid (from); if (!wocky_strdiff (who->from, priv->jid)) { /* It's from us! */ who->jid = g_strdup (priv->user); who->nick = g_strdup (priv->nick); who->role = priv->role; who->affiliation = priv->affiliation; } /* else, we don't know anything more about the sender. * * FIXME: actually, if the server uses XEP-0203 Delayed Delivery * rather than XEP-0091 Legacy Delayed Delivery, the from='' * attribute of the element says who the original JID * actually was. Unfortunately, XEP-0091 said that from='' should be * the bare JID of the MUC, so it's completely useless. * * FIXME: also: we assume here that a delayed message from resource * /blah was sent by the user currently called /blah, but that ain't * necessarily so. */ return who; } /* * Parse timestamp of delayed messages. For non-delayed, it's 0. */ static GDateTime * extract_timestamp (WockyNode *msg) { WockyNode *x = wocky_node_get_child_ns (msg, "x", WOCKY_XMPP_NS_DELAY); GDateTime *stamp = NULL; if (x != NULL) { const gchar *tm = wocky_node_get_attribute (x, "stamp"); /* These timestamps do not contain a timezone, but are understood to be * in GMT. They're in the format yyyymmddThhmmss, so if we append 'Z' * we'll get (one of the many valid syntaxes for) an ISO-8601 timestamp. */ if (tm != NULL) { GTimeVal timeval = { 0, 0 }; gchar *tm_dup = g_strdup_printf ("%sZ", tm); /* FIXME: GTimeVal should go away */ if (!g_time_val_from_iso8601 (tm_dup, &timeval)) DEBUG ("Malformed date string '%s' for " WOCKY_XMPP_NS_DELAY, tm); else stamp = g_date_time_new_from_timeval_local (&timeval); g_free (tm_dup); } } return stamp; } /* Messages starting with /me are ACTION messages, and the /me should be * removed. type="chat" messages are NORMAL. Everything else is * something that doesn't necessarily expect a reply or ongoing * conversation ("normal") or has been auto-sent, so we make it NOTICE in * all other cases. */ static WockyMucMsgType determine_message_type (const gchar **body, WockyStanzaSubType sub_type) { WockyMucMsgType mtype = WOCKY_MUC_MSG_NOTICE; if (*body != NULL) { if (g_str_has_prefix (*body, "/me ")) { mtype = WOCKY_MUC_MSG_ACTION; *body += 4; } else if (g_str_equal (body, "/me")) { mtype = WOCKY_MUC_MSG_ACTION; *body = ""; } else if ((sub_type == WOCKY_STANZA_SUB_TYPE_GROUPCHAT) || (sub_type == WOCKY_STANZA_SUB_TYPE_CHAT)) { mtype = WOCKY_MUC_MSG_NORMAL; } } return mtype; } static WockyMucMsgState extract_chat_state (WockyNode *msg) { WockyNode *child = wocky_node_get_first_child_ns (msg, WOCKY_NS_CHATSTATE); WockyMucMsgState mstate; if (child == NULL || !wocky_enum_from_nick (WOCKY_TYPE_MUC_MSG_STATE, child->name, &mstate)) mstate = WOCKY_MUC_MSG_NONE; return mstate; } static gboolean handle_message (WockyPorter *porter, WockyStanza *stanza, gpointer data) { WockyMuc *muc = WOCKY_MUC (data); WockyNode *msg = wocky_stanza_get_top_node (stanza); const gchar *id = wocky_node_get_attribute (msg, "id"); const gchar *from = wocky_node_get_attribute (msg, "from"); const gchar *body = wocky_node_get_content_from_child (msg, "body"); const gchar *subj = wocky_node_get_content_from_child (msg, "subject"); GDateTime *datetime = extract_timestamp (msg); WockyStanzaSubType sub_type; WockyMucMsgType mtype; WockyMucMember *who = NULL; gboolean member_is_temporary = FALSE; wocky_stanza_get_type_info (stanza, NULL, &sub_type); /* if the message purports to be from a MUC member, treat as such: */ if (strchr (from, '/') != NULL) { who = get_message_sender (muc, from, &member_is_temporary); /* If it's a message from a member (as opposed to the MUC itself), and * it's not type='groupchat', then it's a non-MUC message relayed by the * MUC and therefore not our responsibility. */ if (sub_type != WOCKY_STANZA_SUB_TYPE_GROUPCHAT) { DEBUG ("Non groupchat message from MUC member %s: ignored.", from); return FALSE; } } mtype = determine_message_type (&body, sub_type); if (sub_type == WOCKY_STANZA_SUB_TYPE_ERROR) { WockyXmppErrorType etype; GError *error = NULL; wocky_stanza_extract_errors (stanza, &etype, &error, NULL, NULL); g_signal_emit (muc, signals[SIG_MSG_ERR], 0, stanza, mtype, id, datetime, who, body, etype, error); g_clear_error (&error); } else { WockyMucMsgState mstate = extract_chat_state (msg); g_signal_emit (muc, signals[SIG_MSG], 0, stanza, mtype, id, datetime, who, body, subj, mstate); } if (member_is_temporary) free_member (who); if (datetime != NULL) g_date_time_unref (datetime); return TRUE; } void wocky_muc_join (WockyMuc *muc, GCancellable *cancel) { WockyMucPrivate *priv = muc->priv; WockyStanza *presence = wocky_muc_create_presence (muc, WOCKY_STANZA_SUB_TYPE_NONE, NULL); WockyNode *x = wocky_node_add_child_ns (wocky_stanza_get_top_node (presence), "x", WOCKY_NS_MUC); if (priv->pass != NULL) wocky_node_add_child_with_content (x, "password", priv->pass); if (priv->state < WOCKY_MUC_INITIATED) { register_presence_handler (muc); register_message_handler (muc); } priv->state = WOCKY_MUC_INITIATED; wocky_porter_send (priv->porter, presence); g_object_unref (presence); } /* misc meta data */ const gchar * wocky_muc_jid (WockyMuc *muc) { WockyMucPrivate *priv = muc->priv; return priv->jid; } WockyMucRole wocky_muc_role (WockyMuc *muc) { WockyMucPrivate *priv = muc->priv; return priv->role; } WockyMucAffiliation wocky_muc_affiliation (WockyMuc *muc) { WockyMucPrivate *priv = muc->priv; return priv->affiliation; } const gchar * wocky_muc_user (WockyMuc *muc) { WockyMucPrivate *priv = muc->priv; return priv->user; } GHashTable * wocky_muc_members (WockyMuc *muc) { WockyMucPrivate *priv = muc->priv; if (priv->members != NULL) return g_hash_table_ref (priv->members); return NULL; } WockyMucState wocky_muc_get_state (WockyMuc *muc) { WockyMucPrivate *priv = muc->priv; return priv->state; } /* send message to muc */ /* send message to participant */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-utils.c0000664000175000017500000004476512212322440024502 0ustar00cassidycassidy00000000000000/* * wocky-utils.c - Code for Wocky utility functions * Copyright © 2007–2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * wocky_g_value_slice_* functions have been copied from telepathy-glib's * util.c file: * Copyright (C) 2006-2007 Collabora Ltd. * Copyright (C) 2006-2007 Nokia Corporation */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-utils.h" #include #include /** * wocky_strdiff: * @left: The first string to compare (may be NULL) * @right: The second string to compare (may be NULL) * * Return %TRUE if the given strings are different. Unlike #strcmp this * function will handle null pointers, treating them as distinct from any * string. * * Returns: %FALSE if @left and @right are both %NULL, or if * neither is %NULL and both have the same contents; %TRUE otherwise */ gboolean wocky_strdiff (const gchar *left, const gchar *right) { return g_strcmp0 (left, right) != 0; } static gboolean validate_jid_node (const gchar *node) { /* See RFC 3920 §3.3. */ const gchar *c; for (c = node; *c; c++) if (strchr ("\"&'/:<>@", *c)) /* RFC 3920 §A.5 */ return FALSE; return TRUE; } static gboolean validate_jid_domain (const gchar *domain) { /* XXX: This doesn't do proper validation: it checks the character * range for ASCII characters, but lets through any non-ASCII characters. See * the ifdef-d out tests in wocky-jid-validation-test.c for examples of * erroneously accepted JIDs. In theory, we check that the domain is a * well-formed IDN or an IPv4/IPv6 address literal. * * See RFC 3920 §3.2. */ const gchar *c; for (c = domain; *c; c++) { if ((unsigned char) *c >= 0x7F) continue; if (!g_ascii_isalnum (*c) && !strchr (":-.", *c)) return FALSE; } return TRUE; } /** * wocky_decode_jid: * @jid: a JID * @node: (allow-none): address to store the normalised localpart of the JID * @domain: (allow-none): address to store the normalised domainpart of the JID * @resource: address to store the resourcepart of the JID * * If @jid is valid, returns %TRUE and sets the caller's @node, @domain and * @resource pointers. @node and @resource will be set to %NULL if the * respective part is not present in @jid. If @jid is invalid, sets @node, * @domain and @resource to %NULL and returns %FALSE. * * In theory, the returned parts will be normalised as specified in RFC 6122 (XMPP Address * Format); in practice, Wocky does not fully implement the * normalisation and validation algorithms. FIXME: Do nodeprep/resourceprep and * length checking. * * Returns: %TRUE if the JID is valid */ gboolean wocky_decode_jid (const gchar *jid, gchar **node, gchar **domain, gchar **resource) { char *tmp_jid, *tmp_node, *tmp_domain, *tmp_resource; g_assert (jid != NULL); if (node != NULL) *node = NULL; if (domain != NULL) *domain = NULL; if (resource != NULL) *resource = NULL; /* Take a local copy so we don't modify the caller's string. */ tmp_jid = g_strdup (jid); /* If there's a slash in tmp_jid, split it in two and take the second part as * the resource. */ tmp_resource = strchr (tmp_jid, '/'); if (tmp_resource != NULL) { *tmp_resource = '\0'; tmp_resource++; } else { tmp_resource = NULL; } /* If there's an at sign in tmp_jid, split it in two and set tmp_node and * tmp_domain appropriately. Otherwise, tmp_node is NULL and the domain is * the whole string. */ tmp_domain = strchr (tmp_jid, '@'); if (tmp_domain != NULL) { *tmp_domain = '\0'; tmp_domain++; tmp_node = tmp_jid; } else { tmp_domain = tmp_jid; tmp_node = NULL; } /* Domain must be non-empty and not contain invalid characters. If the node * or the resource exist, they must be non-empty and the node must not * contain invalid characters. */ if (*tmp_domain == '\0' || !validate_jid_domain (tmp_domain) || (tmp_node != NULL && (*tmp_node == '\0' || !validate_jid_node (tmp_node))) || (tmp_resource != NULL && *tmp_resource == '\0')) { g_free (tmp_jid); return FALSE; } /* the server must be stored after we find the resource, in case we * truncated a resource from it */ if (domain != NULL) *domain = g_utf8_strdown (tmp_domain, -1); /* store the username if the user provided a pointer */ if (tmp_node != NULL && node != NULL) *node = g_utf8_strdown (tmp_node, -1); /* store the resource if the user provided a pointer */ if (tmp_resource != NULL && resource != NULL) *resource = g_strdup (tmp_resource); /* free our working copy */ g_free (tmp_jid); return TRUE; } /** * wocky_normalise_jid: * @jid: a JID * * Returns: a normalised JID, using the same rules as wocky_decode_jid(), * or %NULL if the JID could not be sensibly decoded. * This value should be freed when you are done with it. */ gchar * wocky_normalise_jid (const gchar *jid) { gchar *node = NULL; gchar *domain = NULL; gchar *resource = NULL; gchar *rval = NULL; if (jid == NULL) return NULL; if (!wocky_decode_jid (jid, &node, &domain, &resource)) return NULL; rval = wocky_compose_jid (node, domain, resource); g_free (node); g_free (domain); g_free (resource); return rval; } static inline gsize strlen0 (const gchar *s) { return (s == NULL ? 0 : strlen (s)); } /** * wocky_compose_jid: * @node: (allow-none): the node part of a JID, possibly empty or %NULL * @domain: the non-%NULL domain part of a JID * @resource: (allow-none): the resource part of a JID, possibly empty or %NULL * * Composes a JID from its parts. If @node is empty or %NULL, the '@' * separator is also omitted; if @resource is empty or %NULL, the '/' separator * is also omitted. @node and @domain are assumed to have already been * normalised. * * Returns: a JID constructed from @node, @domain and @resource */ gchar * wocky_compose_jid (const gchar *node, const gchar *domain, const gchar *resource) { GString *normal = NULL; normal = g_string_sized_new (strlen0 (node) + strlen0 (domain) + strlen0 (resource) + 2); if (node != NULL && *node != '\0') g_string_printf (normal, "%s@%s", node, domain); else g_string_printf (normal, "%s", domain); if (resource != NULL && *resource != '\0' && normal->len > 0) g_string_append_printf (normal, "/%s", resource); return g_string_free (normal, FALSE); } /** * wocky_g_value_slice_new: * @type: The type desired for the new GValue * * Slice-allocate an empty #GValue. wocky_g_value_slice_new_boolean() and similar * functions are likely to be more convenient to use for the types supported. * * Returns: a newly allocated, newly initialized #GValue, to be freed with * wocky_g_value_slice_free() or g_slice_free(). * Since: 0.5.14 */ GValue * wocky_g_value_slice_new (GType type) { GValue *ret = g_slice_new0 (GValue); g_value_init (ret, type); return ret; } /** * wocky_g_value_slice_new_boolean: * @b: a boolean value * * Slice-allocate and initialize a #GValue. This function is convenient to * use when constructing hash tables from string to #GValue, for example. * * Returns: a #GValue of type %G_TYPE_BOOLEAN with value @b, to be freed with * wocky_g_value_slice_free() or g_slice_free() * * Since: 0.7.27 */ GValue * wocky_g_value_slice_new_boolean (gboolean b) { GValue *v = wocky_g_value_slice_new (G_TYPE_BOOLEAN); g_value_set_boolean (v, b); return v; } /** * wocky_g_value_slice_new_int: * @n: an integer * * Slice-allocate and initialize a #GValue. This function is convenient to * use when constructing hash tables from string to #GValue, for example. * * Returns: a #GValue of type %G_TYPE_INT with value @n, to be freed with * wocky_g_value_slice_free() or g_slice_free() * * Since: 0.7.27 */ GValue * wocky_g_value_slice_new_int (gint n) { GValue *v = wocky_g_value_slice_new (G_TYPE_INT); g_value_set_int (v, n); return v; } /** * wocky_g_value_slice_new_int64: * @n: a 64-bit integer * * Slice-allocate and initialize a #GValue. This function is convenient to * use when constructing hash tables from string to #GValue, for example. * * Returns: a #GValue of type %G_TYPE_INT64 with value @n, to be freed with * wocky_g_value_slice_free() or g_slice_free() * * Since: 0.7.27 */ GValue * wocky_g_value_slice_new_int64 (gint64 n) { GValue *v = wocky_g_value_slice_new (G_TYPE_INT64); g_value_set_int64 (v, n); return v; } /** * wocky_g_value_slice_new_uint: * @n: an unsigned integer * * Slice-allocate and initialize a #GValue. This function is convenient to * use when constructing hash tables from string to #GValue, for example. * * Returns: a #GValue of type %G_TYPE_UINT with value @n, to be freed with * wocky_g_value_slice_free() or g_slice_free() * * Since: 0.7.27 */ GValue * wocky_g_value_slice_new_uint (guint n) { GValue *v = wocky_g_value_slice_new (G_TYPE_UINT); g_value_set_uint (v, n); return v; } /** * wocky_g_value_slice_new_uint64: * @n: a 64-bit unsigned integer * * Slice-allocate and initialize a #GValue. This function is convenient to * use when constructing hash tables from string to #GValue, for example. * * Returns: a #GValue of type %G_TYPE_UINT64 with value @n, to be freed with * wocky_g_value_slice_free() or g_slice_free() * * Since: 0.7.27 */ GValue * wocky_g_value_slice_new_uint64 (guint64 n) { GValue *v = wocky_g_value_slice_new (G_TYPE_UINT64); g_value_set_uint64 (v, n); return v; } /** * wocky_g_value_slice_new_double: * @d: a number * * Slice-allocate and initialize a #GValue. This function is convenient to * use when constructing hash tables from string to #GValue, for example. * * Returns: a #GValue of type %G_TYPE_DOUBLE with value @n, to be freed with * wocky_g_value_slice_free() or g_slice_free() * * Since: 0.7.27 */ GValue * wocky_g_value_slice_new_double (double n) { GValue *v = wocky_g_value_slice_new (G_TYPE_DOUBLE); g_value_set_double (v, n); return v; } /** * wocky_g_value_slice_new_string: * @string: a string to be copied into the value * * Slice-allocate and initialize a #GValue. This function is convenient to * use when constructing hash tables from string to #GValue, for example. * * Returns: a #GValue of type %G_TYPE_STRING whose value is a copy of @string, * to be freed with wocky_g_value_slice_free() or g_slice_free() * * Since: 0.7.27 */ GValue * wocky_g_value_slice_new_string (const gchar *string) { GValue *v = wocky_g_value_slice_new (G_TYPE_STRING); g_value_set_string (v, string); return v; } /** * wocky_g_value_slice_new_static_string: * @string: a static string which must remain valid forever, to be pointed to * by the value * * Slice-allocate and initialize a #GValue. This function is convenient to * use when constructing hash tables from string to #GValue, for example. * * Returns: a #GValue of type %G_TYPE_STRING whose value is @string, * to be freed with wocky_g_value_slice_free() or g_slice_free() * * Since: 0.7.27 */ GValue * wocky_g_value_slice_new_static_string (const gchar *string) { GValue *v = wocky_g_value_slice_new (G_TYPE_STRING); g_value_set_static_string (v, string); return v; } /** * wocky_g_value_slice_new_take_string: * @string: a string which will be freed with g_free() by the returned #GValue * (the caller must own it before calling this function, but no longer owns * it after this function returns) * * Slice-allocate and initialize a #GValue. This function is convenient to * use when constructing hash tables from string to #GValue, for example. * * Returns: a #GValue of type %G_TYPE_STRING whose value is @string, * to be freed with wocky_g_value_slice_free() or g_slice_free() * * Since: 0.7.27 */ GValue * wocky_g_value_slice_new_take_string (gchar *string) { GValue *v = wocky_g_value_slice_new (G_TYPE_STRING); g_value_take_string (v, string); return v; } /** * wocky_g_value_slice_new_boxed: * @type: a boxed type * @p: a pointer of type @type, which will be copied * * Slice-allocate and initialize a #GValue. This function is convenient to * use when constructing hash tables from string to #GValue, for example. * * Returns: a #GValue of type @type whose value is a copy of @p, * to be freed with wocky_g_value_slice_free() or g_slice_free() * * Since: 0.7.27 */ GValue * wocky_g_value_slice_new_boxed (GType type, gconstpointer p) { GValue *v; g_return_val_if_fail (G_TYPE_FUNDAMENTAL (type) == G_TYPE_BOXED, NULL); v = wocky_g_value_slice_new (type); g_value_set_boxed (v, p); return v; } /** * wocky_g_value_slice_new_static_boxed: * @type: a boxed type * @p: a pointer of type @type, which must remain valid forever * * Slice-allocate and initialize a #GValue. This function is convenient to * use when constructing hash tables from string to #GValue, for example. * * Returns: a #GValue of type @type whose value is @p, * to be freed with wocky_g_value_slice_free() or g_slice_free() * * Since: 0.7.27 */ GValue * wocky_g_value_slice_new_static_boxed (GType type, gconstpointer p) { GValue *v; g_return_val_if_fail (G_TYPE_FUNDAMENTAL (type) == G_TYPE_BOXED, NULL); v = wocky_g_value_slice_new (type); g_value_set_static_boxed (v, p); return v; } /** * wocky_g_value_slice_new_take_boxed: * @type: a boxed type * @p: a pointer of type @type which will be freed with g_boxed_free() by the * returned #GValue (the caller must own it before calling this function, but * no longer owns it after this function returns) * * Slice-allocate and initialize a #GValue. This function is convenient to * use when constructing hash tables from string to #GValue, for example. * * Returns: a #GValue of type @type whose value is @p, * to be freed with wocky_g_value_slice_free() or g_slice_free() * * Since: 0.7.27 */ GValue * wocky_g_value_slice_new_take_boxed (GType type, gpointer p) { GValue *v; g_return_val_if_fail (G_TYPE_FUNDAMENTAL (type) == G_TYPE_BOXED, NULL); v = wocky_g_value_slice_new (type); g_value_take_boxed (v, p); return v; } /** * wocky_g_value_slice_free: * @value: A GValue which was allocated with the g_slice API * * Unset and free a slice-allocated GValue. * * (GDestroyNotify) wocky_g_value_slice_free can be used * as a destructor for values in a #GHashTable, for example. */ void wocky_g_value_slice_free (GValue *value) { g_value_unset (value); g_slice_free (GValue, value); } /** * wocky_g_value_slice_dup: * @value: A GValue * * * * Returns: a newly allocated copy of @value, to be freed with * wocky_g_value_slice_free() or g_slice_free(). * Since: 0.5.14 */ GValue * wocky_g_value_slice_dup (const GValue *value) { GValue *ret = wocky_g_value_slice_new (G_VALUE_TYPE (value)); g_value_copy (value, ret); return ret; } /** * wocky_enum_from_nick: * @enum_type: the GType of a subtype of GEnum * @nick: a non-%NULL string purporting to be the nickname of a value of * @enum_type * @value: the address at which to store the value of @enum_type corresponding * to @nick if this functions returns %TRUE; if this function returns * %FALSE, this variable will be left untouched. * * * * Returns: %TRUE if @nick is a member of @enum_type, or %FALSE otherwise */ gboolean wocky_enum_from_nick ( GType enum_type, const gchar *nick, gint *value) { GEnumClass *klass = g_type_class_ref (enum_type); GEnumValue *enum_value; g_return_val_if_fail (klass != NULL, FALSE); g_return_val_if_fail (value != NULL, FALSE); enum_value = g_enum_get_value_by_nick (klass, nick); g_type_class_unref (klass); if (enum_value != NULL) { *value = enum_value->value; return TRUE; } else { return FALSE; } } /** * wocky_enum_to_nick: * @enum_type: the GType of a subtype of GEnum * @value: a value of @enum_type * * * * Returns: the nickname of @value, or %NULL if it is not, in fact, a value of * @enum_type */ const gchar * wocky_enum_to_nick ( GType enum_type, gint value) { GEnumClass *klass = g_type_class_ref (enum_type); GEnumValue *enum_value; g_return_val_if_fail (klass != NULL, NULL); enum_value = g_enum_get_value (klass, value); g_type_class_unref (klass); if (enum_value != NULL) return enum_value->value_nick; else return NULL; } /** * wocky_absolutize_path: * @path: an absolute or relative path * * Return an absolute form of @path. This cleans up duplicate slashes, "." or * ".." path segments, etc., and prepends g_get_current_dir() if necessary, but * does not necessarily resolve symlinks. * * Returns: an absolute path which must be freed with g_free(), or possibly * %NULL for invalid filenames */ gchar * wocky_absolutize_path (const gchar *path) { GFile *cwd, *absolute; gchar *cwd_str, *ret; cwd_str = g_get_current_dir (); cwd = g_file_new_for_path (cwd_str); g_free (cwd_str); if (cwd == NULL) return NULL; absolute = g_file_resolve_relative_path (cwd, path); if (absolute == NULL) { g_object_unref (cwd); return NULL; } ret = g_file_get_path (absolute); /* possibly NULL */ g_object_unref (cwd); g_object_unref (absolute); return ret; } GList * wocky_list_deep_copy (GBoxedCopyFunc copy, GList *items) { GList *ret = NULL; GList *l; g_return_val_if_fail (copy != NULL, NULL); for (l = items; l != NULL; l = l->next) ret = g_list_prepend (ret, copy (l->data)); return g_list_reverse (ret); } GString * wocky_g_string_dup (const GString *str) { if (str == NULL) return NULL; return g_string_new_len (str->str, str->len); } void wocky_g_string_free (GString *str) { if (str != NULL) g_string_free (str, TRUE); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-namespaces.h0000664000175000017500000001430512212322440025451 0ustar00cassidycassidy00000000000000#if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_NAMESPACES_H__ #define __WOCKY_NAMESPACES_H__ #define WOCKY_XMPP_NS_JABBER_CLIENT \ "jabber:client" #define WOCKY_XMPP_NS_STREAM \ "http://etherx.jabber.org/streams" #define WOCKY_XMPP_NS_STREAMS \ "urn:ietf:params:xml:ns:xmpp-streams" #define WOCKY_XMPP_NS_BIND \ "urn:ietf:params:xml:ns:xmpp-bind" #define WOCKY_XMPP_NS_SESSION \ "urn:ietf:params:xml:ns:xmpp-session" #define WOCKY_XMPP_NS_TLS \ "urn:ietf:params:xml:ns:xmpp-tls" #define WOCKY_XMPP_NS_SASL_AUTH \ "urn:ietf:params:xml:ns:xmpp-sasl" #define WOCKY_NS_DISCO_INFO \ "http://jabber.org/protocol/disco#info" #define WOCKY_NS_DISCO_ITEMS \ "http://jabber.org/protocol/disco#items" #define WOCKY_XMPP_NS_XHTML_IM \ "http://jabber.org/protocol/xhtml-im" #define WOCKY_XMPP_NS_IBB \ "http://jabber.org/protocol/ibb" #define WOCKY_XMPP_NS_AMP \ "http://jabber.org/protocol/amp" #define WOCKY_W3C_NS_XHTML \ "http://www.w3.org/1999/xhtml" #define WOCKY_TELEPATHY_NS_CAPS \ "http://telepathy.freedesktop.org/caps" #define WOCKY_TELEPATHY_NS_TUBES \ "http://telepathy.freedesktop.org/xmpp/tubes" #define WOCKY_TELEPATHY_NS_OLPC_ACTIVITY_PROPS \ "http://laptop.org/xmpp/activity-properties" #define WOCKY_XMPP_NS_SI \ "http://jabber.org/protocol/si" #define WOCKY_XMPP_NS_FEATURENEG \ "http://jabber.org/protocol/feature-neg" #define WOCKY_XMPP_NS_DATA \ "jabber:x:data" #define WOCKY_XMPP_NS_EVENT \ "jabber:x:event" #define WOCKY_XMPP_NS_DELAY \ "jabber:x:delay" #define WOCKY_XMPP_NS_STANZAS \ "urn:ietf:params:xml:ns:xmpp-stanzas" #define WOCKY_XMPP_NS_IQ_OOB \ "jabber:iq:oob" #define WOCKY_XMPP_NS_X_OOB \ "jabber:x:oob" #define WOCKY_TELEPATHY_NS_CLIQUE \ "http://telepathy.freedesktop.org/xmpp/clique" #define WOCKY_XEP77_NS_REGISTER \ "jabber:iq:register" /* Namespaces for XEP-0166 draft v0.15, the most capable Jingle dialect * supported by telepathy-gabble < 0.7.16, including the versions shipped with * Maemo Chinook and Diablo. */ #define WOCKY_XMPP_NS_JINGLE015 \ "http://jabber.org/protocol/jingle" /* RTP audio capability in Jingle v0.15 (obsoleted by WOCKY_XMPP_NS_JINGLE_RTP) */ #define WOCKY_XMPP_NS_JINGLE_DESCRIPTION_AUDIO \ "http://jabber.org/protocol/jingle/description/audio" /* RTP video capability in Jingle v0.15 (obsoleted by WOCKY_XMPP_NS_JINGLE_RTP) */ #define WOCKY_XMPP_NS_JINGLE_DESCRIPTION_VIDEO \ "http://jabber.org/protocol/jingle/description/video" /* XEP-0166 Jingle */ #define WOCKY_XMPP_NS_JINGLE \ "urn:xmpp:jingle:1" #define WOCKY_XMPP_NS_JINGLE_ERRORS \ "urn:xmpp:jingle:errors:1" /* XEP-0167 (Jingle RTP) */ #define WOCKY_XMPP_NS_JINGLE_RTP \ "urn:xmpp:jingle:apps:rtp:1" #define WOCKY_XMPP_NS_JINGLE_RTP_ERRORS \ "urn:xmpp:jingle:apps:rtp:errors:1" #define WOCKY_XMPP_NS_JINGLE_RTP_INFO \ "urn:xmpp:jingle:apps:rtp:info:1" #define WOCKY_XMPP_NS_JINGLE_RTP_AUDIO \ "urn:xmpp:jingle:apps:rtp:audio" #define WOCKY_XMPP_NS_JINGLE_RTP_VIDEO \ "urn:xmpp:jingle:apps:rtp:video" /* ProtoXEPs for rtcp-fb and rtp-hdrext */ #define WOCKY_XMPP_NS_JINGLE_RTCP_FB "urn:xmpp:jingle:apps:rtp:rtcp-fb:0" #define WOCKY_XMPP_NS_JINGLE_RTP_HDREXT "urn:xmpp:jingle:apps:rtp:rtp-hdrext:0" /* Google's Jingle dialect */ #define WOCKY_XMPP_NS_GOOGLE_SESSION "http://www.google.com/session" /* Audio capability in Google Jingle dialect */ #define WOCKY_XMPP_NS_GOOGLE_SESSION_PHONE "http://www.google.com/session/phone" /* Video capability in Google's Jingle dialect */ #define WOCKY_XMPP_NS_GOOGLE_SESSION_VIDEO "http://www.google.com/session/video" /* File transfer capability in Google's Jingle dialect */ #define WOCKY_XMPP_NS_GOOGLE_SESSION_SHARE "http://www.google.com/session/share" /* google-p2p transport */ #define WOCKY_XMPP_NS_GOOGLE_TRANSPORT_P2P "http://www.google.com/transport/p2p" /* Jingle RAW-UDP transport */ #define WOCKY_XMPP_NS_JINGLE_TRANSPORT_RAWUDP "urn:xmpp:jingle:transports:raw-udp:1" /* Jingle ICE-UDP transport */ #define WOCKY_XMPP_NS_JINGLE_TRANSPORT_ICEUDP "urn:xmpp:jingle:transports:ice-udp:1" /* Here are some "quirk" pseudo-namespaces imported from Gabble with the Jingle * code and used to work around known bugs in particular Jingle * implementations. ASCII BEL is illegal in XML, so these cannot appear in real * XMPP capabilities. */ /* Gabble 0.7.x with 16 <= x < 29 omits @creator on */ #define WOCKY_QUIRK_OMITS_CONTENT_CREATORS "\x07omits-content-creators" /* The Google Webmail client doesn't support some features */ #define WOCKY_QUIRK_GOOGLE_WEBMAIL_CLIENT "\x07google-webmail-client" /* The Android GTalk client needs a quirk for component names */ #define WOCKY_QUIRK_ANDROID_GTALK_CLIENT "\x07android-gtalk-client" /* Google's extension for retrieving STUN and relay information from the * server. */ #define WOCKY_XMPP_NS_GOOGLE_JINGLE_INFO "google:jingleinfo" /* legacy namespaces */ #define WOCKY_JABBER_NS_AUTH \ "jabber:iq:auth" #define WOCKY_JABBER_NS_AUTH_FEATURE \ "http://jabber.org/features/iq-auth" #define WOCKY_GOOGLE_NS_AUTH \ "http://www.google.com/talk/protocol/auth" #define WOCKY_XMPP_NS_ROSTER \ "jabber:iq:roster" #define WOCKY_XMPP_NS_PUBSUB \ "http://jabber.org/protocol/pubsub" #define WOCKY_XMPP_NS_PUBSUB_EVENT \ WOCKY_XMPP_NS_PUBSUB "#event" #define WOCKY_XMPP_NS_PUBSUB_OWNER \ WOCKY_XMPP_NS_PUBSUB "#owner" #define WOCKY_XMPP_NS_PUBSUB_NODE_CONFIG \ WOCKY_XMPP_NS_PUBSUB "#node_config" #define WOCKY_XMPP_NS_PUBSUB_ERRORS \ WOCKY_XMPP_NS_PUBSUB "#errors" #define WOCKY_XMPP_NS_PING \ "urn:xmpp:ping" #define WOCKY_NS_MUC \ "http://jabber.org/protocol/muc" #define WOCKY_NS_MUC_USER \ WOCKY_NS_MUC "#user" #define WOCKY_NS_MUC_ADMIN \ WOCKY_NS_MUC "#admin" #define WOCKY_NS_MUC_OWNER \ WOCKY_NS_MUC "#owner" #define WOCKY_NS_MUC_UNIQUE \ WOCKY_NS_MUC "#unique" #define WOCKY_NS_CHATSTATE \ "http://jabber.org/protocol/chatstates" #define WOCKY_NS_GOOGLE_SESSION_PHONE \ "http://www.google.com/session/phone" #define WOCKY_NS_GOOGLE_SESSION_VIDEO \ "http://www.google.com/session/video" #define WOCKY_NS_VCARD_TEMP "vcard-temp" #define WOCKY_NS_VCARD_TEMP_UPDATE "vcard-temp:x:update" #endif /* #ifndef __WOCKY_NAMESPACES_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-disco-identity.c0000664000175000017500000001310511720661341026263 0ustar00cassidycassidy00000000000000/* * wocky-disco-identity.c - Source for WockyDiscoIdentity * Copyright (C) 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** * SECTION: wocky-disco-identity * @title: WockyDiscoIdentity * @short_description: Structure holding XMPP disco identity information. * * Contains information regarding the identity information in disco * replies, as described in XEP-0030. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-disco-identity.h" #include #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_PRESENCE #include "wocky-debug-internal.h" G_DEFINE_BOXED_TYPE (WockyDiscoIdentity, wocky_disco_identity, wocky_disco_identity_copy, wocky_disco_identity_free) /** * wocky_disco_identity_new: * @category: disco category * @type: disco type * @lang: disco language * @name: disco name * * * * Returns: a new #WockyDiscoIdentity which should be freed using * wocky_disco_identity_free(). */ WockyDiscoIdentity * wocky_disco_identity_new (const gchar *category, const gchar *type, const gchar *lang, const gchar *name) { WockyDiscoIdentity *ret; g_return_val_if_fail (category != NULL, NULL); g_return_val_if_fail (type != NULL, NULL); ret = g_slice_new (WockyDiscoIdentity); ret->category = g_strdup (category); ret->type = g_strdup (type); ret->lang = g_strdup (lang); ret->name = g_strdup (name); return ret; } /** * wocky_disco_identity_copy: * @source: the #WockyDiscoIdentity to copy * * Creates a new #WockyDiscoIdentity structure with the data given by * @source. The copy also copies the internal data so @source can be * freed after this function is called. * * Returns: a new #WockyDiscoIdentity which is a deep copy of @source */ WockyDiscoIdentity * wocky_disco_identity_copy (const WockyDiscoIdentity *source) { if (source == NULL) return NULL; return wocky_disco_identity_new (source->category, source->type, source->lang, source->name); } /** * wocky_disco_identity_free: * @identity: a #WockyDiscoIdentity * * Frees the memory used by @identity. */ void wocky_disco_identity_free (WockyDiscoIdentity *identity) { if (identity == NULL) return; g_free (identity->category); g_free (identity->type); g_free (identity->lang); g_free (identity->name); g_slice_free (WockyDiscoIdentity, identity); } /** * wocky_disco_identity_array_new: * * Creates a new array of #WockyDiscoIdentity structures. * * Returns: A newly instantiated * array. wocky_disco_identity_array_free() should beq used * to free the memory allocated by this array. * See: wocky_disco_identity_array_free() */ GPtrArray * wocky_disco_identity_array_new (void) { return g_ptr_array_new_with_free_func ( (GDestroyNotify) wocky_disco_identity_free); } /** * wocky_disco_identity_array_copy: * @source: The source array to be copied. * * Copies an array of #WockyDiscoIdentity objects. The returned array contains * new copies of the contents of the source array. * * Returns: A newly instantiated array with new copies of the contents of the * source array. * See: wocky_disco_identity_array_new() */ GPtrArray * wocky_disco_identity_array_copy (const GPtrArray *source) { GPtrArray *ret; guint i; g_return_val_if_fail (source != NULL, NULL); ret = g_ptr_array_sized_new (source->len); g_ptr_array_set_free_func (ret, (GDestroyNotify) wocky_disco_identity_free); for (i = 0; i < source->len; ++i) { g_ptr_array_add (ret, wocky_disco_identity_copy (g_ptr_array_index (source, i))); } return ret; } /** * wocky_disco_identity_array_free: * @arr: Array to be freed. * * Frees an array of #WockyDiscoIdentity objects created with * wocky_disco_identity_array_new() or returned by * wocky_disco_identity_array_copy(). * * Note that if this method is called with an array created with * g_ptr_array_new(), the caller should also free the array contents. * * See: wocky_disco_identity_array_new(), wocky_disco_identity_array_copy() */ void wocky_disco_identity_array_free (GPtrArray *arr) { if (arr == NULL) return; g_ptr_array_unref (arr); } /** * wocky_disco_identity_cmp: * @left: a #WockyDiscoIdentity * @right: a #WockyDiscoIdentity * * Compares @left and @right. It returns an integer less than, equal * to, or greater than zero if @left is found, respectively, to be * less than, to match, or be greater than %right. * * This function can be casted to a %GCompareFunc to sort a list of * #WockyDiscoIdentity structures. * * Returns: the result of comparing @left and @right */ gint wocky_disco_identity_cmp (WockyDiscoIdentity *left, WockyDiscoIdentity *right) { gint ret; if ((ret = strcmp (left->category, right->category)) != 0) return ret; if ((ret = strcmp (left->type, right->type)) != 0) return ret; if ((ret = strcmp (left->lang, right->lang)) != 0) return ret; return strcmp (left->name, right->name); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-heartbeat-source.c0000664000175000017500000002620612005516162026573 0ustar00cassidycassidy00000000000000/* * wocky-heartbeat-source.c: a GSource wrapping libiphb. * Copyright © 2010 Collabora Ltd. * Copyright © 2010 Nokia Corporation * @author Will Thompson * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-heartbeat-source.h" #include #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_HEARTBEAT #include "wocky-debug-internal.h" #ifdef HAVE_IPHB # include #endif typedef struct _WockyHeartbeatSource { GSource parent; #ifdef HAVE_IPHB iphb_t heartbeat; GPollFD fd; #endif guint max_interval; gint64 next_wakeup; } WockyHeartbeatSource; #if HAVE_IPHB static void wocky_heartbeat_source_degrade (WockyHeartbeatSource *self) { /* If we were using the heartbeat before, stop using it. */ if (self->heartbeat != NULL) { GSource *source = (GSource *) self; /* If this is being called from wocky_heartbeat_source_finalize(), the * source has been destroyed (which implicitly removes all polls. */ if (!g_source_is_destroyed (source)) g_source_remove_poll (source, &self->fd); DEBUG ("closing heartbeat connection"); iphb_close (self->heartbeat); self->heartbeat = NULL; } } static guint recommended_intervals[] = { IPHB_GS_WAIT_10_HOURS, IPHB_GS_WAIT_2_HOURS, IPHB_GS_WAIT_1_HOUR, IPHB_GS_WAIT_30_MINS, IPHB_GS_WAIT_10_MINS * 2, /* It aligns with the 1 hour slot. */ IPHB_GS_WAIT_10_MINS, IPHB_GS_WAIT_5_MINS, IPHB_GS_WAIT_2_5_MINS, IPHB_GS_WAIT_30_SEC}; static guint get_system_sync_interval (guint max_interval) { guint i; for (i = 0; i < G_N_ELEMENTS (recommended_intervals); i++) { if (recommended_intervals[i] <= max_interval) return recommended_intervals[i]; } return max_interval; } static void wocky_heartbeat_source_wait ( WockyHeartbeatSource *self, guint max_interval) { guint interval; int ret; if (self->heartbeat == NULL) return; if (max_interval > 0) { /* Passing the same minimum and maximum interval to iphb_wait() means * that the iphb daemon will wake us up when its internal time is a * multiple of the interval. * By using recommended intervals across the platform we can get * multiple processes waken up at the same time. */ interval = get_system_sync_interval (max_interval); DEBUG ("requested %u as maximum interval; using the recommended %u " "interval", max_interval, interval); ret = iphb_wait (self->heartbeat, interval, interval, 0); } else { ret = iphb_I_woke_up (self->heartbeat); } if (ret == -1) { DEBUG ("waiting %u failed: %s; falling back to internal timeouts", max_interval, g_strerror (errno)); wocky_heartbeat_source_degrade (self); } } #endif static gboolean wocky_heartbeat_source_prepare ( GSource *source, gint *msec_to_poll) { WockyHeartbeatSource *self = (WockyHeartbeatSource *) source; gint64 now; #if HAVE_IPHB /* If we're listening to the system heartbeat, always rely on it to wake us * up. */ if (self->heartbeat != NULL) { *msec_to_poll = -1; return FALSE; } #endif if (self->max_interval == 0) return FALSE; now = g_source_get_time (source); /* If now > self->next_wakeup, it's already time to wake up. */ if (now > self->next_wakeup) { DEBUG ("ready to wake up (at %" G_GINT64_FORMAT ")", now); return TRUE; } /* Otherwise, we should only go back to sleep for a period of * (self->next_wakeup - now). Inconveniently, g_source_get_time() gives us µs * but we need to return ms; hence the scaling. * * The value calculated here will always be positive. The difference in * seconds is non-negative; if it's zero, the difference in microseconds is * positive. */ *msec_to_poll = (self->next_wakeup - now) / 1000; return FALSE; } static gboolean wocky_heartbeat_source_check ( GSource *source) { WockyHeartbeatSource *self = (WockyHeartbeatSource *) source; gint64 now; #ifdef HAVE_IPHB if (self->heartbeat != NULL) { if ((self->fd.revents & (G_IO_ERR | G_IO_HUP)) != 0) { DEBUG ("Heartbeat closed unexpectedly: %hu; " "falling back to internal timeouts", self->fd.revents); wocky_heartbeat_source_degrade (self); return FALSE; } else if ((self->fd.revents & G_IO_IN) != 0) { DEBUG ("Heartbeat fired"); return TRUE; } else { return FALSE; } } #endif if (self->max_interval == 0) return FALSE; now = g_source_get_time (source); return (now > self->next_wakeup); } #if HAVE_IPHB static inline guint get_min_interval ( WockyHeartbeatSource *self) { /* We allow the heartbeat service to wake us up up to a minute early. */ return self->max_interval > 60 ? self->max_interval - 60 : 0; } #endif static gboolean wocky_heartbeat_source_dispatch ( GSource *source, GSourceFunc callback, gpointer user_data) { WockyHeartbeatSource *self = (WockyHeartbeatSource *) source; if (callback == NULL) { g_warning ("No callback set for WockyHeartbeatSource %p", self); return FALSE; } /* Call our callback. We don't currently allow callbacks to stop future * heartbeats from occurring: this source is used for keepalives from the * time we're connected until we disconnect. */ if (DEBUGGING) { gint64 now; now = g_source_get_time (source); DEBUG ("calling %p (%p) at %" G_GINT64_FORMAT, callback, user_data, now); } ((WockyHeartbeatCallback) callback) (user_data); #if HAVE_IPHB wocky_heartbeat_source_wait (self, self->max_interval); #endif /* Record the time we next want to wake up. */ self->next_wakeup = g_source_get_time (source); self->next_wakeup += self->max_interval * G_USEC_PER_SEC; DEBUG ("next wakeup at %" G_GINT64_FORMAT, self->next_wakeup); return TRUE; } static void wocky_heartbeat_source_finalize (GSource *source) { #ifdef HAVE_IPHB WockyHeartbeatSource *self = (WockyHeartbeatSource *) source; wocky_heartbeat_source_degrade (self); #endif } static GSourceFuncs wocky_heartbeat_source_funcs = { wocky_heartbeat_source_prepare, wocky_heartbeat_source_check, wocky_heartbeat_source_dispatch, wocky_heartbeat_source_finalize, NULL, NULL }; #if HAVE_IPHB static void connect_to_heartbeat ( WockyHeartbeatSource *self) { GSource *source = (GSource *) self; self->heartbeat = iphb_open (NULL); if (self->heartbeat == NULL) { DEBUG ("Couldn't open connection to heartbeat service: %s", g_strerror (errno)); return; } self->fd.fd = iphb_get_fd (self->heartbeat); self->fd.events = G_IO_IN | G_IO_HUP | G_IO_ERR; g_source_add_poll (source, &self->fd); wocky_heartbeat_source_wait (self, self->max_interval); } #endif /** * wocky_heartbeat_source_new: * @max_interval: the maximum interval between calls to the source's callback, * in seconds. Pass 0 to prevent the callback being called. * * Creates a source which calls its callback at least every @max_interval * seconds. This is similar to g_timeout_source_new_seconds(), except that the * callback may be called slightly earlier than requested, in sync with other * periodic network activity (from other XMPP connections, or other * applications entirely). * * When calling g_source_set_callback() on this source, the supplied callback's * signature should match #WockyHeartbeatCallback. * * Returns: the newly-created source. */ GSource * wocky_heartbeat_source_new ( guint max_interval) { GSource *source = g_source_new (&wocky_heartbeat_source_funcs, sizeof (WockyHeartbeatSource)); WockyHeartbeatSource *self = (WockyHeartbeatSource *) source; /* We can't just call wocky_heartbeat_source_update_interval() because it * assumes that we're attached to a main context. I think this is probably a * reasonable assumption. */ self->max_interval = max_interval; self->next_wakeup = g_get_monotonic_time (); self->next_wakeup += max_interval * G_USEC_PER_SEC; #if HAVE_IPHB connect_to_heartbeat (self); #endif return source; } /** * wocky_heartbeat_source_update_interval: * @source: a source returned by wocky_heartbeat_source_new() * @max_interval: the new maximum interval between calls to the source's * callback, in seconds. Pass 0 to stop the callback being * called. * * Updates the interval between calls to @source's callback. The new interval * may not take effect until after the next call to the callback. */ void wocky_heartbeat_source_update_interval ( GSource *source, guint max_interval) { WockyHeartbeatSource *self = (WockyHeartbeatSource *) source; if (self->max_interval == max_interval) return; /* If we're not using the heartbeat, the new interval takes effect * immediately. * * If we are, we just wait for the next heartbeat to fire as * normal, and then use these new values when we ask it to wait again. * (Except if the heartbeat was previously disabled, or is being disabled, in * which case we have to be sure to schedule a wakeup, or cancel the pending * wakeup, respectively.) * * We could alternatively calculate the time already elapsed since we last * called iphb_wait(), and from that calculate how much longer we want to * wait with these new values, taking care to deal with the cases where one * or both of min_interval and max_interval have already passed. But life is * too short. */ #ifdef HAVE_IPHB /* We specify 0 as the lower bound here to give us a better chance of falling * into step with other connections, which may have started waiting at * slightly different times. */ if (self->max_interval == 0 || max_interval == 0) wocky_heartbeat_source_wait (self, max_interval); #endif /* If we were previously disabled, we need to re-initialize next_wakeup, not * just update it. */ if (self->max_interval == 0) self->next_wakeup = g_source_get_time (source); /* If this moves self->next_wakeup into the past, then we'll wake up ASAP, * which is what we want. */ self->next_wakeup += (max_interval - self->max_interval) * G_USEC_PER_SEC; self->max_interval = max_interval; if (self->max_interval == 0) DEBUG ("heartbeat disabled"); else DEBUG ("next wakeup at or before %" G_GINT64_FORMAT, self->next_wakeup); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jingle-media-rtp.c0000664000175000017500000013201412212322440026453 0ustar00cassidycassidy00000000000000/* * wocky-jingle-media-rtp.c - Source for WockyJingleMediaRtp * * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* Media/RTP content type deals with audio/video content, ie. jingle calls. It * supports standard Jingle drafts (v0.15, v0.26) and Google's jingle variants * (libjingle 0.3/0.4). */ #include "config.h" #include "wocky-jingle-media-rtp.h" #include #include #include #include #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_JINGLE #include "wocky-debug-internal.h" #include "wocky-jingle-content.h" #include "wocky-jingle-factory.h" #include "wocky-jingle-session.h" #include "wocky-namespaces.h" #include "wocky-jingle-transport-google.h" #include "wocky-utils.h" G_DEFINE_TYPE (WockyJingleMediaRtp, wocky_jingle_media_rtp, WOCKY_TYPE_JINGLE_CONTENT); /* signal enum */ enum { REMOTE_MEDIA_DESCRIPTION, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; /* properties */ enum { PROP_MEDIA_TYPE = 1, PROP_REMOTE_MUTE, LAST_PROPERTY }; typedef enum { WOCKY_JINGLE_MEDIA_PROFILE_RTP_AVP, } WockyJingleMediaProfile; struct _WockyJingleMediaRtpPrivate { WockyJingleMediaDescription *local_media_description; /* Holds (WockyJingleCodec *)'s borrowed from local_media_description, * namely codecs which have changed from local_media_description's * previous value. Since the contents are borrowed, this must be * freed with g_list_free, not jingle_media_rtp_free_codecs(). */ GList *local_codec_updates; WockyJingleMediaDescription *remote_media_description; WockyJingleMediaType media_type; gboolean remote_mute; gboolean has_rtcp_fb; gboolean has_rtp_hdrext; gboolean dispose_has_run; }; static void wocky_jingle_media_rtp_init (WockyJingleMediaRtp *obj) { WockyJingleMediaRtpPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, WOCKY_TYPE_JINGLE_MEDIA_RTP, WockyJingleMediaRtpPrivate); obj->priv = priv; priv->dispose_has_run = FALSE; } /** * jingle_media_rtp_codec_new: * @id: a codec ID, as specified in tables 4 and 5 of RFC 3551. * @name: (allow-none): the codec's name. This is optional if @id is one of the * statically-defined codec identifiers, and required if @id is in the range * 96–127. (This is not enforced by this library.) * @clockrate: the clock rate for this codec, or 0 to not specify a clock rate. * @channels: the number of channels, or 0 to leave this unspecified (which the * peer should interpret as the default value, 1). * @params: (element-type utf8 utf8) (transfer none) (allow-none): parameters * for this codec. This is referenced, not copied, so you should avoid * modifying this parameter after calling this function. * * Creates a new structure describing a codec, suitable for including in a * #WockyJingleMediaDescription. * * Returns: (transfer full): the codec description. */ WockyJingleCodec * jingle_media_rtp_codec_new ( guint id, const gchar *name, guint clockrate, guint channels, GHashTable *params) { WockyJingleCodec *p = g_slice_new0 (WockyJingleCodec); p->id = id; p->name = g_strdup (name); p->clockrate = clockrate; p->channels = channels; p->trr_int = G_MAXUINT; if (params != NULL) { g_hash_table_ref (params); p->params = params; } else { p->params = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); } return p; } static GList * wocky_jingle_feedback_message_list_copy (GList *fbs) { GQueue new = G_QUEUE_INIT; GList *li; for (li = fbs; li; li = li->next) { WockyJingleFeedbackMessage *fb = li->data; g_queue_push_tail (&new, wocky_jingle_feedback_message_new (fb->type, fb->subtype)); } return new.head; } static void wocky_jingle_feedback_message_list_free (GList *fbs) { while (fbs != NULL) { wocky_jingle_feedback_message_free (fbs->data); fbs = g_list_delete_link (fbs, fbs); } } void jingle_media_rtp_codec_free (WockyJingleCodec *p) { g_hash_table_unref (p->params); g_free (p->name); wocky_jingle_feedback_message_list_free (p->feedback_msgs); g_slice_free (WockyJingleCodec, p); } static void add_codec_to_table (WockyJingleCodec *codec, GHashTable *table) { g_hash_table_insert (table, GUINT_TO_POINTER ((guint) codec->id), codec); } static GHashTable * build_codec_table (GList *codecs) { GHashTable *table = g_hash_table_new (NULL, NULL); g_list_foreach (codecs, (GFunc) add_codec_to_table, table); return table; } GList * jingle_media_rtp_copy_codecs (GList *codecs) { GList *ret = NULL, *l; for (l = codecs; l != NULL; l = g_list_next (l)) { WockyJingleCodec *c = l->data; WockyJingleCodec *newc = jingle_media_rtp_codec_new (c->id, c->name, c->clockrate, c->channels, c->params); newc->trr_int = c->trr_int; ret = g_list_append (ret, newc); } return ret; } void jingle_media_rtp_free_codecs (GList *codecs) { while (codecs != NULL) { jingle_media_rtp_codec_free (codecs->data); codecs = g_list_delete_link (codecs, codecs); } } static void wocky_jingle_media_rtp_dispose (GObject *object) { WockyJingleMediaRtp *trans = WOCKY_JINGLE_MEDIA_RTP (object); WockyJingleMediaRtpPrivate *priv = trans->priv; if (priv->dispose_has_run) return; DEBUG ("dispose called"); priv->dispose_has_run = TRUE; if (priv->remote_media_description != NULL) wocky_jingle_media_description_free (priv->remote_media_description); priv->remote_media_description = NULL; if (priv->local_media_description != NULL) wocky_jingle_media_description_free (priv->local_media_description); priv->local_media_description = NULL; if (priv->local_codec_updates != NULL) { DEBUG ("We have an unsent codec parameter update! Weird."); g_list_free (priv->local_codec_updates); priv->local_codec_updates = NULL; } if (G_OBJECT_CLASS (wocky_jingle_media_rtp_parent_class)->dispose) G_OBJECT_CLASS (wocky_jingle_media_rtp_parent_class)->dispose (object); } static void wocky_jingle_media_rtp_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyJingleMediaRtp *trans = WOCKY_JINGLE_MEDIA_RTP (object); WockyJingleMediaRtpPrivate *priv = trans->priv; switch (property_id) { case PROP_MEDIA_TYPE: g_value_set_uint (value, priv->media_type); break; case PROP_REMOTE_MUTE: g_value_set_boolean (value, priv->remote_mute); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_jingle_media_rtp_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyJingleMediaRtp *trans = WOCKY_JINGLE_MEDIA_RTP (object); WockyJingleMediaRtpPrivate *priv = trans->priv; switch (property_id) { case PROP_MEDIA_TYPE: priv->media_type = g_value_get_uint (value); break; case PROP_REMOTE_MUTE: priv->remote_mute = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void parse_description (WockyJingleContent *content, WockyNode *desc_node, GError **error); static void produce_description (WockyJingleContent *obj, WockyNode *content_node); static void transport_created (WockyJingleContent *obj, WockyJingleTransportIface *transport); static void wocky_jingle_media_rtp_class_init (WockyJingleMediaRtpClass *cls) { GObjectClass *object_class = G_OBJECT_CLASS (cls); WockyJingleContentClass *content_class = WOCKY_JINGLE_CONTENT_CLASS (cls); GParamSpec *param_spec; g_type_class_add_private (cls, sizeof (WockyJingleMediaRtpPrivate)); object_class->get_property = wocky_jingle_media_rtp_get_property; object_class->set_property = wocky_jingle_media_rtp_set_property; object_class->dispose = wocky_jingle_media_rtp_dispose; content_class->parse_description = parse_description; content_class->produce_description = produce_description; content_class->transport_created = transport_created; param_spec = g_param_spec_uint ("media-type", "RTP media type", "Media type.", WOCKY_JINGLE_MEDIA_TYPE_NONE, G_MAXUINT32, WOCKY_JINGLE_MEDIA_TYPE_NONE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_MEDIA_TYPE, param_spec); param_spec = g_param_spec_boolean ("remote-mute", "Remote mute", "TRUE if the peer has muted this stream", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_REMOTE_MUTE, param_spec); /* signal definitions */ /** * WockyJingleMediaRtp::remote-media-description: * @content: the RTP content * @md: a #WockyJingleMediaDescription * * Emitted when the remote media description is received or subsequently updated. */ signals[REMOTE_MEDIA_DESCRIPTION] = g_signal_new ("remote-media-description", G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); } static void transport_created (WockyJingleContent *content, WockyJingleTransportIface *transport) { WockyJingleMediaRtp *self = WOCKY_JINGLE_MEDIA_RTP (content); WockyJingleMediaRtpPrivate *priv = self->priv; WockyJingleTransportGoogle *gtrans = NULL; WockyJingleDialect dialect; if (WOCKY_IS_JINGLE_TRANSPORT_GOOGLE (transport)) { gtrans = WOCKY_JINGLE_TRANSPORT_GOOGLE (transport); dialect = wocky_jingle_session_get_dialect (content->session); if (priv->media_type == WOCKY_JINGLE_MEDIA_TYPE_VIDEO && (WOCKY_JINGLE_DIALECT_IS_GOOGLE (dialect) || wocky_jingle_session_peer_has_cap (content->session, WOCKY_QUIRK_GOOGLE_WEBMAIL_CLIENT) || wocky_jingle_session_peer_has_cap (content->session, WOCKY_QUIRK_ANDROID_GTALK_CLIENT))) { jingle_transport_google_set_component_name (gtrans, "video_rtp", 1); jingle_transport_google_set_component_name (gtrans, "video_rtcp", 2); } else { jingle_transport_google_set_component_name (gtrans, "rtp", 1); jingle_transport_google_set_component_name (gtrans, "rtcp", 2); } } } static WockyJingleMediaType extract_media_type (WockyNode *desc_node, GError **error) { if (wocky_node_has_ns (desc_node, WOCKY_XMPP_NS_JINGLE_RTP)) { const gchar *type = wocky_node_get_attribute (desc_node, "media"); if (type == NULL) { g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, "missing required media type attribute"); return WOCKY_JINGLE_MEDIA_TYPE_NONE; } if (!wocky_strdiff (type, "audio")) return WOCKY_JINGLE_MEDIA_TYPE_AUDIO; if (!wocky_strdiff (type, "video")) return WOCKY_JINGLE_MEDIA_TYPE_VIDEO; g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, "unknown media type %s", type); return WOCKY_JINGLE_MEDIA_TYPE_NONE; } if (wocky_node_has_ns (desc_node, WOCKY_XMPP_NS_JINGLE_DESCRIPTION_AUDIO)) return WOCKY_JINGLE_MEDIA_TYPE_AUDIO; if (wocky_node_has_ns (desc_node, WOCKY_XMPP_NS_JINGLE_DESCRIPTION_VIDEO)) return WOCKY_JINGLE_MEDIA_TYPE_VIDEO; if (wocky_node_has_ns (desc_node, WOCKY_XMPP_NS_GOOGLE_SESSION_PHONE)) return WOCKY_JINGLE_MEDIA_TYPE_AUDIO; if (wocky_node_has_ns (desc_node, WOCKY_XMPP_NS_GOOGLE_SESSION_VIDEO)) return WOCKY_JINGLE_MEDIA_TYPE_VIDEO; /* If we get here, namespace in use is not one of namespaces we signed up * with, so obviously a bug somewhere. */ g_assert_not_reached (); } static WockyJingleFeedbackMessage * parse_rtcp_fb (WockyJingleContent *content, WockyNode *node) { const gchar *pt_ns = wocky_node_get_ns (node); const gchar *type; const gchar *subtype; if (wocky_strdiff (pt_ns, WOCKY_XMPP_NS_JINGLE_RTCP_FB)) return NULL; type = wocky_node_get_attribute (node, "type"); if (type == NULL) return NULL; subtype = wocky_node_get_attribute (node, "subtype"); /* This is optional, defaults to "" */ if (subtype == NULL) subtype = ""; return wocky_jingle_feedback_message_new (type, subtype); } /* * Returns G_MAXUINT on error */ static guint parse_rtcp_fb_trr_int (WockyJingleContent *content, WockyNode *node) { const gchar *pt_ns = wocky_node_get_ns (node); const gchar *txt; guint trr_int; gchar *endptr = NULL; if (wocky_strdiff (pt_ns, WOCKY_XMPP_NS_JINGLE_RTCP_FB)) return G_MAXUINT; txt = wocky_node_get_attribute (node, "value"); if (txt == NULL) return G_MAXUINT; trr_int = strtol (txt, &endptr, 10); if (endptr == NULL || endptr == txt) return G_MAXUINT; return trr_int; } /** * parse_payload_type: * @node: a node. * * Returns: a newly-allocated WockyJingleCodec if parsing succeeds, or %NULL * otherwise. */ static WockyJingleCodec * parse_payload_type (WockyJingleContent *content, WockyNode *node) { WockyJingleMediaRtp *self = WOCKY_JINGLE_MEDIA_RTP (content); WockyJingleMediaRtpPrivate *priv = self->priv; WockyJingleCodec *p; const char *txt; guint8 id; const gchar *name; guint clockrate = 0; guint channels = 0; WockyNode *param; WockyNodeIter i; txt = wocky_node_get_attribute (node, "id"); if (txt == NULL) return NULL; id = atoi (txt); name = wocky_node_get_attribute (node, "name"); if (name == NULL) name = ""; /* xep-0167 v0.22, gtalk libjingle 0.3/0.4 use "clockrate" */ txt = wocky_node_get_attribute (node, "clockrate"); /* older jingle rtp used "rate" ? */ if (txt == NULL) txt = wocky_node_get_attribute (node, "rate"); if (txt != NULL) clockrate = atoi (txt); txt = wocky_node_get_attribute (node, "channels"); if (txt != NULL) channels = atoi (txt); p = jingle_media_rtp_codec_new (id, name, clockrate, channels, NULL); wocky_node_iter_init (&i, node, NULL, NULL); while (wocky_node_iter_next (&i, ¶m)) { if (!wocky_strdiff (param->name, "parameter")) { const gchar *param_name, *param_value; param_name = wocky_node_get_attribute (param, "name"); param_value = wocky_node_get_attribute (param, "value"); if (param_name == NULL || param_value == NULL) continue; g_hash_table_insert (p->params, g_strdup (param_name), g_strdup (param_value)); } else if (!wocky_strdiff (param->name, "rtcp-fb")) { WockyJingleFeedbackMessage *fb = parse_rtcp_fb (content, param); if (fb != NULL) { p->feedback_msgs = g_list_append (p->feedback_msgs, fb); priv->has_rtcp_fb = TRUE; } } else if (!wocky_strdiff (param->name, "rtcp-fb-trr-int")) { guint trr_int = parse_rtcp_fb_trr_int (content, param); if (trr_int != G_MAXUINT) { p->trr_int = trr_int; priv->has_rtcp_fb = TRUE; } } } DEBUG ("new remote codec: id = %u, name = %s, clockrate = %u, channels = %u", p->id, p->name, p->clockrate, p->channels); return p; } static WockyJingleRtpHeaderExtension * parse_rtp_header_extension (WockyNode *node) { guint id; WockyJingleContentSenders senders; const gchar *uri; const char *txt; txt = wocky_node_get_attribute (node, "id"); if (txt == NULL) return NULL; id = atoi (txt); /* Only valid ranges are 1-256 and 4096-4351 */ if ((id < 1 || id > 256) && (id < 4096 || id > 4351)) return NULL; txt = wocky_node_get_attribute (node, "senders"); if (txt == NULL || !g_ascii_strcasecmp (txt, "both")) senders = WOCKY_JINGLE_CONTENT_SENDERS_BOTH; else if (!g_ascii_strcasecmp (txt, "initiator")) senders = WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR; else if (!g_ascii_strcasecmp (txt, "responder")) senders = WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER; else return NULL; uri = wocky_node_get_attribute (node, "uri"); if (uri == NULL) return NULL; return wocky_jingle_rtp_header_extension_new (id, senders, uri); } /** * codec_update_coherent: * @old_c: this content's old cache of the codec, or %NULL if it hasn't heard * of it. * @new_c: the proposed update, whose id must equal that of @old_c if the * latter is non-NULL. * @domain: the error domain to set @e to if necessary * @code: the error code to set @e to if necessary * @e: location to hold an error * * Compares @old_c and @new_c, which are assumed to have the same id, to check * that the name, clockrate and number of channels hasn't changed. If they * have, returns %FALSE and sets @e. */ static gboolean codec_update_coherent (const WockyJingleCodec *old_c, const WockyJingleCodec *new_c, GError **e) { const GQuark domain = WOCKY_XMPP_ERROR; const gint code = WOCKY_XMPP_ERROR_BAD_REQUEST; if (old_c == NULL) { g_set_error (e, domain, code, "Codec with id %u ('%s') unknown", new_c->id, new_c->name); return FALSE; } if (g_ascii_strcasecmp (new_c->name, old_c->name)) { g_set_error (e, domain, code, "tried to change codec %u's name from %s to %s", new_c->id, old_c->name, new_c->name); return FALSE; } if (new_c->clockrate != old_c->clockrate) { g_set_error (e, domain, code, "tried to change codec %u (%s)'s clockrate from %u to %u", new_c->id, new_c->name, old_c->clockrate, new_c->clockrate); return FALSE; } if (old_c->channels != 0 && new_c->channels != old_c->channels) { g_set_error (e, domain, code, "tried to change codec %u (%s)'s channels from %u to %u", new_c->id, new_c->name, new_c->channels, old_c->channels); return FALSE; } return TRUE; } static void update_remote_media_description (WockyJingleMediaRtp *self, WockyJingleMediaDescription *new_media_description, GError **error) { WockyJingleMediaRtpPrivate *priv = self->priv; GHashTable *rc = NULL; WockyJingleCodec *old_c, *new_c; GList *l; GError *e = NULL; if (priv->remote_media_description == NULL) { priv->remote_media_description = new_media_description; new_media_description = NULL; goto out; } rc = build_codec_table (priv->remote_media_description->codecs); /* We already know some remote codecs, so this is just the other end updating * some parameters. */ for (l = new_media_description->codecs; l != NULL; l = l->next) { new_c = l->data; old_c = g_hash_table_lookup (rc, GUINT_TO_POINTER ((guint) new_c->id)); if (!codec_update_coherent (old_c, new_c, &e)) goto out; } /* Okay, all the updates are cool. Let's switch the parameters around. */ for (l = new_media_description->codecs; l != NULL; l = l->next) { GHashTable *params; new_c = l->data; old_c = g_hash_table_lookup (rc, GUINT_TO_POINTER ((guint) new_c->id)); params = old_c->params; old_c->params = new_c->params; new_c->params = params; } out: if (new_media_description != NULL) wocky_jingle_media_description_free (new_media_description); if (rc != NULL) g_hash_table_unref (rc); if (e != NULL) { DEBUG ("Rejecting codec update: %s", e->message); g_propagate_error (error, e); } else { DEBUG ("Emitting remote-media-description signal"); g_signal_emit (self, signals[REMOTE_MEDIA_DESCRIPTION], 0, priv->remote_media_description); } } static void parse_description (WockyJingleContent *content, WockyNode *desc_node, GError **error) { WockyJingleMediaRtp *self = WOCKY_JINGLE_MEDIA_RTP (content); WockyJingleMediaRtpPrivate *priv = self->priv; WockyJingleMediaType mtype; WockyJingleMediaDescription *md; WockyJingleCodec *p; WockyJingleDialect dialect = wocky_jingle_session_get_dialect (content->session); gboolean video_session = FALSE; WockyNodeIter i; WockyNode *node; gboolean description_error = FALSE; gboolean is_avpf = FALSE; DEBUG ("node: %s", desc_node->name); if (priv->media_type == WOCKY_JINGLE_MEDIA_TYPE_NONE) mtype = extract_media_type (desc_node, error); else mtype = priv->media_type; if (mtype == WOCKY_JINGLE_MEDIA_TYPE_NONE) return; DEBUG ("detected media type %u", mtype); if (dialect == WOCKY_JINGLE_DIALECT_GTALK3) { const gchar *desc_ns = wocky_node_get_ns (desc_node); video_session = !wocky_strdiff (desc_ns, WOCKY_XMPP_NS_GOOGLE_SESSION_VIDEO); } md = wocky_jingle_media_description_new (); wocky_node_iter_init (&i, desc_node, NULL, NULL); while (wocky_node_iter_next (&i, &node) && !description_error) { if (!wocky_strdiff (node->name, "payload-type")) { if (dialect == WOCKY_JINGLE_DIALECT_GTALK3) { const gchar *pt_ns = wocky_node_get_ns (node); if (priv->media_type == WOCKY_JINGLE_MEDIA_TYPE_AUDIO) { if (video_session && wocky_strdiff (pt_ns, WOCKY_XMPP_NS_GOOGLE_SESSION_PHONE)) continue; } else if (priv->media_type == WOCKY_JINGLE_MEDIA_TYPE_VIDEO) { if (!(video_session && pt_ns == NULL) && wocky_strdiff (pt_ns, WOCKY_XMPP_NS_GOOGLE_SESSION_VIDEO)) continue; } } p = parse_payload_type (content, node); if (p == NULL) { description_error = TRUE; } else { md->codecs = g_list_append (md->codecs, p); if (p->trr_int != G_MAXUINT || p->feedback_msgs) is_avpf = TRUE; } } else if (!wocky_strdiff (node->name, "rtp-hdrext")) { const gchar *pt_ns = wocky_node_get_ns (node); WockyJingleRtpHeaderExtension *hdrext; if (wocky_strdiff (pt_ns, WOCKY_XMPP_NS_JINGLE_RTP_HDREXT)) continue; hdrext = parse_rtp_header_extension (node); if (hdrext == NULL) { description_error = TRUE; } else { md->hdrexts = g_list_append (md->hdrexts, hdrext); priv->has_rtp_hdrext = TRUE; } } else if (!wocky_strdiff (node->name, "rtcp-fb")) { WockyJingleFeedbackMessage *fb = parse_rtcp_fb (content, node); if (fb == NULL) { description_error = TRUE; } else { md->feedback_msgs = g_list_append (md->feedback_msgs, fb); is_avpf = TRUE; priv->has_rtcp_fb = TRUE; } } else if (!wocky_strdiff (node->name, "rtcp-fb-trr-int")) { guint trr_int = parse_rtcp_fb_trr_int (content, node); if (trr_int == G_MAXUINT) { description_error = TRUE; } else { md->trr_int = trr_int; is_avpf = TRUE; priv->has_rtcp_fb = TRUE; } } } if (description_error) { /* rollback these */ wocky_jingle_media_description_free (md); g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, "invalid description"); return; } /* If the profile is AVPF, the trr-int default to 0 */ if (is_avpf && md->trr_int == G_MAXUINT) md->trr_int = 0; priv->media_type = mtype; update_remote_media_description (self, md, error); } /* The Google Talk desktop client is picky about the case of codec names, even * though SDP defines them to be case-insensitive. The particular case that was * causing problems was ILBC vs iLBC, but it seems safer to special-case the * lot. This list is taken from the initiate sent by the desktop client on * 2009-07-01. */ static const gchar * const codec_cases[] = { "CN", "EG711A", "EG711U", "G723", "IPCMWB", "ISAC", "PCMA", "PCMU", "iLBC", "speex", "telephone-event", NULL }; static const gchar * gtalk_case (const gchar *codec) { const gchar * const *ret = codec_cases; for (; *ret != NULL; ret++) if (g_ascii_strcasecmp (*ret, codec) == 0) return *ret; return codec; } static void _produce_extra_param (gpointer key, gpointer value, gpointer user_data) { WockyNode *pt_node = user_data; WockyNode *param; gchar *param_name = key; gchar *param_value = value; param = wocky_node_add_child (pt_node, "parameter"); wocky_node_set_attribute (param, "name", param_name); wocky_node_set_attribute (param, "value", param_value); } static void produce_rtcp_fb_trr_int (WockyNode *node, guint trr_int) { WockyNode *trr_int_node; gchar tmp[10]; if (trr_int == G_MAXUINT || trr_int == 0) return; trr_int_node = wocky_node_add_child_ns (node, "rtcp-fb-trr-int", WOCKY_XMPP_NS_JINGLE_RTCP_FB); snprintf (tmp, 9, "%d", trr_int); wocky_node_set_attribute (trr_int_node, "value", tmp); } static void produce_rtcp_fb (WockyJingleFeedbackMessage *fb, WockyNode *node) { WockyNode *fb_node; fb_node = wocky_node_add_child (node, "rtcp-fb"); wocky_node_set_attribute (fb_node, "xmlns", WOCKY_XMPP_NS_JINGLE_RTCP_FB); wocky_node_set_attribute (fb_node, "type", fb->type); if (fb->subtype != NULL && fb->subtype[0] != 0) wocky_node_set_attribute (fb_node, "subtype", fb->subtype); } static void produce_payload_type (WockyJingleContent *content, WockyNode *desc_node, WockyJingleMediaType type, WockyJingleCodec *p, WockyJingleDialect dialect) { WockyJingleMediaRtp *self = WOCKY_JINGLE_MEDIA_RTP (content); WockyJingleMediaRtpPrivate *priv = self->priv; WockyNode *pt_node; gchar buf[16]; pt_node = wocky_node_add_child (desc_node, "payload-type"); /* id: required */ sprintf (buf, "%d", p->id); wocky_node_set_attribute (pt_node, "id", buf); if (dialect == WOCKY_JINGLE_DIALECT_GTALK3) { if (type == WOCKY_JINGLE_MEDIA_TYPE_AUDIO) { /* Gtalk 03 has either an audio or a video session, in case of a * video session the audio codecs need to set their namespace to * WOCKY_XMPP_NS_GOOGLE_SESSION_PHONE. In the case of an audio session it * doesn't matter, so just always set the namespace on audio * payloads. */ pt_node->ns = g_quark_from_static_string ( WOCKY_XMPP_NS_GOOGLE_SESSION_PHONE); } else { /* If width, height and framerate aren't set the google server ignore * our initiate.. These are a recv parameters, to it doesn't matter * for what we're sending, just for what we're getting.. 320x240 * seems a sane enough default */ wocky_node_set_attributes (pt_node, "width", "320", "height", "240", "framerate", "30", NULL); } } /* name: optional */ if (*p->name != '\0') { if (WOCKY_JINGLE_DIALECT_IS_GOOGLE (dialect)) wocky_node_set_attribute (pt_node, "name", gtalk_case (p->name)); else wocky_node_set_attribute (pt_node, "name", p->name); } /* clock rate: optional */ if (p->clockrate != 0) { const gchar *attname = "clockrate"; if (dialect == WOCKY_JINGLE_DIALECT_V015) attname = "rate"; sprintf (buf, "%u", p->clockrate); wocky_node_set_attribute (pt_node, attname, buf); } if (p->channels != 0) { sprintf (buf, "%u", p->channels); wocky_node_set_attribute (pt_node, "channels", buf); } if (p->params != NULL) g_hash_table_foreach (p->params, _produce_extra_param, pt_node); if (priv->has_rtcp_fb) { g_list_foreach (p->feedback_msgs, (GFunc) produce_rtcp_fb, pt_node); produce_rtcp_fb_trr_int (pt_node, p->trr_int); } } static WockyNode * produce_description_node (WockyJingleDialect dialect, WockyJingleMediaType media_type, WockyNode *content_node) { WockyNode *desc_node; const gchar *xmlns = NULL, *media_attr = NULL; if (dialect == WOCKY_JINGLE_DIALECT_GTALK3) return NULL; switch (dialect) { case WOCKY_JINGLE_DIALECT_GTALK4: g_assert (media_type == WOCKY_JINGLE_MEDIA_TYPE_AUDIO); xmlns = WOCKY_XMPP_NS_GOOGLE_SESSION_PHONE; break; case WOCKY_JINGLE_DIALECT_V015: if (media_type == WOCKY_JINGLE_MEDIA_TYPE_AUDIO) xmlns = WOCKY_XMPP_NS_JINGLE_DESCRIPTION_AUDIO; else if (media_type == WOCKY_JINGLE_MEDIA_TYPE_VIDEO) xmlns = WOCKY_XMPP_NS_JINGLE_DESCRIPTION_VIDEO; else { DEBUG ("unknown media type %u", media_type); xmlns = ""; } break; default: xmlns = WOCKY_XMPP_NS_JINGLE_RTP; if (media_type == WOCKY_JINGLE_MEDIA_TYPE_AUDIO) media_attr = "audio"; else if (media_type == WOCKY_JINGLE_MEDIA_TYPE_VIDEO) media_attr = "video"; else g_assert_not_reached (); break; } desc_node = wocky_node_add_child_ns (content_node, "description", xmlns); if (media_attr != NULL) wocky_node_set_attribute (desc_node, "media", media_attr); return desc_node; } static void produce_hdrext (gpointer data, gpointer user_data) { WockyJingleRtpHeaderExtension *hdrext = data; WockyNode *desc_node = user_data; WockyNode *hdrext_node; gchar buf[16]; hdrext_node = wocky_node_add_child (desc_node, "rtp-hdrext"); /* id: required */ sprintf (buf, "%d", hdrext->id); wocky_node_set_attribute (hdrext_node, "id", buf); wocky_node_set_attribute (hdrext_node, "uri", hdrext->uri); if (hdrext->senders == WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR) wocky_node_set_attribute (hdrext_node, "senders", "initiator"); else if (hdrext->senders == WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER) wocky_node_set_attribute (hdrext_node, "senders", "responder"); wocky_node_set_attribute (hdrext_node, "xmlns", WOCKY_XMPP_NS_JINGLE_RTP_HDREXT); } static void produce_description (WockyJingleContent *content, WockyNode *content_node) { WockyJingleMediaRtp *self = WOCKY_JINGLE_MEDIA_RTP (content); WockyJingleMediaRtpPrivate *priv = self->priv; GList *li; WockyJingleDialect dialect = wocky_jingle_session_get_dialect (content->session); WockyNode *desc_node; if (wocky_jingle_session_peer_has_cap (content->session, WOCKY_XMPP_NS_JINGLE_RTCP_FB)) priv->has_rtcp_fb = TRUE; if (wocky_jingle_session_peer_has_cap (content->session, WOCKY_XMPP_NS_JINGLE_RTP_HDREXT)) priv->has_rtp_hdrext = TRUE; desc_node = produce_description_node (dialect, priv->media_type, content_node); /* For GTalk3 the description is added by the session */ if (desc_node == NULL) desc_node = content_node; /* If we're only updating our codec parameters, only generate payload-types * for those. */ if (priv->local_codec_updates != NULL) li = priv->local_codec_updates; else li = priv->local_media_description->codecs; for (; li != NULL; li = li->next) produce_payload_type (content, desc_node, priv->media_type, li->data, dialect); if (priv->has_rtp_hdrext && priv->local_media_description->hdrexts) g_list_foreach (priv->local_media_description->hdrexts, produce_hdrext, desc_node); if (priv->has_rtcp_fb) { g_list_foreach (priv->local_media_description->feedback_msgs, (GFunc) produce_rtcp_fb, desc_node); produce_rtcp_fb_trr_int (desc_node, priv->local_media_description->trr_int); } } /** * string_string_maps_equal: * * Returns: TRUE iff @a and @b contain exactly the same keys and values when * compared as strings. */ static gboolean string_string_maps_equal (GHashTable *a, GHashTable *b) { GHashTableIter iter; gpointer a_key, a_value, b_value; if (g_hash_table_size (a) != g_hash_table_size (b)) return FALSE; g_hash_table_iter_init (&iter, a); while (g_hash_table_iter_next (&iter, &a_key, &a_value)) { if (!g_hash_table_lookup_extended (b, a_key, NULL, &b_value)) return FALSE; if (wocky_strdiff (a_value, b_value)) return FALSE; } return TRUE; } /** * compare_codecs: * @old: previous local codecs * @new: new local codecs supplied by streaming implementation * @changed: location at which to store the changed codecs * @error: location at which to store an error if the update was invalid * * Returns: %TRUE if the update made sense, %FALSE with @error set otherwise */ gboolean jingle_media_rtp_compare_codecs (GList *old, GList *new, GList **changed, GError **e) { gboolean ret = FALSE; GHashTable *old_table = build_codec_table (old); GList *l; WockyJingleCodec *old_c, *new_c; g_assert (changed != NULL && *changed == NULL); for (l = new; l != NULL; l = l->next) { new_c = l->data; old_c = g_hash_table_lookup (old_table, GUINT_TO_POINTER ( (guint) new_c->id)); if (!codec_update_coherent (old_c, new_c, e)) goto out; if (!string_string_maps_equal (old_c->params, new_c->params)) *changed = g_list_prepend (*changed, new_c); } ret = TRUE; out: if (!ret) { g_list_free (*changed); *changed = NULL; } g_hash_table_unref (old_table); return ret; } /** * jingle_media_rtp_set_local_media_description: * @self: a content in an RTP session * @md: (transfer full): new media description for this content * @ready: whether the codecs can regarded as ready to sent from now on * @error: used to return a %WOCKY_XMPP_ERROR if the codec update is illegal. * * Sets or updates the media description (codecs, feedback messages, etc) for * @self. * * Returns: %TRUE if no description was previously set, or if the update is * compatible with the existing description; %FALSE if the update is illegal * (due to adding previously-unknown codecs or renaming an existing codec, for * example) */ gboolean jingle_media_rtp_set_local_media_description (WockyJingleMediaRtp *self, WockyJingleMediaDescription *md, gboolean ready, GError **error) { WockyJingleMediaRtpPrivate *priv = self->priv; DEBUG ("setting new local media description"); if (priv->local_media_description != NULL) { GList *changed = NULL; GError *err = NULL; g_assert (priv->local_codec_updates == NULL); if (!jingle_media_rtp_compare_codecs ( priv->local_media_description->codecs, md->codecs, &changed, &err)) { DEBUG ("codec update was illegal: %s", err->message); wocky_jingle_media_description_free (md); g_propagate_error (error, err); return FALSE; } if (changed == NULL) { DEBUG ("codec update changed nothing!"); wocky_jingle_media_description_free (md); goto out; } DEBUG ("%u codecs changed", g_list_length (changed)); priv->local_codec_updates = changed; wocky_jingle_media_description_free (priv->local_media_description); } priv->local_media_description = md; /* Codecs have changed, sending a fresh description might be necessary */ wocky_jingle_content_maybe_send_description (WOCKY_JINGLE_CONTENT (self)); /* Update done if any, free the changed codecs if any */ g_list_free (priv->local_codec_updates); priv->local_codec_updates = NULL; out: if (ready) _wocky_jingle_content_set_media_ready (WOCKY_JINGLE_CONTENT (self)); return TRUE; } void jingle_media_rtp_register (WockyJingleFactory *factory) { /* Current (v0.25) Jingle draft URI */ wocky_jingle_factory_register_content_type (factory, WOCKY_XMPP_NS_JINGLE_RTP, WOCKY_TYPE_JINGLE_MEDIA_RTP); /* Old Jingle audio/video namespaces */ wocky_jingle_factory_register_content_type (factory, WOCKY_XMPP_NS_JINGLE_DESCRIPTION_AUDIO, WOCKY_TYPE_JINGLE_MEDIA_RTP); wocky_jingle_factory_register_content_type (factory, WOCKY_XMPP_NS_JINGLE_DESCRIPTION_VIDEO, WOCKY_TYPE_JINGLE_MEDIA_RTP); /* GTalk audio call namespace */ wocky_jingle_factory_register_content_type (factory, WOCKY_XMPP_NS_GOOGLE_SESSION_PHONE, WOCKY_TYPE_JINGLE_MEDIA_RTP); /* GTalk video call namespace */ wocky_jingle_factory_register_content_type (factory, WOCKY_XMPP_NS_GOOGLE_SESSION_VIDEO, WOCKY_TYPE_JINGLE_MEDIA_RTP); } /* We can't get remote media description when they're signalled, because * the signal is emitted immediately upon JingleContent creation, * and parsing, which is before a corresponding MediaStream is * created. */ /** * wocky_jingle_media_rtp_get_remote_media_description: * @self : the RTP content * * Gets the current remote media description, if known. The * #WockyJingleMediaRtp:remote-media-description signal is emitted when this * value changes. * * Returns: (transfer none): the current remote media description, which may be * %NULL for outgoing calls until it is first received. */ WockyJingleMediaDescription * wocky_jingle_media_rtp_get_remote_media_description ( WockyJingleMediaRtp *self) { WockyJingleMediaRtpPrivate *priv = self->priv; return priv->remote_media_description; } /** * WockyJingleMediaDescription: * @codecs: a list of #WockyJingleCodecs, allocated with * jingle_media_rtp_codec_new() * @hdrexts: a list of #WockyJingleRtpHeaderExtensions, allocated with * wocky_jingle_rtp_header_extension_new() * @trr_int: number of milliseconds between regular RTCP reports * @feedback_msgs: a list of #WockyJingleFeedbackMessages, allocated * with wocky_jingle_feedback_message_new() * * Media description for a #WockyJingleMediaRtp content. */ /** * wocky_jingle_media_description_new: * * Allocates a new media description. You should fill in all the fields yourself. * * Returns: a new, empty, media description */ WockyJingleMediaDescription * wocky_jingle_media_description_new (void) { WockyJingleMediaDescription *md = g_slice_new0 (WockyJingleMediaDescription); md->trr_int = G_MAXUINT; return md; } void wocky_jingle_media_description_free (WockyJingleMediaDescription *md) { jingle_media_rtp_free_codecs (md->codecs); while (md->hdrexts != NULL) { wocky_jingle_rtp_header_extension_free (md->hdrexts->data); md->hdrexts = g_list_delete_link (md->hdrexts, md->hdrexts); } g_slice_free (WockyJingleMediaDescription, md); } /** * wocky_jingle_media_description_copy: * @md: a media description * * Performs a deep copy of a media description. * * Returns: (transfer full): a deep copy of @md */ WockyJingleMediaDescription * wocky_jingle_media_description_copy (WockyJingleMediaDescription *md) { WockyJingleMediaDescription *newmd = g_slice_new0 (WockyJingleMediaDescription); GList *li; newmd->codecs = jingle_media_rtp_copy_codecs (md->codecs); newmd->feedback_msgs = wocky_jingle_feedback_message_list_copy (md->feedback_msgs); newmd->trr_int = md->trr_int; for (li = md->hdrexts; li; li = li->next) { WockyJingleRtpHeaderExtension *h = li->data; newmd->hdrexts = g_list_append (newmd->hdrexts, wocky_jingle_rtp_header_extension_new (h->id, h->senders, h->uri)); } return newmd; } WockyJingleRtpHeaderExtension * wocky_jingle_rtp_header_extension_new (guint id, WockyJingleContentSenders senders, const gchar *uri) { WockyJingleRtpHeaderExtension *hdrext = g_slice_new (WockyJingleRtpHeaderExtension); hdrext->id = id; hdrext->senders = senders; hdrext->uri = g_strdup (uri); return hdrext; } void wocky_jingle_rtp_header_extension_free (WockyJingleRtpHeaderExtension *hdrext) { g_free (hdrext->uri); g_slice_free (WockyJingleRtpHeaderExtension, hdrext); } WockyJingleFeedbackMessage * wocky_jingle_feedback_message_new (const gchar *type, const gchar *subtype) { WockyJingleFeedbackMessage *fb = g_slice_new0 (WockyJingleFeedbackMessage); fb->type = g_strdup (type); fb->subtype = g_strdup (subtype); return fb; } void wocky_jingle_feedback_message_free (WockyJingleFeedbackMessage *fb) { g_free (fb->type); g_free (fb->subtype); g_slice_free (WockyJingleFeedbackMessage, fb); } static gint wocky_jingle_feedback_message_compare (const WockyJingleFeedbackMessage *fb1, const WockyJingleFeedbackMessage *fb2) { if (!g_ascii_strcasecmp (fb1->type, fb2->type) && !g_ascii_strcasecmp (fb1->subtype, fb2->subtype)) return 0; else return 1; } /** * wocky_jingle_media_description_simplify: * @md: a description to simplify * * Removes duplicated Feedback message and put them in the global structure * * This function will iterate over every codec in a description and look for * feedback messages that are exactly the same in every codec and will instead * put the in the list in the description and remove them from the childs. * This limits the amount of duplication in the resulting XML. */ void wocky_jingle_media_description_simplify (WockyJingleMediaDescription *md) { GList *item; guint trr_int = 0; gboolean trr_int_all_same = TRUE; gboolean init = FALSE; GList *identical_fbs = NULL; for (item = md->codecs; item; item = item->next) { WockyJingleCodec *c = item->data; if (!init) { /* For the first codec, it stores the trr_int and the list * of feedback messages */ trr_int = c->trr_int; identical_fbs = g_list_copy (c->feedback_msgs); init = TRUE; } else { GList *item2; /* For every subsequent codec, we check if the trr_int is the same */ if (trr_int != c->trr_int) trr_int_all_same = FALSE; /* We also intersect the remembered list of feedback messages with * the list for that codec and remove any feedback message that isn't * in both */ for (item2 = identical_fbs; item2;) { WockyJingleFeedbackMessage *fb = identical_fbs->data; GList *next = item2->next; if (!g_list_find_custom (c->feedback_msgs, fb, (GCompareFunc) wocky_jingle_feedback_message_compare)) identical_fbs = g_list_delete_link (identical_fbs, item2); item2 = next; } /* If the trr_int is not the same everywhere and there are not common * feedback messages, then stop */ if (!trr_int_all_same && identical_fbs == NULL) break; } } if (trr_int_all_same && trr_int == G_MAXUINT) trr_int_all_same = FALSE; /* if the trr_int is the same everywhere, lets set it globally */ if (trr_int_all_same) md->trr_int = trr_int; /* If there are feedback messages that are in every codec, put a copy of them * in the global structure */ if (identical_fbs) { md->feedback_msgs = wocky_jingle_feedback_message_list_copy (identical_fbs); g_list_free (identical_fbs); } if (trr_int_all_same || md->feedback_msgs != NULL) for (item = md->codecs; item; item = item->next) { WockyJingleCodec *c = item->data; GList *item2; /* If the trr_int is the same everywhere, lets put the default on * each codec, we have it in the main structure */ if (trr_int_all_same) c->trr_int = G_MAXUINT; /* Find the feedback messages that were put in the main structure and * remove them from each codec */ for (item2 = md->feedback_msgs; item2; item2 = item2->next) { GList *duplicated; WockyJingleFeedbackMessage *fb = item2->data; while ((duplicated = g_list_find_custom (c->feedback_msgs, fb, (GCompareFunc) wocky_jingle_feedback_message_compare)) != NULL) { wocky_jingle_feedback_message_free (duplicated->data); c->feedback_msgs = g_list_delete_link (c->feedback_msgs, duplicated); } } } } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-contact.c0000664000175000017500000000724711720661341025000 0ustar00cassidycassidy00000000000000/* * wocky-contact.c - Source for WockyContact * Copyright (C) 2009 Collabora Ltd. * @author Guillaume Desmottes * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** * SECTION: wocky-contact * @title: WockyContact * @short_description: * @include: wocky/wocky-contact.h * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-contact.h" #include #include #include #ifdef HAVE_UNISTD_H # include #endif #include #include "wocky-signals-marshal.h" #include "wocky-utils.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_ROSTER #include "wocky-debug-internal.h" G_DEFINE_TYPE (WockyContact, wocky_contact, G_TYPE_OBJECT) /* signal enum */ enum { LAST_SIGNAL, }; /* static guint signals[LAST_SIGNAL] = {0}; */ /* private structure */ struct _WockyContactPrivate { gboolean dispose_has_run; }; static void wocky_contact_init (WockyContact *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_CONTACT, WockyContactPrivate); } static void wocky_contact_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { /* WockyContactPrivate *priv = object->priv; */ switch (property_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_contact_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { /* WockyContactPrivate *priv = object->priv; */ switch (property_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_contact_constructed (GObject *object) { } static void wocky_contact_dispose (GObject *object) { WockyContact *self = WOCKY_CONTACT (object); WockyContactPrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; if (G_OBJECT_CLASS (wocky_contact_parent_class)->dispose) G_OBJECT_CLASS (wocky_contact_parent_class)->dispose (object); } static void wocky_contact_finalize (GObject *object) { /* WockyContact *self = WOCKY_CONTACT (object); WockyContactPrivate *priv = self->priv; */ G_OBJECT_CLASS (wocky_contact_parent_class)->finalize (object); } static void wocky_contact_class_init (WockyContactClass *wocky_contact_class) { GObjectClass *object_class = G_OBJECT_CLASS (wocky_contact_class); g_type_class_add_private (wocky_contact_class, sizeof (WockyContactPrivate)); object_class->constructed = wocky_contact_constructed; object_class->set_property = wocky_contact_set_property; object_class->get_property = wocky_contact_get_property; object_class->dispose = wocky_contact_dispose; object_class->finalize = wocky_contact_finalize; } gchar * wocky_contact_dup_jid (WockyContact *self) { WockyContactClass *cls = WOCKY_CONTACT_GET_CLASS (self); if (cls->dup_jid != NULL) return cls->dup_jid (self); else return NULL; } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jabber-auth.h0000664000175000017500000000603211720661341025525 0ustar00cassidycassidy00000000000000/* * wocky-jabber-auth.h - Header for WockyJabberAuth * Copyright (C) 2009-2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_JABBER_AUTH_H__ #define __WOCKY_JABBER_AUTH_H__ #include #include #include "wocky-stanza.h" #include "wocky-xmpp-connection.h" #include "wocky-auth-registry.h" G_BEGIN_DECLS typedef struct _WockyJabberAuth WockyJabberAuth; /** * WockyJabberAuthClass: * * The class of a #WockyJabberAuth. */ typedef struct _WockyJabberAuthClass WockyJabberAuthClass; typedef struct _WockyJabberAuthPrivate WockyJabberAuthPrivate; struct _WockyJabberAuthClass { /**/ GObjectClass parent_class; }; struct _WockyJabberAuth { /**/ GObject parent; WockyJabberAuthPrivate *priv; }; GType wocky_jabber_auth_get_type (void); /* TYPE MACROS */ #define WOCKY_TYPE_JABBER_AUTH \ (wocky_jabber_auth_get_type ()) #define WOCKY_JABBER_AUTH(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_JABBER_AUTH, WockyJabberAuth)) #define WOCKY_JABBER_AUTH_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_JABBER_AUTH, WockyJabberAuthClass)) #define WOCKY_IS_JABBER_AUTH(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_JABBER_AUTH)) #define WOCKY_IS_JABBER_AUTH_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_JABBER_AUTH)) #define WOCKY_JABBER_AUTH_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_JABBER_AUTH, WockyJabberAuthClass)) WockyJabberAuth *wocky_jabber_auth_new (const gchar *server, const gchar *username, const gchar *resource, const gchar *password, WockyXmppConnection *connection, WockyAuthRegistry *auth_registry); void wocky_jabber_auth_add_handler (WockyJabberAuth *self, WockyAuthHandler *handler); void wocky_jabber_auth_authenticate_async (WockyJabberAuth *self, gboolean allow_plain, gboolean is_secure, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_jabber_auth_authenticate_finish (WockyJabberAuth *self, GAsyncResult *result, GError **error); void wocky_jabber_auth_add_handler (WockyJabberAuth *auth, WockyAuthHandler *handler); G_END_DECLS #endif /* #ifndef __WOCKY_JABBER_AUTH_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-loopback-stream.c0000664000175000017500000003532512005516162026423 0ustar00cassidycassidy00000000000000/* * wocky-loopback-stream.c - Source for WockyLoopbackStream * Copyright (C) 2009-2011 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "wocky-loopback-stream.h" enum { PROP_IO_INPUT_STREAM = 1, PROP_IO_OUTPUT_STREAM }; static GType wocky_loopback_input_stream_get_type (void); static GType wocky_loopback_output_stream_get_type (void); struct _WockyLoopbackStreamPrivate { GInputStream *input; GOutputStream *output; }; typedef struct { GOutputStream parent; GAsyncQueue *queue; GError *write_error /* no, this is not a coding style violation */; gboolean dispose_has_run; } WockyLoopbackOutputStream; typedef struct { GOutputStreamClass parent_class; } WockyLoopbackOutputStreamClass; typedef struct { GInputStream parent; GAsyncQueue *queue; guint offset; GArray *out_array; GSimpleAsyncResult *read_result; GCancellable *read_cancellable; gulong read_cancellable_sig_id; void *buffer; gsize count; GError *read_error /* no, this is not a coding style violation */; gboolean dispose_has_run; } WockyLoopbackInputStream; typedef struct { GOutputStreamClass parent_class; } WockyLoopbackInputStreamClass; G_DEFINE_TYPE (WockyLoopbackStream, wocky_loopback_stream, G_TYPE_IO_STREAM); G_DEFINE_TYPE (WockyLoopbackInputStream, wocky_loopback_input_stream, G_TYPE_INPUT_STREAM); G_DEFINE_TYPE (WockyLoopbackOutputStream, wocky_loopback_output_stream, G_TYPE_OUTPUT_STREAM); #define WOCKY_TYPE_LOOPBACK_INPUT_STREAM (wocky_loopback_input_stream_get_type ()) #define WOCKY_TYPE_LOOPBACK_OUTPUT_STREAM (wocky_loopback_output_stream_get_type ()) #define WOCKY_LOOPBACK_INPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ WOCKY_TYPE_LOOPBACK_INPUT_STREAM, \ WockyLoopbackInputStream)) #define WOCKY_LOOPBACK_OUTPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ WOCKY_TYPE_LOOPBACK_OUTPUT_STREAM, \ WockyLoopbackOutputStream)) static gboolean wocky_loopback_input_stream_try_read (WockyLoopbackInputStream *self); static void output_data_written_cb (GOutputStream *output, WockyLoopbackInputStream *input_stream) { wocky_loopback_input_stream_try_read (input_stream); } /* connection */ static void wocky_loopback_stream_init (WockyLoopbackStream *self) { WockyLoopbackStreamPrivate *priv; self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_LOOPBACK_STREAM, WockyLoopbackStreamPrivate); priv = self->priv; priv->output = g_object_new (WOCKY_TYPE_LOOPBACK_OUTPUT_STREAM, NULL); priv->input = g_object_new (WOCKY_TYPE_LOOPBACK_INPUT_STREAM, NULL); WOCKY_LOOPBACK_INPUT_STREAM (priv->input)->queue = g_async_queue_ref ( WOCKY_LOOPBACK_OUTPUT_STREAM (priv->output)->queue); g_signal_connect (priv->output, "data-written", G_CALLBACK (output_data_written_cb), priv->input); } static void wocky_loopback_stream_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyLoopbackStream *self = WOCKY_LOOPBACK_STREAM (object); WockyLoopbackStreamPrivate *priv = self->priv; switch (property_id) { case PROP_IO_INPUT_STREAM: g_value_set_object (value, priv->input); break; case PROP_IO_OUTPUT_STREAM: g_value_set_object (value, priv->output); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_loopback_stream_dispose (GObject *object) { WockyLoopbackStream *self = WOCKY_LOOPBACK_STREAM (object); WockyLoopbackStreamPrivate *priv = self->priv; if (G_OBJECT_CLASS (wocky_loopback_stream_parent_class)->dispose) G_OBJECT_CLASS (wocky_loopback_stream_parent_class)->dispose (object); g_object_unref (priv->input); g_object_unref (priv->output); } static GInputStream * wocky_loopback_stream_get_input_stream (GIOStream *stream) { return WOCKY_LOOPBACK_STREAM (stream)->priv->input; } static GOutputStream * wocky_loopback_stream_get_output_stream (GIOStream *stream) { return WOCKY_LOOPBACK_STREAM (stream)->priv->output; } static void wocky_loopback_stream_class_init ( WockyLoopbackStreamClass *wocky_loopback_stream_class) { GObjectClass *obj_class = G_OBJECT_CLASS (wocky_loopback_stream_class); GIOStreamClass *stream_class = G_IO_STREAM_CLASS ( wocky_loopback_stream_class); g_type_class_add_private (wocky_loopback_stream_class, sizeof (WockyLoopbackStreamPrivate)); obj_class->dispose = wocky_loopback_stream_dispose; obj_class->get_property = wocky_loopback_stream_get_property; stream_class->get_input_stream = wocky_loopback_stream_get_input_stream; stream_class->get_output_stream = wocky_loopback_stream_get_output_stream; g_object_class_install_property (obj_class, PROP_IO_INPUT_STREAM, g_param_spec_object ("input-stream", "Input stream", "the input stream", G_TYPE_INPUT_STREAM, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (obj_class, PROP_IO_OUTPUT_STREAM, g_param_spec_object ("output-stream", "Output stream", "the output stream", G_TYPE_OUTPUT_STREAM, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); } GIOStream * wocky_loopback_stream_new (void) { return g_object_new (WOCKY_TYPE_LOOPBACK_STREAM, NULL); } /* Input stream */ static gssize wocky_loopback_input_stream_read (GInputStream *stream, void *buffer, gsize count, GCancellable *cancellable, GError **error) { WockyLoopbackInputStream *self = WOCKY_LOOPBACK_INPUT_STREAM (stream); gsize written = 0; if (self->out_array == NULL) { g_assert (self->offset == 0); self->out_array = g_async_queue_pop (self->queue); } do { gsize towrite; if (self->offset == 0) { towrite = MIN (count - written, MAX (self->out_array->len/2, 1)); } else { towrite = MIN (count - written, self->out_array->len - self->offset); } memcpy ((guchar *) buffer + written, self->out_array->data + self->offset, towrite); self->offset += towrite; written += towrite; if (self->offset == self->out_array->len) { g_array_unref (self->out_array); self->out_array = g_async_queue_try_pop (self->queue); self->offset = 0; } else { break; } } while (written < count && self->out_array != NULL); return written; } static void read_async_complete (WockyLoopbackInputStream *self) { GSimpleAsyncResult *r = self->read_result; if (self->read_cancellable != NULL) { g_signal_handler_disconnect (self->read_cancellable, self->read_cancellable_sig_id); g_object_unref (self->read_cancellable); self->read_cancellable = NULL; } self->read_result = NULL; g_simple_async_result_complete_in_idle (r); g_object_unref (r); } static void read_cancelled_cb (GCancellable *cancellable, WockyLoopbackInputStream *self) { g_simple_async_result_set_error (self->read_result, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Reading cancelled"); self->buffer = NULL; read_async_complete (self); } static void wocky_loopback_input_stream_read_async (GInputStream *stream, void *buffer, gsize count, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyLoopbackInputStream *self = WOCKY_LOOPBACK_INPUT_STREAM (stream); g_assert (self->buffer == NULL); g_assert (self->read_result == NULL); g_assert (self->read_cancellable == NULL); self->buffer = buffer; self->count = count; self->read_result = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, wocky_loopback_input_stream_read_async); if (self->read_error != NULL) { g_simple_async_result_set_from_error (self->read_result, self->read_error); g_error_free (self->read_error); self->read_error = NULL; read_async_complete (self); return; } if (cancellable != NULL) { self->read_cancellable = g_object_ref (cancellable); self->read_cancellable_sig_id = g_signal_connect (cancellable, "cancelled", G_CALLBACK (read_cancelled_cb), self); } wocky_loopback_input_stream_try_read (self); } static gssize wocky_loopback_input_stream_read_finish (GInputStream *stream, GAsyncResult *result, GError **error) { WockyLoopbackInputStream *self = WOCKY_LOOPBACK_INPUT_STREAM (stream); gssize len = -1; if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) goto out; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), wocky_loopback_input_stream_read_async), -1); len = wocky_loopback_input_stream_read (stream, self->buffer, self->count, NULL, error); out: self->buffer = NULL; return len; } static gboolean wocky_loopback_input_stream_try_read (WockyLoopbackInputStream *self) { if (self->read_result == NULL) /* No pending read operation */ return FALSE; if (self->out_array == NULL && g_async_queue_length (self->queue) == 0) return FALSE; read_async_complete (self); return TRUE; } static void wocky_loopback_input_stream_init (WockyLoopbackInputStream *self) { } static void wocky_loopback_input_stream_dispose (GObject *object) { WockyLoopbackInputStream *self = WOCKY_LOOPBACK_INPUT_STREAM (object); if (self->dispose_has_run) return; self->dispose_has_run = TRUE; if (self->out_array != NULL) g_array_unref (self->out_array); self->out_array = NULL; if (self->queue != NULL) g_async_queue_unref (self->queue); self->queue = NULL; g_warn_if_fail (self->read_result == NULL); g_warn_if_fail (self->read_cancellable == NULL); /* release any references held by the object here */ if (G_OBJECT_CLASS (wocky_loopback_input_stream_parent_class)->dispose) G_OBJECT_CLASS (wocky_loopback_input_stream_parent_class)->dispose (object); } static void wocky_loopback_input_stream_class_init ( WockyLoopbackInputStreamClass *wocky_loopback_input_stream_class) { GObjectClass *obj_class = G_OBJECT_CLASS (wocky_loopback_input_stream_class); GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (wocky_loopback_input_stream_class); obj_class->dispose = wocky_loopback_input_stream_dispose; stream_class->read_fn = wocky_loopback_input_stream_read; stream_class->read_async = wocky_loopback_input_stream_read_async; stream_class->read_finish = wocky_loopback_input_stream_read_finish; } /* Output stream */ enum { OUTPUT_DATA_WRITTEN, LAST_SIGNAL }; static guint output_signals[LAST_SIGNAL] = {0}; static gssize wocky_loopback_output_stream_write (GOutputStream *stream, const void *buffer, gsize count, GCancellable *cancellable, GError **error) { WockyLoopbackOutputStream *self = WOCKY_LOOPBACK_OUTPUT_STREAM (stream); GArray *data; data = g_array_sized_new (FALSE, FALSE, sizeof (guint8), count); g_array_insert_vals (data, 0, buffer, count); g_async_queue_push (self->queue, data); g_signal_emit (self, output_signals[OUTPUT_DATA_WRITTEN], 0); return count; } static void wocky_loopback_output_stream_write_async (GOutputStream *stream, const void *buffer, gsize count, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *simple; GError *error = NULL; gssize result; result = wocky_loopback_output_stream_write (stream, buffer, count, cancellable, &error); simple = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, wocky_loopback_output_stream_write_async); if (result == -1) { g_simple_async_result_set_from_error (simple, error); g_error_free (error); } else { g_simple_async_result_set_op_res_gssize (simple, result); } g_simple_async_result_complete_in_idle (simple); g_object_unref (simple); } static gssize wocky_loopback_output_stream_write_finish (GOutputStream *stream, GAsyncResult *result, GError **error) { if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) return -1; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (stream), wocky_loopback_output_stream_write_async), -1); return g_simple_async_result_get_op_res_gssize ( G_SIMPLE_ASYNC_RESULT (result)); } static void wocky_loopback_output_stream_dispose (GObject *object) { WockyLoopbackOutputStream *self = WOCKY_LOOPBACK_OUTPUT_STREAM (object); if (self->dispose_has_run) return; self->dispose_has_run = TRUE; g_async_queue_push (self->queue, g_array_sized_new (FALSE, FALSE, sizeof (guint8), 0)); g_async_queue_unref (self->queue); /* release any references held by the object here */ if (G_OBJECT_CLASS (wocky_loopback_output_stream_parent_class)->dispose) G_OBJECT_CLASS (wocky_loopback_output_stream_parent_class)->dispose (object); } static void queue_destroyed (gpointer data) { g_array_free ((GArray *) data, TRUE); } static void wocky_loopback_output_stream_init (WockyLoopbackOutputStream *self) { self->queue = g_async_queue_new_full (queue_destroyed); } static void wocky_loopback_output_stream_class_init ( WockyLoopbackOutputStreamClass *wocky_loopback_output_stream_class) { GObjectClass *obj_class = G_OBJECT_CLASS (wocky_loopback_output_stream_class); GOutputStreamClass *stream_class = G_OUTPUT_STREAM_CLASS (wocky_loopback_output_stream_class); obj_class->dispose = wocky_loopback_output_stream_dispose; stream_class->write_fn = wocky_loopback_output_stream_write; stream_class->write_async = wocky_loopback_output_stream_write_async; stream_class->write_finish = wocky_loopback_output_stream_write_finish; output_signals[OUTPUT_DATA_WRITTEN] = g_signal_new ("data-written", G_OBJECT_CLASS_TYPE(wocky_loopback_output_stream_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/Makefile.am0000664000175000017500000001734112212322440024066 0ustar00cassidycassidy00000000000000include $(top_srcdir)/tools/flymake.mk if ENABLE_SHARED_SUFFIX lib_LTLIBRARIES = libwocky.la libwocky_la_LDFLAGS = \ -no-undefined \ -release $(SHARED_SUFFIX) \ $(NULL) else noinst_LTLIBRARIES = libwocky.la endif EXTRA_DIST = enumtype_sources = \ $(srcdir)/wocky-auth-registry.h \ $(srcdir)/wocky-connector.h \ $(srcdir)/wocky-data-form.h \ $(srcdir)/wocky-jingle-info-internal.h \ $(srcdir)/wocky-jingle-types.h \ $(srcdir)/wocky-muc.h \ $(srcdir)/wocky-pubsub-node.h \ $(srcdir)/wocky-pubsub-service.h \ $(srcdir)/wocky-tls.h \ $(srcdir)/wocky-xmpp-error.h \ $(srcdir)/wocky-xmpp-reader.h built_headers = \ wocky-enumtypes.h \ wocky-signals-marshal.h built_sources = \ wocky-enumtypes.c \ wocky-signals-marshal.c \ wocky-signals-marshal.list BUILT_SOURCES = $(built_headers) $(built_sources) OPENSSL_SRC = \ wocky-openssl.c \ wocky-openssl-dh512.c \ wocky-openssl-dh1024.c \ wocky-openssl-dh2048.c \ wocky-openssl-dh4096.c GNUTLS_SRC = wocky-tls.c PROXY_SRC = \ wocky-http-proxy.h \ wocky-http-proxy.c handwritten_headers = \ wocky.h \ wocky-auth-handler.h \ wocky-auth-registry.h \ wocky-bare-contact.h \ wocky-c2s-porter.h \ wocky-caps-cache.h \ wocky-ll-connection-factory.h \ wocky-caps-hash.h \ wocky-connector.h \ wocky-contact.h \ wocky-contact-factory.h \ wocky-data-form.h \ wocky-debug.h \ wocky-disco-identity.h \ wocky-google-relay.h \ wocky-jabber-auth.h \ wocky-jabber-auth-digest.h \ wocky-jabber-auth-password.h \ wocky-jingle-content.h \ wocky-jingle-factory.h \ wocky-jingle-info-internal.h \ wocky-jingle-info.h \ wocky-jingle-media-rtp.h \ wocky-jingle-session.h \ wocky-jingle-transport-google.h \ wocky-jingle-transport-iceudp.h \ wocky-jingle-transport-iface.h \ wocky-jingle-transport-rawudp.h \ wocky-jingle-types.h \ wocky-ll-connector.h \ wocky-ll-contact.h \ wocky-loopback-stream.h \ wocky-meta-porter.h \ wocky-muc.h \ wocky-namespaces.h \ wocky-node.h \ wocky-node-tree.h \ wocky-pep-service.h \ wocky-ping.h \ wocky-porter.h \ wocky-pubsub-helpers.h \ wocky-pubsub-node.h \ wocky-pubsub-node-protected.h \ wocky-pubsub-service.h \ wocky-pubsub-service-protected.h \ wocky-resource-contact.h \ wocky-roster.h \ wocky-sasl-auth.h \ wocky-sasl-utils.h \ wocky-sasl-digest-md5.h \ wocky-sasl-scram.h \ wocky-sasl-plain.h \ wocky-session.h \ wocky-stanza.h \ wocky-tls.h \ wocky-tls-handler.h \ wocky-tls-connector.h \ wocky-types.h \ wocky-utils.h \ wocky-xep-0115-capabilities.h \ wocky-xmpp-connection.h \ wocky-xmpp-error.h \ wocky-xmpp-reader.h \ wocky-xmpp-writer.h handwritten_sources = \ wocky.c \ wocky-auth-handler.c \ wocky-auth-registry.c \ wocky-bare-contact.c \ wocky-c2s-porter.c \ wocky-caps-cache.c \ wocky-ll-connection-factory.c \ wocky-caps-hash.c \ wocky-connector.c \ wocky-contact.c \ wocky-contact-factory.c \ wocky-data-form.c \ wocky-debug.c \ wocky-debug-internal.h \ wocky-disco-identity.c \ wocky-heartbeat-source.c \ wocky-heartbeat-source.h \ wocky-google-relay.c \ wocky-jabber-auth.c \ wocky-jabber-auth-digest.c \ wocky-jabber-auth-password.c \ wocky-jingle-content.c \ wocky-jingle-factory.c \ wocky-jingle-info.c \ wocky-jingle-media-rtp.c \ wocky-jingle-session.c \ wocky-jingle-transport-google.c \ wocky-jingle-transport-iceudp.c \ wocky-jingle-transport-iface.c \ wocky-jingle-transport-rawudp.c \ wocky-ll-connector.c \ wocky-ll-contact.c \ wocky-loopback-stream.c \ wocky-meta-porter.c \ wocky-muc.c \ wocky-node.c \ wocky-node-private.h \ wocky-node-tree.c \ wocky-pep-service.c \ wocky-ping.c \ wocky-porter.c \ wocky-pubsub-helpers.c \ wocky-pubsub-node.c \ wocky-pubsub-node-internal.h \ wocky-pubsub-service.c \ wocky-resource-contact.c \ wocky-roster.c \ wocky-sasl-auth.c \ wocky-sasl-digest-md5.c \ wocky-sasl-scram.c \ wocky-sasl-utils.c \ wocky-sasl-plain.c \ wocky-session.c \ wocky-stanza.c \ wocky-utils.c \ wocky-tls-common.c \ wocky-tls-handler.c \ wocky-tls-connector.c \ wocky-xep-0115-capabilities.c \ wocky-xmpp-connection.c \ wocky-xmpp-error.c \ wocky-xmpp-reader.c \ wocky-xmpp-writer.c if USING_OPENSSL handwritten_sources += $(OPENSSL_SRC) EXTRA_DIST += $(GNUTLS_SRC) else handwritten_sources += $(GNUTLS_SRC) EXTRA_DIST += $(OPENSSL_SRC) endif if HAVE_GIO_PROXY handwritten_sources += $(PROXY_SRC) else EXTRA_DIST += $(PROXY_SRC) endif libwocky_la_SOURCES = $(handwritten_sources) $(built_sources) \ $(handwritten_headers) $(built_headers) if INSTALL_HEADERS libwocky_la_HEADERS = $(handwritten_headers) $(built_headers) libwocky_ladir = $(HEADER_DIR)/wocky if ENABLE_SHARED_SUFFIX pkgconfigdir = ${libdir}/pkgconfig pkgconfig_DATA = wocky.pc endif endif # Coding style checks check_c_sources = \ $(filter-out wocky-openssl%, \ $(filter-out wocky-tls.%, \ $(handwritten_sources) $(handwritten_headers) \ ) \ ) include $(top_srcdir)/tools/check-coding-style.mk check-local: check-coding-style CLEANFILES=$(built_sources) $(built_headers) dist-hook: $(shell for x in $(CLEANFILES); do rm -f $(distdir)/$$x ; done) wocky-signals-marshal.list: $(handwritten_sources) Makefile.am $(AM_V_GEN)( cd $(srcdir) && \ sed -n -e 's/.*_wocky_signals_marshal_\([[:upper:][:digit:]]*__[[:upper:][:digit:]_]*\).*/\1/p' \ $(handwritten_sources) ) \ | sed -e 's/__/:/' -e 'y/_/,/' | sort -u > $@.tmp @if cmp -s $@.tmp $@; then \ rm $@.tmp; \ else \ mv $@.tmp $@; \ fi %-signals-marshal.h: %-signals-marshal.list Makefile.am $(AM_V_GEN)glib-genmarshal --header --prefix=_$(subst -,_,$*)_signals_marshal $< > $@ %-signals-marshal.c: %-signals-marshal.list Makefile.am $(AM_V_GEN){ echo '#include "$*-signals-marshal.h"' && \ glib-genmarshal --body --prefix=_$(subst -,_,$*)_signals_marshal $< ; \ } > $@ AM_CFLAGS = $(ERROR_CFLAGS) $(GCOV_CFLAGS) \ @GLIB_CFLAGS@ @LIBXML2_CFLAGS@ @SQLITE_CFLAGS@ @TLS_CFLAGS@ \ @LIBIPHB_CFLAGS@ \ @SOUP_CFLAGS@ \ -DG_LOG_DOMAIN=\"wocky\" \ -DWOCKY_COMPILATION libwocky_la_LIBADD = \ $(GCOV_LIBS) \ @GLIB_LIBS@ \ @LIBXML2_LIBS@ \ @SQLITE_LIBS@ \ @TLS_LIBS@ \ @LIBIPHB_LIBS@ \ @SOUP_LIBS@ \ $(NULL) # rules for making the glib enum objects wocky-enumtypes.h: $(enumtype_sources) Makefile.am $(AM_V_GEN)glib-mkenums \ --fhead "#ifndef __WOCKY_ENUM_TYPES_H__\n#define __WOCKY_ENUM_TYPES_H__\n\n#include \n\nG_BEGIN_DECLS\n" \ --fprod "/* enumerations from \"@filename@\" */\n" \ --vhead "GType @enum_name@_get_type (void);\n#define WOCKY_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ --ftail "G_END_DECLS\n\n#endif /* __WOCKY_ENUM_TYPES_H__ */" \ $(enumtype_sources) > $@ wocky-enumtypes.c: $(enumtype_sources) Makefile.am $(AM_V_GEN)glib-mkenums \ --fhead "#include \"config.h\"\n" \ --fhead "#include <$*.h>" \ --fprod "\n/* enumerations from \"@filename@\" */\n#include \"@filename@\"" \ --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \ $(enumtype_sources) > $@ Android.mk: Makefile.am $(built_sources) $(built_headers) androgenizer -:PROJECT wocky -:SHARED wocky -:TAGS eng debug \ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ -:SOURCES $(handwritten_sources) $(built_sources) \ -:CFLAGS $(DEFS) $(CFLAGS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CFLAGS) \ -:CPPFLAGS $(CPPFLAGS) $(AM_CPPFLAGS) \ -:LDFLAGS $(AM_LDFLAGS) $(libwocky_la_LIBADD) \ > $@ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jabber-auth-password.h0000664000175000017500000000301611720661341027364 0ustar00cassidycassidy00000000000000#if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef _WOCKY_JABBER_AUTH_PASSWORD_H #define _WOCKY_JABBER_AUTH_PASSWORD_H #include #include "wocky-auth-handler.h" G_BEGIN_DECLS #define WOCKY_TYPE_JABBER_AUTH_PASSWORD wocky_jabber_auth_password_get_type() #define WOCKY_JABBER_AUTH_PASSWORD(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), WOCKY_TYPE_JABBER_AUTH_PASSWORD, \ WockyJabberAuthPassword)) #define WOCKY_JABBER_AUTH_PASSWORD_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), WOCKY_TYPE_JABBER_AUTH_PASSWORD, \ WockyJabberAuthPasswordClass)) #define WOCKY_IS_JABBER_AUTH_PASSWORD(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WOCKY_TYPE_JABBER_AUTH_PASSWORD)) #define WOCKY_IS_JABBER_AUTH_PASSWORD_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), WOCKY_TYPE_JABBER_AUTH_PASSWORD)) #define WOCKY_JABBER_AUTH_PASSWORD_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_JABBER_AUTH_PASSWORD, \ WockyJabberAuthPasswordClass)) typedef struct _WockyJabberAuthPasswordPrivate WockyJabberAuthPasswordPrivate; typedef struct { GObject parent; WockyJabberAuthPasswordPrivate *priv; } WockyJabberAuthPassword; typedef struct { GObjectClass parent_class; } WockyJabberAuthPasswordClass; GType wocky_jabber_auth_password_get_type (void); WockyJabberAuthPassword *wocky_jabber_auth_password_new ( const gchar *password); G_END_DECLS #endif /* defined _WOCKY_JABBER_AUTH_PASSWORD_H */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-sasl-scram.c0000664000175000017500000003742212026011677025411 0ustar00cassidycassidy00000000000000/* * wocky-sasl-scram.c - SCRAM-SHA1 implementation (to be RFC 5802) * Copyright (C) 2010 Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-sasl-scram.h" #include "wocky-sasl-auth.h" #include "wocky-sasl-utils.h" #include "wocky-utils.h" #include #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_AUTH #include "wocky-debug-internal.h" typedef enum { WOCKY_SASL_SCRAM_STATE_STARTED, WOCKY_SASL_SCRAM_STATE_SERVER_FIRST_MESSAGE, WOCKY_SASL_SCRAM_STATE_SERVER_FINAL_MESSAGE, WOCKY_SASL_SCRAM_STATE_FINISHED, } WockySaslScramState; static void sasl_handler_iface_init (gpointer g_iface); G_DEFINE_TYPE_WITH_CODE (WockySaslScram, wocky_sasl_scram, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE ( WOCKY_TYPE_AUTH_HANDLER, sasl_handler_iface_init)) enum { PROP_SERVER = 1, PROP_USERNAME, PROP_PASSWORD }; struct _WockySaslScramPrivate { WockySaslScramState state; gchar *username; gchar *password; gchar *server; gchar *client_nonce; gchar *nonce; gchar *salt; gchar *client_first_bare; gchar *server_first_bare; gchar *auth_message; guint64 iterations; GByteArray *salted_password; }; static void wocky_sasl_scram_get_property ( GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockySaslScram *self = (WockySaslScram *) object; WockySaslScramPrivate *priv = self->priv; switch (property_id) { case PROP_USERNAME: g_value_set_string (value, priv->username); break; case PROP_PASSWORD: g_value_set_string (value, priv->password); break; case PROP_SERVER: g_value_set_string (value, priv->server); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void wocky_sasl_scram_set_property ( GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockySaslScram *self = (WockySaslScram *) object; WockySaslScramPrivate *priv = self->priv; switch (property_id) { case PROP_SERVER: g_free (priv->server); priv->server = g_value_dup_string (value); break; case PROP_USERNAME: g_free (priv->username); priv->username = g_value_dup_string (value); break; case PROP_PASSWORD: g_free (priv->password); priv->password = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void wocky_sasl_scram_dispose (GObject *object) { WockySaslScram *self = (WockySaslScram *) object; WockySaslScramPrivate *priv = self->priv; g_free (priv->server); g_free (priv->username); g_free (priv->password); g_free (priv->client_nonce); g_free (priv->nonce); g_free (priv->salt); g_free (priv->client_first_bare); g_free (priv->server_first_bare); g_free (priv->auth_message); if (priv->salted_password != NULL) g_byte_array_unref (priv->salted_password); G_OBJECT_CLASS (wocky_sasl_scram_parent_class)->dispose (object); } static void wocky_sasl_scram_class_init ( WockySaslScramClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (WockySaslScramPrivate)); object_class->dispose = wocky_sasl_scram_dispose; object_class->set_property = wocky_sasl_scram_set_property; object_class->get_property = wocky_sasl_scram_get_property; g_object_class_install_property (object_class, PROP_SERVER, g_param_spec_string ("server", "server", "The name of the server we're authenticating to", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_USERNAME, g_param_spec_string ("username", "username", "The username to authenticate with", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_PASSWORD, g_param_spec_string ("password", "password", "The password to authenticate with", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); } static gboolean scram_initial_response (WockyAuthHandler *handler, GString **response, GError **error); static gboolean scram_handle_auth_data (WockyAuthHandler *handler, const GString *data, GString **response, GError **error); static gboolean scram_handle_success (WockyAuthHandler *handler, GError **error); static void sasl_handler_iface_init (gpointer g_iface) { WockyAuthHandlerIface *iface = g_iface; iface->mechanism = "SCRAM-SHA-1"; iface->plain = FALSE; iface->initial_response_func = scram_initial_response; iface->auth_data_func = scram_handle_auth_data; iface->success_func = scram_handle_success; } static void wocky_sasl_scram_init (WockySaslScram *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_SASL_SCRAM, WockySaslScramPrivate); self->priv->state = WOCKY_SASL_SCRAM_STATE_STARTED; } WockySaslScram * wocky_sasl_scram_new ( const gchar *server, const gchar *username, const gchar *password) { return g_object_new (WOCKY_TYPE_SASL_SCRAM, "server", server, "username", username, "password", password, NULL); } static gboolean scram_initial_response (WockyAuthHandler *handler, GString **response, GError **error) { WockySaslScram *self = WOCKY_SASL_SCRAM (handler); WockySaslScramPrivate *priv = self->priv; if (priv->username == NULL || priv->password == NULL) { g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NO_CREDENTIALS, "No username or password"); return FALSE; } g_assert (priv->client_nonce == NULL); priv->client_nonce = sasl_generate_base64_nonce (); priv->client_first_bare = g_strdup_printf ("n,,n=%s,r=%s", priv->username, priv->client_nonce); *response = g_string_new (priv->client_first_bare); priv->state = WOCKY_SASL_SCRAM_STATE_SERVER_FIRST_MESSAGE; return TRUE; } static gboolean scram_get_next_attr_value (gchar **message, gchar *attr, gchar **value) { gchar *end; end = *message; /* Need to not be at the end of the string, have a = as the first character * after the attribute and a valid value character as the next one */ if (end[0] == '\0' || end[1] != '=' || end[2] == '\0') return FALSE; *attr = end[0]; end += 2; *value = end; for (; *end != '\0' && *end != ','; end++) /* pass */ ; if (*end != '\0') *message = end + 1; /* Set the end to \0 so we can just point value to the start of it */ *end = '\0'; return TRUE; } /* xor the result array with the in array */ static void scram_xor_array (GByteArray *result, GByteArray *in) { gsize i; g_assert (result->len == in->len); for (i = 0; i < result->len ; i++) result->data[i] ^= in->data[i]; } static void scram_calculate_salted_password (WockySaslScram *self) { WockySaslScramPrivate *priv = self->priv; guint64 i; GByteArray *result, *prev, *salt; guint8 one[] = {0,0,0,1}; gint state = 0; guint save = 0; gsize len; gsize pass_len = strlen (priv->password); /* salt for U1 */ salt = g_byte_array_new (); /* Make sure we have enough data for the decoding base 64 and add 4 extra * bytes for the calculation */ g_byte_array_set_size (salt, (strlen (priv->salt)/4 * 3) + 3 + 4 ); len = g_base64_decode_step (priv->salt, strlen (priv->salt), salt->data, &state, &save); g_byte_array_set_size (salt, len); g_byte_array_append (salt, one, sizeof (one)); /* Calculate U1 */ result = sasl_calculate_hmac_sha1 ((guint8 *) priv->password, pass_len, salt->data, salt->len); prev = g_byte_array_sized_new (result->len); g_byte_array_append (prev, result->data, result->len); /* Calculate U2 and onwards, while keeping a rolling result */ for (i = 1; i < priv->iterations; i++) { GByteArray *U = sasl_calculate_hmac_sha1 ((guint8 *) priv->password, pass_len, prev->data, prev->len); g_byte_array_unref (prev); prev = U; scram_xor_array (result, U); } g_byte_array_unref (prev); g_byte_array_unref (salt); priv->salted_password = result; } static gchar * scram_make_client_proof (WockySaslScram *self) { /* As per RFC * ClientProof := ClientKey XOR ClientSignature * ClientSignature := HMAC(StoredKey, AuthMessage) * StoredKey := H(ClientKey) * ClientKey := HMAC(SaltedPassword, "Client Key") * SaltedPassword := Hi(Normalize(password), salt, i) */ #define CLIENT_KEY_STR "Client Key" WockySaslScramPrivate *priv = self->priv; gchar *proof = NULL; GByteArray *client_key, *client_signature; gsize len = WOCKY_SHA1_DIGEST_SIZE; guint8 stored_key[WOCKY_SHA1_DIGEST_SIZE]; GChecksum *checksum; /* Calculate the salted password and save it for later as we need it to * verify the servers reply */ scram_calculate_salted_password (self); client_key = sasl_calculate_hmac_sha1 (priv->salted_password->data, priv->salted_password->len, (guint8 *) CLIENT_KEY_STR, strlen (CLIENT_KEY_STR)); checksum = g_checksum_new (G_CHECKSUM_SHA1); g_checksum_update (checksum, client_key->data, client_key->len); g_checksum_get_digest (checksum, stored_key, &len); g_checksum_free (checksum); DEBUG ("auth message: %s", priv->auth_message); client_signature = sasl_calculate_hmac_sha1 (stored_key, WOCKY_SHA1_DIGEST_SIZE, (guint8 *) priv->auth_message, strlen (priv->auth_message)); /* xor signature and key, overwriting key */ scram_xor_array (client_key, client_signature); proof = g_base64_encode (client_key->data, client_key->len); g_byte_array_unref (client_key); g_byte_array_unref (client_signature); return proof; #undef CLIENT_KEY_STR } static gboolean scram_handle_server_first_message (WockySaslScram *self, gchar *message, GString **reply, GError **error) { WockySaslScramPrivate *priv = self->priv; gchar attr, *value = NULL; gchar *proof = NULL; GString *client_reply; if (!scram_get_next_attr_value (&message, &attr, &value)) goto invalid; /* Fail when getting an unknown mandatory extension (we don't know any) */ if (attr == 'm') goto unknown_extension; /* get the nonce */ if (attr != 'r') goto invalid; priv->nonce = g_strdup (value); if (strncmp (priv->client_nonce, priv->nonce, strlen (priv->client_nonce)) != 0) goto invalid_nonce; /* get the salt */ if (!scram_get_next_attr_value (&message, &attr, &value) || attr != 's') goto invalid; priv->salt = g_strdup (value); /* get the number of iterations */ if (!scram_get_next_attr_value (&message, &attr, &value) || attr != 'i') goto invalid; priv->iterations = g_ascii_strtoull (value, NULL, 10); if (priv->iterations == 0) goto invalid_iterations; /* We got everything we needed for our response without proof * base64("n,,") => biws */ client_reply = g_string_new (NULL); g_string_append_printf (client_reply, "c=biws,r=%s", priv->nonce); /* So we can make the auth message */ priv->auth_message = g_strdup_printf ("%s,%s,%s", priv->client_first_bare + 3, priv->server_first_bare, client_reply->str); /* and prepare our proof */ proof = scram_make_client_proof (self); g_string_append_printf (client_reply, ",p=%s", proof); g_free (proof); DEBUG ("Client reply: %s", client_reply->str); *reply = client_reply; return TRUE; invalid_iterations: g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, "Server sent an invalid interation count"); return FALSE; invalid_nonce: g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, "Server sent an invalid invalid nonce value"); return FALSE; invalid: g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, "Server sent an invalid first reply"); return FALSE; unknown_extension: g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, "Server sent an unknown mandatory extension"); return FALSE; } static gboolean scram_check_server_verification (WockySaslScram *self, gchar *verification) { /* * ServerSignature := HMAC(ServerKey, AuthMessage) * ServerKey := HMAC(SaltedPassword, "Server Key") */ #define SERVER_KEY_STR "Server Key" WockySaslScramPrivate *priv = self->priv; GByteArray *server_key; GByteArray *server_signature; gchar *v; gboolean ret; server_key = sasl_calculate_hmac_sha1 ( priv->salted_password->data, priv->salted_password->len, (guint8 *) SERVER_KEY_STR, strlen (SERVER_KEY_STR)); server_signature = sasl_calculate_hmac_sha1 (server_key->data, server_key->len, (guint8 *) priv->auth_message, strlen (priv->auth_message)); v = g_base64_encode (server_signature->data, server_signature->len); ret = !wocky_strdiff (v, verification); if (!ret) DEBUG ("Unexpected verification: got %s, expected %s", verification, v); g_byte_array_unref (server_key); g_byte_array_unref (server_signature); g_free (v); return ret; #undef SERVER_KEY_STR } static gboolean scram_handle_server_final_message (WockySaslScram *self, gchar *message, GError **error) { gchar attr, *value = NULL; if (!scram_get_next_attr_value (&message, &attr, &value) || attr != 'v') goto invalid; if (!scram_check_server_verification (self, value)) goto server_not_verified; return TRUE; server_not_verified: g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, "Server sent an incorrect final reply"); return FALSE; invalid: g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, "Server sent an invalid final reply"); return FALSE; } static gboolean scram_handle_auth_data (WockyAuthHandler *handler, const GString *data, GString **response, GError **error) { WockySaslScram *self = WOCKY_SASL_SCRAM (handler); WockySaslScramPrivate *priv = self->priv; gboolean ret = FALSE; DEBUG ("Got server message: %s", data->str); switch (priv->state) { case WOCKY_SASL_SCRAM_STATE_SERVER_FIRST_MESSAGE: priv->server_first_bare = g_strdup (data->str); if (!(ret = scram_handle_server_first_message (self, data->str, response, error))) goto out; priv->state = WOCKY_SASL_SCRAM_STATE_SERVER_FINAL_MESSAGE; break; case WOCKY_SASL_SCRAM_STATE_SERVER_FINAL_MESSAGE: if (!(ret = scram_handle_server_final_message (self, data->str, error))) goto out; priv->state = WOCKY_SASL_SCRAM_STATE_FINISHED; break; default: g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, "Server sent an unexpected reply"); goto out; } out: return ret; } static gboolean scram_handle_success (WockyAuthHandler *handler, GError **error) { WockySaslScram *self = WOCKY_SASL_SCRAM (handler); WockySaslScramPrivate *priv = self->priv; if (priv->state == WOCKY_SASL_SCRAM_STATE_FINISHED) return TRUE; g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, "Server sent success before finishing authentication"); return FALSE; } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jabber-auth-digest.h0000664000175000017500000000301711720661341027002 0ustar00cassidycassidy00000000000000#if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef _WOCKY_JABBER_AUTH_DIGEST_H #define _WOCKY_JABBER_AUTH_DIGEST_H #include #include "wocky-auth-handler.h" G_BEGIN_DECLS #define WOCKY_TYPE_JABBER_AUTH_DIGEST wocky_jabber_auth_digest_get_type() #define WOCKY_JABBER_AUTH_DIGEST(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), WOCKY_TYPE_JABBER_AUTH_DIGEST, \ WockyJabberAuthDigest)) #define WOCKY_JABBER_AUTH_DIGEST_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), WOCKY_TYPE_JABBER_AUTH_DIGEST, \ WockyJabberAuthDigestClass)) #define WOCKY_IS_JABBER_AUTH_DIGEST(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WOCKY_TYPE_JABBER_AUTH_DIGEST)) #define WOCKY_IS_JABBER_AUTH_DIGEST_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), WOCKY_TYPE_JABBER_AUTH_DIGEST)) #define WOCKY_JABBER_AUTH_DIGEST_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_JABBER_AUTH_DIGEST, \ WockyJabberAuthDigestClass)) typedef struct _WockyJabberAuthDigestPrivate WockyJabberAuthDigestPrivate; typedef struct { /**/ GObject parent; WockyJabberAuthDigestPrivate *priv; } WockyJabberAuthDigest; typedef struct { /**/ GObjectClass parent_class; } WockyJabberAuthDigestClass; GType wocky_jabber_auth_digest_get_type (void); WockyJabberAuthDigest *wocky_jabber_auth_digest_new ( const gchar *server, const gchar *password); G_END_DECLS #endif /* defined _WOCKY_JABBER_AUTH_DIGEST_H */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-resource-contact.h0000664000175000017500000000554411720661341026630 0ustar00cassidycassidy00000000000000/* * wocky-resource-contact.h - Header for WockyResourceContact * Copyright (C) 2009 Collabora Ltd. * @author Guillaume Desmottes * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_RESOURCE_CONTACT_H__ #define __WOCKY_RESOURCE_CONTACT_H__ #include #include "wocky-types.h" #include "wocky-contact.h" #include "wocky-bare-contact.h" #include "wocky-roster.h" G_BEGIN_DECLS /** * WockyResourceContactClass: * * The class of a #WockyResourceContact. */ typedef struct _WockyResourceContactClass WockyResourceContactClass; typedef struct _WockyResourceContactPrivate WockyResourceContactPrivate; struct _WockyResourceContactClass { /**/ WockyContactClass parent_class; }; struct _WockyResourceContact { /**/ WockyContact parent; WockyResourceContactPrivate *priv; }; GType wocky_resource_contact_get_type (void); #define WOCKY_TYPE_RESOURCE_CONTACT \ (wocky_resource_contact_get_type ()) #define WOCKY_RESOURCE_CONTACT(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_RESOURCE_CONTACT, \ WockyResourceContact)) #define WOCKY_RESOURCE_CONTACT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_RESOURCE_CONTACT, \ WockyResourceContactClass)) #define WOCKY_IS_RESOURCE_CONTACT(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_RESOURCE_CONTACT)) #define WOCKY_IS_RESOURCE_CONTACT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_RESOURCE_CONTACT)) #define WOCKY_RESOURCE_CONTACT_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_RESOURCE_CONTACT, \ WockyResourceContactClass)) WockyResourceContact * wocky_resource_contact_new (WockyBareContact *bare, const gchar *resource); const gchar * wocky_resource_contact_get_resource ( WockyResourceContact *contact); WockyBareContact * wocky_resource_contact_get_bare_contact ( WockyResourceContact *contact); gboolean wocky_resource_contact_equal (WockyResourceContact *a, WockyResourceContact *b); G_END_DECLS #endif /* #ifndef __WOCKY_RESOURCE_CONTACT_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jingle-content.h0000664000175000017500000001440412212322440026252 0ustar00cassidycassidy00000000000000/* * wocky-jingle-content.h - Header for WockyJingleContent * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __JINGLE_CONTENT_H__ #define __JINGLE_CONTENT_H__ #include #include "wocky-jingle-factory.h" #include "wocky-jingle-transport-iface.h" #include "wocky-jingle-types.h" G_BEGIN_DECLS typedef enum { WOCKY_JINGLE_MEDIA_TYPE_NONE = 0, WOCKY_JINGLE_MEDIA_TYPE_AUDIO, WOCKY_JINGLE_MEDIA_TYPE_VIDEO, } WockyJingleMediaType; typedef enum { WOCKY_JINGLE_CONTENT_STATE_EMPTY = 0, WOCKY_JINGLE_CONTENT_STATE_NEW, WOCKY_JINGLE_CONTENT_STATE_SENT, WOCKY_JINGLE_CONTENT_STATE_ACKNOWLEDGED, WOCKY_JINGLE_CONTENT_STATE_REMOVING } WockyJingleContentState; struct _WockyJingleCandidate { WockyJingleTransportProtocol protocol; WockyJingleCandidateType type; gchar *id; gchar *address; int port; int component; int generation; int preference; gchar *username; gchar *password; int network; }; typedef struct _WockyJingleContentClass WockyJingleContentClass; GType wocky_jingle_content_get_type (void); /* TYPE MACROS */ #define WOCKY_TYPE_JINGLE_CONTENT \ (wocky_jingle_content_get_type ()) #define WOCKY_JINGLE_CONTENT(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_JINGLE_CONTENT, \ WockyJingleContent)) #define WOCKY_JINGLE_CONTENT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_JINGLE_CONTENT, \ WockyJingleContentClass)) #define WOCKY_IS_JINGLE_CONTENT(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_JINGLE_CONTENT)) #define WOCKY_IS_JINGLE_CONTENT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_JINGLE_CONTENT)) #define WOCKY_JINGLE_CONTENT_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_JINGLE_CONTENT, \ WockyJingleContentClass)) struct _WockyJingleContentClass { GObjectClass parent_class; void (*parse_description) (WockyJingleContent *, WockyNode *, GError **); void (*produce_description) (WockyJingleContent *, WockyNode *); void (*transport_created) (WockyJingleContent *, WockyJingleTransportIface *); WockyJingleContentSenders (*get_default_senders) (WockyJingleContent *); }; typedef struct _WockyJingleContentPrivate WockyJingleContentPrivate; struct _WockyJingleContent { GObject parent; WockyJingleContentPrivate *priv; WockyJingleSession *session; }; void wocky_jingle_content_parse_add (WockyJingleContent *c, WockyNode *content_node, gboolean google_mode, GError **error); void wocky_jingle_content_update_senders (WockyJingleContent *c, WockyNode *content_node, GError **error); void wocky_jingle_content_produce_node (WockyJingleContent *c, WockyNode *parent, gboolean include_description, gboolean include_transport, WockyNode **trans_node_out); void wocky_jingle_content_parse_accept (WockyJingleContent *c, WockyNode *content_node, gboolean google_mode, GError **error); void wocky_jingle_content_parse_info (WockyJingleContent *c, WockyNode *content_node, GError **error); void wocky_jingle_content_parse_transport_info (WockyJingleContent *self, WockyNode *trans_node, GError **error); void wocky_jingle_content_parse_description_info (WockyJingleContent *self, WockyNode *trans_node, GError **error); guint wocky_jingle_content_create_share_channel (WockyJingleContent *self, const gchar *name); void wocky_jingle_content_add_candidates (WockyJingleContent *self, GList *li); void _wocky_jingle_content_set_media_ready (WockyJingleContent *self); gboolean wocky_jingle_content_is_ready (WockyJingleContent *self); void wocky_jingle_content_set_transport_state (WockyJingleContent *content, WockyJingleTransportState state); void wocky_jingle_content_remove (WockyJingleContent *c, gboolean signal_peer); void wocky_jingle_content_reject (WockyJingleContent *c, WockyJingleReason reason); GList *wocky_jingle_content_get_remote_candidates (WockyJingleContent *c); GList *wocky_jingle_content_get_local_candidates (WockyJingleContent *c); gboolean wocky_jingle_content_get_credentials (WockyJingleContent *c, gchar **ufrag, gchar **pwd); gboolean wocky_jingle_content_change_direction (WockyJingleContent *c, WockyJingleContentSenders senders); void wocky_jingle_content_retransmit_candidates (WockyJingleContent *self, gboolean all); void wocky_jingle_content_inject_candidates (WockyJingleContent *self, WockyNode *transport_node); gboolean wocky_jingle_content_is_created_by_us (WockyJingleContent *c); gboolean wocky_jingle_content_creator_is_initiator (WockyJingleContent *c); const gchar *wocky_jingle_content_get_name (WockyJingleContent *self); const gchar *wocky_jingle_content_get_ns (WockyJingleContent *self); const gchar *wocky_jingle_content_get_disposition (WockyJingleContent *self); WockyJingleTransportType wocky_jingle_content_get_transport_type (WockyJingleContent *c); const gchar *wocky_jingle_content_get_transport_ns (WockyJingleContent *self); void wocky_jingle_content_maybe_send_description (WockyJingleContent *self); gboolean wocky_jingle_content_sending (WockyJingleContent *self); gboolean wocky_jingle_content_receiving (WockyJingleContent *self); void wocky_jingle_content_set_sending (WockyJingleContent *self, gboolean send); void wocky_jingle_content_request_receiving (WockyJingleContent *self, gboolean receive); void wocky_jingle_content_send_complete (WockyJingleContent *self); G_END_DECLS #endif /* __JINGLE_CONTENT_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-data-form.h0000664000175000017500000001676512332440003025217 0ustar00cassidycassidy00000000000000/* * wocky-data-form.h - Header of WockyDataForm * Copyright © 2009–2010 Collabora Ltd. * Copyright © 2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef WOCKY_DATA_FORM_H #define WOCKY_DATA_FORM_H #include #include "wocky-enumtypes.h" #include "wocky-node.h" G_BEGIN_DECLS /** * WockyDataFormFieldType: * @WOCKY_DATA_FORM_FIELD_TYPE_UNSPECIFIED: Unspecified field type * @WOCKY_DATA_FORM_FIELD_TYPE_BOOLEAN: Boolean field type * @WOCKY_DATA_FORM_FIELD_TYPE_FIXED: Fixed description field type * @WOCKY_DATA_FORM_FIELD_TYPE_HIDDEN: Hidden field type * @WOCKY_DATA_FORM_FIELD_TYPE_JID_MULTI: A list of multiple JIDs * @WOCKY_DATA_FORM_FIELD_TYPE_JID_SINGLE: A single JID * @WOCKY_DATA_FORM_FIELD_TYPE_LIST_MULTI: Many options to choose one * or more from * @WOCKY_DATA_FORM_FIELD_TYPE_LIST_SINGLE: Many options to choose one * from * @WOCKY_DATA_FORM_FIELD_TYPE_TEXT_MULTI: Multiple lines of text * @WOCKY_DATA_FORM_FIELD_TYPE_TEXT_PRIVATE: A single line of text * that should be obscured (by, say, asterisks) * @WOCKY_DATA_FORM_FIELD_TYPE_TEXT_SINGLE: A single line of text * * Data form field types, as documented in XEP-0004 §3.3. */ /*< prefix=WOCKY_DATA_FORM_FIELD_TYPE >*/ typedef enum { WOCKY_DATA_FORM_FIELD_TYPE_UNSPECIFIED, /*< skip >*/ WOCKY_DATA_FORM_FIELD_TYPE_BOOLEAN, WOCKY_DATA_FORM_FIELD_TYPE_FIXED, WOCKY_DATA_FORM_FIELD_TYPE_HIDDEN, WOCKY_DATA_FORM_FIELD_TYPE_JID_MULTI, WOCKY_DATA_FORM_FIELD_TYPE_JID_SINGLE, WOCKY_DATA_FORM_FIELD_TYPE_LIST_MULTI, WOCKY_DATA_FORM_FIELD_TYPE_LIST_SINGLE, WOCKY_DATA_FORM_FIELD_TYPE_TEXT_MULTI, WOCKY_DATA_FORM_FIELD_TYPE_TEXT_PRIVATE, WOCKY_DATA_FORM_FIELD_TYPE_TEXT_SINGLE } WockyDataFormFieldType; /** * WockyDataFormFieldOption: * @label: the option label * @value: the option value * * A single data form field option. */ typedef struct _WockyDataFormFieldOption WockyDataFormFieldOption; struct _WockyDataFormFieldOption { gchar *label; gchar *value; }; /** * WockyDataFormField: * @type: the type of the field * @var: the field name * @label: the label of the field * @desc: the description of the field * @required: %TRUE if the field is required, otherwise %FALSE * @default_value: the default of the field * @raw_value_contents: a %NULL-terminated array holding the literal value(s) as * specified in the original XML. For example, this might be something like * { "1", NULL } * or * { "false", NULL } * for a #WOCKY_DATA_FORM_FIELD_TYPE_BOOLEAN field, or * { "hi", "there", NULL } * for a #WOCKY_DATA_FORM_FIELD_TYPE_TEXT_MULTI field. * @value: the field value * @options: a #GSList of #WockyDataFormFieldOptions if @type * if %WOCKY_DATA_FORM_FIELD_TYPE_LIST_MULTI or * %WOCKY_DATA_FORM_FIELD_TYPE_LIST_SINGLE * * Details about a single data form field in a #WockyDataForm. */ typedef struct _WockyDataFormField WockyDataFormField; struct _WockyDataFormField { WockyDataFormFieldType type; gchar *var; gchar *label; gchar *desc; gboolean required; GValue *default_value; gchar **raw_value_contents; GValue *value; /* for LIST_MULTI and LIST_SINGLE only. * List of (WockyDataFormFieldOption *)*/ GSList *options; }; /** * WockyDataForm: * @fields: a #GHashTable of strings to #WockyDataFormFields * @fields_list: a list of #WockyDataFormFields in the order * they have been presented in the form * @results: a list of #GSLists of #WockyDataFormFields * representing one or more sets of result. * * An object that represents an XMPP data form as described in * XEP-0004. */ typedef struct _WockyDataForm WockyDataForm; /** * WockyDataFormClass: * * The class of a #WockyDataForm. */ typedef struct _WockyDataFormClass WockyDataFormClass; typedef struct _WockyDataFormPrivate WockyDataFormPrivate; /** * WockyDataFormError: * @WOCKY_DATA_FORM_ERROR_NOT_FORM: Node is not a data form * @WOCKY_DATA_FORM_ERROR_WRONG_TYPE: Data form is of the wrong type * * #WockyDataForm specific errors. */ typedef enum { WOCKY_DATA_FORM_ERROR_NOT_FORM, WOCKY_DATA_FORM_ERROR_WRONG_TYPE, } WockyDataFormError; GQuark wocky_data_form_error_quark (void); #define WOCKY_DATA_FORM_ERROR (wocky_data_form_error_quark ()) struct _WockyDataFormClass { /**/ GObjectClass parent_class; }; struct _WockyDataForm { /**/ GObject parent; /**/ /* (gchar *) owned by the WockyDataFormField => * borrowed (WockyDataFormField *) */ GHashTable *fields; /* list containing owned (WockyDataFormField *) in the order they * have been presented in the form */ GSList *fields_list; /* list of GSList * of (WockyDataFormField *), representing one or more sets * of results */ GSList *results; /**/ WockyDataFormPrivate *priv; }; GType wocky_data_form_get_type (void); #define WOCKY_TYPE_DATA_FORM \ (wocky_data_form_get_type ()) #define WOCKY_DATA_FORM(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_DATA_FORM, \ WockyDataForm)) #define WOCKY_DATA_FORM_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_DATA_FORM, \ WockyDataFormClass)) #define WOCKY_IS_DATA_FORM(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_DATA_FORM)) #define WOCKY_IS_DATA_FORM_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_DATA_FORM)) #define WOCKY_DATA_FORM_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_DATA_FORM, \ WockyDataFormClass)) WockyDataForm * wocky_data_form_new_from_form (WockyNode *node, GError **error); WockyDataForm * wocky_data_form_new_from_node (WockyNode *x, GError **error); gboolean wocky_data_form_set_type (WockyDataForm *self, const gchar *form_type); gboolean wocky_data_form_set_boolean (WockyDataForm *self, const gchar *field_name, gboolean field_value, gboolean create_if_missing); gboolean wocky_data_form_set_string (WockyDataForm *self, const gchar *field_name, const gchar *field_value, gboolean create_if_missing); gboolean wocky_data_form_set_strv (WockyDataForm *self, const gchar *field_name, const gchar * const *field_values, gboolean create_if_missing); void wocky_data_form_submit (WockyDataForm *self, WockyNode *node); gboolean wocky_data_form_parse_result (WockyDataForm *self, WockyNode *node, GError **error); const gchar *wocky_data_form_get_title (WockyDataForm *self); const gchar *wocky_data_form_get_instructions (WockyDataForm *self); gint wocky_data_form_field_cmp (const WockyDataFormField *left, const WockyDataFormField *right); void wocky_data_form_add_to_node (WockyDataForm *self, WockyNode *node); G_END_DECLS #endif /* WOCKY_DATA_FORM_H */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-pubsub-helpers.c0000664000175000017500000003523712212322440026274 0ustar00cassidycassidy00000000000000/* * wocky-pubsub-helpers.c — PubSub helper functions * Copyright © 2009–2012 Collabora Ltd. * Copyright © 2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-pubsub-helpers.h" #include "wocky-namespaces.h" #include "wocky-pubsub-service.h" #include "wocky-session.h" #include "wocky-xep-0115-capabilities.h" /** * wocky_pubsub_make_event_stanza: * @node: the the name of the pubsub node; may not be %NULL * @from: a JID to use as the 'from' attribute, or %NULL * @item_out: a location to store the item #WockyNode, or %NULL * * Generates a new message stanza to send to other contacts about an * updated PEP node. * * Note that this should only be used in link-local * connections. Regular pubsub consists of making a publish stanza * with wocky_pubsub_make_publish_stanza() and sending it to your own * server. The server will then send the event stanza on to your * contacts who have the appropriate capability. * * Returns: a new #WockyStanza pubsub event stanza; free with g_object_unref() */ WockyStanza * wocky_pubsub_make_event_stanza (const gchar *node, const gchar *from, WockyNode **item_out) { WockyStanza *stanza; WockyNode *message, *event, *items, *item; g_return_val_if_fail (node != NULL, NULL); stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_HEADLINE, from, NULL, '(', "event", ':', WOCKY_XMPP_NS_PUBSUB_EVENT, '(', "items", '@', "node", node, '(', "item", ')', ')', ')', NULL); message = wocky_stanza_get_top_node (stanza); event = wocky_node_get_first_child (message); items = wocky_node_get_first_child (event); item = wocky_node_get_first_child (items); if (item_out != NULL) *item_out = item; return stanza; } /** * wocky_pubsub_make_publish_stanza: * @service: the JID of a PubSub service, or %NULL * @node: the name of a node on @service; may not be %NULL * @pubsub_out: address at which to store a pointer to the <pubsub/> node * @publish_out: address at which to store a pointer to the <publish/> * node * @item_out: address at which to store a pointer to the <item/> node * * * * Returns: a new iq[type='set']/pubsub/publish/item stanza */ WockyStanza * wocky_pubsub_make_publish_stanza ( const gchar *service, const gchar *node, WockyNode **pubsub_out, WockyNode **publish_out, WockyNode **item_out) { WockyStanza *stanza; WockyNode *publish, *item; g_return_val_if_fail (node != NULL, NULL); stanza = wocky_pubsub_make_stanza (service, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_XMPP_NS_PUBSUB, "publish", pubsub_out, &publish); wocky_node_set_attribute (publish, "node", node); item = wocky_node_add_child (publish, "item"); if (publish_out != NULL) *publish_out = publish; if (item_out != NULL) *item_out = item; return stanza; } /** * wocky_pubsub_make_stanza: * @service: the JID of a PubSub service, or %NULL * @sub_type: #WOCKY_STANZA_SUB_TYPE_SET or #WOCKY_STANZA_SUB_TYPE_GET, as you wish * @pubsub_ns: the namespace for the <pubsub/> node of the stanza * @action_name: the action node to add to <pubsub/> * @pubsub_node: address at which to store a pointer to the <pubsub/> node * @action_node: address at wihch to store a pointer to the <@action/> * node * * * * Returns: a new iq[type=@sub_type]/pubsub/@action stanza */ WockyStanza * wocky_pubsub_make_stanza ( const gchar *service, WockyStanzaSubType sub_type, const gchar *pubsub_ns, const gchar *action_name, WockyNode **pubsub_node, WockyNode **action_node) { WockyStanza *stanza; WockyNode *pubsub, *action; g_assert (pubsub_ns != NULL); g_assert (action_name != NULL); stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, sub_type, NULL, service, '(', "pubsub", ':', pubsub_ns, '*', &pubsub, '(', action_name, '*', &action, ')', ')', NULL); if (pubsub_node != NULL) *pubsub_node = pubsub; if (action_node != NULL) *action_node = action; return stanza; } static void send_stanza_to_contact (WockyPorter *porter, WockyContact *contact, WockyStanza *stanza) { WockyStanza *to_send = wocky_stanza_copy (stanza); wocky_stanza_set_to_contact (to_send, contact); wocky_porter_send (porter, to_send); g_object_unref (to_send); } /** * wocky_send_ll_pep_event: * @session: the WockySession to send on * @stanza: the PEP event stanza to send * * Send a PEP event to all link-local contacts interested in receiving it. */ void wocky_send_ll_pep_event (WockySession *session, WockyStanza *stanza) { WockyContactFactory *contact_factory; WockyPorter *porter; WockyLLContact *self_contact; GList *contacts, *l; WockyNode *message, *event, *items; const gchar *pep_node; gchar *node; g_return_if_fail (WOCKY_IS_SESSION (session)); g_return_if_fail (WOCKY_IS_STANZA (stanza)); message = wocky_stanza_get_top_node (stanza); event = wocky_node_get_first_child (message); items = wocky_node_get_first_child (event); pep_node = wocky_node_get_attribute (items, "node"); if (pep_node == NULL) return; node = g_strdup_printf ("%s+notify", pep_node); contact_factory = wocky_session_get_contact_factory (session); porter = wocky_session_get_porter (session); contacts = wocky_contact_factory_get_ll_contacts (contact_factory); for (l = contacts; l != NULL; l = l->next) { WockyXep0115Capabilities *contact; if (!WOCKY_IS_XEP_0115_CAPABILITIES (l->data)) continue; contact = l->data; if (wocky_xep_0115_capabilities_has_feature (contact, node)) send_stanza_to_contact (porter, WOCKY_CONTACT (contact), stanza); } /* now send to self */ self_contact = wocky_contact_factory_ensure_ll_contact (contact_factory, wocky_porter_get_full_jid (porter)); send_stanza_to_contact (porter, WOCKY_CONTACT (self_contact), stanza); g_object_unref (self_contact); g_list_free (contacts); g_free (node); } static gboolean get_pubsub_child_node (WockyStanza *reply, const gchar *pubsub_ns, const gchar *child_name, WockyNodeTree **child_out, GError **error) { WockyNode *n; g_return_val_if_fail (reply != NULL, FALSE); n = wocky_node_get_child_ns ( wocky_stanza_get_top_node (reply), "pubsub", pubsub_ns); if (n == NULL) { g_set_error (error, WOCKY_PUBSUB_SERVICE_ERROR, WOCKY_PUBSUB_SERVICE_ERROR_WRONG_REPLY, "Reply doesn't contain <pubsub/> node"); return FALSE; } n = wocky_node_get_child (n, child_name); if (n == NULL) { g_set_error (error, WOCKY_PUBSUB_SERVICE_ERROR, WOCKY_PUBSUB_SERVICE_ERROR_WRONG_REPLY, "Reply doesn't contain <%s/> node", child_name); return FALSE; } if (child_out != NULL) *child_out = wocky_node_tree_new_from_node (n); return TRUE; } static gboolean wocky_pubsub_distill_iq_reply_internal (GObject *source, GAsyncResult *res, const gchar *pubsub_ns, const gchar *child_name, gboolean body_optional, WockyNodeTree **child_out, GError **error) { WockyStanza *reply; gboolean ret = FALSE; if (child_out != NULL) *child_out = NULL; /* Superlative news out of the 00:04 to Cambridge: earlier today, an * asynchronous method call announced its plans to bring a node to The * People's Republic of Wocky. */ reply = wocky_porter_send_iq_finish (WOCKY_PORTER (source), res, error); if (reply != NULL) { if (!wocky_stanza_extract_errors (reply, NULL, error, NULL, NULL)) { if (pubsub_ns == NULL) ret = TRUE; else ret = wocky_pubsub_distill_stanza (reply, pubsub_ns, child_name, body_optional, child_out, error); } g_object_unref (reply); } return ret; } /** * wocky_pubsub_distill_stanza: * @result: an iq type='result' * @pubsub_ns: the namespace of the <pubsub/> node expected in this reply * (such as #WOCKY_XMPP_NS_PUBSUB) * @child_name: the name of the child of <pubsub/> expected in this reply * (such as "subscriptions") * @body_optional: If %TRUE, the child being absent is not considered an error * @child_out: location at which to store a reference to the node tree at * @child_name, if it is found, or to be set to %NULL if it is not. * @error: location at which to store an error if the child node is not found * and @body_optional is %FALSE * * Helper function to extract a particular pubsub child node from a reply, if * it is present. If @body_optional is %FALSE, the * <pubsub><@child_name/></pubsub> tree being absent is not * considered an error: @child_out is set to %NULL and the function returns * %TRUE. * * If you are happy to delegate calling wocky_porter_send_iq_finish() and * extracting stanza errors, you would probably be better served by one of * wocky_pubsub_distill_iq_reply() or * wocky_pubsub_distill_ambivalent_iq_reply(). * * Returns: %TRUE if the child was found or was optional; %FALSE with @error * set otherwise. */ gboolean wocky_pubsub_distill_stanza (WockyStanza *result, const gchar *pubsub_ns, const gchar *child_name, gboolean body_optional, WockyNodeTree **child_out, GError **error) { g_return_val_if_fail (pubsub_ns != NULL, FALSE); g_return_val_if_fail (child_name != NULL, FALSE); if (child_out != NULL) *child_out = NULL; /* A force of a thousand function calls will anchor the node to * a resplendent out parameter modeled on the Dear Leader's hand. */ if (get_pubsub_child_node (result, pubsub_ns, child_name, child_out, error)) { /* The People's Great and Harmonious Node Pointer of Peter * Saint-Andre will conclude the most astonishing stanza breakdown * ever witnessed by man. */ return TRUE; } else if (body_optional) { /* “The stanza is perfect. We have already succeeded.” */ g_clear_error (error); return TRUE; } else { /* Meanwhile, the American president today revealed himself to be a * lizard. */ return FALSE; } } /** * wocky_pubsub_distill_iq_reply: * @source: a #WockyPorter instance * @res: a result passed to the callback for wocky_porter_send_iq_async() * @pubsub_ns: the namespace of the <pubsub/> node expected in this reply * (such as #WOCKY_XMPP_NS_PUBSUB), or %NULL if one is not expected * @child_name: the name of the child of <pubsub/> expected in this reply * (such as "subscriptions"); ignored if @pubsub_ns is %NULL * @child_out: location at which to store a reference to the node tree at * @child_name, or %NULL if you don't need it. * @error: location at which to store an error if the call to * wocky_porter_send_iq_async() returned an error, or if the reply was * an error * * Helper function to finish a wocky_porter_send_iq_async() operation * and extract a particular pubsub child from the resulting reply, if needed. * * Returns: %TRUE if the desired pubsub child was found; %FALSE if * sending the IQ failed, the reply had type='error', or the * pubsub child was not found, with @error set appropriately. */ gboolean wocky_pubsub_distill_iq_reply (GObject *source, GAsyncResult *res, const gchar *pubsub_ns, const gchar *child_name, WockyNodeTree **child_out, GError **error) { return wocky_pubsub_distill_iq_reply_internal (source, res, pubsub_ns, child_name, FALSE, child_out, error); } /** * wocky_pubsub_distill_void_iq_reply: * @source: a #WockyPorter instance * @res: a result passed to the callback for wocky_porter_send_iq_async() * @error: location at which to store an error if the call to * wocky_porter_send_iq_async() returned an error, or if the reply was * an error * * Helper function to finish a wocky_porter_send_iq_async() operation where no * pubsub child is expected in the resulting reply. * * Returns: %TRUE if the IQ was a success; %FALSE if * sending the IQ failed or the reply had type='error', * with @error set appropriately. */ gboolean wocky_pubsub_distill_void_iq_reply (GObject *source, GAsyncResult *res, GError **error) { return wocky_pubsub_distill_iq_reply_internal (source, res, NULL, NULL, TRUE, NULL, error); } /** * wocky_pubsub_distill_ambivalent_iq_reply: * @source: a #WockyPorter instance * @res: a result passed to the callback for wocky_porter_send_iq_async() * @pubsub_ns: the namespace of the <pubsub/> node accepted in this reply * (such as #WOCKY_XMPP_NS_PUBSUB) * @child_name: the name of the child of <pubsub/> accepted in this reply * (such as "subscriptions") * @child_out: location at which to store a reference to the node tree at * @child_name, if it is found, or to be set to %NULL if it is not * found * @error: location at which to store an error if the call to * wocky_porter_send_iq_async() returned an error, or if the reply was * an error * * Helper function to finish a wocky_porter_send_iq_async() operation * and extract a particular pubsub child from the resulting reply, if it is * present. This is like wocky_pubsub_distill_iq_reply(), but is ambivalent as * to whether the <pubsub/> structure has to be included. * * Returns: %TRUE if the IQ was a success; %FALSE if * sending the IQ failed or the reply had type='error', * with @error set appropriately. */ gboolean wocky_pubsub_distill_ambivalent_iq_reply (GObject *source, GAsyncResult *res, const gchar *pubsub_ns, const gchar *child_name, WockyNodeTree **child_out, GError **error) { return wocky_pubsub_distill_iq_reply_internal (source, res, pubsub_ns, child_name, TRUE, child_out, error); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-debug-internal.h0000664000175000017500000000406112212322440026230 0ustar00cassidycassidy00000000000000#if !defined (WOCKY_COMPILATION) # error "This is an internal header." #endif #ifndef WOCKY_DEBUG_INTERNAL_H #define WOCKY_DEBUG_INTERNAL_H #include "config.h" #include #include "wocky-debug.h" #include "wocky-stanza.h" G_BEGIN_DECLS #ifdef ENABLE_DEBUG void wocky_debug_set_flags_from_env (void); gboolean wocky_debug_flag_is_set (WockyDebugFlags flag); void wocky_debug_valist (WockyDebugFlags flag, const gchar *format, va_list args); void wocky_debug (WockyDebugFlags flag, const gchar *format, ...) G_GNUC_PRINTF (2, 3); void wocky_debug_stanza (WockyDebugFlags flag, WockyStanza *stanza, const gchar *format, ...) G_GNUC_PRINTF (3, 4); void wocky_debug_node_tree (WockyDebugFlags flag, WockyNodeTree *tree, const gchar *format, ...) G_GNUC_PRINTF (3, 4); void wocky_debug_node (WockyDebugFlags flag, WockyNode *node, const gchar *format, ...) G_GNUC_PRINTF (3, 4); #ifdef WOCKY_DEBUG_FLAG #define DEBUG(format, ...) \ wocky_debug (WOCKY_DEBUG_FLAG, "%s: %s: " format, G_STRFUNC, G_STRLOC, \ ##__VA_ARGS__) #define DEBUG_STANZA(stanza, format, ...) \ wocky_debug_stanza (WOCKY_DEBUG_FLAG, stanza, "%s: " format, G_STRFUNC,\ ##__VA_ARGS__) #define DEBUG_NODE_TREE(tree, format, ...) \ wocky_debug_node_tree (WOCKY_DEBUG_FLAG, tree, "%s: " format, G_STRFUNC,\ ##__VA_ARGS__) #define DEBUG_NODE(node, format, ...) \ wocky_debug_node (WOCKY_DEBUG_FLAG, node, "%s: " format, G_STRFUNC,\ ##__VA_ARGS__) #define DEBUGGING wocky_debug_flag_is_set(WOCKY_DEBUG_FLAG) #endif /* WOCKY_DEBUG_FLAG */ #else /* ENABLE_DEBUG */ #ifdef WOCKY_DEBUG_FLAG static inline void DEBUG ( const gchar *format, ...) { /* blah blah blah */ } static inline void DEBUG_STANZA (WockyStanza *stanza, const gchar *format, ...) { } static inline void DEBUG_NODE_TREE (WockyNodeTree *tree, const gchar *format, ...) { } static inline void DEBUG_NODE (WockyNode *node, const gchar *format, ...) { } #define DEBUGGING 0 #endif /* WOCKY_DEBUG_FLAG */ #endif /* ENABLE_DEBUG */ G_END_DECLS #endif telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-node-private.h0000664000175000017500000000231511720661341025736 0ustar00cassidycassidy00000000000000/* * wocky-node-private.h - Private header for dealing with Wocky xmpp nodes * Copyright (C) 2010 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_COMPILATION) # error "This is an internal header." #endif #ifndef __WOCKY__NODE_PRIVATE_H__ #define __WOCKY__NODE_PRIVATE_H__ #include #include G_BEGIN_DECLS WockyNode *_wocky_node_copy (WockyNode *node); G_END_DECLS #endif /* #ifndef __WOCKY_NODE__PRIVATE_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-sasl-auth.h0000664000175000017500000000575011720661341025250 0ustar00cassidycassidy00000000000000/* * wocky-sasl-auth.h - Header for WockySaslAuth * Copyright (C) 2006 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_SASL_AUTH_H__ #define __WOCKY_SASL_AUTH_H__ #include #include #include "wocky-stanza.h" #include "wocky-xmpp-connection.h" #include "wocky-auth-registry.h" G_BEGIN_DECLS typedef struct _WockySaslAuth WockySaslAuth; /** * WockySaslAuthClass: * * The class of a #WockySaslAuth. */ typedef struct _WockySaslAuthClass WockySaslAuthClass; typedef struct _WockySaslAuthPrivate WockySaslAuthPrivate; struct _WockySaslAuthClass { /**/ GObjectClass parent_class; }; struct _WockySaslAuth { /**/ GObject parent; WockySaslAuthPrivate *priv; }; GType wocky_sasl_auth_get_type (void); /* TYPE MACROS */ #define WOCKY_TYPE_SASL_AUTH \ (wocky_sasl_auth_get_type ()) #define WOCKY_SASL_AUTH(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_SASL_AUTH, WockySaslAuth)) #define WOCKY_SASL_AUTH_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_SASL_AUTH, WockySaslAuthClass)) #define WOCKY_IS_SASL_AUTH(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_SASL_AUTH)) #define WOCKY_IS_SASL_AUTH_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_SASL_AUTH)) #define WOCKY_SASL_AUTH_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_SASL_AUTH, WockySaslAuthClass)) WockySaslAuth *wocky_sasl_auth_new (const gchar *server, const gchar *username, const gchar *password, WockyXmppConnection *connection, WockyAuthRegistry *auth_registry); void wocky_sasl_auth_add_handler (WockySaslAuth *sasl, WockyAuthHandler *handler); void wocky_sasl_auth_authenticate_async (WockySaslAuth *sasl, WockyStanza *features, gboolean allow_plain, gboolean is_secure, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_sasl_auth_authenticate_finish (WockySaslAuth *sasl, GAsyncResult *result, GError **error); void wocky_sasl_auth_add_handler (WockySaslAuth *auth, WockyAuthHandler *handler); G_END_DECLS #endif /* #ifndef __WOCKY_SASL_AUTH_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-node-tree.c0000664000175000017500000001240212005516162025211 0ustar00cassidycassidy00000000000000/* * wocky-node-tree.c - Source for WockyNodeTree * Copyright (C) 2006-2010 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "wocky-node-tree.h" #include "wocky-node-private.h" G_DEFINE_TYPE(WockyNodeTree, wocky_node_tree, G_TYPE_OBJECT) /* properties */ enum { PROP_TOP_NODE = 1, }; struct _WockyNodeTreePrivate { gboolean dispose_has_run; WockyNode *node; }; static void wocky_node_tree_init (WockyNodeTree *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_NODE_TREE, WockyNodeTreePrivate); } static void wocky_node_tree_dispose (GObject *object); static void wocky_node_tree_finalize (GObject *object); static void wocky_node_tree_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyNodeTree *self = WOCKY_NODE_TREE (object); switch (property_id) { case PROP_TOP_NODE: self->priv->node = g_value_get_pointer (value); g_warn_if_fail (self->priv->node != NULL); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_node_tree_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyNodeTree *self = WOCKY_NODE_TREE (object); switch (property_id) { case PROP_TOP_NODE: g_value_set_pointer (value, self->priv->node); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_node_tree_class_init (WockyNodeTreeClass *wocky_node_tree_class) { GObjectClass *object_class = G_OBJECT_CLASS (wocky_node_tree_class); GParamSpec *param_spec; g_type_class_add_private (wocky_node_tree_class, sizeof (WockyNodeTreePrivate)); object_class->dispose = wocky_node_tree_dispose; object_class->finalize = wocky_node_tree_finalize; object_class->set_property = wocky_node_tree_set_property; object_class->get_property = wocky_node_tree_get_property; param_spec = g_param_spec_pointer ("top-node", "top-node", "The topmost node of the node-tree", G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_TOP_NODE, param_spec); } void wocky_node_tree_dispose (GObject *object) { WockyNodeTree *self = WOCKY_NODE_TREE (object); WockyNodeTreePrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; /* release any references held by the object here */ if (G_OBJECT_CLASS (wocky_node_tree_parent_class)->dispose) G_OBJECT_CLASS (wocky_node_tree_parent_class)->dispose (object); } void wocky_node_tree_finalize (GObject *object) { WockyNodeTree *self = WOCKY_NODE_TREE (object); /* free any data held directly by the object here */ wocky_node_free (self->priv->node); G_OBJECT_CLASS (wocky_node_tree_parent_class)->finalize (object); } /** * wocky_node_tree_new: * @name: The name of the toplevel node * @ns: The namespace of the toplevel node * @...: the description of the node tree to build, * terminated with %NULL * * Build a node-tree from a list of arguments. * Example: * * * wocky_node_tree_new ("html", "http://www.w3.org/1999/xhtml", * '(', "body", '@', "textcolor", "red", * '$', "Wocky wooo", * ')', * NULL); * * * Returns: a new node-tree object */ WockyNodeTree * wocky_node_tree_new (const gchar *name, const gchar *ns, ...) { WockyNodeTree *tree; va_list va; va_start (va, ns); tree = wocky_node_tree_new_va (name, ns, va); va_end (va); return tree; } WockyNodeTree * wocky_node_tree_new_va (const gchar *name, const char *ns, va_list va) { WockyNode *top; g_return_val_if_fail (name != NULL, NULL); g_return_val_if_fail (ns != NULL, NULL); top = wocky_node_new (name, ns); wocky_node_add_build_va (top, va); return g_object_new (WOCKY_TYPE_NODE_TREE, "top-node", top, NULL); } /** * wocky_node_tree_new_from_node: * @node: The node to copy * * Build a new WockyNodeTree that contains a copy of the given node. * * Returns: a new node-tree object */ WockyNodeTree * wocky_node_tree_new_from_node (WockyNode *node) { WockyNode *top = _wocky_node_copy (node); return g_object_new (WOCKY_TYPE_NODE_TREE, "top-node", top, NULL); } WockyNode * wocky_node_tree_get_top_node (WockyNodeTree *self) { return self->priv->node; } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-contact-factory.c0000664000175000017500000003324411720661341026441 0ustar00cassidycassidy00000000000000/* * wocky-contact-factory.c - Source for WockyContactFactory * Copyright (C) 2009 Collabora Ltd. * @author Guillaume Desmottes * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** * SECTION: wocky-contact-factory * @title: WockyContactFactory * @short_description: creates and looks up #WockyContact objects * @include: wocky/wocky-contact-factory.h * * Provides a way to create #WockyContact objects. The objects created * this way are cached by the factory and you can eventually look them up * without creating them again. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-contact-factory.h" #include #include #ifdef HAVE_UNISTD_H # include #endif #include #include #include "wocky-signals-marshal.h" #include "wocky-utils.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_ROSTER #include "wocky-debug-internal.h" G_DEFINE_TYPE (WockyContactFactory, wocky_contact_factory, G_TYPE_OBJECT) #if 0 /* properties */ enum { }; #endif /* signal enum */ enum { BARE_CONTACT_ADDED, RESOURCE_CONTACT_ADDED, LL_CONTACT_ADDED, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL] = {0}; /* private structure */ struct _WockyContactFactoryPrivate { /* bare JID (gchar *) => weak reffed (WockyBareContact *) */ GHashTable *bare_contacts; /* full JID (gchar *) => weak reffed (WockyResourceContact *) */ GHashTable *resource_contacts; /* JID (gchar *) => weak reffed (WockyLLContact *) */ GHashTable *ll_contacts; gboolean dispose_has_run; }; static void wocky_contact_factory_init (WockyContactFactory *self) { WockyContactFactoryPrivate *priv; self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_CONTACT_FACTORY, WockyContactFactoryPrivate); priv = self->priv; priv->bare_contacts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); priv->resource_contacts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); priv->ll_contacts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); } static void wocky_contact_factory_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { switch (property_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_contact_factory_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { switch (property_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_contact_factory_constructed (GObject *object) { } static gboolean remove_contact (gpointer key, gpointer value, gpointer contact) { return value == contact; } /* Called when a WockyBareContact, WockyResourceContact or * WockyLLContact has been disposed so we can remove it from his hash * table. */ static void contact_disposed_cb (gpointer user_data, GObject *contact) { GHashTable *table = (GHashTable *) user_data; g_hash_table_foreach_remove (table, remove_contact, contact); } static void wocky_contact_factory_dispose (GObject *object) { WockyContactFactory *self = WOCKY_CONTACT_FACTORY (object); WockyContactFactoryPrivate *priv = self->priv; GHashTableIter iter; gpointer contact; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; g_hash_table_iter_init (&iter, priv->bare_contacts); while (g_hash_table_iter_next (&iter, NULL, &contact)) { g_object_weak_unref (G_OBJECT (contact), contact_disposed_cb, priv->bare_contacts); } g_hash_table_iter_init (&iter, priv->resource_contacts); while (g_hash_table_iter_next (&iter, NULL, &contact)) { g_object_weak_unref (G_OBJECT (contact), contact_disposed_cb, priv->resource_contacts); } g_hash_table_iter_init (&iter, priv->ll_contacts); while (g_hash_table_iter_next (&iter, NULL, &contact)) { g_object_weak_unref (G_OBJECT (contact), contact_disposed_cb, priv->ll_contacts); } if (G_OBJECT_CLASS (wocky_contact_factory_parent_class)->dispose) G_OBJECT_CLASS (wocky_contact_factory_parent_class)->dispose (object); } static void wocky_contact_factory_finalize (GObject *object) { WockyContactFactory *self = WOCKY_CONTACT_FACTORY (object); WockyContactFactoryPrivate *priv = self->priv; g_hash_table_unref (priv->bare_contacts); g_hash_table_unref (priv->resource_contacts); g_hash_table_unref (priv->ll_contacts); G_OBJECT_CLASS (wocky_contact_factory_parent_class)->finalize (object); } static void wocky_contact_factory_class_init ( WockyContactFactoryClass *wocky_contact_factory_class) { GObjectClass *object_class = G_OBJECT_CLASS (wocky_contact_factory_class); g_type_class_add_private (wocky_contact_factory_class, sizeof (WockyContactFactoryPrivate)); object_class->constructed = wocky_contact_factory_constructed; object_class->set_property = wocky_contact_factory_set_property; object_class->get_property = wocky_contact_factory_get_property; object_class->dispose = wocky_contact_factory_dispose; object_class->finalize = wocky_contact_factory_finalize; signals[BARE_CONTACT_ADDED] = g_signal_new ("bare-contact-added", G_OBJECT_CLASS_TYPE (wocky_contact_factory_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); signals[RESOURCE_CONTACT_ADDED] = g_signal_new ("resource-contact-added", G_OBJECT_CLASS_TYPE (wocky_contact_factory_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); signals[LL_CONTACT_ADDED] = g_signal_new ("ll-contact-added", G_OBJECT_CLASS_TYPE (wocky_contact_factory_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); } /** * wocky_contact_factory_new: * * Convenience function to create a new #WockyContactFactory object. * * Returns: a newly created instance of #WockyContactFactory */ WockyContactFactory * wocky_contact_factory_new (void) { return g_object_new (WOCKY_TYPE_CONTACT_FACTORY, NULL); } /** * wocky_contact_factory_ensure_bare_contact: * @factory: a #WockyContactFactory instance * @bare_jid: the JID of a bare contact * * Returns an instance of #WockyBareContact for @bare_jid. The factory cache * is used, but if the contact is not found in the cache, a new * #WockyBareContact is created and cached for future use. * * Returns: a new reference to a #WockyBareContact instance, which the caller * is expected to release with g_object_unref() after use. */ WockyBareContact * wocky_contact_factory_ensure_bare_contact (WockyContactFactory *self, const gchar *bare_jid) { WockyContactFactoryPrivate *priv = self->priv; WockyBareContact *contact; contact = g_hash_table_lookup (priv->bare_contacts, bare_jid); if (contact != NULL) return g_object_ref (contact); contact = wocky_bare_contact_new (bare_jid); g_object_weak_ref (G_OBJECT (contact), contact_disposed_cb, priv->bare_contacts); g_hash_table_insert (priv->bare_contacts, g_strdup (bare_jid), contact); g_signal_emit (self, signals[BARE_CONTACT_ADDED], 0, contact); return contact; } /** * wocky_contact_factory_lookup_bare_contact: * @factory: a #WockyContactFactory instance * @bare_jid: the JID of a bare contact * * Looks up if there's a #WockyBareContact for @bare_jid in the cache, and * returns it if it's found. * * Returns: a borrowed #WockyBareContact instance (which the caller should * reference with g_object_ref() if it will be kept), or %NULL if the * contact is not found. */ WockyBareContact * wocky_contact_factory_lookup_bare_contact (WockyContactFactory *self, const gchar *bare_jid) { WockyContactFactoryPrivate *priv = self->priv; return g_hash_table_lookup (priv->bare_contacts, bare_jid); } /** * wocky_contact_factory_ensure_resource_contact: * @factory: a #WockyContactFactory instance * @full_jid: the full JID of a resource * * Returns an instance of #WockyResourceContact for @full_jid. * The factory cache is used, but if the resource is not found in the cache, * a new #WockyResourceContact is created and cached for future use. * * Returns: a new reference to a #WockyResourceContact instance, which the * caller is expected to release with g_object_unref() after use. */ WockyResourceContact * wocky_contact_factory_ensure_resource_contact (WockyContactFactory *self, const gchar *full_jid) { WockyContactFactoryPrivate *priv = self->priv; WockyBareContact *bare; WockyResourceContact *contact; gchar *node, *domain, *resource, *bare_jid; contact = g_hash_table_lookup (priv->resource_contacts, full_jid); if (contact != NULL) return g_object_ref (contact); wocky_decode_jid (full_jid, &node, &domain, &resource); bare_jid = g_strdup_printf ("%s@%s", node, domain); bare = wocky_contact_factory_ensure_bare_contact (self, bare_jid); contact = wocky_resource_contact_new (bare, resource); g_object_weak_ref (G_OBJECT (contact), contact_disposed_cb, priv->resource_contacts); g_hash_table_insert (priv->resource_contacts, g_strdup (full_jid), contact); wocky_bare_contact_add_resource (bare, contact); g_free (node); g_free (domain); g_free (resource); g_free (bare_jid); g_object_unref (bare); g_signal_emit (self, signals[RESOURCE_CONTACT_ADDED], 0, contact); return contact; } /** * wocky_contact_factory_lookup_resource_contact: * @factory: a #WockyContactFactory instance * @full_jid: the full JID of a resource * * Looks up if there's a #WockyResourceContact for @full_jid in the cache, and * returns it if it's found. * * Returns: a borrowed #WockyResourceContact instance (which the caller should * reference with g_object_ref() if it will be kept), or %NULL if the * contact is not found. */ WockyResourceContact * wocky_contact_factory_lookup_resource_contact (WockyContactFactory *self, const gchar *full_jid) { WockyContactFactoryPrivate *priv = self->priv; return g_hash_table_lookup (priv->resource_contacts, full_jid); } /** * wocky_contact_factory_ensure_ll_contact: * @factory: a #WockyContactFactory instance * @jid: the JID of a contact * * Returns an instance of #WockyLLContact for @jid. * The factory cache is used, but if the contact is not found in the cache, * a new #WockyLLContact is created and cached for future use. * * Returns: a new reference to a #WockyLLContact instance, which the * caller is expected to release with g_object_unref() after use. */ WockyLLContact * wocky_contact_factory_ensure_ll_contact (WockyContactFactory *self, const gchar *jid) { WockyContactFactoryPrivate *priv = self->priv; WockyLLContact *contact; g_return_val_if_fail (jid != NULL, NULL); contact = g_hash_table_lookup (priv->ll_contacts, jid); if (contact != NULL) return g_object_ref (contact); contact = wocky_ll_contact_new (jid); g_object_weak_ref (G_OBJECT (contact), contact_disposed_cb, priv->ll_contacts); g_hash_table_insert (priv->ll_contacts, g_strdup (jid), contact); g_signal_emit (self, signals[LL_CONTACT_ADDED], 0, contact); return contact; } /** * wocky_contact_factory_lookup_ll_contact: * @factory: a #WockyContactFactory instance * @jid: the JID of a contact * * Looks up if there's a #WockyLLContact for @jid in the cache, and * returns it if it's found. * * Returns: a borrowed #WockyLLContact instance (which the caller should * reference with g_object_ref() if it will be kept), or %NULL if the * contact is not found. */ WockyLLContact * wocky_contact_factory_lookup_ll_contact (WockyContactFactory *self, const gchar *jid) { WockyContactFactoryPrivate *priv = self->priv; return g_hash_table_lookup (priv->ll_contacts, jid); } /** * wocky_contact_factory_add_ll_contact: * @factory: a #WockyContactFactory instance * @contact: a #WockyLLContact * * Adds @contact to the contact factory. */ void wocky_contact_factory_add_ll_contact (WockyContactFactory *self, WockyLLContact *contact) { WockyContactFactoryPrivate *priv = self->priv; gchar *jid = wocky_contact_dup_jid (WOCKY_CONTACT (contact)); WockyLLContact *old_contact = g_hash_table_lookup (priv->ll_contacts, jid); if (old_contact == contact) { g_free (jid); return; } if (old_contact != NULL) { g_object_weak_unref (G_OBJECT (old_contact), contact_disposed_cb, priv->ll_contacts); } g_object_weak_ref (G_OBJECT (contact), contact_disposed_cb, priv->ll_contacts); g_hash_table_insert (priv->ll_contacts, jid, contact); g_signal_emit (self, signals[LL_CONTACT_ADDED], 0, contact); } /** * wocky_contact_factory_get_ll_contacts: * @factory: a #WockyContactFactory instance * * * * Returns: a newly allocated #GList of #WockyLLContacts which * should be freed using g_list_free(). */ GList * wocky_contact_factory_get_ll_contacts (WockyContactFactory *self) { return g_hash_table_get_values (self->priv->ll_contacts); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-debug.c0000664000175000017500000000764412212322440024423 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "wocky-debug-internal.h" #ifdef ENABLE_DEBUG static WockyDebugFlags flags = 0; static gboolean initialized = FALSE; static GDebugKey keys[] = { { "transport", WOCKY_DEBUG_TRANSPORT }, { "net", WOCKY_DEBUG_NET }, { "xmpp", WOCKY_DEBUG_XMPP }, { "xmpp-reader", WOCKY_DEBUG_XMPP_READER }, { "xmpp-writer", WOCKY_DEBUG_XMPP_WRITER }, { "auth", WOCKY_DEBUG_AUTH }, { "ssl", WOCKY_DEBUG_SSL }, { "rmulticast", WOCKY_DEBUG_RMULTICAST }, { "rmulticast-sender", WOCKY_DEBUG_RMULTICAST_SENDER }, { "muc-connection", WOCKY_DEBUG_MUC_CONNECTION }, { "bytestream", WOCKY_DEBUG_BYTESTREAM }, { "ft", WOCKY_DEBUG_FILE_TRANSFER }, { "porter", WOCKY_DEBUG_PORTER }, { "connector", WOCKY_DEBUG_CONNECTOR }, { "roster", WOCKY_DEBUG_ROSTER }, { "tls", WOCKY_DEBUG_TLS }, { "pubsub", WOCKY_DEBUG_PUBSUB }, { "dataform", WOCKY_DEBUG_DATA_FORM }, { "ping", WOCKY_DEBUG_PING }, { "heartbeat", WOCKY_DEBUG_HEARTBEAT }, { "presence", WOCKY_DEBUG_PRESENCE }, { "connection-factory",WOCKY_DEBUG_CONNECTION_FACTORY}, { "media", WOCKY_DEBUG_JINGLE }, { 0, }, }; void wocky_debug_set_flags_from_env () { guint nkeys; const gchar *flags_string; for (nkeys = 0; keys[nkeys].value; nkeys++); flags_string = g_getenv ("WOCKY_DEBUG"); if (flags_string) wocky_debug_set_flags (g_parse_debug_string (flags_string, keys, nkeys)); initialized = TRUE; } void wocky_debug_set_flags (WockyDebugFlags new_flags) { flags |= new_flags; initialized = TRUE; } gboolean wocky_debug_flag_is_set (WockyDebugFlags flag) { return flag & flags; } void wocky_debug (WockyDebugFlags flag, const gchar *format, ...) { va_list args; va_start (args, format); wocky_debug_valist (flag, format, args); va_end (args); } void wocky_debug_valist (WockyDebugFlags flag, const gchar *format, va_list args) { if (G_UNLIKELY(!initialized)) wocky_debug_set_flags_from_env (); if (flag & flags) g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format, args); } static void wocky_debug_node_va (WockyDebugFlags flag, WockyNode *node, const gchar *format, va_list args) { if (G_UNLIKELY(!initialized)) wocky_debug_set_flags_from_env (); if (flag & flags) { gchar *msg, *node_str; msg = g_strdup_vprintf (format, args); node_str = wocky_node_to_string (node); g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "%s\n%s", msg, node_str); g_free (msg); g_free (node_str); } } void wocky_debug_node (WockyDebugFlags flag, WockyNode *node, const gchar *format, ...) { va_list args; va_start (args, format); wocky_debug_node_va (flag, node, format, args); va_end (args); } static void wocky_debug_node_tree_va (WockyDebugFlags flag, WockyNodeTree *tree, const gchar *format, va_list args) { wocky_debug_node_va (flag, wocky_node_tree_get_top_node (tree), format, args); } void wocky_debug_node_tree (WockyDebugFlags flag, WockyNodeTree *tree, const gchar *format, ...) { va_list args; va_start (args, format); wocky_debug_node_tree_va (flag, tree, format, args); va_end (args); } void wocky_debug_stanza (WockyDebugFlags flag, WockyStanza *stanza, const gchar *format, ...) { va_list args; va_start (args, format); wocky_debug_node_tree_va (flag, (WockyNodeTree *) stanza, format, args); va_end (args); } #else /* !ENABLE_DEBUG */ void wocky_debug_set_flags (WockyDebugFlags flags) { } #endif telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-node.c0000664000175000017500000011621012212322440024250 0ustar00cassidycassidy00000000000000/* * wocky-node.c - Code for Wocky xmpp nodes * Copyright (C) 2006-2010 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "wocky-node.h" #include "wocky-node-private.h" #include "wocky-node-tree.h" #include "wocky-utils.h" #include "wocky-namespaces.h" /** * SECTION: wocky-node * @title: WockyNode * @short_description: representation of a XMPP node * @include: wocky/wocky-node.h * * Low level representation of a XMPP node. Provides ways to set various * parameters on the node, such as content, language, namespaces and prefixes. * It also offers methods to lookup children of a node. */ typedef struct { gchar *key; gchar *value; gchar *prefix; GQuark ns; } Attribute; typedef struct { const gchar *key; GQuark ns; } Tuple; typedef struct { const gchar *ns_urn; gchar *prefix; GQuark ns; } NSPrefix; static NSPrefix default_attr_ns_prefixes[] = { { WOCKY_GOOGLE_NS_AUTH, "ga" }, { NULL, NULL } }; static GHashTable *user_ns_prefixes = NULL; static GHashTable *default_ns_prefixes = NULL; /* Do a strndup operation, but at the same time replace all characters that * aren't valid according to g_utf8_validate by � */ static gchar * strndup_make_valid (const gchar *str, gssize len) { const gchar *remainder = str; GString *result; const gchar *endp; gssize left = len; /* Simplify things by always keeping track of the string lenght */ if (left < 0) left = strlen (remainder); result = g_string_sized_new (len); while (!g_utf8_validate (remainder, left, &endp)) { g_string_append_len (result, remainder, endp - remainder); /* append U+FFFD REPLACEMENT CHARACTER */ g_string_append (result, "\357\277\275"); /* left, minus the valid part of the string */ left -= (endp - remainder); remainder = g_utf8_find_next_char (endp, endp + left); /* left, minus the skipped part, if there is no next utf8 character, * nothing is left */ if (remainder == NULL) left = 0; else if (left > 0) left -= (remainder - endp); } g_string_append_len (result, remainder, left); return g_string_free (result, FALSE); } static gchar * strndup_validated (const gchar *str, gssize len) { if (str == NULL) return NULL; /* Fast path, string happily validates, simple copy */ if (G_LIKELY (g_utf8_validate (str, len, NULL))) { if (len < 0) return g_strdup (str); else return g_strndup (str, len); } /* slow path, string doesn't validate.. */ return strndup_make_valid (str, len); } static gchar * concat_validated (const gchar *s1, const gchar *s2, gssize s2_size) { gchar *result; gssize s1_size; /* data to be freed after use if needed */ const gchar *to_free = NULL; /* concatting to nothing, iotw, strndup :) */ if (s1 == NULL) return strndup_validated (s2, s2_size); s1_size = strlen (s1); if (s2_size < 0) s2_size = strlen (s2); if (G_UNLIKELY (!g_utf8_validate (s2, s2_size, NULL))) { /* Make a validated copy we will free later on. Making a copy to just * concat and then free isn't the most efficient way, but at this point * we're out of the fast-path anyway */ to_free = s2 = strndup_make_valid (s2, s2_size); s2_size = strlen (s2); } result = g_malloc0 (s1_size + s2_size + 1); memcpy (result, s1, s1_size); memcpy (result + s1_size, s2, s2_size); g_free ((gchar *) to_free); return result; } static WockyNode * new_node (const char *name, GQuark ns) { WockyNode *result; g_return_val_if_fail (name != NULL, NULL); g_return_val_if_fail (ns != 0, NULL); result = g_slice_new0 (WockyNode); result->name = strndup_validated (name, -1); result->ns = ns; return result; } /** * wocky_node_new: * @name: the node's name (may not be NULL) * @ns: the nodes namespace (may not be NULL) * * Convenience function which creates a #WockyNode and sets its * name to @name. * * Returns: a newly allocated #WockyNode. */ WockyNode * wocky_node_new (const char *name, const gchar *ns) { g_return_val_if_fail (ns != NULL, NULL); return new_node (name, g_quark_from_string (ns)); } static void attribute_free (Attribute *a) { g_free (a->key); g_free (a->value); g_free (a->prefix); g_slice_free (Attribute, a); } /** * wocky_node_free: * @node: a #WockyNode. * * Convenience function that frees the passed in #WockyNode and * all of its children. */ void wocky_node_free (WockyNode *node) { GSList *l; if (node == NULL) { return ; } g_free (node->name); g_free (node->content); g_free (node->language); for (l = node->children; l != NULL ; l = l->next) { wocky_node_free ((WockyNode *) l->data); } g_slist_free (node->children); for (l = node->attributes; l != NULL ; l = l->next) { Attribute *a = (Attribute *) l->data; attribute_free (a); } g_slist_free (node->attributes); g_slice_free (WockyNode, node); } /** * wocky_node_each_attribute: * @node: a #WockyNode * @func: the function to be called on each node's attribute * @user_data: user data to pass to the function * * Calls a function for each attribute of a #WockyNode. */ void wocky_node_each_attribute (WockyNode *node, wocky_node_each_attr_func func, gpointer user_data) { GSList *l; for (l = node->attributes; l != NULL ; l = l->next) { Attribute *a = (Attribute *) l->data; const gchar *ns = g_quark_to_string (a->ns); if (!func (a->key, a->value, a->prefix, ns, user_data)) { return; } } } /** * wocky_node_each_child: * @node: a #WockyNode * @func: the function to be called on each node's child * @user_data: user data to pass to the function * * Calls a function for each child of a #WockyNode. */ void wocky_node_each_child (WockyNode *node, wocky_node_each_child_func func, gpointer user_data) { GSList *l; for (l = node->children; l != NULL ; l = l->next) { WockyNode *n = (WockyNode *) l->data; if (!func (n, user_data)) { return; } } } static gint attribute_compare (gconstpointer a, gconstpointer b) { const Attribute *attr = (const Attribute *)a; const Tuple *target = (const Tuple *)b; if (target->ns != 0 && attr->ns != target->ns) { return 1; } return strcmp (attr->key, target->key); } /** * wocky_node_get_attribute_ns: * @node: a #WockyNode * @key: the attribute name * @ns: the namespace to search within, or %NULL * * Returns the value of an attribute in a #WockyNode, limiting the search * within a specific namespace. If the namespace is %NULL, this is equivalent * to wocky_node_get_attribute(). * * Returns: the value of the attribute @key, or %NULL if @node doesn't * have such attribute in @ns. */ const gchar * wocky_node_get_attribute_ns (WockyNode *node, const gchar *key, const gchar *ns) { GSList *link; Tuple search; search.key = (gchar *) key; search.ns = (ns != NULL ? g_quark_from_string (ns) : 0); link = g_slist_find_custom (node->attributes, &search, attribute_compare); return (link == NULL) ? NULL : ((Attribute *) (link->data))->value; } /** * wocky_node_get_attribute: * @node: a #WockyNode * @key: the attribute name * * Returns the value of an attribute in a #WockyNode. * * Returns: the value of the attribute @key, or %NULL if @node doesn't * have such attribute. */ const gchar * wocky_node_get_attribute (WockyNode *node, const gchar *key) { return wocky_node_get_attribute_ns (node, key, NULL); } /** * wocky_node_set_attribute: * @node: a #WockyNode * @key: the attribute name to set * @value: the value to set * * Sets an attribute in a #WockyNode to a specific value. */ void wocky_node_set_attribute (WockyNode *node, const gchar *key, const gchar *value) { g_assert (value != NULL); wocky_node_set_attribute_n_ns (node, key, value, strlen (value), NULL); } /** * wocky_node_set_attributes: * @node: a #WockyNode * @key: the attribute name to set * @...: pairs of keys and values, terminated by %NULL * * Sets attributes in a #WockyNode to specific values. */ void wocky_node_set_attributes (WockyNode *node, const gchar *key, ...) { va_list args; g_return_if_fail (key != NULL); va_start (args, key); while (key != NULL) { const gchar *value; value = (const gchar *) va_arg (args, gchar *); wocky_node_set_attribute (node, key, value); key = (const gchar *) va_arg (args, gchar *); } va_end (args); } /** * wocky_node_set_attribute_ns: * @node: a #WockyNode * @key: the attribute name to set * @value: the value to set * @ns: a namespace, or %NULL * * Sets an attribute in a #WockyNode, within a specific namespace. * If the namespace is %NULL, this is equivalent to * wocky_node_set_attribute(). */ void wocky_node_set_attribute_ns (WockyNode *node, const gchar *key, const gchar *value, const gchar *ns) { wocky_node_set_attribute_n_ns (node, key, value, strlen (value), ns); } static NSPrefix * ns_prefix_new (const gchar *urn, GQuark ns, const gchar *prefix) { NSPrefix *nsp = g_slice_new0 (NSPrefix); nsp->ns_urn = urn; nsp->prefix = strndup_validated (prefix, -1); nsp->ns = ns; return nsp; } static void ns_prefix_free (NSPrefix *nsp) { g_free (nsp->prefix); g_slice_free (NSPrefix, nsp); } static GHashTable * _init_prefix_table (void) { /* do NOT use the astonishingly poorly named g_int_hash here */ /* it most emphatically does NOT do what it says on the tin */ return g_hash_table_new_full (g_direct_hash, /* quarks are uint32s */ g_direct_equal, /* ibid */ NULL, /* cannot free quarks */ (GDestroyNotify)ns_prefix_free); } /* convert the NS URN Quark to a base-26 number represented as a * * lowercase a-z digit string (aa, ab, ac, ad ... etc) * * then prepend a string ("wocky-") to make the attr ns prefix */ static gchar * _generate_ns_prefix (GQuark ns) { GString *prefix = g_string_new ("wocky-"); int p = ns; /* actually, I think we might end up with the digits in le order * * having re-read the code, but that doesn't actually matter. */ while (p > 0) { guchar x = (p % 26); p -= x; p /= 26; x += 'a'; g_string_append_c (prefix, x); } return g_string_free (prefix, FALSE); } static void _init_user_prefix_table (void) { if (user_ns_prefixes == NULL) user_ns_prefixes = _init_prefix_table (); } static const NSPrefix * _add_prefix_to_table (GHashTable *table, GQuark ns, const gchar *urn, const gchar *prefix) { NSPrefix *nsp = ns_prefix_new (urn, ns, prefix); g_hash_table_insert (table, GINT_TO_POINTER (ns), nsp); return nsp; } static void _init_default_prefix_table (void) { int i; if (default_ns_prefixes != NULL) return; default_ns_prefixes = _init_prefix_table (); for (i = 0; default_attr_ns_prefixes[i].ns_urn != NULL; i++) { const gchar *urn = default_attr_ns_prefixes[i].ns_urn; GQuark ns = g_quark_from_string (urn); gchar *prefix = _generate_ns_prefix (ns); _add_prefix_to_table (default_ns_prefixes, ns, urn, prefix); g_free (prefix); } } static const gchar * _attribute_ns_get_prefix (GQuark ns, const gchar *urn) { const NSPrefix *nsp = NULL; gchar *prefix; /* check user-registered explicit prefixes for this namespace */ nsp = g_hash_table_lookup (user_ns_prefixes, GINT_TO_POINTER (ns)); if (nsp != NULL) return nsp->prefix; /* check any built-in explicit prefixes for this namespace */ nsp = g_hash_table_lookup (default_ns_prefixes, GINT_TO_POINTER (ns)); if (nsp != NULL) return nsp->prefix; /* ok, there was no registered prefix - generate and register a prefix */ /* initialise the user prefix table here if we need to */ prefix = _generate_ns_prefix (ns); nsp = _add_prefix_to_table (user_ns_prefixes, ns, urn, prefix); g_free (prefix); return nsp->prefix; } /** * wocky_node_attribute_ns_get_prefix_from_quark: * @ns: a quark corresponding to an XML namespace URN * * Gets the prefix of the namespace identified by the quark. * * Returns: a string containing the prefix of the namespace @ns. */ const gchar * wocky_node_attribute_ns_get_prefix_from_quark (GQuark ns) { const gchar *urn; if (ns == 0) return NULL; urn = g_quark_to_string (ns); /* fetch an existing prefix, a default prefix, or a newly allocated one * * in that order of preference */ return _attribute_ns_get_prefix (ns, urn); } /** * wocky_node_attribute_ns_get_prefix_from_urn: * @urn: a string containing an URN * * Gets the prefix of the namespace identified by the URN. * * Returns: a string containing the prefix of the namespace @urn. */ const gchar * wocky_node_attribute_ns_get_prefix_from_urn (const gchar *urn) { GQuark ns; if ((urn == NULL) || (*urn == '\0')) return NULL; ns = g_quark_from_string (urn); /* fetch an existing prefix, a default prefix, or a newly allocated one * * in that order of preference */ return _attribute_ns_get_prefix (ns, urn); } /** * wocky_node_attribute_ns_set_prefix: * @ns: a #GQuark * @prefix: a string containing the desired prefix * * Sets a desired prefix for a namespace. */ void wocky_node_attribute_ns_set_prefix (GQuark ns, const gchar *prefix) { const gchar *urn = g_quark_to_string (ns); /* add/replace user prefix table entry */ _add_prefix_to_table (user_ns_prefixes, ns, urn, prefix); } /** * wocky_node_set_attribute_n_ns: * @node: a #WockyNode * @key: the attribute to set * @value: the value to set * @value_size: the number of bytes of @value to set as a value * @ns: a namespace, or %NULL * * Sets a new attribute to a #WockyNode, with the supplied values. * If the namespace is %NULL, this is equivalent to * wocky_node_set_attribute_n(). */ void wocky_node_set_attribute_n_ns (WockyNode *node, const gchar *key, const gchar *value, gsize value_size, const gchar *ns) { Attribute *a = g_slice_new0 (Attribute); GSList *link; Tuple search; a->key = strndup_validated (key, -1); a->value = strndup_validated (value, value_size); a->prefix = g_strdup (wocky_node_attribute_ns_get_prefix_from_urn (ns)); a->ns = (ns != NULL) ? g_quark_from_string (ns) : 0; /* Remove the old attribute if needed */ search.key = a->key; search.ns = a->ns; link = g_slist_find_custom (node->attributes, &search, attribute_compare); if (link != NULL) { Attribute *old = (Attribute *) link->data; attribute_free (old); node->attributes = g_slist_delete_link (node->attributes, link); } node->attributes = g_slist_append (node->attributes, a); } /** * wocky_node_set_attribute_n: * @node: a #WockyNode * @key: the attribute to set * @value: the value to set * @value_size: the number of bytes of @value to set as a value * * Sets a new attribute to a #WockyNode, with the supplied values. */ void wocky_node_set_attribute_n (WockyNode *node, const gchar *key, const gchar *value, gsize value_size) { wocky_node_set_attribute_n_ns (node, key, value, value_size, NULL); } static gint node_compare_child (gconstpointer a, gconstpointer b) { const WockyNode *node = (const WockyNode *)a; Tuple *target = (Tuple *) b; if (target->ns != 0 && target->ns != node->ns) return 1; if (target->key == NULL) return 0; return strcmp (node->name, target->key); } /** * wocky_node_get_child_ns: * @node: a #WockyNode * @name: the name of the child to get * @ns: the namespace of the child to get, or %NULL * * Gets the child of a node, searching by name and limiting the search * to the specified namespace. * If the namespace is %NULL, this is equivalent to wocky_node_get_child() * * Returns: a #WockyNode. */ WockyNode * wocky_node_get_child_ns (WockyNode *node, const gchar *name, const gchar *ns) { GSList *link; Tuple t; /* This secretly works just fine if @name is %NULL, but don't tell anyone! * wocky_node_get_first_child_ns() is what people should be using. * */ t.key = name; t.ns = (ns != NULL ? g_quark_from_string (ns) : 0); link = g_slist_find_custom (node->children, &t, node_compare_child); return (link == NULL) ? NULL : (WockyNode *) (link->data); } /** * wocky_node_get_child: * @node: a #WockyNode * @name: the name of the child to get * * Gets a child of a node, searching by name. * * Returns: a #WockyNode. */ WockyNode * wocky_node_get_child (WockyNode *node, const gchar *name) { return wocky_node_get_child_ns (node, name, NULL); } /** * wocky_node_get_first_child: * @node: a #WockyNode * * Convenience function to return the first child of a #WockyNode. * * Returns: a #WockyNode, or %NULL if @node has no children. */ WockyNode * wocky_node_get_first_child (WockyNode *node) { g_return_val_if_fail (node != NULL, NULL); if (node->children == NULL) return NULL; return (WockyNode *) node->children->data; } /** * wocky_node_get_first_child_ns: * @node: a #WockyNode * @ns: the namespace of the child node you seek. * * Returns the first child of @node whose namespace is @ns, saving you the * bother of faffing around with a #WockyNodeIter. * * Returns: the first child of @node whose namespace is @ns, or %NULL if none * is found. */ WockyNode * wocky_node_get_first_child_ns (WockyNode *node, const gchar *ns) { g_return_val_if_fail (node != NULL, NULL); g_return_val_if_fail (ns != NULL, NULL); return wocky_node_get_child_ns (node, NULL, ns); } /** * wocky_node_get_content_from_child: * @node: a #WockyNode * @name: the name of the child whose content to retrieve * * Retrieves the content from a child of a node, if it exists. * * Returns: the content of the child of @node named @name, or %NULL if @node * has no such child. */ const gchar * wocky_node_get_content_from_child (WockyNode *node, const gchar *name) { return wocky_node_get_content_from_child_ns (node, name, NULL); } /** * wocky_node_get_content_from_child_ns: * @node: a #WockyNode * @name: the name of the child whose content to retrieve * @ns: the namespace of the child whose content to retrieve * * Retrieves the content from a child of a node, if it exists. * * Returns: the content of the child of @node named @name in @ns, or %NULL if * @node has no such child. */ const gchar *wocky_node_get_content_from_child_ns (WockyNode *node, const gchar *name, const gchar *ns) { WockyNode *child = wocky_node_get_child_ns (node, name, ns); if (child == NULL) return NULL; else return child->content; } /** * wocky_node_add_child: * @node: a #WockyNode * @name: the name of the child to add * * Adds a #WockyNode with the specified name to an already existing node. * * Returns: the newly added #WockyNode. */ WockyNode * wocky_node_add_child (WockyNode *node, const gchar *name) { return wocky_node_add_child_with_content_ns_q (node, name, NULL, 0); } /** * wocky_node_add_child_ns: * @node: a #WockyNode * @name: the name of the child to add * @ns: a namespace * * Adds a #WockyNode with the specified name to an already existing node, * under the specified namespace. If the namespace is %NULL, this is equivalent * to wocky_node_add_child(). * * Returns: the newly added #WockyNode. */ WockyNode * wocky_node_add_child_ns (WockyNode *node, const gchar *name, const gchar *ns) { return wocky_node_add_child_with_content_ns (node, name, NULL, ns); } /** * wocky_node_add_child_ns_q: * @node: a #WockyNode * @name: the name of the child to add * @ns: a namespace * * Adds a #WockyNode with the specified name to an already existing node, * under the specified namespace. If the namespace is 0, this is equivalent * to wocky_node_add_child(). * * Returns: the newly added #WockyNode. */ WockyNode * wocky_node_add_child_ns_q (WockyNode *node, const gchar *name, GQuark ns) { return wocky_node_add_child_with_content_ns_q (node, name, NULL, ns); } /** * wocky_node_add_child_with_content: * @node: a #WockyNode * @name: the name of the child to add * @content: the content of the child to add * * Adds a #WockyNode with the specified name and containing the * specified content to an already existing node. * * Returns: the newly added #WockyNode. */ WockyNode * wocky_node_add_child_with_content (WockyNode *node, const gchar *name, const char *content) { return wocky_node_add_child_with_content_ns_q (node, name, content, 0); } /** * wocky_node_add_child_with_content_ns: * @node: a #WockyNode * @name: the name of the child to add * @content: the content of the child to add * @ns: a namespace * * Adds a #WockyNode with the specified name and the specified content * to an already existing node, under the specified namespace. * If the namespace is %NULL, this is equivalent to * wocky_node_add_child_with_content(). * * Returns: the newly added #WockyNode. */ WockyNode * wocky_node_add_child_with_content_ns (WockyNode *node, const gchar *name, const gchar *content, const gchar *ns) { return wocky_node_add_child_with_content_ns_q (node, name, content, ns != NULL ? g_quark_from_string (ns) : 0); } /** * wocky_node_add_child_with_content_ns_q: * @node: a #WockyNode * @name: the name of the child to add * @content: the content of the child to add * @ns: a namespace * * Adds a #WockyNode with the specified name and the specified content * to an already existing node, under the specified namespace. * If the namespace is 0, this is equivalent to * wocky_node_add_child_with_content(). * * Returns: the newly added #WockyNode. */ WockyNode * wocky_node_add_child_with_content_ns_q (WockyNode *node, const gchar *name, const gchar *content, GQuark ns) { WockyNode *result = new_node (name, ns != 0 ? ns : node->ns); wocky_node_set_content (result, content); node->children = g_slist_append (node->children, result); return result; } /** * wocky_node_get_ns: * @node: a #WockyNode * * Gets the namespace of a #WockyNode * * Returns: a string containing the namespace of the node. */ const gchar * wocky_node_get_ns (WockyNode *node) { return g_quark_to_string (node->ns); } gboolean wocky_node_has_ns (WockyNode *node, const gchar *ns) { return wocky_node_has_ns_q (node, g_quark_try_string (ns)); } gboolean wocky_node_has_ns_q (WockyNode *node, GQuark ns) { return node->ns == ns; } /** * wocky_node_matches_q: * @node: a #WockyNode * @name: the expected element name, which may not be %NULL * @ns: the expected element namespace, which may not be 0 * * Checks whether a node has a particular name and namespace. * * Returns: %TRUE if @node is named @name, in namespace @ns. */ gboolean wocky_node_matches_q ( WockyNode *node, const gchar *name, GQuark ns) { g_return_val_if_fail (node != NULL, FALSE); g_return_val_if_fail (name != NULL, FALSE); g_return_val_if_fail (ns != 0, FALSE); if (wocky_strdiff (node->name, name)) return FALSE; return wocky_node_has_ns_q (node, ns); } /** * wocky_node_matches: * @node: a #WockyNode * @name: the expected element name, which may not be %NULL * @ns: the expected element namespace, which may not be %NULL * * Checks whether a node has a particular name and namespace. * * Returns: %TRUE if @node is named @name, in namespace @ns. */ gboolean wocky_node_matches ( WockyNode *node, const gchar *name, const gchar *ns) { g_return_val_if_fail (node != NULL, FALSE); g_return_val_if_fail (name != NULL, FALSE); g_return_val_if_fail (ns != NULL, FALSE); return wocky_node_matches_q (node, name, g_quark_try_string (ns)); } /** * wocky_node_get_language: * @node: a #WockyNode * * Gets the language of a #WockyNode * * Returns: a string containing the language of the node. */ const gchar * wocky_node_get_language (WockyNode *node) { g_return_val_if_fail (node != NULL, NULL); return node->language; } /** * wocky_node_set_language_n: * @node: a #WockyNode * @lang: a language * @lang_size: the length of @lang, in bytes. * * Sets the language of a #WockyNode. */ void wocky_node_set_language_n (WockyNode *node, const gchar *lang, gsize lang_size) { g_free (node->language); node->language = strndup_validated (lang, lang_size); } /** * wocky_node_set_language: * @node: a #WockyNode * @lang: a %NULL-terminated string containing the language * * Sets the language of a #WockyNode. */ void wocky_node_set_language (WockyNode *node, const gchar *lang) { gsize lang_size = 0; if (lang != NULL) { lang_size = strlen (lang); } wocky_node_set_language_n (node, lang, lang_size); } /** * wocky_node_set_content: * @node: a #WockyNode * @content: the content to set to the node * * Sets the content of a #WockyNode. */ void wocky_node_set_content (WockyNode *node, const gchar *content) { g_free (node->content); node->content = strndup_validated (content, -1); } /** * wocky_node_append_content: * @node: a #WockyNode * @content: the content to append to the node * * Appends some content to the content of a #WockyNode. */ void wocky_node_append_content (WockyNode *node, const gchar *content) { gchar *t = node->content; node->content = concat_validated (t, content, -1); g_free (t); } /** * wocky_node_append_content_n: * @node: a #WockyNode * @content: the content to append to the node * @size: the size of the content to append * * Appends a specified number of content bytes to the content of a * #WockyNode. */ void wocky_node_append_content_n (WockyNode *node, const gchar *content, gsize size) { gchar *t = node->content; node->content = concat_validated (t, content, size); g_free (t); } static gboolean attribute_to_string (const gchar *key, const gchar *value, const gchar *prefix, const gchar *ns, gpointer user_data) { GString *str = user_data; g_string_append_c (str, ' '); if (ns != NULL) g_string_append_printf (str, "xmlns:%s='%s' ", prefix, ns); if (prefix != NULL) { g_string_append (str, prefix); g_string_append_c (str, ':'); } g_string_append_printf (str, "%s='%s'", key, value); return TRUE; } static gboolean node_to_string (WockyNode *node, GQuark parent_ns, const gchar *prefix, GString *str) { GSList *l; gchar *nprefix; g_string_append_printf (str, "%s* %s", prefix, node->name); if (parent_ns != node->ns) { const gchar *ns = wocky_node_get_ns (node); g_string_append_printf (str, " xmlns='%s'", ns); } wocky_node_each_attribute (node, attribute_to_string, str); g_string_append_c (str, '\n'); nprefix = g_strdup_printf ("%s ", prefix); if (node->content != NULL && *node->content != '\0') g_string_append_printf (str, "%s\"%s\"\n", nprefix, node->content); for (l = node->children ; l != NULL; l = g_slist_next (l)) node_to_string (l->data, node->ns, nprefix, str); g_free (nprefix); return TRUE; } /** * wocky_node_to_string: * @node: a #WockyNode * * Obtains a string representation of a #WockyNode. * * Returns: a newly allocated string containing a serialization of * the node. */ gchar * wocky_node_to_string (WockyNode *node) { GString *str; gchar *result; str = g_string_new (""); node_to_string (node, 0, "", str); g_string_truncate (str, str->len - 1); result = str->str; g_string_free (str, FALSE); return result; } /** * wocky_node_equal: * @node0: a #WockyNode * @node1: a #WockyNode to compare to @node0 * * Compares two #WockyNodes for equality. * * Returns: %TRUE if the two nodes are equal. */ gboolean wocky_node_equal (WockyNode *node0, WockyNode *node1) { GSList *l0, *l1; if (wocky_strdiff (node0->name, node1->name)) return FALSE; if (wocky_strdiff (node0->content, node1->content)) return FALSE; if (wocky_strdiff (node0->language, node1->language)) return FALSE; if (node0->ns != node1->ns) return FALSE; if (g_slist_length (node0->attributes) != g_slist_length (node1->attributes)) return FALSE; /* Compare attributes */ for (l0 = node0->attributes ; l0 != NULL; l0 = g_slist_next (l0)) { Attribute *a = (Attribute *) l0->data; const gchar *c; c = wocky_node_get_attribute_ns (node1, a->key, a->ns == 0 ? NULL : g_quark_to_string (a->ns)); if (wocky_strdiff (a->value, c)) return FALSE; } /* Recursively compare children, order matters */ for (l0 = node0->children, l1 = node1->children ; l0 != NULL && l1 != NULL; l0 = g_slist_next (l0), l1 = g_slist_next (l1)) { WockyNode *c0 = (WockyNode *) l0->data; WockyNode *c1 = (WockyNode *) l1->data; if (!wocky_node_equal (c0, c1)) return FALSE; } if (l0 != NULL || l1 != NULL) return FALSE; return TRUE; } /** * wocky_node_is_superset: * @node: the #WockyNode to test * @subset: the supposed subset * * Returns: %TRUE if @node is a superset of @subset. */ gboolean wocky_node_is_superset (WockyNode *node, WockyNode *subset) { GSList *l; if (subset == NULL) /* We are always a superset of nothing */ return TRUE; if (node == NULL) /* subset is not NULL so we are not a superset */ return FALSE; if (wocky_strdiff (node->name, subset->name)) /* Node name doesn't match */ return FALSE; if (subset->ns != 0 && node->ns != subset->ns) /* Namespace doesn't match */ return FALSE; if (subset->content != NULL && wocky_strdiff (node->content, subset->content)) /* Content doesn't match */ return FALSE; /* Check attributes */ for (l = subset->attributes; l != NULL; l = g_slist_next (l)) { Attribute *a = (Attribute *) l->data; const gchar *c; c = wocky_node_get_attribute_ns (node, a->key, a->ns == 0 ? NULL : g_quark_to_string (a->ns)); if (wocky_strdiff (a->value, c)) return FALSE; } /* Recursively check children; order doesn't matter */ for (l = subset->children; l != NULL; l = g_slist_next (l)) { WockyNode *pattern_child = (WockyNode *) l->data; WockyNode *node_child; node_child = wocky_node_get_child_ns (node, pattern_child->name, wocky_node_get_ns (pattern_child)); if (!wocky_node_is_superset (node_child, pattern_child)) return FALSE; } return TRUE; } /** * wocky_node_iter_init: * @iter: unitialized iterator * @node: Node whose children to iterate over * @name: Name to filter on or %NULL * @ns: namespace to filter on or %NULL * * Initializes an iterator that can be used to iterate over the children of * @node, filtered by @name and @ns * |[ * WockyNodeIter iter; * WockyNode *child; * * wocky_node_iter_init (&iter, wocky_stanza_get_top_node (stanza), * "payload-type", * WOCKY_XMPP_NS_JINGLE_RTP); * while (wocky_node_iter_next (iter, &child)) * { * /* do something with the child */ * } * ]| */ void wocky_node_iter_init (WockyNodeIter *iter, WockyNode *node, const gchar *name, const gchar *ns) { g_return_if_fail (iter != NULL); g_return_if_fail (node != NULL); iter->node = node; iter->pending = node->children; iter->current = NULL; iter->name = name; iter->ns = g_quark_from_string (ns); } /** * wocky_node_iter_next: * @iter: an initialized WockyNodeIter * @next: a location to store the next child * * Advances iter to the next child that matches its filter. if %FALSE is * returned next is not set and the iterator becomes invalid * * Returns: %FALSE if the last child has been reached * */ gboolean wocky_node_iter_next (WockyNodeIter *iter, WockyNode **next) { while (iter->pending != NULL) { WockyNode *ln = (WockyNode *) iter->pending->data; iter->current = iter->pending; iter->pending = g_slist_next (iter->pending); if (iter->name != NULL && wocky_strdiff (ln->name, iter->name)) continue; if (iter->ns != 0 && iter->ns != ln->ns) continue; if (next != NULL) *next = ln; return TRUE; } iter->current = NULL; return FALSE; } /** * wocky_node_iter_remove: * @iter: an initialized #WockyNodeIter * * Removes and frees the node returned by the last call to * wocky_node_iter_next() from its parent. Can only be called after * wocky_node_iter_next() returned %TRUE, and cannot be called more than once * per successful call to wocky_node_iter_next(). */ void wocky_node_iter_remove (WockyNodeIter *iter) { g_return_if_fail (iter->node != NULL); g_return_if_fail (iter->current != NULL); g_assert (iter->current->data != NULL); wocky_node_free (iter->current->data); iter->node->children = g_slist_delete_link (iter->node->children, iter->current); iter->current = NULL; } /** * wocky_node_add_build: * @node: The node under which to add a new subtree * @...: the description of the stanza to build, * terminated with %NULL * * Add a node subtree to an existing parent node. * * wocky_node_add_build (node, * '(', "body", * '$', "Telepathy rocks!", * ')', * NULL); * * * The above examples adds the following subtree under the given node: * * <body> * Telepathy rocks! * </body> * * */ void wocky_node_add_build (WockyNode *node, ...) { va_list ap; va_start (ap, node); wocky_node_add_build_va (node, ap); va_end (ap); } void wocky_node_add_build_va (WockyNode *node, va_list ap) { GSList *stack = NULL; WockyNodeBuildTag arg; stack = g_slist_prepend (stack, node); while ((arg = va_arg (ap, WockyNodeBuildTag)) != 0) { switch (arg) { case WOCKY_NODE_ATTRIBUTE: { gchar *key = va_arg (ap, gchar *); gchar *value = va_arg (ap, gchar *); g_assert (key != NULL); g_assert (value != NULL); g_assert (stack != NULL); wocky_node_set_attribute (stack->data, key, value); } break; case WOCKY_NODE_START: { gchar *name = va_arg (ap, gchar *); WockyNode *child; g_assert (name != NULL); g_assert (stack != NULL); child = wocky_node_add_child (stack->data, name); stack = g_slist_prepend (stack, child); } break; case WOCKY_NODE_TEXT: { gchar *txt = va_arg (ap, gchar *); g_assert (stack != NULL); wocky_node_set_content (stack->data, txt); } break; case WOCKY_NODE_XMLNS: { gchar *ns = va_arg (ap, gchar *); g_assert (ns != NULL); g_assert (stack != NULL); ((WockyNode *) stack->data)->ns = g_quark_from_string (ns); } break; case WOCKY_NODE_LANGUAGE: { gchar *lang = va_arg (ap, gchar *); g_assert (lang != NULL); wocky_node_set_language ((WockyNode *) stack->data, lang); } break; case WOCKY_NODE_END: { /* delete the top of the stack */ stack = g_slist_delete_link (stack, stack); /* If you put too many ')'s at the end of your build spec, we just * warn; if you actually try to do anything else having fallen off * the end, we'll assert in the relevant branch. */ g_warn_if_fail (stack != NULL); } break; case WOCKY_NODE_ASSIGN_TO: { WockyNode **dest = va_arg (ap, WockyNode **); g_assert (dest != NULL); g_assert (stack != NULL); *dest = stack->data; } break; default: g_critical ("unknown build tag %c", arg); g_assert_not_reached (); } } if (G_UNLIKELY (stack != NULL && stack->data != node)) { GString *still_open = g_string_new (""); while (stack != NULL && stack->data != node) { WockyNode *unclosed = stack->data; g_string_append_printf (still_open, " ", unclosed->name); stack = stack->next; } g_warning ("improperly nested build spec! unclosed: %s", still_open->str); g_string_free (still_open, TRUE); } g_slist_free (stack); } WockyNode * _wocky_node_copy (WockyNode *node) { WockyNode *result = new_node (node->name, node->ns); GSList *l; result->content = g_strdup (node->content); result->language = g_strdup (node->language); for (l = node->attributes ; l != NULL; l = g_slist_next (l)) { Attribute *a = l->data; Attribute *b = g_slice_new0 (Attribute); b->key = g_strdup (a->key); b->value = g_strdup (a->value); b->prefix = g_strdup (a->prefix); b->ns = a->ns; result->attributes = g_slist_append (result->attributes, b); } for (l = node->children ; l != NULL; l = g_slist_next (l)) result->children = g_slist_append (result->children, _wocky_node_copy ((WockyNode *) l->data)); return result; } /** * wocky_node_add_node_tree: * @node: A node * @tree: The node tree to add * * Copies the nodes from @tree, and appends them to @node's children. * * Returns: the root of the copy of @tree added to @node. */ WockyNode * wocky_node_add_node_tree (WockyNode *node, WockyNodeTree *tree) { WockyNode *copy; g_return_val_if_fail (node != NULL, NULL); g_return_val_if_fail (tree != NULL, NULL); copy = _wocky_node_copy (wocky_node_tree_get_top_node (tree)); node->children = g_slist_append (node->children, copy); return copy; } /** * wocky_node_prepend_node_tree: * @node: a node * @tree: the node tree to prepend to @node's children * * Copies the nodes from @tree, and inserts them as the first child of @node, * before any existing children. * * Returns: the root of the copy of @tree added to @node. */ WockyNode * wocky_node_prepend_node_tree ( WockyNode *node, WockyNodeTree *tree) { WockyNode *copy; g_return_val_if_fail (node != NULL, NULL); g_return_val_if_fail (tree != NULL, NULL); copy = _wocky_node_copy (wocky_node_tree_get_top_node (tree)); node->children = g_slist_prepend (node->children, copy); return copy; } /** * wocky_node_init: * * Initializes the caches used by #WockyNode. * This should be always called before using #WockyNode structs. */ void wocky_node_init () { _init_user_prefix_table (); _init_default_prefix_table (); } /** * wocky_node_deinit: * * Releases all the resources used by the #WockyNode caches. */ void wocky_node_deinit () { g_hash_table_unref (user_ns_prefixes); g_hash_table_unref (default_ns_prefixes); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-sasl-digest-md5.h0000664000175000017500000000267011720661341026247 0ustar00cassidycassidy00000000000000#if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef _WOCKY_SASL_DIGEST_MD5_H #define _WOCKY_SASL_DIGEST_MD5_H #include #include "wocky-auth-handler.h" G_BEGIN_DECLS #define WOCKY_TYPE_SASL_DIGEST_MD5 \ wocky_sasl_digest_md5_get_type () #define WOCKY_SASL_DIGEST_MD5(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), WOCKY_TYPE_SASL_DIGEST_MD5, \ WockySaslDigestMd5)) #define WOCKY_SASL_DIGEST_MD5_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), WOCKY_TYPE_SASL_DIGEST_MD5, \ WockySaslDigestMd5Class)) #define WOCKY_IS_SASL_DIGEST_MD5(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WOCKY_TYPE_SASL_DIGEST_MD5)) #define WOCKY_IS_SASL_DIGEST_MD5_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), WOCKY_TYPE_SASL_DIGEST_MD5)) #define WOCKY_SASL_DIGEST_MD5_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_SASL_DIGEST_MD5, \ WockySaslDigestMd5Class)) typedef struct _WockySaslDigestMd5Private WockySaslDigestMd5Private; typedef struct { GObject parent; WockySaslDigestMd5Private *priv; } WockySaslDigestMd5; typedef struct { GObjectClass parent_class; } WockySaslDigestMd5Class; GType wocky_sasl_digest_md5_get_type (void); WockySaslDigestMd5 * wocky_sasl_digest_md5_new ( const gchar *server, const gchar *username, const gchar *password); G_END_DECLS #endif /* _WOCKY_SASL_DIGEST_MD5_H */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-sasl-scram.h0000664000175000017500000000424311720661341025410 0ustar00cassidycassidy00000000000000/* * wocky-sasl-scram.h - SCRAM-SHA1 implementation (to be RFC 5802) * Copyright (C) 2010 Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef _WOCKY_SASL_SCRAM_H #define _WOCKY_SASL_SCRAM_H #include #include "wocky-auth-handler.h" G_BEGIN_DECLS #define WOCKY_TYPE_SASL_SCRAM \ wocky_sasl_scram_get_type () #define WOCKY_SASL_SCRAM(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), WOCKY_TYPE_SASL_SCRAM, \ WockySaslScram)) #define WOCKY_SASL_SCRAM_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), WOCKY_TYPE_SASL_SCRAM, \ WockySaslScramClass)) #define WOCKY_IS_SASL_SCRAM(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WOCKY_TYPE_SASL_SCRAM)) #define WOCKY_IS_SASL_SCRAM_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), WOCKY_TYPE_SASL_SCRAM)) #define WOCKY_SASL_SCRAM_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_SASL_SCRAM, \ WockySaslScramClass)) typedef struct _WockySaslScramPrivate WockySaslScramPrivate; typedef struct { GObject parent; WockySaslScramPrivate *priv; } WockySaslScram; typedef struct { GObjectClass parent_class; } WockySaslScramClass; GType wocky_sasl_scram_get_type (void); WockySaslScram * wocky_sasl_scram_new ( const gchar *server, const gchar *username, const gchar *password); G_END_DECLS #endif /* _WOCKY_SASL_SCRAM_H */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-stanza.c0000664000175000017500000005373112212322440024633 0ustar00cassidycassidy00000000000000/* * wocky-stanza.c - Source for WockyStanza * Copyright (C) 2006-2010 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "wocky-stanza.h" #include "wocky-xmpp-error.h" #include "wocky-namespaces.h" #include "wocky-debug-internal.h" #include "wocky-node-private.h" G_DEFINE_TYPE(WockyStanza, wocky_stanza, WOCKY_TYPE_NODE_TREE) /* private structure */ struct _WockyStanzaPrivate { WockyContact *from_contact; WockyContact *to_contact; gboolean dispose_has_run; }; typedef struct { WockyStanzaType type; const gchar *name; const gchar *ns; GQuark ns_q; } StanzaTypeName; static StanzaTypeName type_names[NUM_WOCKY_STANZA_TYPE] = { { WOCKY_STANZA_TYPE_NONE, NULL, WOCKY_XMPP_NS_JABBER_CLIENT }, { WOCKY_STANZA_TYPE_MESSAGE, "message", WOCKY_XMPP_NS_JABBER_CLIENT }, { WOCKY_STANZA_TYPE_PRESENCE, "presence", WOCKY_XMPP_NS_JABBER_CLIENT }, { WOCKY_STANZA_TYPE_IQ, "iq", WOCKY_XMPP_NS_JABBER_CLIENT }, { WOCKY_STANZA_TYPE_STREAM, "stream", WOCKY_XMPP_NS_STREAM }, { WOCKY_STANZA_TYPE_STREAM_FEATURES, "features", WOCKY_XMPP_NS_STREAM }, { WOCKY_STANZA_TYPE_AUTH, "auth", WOCKY_XMPP_NS_SASL_AUTH }, { WOCKY_STANZA_TYPE_CHALLENGE, "challenge", WOCKY_XMPP_NS_SASL_AUTH }, { WOCKY_STANZA_TYPE_RESPONSE, "response", WOCKY_XMPP_NS_SASL_AUTH }, { WOCKY_STANZA_TYPE_SUCCESS, "success", WOCKY_XMPP_NS_SASL_AUTH }, { WOCKY_STANZA_TYPE_FAILURE, "failure", WOCKY_XMPP_NS_SASL_AUTH }, { WOCKY_STANZA_TYPE_STREAM_ERROR, "error", WOCKY_XMPP_NS_STREAM }, { WOCKY_STANZA_TYPE_UNKNOWN, NULL, NULL }, }; static void fill_in_namespace_quarks (void) { int i; /* We skip the first entry as it's NONE */ for (i = 1; type_names[i].type != WOCKY_STANZA_TYPE_UNKNOWN; i++) type_names[i].ns_q = g_quark_from_static_string (type_names[i].ns); } typedef struct { WockyStanzaSubType sub_type; const gchar *name; WockyStanzaType type; } StanzaSubTypeName; static const StanzaSubTypeName sub_type_names[NUM_WOCKY_STANZA_SUB_TYPE] = { { WOCKY_STANZA_SUB_TYPE_NONE, NULL, WOCKY_STANZA_TYPE_NONE }, { WOCKY_STANZA_SUB_TYPE_AVAILABLE, NULL, WOCKY_STANZA_TYPE_PRESENCE }, { WOCKY_STANZA_SUB_TYPE_NORMAL, "normal", WOCKY_STANZA_TYPE_NONE }, { WOCKY_STANZA_SUB_TYPE_CHAT, "chat", WOCKY_STANZA_TYPE_MESSAGE }, { WOCKY_STANZA_SUB_TYPE_GROUPCHAT, "groupchat", WOCKY_STANZA_TYPE_MESSAGE }, { WOCKY_STANZA_SUB_TYPE_HEADLINE, "headline", WOCKY_STANZA_TYPE_MESSAGE }, { WOCKY_STANZA_SUB_TYPE_UNAVAILABLE, "unavailable", WOCKY_STANZA_TYPE_PRESENCE }, { WOCKY_STANZA_SUB_TYPE_PROBE, "probe", WOCKY_STANZA_TYPE_PRESENCE }, { WOCKY_STANZA_SUB_TYPE_SUBSCRIBE, "subscribe", WOCKY_STANZA_TYPE_PRESENCE }, { WOCKY_STANZA_SUB_TYPE_UNSUBSCRIBE, "unsubscribe", WOCKY_STANZA_TYPE_PRESENCE }, { WOCKY_STANZA_SUB_TYPE_SUBSCRIBED, "subscribed", WOCKY_STANZA_TYPE_PRESENCE }, { WOCKY_STANZA_SUB_TYPE_UNSUBSCRIBED, "unsubscribed", WOCKY_STANZA_TYPE_PRESENCE }, { WOCKY_STANZA_SUB_TYPE_GET, "get", WOCKY_STANZA_TYPE_IQ }, { WOCKY_STANZA_SUB_TYPE_SET, "set", WOCKY_STANZA_TYPE_IQ }, { WOCKY_STANZA_SUB_TYPE_RESULT, "result", WOCKY_STANZA_TYPE_IQ }, { WOCKY_STANZA_SUB_TYPE_ERROR, "error", WOCKY_STANZA_TYPE_NONE }, { WOCKY_STANZA_SUB_TYPE_UNKNOWN, NULL, WOCKY_STANZA_TYPE_UNKNOWN }, }; static void wocky_stanza_init (WockyStanza *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_STANZA, WockyStanzaPrivate); self->priv->from_contact = NULL; self->priv->to_contact = NULL; } static void wocky_stanza_dispose (GObject *object); static void wocky_stanza_finalize (GObject *object); static void wocky_stanza_class_init (WockyStanzaClass *wocky_stanza_class) { GObjectClass *object_class = G_OBJECT_CLASS (wocky_stanza_class); g_type_class_add_private (wocky_stanza_class, sizeof (WockyStanzaPrivate)); object_class->dispose = wocky_stanza_dispose; object_class->finalize = wocky_stanza_finalize; fill_in_namespace_quarks (); } static void wocky_stanza_dispose (GObject *object) { WockyStanza *self = WOCKY_STANZA (object); WockyStanzaPrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; /* release any references held by the object here */ if (G_OBJECT_CLASS (wocky_stanza_parent_class)->dispose) G_OBJECT_CLASS (wocky_stanza_parent_class)->dispose (object); } static void wocky_stanza_finalize (GObject *object) { WockyStanza *self = WOCKY_STANZA (object); if (self->priv->from_contact != NULL) { g_object_unref (self->priv->from_contact); self->priv->from_contact = NULL; } if (self->priv->to_contact != NULL) { g_object_unref (self->priv->to_contact); self->priv->to_contact = NULL; } G_OBJECT_CLASS (wocky_stanza_parent_class)->finalize (object); } WockyStanza * wocky_stanza_new (const gchar *name, const gchar *ns) { WockyStanza *result; result = WOCKY_STANZA (g_object_new (WOCKY_TYPE_STANZA, "top-node", wocky_node_new (name, ns), NULL)); return result; } WockyStanza * wocky_stanza_copy (WockyStanza *old) { WockyNode *top; top = _wocky_node_copy (wocky_stanza_get_top_node (old)); return g_object_new (WOCKY_TYPE_STANZA, "top-node", top, NULL); } static const gchar * get_type_name (WockyStanzaType type) { if (type <= WOCKY_STANZA_TYPE_NONE || type >= NUM_WOCKY_STANZA_TYPE) return NULL; g_assert (type_names[type].type == type); return type_names[type].name; } static const gchar * get_type_ns (WockyStanzaType type) { if (type <= WOCKY_STANZA_TYPE_NONE || type >= NUM_WOCKY_STANZA_TYPE) return NULL; g_assert (type_names[type].type == type); return type_names[type].ns; } static const gchar * get_sub_type_name (WockyStanzaSubType sub_type) { if (sub_type <= WOCKY_STANZA_SUB_TYPE_NONE || sub_type >= NUM_WOCKY_STANZA_SUB_TYPE) return NULL; g_assert (sub_type_names[sub_type].sub_type == sub_type); return sub_type_names[sub_type].name; } static gboolean check_sub_type (WockyStanzaType type, WockyStanzaSubType sub_type) { WockyStanzaType expected_type; g_return_val_if_fail (type > WOCKY_STANZA_TYPE_NONE && type < NUM_WOCKY_STANZA_TYPE, FALSE); g_return_val_if_fail (sub_type < NUM_WOCKY_STANZA_SUB_TYPE, FALSE); g_assert (sub_type_names[sub_type].sub_type == sub_type); expected_type = sub_type_names[sub_type].type; if (expected_type != WOCKY_STANZA_TYPE_NONE && expected_type != type) { g_critical ("Stanza sub-type '%s' may only be used with stanzas of " "type '%s', not of type '%s'", sub_type_names[sub_type].name, type_names[expected_type].name, type_names[type].name); g_return_val_if_reached (FALSE); } return TRUE; } static WockyStanza * wocky_stanza_new_with_sub_type (WockyStanzaType type, WockyStanzaSubType sub_type) { WockyStanza *stanza = NULL; const gchar *sub_type_name; if (!check_sub_type (type, sub_type)) return NULL; stanza = wocky_stanza_new (get_type_name (type), get_type_ns (type)); sub_type_name = get_sub_type_name (sub_type); if (sub_type_name != NULL) wocky_node_set_attribute (wocky_stanza_get_top_node (stanza), "type", sub_type_name); return stanza; } /** * wocky_stanza_build: * @type: The type of stanza to build * @sub_type: The stanza's subtype; valid values depend on @type. (For instance, * #WOCKY_STANZA_TYPE_IQ can use #WOCKY_STANZA_SUB_TYPE_GET, but not * #WOCKY_STANZA_SUB_TYPE_SUBSCRIBED.) * @from: The sender's JID, or %NULL to leave it unspecified. * @to: The target's JID, or %NULL to leave it unspecified. * @...: the description of the stanza to build, * terminated with %NULL * * Build a XMPP stanza from a list of arguments. For example, the following invocation: * * |[ * wocky_stanza_build ( * WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, * "alice@collabora.co.uk", "bob@collabora.co.uk", * WOCKY_NODE_START, "html", * WOCKY_NODE_XMLNS, "http://www.w3.org/1999/xhtml", * WOCKY_NODE, "body", * WOCKY_NODE_ATTRIBUTE, "textcolor", "red", * WOCKY_NODE_TEXT, "Telepathy rocks!", * WOCKY_NODE_END, * WOCKY_NODE_END, * NULL); * ]| * * produces this stanza: * * |[ * <message from='alice@collabora.co.uk' to='bob@collabora.co.uk'> * <html xmlns='http://www.w3.org/1999/xhtml'> * <body textcolor='red'> * Telepathy rocks! * </body> * </html> * </message> * ]| * * You may optionally use mnemonic ASCII characters in place of the build tags, * to better reflect the structure of the stanza in C source. For example, the * above stanza could be written as: * * |[ * wocky_stanza_build ( * WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, * "alice@collabora.co.uk", "bob@collabora.co.uk", * '(', "html", ':', "http://www.w3.org/1999/xhtml", * '(', "body", '@', "textcolor", "red", * '$', "Telepathy rocks!", * ')', * ')' * NULL); * ]| * * Returns: a new stanza object */ WockyStanza * wocky_stanza_build (WockyStanzaType type, WockyStanzaSubType sub_type, const gchar *from, const gchar *to, ...) { WockyStanza *stanza; va_list ap; va_start (ap, to); stanza = wocky_stanza_build_va (type, sub_type, from, to, ap); va_end (ap); return stanza; } WockyStanza * wocky_stanza_build_to_contact (WockyStanzaType type, WockyStanzaSubType sub_type, const gchar *from, WockyContact *to, ...) { WockyStanza *stanza; va_list ap; gchar *to_jid = NULL; if (to != NULL) to_jid = wocky_contact_dup_jid (to); va_start (ap, to); stanza = wocky_stanza_build_va (type, sub_type, from, to_jid, ap); va_end (ap); g_free (to_jid); stanza->priv->to_contact = g_object_ref (to); return stanza; } WockyStanza * wocky_stanza_build_va (WockyStanzaType type, WockyStanzaSubType sub_type, const gchar *from, const gchar *to, va_list ap) { WockyStanza *stanza; g_return_val_if_fail (type < NUM_WOCKY_STANZA_TYPE, NULL); g_return_val_if_fail (sub_type < NUM_WOCKY_STANZA_SUB_TYPE, NULL); stanza = wocky_stanza_new_with_sub_type (type, sub_type); if (stanza == NULL) return NULL; if (from != NULL) wocky_node_set_attribute (wocky_stanza_get_top_node (stanza), "from", from); if (to != NULL) wocky_node_set_attribute (wocky_stanza_get_top_node (stanza), "to", to); wocky_node_add_build_va (wocky_stanza_get_top_node (stanza), ap); return stanza; } static WockyStanzaType get_type_from_node (WockyNode *node) { const gchar *name = node->name; GQuark ns = node->ns; guint i; if (name == NULL) return WOCKY_STANZA_TYPE_NONE; /* We skip the first entry as it's NONE */ for (i = 1; i < WOCKY_STANZA_TYPE_UNKNOWN; i++) { if (type_names[i].name != NULL && ns == type_names[i].ns_q && strcmp (name, type_names[i].name) == 0) { return type_names[i].type; } } return WOCKY_STANZA_TYPE_UNKNOWN; } static WockyStanzaSubType get_sub_type_from_name (const gchar *name) { guint i; if (name == NULL) return WOCKY_STANZA_SUB_TYPE_NONE; /* We skip the first entry as it's NONE */ for (i = 1; i < WOCKY_STANZA_SUB_TYPE_UNKNOWN; i++) { if (sub_type_names[i].name != NULL && strcmp (name, sub_type_names[i].name) == 0) { return sub_type_names[i].sub_type; } } return WOCKY_STANZA_SUB_TYPE_UNKNOWN; } void wocky_stanza_get_type_info (WockyStanza *stanza, WockyStanzaType *type, WockyStanzaSubType *sub_type) { WockyNode *top_node; g_return_if_fail (stanza != NULL); top_node = wocky_stanza_get_top_node (stanza); g_assert (top_node != NULL); if (type != NULL) *type = get_type_from_node (top_node); if (sub_type != NULL) *sub_type = get_sub_type_from_name ( wocky_node_get_attribute (top_node, "type")); } gboolean wocky_stanza_has_type (WockyStanza *stanza, WockyStanzaType expected_type) { WockyStanzaType actual_type; g_return_val_if_fail (WOCKY_IS_STANZA (stanza), FALSE); wocky_stanza_get_type_info (stanza, &actual_type, NULL); return expected_type == actual_type; } static WockyStanza * create_iq_reply (WockyStanza *iq, WockyStanzaSubType sub_type_reply, va_list ap) { WockyStanza *reply; WockyStanzaType type; WockyNode *node; WockyStanzaSubType sub_type; const gchar *from, *to, *id; WockyContact *contact; g_return_val_if_fail (iq != NULL, NULL); wocky_stanza_get_type_info (iq, &type, &sub_type); g_return_val_if_fail (type == WOCKY_STANZA_TYPE_IQ, NULL); g_return_val_if_fail (sub_type == WOCKY_STANZA_SUB_TYPE_GET || sub_type == WOCKY_STANZA_SUB_TYPE_SET, NULL); node = wocky_stanza_get_top_node (iq); from = wocky_node_get_attribute (node, "from"); to = wocky_node_get_attribute (node, "to"); id = wocky_node_get_attribute (node, "id"); if (id == NULL) return NULL; reply = wocky_stanza_build_va (WOCKY_STANZA_TYPE_IQ, sub_type_reply, to, from, ap); wocky_node_set_attribute (wocky_stanza_get_top_node (reply), "id", id); contact = wocky_stanza_get_from_contact (iq); if (contact != NULL) wocky_stanza_set_to_contact (reply, contact); return reply; } WockyStanza * wocky_stanza_build_iq_result (WockyStanza *iq, ...) { WockyStanza *reply; va_list ap; va_start (ap, iq); reply = create_iq_reply (iq, WOCKY_STANZA_SUB_TYPE_RESULT, ap); va_end (ap); return reply; } WockyStanza * wocky_stanza_build_iq_result_va ( WockyStanza *iq, va_list ap) { return create_iq_reply (iq, WOCKY_STANZA_SUB_TYPE_RESULT, ap); } /** * wocky_stanza_build_iq_error: * @iq: a stanza of type #WOCKY_STANZA_TYPE_IQ and sub-type either * #WOCKY_STANZA_SUB_TYPE_SET or #WOCKY_STANZA_SUB_TYPE_GET * @...: a wocky_stanza_build() specification * * Builds an error reply to @iq containing the given body. This function also * adds the child element of @iq to the reply, as recommended by RFC3920 §9.2.3 * ‘IQ Semantics’. * * No <error/> element is added to the reply. To add a * standard stanza error, plus message, consider using * wocky_stanza_error_to_node(). To add a more complicated error with an * application-specific condition, specify it when calling this function. For * example: * * |[ * WockyStanza *reply = wocky_stanza_build_iq_error (iq, * '(', "error", * '@', "type", "cancel", * '(', "feature-not-implemented", ':', WOCKY_XMPP_NS_STANZAS, ')', * '(', "unsupported", ':', WOCKY_XMPP_NS_PUBSUB_ERRORS, * '@', "feature", "subscribe", * ')', * ')', NULL); * ]| * * Returns: an error reply for @iq */ WockyStanza * wocky_stanza_build_iq_error (WockyStanza *iq, ...) { WockyStanza *reply; WockyNode *query; va_list ap; va_start (ap, iq); reply = create_iq_reply (iq, WOCKY_STANZA_SUB_TYPE_ERROR, ap); va_end (ap); /* RFC3920 §9.2.3 dictates: * 5. An IQ stanza of type "get" or "set" MUST contain one and only one * child element that specifies the semantics of the particular request * or response. * … * 7. An IQ stanza of type "error" SHOULD include the child element * contained in the associated "get" or "set" and MUST include an * child; for details, see Stanza Errors. * * So here we take the first child out of the stanza we're replying to, and * include it in the error reply. If @iq has more than one child, it * was illegal, so we're within our rights to ignore everything after the * first. If @iq has no children, it was also illegal, so there's no way we * can comply with the SHOULD. */ query = wocky_node_get_first_child (wocky_stanza_get_top_node (iq)); if (reply != NULL && query != NULL) { WockyNodeTree *query_tree = wocky_node_tree_new_from_node (query); wocky_node_prepend_node_tree (wocky_stanza_get_top_node (reply), query_tree); g_object_unref (query_tree); } return reply; } WockyStanza * wocky_stanza_build_iq_error_va ( WockyStanza *iq, va_list ap) { return create_iq_reply (iq, WOCKY_STANZA_SUB_TYPE_ERROR, ap); } /** * wocky_stanza_extract_errors: * @stanza: a message/iq/presence stanza * @type: location at which to store the error type * @core: location at which to store an error in the domain #WOCKY_XMPP_ERROR * @specialized: location at which to store an error in an application-specific * domain, if one is found * @specialized_node: location at which to store the node representing an * application-specific error, if one is found * * Given a message, iq or presence stanza with type='error', breaks it down * into values describing the error. @type and @core are guaranteed to be set; * @specialized and @specialized_node will be set if a recognised * application-specific error is found, and the latter will be set to %NULL if * no application-specific error is found. * * Any or all of the out parameters may be %NULL to ignore the value. The * value stored in @specialized_node is borrowed from @stanza, and is only * valid as long as the latter is alive. * * Returns: %TRUE if the stanza had type='error'; %FALSE otherwise */ gboolean wocky_stanza_extract_errors (WockyStanza *stanza, WockyXmppErrorType *type, GError **core, GError **specialized, WockyNode **specialized_node) { WockyStanzaSubType sub_type; WockyNode *error; wocky_stanza_get_type_info (stanza, NULL, &sub_type); if (sub_type != WOCKY_STANZA_SUB_TYPE_ERROR) return FALSE; error = wocky_node_get_child (wocky_stanza_get_top_node (stanza), "error"); if (error == NULL) { if (type != NULL) *type = WOCKY_XMPP_ERROR_TYPE_CANCEL; g_set_error (core, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_UNDEFINED_CONDITION, "stanza had type='error' but no node"); if (specialized_node != NULL) *specialized_node = NULL; } else { wocky_xmpp_error_extract (error, type, core, specialized, specialized_node); } return TRUE; } /** * wocky_stanza_extract_stream_error: * @stanza: a stanza * @stream_error: location at which to store an error in domain * #WOCKY_XMPP_STREAM_ERROR, if one is found. * * Returns: %TRUE and sets @stream_error if the stanza was indeed a stream * error. */ gboolean wocky_stanza_extract_stream_error (WockyStanza *stanza, GError **stream_error) { if (!wocky_stanza_has_type (stanza, WOCKY_STANZA_TYPE_STREAM_ERROR)) return FALSE; g_propagate_error (stream_error, wocky_xmpp_stream_error_from_node (wocky_stanza_get_top_node (stanza))); return TRUE; } /** * wocky_stanza_get_top_node: * @self: a stanza * * Returns: A pointer to the topmost node of the stanza */ WockyNode * wocky_stanza_get_top_node (WockyStanza *self) { return wocky_node_tree_get_top_node (WOCKY_NODE_TREE (self)); } /** * wocky_stanza_get_from: * @self: a stanza * * * * Returns: The sender of @self, or %NULL if no sender was specified. */ const gchar * wocky_stanza_get_from (WockyStanza *self) { g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (WOCKY_IS_STANZA (self), NULL); return wocky_node_get_attribute (wocky_stanza_get_top_node (self), "from"); } /** * wocky_stanza_get_to: * @self: a stanza * * * * Returns: The recipient of @self, or %NULL if no recipient was specified. */ const gchar * wocky_stanza_get_to (WockyStanza *self) { g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (WOCKY_IS_STANZA (self), NULL); return wocky_node_get_attribute (wocky_stanza_get_top_node (self), "to"); } WockyContact * wocky_stanza_get_to_contact (WockyStanza *self) { g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (WOCKY_IS_STANZA (self), NULL); return self->priv->to_contact; } WockyContact * wocky_stanza_get_from_contact (WockyStanza *self) { g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (WOCKY_IS_STANZA (self), NULL); return self->priv->from_contact; } void wocky_stanza_set_to_contact (WockyStanza *self, WockyContact *contact) { g_return_if_fail (self != NULL); g_return_if_fail (WOCKY_IS_STANZA (self)); g_return_if_fail (WOCKY_IS_CONTACT (contact)); if (self->priv->to_contact != NULL) g_object_unref (self->priv->to_contact); self->priv->to_contact = g_object_ref (contact); } void wocky_stanza_set_from_contact (WockyStanza *self, WockyContact *contact) { g_return_if_fail (self != NULL); g_return_if_fail (WOCKY_IS_STANZA (self)); g_return_if_fail (WOCKY_IS_CONTACT (contact)); if (self->priv->from_contact != NULL) g_object_unref (self->priv->from_contact); self->priv->from_contact = g_object_ref (contact); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-utils.h0000664000175000017500000001225112212322440024470 0ustar00cassidycassidy00000000000000/* * wocky-utils.h - Header for Wocky utility functions * Copyright © 2007–2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_UTILS_H__ #define __WOCKY_UTILS_H__ #include #include G_BEGIN_DECLS gboolean wocky_strdiff (const gchar *left, const gchar *right); gchar * wocky_normalise_jid (const gchar *jid); gboolean wocky_decode_jid (const gchar *jid, gchar **node, gchar **domain, gchar **resource); gchar *wocky_compose_jid (const gchar *node, const gchar *domain, const gchar *resource); GValue *wocky_g_value_slice_new (GType type); GValue *wocky_g_value_slice_new_boolean (gboolean b); GValue *wocky_g_value_slice_new_int (gint n); GValue *wocky_g_value_slice_new_int64 (gint64 n); GValue *wocky_g_value_slice_new_uint (guint n); GValue *wocky_g_value_slice_new_uint64 (guint64 n); GValue *wocky_g_value_slice_new_double (double d); GValue *wocky_g_value_slice_new_string (const gchar *string); GValue *wocky_g_value_slice_new_static_string (const gchar *string); GValue *wocky_g_value_slice_new_take_string (gchar *string); GValue *wocky_g_value_slice_new_boxed (GType type, gconstpointer p); GValue *wocky_g_value_slice_new_static_boxed (GType type, gconstpointer p); GValue *wocky_g_value_slice_new_take_boxed (GType type, gpointer p); void wocky_g_value_slice_free (GValue *value); GValue *wocky_g_value_slice_dup (const GValue *value); gboolean wocky_enum_from_nick (GType enum_type, const gchar *nick, gint *value); const gchar *wocky_enum_to_nick (GType enum_type, gint value); gchar *wocky_absolutize_path (const gchar *path); GList *wocky_list_deep_copy (GBoxedCopyFunc copy, GList *items); GString *wocky_g_string_dup (const GString *str); void wocky_g_string_free (GString *str); /* These are macros so that the critical message raised by * g_return_val_if_fail() contains the actual function name and tag. They * magically returns from the function rather than evaluating to a boolean * because doing the latter in macros seems to be a GCC extension. I could * probably rewrite them using , and ?: but... * * They should really be in GLib, but let's experiment here first. */ #define wocky_implement_finish_void(source, tag) \ G_STMT_START { \ GSimpleAsyncResult *_simple; \ _simple = (GSimpleAsyncResult *) result; \ if (g_simple_async_result_propagate_error ( \ _simple, error)) \ return FALSE; \ g_return_val_if_fail (g_simple_async_result_is_valid (result, \ G_OBJECT (source), (tag)), \ FALSE); \ return TRUE; \ } G_STMT_END #define wocky_implement_finish_copy_pointer(source, tag, copy_func, \ out_param) \ G_STMT_START { \ GSimpleAsyncResult *_simple; \ _simple = (GSimpleAsyncResult *) result; \ if (g_simple_async_result_propagate_error (_simple, error)) \ return FALSE; \ g_return_val_if_fail (g_simple_async_result_is_valid (result, \ G_OBJECT (source), (tag)), \ FALSE); \ if ((out_param) != NULL) \ { \ gpointer _p = g_simple_async_result_get_op_res_gpointer (_simple); \ if (_p != NULL) \ *(out_param) = (copy_func) (_p); \ else \ *(out_param) = NULL; \ } \ return TRUE; \ } G_STMT_END #define wocky_implement_finish_return_copy_pointer(source, tag, \ copy_func) \ G_STMT_START { \ GSimpleAsyncResult *_simple; \ gpointer _p; \ _simple = (GSimpleAsyncResult *) result; \ if (g_simple_async_result_propagate_error (_simple, error)) \ return NULL; \ g_return_val_if_fail (g_simple_async_result_is_valid (result, \ G_OBJECT (source), (tag)), \ NULL); \ _p = g_simple_async_result_get_op_res_gpointer (_simple); \ if (_p != NULL) \ return (copy_func) (_p); \ return NULL; \ } G_STMT_END #define wocky_implement_finish_return_pointer(source, tag) \ G_STMT_START { \ GSimpleAsyncResult *_simple; \ _simple = (GSimpleAsyncResult *) result; \ if (g_simple_async_result_propagate_error (_simple, error)) \ return NULL; \ g_return_val_if_fail (g_simple_async_result_is_valid (result, \ G_OBJECT (source), tag), \ NULL); \ return g_simple_async_result_get_op_res_gpointer (_simple); \ } G_STMT_END G_END_DECLS #endif /* #ifndef __WOCKY_UTILS_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-auth-handler.c0000664000175000017500000001073312005516162025710 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-auth-handler.h" #include "wocky-auth-registry.h" GType wocky_auth_handler_get_type (void) { static volatile gsize g_define_type_id__volatile = 0; if (g_once_init_enter (&g_define_type_id__volatile)) { const GTypeInfo info = { /* class_size */ sizeof (WockyAuthHandlerIface), /* base_init */ NULL, /* base_finalize */ NULL, /* class_init */ NULL, /* class_finalize */ NULL, /* class_data */ NULL, /* instance_size */ 0, /* n_preallocs */ 0, /* instance_init */ NULL, /* value_table */ NULL }; GType g_define_type_id = g_type_register_static ( G_TYPE_INTERFACE, "WockyAuthHandler", &info, 0); g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_OBJECT); g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); } return g_define_type_id__volatile; } /** * wocky_auth_handler_get_mechanism: * @handler: a handler for a SASL mechanism. * * Returns the name of the SASL mechanism @handler implements. * * Returns: the name of the SASL mechanism @handler implements. */ const gchar * wocky_auth_handler_get_mechanism (WockyAuthHandler *handler) { return WOCKY_AUTH_HANDLER_GET_IFACE (handler)->mechanism; } /** * wocky_auth_handler_is_plain: * @handler: a handler for a SASL mechanism. * * Checks whether @handler sends secrets in plaintext. This may be used to * decide whether to use @handler on an insecure XMPP connection. * * Returns: %TRUE if @handler sends secrets in plaintext. */ gboolean wocky_auth_handler_is_plain (WockyAuthHandler *handler) { return WOCKY_AUTH_HANDLER_GET_IFACE (handler)->plain; } /** * wocky_auth_handler_get_initial_response: * @handler: a handler for a SASL mechanism * @initial_data: (out) (transfer full): initial data to send to the server, if * any * @error: an optional location for a #GError to fill, or %NULL * * Called when authentication begins to fetch the initial data to send to the * server in the <auth/> stanza. * * If this function returns %TRUE, @initial_data will be non-%NULL if @handler * provides an initial response, and %NULL otherwise. * * Returns: %TRUE on success; %FALSE otherwise. */ gboolean wocky_auth_handler_get_initial_response (WockyAuthHandler *handler, GString **initial_data, GError **error) { WockyAuthInitialResponseFunc func = WOCKY_AUTH_HANDLER_GET_IFACE (handler)->initial_response_func; g_assert (initial_data != NULL); *initial_data = NULL; if (func == NULL) return TRUE; return func (handler, initial_data, error); } /** * wocky_auth_handler_handle_auth_data: * @handler: a #WockyAuthHandler object * @data: the challenge string * @response: (out) (transfer full): a location to fill with a challenge * response in a #GString * @error: an optional location for a #GError to fill, or %NULL * * Asks @handler to respond to a <challenge/> stanza or a * <success/> with data. On success, @handler will put * response data into @response, Base64-encoding it if appropriate. * * Returns: %TRUE on success, otherwise %FALSE */ gboolean wocky_auth_handler_handle_auth_data ( WockyAuthHandler *handler, const GString *data, GString **response, GError **error) { WockyAuthAuthDataFunc func = WOCKY_AUTH_HANDLER_GET_IFACE (handler)->auth_data_func; g_assert (response != NULL); *response = NULL; if (func == NULL) { g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, "Server send a challenge, but the mechanism didn't expect any"); return FALSE; } return func (handler, data, response, error); } /** * wocky_auth_handler_handle_success: * @handler: a #WockyAuthHandler object * @error: an optional location for a #GError to fill, or %NULL * * Called when a <success/> stanza is received * during authentication. If no error is returned, then authentication * is considered finished. (Typically, an error is only raised if the * <success/> stanza was received earlier than * expected) * * Returns: %TRUE on success, otherwise %FALSE */ gboolean wocky_auth_handler_handle_success ( WockyAuthHandler *handler, GError **error) { WockyAuthSuccessFunc func = WOCKY_AUTH_HANDLER_GET_IFACE (handler)->success_func; if (func == NULL) return TRUE; else return func (handler, error); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-ping.c0000664000175000017500000001445412005516162024275 0ustar00cassidycassidy00000000000000/* * wocky-ping.c - Source for WockyPing * Copyright (C) 2010 Collabora Ltd. * @author Senko Rasic * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** * SECTION: wocky-ping * @title: WockyPing * @short_description: support for pings/keepalives * * Support for XEP-0199 pings. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-ping.h" #include "wocky-heartbeat-source.h" #include "wocky-namespaces.h" #include "wocky-stanza.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_PING #include "wocky-debug-internal.h" G_DEFINE_TYPE (WockyPing, wocky_ping, G_TYPE_OBJECT) /* properties */ enum { PROP_PORTER = 1, PROP_PING_INTERVAL, }; /* private structure */ struct _WockyPingPrivate { WockyC2SPorter *porter; guint ping_interval; GSource *heartbeat; gulong ping_iq_cb; gboolean dispose_has_run; }; static void send_ping (WockyPing *self); static gboolean ping_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer data); static void wocky_ping_init (WockyPing *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_PING, WockyPingPrivate); } static void wocky_ping_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyPing *self = WOCKY_PING (object); WockyPingPrivate *priv = self->priv; switch (property_id) { case PROP_PORTER: priv->porter = g_value_dup_object (value); break; case PROP_PING_INTERVAL: priv->ping_interval = g_value_get_uint (value); DEBUG ("updated ping interval to %u", priv->ping_interval); if (priv->heartbeat != NULL) wocky_heartbeat_source_update_interval (priv->heartbeat, priv->ping_interval); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_ping_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyPing *self = WOCKY_PING (object); WockyPingPrivate *priv = self->priv; switch (property_id) { case PROP_PORTER: g_value_set_object (value, priv->porter); break; case PROP_PING_INTERVAL: g_value_set_uint (value, priv->ping_interval); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_ping_constructed (GObject *object) { WockyPing *self = WOCKY_PING (object); WockyPingPrivate *priv = self->priv; g_assert (priv->porter != NULL); priv->ping_iq_cb = wocky_porter_register_handler_from_anyone ( WOCKY_PORTER (priv->porter), WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, ping_iq_cb, self, '(', "ping", ':', WOCKY_XMPP_NS_PING, ')', NULL); priv->heartbeat = wocky_heartbeat_source_new (priv->ping_interval); g_source_set_callback (priv->heartbeat, (GSourceFunc) send_ping, self, NULL); g_source_attach (priv->heartbeat, NULL); } static void wocky_ping_dispose (GObject *object) { WockyPing *self = WOCKY_PING (object); WockyPingPrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; if (priv->ping_iq_cb != 0) { wocky_porter_unregister_handler (WOCKY_PORTER (priv->porter), priv->ping_iq_cb); priv->ping_iq_cb = 0; } g_object_unref (priv->porter); priv->porter = NULL; g_source_destroy (self->priv->heartbeat); g_source_unref (self->priv->heartbeat); self->priv->heartbeat = NULL; if (G_OBJECT_CLASS (wocky_ping_parent_class)->dispose) G_OBJECT_CLASS (wocky_ping_parent_class)->dispose (object); } static void wocky_ping_class_init (WockyPingClass *wocky_ping_class) { GObjectClass *object_class = G_OBJECT_CLASS (wocky_ping_class); GParamSpec *spec; g_type_class_add_private (wocky_ping_class, sizeof (WockyPingPrivate)); object_class->constructed = wocky_ping_constructed; object_class->set_property = wocky_ping_set_property; object_class->get_property = wocky_ping_get_property; object_class->dispose = wocky_ping_dispose; spec = g_param_spec_object ("porter", "Wocky C2S porter", "the wocky porter to set up keepalive pings on", WOCKY_TYPE_C2S_PORTER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_PORTER, spec); spec = g_param_spec_uint ("ping-interval", "Ping interval", "keepalive ping interval in seconds, or 0 to disable", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_PING_INTERVAL, spec); } WockyPing * wocky_ping_new (WockyC2SPorter *porter, guint interval) { g_return_val_if_fail (WOCKY_IS_C2S_PORTER (porter), NULL); return g_object_new (WOCKY_TYPE_PING, "porter", porter, "ping-interval", interval, NULL); } static void send_ping (WockyPing *self) { g_return_if_fail (WOCKY_IS_PING (self)); /* We send a whitespace ping and not a XMPP one to save bandwidth. * As much as it can sound a stupidly small gain, it can be useful when * sending pings on an idle cellular connection; very small packets can * be sent using a low power 3G channel. */ DEBUG ("pinging"); wocky_c2s_porter_send_whitespace_ping_async (self->priv->porter, NULL, NULL, NULL); } static gboolean ping_iq_cb (WockyPorter *porter, WockyStanza *stanza, gpointer data) { const gchar *from = wocky_stanza_get_from (stanza); DEBUG ("replying to ping from %s", from ? from : ""); wocky_porter_acknowledge_iq (porter, stanza, NULL); return TRUE; } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-caps-cache.c0000664000175000017500000004572711720661341025341 0ustar00cassidycassidy00000000000000/* * wocky-caps-cache.c - Source for WockyCapsCache * Copyright (C) 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-caps-cache.h" #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include #include "wocky-xmpp-reader.h" #include "wocky-xmpp-writer.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_PRESENCE #include "wocky-debug-internal.h" #define DB_USER_VERSION 2 G_DEFINE_TYPE (WockyCapsCache, wocky_caps_cache, G_TYPE_OBJECT) static WockyCapsCache *shared_cache = NULL; struct _WockyCapsCachePrivate { gchar *path; sqlite3 *db; guint inserts; WockyXmppReader *reader; WockyXmppWriter *writer; }; enum { PROP_PATH = 1, }; static void wocky_caps_cache_constructed (GObject *object); static gboolean caps_cache_get_one_uint (WockyCapsCache *self, const gchar *sql, guint *value); static void wocky_caps_cache_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyCapsCache *self = (WockyCapsCache *) object; switch (property_id) { case PROP_PATH: g_value_set_string (value, self->priv->path); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void wocky_caps_cache_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyCapsCache *self = (WockyCapsCache *) object; switch (property_id) { case PROP_PATH: g_free (self->priv->path); self->priv->path = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void wocky_caps_cache_dispose (GObject *object) { G_OBJECT_CLASS (wocky_caps_cache_parent_class)->dispose (object); } static void wocky_caps_cache_finalize (GObject *object) { WockyCapsCache *self = WOCKY_CAPS_CACHE (object); g_free (self->priv->path); self->priv->path = NULL; if (self->priv->db != NULL) { sqlite3_close (self->priv->db); self->priv->db = NULL; } if (self->priv->reader != NULL) { g_object_unref (self->priv->reader); self->priv->reader = NULL; } if (self->priv->writer != NULL) { g_object_unref (self->priv->writer); self->priv->writer = NULL; } G_OBJECT_CLASS (wocky_caps_cache_parent_class)->finalize (object); } static void wocky_caps_cache_class_init (WockyCapsCacheClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (WockyCapsCachePrivate)); object_class->constructed = wocky_caps_cache_constructed; object_class->get_property = wocky_caps_cache_get_property; object_class->set_property = wocky_caps_cache_set_property; object_class->dispose = wocky_caps_cache_dispose; object_class->finalize = wocky_caps_cache_finalize; /** * WockyCapsCache:path: * * The path on disk to the SQLite database where this * #WockyCapsCache stores its information. */ g_object_class_install_property (object_class, PROP_PATH, g_param_spec_string ("path", "Path", "The path to the cache", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } static gchar * get_path (void) { gchar *free_dir = NULL, *ret; const gchar *dir, *path; /* This should still work if it's the magic value ":memory:". */ path = g_getenv ("WOCKY_CAPS_CACHE"); if (path != NULL) { dir = free_dir = g_path_get_dirname (path); ret = g_strdup (path); } else { dir = g_getenv ("WOCKY_CACHE_DIR"); if (dir != NULL) { ret = g_build_path (G_DIR_SEPARATOR_S, dir, "caps-cache.db", NULL); } else { ret = g_build_path (G_DIR_SEPARATOR_S, g_get_user_cache_dir (), "wocky", "caps", "caps-cache.db", NULL); dir = free_dir = g_path_get_dirname (ret); } } /* Any errors are ignored here, on the basis that we'll find out the path is * duff when we try to open the database anyway. */ g_mkdir_with_parents (dir, 0755); g_free (free_dir); return ret; } static gboolean caps_cache_check_version (WockyCapsCache *self) { guint version; if (!caps_cache_get_one_uint (self, "PRAGMA user_version;", &version)) return FALSE; if (version == 0) { /* ______________________________________________________________________ ( Unfortunately the first incarnation of the caps cache db didn't set ) ( user_version, so we can't tell if 0 means this is a new, empty ) ( database or an old one. ) ( ) ( So... let's check if the capabilities table exists. If so, we'll ) ( pretend user_version was 1. ) ( ) ( When there's nothing left to burn, you have to set yourself on fire. ) ---------------------------------------------------------------------- o ^__^ o (oo)\_______ (__)\ )\/\ ||----w | || || */ guint dummy; if (caps_cache_get_one_uint (self, "PRAGMA table_info(capabilities)", &dummy)) { DEBUG ("capabilities table exists; this isn't a new database"); version = 1; } } switch (version) { case 0: DEBUG ("opened new, empty database at %s", self->priv->path); return TRUE; case DB_USER_VERSION: DEBUG ("opened %s, user_version %u", self->priv->path, version); return TRUE; default: DEBUG ("%s is version %u, not our version %u; let's nuke it", self->priv->path, version, DB_USER_VERSION); return FALSE; } } static gboolean caps_cache_open (WockyCapsCache *self) { gint ret; gchar *error; g_return_val_if_fail (self->priv->db == NULL, FALSE); ret = sqlite3_open (self->priv->path, &self->priv->db); if (ret != SQLITE_OK) { DEBUG ("opening database %s failed: %s", self->priv->path, sqlite3_errmsg (self->priv->db)); goto err; } if (!caps_cache_check_version (self)) goto err; ret = sqlite3_exec (self->priv->db, "PRAGMA user_version = " G_STRINGIFY (DB_USER_VERSION) ";" "PRAGMA journal_mode = MEMORY;" "PRAGMA synchronous = OFF", NULL, NULL, &error); if (ret != SQLITE_OK) { DEBUG ("failed to set user_version, turn off fsync() and " "turn off on-disk journalling: %s", error); sqlite3_free (error); goto err; } ret = sqlite3_exec (self->priv->db, "CREATE TABLE IF NOT EXISTS capabilities (\n" " node text PRIMARY KEY,\n" " disco_reply text,\n" " timestamp int)", NULL, NULL, &error); if (ret != SQLITE_OK) { DEBUG ("failed to ensure table exists: %s", error); sqlite3_free (error); goto err; } return TRUE; err: sqlite3_close (self->priv->db); self->priv->db = NULL; return FALSE; } static void nuke_it_and_try_again (WockyCapsCache *self) { int ret; g_return_if_fail (self->priv->path != NULL); g_return_if_fail (self->priv->db == NULL); ret = unlink (self->priv->path); if (ret != 0) DEBUG ("removing database failed: %s", g_strerror (errno)); else caps_cache_open (self); } static void close_nuke_and_reopen_database (WockyCapsCache *self) { g_return_if_fail (self->priv->db != NULL); DEBUG ("Database seems to be corrupt; blowing it away and reinitializing"); sqlite3_close (self->priv->db); self->priv->db = NULL; nuke_it_and_try_again (self); } static void wocky_caps_cache_constructed (GObject *object) { WockyCapsCache *self = WOCKY_CAPS_CACHE (object); if (!caps_cache_open (self)) { /* Couldn't open it, or it's got a different user_version. */ nuke_it_and_try_again (self); } if (self->priv->db == NULL) { DEBUG ("couldn't open db; giving up"); return; } self->priv->reader = wocky_xmpp_reader_new_no_stream (); self->priv->writer = wocky_xmpp_writer_new_no_stream (); } static void wocky_caps_cache_init (WockyCapsCache *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE ( self, WOCKY_TYPE_CAPS_CACHE, WockyCapsCachePrivate); } /** * wocky_caps_cache_new: * @path: full path to where the cache SQLite database should be stored * * Convenience function to create a new #WockyCapsCache. * * Returns: a new #WockyCapsCache. */ WockyCapsCache * wocky_caps_cache_new (const gchar *path) { return g_object_new (WOCKY_TYPE_CAPS_CACHE, "path", path, NULL); } /** * wocky_caps_cache_dup_shared: * * Returns a new or existing #WockyCapsCache object. * * The returned #WockyCapsCache is cached; the same #WockyCapsCache * object will be returned by this function repeatedly in the same * process. At the end of the process, the caller should call * wocky_caps_cache_free_shared() to shared the shared #WockyCapsCache * object. * * Returns: a new, or cached, #WockyCapsCache. */ WockyCapsCache * wocky_caps_cache_dup_shared (void) { if (shared_cache == NULL) { gchar *path; path = get_path (); shared_cache = wocky_caps_cache_new (path); g_free (path); } g_object_ref (shared_cache); return shared_cache; } /** * wocky_caps_cache_free_shared: * * Free the shared #WockyCapsCache instance which was created by * calling wocky_caps_cache_dup_shared(), or do nothing if said * function was not called. */ void wocky_caps_cache_free_shared (void) { if (shared_cache != NULL) { g_object_unref (shared_cache); shared_cache = NULL; } } static gboolean caps_cache_prepare (WockyCapsCache *self, const gchar *sql, sqlite3_stmt **stmt) { gint ret; g_return_val_if_fail (self->priv->db != NULL, FALSE); ret = sqlite3_prepare_v2 (self->priv->db, sql, -1, stmt, NULL); if (ret != SQLITE_OK) { g_warning ("preparing statement '%s' failed: %s", sql, sqlite3_errmsg (self->priv->db)); return FALSE; } g_assert (stmt != NULL); return TRUE; } /* Finalizes @stmt if an error happens. */ static gboolean caps_cache_bind_int (WockyCapsCache *self, sqlite3_stmt *stmt, gint param, gint value) { gint ret = sqlite3_bind_int (stmt, param, value); if (ret != SQLITE_OK) { g_warning ("parameter binding failed: %s", sqlite3_errmsg (self->priv->db)); sqlite3_finalize (stmt); return FALSE; } return TRUE; } /* Finalizes @stmt if an error happens. * * Note: the parameter is bound statically, so it mustn't be freed before the * statment is finalized. */ static gboolean caps_cache_bind_text (WockyCapsCache *self, sqlite3_stmt *stmt, gint param, gint len, const gchar *value) { gint ret = sqlite3_bind_text (stmt, param, value, len, SQLITE_STATIC); if (ret != SQLITE_OK) { g_warning ("parameter binding failed: %s", sqlite3_errmsg (self->priv->db)); sqlite3_finalize (stmt); return FALSE; } return TRUE; } /* * caps_cache_get_one_uint: * @self: the caps cache * @sql: a query expected to yield one row with one integer colum * @value: location at which to store that single unsigned integer * * Returns: %TRUE if @value was successfully retrieved; %FALSE otherwise. */ static gboolean caps_cache_get_one_uint (WockyCapsCache *self, const gchar *sql, guint *value) { sqlite3_stmt *stmt; int ret; if (!caps_cache_prepare (self, sql, &stmt)) return FALSE; ret = sqlite3_step (stmt); switch (ret) { case SQLITE_ROW: *value = sqlite3_column_int (stmt, 0); sqlite3_finalize (stmt); return TRUE; case SQLITE_DONE: DEBUG ("'%s' returned no results", sql); break; default: DEBUG ("executing '%s' failed: %s", sql, sqlite3_errmsg (self->priv->db)); } sqlite3_finalize (stmt); return FALSE; } /* Update cache entry timestmp. */ static void caps_cache_touch (WockyCapsCache *self, const gchar *node) { gint ret = SQLITE_OK; sqlite3_stmt *stmt; if (!caps_cache_prepare (self, "UPDATE capabilities SET timestamp=? WHERE node=?", &stmt)) return; if (!caps_cache_bind_int (self, stmt, 1, time (NULL))) return; if (!caps_cache_bind_text (self, stmt, 2, -1, node)) return; ret = sqlite3_step (stmt); if (ret != SQLITE_DONE) { DEBUG ("statement execution failed: %s", sqlite3_errmsg (self->priv->db)); } sqlite3_finalize (stmt); if (ret == SQLITE_CORRUPT) close_nuke_and_reopen_database (self); } /** * wocky_caps_cache_lookup: * @self: a #WockyCapsCache * @node: the node to look up in the cache * * Look up @node in the caps cache @self. The caller is responsible * for unreffing the returned #WockyNodeTree. * * Returns: a #WockyNodeTree if @node was found in the cache, or %NULL * if a match was not found */ WockyNodeTree * wocky_caps_cache_lookup (WockyCapsCache *self, const gchar *node) { gint ret; sqlite3_stmt *stmt; const guchar *value; int bytes; WockyNodeTree *query_node; if (!self->priv->db) /* DB open failed. */ return NULL; if (!caps_cache_prepare (self, "SELECT disco_reply FROM capabilities WHERE node=?", &stmt)) return NULL; if (!caps_cache_bind_text (self, stmt, 1, -1, node)) return NULL; ret = sqlite3_step (stmt); if (ret == SQLITE_DONE) { /* No result. */ DEBUG ("caps cache miss: %s", node); sqlite3_finalize (stmt); return NULL; } if (ret != SQLITE_ROW) { DEBUG ("statement execution failed: %s", sqlite3_errmsg (self->priv->db)); sqlite3_finalize (stmt); return NULL; } DEBUG ("caps cache hit: %s", node); value = sqlite3_column_text (stmt, 0); bytes = sqlite3_column_bytes (stmt, 0); wocky_xmpp_reader_push (self->priv->reader, value, bytes); query_node = (WockyNodeTree *) wocky_xmpp_reader_pop_stanza (self->priv->reader); sqlite3_finalize (stmt); if (query_node == NULL) { GError *error = wocky_xmpp_reader_get_error (self->priv->reader); g_warning ("could not parse query_node of %s: %s", node, (error != NULL ? error->message : "no error; incomplete xml?")); if (error != NULL) g_error_free (error); /* Destroy the town in order to save it. */ close_nuke_and_reopen_database (self); } else { caps_cache_touch (self, node); } wocky_xmpp_reader_reset (self->priv->reader); return query_node; } static void caps_cache_insert (WockyCapsCache *self, const gchar *node, WockyNodeTree *query_node) { const guint8 *val; gsize len; gint ret = SQLITE_OK; sqlite3_stmt *stmt; if (!caps_cache_prepare (self, "INSERT INTO capabilities (node, disco_reply, timestamp) " "VALUES (?, ?, ?)", &stmt)) return; if (!caps_cache_bind_text (self, stmt, 1, -1, node)) return; wocky_xmpp_writer_write_node_tree (self->priv->writer, query_node, &val, &len); if (!caps_cache_bind_text (self, stmt, 2, len, (const gchar *) val)) return; if (!caps_cache_bind_int (self, stmt, 3, time (NULL))) return; ret = sqlite3_step (stmt); if (ret == SQLITE_CONSTRAINT) /* Presumably the error is because the key already exists. Ignore it. */ goto OUT; if (ret != SQLITE_DONE) { DEBUG ("statement execution failed: %s", sqlite3_errmsg (self->priv->db)); } OUT: sqlite3_finalize (stmt); if (ret == SQLITE_CORRUPT) close_nuke_and_reopen_database (self); } static gboolean caps_cache_count_entries (WockyCapsCache *self, guint *count) { if (!self->priv->db) return FALSE; return caps_cache_get_one_uint (self, "SELECT COUNT(*) FROM capabilities", count); } /* If the number of entries is above @high_threshold, remove entries older * than @max_age while the cache is bigger than @low_threshold. */ static void caps_cache_gc (WockyCapsCache *self, guint high_threshold, guint low_threshold) { gint ret; guint count; sqlite3_stmt *stmt; if (!caps_cache_count_entries (self, &count)) return; if (count <= high_threshold) return; /* This emulates DELETE ... ORDER ... LIMIT because some Sqlites (e.g. * Debian) ship without SQLITE_ENABLE_UPDATE_DELETE_LIMIT unabled. */ if (!caps_cache_prepare (self, "DELETE FROM capabilities WHERE oid IN (" " SELECT oid FROM capabilities" " ORDER BY timestamp ASC, oid ASC" " LIMIT ?)", &stmt)) return; if (!caps_cache_bind_int (self, stmt, 1, count - low_threshold)) return; ret = sqlite3_step (stmt); if (ret == SQLITE_DONE) DEBUG ("cache reduced from %d to %d items", count, count - sqlite3_changes (self->priv->db)); else DEBUG ("statement execution failed: %s", sqlite3_errmsg (self->priv->db)); sqlite3_finalize (stmt); if (ret == SQLITE_CORRUPT) close_nuke_and_reopen_database (self); } static guint get_size (void) { static gboolean ready = FALSE; static guint size = 1000; if (G_UNLIKELY (!ready)) { const gchar *str = g_getenv ("WOCKY_CAPS_CACHE_SIZE"); if (str != NULL) { /* Ignoring return code; size will retain default value on failure. */ sscanf (str, "%u", &size); } ready = TRUE; /* DEBUG ("caps cache size = %d", size); */ } return size; } /** * wocky_caps_cache_insert: * @self: a #WockyCapsCache * @node: the capability node * @query_node: the query #WockyNodeTree associated with @node * * Adds a new item to the caps cache. @node is associated with * @query_node so that subsequent calls to wocky_caps_cache_lookup() * with the same @node value will return @query_node. */ void wocky_caps_cache_insert (WockyCapsCache *self, const gchar *node, WockyNodeTree *query_node) { guint size = get_size (); if (!self->priv->db) /* DB open failed. */ return; DEBUG ("caps cache insert: %s", node); caps_cache_insert (self, node, query_node); /* Remove old entries after every 50th insert. */ if (self->priv->inserts % 50 == 0) caps_cache_gc (self, size, MAX (1, 0.95 * size)); self->priv->inserts++; } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jingle-transport-rawudp.h0000664000175000017500000000503712212322440030136 0ustar00cassidycassidy00000000000000/* * wocky-jingle-transport-rawudp.h - Header for WockyJingleTransportRawUdp * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __JINGLE_TRANSPORT_RAWUDP_H__ #define __JINGLE_TRANSPORT_RAWUDP_H__ #include #include "wocky-jingle-types.h" G_BEGIN_DECLS typedef struct _WockyJingleTransportRawUdpClass WockyJingleTransportRawUdpClass; GType wocky_jingle_transport_rawudp_get_type (void); /* TYPE MACROS */ #define WOCKY_TYPE_JINGLE_TRANSPORT_RAWUDP \ (wocky_jingle_transport_rawudp_get_type ()) #define WOCKY_JINGLE_TRANSPORT_RAWUDP(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_JINGLE_TRANSPORT_RAWUDP, \ WockyJingleTransportRawUdp)) #define WOCKY_JINGLE_TRANSPORT_RAWUDP_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_JINGLE_TRANSPORT_RAWUDP, \ WockyJingleTransportRawUdpClass)) #define WOCKY_IS_JINGLE_TRANSPORT_RAWUDP(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_JINGLE_TRANSPORT_RAWUDP)) #define WOCKY_IS_JINGLE_TRANSPORT_RAWUDP_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_JINGLE_TRANSPORT_RAWUDP)) #define WOCKY_JINGLE_TRANSPORT_RAWUDP_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_JINGLE_TRANSPORT_RAWUDP, \ WockyJingleTransportRawUdpClass)) struct _WockyJingleTransportRawUdpClass { GObjectClass parent_class; }; typedef struct _WockyJingleTransportRawUdpPrivate WockyJingleTransportRawUdpPrivate; struct _WockyJingleTransportRawUdp { GObject parent; WockyJingleTransportRawUdpPrivate *priv; }; void jingle_transport_rawudp_register (WockyJingleFactory *factory); G_END_DECLS #endif /* __JINGLE_TRANSPORT_RAWUDP_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jingle-factory.c0000664000175000017500000004277512212322440026256 0ustar00cassidycassidy00000000000000/* * wocky-jingle-factory.c - Support for XEP-0166 (Jingle) * * Copyright (C) 2006-2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "wocky-jingle-factory.h" #include #include #include #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_JINGLE #include "wocky-debug-internal.h" #include "wocky-signals-marshal.h" #include "wocky-jingle-media-rtp.h" #include "wocky-jingle-session.h" #include "wocky-jingle-transport-google.h" #include "wocky-jingle-transport-rawudp.h" #include "wocky-jingle-transport-iceudp.h" #include "wocky-namespaces.h" #include "wocky-session.h" #include "wocky-utils.h" #include "wocky-google-relay.h" G_DEFINE_TYPE(WockyJingleFactory, wocky_jingle_factory, G_TYPE_OBJECT); /* signal enum */ enum { NEW_SESSION, QUERY_CAP, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; /* properties */ enum { PROP_SESSION = 1, LAST_PROPERTY }; struct _WockyJingleFactoryPrivate { WockySession *session; WockyPorter *porter; guint jingle_handler_id; GHashTable *content_types; GHashTable *transports; /* instances of SESSION_MAP_KEY_FORMAT => WockyJingleSession. */ GHashTable *sessions; WockyJingleInfo *jingle_info; gboolean dispose_has_run; }; static gboolean jingle_cb ( WockyPorter *porter, WockyStanza *msg, gpointer user_data); static WockyJingleSession *create_session (WockyJingleFactory *fac, const gchar *sid, const gchar *jid, WockyJingleDialect dialect, gboolean local_hold); static gboolean session_query_cap_cb ( WockyJingleSession *session, WockyContact *contact, const gchar *cap_or_quirk, gpointer user_data); static void session_terminated_cb (WockyJingleSession *sess, gboolean local_terminator, WockyJingleReason reason, const gchar *text, WockyJingleFactory *fac); static void attach_to_wocky_session (WockyJingleFactory *self); static void wocky_jingle_factory_init (WockyJingleFactory *obj) { WockyJingleFactoryPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, WOCKY_TYPE_JINGLE_FACTORY, WockyJingleFactoryPrivate); obj->priv = priv; priv->sessions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); priv->transports = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); priv->content_types = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); priv->dispose_has_run = FALSE; } static void wocky_jingle_factory_dispose (GObject *object) { WockyJingleFactory *fac = WOCKY_JINGLE_FACTORY (object); WockyJingleFactoryPrivate *priv = fac->priv; GHashTableIter iter; gpointer val; if (priv->dispose_has_run) return; DEBUG ("dispose called"); priv->dispose_has_run = TRUE; wocky_jingle_factory_stop (fac); g_clear_object (&priv->session); g_clear_object (&priv->porter); g_hash_table_iter_init (&iter, priv->sessions); while (g_hash_table_iter_next (&iter, NULL, &val)) g_signal_handlers_disconnect_by_func (val, session_query_cap_cb, fac); g_hash_table_unref (priv->sessions); priv->sessions = NULL; g_hash_table_unref (priv->content_types); priv->content_types = NULL; g_hash_table_unref (priv->transports); priv->transports = NULL; g_clear_object (&priv->jingle_info); if (G_OBJECT_CLASS (wocky_jingle_factory_parent_class)->dispose) G_OBJECT_CLASS (wocky_jingle_factory_parent_class)->dispose (object); } static void wocky_jingle_factory_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyJingleFactory *chan = WOCKY_JINGLE_FACTORY (object); WockyJingleFactoryPrivate *priv = chan->priv; switch (property_id) { case PROP_SESSION: g_value_set_object (value, priv->session); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_jingle_factory_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyJingleFactory *chan = WOCKY_JINGLE_FACTORY (object); WockyJingleFactoryPrivate *priv = chan->priv; switch (property_id) { case PROP_SESSION: priv->session = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_jingle_factory_constructed (GObject *obj) { WockyJingleFactory *self = WOCKY_JINGLE_FACTORY (obj); GObjectClass *parent = G_OBJECT_CLASS (wocky_jingle_factory_parent_class); if (parent->constructed != NULL) parent->constructed (obj); attach_to_wocky_session (self); jingle_media_rtp_register (self); jingle_transport_google_register (self); jingle_transport_rawudp_register (self); jingle_transport_iceudp_register (self); } static void wocky_jingle_factory_class_init (WockyJingleFactoryClass *cls) { GObjectClass *object_class = G_OBJECT_CLASS (cls); GParamSpec *param_spec; g_type_class_add_private (cls, sizeof (WockyJingleFactoryPrivate)); object_class->constructed = wocky_jingle_factory_constructed; object_class->get_property = wocky_jingle_factory_get_property; object_class->set_property = wocky_jingle_factory_set_property; object_class->dispose = wocky_jingle_factory_dispose; param_spec = g_param_spec_object ("session", "WockySession object", "WockySession to listen for Jingle sessions on", WOCKY_TYPE_SESSION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SESSION, param_spec); /* signal definitions */ /* * @session: a fresh new Jingle session for your listening pleasure * @initiated_locally: %TRUE if this is a new outgoing session; %FALSE if it * is a new incoming session */ signals[NEW_SESSION] = g_signal_new ("new-session", G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT_BOOL, G_TYPE_NONE, 2, WOCKY_TYPE_JINGLE_SESSION, G_TYPE_BOOLEAN); /* * @contact: the peer in a call * @cap: the XEP-0115 feature string the session is interested in. * * Emitted when a Jingle session wants to check whether the peer has a * particular capability. The handler should return %TRUE if @contact has * @cap. */ signals[QUERY_CAP] = g_signal_new ("query-cap", G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST, 0, g_signal_accumulator_first_wins, NULL, _wocky_signals_marshal_BOOLEAN__OBJECT_STRING, G_TYPE_BOOLEAN, 2, WOCKY_TYPE_CONTACT, G_TYPE_STRING); } WockyJingleFactory * wocky_jingle_factory_new ( WockySession *session) { return g_object_new (WOCKY_TYPE_JINGLE_FACTORY, "session", session, NULL); } static void attach_to_wocky_session (WockyJingleFactory *self) { WockyJingleFactoryPrivate *priv = self->priv; g_assert (priv->session != NULL); g_assert (priv->porter == NULL); priv->porter = g_object_ref (wocky_session_get_porter (priv->session)); /* TODO: we could match different dialects here maybe? */ priv->jingle_handler_id = wocky_porter_register_handler_from_anyone ( priv->porter, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, jingle_cb, self, NULL); priv->jingle_info = wocky_jingle_info_new (priv->porter); } void wocky_jingle_factory_stop (WockyJingleFactory *self) { WockyJingleFactoryPrivate *priv = self->priv; if (priv->porter != NULL && priv->jingle_handler_id != 0) { wocky_porter_unregister_handler (priv->porter, priv->jingle_handler_id); priv->jingle_handler_id = 0; } } /* The 'session' map is keyed by: * "\n" */ #define SESSION_MAP_KEY_FORMAT "%s\n%s" static gchar * make_session_map_key ( const gchar *jid, const gchar *sid) { return g_strdup_printf (SESSION_MAP_KEY_FORMAT, jid, sid); } static gchar * get_unique_sid_for (WockyJingleFactory *factory, const gchar *jid, gchar **key) { guint32 val; gchar *sid = NULL; gchar *key_ = NULL; do { val = g_random_int_range (1000000, G_MAXINT); g_free (sid); g_free (key_); sid = g_strdup_printf ("%u", val); key_ = make_session_map_key (jid, sid); } while (g_hash_table_lookup (factory->priv->sessions, key_) != NULL); *key = key_; return sid; } static WockyJingleSession * ensure_session (WockyJingleFactory *self, const gchar *sid, const gchar *from, WockyJingleAction action, WockyJingleDialect dialect, gboolean *new_session, GError **error) { WockyJingleFactoryPrivate *priv = self->priv; gchar *key; WockyJingleSession *sess; if (!wocky_decode_jid (from, NULL, NULL, NULL)) { g_prefix_error (error, "Couldn't parse sender '%s': ", from); return NULL; } /* If we can ensure the handle, we can decode the jid */ key = make_session_map_key (from, sid); sess = g_hash_table_lookup (priv->sessions, key); g_free (key); if (sess == NULL) { if (action == WOCKY_JINGLE_ACTION_SESSION_INITIATE) { sess = create_session (self, sid, from, dialect, FALSE); *new_session = TRUE; } else { g_set_error (error, WOCKY_JINGLE_ERROR, WOCKY_JINGLE_ERROR_UNKNOWN_SESSION, "session %s is unknown", sid); return NULL; } } else { *new_session = FALSE; } return sess; } static gboolean jingle_cb ( WockyPorter *porter, WockyStanza *msg, gpointer user_data) { WockyJingleFactory *self = WOCKY_JINGLE_FACTORY (user_data); GError *error = NULL; const gchar *sid, *from; WockyJingleSession *sess; gboolean new_session = FALSE; WockyJingleAction action; WockyJingleDialect dialect; /* see if it's a jingle message and detect dialect */ sid = wocky_jingle_session_detect (msg, &action, &dialect); from = wocky_stanza_get_from (msg); if (sid == NULL || from == NULL) return FALSE; sess = ensure_session (self, sid, from, action, dialect, &new_session, &error); if (sess == NULL) goto REQUEST_ERROR; else /* One of the possible outcomes of wocky_jingle_session_parse() is that * the Jingle session is terminated, which removes it from our * hash table, which could release its last ref. */ g_object_ref (sess); /* now act on the message */ if (!wocky_jingle_session_parse (sess, action, msg, &error)) goto REQUEST_ERROR; /* This has to be after the call to parse(), not inside create_session(): * until the session has parsed the session-initiate stanza, it does not know * about its own contents, and we don't even know if the content types are * something we understand. So it's essentially half-alive and useless to * signal listeners. */ if (new_session) g_signal_emit (self, signals[NEW_SESSION], 0, sess, FALSE); /* all went well, we can acknowledge the IQ */ wocky_jingle_session_acknowledge_iq (sess, msg); g_object_unref (sess); return TRUE; REQUEST_ERROR: g_assert (error != NULL); DEBUG ("NAKing with error: %s", error->message); wocky_porter_send_iq_gerror (porter, msg, error); g_error_free (error); if (sess != NULL) { if (new_session) wocky_jingle_session_terminate (sess, WOCKY_JINGLE_REASON_UNKNOWN, NULL, NULL); g_object_unref (sess); } return TRUE; } static gboolean session_query_cap_cb ( WockyJingleSession *session, WockyContact *contact, const gchar *cap_or_quirk, gpointer user_data) { WockyJingleFactory *self = WOCKY_JINGLE_FACTORY (user_data); gboolean ret; /* Propagate the query out to the application. We can't depend on the * application connecting to ::query-cap on the session because caps queries * may happen while parsing the session-initiate stanza, which must happen * before the session is announced to the application. */ g_signal_emit (self, signals[QUERY_CAP], 0, contact, cap_or_quirk, &ret); return ret; } /* * If sid is set to NULL a unique sid is generated and * the "local-initiator" property of the newly created * WockyJingleSession is set to true. */ static WockyJingleSession * create_session (WockyJingleFactory *fac, const gchar *sid, const gchar *jid, WockyJingleDialect dialect, gboolean local_hold) { WockyJingleFactoryPrivate *priv = fac->priv; WockyJingleSession *sess; gboolean local_initiator; gchar *sid_, *key; gpointer contact; WockyContactFactory *factory; factory = wocky_session_get_contact_factory (priv->session); g_assert (jid != NULL); if (strchr (jid, '/') != NULL) contact = wocky_contact_factory_ensure_resource_contact (factory, jid); else contact = wocky_contact_factory_ensure_bare_contact (factory, jid); g_return_val_if_fail (contact != NULL, NULL); g_return_val_if_fail (WOCKY_IS_CONTACT (contact), NULL); if (sid != NULL) { key = make_session_map_key (jid, sid); sid_ = g_strdup (sid); local_initiator = FALSE; } else { sid_ = get_unique_sid_for (fac, jid, &key); local_initiator = TRUE; } /* Either we should have found the existing session when the IQ arrived, or * get_unique_sid_for should have ensured the key is fresh. */ g_assert (NULL == g_hash_table_lookup (priv->sessions, key)); sess = wocky_jingle_session_new ( fac, priv->porter, sid_, local_initiator, contact, dialect, local_hold); g_signal_connect (sess, "terminated", (GCallback) session_terminated_cb, fac); /* Takes ownership of key and sess */ g_hash_table_insert (priv->sessions, key, sess); DEBUG ("new session (%s, %s) @ %p", jid, sid_, sess); g_free (sid_); g_object_unref (contact); g_signal_connect (sess, "query-cap", (GCallback) session_query_cap_cb, (GObject *) fac); return sess; } /** * wocky_jingle_factory_create_session: * @fac: the factory * @jid: the full JID (typically including a resource) to establish a session * with * @dialect: the variant of the Jingle protocol to use * @local_hold: whether the call should start out on hold; if in doubt, pass %FALSE * * Creates a new #WockyJingleSession to the specified contact. Note that the * session will not be initiated until at least one content is added with * wocky_jingle_session_add_content(), and those contents are ready. * * You would typically determine which @dialect to use from the peer's * capabilities. * * Returns: (transfer none): the new session, which will not be %NULL */ WockyJingleSession * wocky_jingle_factory_create_session (WockyJingleFactory *fac, const gchar *jid, WockyJingleDialect dialect, gboolean local_hold) { WockyJingleSession *session = create_session (fac, NULL, jid, dialect, local_hold); g_signal_emit (fac, signals[NEW_SESSION], 0, session, TRUE); return session; } void wocky_jingle_factory_register_transport (WockyJingleFactory *self, gchar *xmlns, GType transport_type) { g_return_if_fail (g_type_is_a (transport_type, WOCKY_TYPE_JINGLE_TRANSPORT_IFACE)); g_hash_table_insert (self->priv->transports, xmlns, GSIZE_TO_POINTER (transport_type)); } GType wocky_jingle_factory_lookup_transport (WockyJingleFactory *self, const gchar *xmlns) { return GPOINTER_TO_SIZE (g_hash_table_lookup (self->priv->transports, xmlns)); } void wocky_jingle_factory_register_content_type (WockyJingleFactory *self, gchar *xmlns, GType content_type) { g_return_if_fail (g_type_is_a (content_type, WOCKY_TYPE_JINGLE_CONTENT)); g_hash_table_insert (self->priv->content_types, xmlns, GSIZE_TO_POINTER (content_type)); } GType wocky_jingle_factory_lookup_content_type (WockyJingleFactory *self, const gchar *xmlns) { return GPOINTER_TO_SIZE (g_hash_table_lookup (self->priv->content_types, xmlns)); } static void session_terminated_cb (WockyJingleSession *session, gboolean local_terminator G_GNUC_UNUSED, WockyJingleReason reason G_GNUC_UNUSED, const gchar *text G_GNUC_UNUSED, WockyJingleFactory *factory) { gchar *key = make_session_map_key ( wocky_jingle_session_get_peer_jid (session), wocky_jingle_session_get_sid (session)); DEBUG ("removing terminated session with key %s", key); g_signal_handlers_disconnect_by_func (session, session_query_cap_cb, factory); g_warn_if_fail (g_hash_table_remove (factory->priv->sessions, key)); g_free (key); } WockyJingleInfo * wocky_jingle_factory_get_jingle_info ( WockyJingleFactory *self) { return self->priv->jingle_info; } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jabber-auth-digest.c0000664000175000017500000001117712005516162027000 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-jabber-auth-digest.h" #include "wocky-auth-registry.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_AUTH #include "wocky-debug-internal.h" static void auth_handler_iface_init (gpointer g_iface); G_DEFINE_TYPE_WITH_CODE (WockyJabberAuthDigest, wocky_jabber_auth_digest, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (WOCKY_TYPE_AUTH_HANDLER, auth_handler_iface_init)) enum { PROP_SESSION_ID = 1, PROP_PASSWORD, }; struct _WockyJabberAuthDigestPrivate { gchar *session_id; gchar *password; }; static void wocky_jabber_auth_digest_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyJabberAuthDigest *self = WOCKY_JABBER_AUTH_DIGEST (object); WockyJabberAuthDigestPrivate *priv = self->priv; switch (property_id) { case PROP_SESSION_ID: g_value_set_string (value, priv->session_id); break; case PROP_PASSWORD: g_value_set_string (value, priv->password); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void wocky_jabber_auth_digest_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyJabberAuthDigest *self = WOCKY_JABBER_AUTH_DIGEST (object); WockyJabberAuthDigestPrivate *priv = self->priv; switch (property_id) { case PROP_SESSION_ID: g_free (priv->session_id); priv->session_id = g_value_dup_string (value); break; case PROP_PASSWORD: g_free (priv->password); priv->password = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void wocky_jabber_auth_digest_dispose (GObject *object) { WockyJabberAuthDigest *self = WOCKY_JABBER_AUTH_DIGEST (object); WockyJabberAuthDigestPrivate *priv = self->priv; g_free (priv->session_id); g_free (priv->password); G_OBJECT_CLASS (wocky_jabber_auth_digest_parent_class)->dispose (object); } static void wocky_jabber_auth_digest_class_init (WockyJabberAuthDigestClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (WockyJabberAuthDigestPrivate)); object_class->get_property = wocky_jabber_auth_digest_get_property; object_class->set_property = wocky_jabber_auth_digest_set_property; object_class->dispose = wocky_jabber_auth_digest_dispose; g_object_class_install_property (object_class, PROP_SESSION_ID, g_param_spec_string ("session-id", "session-id", "The session_id to authenticate with", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_PASSWORD, g_param_spec_string ("password", "password", "The password to authenticate with", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); } static gboolean digest_initial_response (WockyAuthHandler *handler, GString **initial_data, GError **error); static void auth_handler_iface_init (gpointer g_iface) { WockyAuthHandlerIface *iface = g_iface; iface->mechanism = WOCKY_AUTH_MECH_JABBER_DIGEST; iface->plain = FALSE; iface->initial_response_func = digest_initial_response; } static void wocky_jabber_auth_digest_init (WockyJabberAuthDigest *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE ( self, WOCKY_TYPE_JABBER_AUTH_DIGEST, WockyJabberAuthDigestPrivate); } WockyJabberAuthDigest * wocky_jabber_auth_digest_new (const gchar *session_id, const gchar *password) { return g_object_new (WOCKY_TYPE_JABBER_AUTH_DIGEST, "session-id", session_id, "password", password, NULL); } static GString * digest_generate_initial_response (const gchar *session_id, const gchar *password) { gchar *hsrc = g_strconcat (session_id, password, NULL); gchar *sha1 = g_compute_checksum_for_string (G_CHECKSUM_SHA1, hsrc, -1); GString *response = g_string_new (sha1); g_free (hsrc); g_free (sha1); return response; } static gboolean digest_initial_response (WockyAuthHandler *handler, GString **initial_data, GError **error) { WockyJabberAuthDigest *self = WOCKY_JABBER_AUTH_DIGEST (handler); WockyJabberAuthDigestPrivate *priv = self->priv; if (priv->password == NULL || priv->session_id == NULL) { g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NO_CREDENTIALS, "No session-id or password provided"); return FALSE; } DEBUG ("Got session-id and password"); *initial_data = digest_generate_initial_response (priv->session_id, priv->password); return TRUE; } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-pubsub-service-protected.h0000664000175000017500000000417711720661341030276 0ustar00cassidycassidy00000000000000/* * wocky-pubsub-service-protected.h - protected methods on WockyPubsubService * Copyright © 2010 Collabora Ltd. * Copyright © 2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef WOCKY_PUBSUB_SERVICE_PROTECTED_H #define WOCKY_PUBSUB_SERVICE_PROTECTED_H #include "wocky-pubsub-service.h" WockyStanza *wocky_pubsub_service_create_retrieve_subscriptions_stanza ( WockyPubsubService *self, WockyPubsubNode *node, WockyNode **pubsub_node, WockyNode **subscriptions_node); WockyPubsubSubscription * wocky_pubsub_service_parse_subscription (WockyPubsubService *self, WockyNode *subscription_node, const gchar *parent_node_attr, GError **error); GList * wocky_pubsub_service_parse_subscriptions (WockyPubsubService *self, WockyNode *subscriptions_node, GList **subscription_nodes); WockyStanza *wocky_pubsub_service_create_create_node_stanza ( WockyPubsubService *self, const gchar *name, WockyDataForm *config, WockyNode **pubsub_node, WockyNode **create_node); WockyPubsubNode *wocky_pubsub_service_handle_create_node_reply ( WockyPubsubService *self, WockyNodeTree *create_tree, const gchar *requested_name, GError **error); WockyPorter *wocky_pubsub_service_get_porter (WockyPubsubService *self); #endif /* WOCKY_PUBSUB_SERVICE_PROTECTED_H */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-connector.c0000664000175000017500000022044312212322440025321 0ustar00cassidycassidy00000000000000/* * wocky-connector.c - Source for WockyConnector * Copyright © 2009 Collabora Ltd. * @author Vivek Dasmohapatra * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** * SECTION: wocky-connector * @title: WockyConnector * @short_description: Low-level XMPP connection generator. * @include: wocky/wocky-connector.h * * See: RFC3920 XEP-0077 * * Sends and receives #WockyStanzas from an underlying #GIOStream. * negotiating TLS if possible and completing authentication with the server * by the "most suitable" method available. * Returns a #WockyXmppConnection object to the user on successful completion. * * Can also be used to register or unregister an account: When unregistering * (cancelling) an account, a #WockyXmppConnection is NOT returned - a #gboolean * value indicating success or failure is returned instead. * * The WOCKY_DEBUG tag for this module is "connector". * * The flow of control during connection is roughly as follows: * (registration/cancellation flows are not represented with here) * * * * tcp_srv_connected * │ * ├→ tcp_host_connected * │ ↓ * └→ maybe_old_ssl * ↓ * xmpp_init ←─────────────────┬──┐ * ↓ │ │ * xmpp_init_sent_cb │ │ * ↓ │ │ * xmpp_init_recv_cb │ │ * │ ↓ │ │ * │ xmpp_features_cb │ │ * │ │ │ ↓ │ │ * │ │ │ tls_module_secure_cb ─┘ │ ① * │ │ ↓ │ ↑ * │ │ sasl_request_auth │ jabber_auth_done * │ │ ↓ │ ↑ * │ │ sasl_auth_done ────────┴─[no sasl]─→ jabber_request_auth * │ ↓ ↑ * │ iq_bind_resource │ * │ ↓ │ * │ iq_bind_resource_sent_cb │ * │ ↓ │ * │ iq_bind_resource_recv_cb │ * │ ↓ │ * │ ① │ * └──────────[old auth]────────────────────┘ * * ① * ↓ * establish_session ─────────→ success * ↓ ↑ * establish_session_sent_cb │ * ↓ │ * establish_session_recv_cb ─────┘ * * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-connector.h" #include #include #include #ifdef HAVE_UNISTD_H # include #endif #include #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_CONNECTOR #include "wocky-debug-internal.h" #include "wocky-http-proxy.h" #include "wocky-sasl-auth.h" #include "wocky-tls-handler.h" #include "wocky-tls-connector.h" #include "wocky-jabber-auth.h" #include "wocky-namespaces.h" #include "wocky-xmpp-connection.h" #include "wocky-xmpp-error.h" #include "wocky-signals-marshal.h" #include "wocky-utils.h" G_DEFINE_TYPE (WockyConnector, wocky_connector, G_TYPE_OBJECT); enum { CONNECTION_ESTABLISHED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; static void wocky_connector_class_init (WockyConnectorClass *klass); /* XMPP connect/auth/etc handlers */ static void tcp_srv_connected (GObject *source, GAsyncResult *result, gpointer connector); static void tcp_host_connected (GObject *source, GAsyncResult *result, gpointer connector); static void maybe_old_ssl (WockyConnector *self); static void xmpp_init (WockyConnector *connector); static void xmpp_init_sent_cb (GObject *source, GAsyncResult *result, gpointer data); static void xmpp_init_recv_cb (GObject *source, GAsyncResult *result, gpointer data); static void xmpp_features_cb (GObject *source, GAsyncResult *result, gpointer data); static void tls_connector_secure_cb (GObject *source, GAsyncResult *res, gpointer user_data); static void sasl_request_auth (WockyConnector *object, WockyStanza *stanza); static void sasl_auth_done (GObject *source, GAsyncResult *result, gpointer data); static void xep77_begin (WockyConnector *self); static void xep77_begin_sent (GObject *source, GAsyncResult *result, gpointer data); static void xep77_begin_recv (GObject *source, GAsyncResult *result, gpointer data); static void xep77_cancel_send (WockyConnector *self); static void xep77_cancel_sent (GObject *source, GAsyncResult *res, gpointer data); static void xep77_cancel_recv (GObject *source, GAsyncResult *res, gpointer data); static void xep77_signup_send (WockyConnector *self, WockyNode *req); static void xep77_signup_sent (GObject *source, GAsyncResult *result, gpointer data); static void xep77_signup_recv (GObject *source, GAsyncResult *result, gpointer data); static void iq_bind_resource (WockyConnector *self); static void iq_bind_resource_sent_cb (GObject *source, GAsyncResult *result, gpointer data); static void iq_bind_resource_recv_cb (GObject *source, GAsyncResult *result, gpointer data); void establish_session (WockyConnector *self); static void establish_session_sent_cb (GObject *source, GAsyncResult *result, gpointer data); static void establish_session_recv_cb (GObject *source, GAsyncResult *result, gpointer data); /* old-style jabber auth handlers */ static void jabber_request_auth (WockyConnector *self); static void jabber_auth_done (GObject *source, GAsyncResult *res, gpointer data); /* private methods */ static void wocky_connector_dispose (GObject *object); static void wocky_connector_finalize (GObject *object); enum { PROP_JID = 1, PROP_PASS, PROP_AUTH_INSECURE_OK, PROP_ENC_PLAIN_AUTH_OK, PROP_RESOURCE, PROP_TLS_REQUIRED, PROP_XMPP_PORT, PROP_XMPP_HOST, PROP_IDENTITY, PROP_FEATURES, PROP_LEGACY, PROP_LEGACY_SSL, PROP_SESSION_ID, PROP_EMAIL, PROP_AUTH_REGISTRY, PROP_TLS_HANDLER, }; /* this tracks which XEP 0077 operation (register account, cancel account) * * we are attempting (if any). There is at leats one other XEP77 operation, * * password change - but we don't deal with that here as it's not really a * * connector operation: */ typedef enum { XEP77_NONE, XEP77_SIGNUP, XEP77_CANCEL, } WockyConnectorXEP77Op; typedef enum { WCON_DISCONNECTED, WCON_TCP_CONNECTING, WCON_TCP_CONNECTED, WCON_XMPP_AUTHED, WCON_XMPP_BOUND, } WockyConnectorState; struct _WockyConnectorPrivate { /* caller's choices about what to allow/disallow */ gboolean auth_insecure_ok; /* can we auth over non-ssl */ gboolean encrypted_plain_auth_ok; /* plaintext auth over secure channel */ /* xmpp account related properties */ gboolean tls_required; guint xmpp_port; gchar *xmpp_host; gchar *pass; gchar *email; gchar *jid; gchar *resource; /* the /[...] part of the jid, if any */ gchar *user; /* the [...]@ part of the initial JID */ gchar *domain; /* the @[...]/ part of the initial JID */ /* volatile/derived property: identity = jid, but may be updated by server: */ gchar *identity; /* if the server hands us a new JID (not handled yet) */ gboolean legacy_support; gboolean legacy_ssl; gchar *session_id; gchar *ca; /* file or dir containing x509 CA files */ /* XMPP connection data */ WockyStanza *features; /* misc internal state: */ WockyConnectorState state; gboolean dispose_has_run; gboolean authed; gboolean encrypted; gboolean connected; /* register/cancel account, or normal login */ WockyConnectorXEP77Op reg_op; GSimpleAsyncResult *result; GCancellable *cancellable; /* Used to hold the error from connecting to the result of an SRV lookup * while we fall back to connecting directly to the host. */ GError *srv_connect_error /* jesus christ it's a lion */; /* socket/tls/etc structures */ GSocketClient *client; GSocketConnection *sock; WockyXmppConnection *conn; WockyTLSHandler *tls_handler; WockyAuthRegistry *auth_registry; guint see_other_host_count; }; /* choose an appropriate chunk of text describing our state for debug/error */ static const gchar * state_message (WockyConnectorPrivate *priv) { if (priv->authed) return "Authentication Completed"; else if (priv->encrypted) { if (priv->legacy_ssl) return "SSL Negotiated"; else return "TLS Negotiated"; } else if (priv->connected) return "TCP Connection Established"; else return "Connecting... "; } static void complete_operation (WockyConnector *connector) { WockyConnectorPrivate *priv = connector->priv; GSimpleAsyncResult *tmp; tmp = priv->result; priv->result = NULL; g_simple_async_result_complete (tmp); g_object_unref (tmp); } static void abort_connect_error (WockyConnector *connector, GError **error, const char *fmt, ...) { WockyConnectorPrivate *priv = NULL; va_list args; DEBUG ("connector: %p", connector); priv = connector->priv; g_assert (error != NULL); g_assert (*error != NULL); va_start (args, fmt); if ((fmt != NULL) && (*fmt != '\0')) { gchar *msg = g_strdup_vprintf (fmt, args); g_prefix_error (error, "%s: ", msg); g_free (msg); } va_end (args); if (priv->sock != NULL) { g_object_unref (priv->sock); priv->sock = NULL; } priv->state = WCON_DISCONNECTED; if (priv->cancellable != NULL) { g_object_unref (priv->cancellable); priv->cancellable = NULL; } g_simple_async_result_set_from_error (priv->result, *error); complete_operation (connector); } static void abort_connect (WockyConnector *connector, GError *error) { WockyConnectorPrivate *priv = connector->priv; if (priv->sock != NULL) { g_object_unref (priv->sock); priv->sock = NULL; } priv->state = WCON_DISCONNECTED; if (priv->cancellable != NULL) { g_object_unref (priv->cancellable); priv->cancellable = NULL; } g_simple_async_result_set_from_error (priv->result, error); complete_operation (connector); } static void abort_connect_code (WockyConnector *connector, int code, const char *fmt, ...) { GError *err = NULL; va_list args; va_start (args, fmt); err = g_error_new_valist (WOCKY_CONNECTOR_ERROR, code, fmt, args); va_end (args); abort_connect (connector, err); g_error_free (err); } GQuark wocky_connector_error_quark (void) { static GQuark quark = 0; if (quark == 0) quark = g_quark_from_static_string ("wocky-connector-error"); return quark; } static void wocky_connector_init (WockyConnector *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_CONNECTOR, WockyConnectorPrivate); } static void wocky_connector_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyConnector *connector = WOCKY_CONNECTOR (object); WockyConnectorPrivate *priv = connector->priv; switch (property_id) { case PROP_TLS_REQUIRED: priv->tls_required = g_value_get_boolean (value); break; case PROP_AUTH_INSECURE_OK: priv->auth_insecure_ok = g_value_get_boolean (value); break; case PROP_ENC_PLAIN_AUTH_OK: priv->encrypted_plain_auth_ok = g_value_get_boolean (value); break; case PROP_JID: g_free (priv->jid); priv->jid = g_value_dup_string (value); break; case PROP_EMAIL: g_free (priv->email); priv->email = g_value_dup_string (value); break; case PROP_PASS: g_free (priv->pass); priv->pass = g_value_dup_string (value); break; case PROP_RESOURCE: g_free (priv->resource); if ((g_value_get_string (value) != NULL) && *g_value_get_string (value) != '\0') priv->resource = g_value_dup_string (value); else priv->resource = NULL; break; case PROP_XMPP_PORT: priv->xmpp_port = g_value_get_uint (value); break; case PROP_XMPP_HOST: g_free (priv->xmpp_host); priv->xmpp_host = g_value_dup_string (value); break; case PROP_LEGACY: priv->legacy_support = g_value_get_boolean (value); break; case PROP_LEGACY_SSL: priv->legacy_ssl = g_value_get_boolean (value); break; case PROP_SESSION_ID: g_free (priv->session_id); priv->session_id = g_value_dup_string (value); break; case PROP_AUTH_REGISTRY: priv->auth_registry = g_value_dup_object (value); break; case PROP_TLS_HANDLER: priv->tls_handler = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_connector_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyConnector *connector = WOCKY_CONNECTOR (object); WockyConnectorPrivate *priv = connector->priv; switch (property_id) { case PROP_TLS_REQUIRED: g_value_set_boolean (value, priv->tls_required); break; case PROP_AUTH_INSECURE_OK: g_value_set_boolean (value, priv->auth_insecure_ok); break; case PROP_ENC_PLAIN_AUTH_OK: g_value_set_boolean (value, priv->encrypted_plain_auth_ok); break; case PROP_JID: g_value_set_string (value, priv->jid); break; case PROP_PASS: g_value_set_string (value, priv->pass); break; case PROP_EMAIL: g_value_set_string (value, priv->email); break; case PROP_RESOURCE: g_value_set_string (value, priv->resource); break; case PROP_XMPP_PORT: g_value_set_uint (value, priv->xmpp_port); break; case PROP_XMPP_HOST: g_value_set_string (value, priv->xmpp_host); break; case PROP_IDENTITY: g_value_set_string (value, priv->identity); break; case PROP_FEATURES: g_value_set_object (value, priv->features); break; case PROP_LEGACY: g_value_set_boolean (value, priv->legacy_support); break; case PROP_LEGACY_SSL: g_value_set_boolean (value, priv->legacy_ssl); break; case PROP_SESSION_ID: g_value_set_string (value, priv->session_id); break; case PROP_AUTH_REGISTRY: g_value_set_object (value, priv->auth_registry); break; case PROP_TLS_HANDLER: g_value_set_object (value, priv->tls_handler); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_connector_class_init (WockyConnectorClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); GParamSpec *spec; g_type_class_add_private (klass, sizeof (WockyConnectorPrivate)); oclass->set_property = wocky_connector_set_property; oclass->get_property = wocky_connector_get_property; oclass->dispose = wocky_connector_dispose; oclass->finalize = wocky_connector_finalize; #if HAVE_GIO_PROXY /* Ensure that HTTP Proxy extension is registered */ _wocky_http_proxy_get_type (); #endif /** * WockyConnector:plaintext-auth-allowed: * * Whether auth info can be sent in the clear (eg PLAINTEXT auth). * This is independent of any encryption (TLS, SSL) that has been negotiated. */ spec = g_param_spec_boolean ("plaintext-auth-allowed", "plaintext-auth-allowed", "Whether auth info can be sent in the clear", FALSE, (G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_AUTH_INSECURE_OK, spec); /** * WockyConnector:encrypted-plain-auth-ok: * * Whether PLAINTEXT auth is ok when encrypted. */ spec = g_param_spec_boolean ("encrypted-plain-auth-ok", "encrypted-plain-auth-ok", "Whether PLAIN auth can be used when encrypted", TRUE, (G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_ENC_PLAIN_AUTH_OK, spec); /** * WockyConnector:tls-required: * * Whether we require successful tls/ssl negotiation to continue. */ spec = g_param_spec_boolean ("tls-required", "TLS required", "Whether SSL/TLS is required", TRUE, (G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_TLS_REQUIRED, spec); /** * WockyConnector:jid: * * The XMPP account's JID (with or without a /resource). */ spec = g_param_spec_string ("jid", "jid", "The XMPP jid", NULL, (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_JID, spec); /** * WockyConnector:email: * * The XMPP account's email address (optional, MAY be required by the server * if we are registering an account, not required otherwise). */ spec = g_param_spec_string ("email", "email", "user's email address", NULL, (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_EMAIL, spec); /** * WockyConnector:password: * * XMPP Account password. */ spec = g_param_spec_string ("password", "pass", "Password", NULL, (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_PASS, spec); /** * WockyConnector:resource: * * The resource (sans '/') for this connection. If %NULL or the empty string, * Wocky will let the server decide. Even if you specify a particular * resource, the server may modify it. */ spec = g_param_spec_string ("resource", "resource", "XMPP resource to append to the jid", NULL, (G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_RESOURCE, spec); /** * WockyConnector:identity: * * JID + resource (a AT b SLASH c) that is in effect _after_ a successful * resource binding operation. This is NOT guaranteed to be related to * the JID specified in the original #WockyConnector:jid property. * The resource, in particular, is often different, and with gtalk the * domain is often different. */ spec = g_param_spec_string ("identity", "identity", "jid + resource (set by XMPP server)", NULL, (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_IDENTITY, spec); /** * WockyConnector:xmpp-server: * * Optional XMPP connect server. Any DNS SRV record and the host specified * in #WockyConnector:jid will be ignored if this is set. May be a hostname * (fully qualified or otherwise), a dotted quad or an ipv6 address. */ spec = g_param_spec_string ("xmpp-server", "XMPP server", "XMPP connect server hostname or address", NULL, (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_XMPP_HOST, spec); /** * WockyConnector:xmpp-port: * * Optional XMPP connect port. Any DNS SRV record will be ignored if * this is set. (So the host will be either the WockyConnector:xmpp-server * property or the domain part of the JID, in descending order of preference) */ spec = g_param_spec_uint ("xmpp-port", "XMPP port", "XMPP port", 0, 65535, 0, (G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_XMPP_PORT, spec); /** * WockyConnector:features: * * A #WockyStanza instance, the last WockyStanza instance received * by the connector during the connection procedure (there may be several, * the most recent one always being the one we should refer to). */ spec = g_param_spec_object ("features", "XMPP Features", "Last XMPP Feature Stanza advertised by server", WOCKY_TYPE_STANZA, (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_FEATURES, spec); /** * WockyConnector:legacy: * * Whether to attempt old-style (non-SASL) jabber auth. */ spec = g_param_spec_boolean ("legacy", "Legacy Jabber Support", "Old style Jabber (Auth) support", FALSE, (G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_LEGACY, spec); /** * WockyConnector:old-ssl: * * Whether to use old-style SSL-at-connect-time encryption rather than * the more modern STARTTLS approach. */ spec = g_param_spec_boolean ("old-ssl", "Legacy SSL Support", "Old style SSL support", FALSE, (G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_LEGACY_SSL, spec); /** * WockyConnector:session-id: * * The Session ID supplied by the server upon successfully connecting. * May be useful later on as some XEPs suggest this value should be used * at various stages as part of a hash or as an ID. */ spec = g_param_spec_string ("session-id", "XMPP Session ID", "XMPP Session ID", NULL, (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_SESSION_ID, spec); /** * WockyConnector:auth-registry * * An authentication registry that holds handlers for different * authentication mechanisms, arbitrates mechanism selection and relays * challenges and responses between the handlers and the connection. */ spec = g_param_spec_object ("auth-registry", "Authentication Registry", "Authentication Registry", WOCKY_TYPE_AUTH_REGISTRY, (G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_AUTH_REGISTRY, spec); /** * WockyConnector:tls-handler * * A TLS handler that carries out the interactive verification of the * TLS certitificates provided by the server. */ spec = g_param_spec_object ("tls-handler", "TLS Handler", "TLS Handler", WOCKY_TYPE_TLS_HANDLER, (G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (oclass, PROP_TLS_HANDLER, spec); /** * WockyConnector::connection-established: * @connection: the #GSocketConnection * * Emitted as soon as a connection to the remote server has been * established. This can be useful if you want to do something * unusual to the connection early in its lifetime not supported by * the #WockyConnector APIs. * * As the connection process has only just started and the stream * not even opened yet, no data must be sent over @connection. This * signal is merely intended to set esoteric socket options (such as * TCP_NODELAY) on the connection. */ signals[CONNECTION_ESTABLISHED] = g_signal_new ("connection-established", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_SOCKET_CONNECTION); } #define GFREE_AND_FORGET(x) g_free (x); x = NULL; static void wocky_connector_dispose (GObject *object) { WockyConnector *self = WOCKY_CONNECTOR (object); WockyConnectorPrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; g_clear_object (&priv->conn); g_clear_object (&priv->client); g_clear_object (&priv->sock); g_clear_object (&priv->features); g_clear_object (&priv->auth_registry); g_clear_object (&priv->tls_handler); if (G_OBJECT_CLASS (wocky_connector_parent_class )->dispose) G_OBJECT_CLASS (wocky_connector_parent_class)->dispose (object); } static void wocky_connector_finalize (GObject *object) { WockyConnector *self = WOCKY_CONNECTOR (object); WockyConnectorPrivate *priv = self->priv; GFREE_AND_FORGET (priv->jid); GFREE_AND_FORGET (priv->user); GFREE_AND_FORGET (priv->domain); GFREE_AND_FORGET (priv->resource); GFREE_AND_FORGET (priv->identity); GFREE_AND_FORGET (priv->xmpp_host); GFREE_AND_FORGET (priv->pass); GFREE_AND_FORGET (priv->session_id); GFREE_AND_FORGET (priv->email); if (priv->srv_connect_error != NULL) g_clear_error (&priv->srv_connect_error); G_OBJECT_CLASS (wocky_connector_parent_class)->finalize (object); } static void connect_to_host_async (WockyConnector *connector, const gchar *host_and_port, guint default_port) { WockyConnectorPrivate *priv = connector->priv; #if HAVE_GIO_PROXY { const gchar *uri_format = "%s://%s"; gchar *uri; /* If host_and_port is an ipv6 address we must ensure it has [] around it */ if (host_and_port[0] != '[') { const gchar *p; /* if host_and_port contains 2 ':' chars, it must be an ipv6 address */ p = g_strstr_len (host_and_port, -1, ":"); if (p != NULL) p = g_strstr_len (p + 1, -1, ":"); if (p != NULL) uri_format = "%s://[%s]"; } /* Legacy SSL mode is just like doing HTTPS, so let's trigger HTTPS * proxy setting if any */ uri = g_strdup_printf (uri_format, priv->legacy_ssl ? "https" : "xmpp-client", host_and_port); g_socket_client_connect_to_uri_async (priv->client, uri, default_port, NULL, tcp_host_connected, connector); g_free (uri); } #else g_socket_client_connect_to_host_async (priv->client, host_and_port, default_port, NULL, tcp_host_connected, connector); #endif } static void tcp_srv_connected (GObject *source, GAsyncResult *result, gpointer connector) { GError *error = NULL; WockyConnector *self = WOCKY_CONNECTOR (connector); WockyConnectorPrivate *priv = self->priv; priv->sock = g_socket_client_connect_to_service_finish (G_SOCKET_CLIENT (source), result, &error); /* if we didn't manage to connect via SRV records based on the JID (no SRV records or host unreachable/not listening) fall back to treating the domain part of the JID as a real host and try to talk to that */ if (priv->sock == NULL) { gchar *node = NULL; /* username */ /* @ */ gchar *host = NULL; /* domain.tld */ /* / */ guint port = (priv->xmpp_port == 0) ? 5222 : priv->xmpp_port; /* g_socket_client_connect_to_service_finish() should have set error if * it returned %NULL. */ g_return_if_fail (error != NULL); DEBUG ("SRV connect failed: %s:%d %s", g_quark_to_string (error->domain), error->code, error->message); /* An IO error implies there IS a SRV record but we could not * connect. Stash the error, and fall back to connecting to the host * directly; if we also fail to connect to the host, we'll report the * error we stashed here rather than the later error. This is * predominantly to work around chat.facebook.com having a broken SRV * record. * * For any other kind of error, we assume this means there's no SRV * record, bin the GError and just fall back to the host completely. */ if (error->domain == G_IO_ERROR) priv->srv_connect_error = error; else g_clear_error (&error); priv->state = WCON_TCP_CONNECTING; /* decode a hostname from the JID here: Don't check for an explicit * * connect host supplied by the user as we shouldn't even try a SRV * * connection in that case, and should therefore never get here */ wocky_decode_jid (priv->jid, &node, &host, NULL); if ((host != NULL) && (*host != '\0')) { DEBUG ("Falling back to HOST connection to %s port %u", host, port); connect_to_host_async (connector, host, port); } else { abort_connect_code (self, WOCKY_CONNECTOR_ERROR_BAD_JID, "JID contains no domain: %s", priv->jid); } g_free (node); g_free (host); } else { DEBUG ("SRV connection succeeded"); g_signal_emit (self, signals[CONNECTION_ESTABLISHED], 0, priv->sock); priv->connected = TRUE; priv->state = WCON_TCP_CONNECTED; maybe_old_ssl (self); } } static void tcp_host_connected (GObject *source, GAsyncResult *result, gpointer connector) { GError *error = NULL; WockyConnector *self = WOCKY_CONNECTOR (connector); WockyConnectorPrivate *priv = self->priv; GSocketClient *sock = G_SOCKET_CLIENT (source); priv->sock = g_socket_client_connect_to_host_finish (sock, result, &error); if (priv->sock == NULL) { DEBUG ("HOST connect failed: %s", error->message); if (priv->srv_connect_error != NULL) { DEBUG ("we previously hit a GIOError when connecting using SRV; " "reporting that error"); abort_connect_error (connector, &priv->srv_connect_error, "couldn't connect to server specified by SRV record"); } else { abort_connect_error (connector, &error, "couldn't connect to server"); } g_error_free (error); } else { DEBUG ("HOST connection succeeded"); g_signal_emit (self, signals[CONNECTION_ESTABLISHED], 0, priv->sock); priv->connected = TRUE; priv->state = WCON_TCP_CONNECTED; maybe_old_ssl (self); } } /* ************************************************************************* */ /* legacy jabber support */ static void jabber_request_auth (WockyConnector *self) { WockyConnectorPrivate *priv = self->priv; WockyJabberAuth *jabber_auth; gboolean clear = FALSE; jabber_auth = wocky_jabber_auth_new (priv->session_id, priv->user, priv->resource, priv->pass, priv->conn, priv->auth_registry); if (priv->auth_insecure_ok || (priv->encrypted && priv->encrypted_plain_auth_ok)) clear = TRUE; DEBUG ("handing over control to WockyJabberAuth"); wocky_jabber_auth_authenticate_async (jabber_auth, clear, priv->encrypted, priv->cancellable, jabber_auth_done, self); } static void jabber_auth_done (GObject *source, GAsyncResult *result, gpointer data) { GError *error = NULL; WockyConnector *self = WOCKY_CONNECTOR (data); WockyConnectorPrivate *priv = self->priv; WockyJabberAuth *jabber_auth = WOCKY_JABBER_AUTH (source); if (!wocky_jabber_auth_authenticate_finish (jabber_auth, result, &error)) { /* nothing to add, the SASL error should be informative enough */ DEBUG ("Jabber auth complete (failure)"); abort_connect_error (self, &error, ""); g_error_free (error); goto out; } DEBUG ("Jabber auth complete (success)"); priv->state = WCON_XMPP_AUTHED; priv->authed = TRUE; priv->identity = g_strdup_printf ("%s@%s/%s", priv->user, priv->domain, priv->resource); /* if there has been no features stanza, this will just finish up * * if there has been a feature stanza, we are in an XMPP 1.x * * server that _only_ supports old style auth (no SASL). In this * * bizarre situation, we would then proceed as if we were in a * * normal XMPP server after a successful bind. */ establish_session (self); out: g_object_unref (jabber_auth); } /* ************************************************************************* */ /* old-style SSL */ static const gchar * get_peername (WockyConnector *self) { WockyConnectorPrivate *priv = self->priv; const gchar *peer; if (priv->legacy_ssl) peer = (priv->xmpp_host != NULL) ? priv->xmpp_host : priv->domain; else peer = priv->domain; return peer; } static void maybe_old_ssl (WockyConnector *self) { WockyConnectorPrivate *priv = self->priv; g_assert (priv->conn == NULL); g_assert (priv->sock != NULL); priv->conn = wocky_xmpp_connection_new (G_IO_STREAM (priv->sock)); if (priv->legacy_ssl && !priv->encrypted) { WockyTLSConnector *tls_connector; DEBUG ("Creating SSL connector"); tls_connector = wocky_tls_connector_new (priv->tls_handler); DEBUG ("Beginning SSL handshake"); wocky_tls_connector_secure_async (tls_connector, priv->conn, TRUE, get_peername (self), NULL, priv->cancellable, tls_connector_secure_cb, self); g_object_unref (tls_connector); } else { xmpp_init (self); } } /* ************************************************************************* */ /* standard XMPP stanza handling */ static void xmpp_init (WockyConnector *connector) { WockyConnector *self = WOCKY_CONNECTOR (connector); WockyConnectorPrivate *priv = self->priv; DEBUG ("sending XMPP stream open to server"); wocky_xmpp_connection_send_open_async (priv->conn, priv->domain, NULL, "1.0", NULL, NULL, priv->cancellable, xmpp_init_sent_cb, connector); } static void xmpp_init_sent_cb (GObject *source, GAsyncResult *result, gpointer data) { GError *error = NULL; WockyConnector *self = WOCKY_CONNECTOR (data); WockyConnectorPrivate *priv = self->priv; if (!wocky_xmpp_connection_send_open_finish (priv->conn, result, &error)) { abort_connect_error (self, &error, "Failed to send open stanza"); g_error_free (error); return; } DEBUG ("waiting for stream open from server"); wocky_xmpp_connection_recv_open_async (priv->conn, priv->cancellable, xmpp_init_recv_cb, data); } static void xmpp_init_recv_cb (GObject *source, GAsyncResult *result, gpointer data) { GError *error = NULL; WockyConnector *self = WOCKY_CONNECTOR (data); WockyConnectorPrivate *priv = self->priv; gchar *version = NULL; gchar *from = NULL; gchar *id = NULL; gdouble ver = 0; if (!wocky_xmpp_connection_recv_open_finish (priv->conn, result, NULL, &from, &version, NULL, &id, &error)) { abort_connect_error (self, &error, "%s: %s", state_message (priv), error->message); g_error_free (error); goto out; } g_free (priv->session_id); priv->session_id = g_strdup (id); DEBUG ("%s: received XMPP version=%s stream open from server", state_message (priv), version != NULL ? version : "(unspecified)"); ver = (version != NULL) ? atof (version) : -1; if (ver < 1.0) { if (!priv->legacy_support) abort_connect_code (self, WOCKY_CONNECTOR_ERROR_NON_XMPP_V1_SERVER, "Server not XMPP 1.0 Compliant"); else if (priv->tls_required && !priv->encrypted) abort_connect_code (data, WOCKY_CONNECTOR_ERROR_TLS_UNAVAILABLE, "TLS requested but server is not XMPP 1.0 compliant (try using \"old SSL\")"); else jabber_request_auth (self); } else { DEBUG ("waiting for feature stanza from server"); wocky_xmpp_connection_recv_stanza_async (priv->conn, priv->cancellable, xmpp_features_cb, data); } out: g_free (version); g_free (from); g_free (id); } /* ************************************************************************* */ /* handle stream errors */ static gboolean stream_error_abort (WockyConnector *self, WockyStanza *stanza) { GError *error = NULL; if (!wocky_stanza_extract_stream_error (stanza, &error)) return FALSE; if (g_error_matches (error, WOCKY_XMPP_STREAM_ERROR, WOCKY_XMPP_STREAM_ERROR_SEE_OTHER_HOST)) { const gchar *other_host; other_host = wocky_node_get_content_from_child_ns ( wocky_stanza_get_top_node (stanza), "see-other-host", WOCKY_XMPP_NS_STREAMS); if (other_host != NULL && self->priv->see_other_host_count < 5) { DEBUG ("Need to restart connection with host: %s", other_host); self->priv->see_other_host_count++; /* Reset to initial state */ g_clear_object (&self->priv->features); g_clear_object (&self->priv->sock); g_clear_object (&self->priv->conn); self->priv->state = WCON_TCP_CONNECTING; self->priv->authed = FALSE; self->priv->encrypted = FALSE; self->priv->connected = FALSE; connect_to_host_async (self, other_host, 5222); goto out; } } DEBUG ("Received stream error: %s", error->message); abort_connect (self, error); out: g_error_free (error); return TRUE; } /* ************************************************************************* */ static void xmpp_features_cb (GObject *source, GAsyncResult *result, gpointer data) { GError *error = NULL; WockyConnector *self = WOCKY_CONNECTOR (data); WockyConnectorPrivate *priv = self->priv; WockyStanza *stanza; WockyNode *node; gboolean can_encrypt = FALSE; gboolean can_bind = FALSE; stanza = wocky_xmpp_connection_recv_stanza_finish (priv->conn, result, &error); if (stanza == NULL) { abort_connect_error (self, &error, "disconnected before XMPP features stanza"); g_error_free (error); return; } if (stream_error_abort (self, stanza)) goto out; if (!wocky_stanza_has_type (stanza, WOCKY_STANZA_TYPE_STREAM_FEATURES)) { abort_connect_code (data, WOCKY_CONNECTOR_ERROR_BAD_FEATURES, "%s: %s", state_message (priv), "Malformed or missing feature stanza"); goto out; } DEBUG ("received feature stanza from server"); node = wocky_stanza_get_top_node (stanza); /* cache the current feature set: according to the RFC, we should forget * any previous feature set as soon as we open a new stream, so that * happens elsewhere */ if (stanza != NULL) { if (priv->features != NULL) g_object_unref (priv->features); priv->features = g_object_ref (stanza); } can_encrypt = wocky_node_get_child_ns (node, "starttls", WOCKY_XMPP_NS_TLS) != NULL; can_bind = wocky_node_get_child_ns (node, "bind", WOCKY_XMPP_NS_BIND) != NULL; /* conditions: * not encrypted, not encryptable, require encryption → ABORT * !encrypted && encryptable → STARTTLS * !authed && xep77_reg → XEP77 REGISTRATION * !authed → AUTH * not bound && can bind → BIND */ if (!priv->encrypted && !can_encrypt && priv->tls_required) { abort_connect_code (data, WOCKY_CONNECTOR_ERROR_TLS_UNAVAILABLE, "TLS requested but lack server support"); goto out; } if (!priv->encrypted && can_encrypt) { WockyTLSConnector *tls_connector; tls_connector = wocky_tls_connector_new (priv->tls_handler); wocky_tls_connector_secure_async (tls_connector, priv->conn, FALSE, get_peername (self), NULL, priv->cancellable, tls_connector_secure_cb, self); g_object_unref (tls_connector); goto out; } if (!priv->authed && priv->reg_op == XEP77_SIGNUP) { xep77_begin (self); goto out; } if (!priv->authed) { sasl_request_auth (self, stanza); goto out; } /* we MUST bind here http://www.ietf.org/rfc/rfc3920.txt */ if (can_bind) iq_bind_resource (self); else abort_connect_code (data, WOCKY_CONNECTOR_ERROR_BIND_UNAVAILABLE, "XMPP Server does not support resource binding"); out: if (stanza != NULL) g_object_unref (stanza); } static void tls_connector_secure_cb (GObject *source, GAsyncResult *res, gpointer user_data) { WockyTLSConnector *tls_connector = WOCKY_TLS_CONNECTOR (source); WockyConnector *self = user_data; GError *error = NULL; WockyXmppConnection *new_connection; new_connection = wocky_tls_connector_secure_finish (tls_connector, res, &error); if (error != NULL) { abort_connect (self, error); g_error_free (error); return; } if (self->priv->conn != NULL) g_object_unref (self->priv->conn); self->priv->conn = new_connection; self->priv->encrypted = TRUE; xmpp_init (self); } /* ************************************************************************* */ /* AUTH calls */ static void sasl_request_auth (WockyConnector *object, WockyStanza *stanza) { WockyConnector *self = WOCKY_CONNECTOR (object); WockyConnectorPrivate *priv = self->priv; WockySaslAuth *s; gboolean clear = FALSE; s = wocky_sasl_auth_new (priv->domain, priv->user, priv->pass, priv->conn, priv->auth_registry); if (priv->auth_insecure_ok || (priv->encrypted && priv->encrypted_plain_auth_ok)) clear = TRUE; DEBUG ("handing over control to SASL module"); wocky_sasl_auth_authenticate_async (s, stanza, clear, priv->encrypted, priv->cancellable, sasl_auth_done, self); } static void sasl_auth_done (GObject *source, GAsyncResult *result, gpointer data) { GError *error = NULL; WockyConnector *self = WOCKY_CONNECTOR (data); WockyConnectorPrivate *priv = self->priv; WockySaslAuth *sasl = WOCKY_SASL_AUTH (source); if (!wocky_sasl_auth_authenticate_finish (sasl, result, &error)) { /* nothing to add, the SASL error should be informative enough */ DEBUG ("SASL complete (failure)"); /* except: if there's no SASL and Jabber auth is available, we * * are allowed to attempt that instead */ if ((error->domain == WOCKY_AUTH_ERROR) && (error->code == WOCKY_AUTH_ERROR_NOT_SUPPORTED) && (wocky_node_get_child_ns ( wocky_stanza_get_top_node (priv->features), "auth", WOCKY_JABBER_NS_AUTH_FEATURE) != NULL)) jabber_request_auth (self); else abort_connect_error (self, &error, ""); g_error_free (error); goto out; } DEBUG ("SASL complete (success)"); priv->state = WCON_XMPP_AUTHED; priv->authed = TRUE; wocky_xmpp_connection_reset (priv->conn); xmpp_init (self); out: g_object_unref (sasl); } /* ************************************************************************* */ /* XEP 0077 register/cancel calls */ static void xep77_cancel_send (WockyConnector *self) { WockyConnectorPrivate *priv = self->priv; WockyStanza *iqs = NULL; gchar *iid = NULL; DEBUG (""); iid = wocky_xmpp_connection_new_id (priv->conn); iqs = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, /* FIXME: It is debatable (XEP0077 section 3.2) whether we should * * include our JID here. The examples include it, the text states * * that we SHOULD NOT, at least in some use cases */ NULL /* priv->identity */, priv->domain, '@', "id", iid, '(', "query", ':', WOCKY_XEP77_NS_REGISTER, '(', "remove", ')', ')', NULL); wocky_xmpp_connection_send_stanza_async (priv->conn, iqs, priv->cancellable, xep77_cancel_sent, self); g_free (iid); g_object_unref (iqs); } static void xep77_cancel_sent (GObject *source, GAsyncResult *res, gpointer data) { GError *error = NULL; WockyConnector *self = WOCKY_CONNECTOR (data); WockyConnectorPrivate *priv = self->priv; DEBUG (""); if (!wocky_xmpp_connection_send_stanza_finish (priv->conn, res, &error)) { abort_connect_error (self, &error, "Failed to send unregister iq set"); g_error_free (error); return; } wocky_xmpp_connection_recv_stanza_async (priv->conn, priv->cancellable, xep77_cancel_recv, self); } static void xep77_cancel_recv (GObject *source, GAsyncResult *res, gpointer data) { GError *error = NULL; WockyConnector *self = WOCKY_CONNECTOR (data); WockyConnectorPrivate *priv = self->priv; WockyStanza *iq = NULL; WockyStanzaType type; WockyStanzaSubType sub_type; DEBUG (""); iq = wocky_xmpp_connection_recv_stanza_finish (priv->conn, res, &error); if (iq == NULL) { g_simple_async_result_set_from_error (priv->result, error); g_error_free (error); goto out; } wocky_stanza_get_type_info (iq, &type, &sub_type); DEBUG ("type == %d; sub_type: %d", type, sub_type); if (wocky_stanza_extract_stream_error (iq, &error)) { if (error->code != WOCKY_XMPP_STREAM_ERROR_NOT_AUTHORIZED) g_simple_async_result_set_from_error (priv->result, error); g_error_free (error); goto out; } if (type != WOCKY_STANZA_TYPE_IQ) { g_simple_async_result_set_error (priv->result, WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_UNREGISTER_FAILED, "Unregister: Invalid response"); goto out; } switch (sub_type) { int code; case WOCKY_STANZA_SUB_TYPE_ERROR: wocky_stanza_extract_errors (iq, NULL, &error, NULL, NULL); switch (error->code) { case WOCKY_XMPP_ERROR_FORBIDDEN: case WOCKY_XMPP_ERROR_NOT_ALLOWED: code = WOCKY_CONNECTOR_ERROR_UNREGISTER_DENIED; break; default: code = WOCKY_CONNECTOR_ERROR_UNREGISTER_FAILED; } g_simple_async_result_set_error (priv->result, WOCKY_CONNECTOR_ERROR, code, "Unregister: %s", error->message); g_clear_error (&error); break; case WOCKY_STANZA_SUB_TYPE_RESULT: /* Do nothing, we have already succeeded. */ break; default: g_simple_async_result_set_error (priv->result, WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_UNREGISTER_FAILED, "Unregister: Malformed Response"); break; } out: if (iq != NULL) g_object_unref (iq); if (priv->sock != NULL) { g_object_unref (priv->sock); priv->sock = NULL; } if (priv->cancellable != NULL) { g_object_unref (priv->cancellable); priv->cancellable = NULL; } complete_operation (self); priv->state = WCON_DISCONNECTED; } static void xep77_begin (WockyConnector *self) { WockyConnectorPrivate *priv = self->priv; WockyStanza *iqs = NULL; gchar *iid = NULL; gchar *jid = NULL; DEBUG (""); if (!priv->encrypted && !priv->auth_insecure_ok) { abort_connect_code (self, WOCKY_CONNECTOR_ERROR_INSECURE, "Cannot register account without encryption"); return; } jid = g_strdup_printf ("%s@%s", priv->user, priv->domain); iid = wocky_xmpp_connection_new_id (priv->conn); iqs = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, jid, priv->domain, '@', "id", iid, '(', "query", ':', WOCKY_XEP77_NS_REGISTER, ')', NULL); wocky_xmpp_connection_send_stanza_async (priv->conn, iqs, priv->cancellable, xep77_begin_sent, self); g_free (jid); g_free (iid); g_object_unref (iqs); } static void xep77_begin_sent (GObject *source, GAsyncResult *result, gpointer data) { GError *error = NULL; WockyConnector *self = WOCKY_CONNECTOR (data); WockyConnectorPrivate *priv = self->priv; DEBUG (""); if (!wocky_xmpp_connection_send_stanza_finish (priv->conn, result, &error)) { abort_connect_error (self, &error, "Failed to send register iq get"); g_error_free (error); return; } wocky_xmpp_connection_recv_stanza_async (priv->conn, priv->cancellable, xep77_begin_recv, self); } static void xep77_begin_recv (GObject *source, GAsyncResult *result, gpointer data) { GError *error = NULL; WockyConnector *self = WOCKY_CONNECTOR (data); WockyConnectorPrivate *priv = self->priv; WockyStanza *iq = NULL; WockyNode *query = NULL; WockyStanzaType type; WockyStanzaSubType sub_type; DEBUG (""); iq = wocky_xmpp_connection_recv_stanza_finish (priv->conn, result, &error); if (iq == NULL) { abort_connect_error (self, &error, "Failed to receive register iq set"); g_error_free (error); goto out; } wocky_stanza_get_type_info (iq, &type, &sub_type); if (type != WOCKY_STANZA_TYPE_IQ) { abort_connect_code (self, WOCKY_CONNECTOR_ERROR_REGISTRATION_FAILED, "Register: Response Invalid"); goto out; } switch (sub_type) { int code; case WOCKY_STANZA_SUB_TYPE_ERROR: wocky_stanza_extract_errors (iq, NULL, &error, NULL, NULL); if (error->code == WOCKY_XMPP_ERROR_SERVICE_UNAVAILABLE) code = WOCKY_CONNECTOR_ERROR_REGISTRATION_UNAVAILABLE; else code = WOCKY_CONNECTOR_ERROR_REGISTRATION_FAILED; abort_connect_code (self, code, "Registration: %s", error->message); g_clear_error (&error); break; case WOCKY_STANZA_SUB_TYPE_RESULT: DEBUG ("WOCKY_STANZA_SUB_TYPE_RESULT"); query = wocky_node_get_child_ns ( wocky_stanza_get_top_node (iq), "query", WOCKY_XEP77_NS_REGISTER); if (query == NULL) { abort_connect_code (self, WOCKY_CONNECTOR_ERROR_REGISTRATION_FAILED, "Malformed response to register iq"); goto out; } /* already registered. woo hoo. proceed to auth stage */ if (wocky_node_get_child (query, "registered") != NULL) { priv->reg_op = XEP77_NONE; sasl_request_auth (self, priv->features); goto out; } switch (priv->reg_op) { case XEP77_SIGNUP: xep77_signup_send (self, query); break; case XEP77_CANCEL: xep77_cancel_send (self); break; default: abort_connect_code (self, WOCKY_CONNECTOR_ERROR_UNKNOWN, "This should never happen: broken logic in connctor"); } break; default: DEBUG ("WOCKY_STANZA_SUB_TYPE_*"); abort_connect_code (self, WOCKY_CONNECTOR_ERROR_REGISTRATION_FAILED, "Register: Response Invalid"); break; } out: if (iq != NULL) g_object_unref (iq); } static void xep77_signup_send (WockyConnector *self, WockyNode *req) { WockyConnectorPrivate *priv = self->priv; WockyStanza *riq = NULL; WockyNode *reg = NULL; GSList *arg = NULL; gchar *jid = g_strdup_printf ("%s@%s", priv->user, priv->domain); gchar *iid = wocky_xmpp_connection_new_id (priv->conn); guint args = 0; DEBUG (""); riq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, jid, priv->domain, '@', "id", iid, NULL); reg = wocky_node_add_child_ns (wocky_stanza_get_top_node (riq), "query", WOCKY_XEP77_NS_REGISTER); for (arg = req->children; arg != NULL; arg = g_slist_next (arg)) { gchar *value = NULL; WockyNode *a = (WockyNode *) arg->data; if (!wocky_strdiff ("instructions", a->name)) continue; else if (!wocky_strdiff ("username", a->name)) value = priv->user; else if (!wocky_strdiff ("password", a->name)) value = priv->pass; else if (!wocky_strdiff ("email", a->name)) if ((priv->email != NULL) && *(priv->email) != '0') value = priv->email; else { abort_connect_code (self, WOCKY_CONNECTOR_ERROR_REGISTRATION_REJECTED, "Registration parameter %s missing", a->name); goto out; } else { abort_connect_code (self, WOCKY_CONNECTOR_ERROR_REGISTRATION_UNSUPPORTED, "Did not understand '%s' registration parameter", a->name); goto out; } DEBUG ("%s := %s", a->name, value); wocky_node_add_child_with_content (reg, a->name, value); args++; } /* we understood all args, and there was at least one of them: */ if (args > 0) wocky_xmpp_connection_send_stanza_async (priv->conn, riq, priv->cancellable, xep77_signup_sent, self); else abort_connect_code (self, WOCKY_CONNECTOR_ERROR_REGISTRATION_EMPTY, "Registration without parameters makes no sense"); out: g_object_unref (riq); g_free (jid); g_free (iid); } static void xep77_signup_sent (GObject *source, GAsyncResult *result, gpointer data) { GError *error = NULL; WockyConnector *self = WOCKY_CONNECTOR (data); WockyConnectorPrivate *priv = self->priv; DEBUG (""); if (!wocky_xmpp_connection_send_stanza_finish (priv->conn, result, &error)) { abort_connect_error (self, &error, "Failed to send registration"); g_error_free (error); return; } wocky_xmpp_connection_recv_stanza_async (priv->conn, priv->cancellable, xep77_signup_recv, self); } static void xep77_signup_recv (GObject *source, GAsyncResult *result, gpointer data) { GError *error = NULL; WockyConnector *self = WOCKY_CONNECTOR (data); WockyConnectorPrivate *priv = self->priv; WockyStanza *iq = NULL; WockyStanzaType type; WockyStanzaSubType sub_type; DEBUG (""); iq = wocky_xmpp_connection_recv_stanza_finish (priv->conn, result, &error); if (iq == NULL) { abort_connect_error (self, &error, "Failed to receive register result"); g_error_free (error); return; } wocky_stanza_get_type_info (iq, &type, &sub_type); if (type != WOCKY_STANZA_TYPE_IQ) { abort_connect_code (self, WOCKY_CONNECTOR_ERROR_REGISTRATION_FAILED, "Register: Response Invalid"); goto out; } switch (sub_type) { int code; case WOCKY_STANZA_SUB_TYPE_ERROR: wocky_stanza_extract_errors (iq, NULL, &error, NULL, NULL); switch (error->code) { case WOCKY_XMPP_ERROR_CONFLICT: code = WOCKY_CONNECTOR_ERROR_REGISTRATION_CONFLICT; break; case WOCKY_XMPP_ERROR_NOT_ACCEPTABLE: code = WOCKY_CONNECTOR_ERROR_REGISTRATION_REJECTED; break; default: code = WOCKY_CONNECTOR_ERROR_REGISTRATION_FAILED; } abort_connect_code (self, code, "Registration: %s %s", wocky_xmpp_error_string (error->code), error->message); g_clear_error (&error); break; case WOCKY_STANZA_SUB_TYPE_RESULT: DEBUG ("WOCKY_STANZA_SUB_TYPE_RESULT"); /* successfully registered. woo hoo. proceed to auth stage */ priv->reg_op = XEP77_NONE; sasl_request_auth (self, priv->features); break; default: DEBUG ("WOCKY_STANZA_SUB_TYPE_*"); abort_connect_code (self, WOCKY_CONNECTOR_ERROR_REGISTRATION_FAILED, "Register: Response Invalid"); break; } out: g_object_unref (iq); } /* ************************************************************************* */ /* BIND calls */ static void iq_bind_resource (WockyConnector *self) { WockyConnectorPrivate *priv = self->priv; gchar *id = wocky_xmpp_connection_new_id (priv->conn); WockyNode *bind; WockyStanza *iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL, '@', "id", id, '(', "bind", ':', WOCKY_XMPP_NS_BIND, '*', &bind, ')', NULL); /* if we have a specific resource to ask for, ask for it: otherwise the * server will make one up for us */ if ((priv->resource != NULL) && (*priv->resource != '\0')) wocky_node_add_child_with_content (bind, "resource", priv->resource); DEBUG ("sending bind iq set stanza"); wocky_xmpp_connection_send_stanza_async (priv->conn, iq, priv->cancellable, iq_bind_resource_sent_cb, self); g_free (id); g_object_unref (iq); } static void iq_bind_resource_sent_cb (GObject *source, GAsyncResult *result, gpointer data) { GError *error = NULL; WockyConnector *self = WOCKY_CONNECTOR (data); WockyConnectorPrivate *priv = self->priv; if (!wocky_xmpp_connection_send_stanza_finish (priv->conn, result, &error)) { abort_connect_error (self, &error, "Failed to send bind iq set"); g_error_free (error); return; } DEBUG ("bind iq set stanza sent"); wocky_xmpp_connection_recv_stanza_async (priv->conn, priv->cancellable, iq_bind_resource_recv_cb, data); } static void iq_bind_resource_recv_cb (GObject *source, GAsyncResult *result, gpointer data) { GError *error = NULL; WockyConnector *self = WOCKY_CONNECTOR (data); WockyConnectorPrivate *priv = self->priv; WockyStanza *reply = NULL; WockyStanzaType type = WOCKY_STANZA_TYPE_NONE; WockyStanzaSubType sub = WOCKY_STANZA_SUB_TYPE_NONE; reply = wocky_xmpp_connection_recv_stanza_finish (priv->conn, result, &error); DEBUG ("bind iq response stanza received"); if (reply == NULL) { abort_connect_error (self, &error, "Failed to receive bind iq result"); g_error_free (error); return; } if (stream_error_abort (self, reply)) goto out; wocky_stanza_get_type_info (reply, &type, &sub); if (type != WOCKY_STANZA_TYPE_IQ) { abort_connect_code (self, WOCKY_CONNECTOR_ERROR_BIND_FAILED, "Bind iq response invalid"); goto out; } switch (sub) { WockyNode *node = NULL; WockyConnectorError code; case WOCKY_STANZA_SUB_TYPE_ERROR: wocky_stanza_extract_errors (reply, NULL, &error, NULL, NULL); switch (error->code) { case WOCKY_XMPP_ERROR_BAD_REQUEST: code = WOCKY_CONNECTOR_ERROR_BIND_INVALID; break; case WOCKY_XMPP_ERROR_NOT_ALLOWED: code = WOCKY_CONNECTOR_ERROR_BIND_DENIED; break; case WOCKY_XMPP_ERROR_CONFLICT: code = WOCKY_CONNECTOR_ERROR_BIND_CONFLICT; break; default: code = WOCKY_CONNECTOR_ERROR_BIND_REJECTED; } abort_connect_code (self, code, "resource binding: %s", wocky_xmpp_error_string (error->code)); g_clear_error (&error); break; case WOCKY_STANZA_SUB_TYPE_RESULT: node = wocky_node_get_child ( wocky_stanza_get_top_node (reply), "bind"); if (node != NULL) node = wocky_node_get_child (node, "jid"); /* store the returned id (or the original if none came back)*/ g_free (priv->identity); if ((node != NULL) && (node->content != NULL) && *(node->content)) priv->identity = g_strdup (node->content); else priv->identity = g_strdup (priv->jid); priv->state = WCON_XMPP_BOUND; establish_session (self); break; default: abort_connect_code (self, WOCKY_CONNECTOR_ERROR_BIND_FAILED, "Bizarre response to bind iq set"); break; } out: g_object_unref (reply); } /* ************************************************************************* */ /* final stage: establish a session, if so advertised: */ void establish_session (WockyConnector *self) { WockyConnectorPrivate *priv = self->priv; WockyNode *feat = (priv->features != NULL) ? wocky_stanza_get_top_node (priv->features) : NULL; /* _if_ session setup is advertised, a session _must_ be established to * * allow presence/messaging etc to work. If not, it is not important */ if ((feat != NULL) && wocky_node_get_child_ns (feat, "session", WOCKY_XMPP_NS_SESSION)) { WockyXmppConnection *conn = priv->conn; gchar *id = wocky_xmpp_connection_new_id (conn); WockyStanza *session = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL, '@', "id", id, '(', "session", ':', WOCKY_XMPP_NS_SESSION, ')', NULL); wocky_xmpp_connection_send_stanza_async (conn, session, priv->cancellable, establish_session_sent_cb, self); g_object_unref (session); g_free (id); } else if (priv->reg_op == XEP77_CANCEL) { /* sessions unavailable and we are cancelling our registration: * * enter the xep77 code instead of completing the _async call */ xep77_begin (self); } else { if (priv->cancellable != NULL) { g_object_unref (priv->cancellable); priv->cancellable = NULL; } complete_operation (self); } } static void establish_session_sent_cb (GObject *source, GAsyncResult *result, gpointer data) { GError *error = NULL; WockyConnector *self = WOCKY_CONNECTOR (data); WockyConnectorPrivate *priv = self->priv; if (!wocky_xmpp_connection_send_stanza_finish (priv->conn, result, &error)) { abort_connect_error (self, &error, "Failed to send session iq set"); g_error_free (error); return; } wocky_xmpp_connection_recv_stanza_async (priv->conn, priv->cancellable, establish_session_recv_cb, data); } static void establish_session_recv_cb (GObject *source, GAsyncResult *result, gpointer data) { GError *error = NULL; WockyConnector *self = WOCKY_CONNECTOR (data); WockyConnectorPrivate *priv = self->priv; WockyStanza *reply = NULL; WockyStanzaType type = WOCKY_STANZA_TYPE_NONE; WockyStanzaSubType sub = WOCKY_STANZA_SUB_TYPE_NONE; reply = wocky_xmpp_connection_recv_stanza_finish (priv->conn, result, &error); if (reply == NULL) { abort_connect_error (self, &error, "Failed to receive session iq result"); g_error_free (error); return; } if (stream_error_abort (self, reply)) goto out; wocky_stanza_get_type_info (reply, &type, &sub); if (type != WOCKY_STANZA_TYPE_IQ) { abort_connect_code (self, WOCKY_CONNECTOR_ERROR_SESSION_FAILED, "Session iq response invalid"); goto out; } switch (sub) { WockyConnectorError code; case WOCKY_STANZA_SUB_TYPE_ERROR: wocky_stanza_extract_errors (reply, NULL, &error, NULL, NULL); switch (error->code) { case WOCKY_XMPP_ERROR_INTERNAL_SERVER_ERROR: code = WOCKY_CONNECTOR_ERROR_SESSION_FAILED; break; case WOCKY_XMPP_ERROR_FORBIDDEN: code = WOCKY_CONNECTOR_ERROR_SESSION_DENIED; break; case WOCKY_XMPP_ERROR_CONFLICT: code = WOCKY_CONNECTOR_ERROR_SESSION_CONFLICT; break; default: code = WOCKY_CONNECTOR_ERROR_SESSION_REJECTED; } abort_connect_code (self, code, "establish session: %s", wocky_xmpp_error_string (error->code)); g_clear_error (&error); break; case WOCKY_STANZA_SUB_TYPE_RESULT: if (priv->reg_op == XEP77_CANCEL) { /* session initialised: if we were cancelling our account * * we can now start the xep77 cancellation process */ xep77_begin (self); } else { if (priv->cancellable != NULL) { g_object_unref (priv->cancellable); priv->cancellable = NULL; } complete_operation (self); } break; default: abort_connect_code (self, WOCKY_CONNECTOR_ERROR_SESSION_FAILED, "Bizarre response to session iq set"); break; } out: g_object_unref (reply); } static void connector_propagate_jid_and_sid (WockyConnector *self, gchar **jid, gchar **sid) { if (jid != NULL) { if (*jid != NULL) g_warning ("overwriting non-NULL gchar * pointer arg (JID)"); *jid = g_strdup (self->priv->identity); } if (sid != NULL) { if (*sid != NULL) g_warning ("overwriting non-NULL gchar * pointer arg (Session ID)"); *sid = g_strdup (self->priv->session_id); } } /* ************************************************************************* * exposed methods * ************************************************************************* */ /** * wocky_connector_connect_finish: * @self: a #WockyConnector instance. * @res: a #GAsyncResult (from your wocky_connector_connect_async() callback). * @jid: (%NULL to ignore) the user JID from the server is stored here. * @sid: (%NULL to ignore) the Session ID is stored here. * @error: (%NULL to ignore) the #GError (if any) is sored here. * * Called by the callback passed to wocky_connector_connect_async(). * * Returns: a #WockyXmppConnection instance (success), or %NULL (failure). */ WockyXmppConnection * wocky_connector_connect_finish (WockyConnector *self, GAsyncResult *res, gchar **jid, gchar **sid, GError **error) { GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (res); if (g_simple_async_result_propagate_error (result, error)) return NULL; g_return_val_if_fail (g_simple_async_result_is_valid (res, G_OBJECT (self), wocky_connector_connect_async), NULL); connector_propagate_jid_and_sid (self, jid, sid); return self->priv->conn; } /** * wocky_connector_register_finish: * @self: a #WockyConnector instance. * @res: a #GAsyncResult (from your wocky_connector_register_async() callback). * @jid: (%NULL to ignore) the JID in effect after connection is stored here. * @sid: (%NULL to ignore) the Session ID after connection is stored here. * @error: (%NULL to ignore) the #GError (if any) is stored here. * * Called by the callback passed to wocky_connector_register_async(). * * Returns: a #WockyXmppConnection instance (success), or %NULL (failure). */ WockyXmppConnection * wocky_connector_register_finish (WockyConnector *self, GAsyncResult *res, gchar **jid, gchar **sid, GError **error) { GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (res); if (g_simple_async_result_propagate_error (result, error)) return NULL; g_return_val_if_fail (g_simple_async_result_is_valid (res, G_OBJECT (self), wocky_connector_register_async), NULL); connector_propagate_jid_and_sid (self, jid, sid); return self->priv->conn; } /** * wocky_connector_unregister_finish: * @self: a #WockyConnector instance. * @res: a #GAsyncResult (from the wocky_connector_unregister_async() callback). * @error: (%NULL to ignore) the #GError (if any) is stored here. * * Called by the callback passed to wocky_connector_unregister_async(). * * Returns: a #gboolean value %TRUE (success), or %FALSE (failure). */ gboolean wocky_connector_unregister_finish (WockyConnector *self, GAsyncResult *res, GError **error) { GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (res); GObject *obj = G_OBJECT (self); if (g_simple_async_result_propagate_error (result, error)) return FALSE; g_return_val_if_fail (g_simple_async_result_is_valid (res, obj, wocky_connector_unregister_async), FALSE); return TRUE; } static void connector_connect_async (WockyConnector *self, gpointer source_tag, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer user_data) { WockyConnectorPrivate *priv = self->priv; /* 'host' is (by default) the part of the jid after the @ * it must be non-empty (although this test may need to be changed * for serverless XMPP (eg 'Bonjour')): if the xmpp_host property * is set, it takes precedence for the purposes of finding a * an XMPP server: Otherwise we look for a SRV record for 'host', * falling back to a direct connection to 'host' if that fails. */ gchar *node = NULL; /* username */ /* @ */ gchar *host = NULL; /* domain.tld */ /* / */ gchar *uniq = NULL; /* uniquifier */ if (priv->result != NULL) { g_simple_async_report_error_in_idle (G_OBJECT (self), cb, user_data, WOCKY_CONNECTOR_ERROR, WOCKY_CONNECTOR_ERROR_IN_PROGRESS, "Connection already established or in progress"); return; } if (priv->cancellable != NULL) { g_warning ("Cancellable already present, but the async result is NULL; " "something's wrong with the state of the connector, please file a bug."); g_object_unref (priv->cancellable); priv->cancellable = NULL; } priv->result = g_simple_async_result_new (G_OBJECT (self), cb, user_data, source_tag); if (cancellable != NULL) priv->cancellable = g_object_ref (cancellable); wocky_decode_jid (priv->jid, &node, &host, &uniq); if (host == NULL) { abort_connect_code (self, WOCKY_CONNECTOR_ERROR_BAD_JID, "Invalid JID %s", priv->jid); goto abort; } if (*host == '\0') { abort_connect_code (self, WOCKY_CONNECTOR_ERROR_BAD_JID, "Missing Domain %s", priv->jid); goto abort; } if (priv->resource == NULL) priv->resource = uniq; else g_free (uniq); priv->user = node; priv->domain = host; priv->client = g_socket_client_new (); priv->state = WCON_TCP_CONNECTING; /* if the user supplied a specific HOST or PORT, use those: if just a HOST is supplied, HOST:5222, if just a port, set HOST from the JID and use JIDHOST:PORT otherwise attempt to find a SRV record */ if ((priv->xmpp_host != NULL) || (priv->xmpp_port != 0)) { guint port = (priv->xmpp_port == 0) ? 5222 : priv->xmpp_port; const gchar *srv = (priv->xmpp_host == NULL) ? host : priv->xmpp_host; DEBUG ("host: %s; port: %d", priv->xmpp_host, priv->xmpp_port); connect_to_host_async (self, srv, port); } else { g_socket_client_connect_to_service_async (priv->client, host, "xmpp-client", priv->cancellable, tcp_srv_connected, self); } return; abort: g_free (host); g_free (node); g_free (uniq); return; } /** * wocky_connector_connect_async: * @self: a #WockyConnector instance. * @cancellable: an #GCancellable, or %NULL * @cb: a #GAsyncReadyCallback to call when the operation completes. * @user_data: a #gpointer to pass to the callback. * * Connect to the account/server specified by the @self. * @cb should invoke wocky_connector_connect_finish(). */ void wocky_connector_connect_async (WockyConnector *self, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer user_data) { connector_connect_async (self, wocky_connector_connect_async, cancellable, cb, user_data); } /** * wocky_connector_unregister_async: * @self: a #WockyConnector instance. * @cancellable: an #GCancellable, or %NULL * @cb: a #GAsyncReadyCallback to call when the operation completes. * @user_data: a #gpointer to pass to the callback @cb. * * Connect to the account/server specified by @self, and unregister (cancel) * the account there. * @cb should invoke wocky_connector_unregister_finish(). */ void wocky_connector_unregister_async (WockyConnector *self, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer user_data) { WockyConnectorPrivate *priv = self->priv; priv->reg_op = XEP77_CANCEL; connector_connect_async (self, wocky_connector_unregister_async, cancellable, cb, user_data); } /** * wocky_connector_register_async: * @self: a #WockyConnector instance. * @cancellable: an #GCancellable, or %NULL * @cb: a #GAsyncReadyCallback to call when the operation completes. * @user_data: a #gpointer to pass to the callback @cb. * * Connect to the account/server specified by @self, register (set up) * the account there and then log in to it. * @cb should invoke wocky_connector_register_finish(). */ void wocky_connector_register_async (WockyConnector *self, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer user_data) { WockyConnectorPrivate *priv = self->priv; priv->reg_op = XEP77_SIGNUP; connector_connect_async (self, wocky_connector_register_async, cancellable, cb, user_data); } /** * wocky_connector_new: * @jid: a JID (user AT domain). * @pass: the password. * @resource: the resource (sans '/'), or NULL to autogenerate one. * @auth_registry: a #WockyAuthRegistry, or %NULL * @tls_handler: a #WockyTLSHandler, or %NULL * * Connect to the account/server specified by @self. * To set other #WockyConnector properties, use g_object_new() instead. * * Returns: a #WockyConnector instance which can be used to connect to, * register or cancel an account */ WockyConnector * wocky_connector_new (const gchar *jid, const gchar *pass, const gchar *resource, WockyAuthRegistry *auth_registry, WockyTLSHandler *tls_handler) { return g_object_new (WOCKY_TYPE_CONNECTOR, "jid", jid, "password", pass, "resource", resource, "auth-registry", auth_registry, "tls-handler", tls_handler, NULL); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-tls-handler.h0000664000175000017500000000735012212322440025551 0ustar00cassidycassidy00000000000000/* * wocky-tls-handler.h - Header for WockyTLSHandler * Copyright (C) 2010 Collabora Ltd. * @author Cosimo Cecchi * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_TLS_HANDLER_H__ #define __WOCKY_TLS_HANDLER_H__ #include #include "wocky-tls.h" G_BEGIN_DECLS typedef struct _WockyTLSHandler WockyTLSHandler; /** * WockyTLSHandlerClass: * @verify_async_func: a function to call to start an asychronous * verify operation; see wocky_tls_handler_verify_async() for more * details * @verify_finish_func: a function to call to finish an asychronous * verify operation; see wocky_tls_handler_verify_finish() for more * details * * The class of a #WockyTLSHandler. */ typedef struct _WockyTLSHandlerClass WockyTLSHandlerClass; typedef struct _WockyTLSHandlerPrivate WockyTLSHandlerPrivate; typedef void (*WockyTLSHandlerVerifyAsyncFunc) (WockyTLSHandler *self, WockyTLSSession *tls_session, const gchar *peername, GStrv extra_identities, GAsyncReadyCallback callback, gpointer user_data); typedef gboolean (*WockyTLSHandlerVerifyFinishFunc) (WockyTLSHandler *self, GAsyncResult *res, GError **error); struct _WockyTLSHandlerClass { /**/ GObjectClass parent_class; /**/ WockyTLSHandlerVerifyAsyncFunc verify_async_func; WockyTLSHandlerVerifyFinishFunc verify_finish_func; }; struct _WockyTLSHandler { /**/ GObject parent; WockyTLSHandlerPrivate *priv; }; GType wocky_tls_handler_get_type (void); #define WOCKY_TYPE_TLS_HANDLER \ (wocky_tls_handler_get_type ()) #define WOCKY_TLS_HANDLER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_TLS_HANDLER, WockyTLSHandler)) #define WOCKY_TLS_HANDLER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_TLS_HANDLER, \ WockyTLSHandlerClass)) #define WOCKY_IS_TLS_HANDLER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_TLS_HANDLER)) #define WOCKY_IS_TLS_HANDLER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_TLS_HANDLER)) #define WOCKY_TLS_HANDLER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_TLS_HANDLER, \ WockyTLSHandlerClass)) WockyTLSHandler * wocky_tls_handler_new (gboolean ignore_ssl_errors); void wocky_tls_handler_verify_async (WockyTLSHandler *self, WockyTLSSession *tls_session, const gchar *peername, GStrv extra_identities, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_tls_handler_verify_finish (WockyTLSHandler *self, GAsyncResult *result, GError **error); gboolean wocky_tls_handler_add_ca (WockyTLSHandler *self, const gchar *path); void wocky_tls_handler_forget_cas (WockyTLSHandler *self); gboolean wocky_tls_handler_add_crl (WockyTLSHandler *self, const gchar *path); GSList *wocky_tls_handler_get_cas (WockyTLSHandler *self); GSList *wocky_tls_handler_get_crl (WockyTLSHandler *self); G_END_DECLS #endif /* #ifndef __WOCKY_TLS_HANDLER_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-tls-connector.h0000664000175000017500000000553611720661341026143 0ustar00cassidycassidy00000000000000/* * wocky-tls-connector.h - Header for WockyTLSConnector * Copyright (C) 2010 Collabora Ltd. * @author Cosimo Cecchi * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_TLS_CONNECTOR_H__ #define __WOCKY_TLS_CONNECTOR_H__ #include #include "wocky-tls-handler.h" #include "wocky-xmpp-connection.h" G_BEGIN_DECLS typedef struct _WockyTLSConnector WockyTLSConnector; /** * WockyTLSConnectorClass: * * The class of a #WockyTLSConnector. */ typedef struct _WockyTLSConnectorClass WockyTLSConnectorClass; typedef struct _WockyTLSConnectorPrivate WockyTLSConnectorPrivate; struct _WockyTLSConnectorClass { /**/ GObjectClass parent_class; }; struct _WockyTLSConnector { /**/ GObject parent; WockyTLSConnectorPrivate *priv; }; GType wocky_tls_connector_get_type (void); #define WOCKY_TYPE_TLS_CONNECTOR \ (wocky_tls_connector_get_type ()) #define WOCKY_TLS_CONNECTOR(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_TLS_CONNECTOR, \ WockyTLSConnector)) #define WOCKY_TLS_CONNECTOR_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_TLS_CONNECTOR, \ WockyTLSConnectorClass)) #define WOCKY_IS_TLS_CONNECTOR(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_TLS_CONNECTOR)) #define WOCKY_IS_TLS_CONNECTOR_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_TLS_CONNECTOR)) #define WOCKY_TLS_CONNECTOR_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_TLS_CONNECTOR, \ WockyTLSConnectorClass)) WockyTLSConnector * wocky_tls_connector_new (WockyTLSHandler *handler); void wocky_tls_connector_secure_async (WockyTLSConnector *self, WockyXmppConnection *connection, gboolean old_style_ssl, const gchar *peername, GStrv extra_identities, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); WockyXmppConnection * wocky_tls_connector_secure_finish (WockyTLSConnector *self, GAsyncResult *res, GError **error); G_END_DECLS #endif /* #ifndef __WOCKY_TLS_CONNECTOR_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-auth-handler.h0000664000175000017500000001054411720661341025720 0ustar00cassidycassidy00000000000000#if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef _WOCKY_AUTH_HANDLER_H #define _WOCKY_AUTH_HANDLER_H #include #include "wocky-stanza.h" G_BEGIN_DECLS #define WOCKY_TYPE_AUTH_HANDLER (wocky_auth_handler_get_type ()) #define WOCKY_AUTH_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST( \ (obj), WOCKY_TYPE_AUTH_HANDLER, WockyAuthHandler)) #define WOCKY_IS_AUTH_HANDLER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_AUTH_HANDLER)) #define WOCKY_AUTH_HANDLER_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ( \ (obj), WOCKY_TYPE_AUTH_HANDLER, WockyAuthHandlerIface)) typedef struct _WockyAuthHandler WockyAuthHandler; /** * WockyAuthInitialResponseFunc: * @handler: a #WockyAuthHandler object * @initial_data: (out): a #GString location to fill with the initial data * @error: an optional location for a #GError to fill, or %NULL * * Called when authentication begins, if the mechanism allows a * response to an implicit challenge during AUTH initiation (which, in * XMPP, corresponds to sending the <auth/> stanza * to the server). * * The function should return %TRUE on success, and optionally set the * @initial_data to a string if there is * initial data to send. On error, it should return %FALSE and set * @error. * * Returns: %TRUE on success, otherwise %FALSE **/ typedef gboolean (*WockyAuthInitialResponseFunc) (WockyAuthHandler *handler, GString **initial_data, GError **error); /** * WockyAuthChallengeFunc: * @handler: a #WockyAuthHandler object * @data: the challenge string * @response: (out) (transfer full): a location to fill with a challenge * response in a #GString * @error: an optional location for a #GError to fill, or %NULL * * Called during authentication when a * <challenge/> stanza or a * <success/> with data is received. The handler * should put response data into @response if * appropriate. The handler is responsible for Base64-encoding * responses if appropriate. * * On success the handler should return %TRUE and on failure it should * return %FALSE and must set the error passed via @error. * * Returns: %TRUE On success, otherwise %FALSE **/ typedef gboolean (*WockyAuthAuthDataFunc) ( WockyAuthHandler *handler, const GString *data, GString **response, GError **error); /** * WockyAuthSuccessFunc: * @handler: a #WockyAuthHandler object * @error: an optional location for a #GError to fill, or %NULL * * Called when a <success/> stanza is received * during authentication. If no error is returned, then authentication * is considered finished. (Typically, an error is only raised if the * <success/> stanza was received earlier than * expected) * * Returns: %TRUE on success, otherwise %FALSE **/ typedef gboolean (*WockyAuthSuccessFunc) ( WockyAuthHandler *handler, GError **error); GType wocky_auth_handler_get_type (void); const gchar * wocky_auth_handler_get_mechanism (WockyAuthHandler *handler); gboolean wocky_auth_handler_is_plain (WockyAuthHandler *handler); gboolean wocky_auth_handler_get_initial_response (WockyAuthHandler *handler, GString **initial_data, GError **error); gboolean wocky_auth_handler_handle_auth_data ( WockyAuthHandler *handler, const GString *data, GString **response, GError **error); gboolean wocky_auth_handler_handle_success ( WockyAuthHandler *handler, GError **error); typedef struct _WockyAuthHandlerIface WockyAuthHandlerIface; /** * WockyAuthHandlerIface: * @parent: The parent interface. * @mechanism: The AUTH mechanism which this handler responds to * challenges for. * @plain: Whether the mechanism this handler handles sends secrets in * plaintext. * @initial_response_func: Called when the initial <auth * /> stanza is generated * @auth_data_func: Called when any authentication data from the * server is received * @success_func: Called when a <success/> stanza * is received. **/ struct _WockyAuthHandlerIface { GTypeInterface parent; gchar *mechanism; gboolean plain; WockyAuthInitialResponseFunc initial_response_func; WockyAuthAuthDataFunc auth_data_func; WockyAuthSuccessFunc success_func; }; G_END_DECLS #endif /* defined _WOCKY_AUTH_HANDLER_H */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-xmpp-connection.h0000664000175000017500000001412311720661341026462 0ustar00cassidycassidy00000000000000/* * wocky-xmpp-connection.h - Header for WockyXmppConnection * Copyright (C) 2006-2009 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_XMPP_CONNECTION_H__ #define __WOCKY_XMPP_CONNECTION_H__ #include #include #include "wocky-stanza.h" G_BEGIN_DECLS typedef struct _WockyXmppConnection WockyXmppConnection; /** * WockyXmppConnectionClass: * * The class of a #WockyXmppConnection. */ typedef struct _WockyXmppConnectionClass WockyXmppConnectionClass; typedef struct _WockyXmppConnectionPrivate WockyXmppConnectionPrivate; /** * WockyXmppConnectionError: * @WOCKY_XMPP_CONNECTION_ERROR_EOS : Connection got closed before receiving * an XMPP stream close. * @WOCKY_XMPP_CONNECTION_ERROR_CLOSED : Other side closed the xmpp stream. * @WOCKY_XMPP_CONNECTION_ERROR_NOT_OPEN : Trying to send or receive while the * connection isn't open. * @WOCKY_XMPP_CONNECTION_ERROR_IS_CLOSED : Trying to send or receive * while the connection is closed. * @WOCKY_XMPP_CONNECTION_ERROR_IS_OPEN: Trying to send or receive * the connection opening when it's already open * * The #WockyXmppConnection specific errors that can occur while * reading a stream. */ typedef enum { WOCKY_XMPP_CONNECTION_ERROR_EOS, WOCKY_XMPP_CONNECTION_ERROR_CLOSED, WOCKY_XMPP_CONNECTION_ERROR_NOT_OPEN, WOCKY_XMPP_CONNECTION_ERROR_IS_CLOSED, WOCKY_XMPP_CONNECTION_ERROR_IS_OPEN, } WockyXmppConnectionError; GQuark wocky_xmpp_connection_error_quark (void); /** * WOCKY_XMPP_CONNECTION_ERROR: * * Get access to the error quark of the xmpp connection. */ #define WOCKY_XMPP_CONNECTION_ERROR (wocky_xmpp_connection_error_quark ()) struct _WockyXmppConnectionClass { /**/ GObjectClass parent_class; }; struct _WockyXmppConnection { /**/ GObject parent; WockyXmppConnectionPrivate *priv; }; GType wocky_xmpp_connection_get_type (void); /* TYPE MACROS */ #define WOCKY_TYPE_XMPP_CONNECTION \ (wocky_xmpp_connection_get_type ()) #define WOCKY_XMPP_CONNECTION(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_XMPP_CONNECTION, \ WockyXmppConnection)) #define WOCKY_XMPP_CONNECTION_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_XMPP_CONNECTION, \ WockyXmppConnectionClass)) #define WOCKY_IS_XMPP_CONNECTION(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_XMPP_CONNECTION)) #define WOCKY_IS_XMPP_CONNECTION_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_XMPP_CONNECTION)) #define WOCKY_XMPP_CONNECTION_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_XMPP_CONNECTION, \ WockyXmppConnectionClass)) WockyXmppConnection *wocky_xmpp_connection_new (GIOStream *stream); void wocky_xmpp_connection_send_open_async (WockyXmppConnection *connection, const gchar *to, const gchar *from, const gchar *version, const gchar *lang, const gchar *id, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_xmpp_connection_send_open_finish ( WockyXmppConnection *connection, GAsyncResult *result, GError **error); void wocky_xmpp_connection_recv_open_async (WockyXmppConnection *connection, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_xmpp_connection_recv_open_finish ( WockyXmppConnection *connection, GAsyncResult *result, gchar **to, gchar **from, gchar **version, gchar **lang, gchar **id, GError **error); void wocky_xmpp_connection_send_stanza_async (WockyXmppConnection *connection, WockyStanza *stanza, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_xmpp_connection_send_stanza_finish ( WockyXmppConnection *connection, GAsyncResult *result, GError **error); void wocky_xmpp_connection_recv_stanza_async (WockyXmppConnection *connection, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); WockyStanza *wocky_xmpp_connection_recv_stanza_finish ( WockyXmppConnection *connection, GAsyncResult *result, GError **error); void wocky_xmpp_connection_send_close_async (WockyXmppConnection *connection, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_xmpp_connection_send_close_finish ( WockyXmppConnection *connection, GAsyncResult *result, GError **error); void wocky_xmpp_connection_force_close_async (WockyXmppConnection *connection, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_xmpp_connection_force_close_finish ( WockyXmppConnection *connection, GAsyncResult *result, GError **error); void wocky_xmpp_connection_send_whitespace_ping_async (WockyXmppConnection *connection, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_xmpp_connection_send_whitespace_ping_finish ( WockyXmppConnection *connection, GAsyncResult *result, GError **error); void wocky_xmpp_connection_reset (WockyXmppConnection *connection); gchar * wocky_xmpp_connection_new_id (WockyXmppConnection *self); G_END_DECLS #endif /* #ifndef __WOCKY_XMPP_CONNECTION_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-pubsub-node-internal.h0000664000175000017500000000302411720661341027374 0ustar00cassidycassidy00000000000000/* * wocky-pubsub-node-internal.h - internal methods on WockyPubsubNode * used by WockyPubsubService * Copyright © 2010 Collabora Ltd. * Copyright © 2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_COMPILATION) # error "This is an internal header." #endif #ifndef WOCKY_PUBSUB_NODE_INTERNAL_H #define WOCKY_PUBSUB_NODE_INTERNAL_H #include "wocky-pubsub-node.h" typedef void (*WockyPubsubNodeEventHandler) ( WockyPubsubNode *self, WockyStanza *event_stanza, WockyNode *event_node, WockyNode *action_node); typedef struct { const gchar *action; WockyPubsubNodeEventHandler method; } WockyPubsubNodeEventMapping; const WockyPubsubNodeEventMapping *_wocky_pubsub_node_get_event_mappings ( guint *n_mappings); #endif /* WOCKY_PUBSUB_NODE_INTERNAL_H */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-http-proxy.c0000644000175000017500000002506311544576223025505 0ustar00cassidycassidy00000000000000 /* wocky-http-proxy.c: Source for WockyHttpProxy * * Copyright (C) 2010 Collabora, Ltd. * @author Nicolas Dufresne * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "wocky-http-proxy.h" #include #include struct _WockyHttpProxy { GObject parent; }; struct _WockyHttpProxyClass { GObjectClass parent_class; }; static void wocky_http_proxy_iface_init (GProxyInterface *proxy_iface); #define wocky_http_proxy_get_type _wocky_http_proxy_get_type G_DEFINE_TYPE_WITH_CODE (WockyHttpProxy, wocky_http_proxy, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_PROXY, wocky_http_proxy_iface_init) g_io_extension_point_set_required_type ( g_io_extension_point_register (G_PROXY_EXTENSION_POINT_NAME), G_TYPE_PROXY); g_io_extension_point_implement (G_PROXY_EXTENSION_POINT_NAME, g_define_type_id, "http", 0)) static void wocky_http_proxy_init (WockyHttpProxy *proxy) { } #define HTTP_END_MARKER "\r\n\r\n" static gchar * create_request (GProxyAddress *proxy_address, gboolean *has_cred) { const gchar *hostname; gint port; const gchar *username; const gchar *password; GString *request; gchar *ascii_hostname; if (has_cred) *has_cred = FALSE; hostname = g_proxy_address_get_destination_hostname (proxy_address); port = g_proxy_address_get_destination_port (proxy_address); username = g_proxy_address_get_username (proxy_address); password = g_proxy_address_get_password (proxy_address); request = g_string_new (NULL); ascii_hostname = g_hostname_to_ascii (hostname); g_string_append_printf (request, "CONNECT %s:%i HTTP/1.0\r\n" "Host: %s:%i\r\n" "Proxy-Connection: keep-alive\r\n" "User-Agent: GLib/%i.%i\r\n", ascii_hostname, port, ascii_hostname, port, GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION); g_free (ascii_hostname); if (username != NULL && password != NULL) { gchar *cred; gchar *base64_cred; if (has_cred) *has_cred = TRUE; cred = g_strdup_printf ("%s:%s", username, password); base64_cred = g_base64_encode ((guchar *) cred, strlen (cred)); g_free (cred); g_string_append_printf (request, "Proxy-Authorization: %s\r\n", base64_cred); g_free (base64_cred); } g_string_append (request, "\r\n"); return g_string_free (request, FALSE); } static gboolean check_reply (const gchar *buffer, gboolean has_cred, GError **error) { gint err_code; const gchar *ptr = buffer + 7; if (strncmp (buffer, "HTTP/1.", 7) != 0 || (*ptr != '0' && *ptr != '1')) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED, "Bad HTTP proxy reply"); return FALSE; } ptr++; while (*ptr == ' ') ptr++; err_code = atoi (ptr); if (err_code < 200 || err_code >= 300) { const gchar *msg_start; gchar *msg; while (g_ascii_isdigit (*ptr)) ptr++; while (*ptr == ' ') ptr++; msg_start = ptr; ptr = strchr (msg_start, '\r'); if (ptr == NULL) ptr = strchr (msg_start, '\0'); msg = g_strndup (msg_start, ptr - msg_start); if (err_code == 407) { if (has_cred) g_set_error (error, G_IO_ERROR, G_IO_ERROR_PROXY_AUTH_FAILED, "HTTP proxy authentication failed"); else g_set_error (error, G_IO_ERROR, G_IO_ERROR_PROXY_NEED_AUTH, "HTTP proxy authentication required"); } else if (msg[0] == '\0') g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED, "Connection failed due to broken HTTP reply"); else g_set_error (error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED, "HTTP proxy connection failed: %i %s", err_code, msg); g_free (msg); return FALSE; } return TRUE; } static GIOStream * wocky_http_proxy_connect (GProxy *proxy, GIOStream *io_stream, GProxyAddress *proxy_address, GCancellable *cancellable, GError **error) { GInputStream *in; GOutputStream *out; GDataInputStream *data_in; gchar *buffer; gboolean has_cred; in = g_io_stream_get_input_stream (io_stream); out = g_io_stream_get_output_stream (io_stream); data_in = g_data_input_stream_new (in); g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (data_in), FALSE); buffer = create_request (proxy_address, &has_cred); if (!g_output_stream_write_all (out, buffer, strlen (buffer), NULL, cancellable, error)) goto error; g_free (buffer); buffer = g_data_input_stream_read_until (data_in, HTTP_END_MARKER, NULL, cancellable, error); g_object_unref (data_in); data_in = NULL; if (buffer == NULL) { if (error && (*error == NULL)) g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED, "HTTP proxy server closed connection unexpectedly."); goto error; } if (!check_reply (buffer, has_cred, error)) goto error; g_free (buffer); return g_object_ref (io_stream); error: if (data_in != NULL) g_object_unref (data_in); g_free (buffer); return NULL; } typedef struct { GSimpleAsyncResult *simple; GIOStream *io_stream; gchar *buffer; gssize length; gssize offset; GDataInputStream *data_in; gboolean has_cred; GCancellable *cancellable; } ConnectAsyncData; static void request_write_cb (GObject *source, GAsyncResult *res, gpointer user_data); static void reply_read_cb (GObject *source, GAsyncResult *res, gpointer user_data); static void free_connect_data (ConnectAsyncData *data) { if (data->io_stream != NULL) g_object_unref (data->io_stream); g_free (data->buffer); if (data->data_in != NULL) g_object_unref (data->data_in); if (data->cancellable != NULL) g_object_unref (data->cancellable); g_slice_free (ConnectAsyncData, data); } static void complete_async_from_error (ConnectAsyncData *data, GError *error) { GSimpleAsyncResult *simple = data->simple; if (error == NULL) g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_PROXY_FAILED, "HTTP proxy server closed connection unexpectedly."); g_simple_async_result_set_from_error (data->simple, error); g_error_free (error); g_simple_async_result_set_op_res_gpointer (simple, NULL, NULL); g_simple_async_result_complete (simple); g_object_unref (simple); } static void do_write (GAsyncReadyCallback callback, ConnectAsyncData *data) { GOutputStream *out; out = g_io_stream_get_output_stream (data->io_stream); g_output_stream_write_async (out, data->buffer + data->offset, data->length - data->offset, G_PRIORITY_DEFAULT, data->cancellable, callback, data); } static void wocky_http_proxy_connect_async (GProxy *proxy, GIOStream *io_stream, GProxyAddress *proxy_address, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *simple; ConnectAsyncData *data; GInputStream *in; simple = g_simple_async_result_new (G_OBJECT (proxy), callback, user_data, wocky_http_proxy_connect_async); data = g_slice_new0 (ConnectAsyncData); data->simple = simple; data->io_stream = g_object_ref (io_stream); if (cancellable != NULL) data->cancellable = g_object_ref (cancellable); in = g_io_stream_get_input_stream (io_stream); data->data_in = g_data_input_stream_new (in); g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (data->data_in), FALSE); g_simple_async_result_set_op_res_gpointer (simple, data, (GDestroyNotify) free_connect_data); data->buffer = create_request (proxy_address, &data->has_cred); data->length = strlen (data->buffer); data->offset = 0; do_write (request_write_cb, data); } static void request_write_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GError *error = NULL; ConnectAsyncData *data = user_data; gssize written; written = g_output_stream_write_finish (G_OUTPUT_STREAM (source), res, &error); if (written < 0) { complete_async_from_error (data, error); return; } data->offset += written; if (data->offset == data->length) { g_free (data->buffer); data->buffer = NULL; g_data_input_stream_read_until_async (data->data_in, HTTP_END_MARKER, G_PRIORITY_DEFAULT, data->cancellable, reply_read_cb, data); } else { do_write (request_write_cb, data); } } static void reply_read_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GError *error = NULL; ConnectAsyncData *data = user_data; data->buffer = g_data_input_stream_read_until_finish (data->data_in, res, NULL, &error); if (data->buffer == NULL) { complete_async_from_error (data, error); return; } if (!check_reply (data->buffer, data->has_cred, &error)) { complete_async_from_error (data, error); return; } g_simple_async_result_complete (data->simple); g_object_unref (data->simple); } static GIOStream * wocky_http_proxy_connect_finish (GProxy *proxy, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); ConnectAsyncData *data = g_simple_async_result_get_op_res_gpointer (simple); if (g_simple_async_result_propagate_error (simple, error)) return NULL; return g_object_ref (data->io_stream); } static gboolean wocky_http_proxy_supports_hostname (GProxy *proxy) { return TRUE; } static void wocky_http_proxy_class_init (WockyHttpProxyClass *class) { } static void wocky_http_proxy_iface_init (GProxyInterface *proxy_iface) { proxy_iface->connect = wocky_http_proxy_connect; proxy_iface->connect_async = wocky_http_proxy_connect_async; proxy_iface->connect_finish = wocky_http_proxy_connect_finish; proxy_iface->supports_hostname = wocky_http_proxy_supports_hostname; } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jingle-transport-google.c0000664000175000017500000004570112212322440030105 0ustar00cassidycassidy00000000000000/* * wocky-jingle-transport-google.c - Source for WockyJingleTransportGoogle * * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "wocky-jingle-transport-google.h" #include #include #include #include #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_JINGLE #include "wocky-debug-internal.h" #include "wocky-jingle-content.h" #include "wocky-jingle-factory.h" #include "wocky-jingle-session.h" #include "wocky-namespaces.h" #include "wocky-utils.h" static void transport_iface_init (gpointer g_iface, gpointer iface_data); G_DEFINE_TYPE_WITH_CODE (WockyJingleTransportGoogle, wocky_jingle_transport_google, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (WOCKY_TYPE_JINGLE_TRANSPORT_IFACE, transport_iface_init)); /* signal enum */ enum { NEW_CANDIDATES, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; /* properties */ enum { PROP_CONTENT = 1, PROP_TRANSPORT_NS, PROP_STATE, LAST_PROPERTY }; struct _WockyJingleTransportGooglePrivate { WockyJingleContent *content; WockyJingleTransportState state; gchar *transport_ns; /* Component names or jingle-share transport 'channels' g_strdup'd component name => GINT_TO_POINTER (component id) */ GHashTable *component_names; GList *local_candidates; /* A pointer into "local_candidates" list to mark the * candidates that are still not transmitted, or NULL * if all of them are transmitted. */ GList *pending_candidates; GList *remote_candidates; gboolean dispose_has_run; }; static void wocky_jingle_transport_google_init (WockyJingleTransportGoogle *obj) { WockyJingleTransportGooglePrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, WOCKY_TYPE_JINGLE_TRANSPORT_GOOGLE, WockyJingleTransportGooglePrivate); obj->priv = priv; priv->component_names = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); priv->dispose_has_run = FALSE; } static void wocky_jingle_transport_google_dispose (GObject *object) { WockyJingleTransportGoogle *trans = WOCKY_JINGLE_TRANSPORT_GOOGLE (object); WockyJingleTransportGooglePrivate *priv = trans->priv; if (priv->dispose_has_run) return; DEBUG ("dispose called"); priv->dispose_has_run = TRUE; g_hash_table_unref (priv->component_names); priv->component_names = NULL; jingle_transport_free_candidates (priv->remote_candidates); priv->remote_candidates = NULL; jingle_transport_free_candidates (priv->local_candidates); priv->local_candidates = NULL; g_free (priv->transport_ns); priv->transport_ns = NULL; if (G_OBJECT_CLASS (wocky_jingle_transport_google_parent_class)->dispose) G_OBJECT_CLASS (wocky_jingle_transport_google_parent_class)->dispose (object); } static void wocky_jingle_transport_google_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyJingleTransportGoogle *trans = WOCKY_JINGLE_TRANSPORT_GOOGLE (object); WockyJingleTransportGooglePrivate *priv = trans->priv; switch (property_id) { case PROP_CONTENT: g_value_set_object (value, priv->content); break; case PROP_TRANSPORT_NS: g_value_set_string (value, priv->transport_ns); break; case PROP_STATE: g_value_set_uint (value, priv->state); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_jingle_transport_google_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyJingleTransportGoogle *trans = WOCKY_JINGLE_TRANSPORT_GOOGLE (object); WockyJingleTransportGooglePrivate *priv = trans->priv; switch (property_id) { case PROP_CONTENT: priv->content = g_value_get_object (value); break; case PROP_TRANSPORT_NS: g_free (priv->transport_ns); priv->transport_ns = g_value_dup_string (value); break; case PROP_STATE: priv->state = g_value_get_uint (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_jingle_transport_google_class_init (WockyJingleTransportGoogleClass *cls) { GObjectClass *object_class = G_OBJECT_CLASS (cls); GParamSpec *param_spec; g_type_class_add_private (cls, sizeof (WockyJingleTransportGooglePrivate)); object_class->get_property = wocky_jingle_transport_google_get_property; object_class->set_property = wocky_jingle_transport_google_set_property; object_class->dispose = wocky_jingle_transport_google_dispose; /* property definitions */ param_spec = g_param_spec_object ("content", "WockyJingleContent object", "Jingle content object using this transport.", WOCKY_TYPE_JINGLE_CONTENT, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_CONTENT, param_spec); param_spec = g_param_spec_string ("transport-ns", "Transport namespace", "Namespace identifying the transport type.", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_TRANSPORT_NS, param_spec); param_spec = g_param_spec_uint ("state", "Connection state for the transport.", "Enum specifying the connection state of the transport.", WOCKY_JINGLE_TRANSPORT_STATE_DISCONNECTED, WOCKY_JINGLE_TRANSPORT_STATE_CONNECTED, WOCKY_JINGLE_TRANSPORT_STATE_DISCONNECTED, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_STATE, param_spec); /* signal definitions */ signals[NEW_CANDIDATES] = g_signal_new ( "new-candidates", G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); } static void parse_candidates (WockyJingleTransportIface *obj, WockyNode *transport_node, GError **error) { WockyJingleTransportGoogle *t = WOCKY_JINGLE_TRANSPORT_GOOGLE (obj); WockyJingleTransportGooglePrivate *priv = t->priv; GList *candidates = NULL; WockyNodeIter i; WockyNode *node; wocky_node_iter_init (&i, transport_node, "candidate", NULL); while (wocky_node_iter_next (&i, &node)) { const gchar *name, *address, *user, *pass, *str; guint port, net, gen, component; int pref; WockyJingleTransportProtocol proto; WockyJingleCandidateType ctype; WockyJingleCandidate *c; name = wocky_node_get_attribute (node, "name"); if (name == NULL) break; if (!g_hash_table_lookup_extended (priv->component_names, name, NULL, NULL)) { DEBUG ("component name %s unknown to this transport", name); continue; } component = GPOINTER_TO_INT (g_hash_table_lookup (priv->component_names, name)); address = wocky_node_get_attribute (node, "address"); if (address == NULL) break; str = wocky_node_get_attribute (node, "port"); if (str == NULL) break; port = atoi (str); str = wocky_node_get_attribute (node, "protocol"); if (str == NULL) break; if (!wocky_strdiff (str, "udp")) { proto = WOCKY_JINGLE_TRANSPORT_PROTOCOL_UDP; } else if (!wocky_strdiff (str, "tcp")) { /* candiates on port 443 must be "ssltcp" */ if (port == 443) break; proto = WOCKY_JINGLE_TRANSPORT_PROTOCOL_TCP; } else if (!wocky_strdiff (str, "ssltcp")) { /* "ssltcp" must use port 443 */ if (port != 443) break; /* we really don't care about "ssltcp" otherwise */ proto = WOCKY_JINGLE_TRANSPORT_PROTOCOL_TCP; } else { /* unknown protocol */ DEBUG ("unknown protocol: %s", str); break; } str = wocky_node_get_attribute (node, "preference"); if (str == NULL) break; pref = g_ascii_strtod (str, NULL) * 65536; str = wocky_node_get_attribute (node, "type"); if (str == NULL) break; if (!wocky_strdiff (str, "local")) { ctype = WOCKY_JINGLE_CANDIDATE_TYPE_LOCAL; } else if (!wocky_strdiff (str, "stun")) { ctype = WOCKY_JINGLE_CANDIDATE_TYPE_STUN; } else if (!wocky_strdiff (str, "relay")) { ctype = WOCKY_JINGLE_CANDIDATE_TYPE_RELAY; } else { /* unknown candidate type */ DEBUG ("unknown candidate type: %s", str); break; } user = wocky_node_get_attribute (node, "username"); if (user == NULL) break; pass = wocky_node_get_attribute (node, "password"); if (pass == NULL) break; str = wocky_node_get_attribute (node, "network"); if (str == NULL) break; net = atoi (str); str = wocky_node_get_attribute (node, "generation"); if (str == NULL) break; gen = atoi (str); str = wocky_node_get_attribute (node, "component"); if (str != NULL) component = atoi (str); c = wocky_jingle_candidate_new (proto, ctype, NULL, component, address, port, gen, pref, user, pass, net); candidates = g_list_append (candidates, c); } if (wocky_node_iter_next (&i, NULL)) { DEBUG ("not all nodes were processed, reporting error"); /* rollback these */ jingle_transport_free_candidates (candidates); g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, "invalid candidate"); return; } DEBUG ("emitting %d new remote candidates", g_list_length (candidates)); g_signal_emit (obj, signals[NEW_CANDIDATES], 0, candidates); /* append them to the known remote candidates */ priv->remote_candidates = g_list_concat (priv->remote_candidates, candidates); } static void transmit_candidates (WockyJingleTransportGoogle *transport, const gchar *name, GList *candidates) { WockyJingleTransportGooglePrivate *priv = transport->priv; GList *li; WockyStanza *msg; WockyNode *trans_node, *sess_node; if (candidates == NULL) return; msg = wocky_jingle_session_new_message (priv->content->session, WOCKY_JINGLE_ACTION_TRANSPORT_INFO, &sess_node); wocky_jingle_content_produce_node (priv->content, sess_node, FALSE, TRUE, &trans_node); for (li = candidates; li; li = li->next) { WockyJingleCandidate *c = (WockyJingleCandidate *) li->data; gchar port_str[16], pref_str[16], comp_str[16], *type_str, *proto_str; WockyNode *cnode; sprintf (port_str, "%d", c->port); sprintf (pref_str, "%lf", c->preference / 65536.0); sprintf (comp_str, "%d", c->component); switch (c->type) { case WOCKY_JINGLE_CANDIDATE_TYPE_LOCAL: type_str = "local"; break; case WOCKY_JINGLE_CANDIDATE_TYPE_STUN: type_str = "stun"; break; case WOCKY_JINGLE_CANDIDATE_TYPE_RELAY: type_str = "relay"; break; default: g_assert_not_reached (); } switch (c->protocol) { case WOCKY_JINGLE_TRANSPORT_PROTOCOL_UDP: proto_str = "udp"; break; case WOCKY_JINGLE_TRANSPORT_PROTOCOL_TCP: if ((c->port == 443) && (c->type == WOCKY_JINGLE_CANDIDATE_TYPE_RELAY)) proto_str = "ssltcp"; else proto_str = "tcp"; break; default: g_assert_not_reached (); } cnode = wocky_node_add_child (trans_node, "candidate"); wocky_node_set_attributes (cnode, "address", c->address, "port", port_str, "username", c->username, "password", c->password != NULL ? c->password : "", "preference", pref_str, "protocol", proto_str, "type", type_str, "component", comp_str, "network", "0", "generation", "0", NULL); wocky_node_set_attribute (cnode, "name", name); } wocky_porter_send_iq_async ( wocky_jingle_session_get_porter (priv->content->session), msg, NULL, NULL, NULL); g_object_unref (msg); } /* Groups @candidates into rtp and rtcp and sends each group in its own * transport-info. This works around old Gabble, which rejected transport-info * stanzas containing non-rtp candidates. */ static void group_and_transmit_candidates (WockyJingleTransportGoogle *transport, GList *candidates) { WockyJingleTransportGooglePrivate *priv = transport->priv; GList *all_candidates = NULL; GList *li; GList *cands; for (li = candidates; li != NULL; li = g_list_next (li)) { WockyJingleCandidate *c = li->data; for (cands = all_candidates; cands != NULL; cands = g_list_next (cands)) { WockyJingleCandidate *c2 = ((GList *) cands->data)->data; if (c->component == c2->component) { break; } } if (cands == NULL) { all_candidates = g_list_prepend (all_candidates, NULL); cands = all_candidates; } cands->data = g_list_prepend (cands->data, c); } for (cands = all_candidates; cands != NULL; cands = g_list_next (cands)) { GHashTableIter iter; gpointer key, value; gchar *name = NULL; WockyJingleCandidate *c = ((GList *) cands->data)->data; g_hash_table_iter_init (&iter, priv->component_names); while (g_hash_table_iter_next (&iter, &key, &value)) { if (GPOINTER_TO_INT (value) == c->component) { name = key; break; } } if (name) { transmit_candidates (transport, name, cands->data); } else { DEBUG ("Ignoring unknown component %d", c->component); } g_list_free (cands->data); } g_list_free (all_candidates); } /* Takes in a list of slice-allocated WockyJingleCandidate structs */ static void new_local_candidates (WockyJingleTransportIface *obj, GList *new_candidates) { WockyJingleTransportGoogle *transport = WOCKY_JINGLE_TRANSPORT_GOOGLE (obj); WockyJingleTransportGooglePrivate *priv = transport->priv; priv->local_candidates = g_list_concat (priv->local_candidates, new_candidates); /* If all previous candidates have been signalled, set the new * ones as pending. If there are existing pending candidates, * the new ones will just be appended to that list. */ if (priv->pending_candidates == NULL) priv->pending_candidates = new_candidates; } static void send_candidates (WockyJingleTransportIface *obj, gboolean all) { WockyJingleTransportGoogle *transport = WOCKY_JINGLE_TRANSPORT_GOOGLE (obj); WockyJingleTransportGooglePrivate *priv = transport->priv; if (all) { /* for gtalk3, we might have to retransmit everything */ group_and_transmit_candidates (transport, priv->local_candidates); priv->pending_candidates = NULL; } else { /* If the content became ready after we wanted to transmit * these originally, we are called to transmit when it them */ if (priv->pending_candidates != NULL) { group_and_transmit_candidates (transport, priv->pending_candidates); priv->pending_candidates = NULL; } } } static GList * get_local_candidates (WockyJingleTransportIface *iface) { WockyJingleTransportGoogle *transport = WOCKY_JINGLE_TRANSPORT_GOOGLE (iface); WockyJingleTransportGooglePrivate *priv = transport->priv; return priv->local_candidates; } static GList * get_remote_candidates (WockyJingleTransportIface *iface) { WockyJingleTransportGoogle *transport = WOCKY_JINGLE_TRANSPORT_GOOGLE (iface); WockyJingleTransportGooglePrivate *priv = transport->priv; return priv->remote_candidates; } static WockyJingleTransportType get_transport_type (void) { return JINGLE_TRANSPORT_GOOGLE_P2P; } static void transport_iface_init (gpointer g_iface, gpointer iface_data) { WockyJingleTransportIfaceClass *klass = (WockyJingleTransportIfaceClass *) g_iface; klass->parse_candidates = parse_candidates; klass->new_local_candidates = new_local_candidates; /* Not implementing inject_candidates: gtalk-p2p candidates are always sent * in transport-info or equivalent. */ klass->send_candidates = send_candidates; klass->get_remote_candidates = get_remote_candidates; klass->get_local_candidates = get_local_candidates; klass->get_transport_type = get_transport_type; } /* Returns FALSE if the component name already exists */ gboolean jingle_transport_google_set_component_name ( WockyJingleTransportGoogle *transport, const gchar *name, guint component_id) { WockyJingleTransportGooglePrivate *priv = transport->priv; if (g_hash_table_lookup_extended (priv->component_names, name, NULL, NULL)) return FALSE; g_hash_table_insert (priv->component_names, g_strdup (name), GINT_TO_POINTER (component_id)); return TRUE; } void jingle_transport_google_register (WockyJingleFactory *factory) { /* GTalk libjingle0.3 dialect */ wocky_jingle_factory_register_transport (factory, "", WOCKY_TYPE_JINGLE_TRANSPORT_GOOGLE); /* GTalk libjingle0.4 dialect */ wocky_jingle_factory_register_transport (factory, WOCKY_XMPP_NS_GOOGLE_TRANSPORT_P2P, WOCKY_TYPE_JINGLE_TRANSPORT_GOOGLE); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-ll-contact.h0000664000175000017500000000507211720661341025404 0ustar00cassidycassidy00000000000000/* * wocky-ll-contact.h - Header for WockyLLContact * Copyright (C) 2011 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_LL_CONTACT_H__ #define __WOCKY_LL_CONTACT_H__ #include #include #include "wocky-types.h" #include "wocky-contact.h" G_BEGIN_DECLS typedef struct _WockyLLContactClass WockyLLContactClass; typedef struct _WockyLLContactPrivate WockyLLContactPrivate; typedef GList * (*WockyLLContactGetAddressesImpl) (WockyLLContact *); struct _WockyLLContactClass { WockyContactClass parent_class; WockyLLContactGetAddressesImpl get_addresses; }; struct _WockyLLContact { WockyContact parent; WockyLLContactPrivate *priv; }; GType wocky_ll_contact_get_type (void); #define WOCKY_TYPE_LL_CONTACT \ (wocky_ll_contact_get_type ()) #define WOCKY_LL_CONTACT(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_LL_CONTACT, \ WockyLLContact)) #define WOCKY_LL_CONTACT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_LL_CONTACT, \ WockyLLContactClass)) #define WOCKY_IS_LL_CONTACT(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_LL_CONTACT)) #define WOCKY_IS_LL_CONTACT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_LL_CONTACT)) #define WOCKY_LL_CONTACT_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_LL_CONTACT, \ WockyLLContactClass)) WockyLLContact * wocky_ll_contact_new (const gchar *jid); const gchar *wocky_ll_contact_get_jid (WockyLLContact *contact); gboolean wocky_ll_contact_equal (WockyLLContact *a, WockyLLContact *b); GList * wocky_ll_contact_get_addresses (WockyLLContact *self); gboolean wocky_ll_contact_has_address (WockyLLContact *self, GInetAddress *address); G_END_DECLS #endif /* #ifndef __WOCKY_LL_CONTACT_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jingle-transport-iface.c0000664000175000017500000002001612332440453027700 0ustar00cassidycassidy00000000000000/* * wocky-jingle-transport-iface.c - Source for WockyJingleTransportIface * Copyright (C) 2007-2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "wocky-jingle-transport-iface.h" #include #include "wocky-jingle-content.h" #include "wocky-jingle-session.h" WockyJingleTransportIface * wocky_jingle_transport_iface_new (GType type, WockyJingleContent *content, const gchar *transport_ns) { g_return_val_if_fail (g_type_is_a (type, WOCKY_TYPE_JINGLE_TRANSPORT_IFACE), NULL); return g_object_new (type, "content", content, "transport-ns", transport_ns, NULL); } void wocky_jingle_transport_iface_parse_candidates (WockyJingleTransportIface *self, WockyNode *node, GError **error) { void (*virtual_method)(WockyJingleTransportIface *, WockyNode *, GError **) = WOCKY_JINGLE_TRANSPORT_IFACE_GET_CLASS (self)->parse_candidates; g_assert (virtual_method != NULL); return virtual_method (self, node, error); } /* Takes in a list of slice-allocated WockyJingleCandidate structs */ void wocky_jingle_transport_iface_new_local_candidates (WockyJingleTransportIface *self, GList *candidates) { void (*virtual_method)(WockyJingleTransportIface *, GList *) = WOCKY_JINGLE_TRANSPORT_IFACE_GET_CLASS (self)->new_local_candidates; g_assert (virtual_method != NULL); virtual_method (self, candidates); } /* Inserts candidates into the given node, or equivalent, of a * session-initiate, session-accept, content-add or content-accept action. */ void wocky_jingle_transport_iface_inject_candidates ( WockyJingleTransportIface *self, WockyNode *transport_node) { void (*virtual_method)(WockyJingleTransportIface *, WockyNode *) = WOCKY_JINGLE_TRANSPORT_IFACE_GET_CLASS (self)->inject_candidates; if (virtual_method != NULL) virtual_method (self, transport_node); } /* Transmits outstanding or all candidates (if applicable and @all is set). */ void wocky_jingle_transport_iface_send_candidates ( WockyJingleTransportIface *self, gboolean all) { void (*virtual_method) (WockyJingleTransportIface *, gboolean) = WOCKY_JINGLE_TRANSPORT_IFACE_GET_CLASS (self)->send_candidates; if (virtual_method != NULL) virtual_method (self, all); } /* Returns TRUE if and only if @self has enough candidates to inject into a * {session,content}-accept, and is connected. */ gboolean wocky_jingle_transport_iface_can_accept (WockyJingleTransportIface *self) { WockyJingleTransportState state; gboolean (*m) (WockyJingleTransportIface *) = WOCKY_JINGLE_TRANSPORT_IFACE_GET_CLASS (self)->can_accept; g_object_get (self, "state", &state, NULL); if (state != WOCKY_JINGLE_TRANSPORT_STATE_CONNECTED) return FALSE; /* Only Raw UDP *needs* candidates in order to accept. */ if (m != NULL) return m (self); else return TRUE; } GList * wocky_jingle_transport_iface_get_remote_candidates ( WockyJingleTransportIface *self) { GList * (*virtual_method)(WockyJingleTransportIface *) = WOCKY_JINGLE_TRANSPORT_IFACE_GET_CLASS (self)->get_remote_candidates; g_assert (virtual_method != NULL); return virtual_method (self); } GList * wocky_jingle_transport_iface_get_local_candidates ( WockyJingleTransportIface *self) { GList * (*virtual_method)(WockyJingleTransportIface *) = WOCKY_JINGLE_TRANSPORT_IFACE_GET_CLASS (self)->get_local_candidates; g_assert (virtual_method != NULL); return virtual_method (self); } gboolean jingle_transport_get_credentials (WockyJingleTransportIface *self, gchar **ufrag, gchar **pwd) { WockyJingleTransportIfaceClass *klass = WOCKY_JINGLE_TRANSPORT_IFACE_GET_CLASS (self); if (klass->get_credentials) return klass->get_credentials (self, ufrag, pwd); else return FALSE; } WockyJingleTransportType wocky_jingle_transport_iface_get_transport_type (WockyJingleTransportIface *self) { WockyJingleTransportType (*virtual_method)(void) = WOCKY_JINGLE_TRANSPORT_IFACE_GET_CLASS (self)->get_transport_type; g_assert (virtual_method != NULL); return virtual_method (); } static void wocky_jingle_transport_iface_base_init (gpointer klass) { static gboolean initialized = FALSE; if (!initialized) { GParamSpec *param_spec; param_spec = g_param_spec_object ( "content", "WockyJingleContent object", "Jingle content that's using this jingle transport object.", WOCKY_TYPE_JINGLE_CONTENT, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_string ( "transport-ns", "Transport namespace", "Namespace identifying the transport type.", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); g_object_interface_install_property (klass, param_spec); param_spec = g_param_spec_uint ( "state", "Connection state for the transport.", "Enum specifying the connection state of the transport.", WOCKY_JINGLE_TRANSPORT_STATE_DISCONNECTED, WOCKY_JINGLE_TRANSPORT_STATE_CONNECTED, WOCKY_JINGLE_TRANSPORT_STATE_DISCONNECTED, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); g_object_interface_install_property (klass, param_spec); initialized = TRUE; } } GType wocky_jingle_transport_iface_get_type (void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof (WockyJingleTransportIfaceClass), wocky_jingle_transport_iface_base_init, /* base_init */ NULL, /* base_finalize */ NULL, /* class_init */ NULL, /* class_finalize */ NULL, /* class_data */ 0, 0, /* n_preallocs */ NULL /* instance_init */ }; type = g_type_register_static (G_TYPE_INTERFACE, "WockyJingleTransportIface", &info, 0); } return type; } WockyJingleCandidate * wocky_jingle_candidate_new (WockyJingleTransportProtocol protocol, WockyJingleCandidateType type, const gchar *id, int component, const gchar *address, int port, int generation, int preference, const gchar *username, const gchar *password, int network) { WockyJingleCandidate *c = g_slice_new0 (WockyJingleCandidate); c->protocol = protocol; c->type = type; c->id = g_strdup (id); c->address = g_strdup (address); c->component = component; c->port = port; c->generation = generation; c->preference = preference; c->username = g_strdup (username); c->password = g_strdup (password); c->network = network; return c; } void wocky_jingle_candidate_free (WockyJingleCandidate *c) { g_free (c->id); g_free (c->address); g_free (c->username); g_free (c->password); g_slice_free (WockyJingleCandidate, c); } void jingle_transport_free_candidates (GList *candidates) { while (candidates != NULL) { WockyJingleCandidate *c = (WockyJingleCandidate *) candidates->data; wocky_jingle_candidate_free (c); candidates = g_list_remove (candidates, c); } } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-auth-registry.h0000664000175000017500000002540112212322440026140 0ustar00cassidycassidy00000000000000#if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif /* wocky-auth-registry.h */ #ifndef _WOCKY_AUTH_REGISTRY_H #define _WOCKY_AUTH_REGISTRY_H #include #include #include "wocky-auth-handler.h" #include "wocky-enumtypes.h" G_BEGIN_DECLS GQuark wocky_auth_error_quark (void); #define WOCKY_AUTH_ERROR \ wocky_auth_error_quark () /** * WockyAuthError: * @WOCKY_AUTH_ERROR_INIT_FAILED: Failed to initialize our auth * support * @WOCKY_AUTH_ERROR_NOT_SUPPORTED: Server doesn't support this * authentication method * @WOCKY_AUTH_ERROR_NO_SUPPORTED_MECHANISMS: Server doesn't support * any mechanisms that we support * @WOCKY_AUTH_ERROR_NETWORK: Couldn't send our stanzas to the server * @WOCKY_AUTH_ERROR_INVALID_REPLY: Server sent an invalid reply * @WOCKY_AUTH_ERROR_NO_CREDENTIALS: Failure to provide user * credentials * @WOCKY_AUTH_ERROR_FAILURE: Server sent a failure * @WOCKY_AUTH_ERROR_CONNRESET: disconnected * @WOCKY_AUTH_ERROR_STREAM: XMPP stream error while authing * @WOCKY_AUTH_ERROR_RESOURCE_CONFLICT: Resource conflict (relevant in * in jabber auth) * @WOCKY_AUTH_ERROR_NOT_AUTHORIZED: Provided credentials are not * valid * * #WockyAuthRegistry specific errors. */ typedef enum { WOCKY_AUTH_ERROR_INIT_FAILED, WOCKY_AUTH_ERROR_NOT_SUPPORTED, WOCKY_AUTH_ERROR_NO_SUPPORTED_MECHANISMS, WOCKY_AUTH_ERROR_NETWORK, WOCKY_AUTH_ERROR_INVALID_REPLY, WOCKY_AUTH_ERROR_NO_CREDENTIALS, WOCKY_AUTH_ERROR_FAILURE, WOCKY_AUTH_ERROR_CONNRESET, WOCKY_AUTH_ERROR_STREAM, WOCKY_AUTH_ERROR_RESOURCE_CONFLICT, WOCKY_AUTH_ERROR_NOT_AUTHORIZED, } WockyAuthError; #define WOCKY_AUTH_MECH_JABBER_DIGEST "X-WOCKY-JABBER-DIGEST" #define WOCKY_AUTH_MECH_JABBER_PASSWORD "X-WOCKY-JABBER-PASSWORD" #define WOCKY_AUTH_MECH_SASL_DIGEST_MD5 "DIGEST-MD5" #define WOCKY_AUTH_MECH_SASL_PLAIN "PLAIN" #define WOCKY_AUTH_MECH_SASL_SCRAM_SHA_1 "SCRAM-SHA-1" /** * WockyAuthRegistryStartData: * @mechanism: the name of the mechanism * @initial_response: the data in the response * * A structure to hold the mechanism and response data. */ typedef struct { gchar *mechanism; GString *initial_response; } WockyAuthRegistryStartData; #define WOCKY_TYPE_AUTH_REGISTRY wocky_auth_registry_get_type() #define WOCKY_AUTH_REGISTRY(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ WOCKY_TYPE_AUTH_REGISTRY, WockyAuthRegistry)) #define WOCKY_AUTH_REGISTRY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), \ WOCKY_TYPE_AUTH_REGISTRY, WockyAuthRegistryClass)) #define WOCKY_IS_AUTH_REGISTRY(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ WOCKY_TYPE_AUTH_REGISTRY)) #define WOCKY_IS_AUTH_REGISTRY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), \ WOCKY_TYPE_AUTH_REGISTRY)) #define WOCKY_AUTH_REGISTRY_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ WOCKY_TYPE_AUTH_REGISTRY, WockyAuthRegistryClass)) typedef struct _WockyAuthRegistry WockyAuthRegistry; /** * WockyAuthRegistryClass: * @start_auth_async_func: a function to call to start an asynchronous * start auth operation; see wocky_auth_registry_start_auth_async() for * more details. * @start_auth_finish_func: a function to call to finish an * asynchronous start auth operation; see * wocky_auth_registry_start_auth_finish() for more details. * @challenge_async_func: a function to call to start an asynchronous * challenge operation; see wocky_auth_registry_challenge_async() for * more details. * @challenge_finish_func: a function to call to finish an asynchronous * challenge operation; see wocky_auth_registry_challenge_finish() for * more details. * @success_async_func: a function to call to start an asynchronous * success operation; see wocky_auth_registry_success_async() for * more details. * @success_finish_func: a function to call to finish an asynchronous * success operation; see wocky_auth_registry_success_finish() for * more details. * @failure_func: a function to call on failure; see * wocky_auth_registry_failure() for more details. * * The class of a #WockyAuthRegistry. */ typedef struct _WockyAuthRegistryClass WockyAuthRegistryClass; typedef struct _WockyAuthRegistryPrivate WockyAuthRegistryPrivate; /** * WockyAuthRegistryStartAuthAsyncFunc: * @self: a #WockyAuthRegistry object * @mechanisms: a list of avahilable mechanisms * @allow_plain: %TRUE if PLAIN is allowed, otherwise %FALSE * @is_secure_channel: %TRUE if channel is secure, otherwise %FALSE * @username: the username * @password: the password * @server: the server * @session_id: the session ID * @callback: a callback to be called when finished * @user_data: data to pass to @callback * * Starts a async authentication: chooses mechanism and gets initial data. * The default function chooses a #WockyAuthHandler by which mechanism it * supports and gets the initial data from the chosen handler. */ typedef void (*WockyAuthRegistryStartAuthAsyncFunc) (WockyAuthRegistry *self, GSList *mechanisms, gboolean allow_plain, gboolean is_secure_channel, const gchar *username, const gchar *password, const gchar *server, const gchar *session_id, GAsyncReadyCallback callback, gpointer user_data); /** * WockyAuthRegistryStartAuthFinishFunc: * @self: a #WockyAuthRegistry object * @result: a #GAsyncResult object * @start_data: a location to fill with a #WockyAuthRegistryStartData structure * @error: a location to fill with a #GError if an error is hit, or %NULL * * Called to finish the #GAsyncResult task for authentication * start. By default, it extracts a #WockyAuthRegistryStartData * pointer from a given #GSimpleAsyncResult and copies it to the out * param. * * Returns: %TRUE on success, otherwise %FALSE */ typedef gboolean (*WockyAuthRegistryStartAuthFinishFunc) ( WockyAuthRegistry *self, GAsyncResult *result, WockyAuthRegistryStartData **start_data, GError **error); /** * WockyAuthRegistryChallengeAsyncFunc: * @self: a #WockyAuthRegistry object * @challenge_data: the challenge data string * @callback: a callback to call when finished * @user_data: data to pass to @callback * * Recieves a challenge and asynchronously provides a reply. By * default the challenge is passed on to the chosen #WockyAuthHandler. */ typedef void (*WockyAuthRegistryChallengeAsyncFunc) (WockyAuthRegistry *self, const GString *challenge_data, GAsyncReadyCallback callback, gpointer user_data); /** * WockyAuthRegistryChallengeFinishFunc: * @self: a #WockyAuthRegistry object * @result: a #GAsyncResult object * @response: a location to be filled with the response string * @error: a location to fill with a #GError if an error is hit, or %NULL * * Finishes a #GAsyncResult from * #WockyAuthRegistryChallengeAsyncFunc. By default it extracts a * #GString response from the given #GSimpleAsyncResult and copies it * to the out param. * * Returns: %TRUE on success, otherwise %FALSE */ typedef gboolean (*WockyAuthRegistryChallengeFinishFunc) ( WockyAuthRegistry *self, GAsyncResult *result, GString **response, GError **error); /** * WockyAuthRegistrySuccessAsyncFunc: * @self: a #WockyAuthRegistry object * @callback: a callback to be called when finished * @user_data: data to pass to @callback * * Notifies the registry of authentication success, and allows a last ditch * attempt at aborting the authentication at the client's discretion. */ typedef void (*WockyAuthRegistrySuccessAsyncFunc) (WockyAuthRegistry *self, GAsyncReadyCallback callback, gpointer user_data); /** * WockyAuthRegistrySuccessFinishFunc: * @self: a #WockyAuthRegistry object * @result: a #GAsyncResult object * @error: a location to fill with a #GError if an error is hit, or %NULL * * Finishes a #GAsyncResult from * #WockyAuthRegistrySuccessAsyncFunc. It checks for any errors set on * the given #GSimpleAsyncResult, copies the #GError to an out param * and returns %FALSE if there was an error. * * Returns: %TRUE on success, otherwise %FALSE */ typedef gboolean (*WockyAuthRegistrySuccessFinishFunc) ( WockyAuthRegistry *self, GAsyncResult *result, GError **error); /** * WockyAuthRegistryFailureFunc: * @self: a #WockyAuthRegistry object * @error: a #GError describing the failure * * Notifies the client of a server-side error. By default this is not * implemented. * */ typedef void (*WockyAuthRegistryFailureFunc) (WockyAuthRegistry *self, GError *error); struct _WockyAuthRegistry { /**/ GObject parent; WockyAuthRegistryPrivate *priv; }; struct _WockyAuthRegistryClass { /**/ GObjectClass parent_class; /**/ WockyAuthRegistryStartAuthAsyncFunc start_auth_async_func; WockyAuthRegistryStartAuthFinishFunc start_auth_finish_func; WockyAuthRegistryChallengeAsyncFunc challenge_async_func; WockyAuthRegistryChallengeFinishFunc challenge_finish_func; WockyAuthRegistrySuccessAsyncFunc success_async_func; WockyAuthRegistrySuccessFinishFunc success_finish_func; WockyAuthRegistryFailureFunc failure_func; }; GType wocky_auth_registry_get_type (void) G_GNUC_CONST; WockyAuthRegistry *wocky_auth_registry_new (void); void wocky_auth_registry_start_auth_async (WockyAuthRegistry *self, GSList *mechanisms, gboolean allow_plain, gboolean is_secure_channel, const gchar *username, const gchar *password, const gchar *server, const gchar *session_id, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_auth_registry_start_auth_finish (WockyAuthRegistry *self, GAsyncResult *result, WockyAuthRegistryStartData **start_data, GError **error); void wocky_auth_registry_challenge_async (WockyAuthRegistry *self, const GString *challenge_data, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_auth_registry_challenge_finish (WockyAuthRegistry *self, GAsyncResult *res, GString **response, GError **error); void wocky_auth_registry_success_async (WockyAuthRegistry *self, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_auth_registry_success_finish (WockyAuthRegistry *self, GAsyncResult *res, GError **error); void wocky_auth_registry_add_handler (WockyAuthRegistry *self, WockyAuthHandler *handler); void wocky_auth_registry_start_data_free ( WockyAuthRegistryStartData *start_data); WockyAuthRegistryStartData * wocky_auth_registry_start_data_new ( const gchar *mechanism, const GString *initial_response); WockyAuthRegistryStartData * wocky_auth_registry_start_data_dup ( WockyAuthRegistryStartData *start_data); void wocky_auth_registry_failure (WockyAuthRegistry *self, GError *error); gboolean wocky_auth_registry_supports_one_of (WockyAuthRegistry *self, GSList *mechanisms, gboolean allow_plain); G_END_DECLS #endif /* _WOCKY_AUTH_REGISTRY_H */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jingle-session.c0000664000175000017500000023262212212322440026262 0ustar00cassidycassidy00000000000000/* * wocky-jingle-session.c - Source for WockyJingleSession * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "wocky-jingle-session.h" #include #include #include #include #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_JINGLE #include "wocky-debug-internal.h" #include "wocky-signals-marshal.h" #include "wocky-enumtypes.h" #include "wocky-jingle-content.h" #include "wocky-jingle-factory.h" /* FIXME: the RTP-specific bits of this file should be separated from the * generic Jingle code. */ #include "wocky-jingle-media-rtp.h" #include "wocky-namespaces.h" #include "wocky-node-private.h" #include "wocky-resource-contact.h" #include "wocky-utils.h" G_DEFINE_TYPE(WockyJingleSession, wocky_jingle_session, G_TYPE_OBJECT); /* signal enum */ enum { NEW_CONTENT, REMOTE_STATE_CHANGED, TERMINATED, CONTENT_REJECTED, QUERY_CAP, ABOUT_TO_INITIATE, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; /* properties */ enum { PROP_JINGLE_FACTORY = 1, PROP_PORTER, PROP_SESSION_ID, PROP_PEER_CONTACT, PROP_LOCAL_INITIATOR, PROP_STATE, PROP_DIALECT, PROP_LOCAL_HOLD, PROP_REMOTE_HOLD, PROP_REMOTE_RINGING, LAST_PROPERTY }; struct _WockyJingleSessionPrivate { /* Borrowed; the factory owns us. */ WockyJingleFactory *jingle_factory; WockyPorter *porter; WockyContact *peer_contact; /* Borrowed from peer_contact if it's a WockyResourceContact. */ const gchar *peer_resource; gchar *peer_jid; /* Either borrowed from 'porter' or equal to peer_jid. */ const gchar *initiator; gboolean local_initiator; /* WockyJingleContent objects keyed by content name. * Table owns references to these objects. */ GHashTable *initiator_contents; GHashTable *responder_contents; WockyJingleDialect dialect; WockyJingleState state; gchar *sid; gboolean locally_accepted; gboolean locally_terminated; gboolean local_hold; gboolean remote_hold; gboolean remote_ringing; gboolean dispose_has_run; }; typedef struct { WockyJingleState state; WockyJingleAction *actions; } WockyJingleStateActions; /* gcc should be able to figure this out from the table below, but.. */ #define MAX_ACTIONS_PER_STATE 12 /* NB: WOCKY_JINGLE_ACTION_UNKNOWN is used as a terminator here. */ static WockyJingleAction allowed_actions[WOCKY_N_JINGLE_STATES][MAX_ACTIONS_PER_STATE] = { /* WOCKY_JINGLE_STATE_PENDING_CREATED */ { WOCKY_JINGLE_ACTION_SESSION_INITIATE, WOCKY_JINGLE_ACTION_UNKNOWN }, /* WOCKY_JINGLE_STATE_PENDING_INITIATE_SENT */ { WOCKY_JINGLE_ACTION_SESSION_TERMINATE, WOCKY_JINGLE_ACTION_SESSION_ACCEPT, WOCKY_JINGLE_ACTION_TRANSPORT_ACCEPT, /* required for GTalk4 */ WOCKY_JINGLE_ACTION_DESCRIPTION_INFO, WOCKY_JINGLE_ACTION_SESSION_INFO, WOCKY_JINGLE_ACTION_TRANSPORT_INFO, WOCKY_JINGLE_ACTION_INFO, WOCKY_JINGLE_ACTION_UNKNOWN }, /* WOCKY_JINGLE_STATE_PENDING_INITIATED */ { WOCKY_JINGLE_ACTION_SESSION_ACCEPT, WOCKY_JINGLE_ACTION_SESSION_TERMINATE, WOCKY_JINGLE_ACTION_TRANSPORT_INFO, WOCKY_JINGLE_ACTION_CONTENT_REJECT, WOCKY_JINGLE_ACTION_CONTENT_MODIFY, WOCKY_JINGLE_ACTION_CONTENT_ACCEPT, WOCKY_JINGLE_ACTION_CONTENT_REMOVE, WOCKY_JINGLE_ACTION_DESCRIPTION_INFO, WOCKY_JINGLE_ACTION_TRANSPORT_ACCEPT, WOCKY_JINGLE_ACTION_SESSION_INFO, WOCKY_JINGLE_ACTION_INFO, WOCKY_JINGLE_ACTION_UNKNOWN }, /* WOCKY_JINGLE_STATE_PENDING_ACCEPT_SENT */ { WOCKY_JINGLE_ACTION_TRANSPORT_INFO, WOCKY_JINGLE_ACTION_DESCRIPTION_INFO, WOCKY_JINGLE_ACTION_SESSION_TERMINATE, WOCKY_JINGLE_ACTION_SESSION_INFO, WOCKY_JINGLE_ACTION_INFO, WOCKY_JINGLE_ACTION_UNKNOWN }, /* WOCKY_JINGLE_STATE_ACTIVE */ { WOCKY_JINGLE_ACTION_CONTENT_MODIFY, WOCKY_JINGLE_ACTION_CONTENT_ADD, WOCKY_JINGLE_ACTION_CONTENT_REMOVE, WOCKY_JINGLE_ACTION_CONTENT_REPLACE, WOCKY_JINGLE_ACTION_CONTENT_ACCEPT, WOCKY_JINGLE_ACTION_CONTENT_REJECT, WOCKY_JINGLE_ACTION_SESSION_INFO, WOCKY_JINGLE_ACTION_TRANSPORT_INFO, WOCKY_JINGLE_ACTION_DESCRIPTION_INFO, WOCKY_JINGLE_ACTION_INFO, WOCKY_JINGLE_ACTION_SESSION_TERMINATE, WOCKY_JINGLE_ACTION_UNKNOWN }, /* WOCKY_JINGLE_STATE_ENDED */ { WOCKY_JINGLE_ACTION_UNKNOWN } }; gboolean wocky_jingle_session_defines_action (WockyJingleSession *sess, WockyJingleAction a) { WockyJingleDialect d = sess->priv->dialect; if (a == WOCKY_JINGLE_ACTION_UNKNOWN) return FALSE; switch (d) { case WOCKY_JINGLE_DIALECT_V032: return TRUE; case WOCKY_JINGLE_DIALECT_V015: return (a != WOCKY_JINGLE_ACTION_DESCRIPTION_INFO && a != WOCKY_JINGLE_ACTION_SESSION_INFO); case WOCKY_JINGLE_DIALECT_GTALK4: if (a == WOCKY_JINGLE_ACTION_TRANSPORT_ACCEPT || a == WOCKY_JINGLE_ACTION_INFO ) return TRUE; case WOCKY_JINGLE_DIALECT_GTALK3: return (a == WOCKY_JINGLE_ACTION_SESSION_ACCEPT || a == WOCKY_JINGLE_ACTION_SESSION_INITIATE || a == WOCKY_JINGLE_ACTION_SESSION_TERMINATE || a == WOCKY_JINGLE_ACTION_TRANSPORT_INFO || a == WOCKY_JINGLE_ACTION_INFO); default: return FALSE; } } static void wocky_jingle_session_send_held (WockyJingleSession *sess); static void content_ready_cb (WockyJingleContent *c, gpointer user_data); static void content_removed_cb (WockyJingleContent *c, gpointer user_data); static void wocky_jingle_session_init (WockyJingleSession *obj) { WockyJingleSessionPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, WOCKY_TYPE_JINGLE_SESSION, WockyJingleSessionPrivate); obj->priv = priv; DEBUG ("Initializing the jingle session %p", obj); priv->initiator_contents = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); priv->responder_contents = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); priv->state = WOCKY_JINGLE_STATE_PENDING_CREATED; priv->locally_accepted = FALSE; priv->locally_terminated = FALSE; priv->dispose_has_run = FALSE; } static void dispose_content_hash ( WockyJingleSession *sess, GHashTable **contents) { GHashTableIter iter; gpointer content; g_hash_table_iter_init (&iter, *contents); while (g_hash_table_iter_next (&iter, NULL, &content)) { g_signal_handlers_disconnect_by_func (content, content_ready_cb, sess); g_signal_handlers_disconnect_by_func (content, content_removed_cb, sess); g_hash_table_iter_remove (&iter); } g_hash_table_unref (*contents); *contents = NULL; } static void wocky_jingle_session_dispose (GObject *object) { WockyJingleSession *sess = WOCKY_JINGLE_SESSION (object); WockyJingleSessionPrivate *priv = sess->priv; if (priv->dispose_has_run) return; DEBUG ("called"); priv->dispose_has_run = TRUE; g_assert ((priv->state == WOCKY_JINGLE_STATE_PENDING_CREATED) || (priv->state == WOCKY_JINGLE_STATE_ENDED)); dispose_content_hash (sess, &priv->initiator_contents); dispose_content_hash (sess, &priv->responder_contents); g_clear_object (&priv->peer_contact); g_clear_object (&priv->porter); g_free (priv->sid); priv->sid = NULL; g_free (priv->peer_jid); priv->peer_jid = NULL; if (G_OBJECT_CLASS (wocky_jingle_session_parent_class)->dispose) G_OBJECT_CLASS (wocky_jingle_session_parent_class)->dispose (object); } static void wocky_jingle_session_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyJingleSession *sess = WOCKY_JINGLE_SESSION (object); WockyJingleSessionPrivate *priv = sess->priv; switch (property_id) { case PROP_JINGLE_FACTORY: g_value_set_object (value, priv->jingle_factory); break; case PROP_PORTER: g_value_set_object (value, priv->porter); break; case PROP_SESSION_ID: g_value_set_string (value, priv->sid); break; case PROP_LOCAL_INITIATOR: g_value_set_boolean (value, priv->local_initiator); break; case PROP_PEER_CONTACT: g_value_set_object (value, priv->peer_contact); break; case PROP_STATE: g_value_set_uint (value, priv->state); break; case PROP_DIALECT: g_value_set_uint (value, priv->dialect); break; case PROP_LOCAL_HOLD: g_value_set_boolean (value, priv->local_hold); break; case PROP_REMOTE_HOLD: g_value_set_boolean (value, priv->remote_hold); break; case PROP_REMOTE_RINGING: g_value_set_boolean (value, priv->remote_ringing); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_jingle_session_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyJingleSession *sess = WOCKY_JINGLE_SESSION (object); WockyJingleSessionPrivate *priv = sess->priv; switch (property_id) { case PROP_JINGLE_FACTORY: priv->jingle_factory = g_value_get_object (value); g_assert (priv->jingle_factory != NULL); break; case PROP_PORTER: priv->porter = g_value_dup_object (value); g_assert (priv->porter != NULL); break; case PROP_SESSION_ID: g_free (priv->sid); priv->sid = g_value_dup_string (value); break; case PROP_LOCAL_INITIATOR: priv->local_initiator = g_value_get_boolean (value); break; case PROP_DIALECT: priv->dialect = g_value_get_uint (value); break; case PROP_PEER_CONTACT: priv->peer_contact = g_value_dup_object (value); break; case PROP_LOCAL_HOLD: { gboolean local_hold = g_value_get_boolean (value); if (priv->local_hold != local_hold) { priv->local_hold = local_hold; if (priv->state >= WOCKY_JINGLE_STATE_PENDING_INITIATED && priv->state < WOCKY_JINGLE_STATE_ENDED) wocky_jingle_session_send_held (sess); /* else, we'll send this in set_state when we move to PENDING_INITIATED or * better. */ } break; } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); g_assert_not_reached (); break; } } static void wocky_jingle_session_constructed (GObject *object) { void (*chain_up) (GObject *) = G_OBJECT_CLASS (wocky_jingle_session_parent_class)->constructed; WockyJingleSession *self = WOCKY_JINGLE_SESSION (object); WockyJingleSessionPrivate *priv = self->priv; if (chain_up != NULL) chain_up (object); g_assert (priv->jingle_factory != NULL); g_assert (priv->porter != NULL); g_assert (priv->peer_contact != NULL); g_assert (priv->sid != NULL); priv->peer_jid = wocky_contact_dup_jid (priv->peer_contact); if (priv->local_initiator) priv->initiator = wocky_porter_get_full_jid (priv->porter); else priv->initiator = priv->peer_jid; if (WOCKY_IS_RESOURCE_CONTACT (priv->peer_contact)) priv->peer_resource = wocky_resource_contact_get_resource ( WOCKY_RESOURCE_CONTACT (priv->peer_contact)); } WockyJingleSession * wocky_jingle_session_new ( WockyJingleFactory *factory, WockyPorter *porter, const gchar *session_id, gboolean local_initiator, WockyContact *peer, WockyJingleDialect dialect, gboolean local_hold) { return g_object_new (WOCKY_TYPE_JINGLE_SESSION, "session-id", session_id, "jingle-factory", factory, "porter", porter, "local-initiator", local_initiator, "peer-contact", peer, "dialect", dialect, "local-hold", local_hold, NULL); } static void wocky_jingle_session_class_init (WockyJingleSessionClass *cls) { GObjectClass *object_class = G_OBJECT_CLASS (cls); GParamSpec *param_spec; g_type_class_add_private (cls, sizeof (WockyJingleSessionPrivate)); object_class->constructed = wocky_jingle_session_constructed; object_class->get_property = wocky_jingle_session_get_property; object_class->set_property = wocky_jingle_session_set_property; object_class->dispose = wocky_jingle_session_dispose; /* property definitions */ param_spec = g_param_spec_object ("jingle-factory", "WockyJingleFactory object", "The Jingle factory which created this session", WOCKY_TYPE_JINGLE_FACTORY, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_JINGLE_FACTORY, param_spec); param_spec = g_param_spec_object ("porter", "WockyPorter", "The WockyPorter for the current connection", WOCKY_TYPE_PORTER, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_PORTER, param_spec); param_spec = g_param_spec_string ("session-id", "Session ID", "A unique session identifier used throughout all communication.", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SESSION_ID, param_spec); param_spec = g_param_spec_boolean ("local-initiator", "Session initiator", "Specifies if local end initiated the session.", TRUE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_LOCAL_INITIATOR, param_spec); /** * WockyJingleSession:peer-contact: * * The #WockyContact representing the other party in the session. Note that * if this is a #WockyBareContact (as opposed to a #WockyResourceContact) the * session is with the contact's bare JID. */ param_spec = g_param_spec_object ("peer-contact", "Session peer", "The WockyContact representing the other party in the session.", WOCKY_TYPE_CONTACT, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_PEER_CONTACT, param_spec); param_spec = g_param_spec_uint ("state", "Session state", "The current state that the session is in.", 0, G_MAXUINT32, WOCKY_JINGLE_STATE_PENDING_CREATED, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_STATE, param_spec); param_spec = g_param_spec_uint ("dialect", "Jingle dialect", "Jingle dialect used for this session.", 0, G_MAXUINT32, WOCKY_JINGLE_DIALECT_ERROR, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_DIALECT, param_spec); param_spec = g_param_spec_boolean ("local-hold", "Local hold", "TRUE if we've placed the peer on hold", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_LOCAL_HOLD, param_spec); param_spec = g_param_spec_boolean ("remote-hold", "Remote hold", "TRUE if the peer has placed us on hold", FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_REMOTE_HOLD, param_spec); param_spec = g_param_spec_boolean ("remote-ringing", "Remote ringing", "TRUE if the peer's client is ringing", FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_REMOTE_RINGING, param_spec); /* signal definitions */ signals[NEW_CONTENT] = g_signal_new ("new-content", G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); /** * WockyJingleSession::terminated: * @session: the session * @locally_terminated: %TRUE if the session ended due to a call to * wocky_jingle_session_terminate(); %FALSE if the peer ended the session. * @reason: a #WockyJingleReason describing why the session terminated * @text: a possibly-%NULL human-readable string describing why the session * terminated * * Emitted when the session ends, just after #WockyJingleSession:state moves * to #WOCKY_JINGLE_STATE_ENDED. */ signals[TERMINATED] = g_signal_new ("terminated", G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__BOOLEAN_UINT_STRING, G_TYPE_NONE, 3, G_TYPE_BOOLEAN, G_TYPE_UINT, G_TYPE_STRING); signals[REMOTE_STATE_CHANGED] = g_signal_new ("remote-state-changed", G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[CONTENT_REJECTED] = g_signal_new ("content-rejected", G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT_UINT_STRING, G_TYPE_NONE, 3, G_TYPE_OBJECT, G_TYPE_UINT, G_TYPE_STRING); /* * @contact: this call's peer (the artist commonly known as * wocky_jingle_session_get_peer_contact()) * @cap: the XEP-0115 feature string the session is interested in. * * Emitted when the session wants to check whether the peer has a particular * capability. The handler should return %TRUE if @contact has @cap. */ signals[QUERY_CAP] = g_signal_new ("query-cap", G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST, 0, g_signal_accumulator_first_wins, NULL, _wocky_signals_marshal_BOOLEAN__OBJECT_STRING, G_TYPE_BOOLEAN, 2, WOCKY_TYPE_CONTACT, G_TYPE_STRING); signals[ABOUT_TO_INITIATE] = g_signal_new ("about-to-initiate", G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } typedef void (*HandlerFunc)(WockyJingleSession *sess, WockyNode *node, GError **error); typedef void (*ContentHandlerFunc)(WockyJingleSession *sess, WockyJingleContent *c, WockyNode *content_node, gpointer user_data, GError **error); static gboolean extract_reason (WockyNode *node, WockyJingleReason *reason, gchar **message) { WockyJingleReason _reason = WOCKY_JINGLE_REASON_UNKNOWN; WockyNode *child; WockyNodeIter iter; g_return_val_if_fail (node != NULL, FALSE); if (message != NULL) *message = g_strdup (wocky_node_get_content_from_child (node, "text")); wocky_node_iter_init (&iter, node, NULL, NULL); while (wocky_node_iter_next (&iter, &child)) { if (wocky_enum_from_nick ( wocky_jingle_reason_get_type (), child->name, (gint *) &_reason)) { if (reason != NULL) *reason = _reason; return TRUE; } } return FALSE; } static WockyJingleAction parse_action (const gchar *txt) { if (txt == NULL) return WOCKY_JINGLE_ACTION_UNKNOWN; /* synonyms, best deal with them right now */ if (!wocky_strdiff (txt, "initiate") || !wocky_strdiff (txt, "session-initiate")) return WOCKY_JINGLE_ACTION_SESSION_INITIATE; else if (!wocky_strdiff (txt, "terminate") || !wocky_strdiff (txt, "session-terminate") || !wocky_strdiff (txt, "reject")) return WOCKY_JINGLE_ACTION_SESSION_TERMINATE; else if (!wocky_strdiff (txt, "accept") || !wocky_strdiff (txt, "session-accept")) return WOCKY_JINGLE_ACTION_SESSION_ACCEPT; else if (!wocky_strdiff (txt, "candidates") || !wocky_strdiff (txt, "transport-info")) return WOCKY_JINGLE_ACTION_TRANSPORT_INFO; else if (!wocky_strdiff (txt, "content-accept")) return WOCKY_JINGLE_ACTION_CONTENT_ACCEPT; else if (!wocky_strdiff (txt, "content-add")) return WOCKY_JINGLE_ACTION_CONTENT_ADD; else if (!wocky_strdiff (txt, "content-modify")) return WOCKY_JINGLE_ACTION_CONTENT_MODIFY; else if (!wocky_strdiff (txt, "content-replace")) return WOCKY_JINGLE_ACTION_CONTENT_REPLACE; else if (!wocky_strdiff (txt, "content-reject")) return WOCKY_JINGLE_ACTION_CONTENT_REJECT; else if (!wocky_strdiff (txt, "content-remove")) return WOCKY_JINGLE_ACTION_CONTENT_REMOVE; else if (!wocky_strdiff (txt, "session-info")) return WOCKY_JINGLE_ACTION_SESSION_INFO; else if (!wocky_strdiff (txt, "transport-accept")) return WOCKY_JINGLE_ACTION_TRANSPORT_ACCEPT; else if (!wocky_strdiff (txt, "description-info")) return WOCKY_JINGLE_ACTION_DESCRIPTION_INFO; else if (!wocky_strdiff (txt, "info")) return WOCKY_JINGLE_ACTION_INFO; return WOCKY_JINGLE_ACTION_UNKNOWN; } static const gchar * produce_action (WockyJingleAction action, WockyJingleDialect dialect) { gboolean gmode = (dialect == WOCKY_JINGLE_DIALECT_GTALK3) || (dialect == WOCKY_JINGLE_DIALECT_GTALK4); g_return_val_if_fail (action != WOCKY_JINGLE_ACTION_UNKNOWN, NULL); switch (action) { case WOCKY_JINGLE_ACTION_SESSION_INITIATE: return (gmode) ? "initiate" : "session-initiate"; case WOCKY_JINGLE_ACTION_SESSION_TERMINATE: return (gmode) ? "terminate" : "session-terminate"; case WOCKY_JINGLE_ACTION_SESSION_ACCEPT: return (gmode) ? "accept" : "session-accept"; case WOCKY_JINGLE_ACTION_TRANSPORT_INFO: return (dialect == WOCKY_JINGLE_DIALECT_GTALK3) ? "candidates" : "transport-info"; case WOCKY_JINGLE_ACTION_CONTENT_ACCEPT: return "content-accept"; case WOCKY_JINGLE_ACTION_CONTENT_ADD: return "content-add"; case WOCKY_JINGLE_ACTION_CONTENT_MODIFY: return "content-modify"; case WOCKY_JINGLE_ACTION_CONTENT_REMOVE: return "content-remove"; case WOCKY_JINGLE_ACTION_CONTENT_REPLACE: return "content-replace"; case WOCKY_JINGLE_ACTION_CONTENT_REJECT: return "content-reject"; case WOCKY_JINGLE_ACTION_SESSION_INFO: return "session-info"; case WOCKY_JINGLE_ACTION_TRANSPORT_ACCEPT: return "transport-accept"; case WOCKY_JINGLE_ACTION_DESCRIPTION_INFO: return "description-info"; case WOCKY_JINGLE_ACTION_INFO: return "info"; default: /* only reached if g_return_val_if_fail is disabled */ DEBUG ("unknown action %u", action); return NULL; } } static gboolean action_is_allowed (WockyJingleAction action, WockyJingleState state) { guint i; for (i = 0; allowed_actions[state][i] != WOCKY_JINGLE_ACTION_UNKNOWN; i++) { if (allowed_actions[state][i] == action) return TRUE; } return FALSE; } static void wocky_jingle_session_send_rtp_info (WockyJingleSession *sess, const gchar *name); static void set_state (WockyJingleSession *sess, WockyJingleState state, WockyJingleReason termination_reason, const gchar *text); static WockyJingleContent *_get_any_content (WockyJingleSession *session); gboolean wocky_jingle_session_peer_has_cap ( WockyJingleSession *self, const gchar *cap_or_quirk) { gboolean ret; g_return_val_if_fail (WOCKY_IS_JINGLE_SESSION (self), FALSE); g_return_val_if_fail (cap_or_quirk != NULL, FALSE); g_signal_emit (self, signals[QUERY_CAP], 0, self->priv->peer_contact, cap_or_quirk, &ret); return ret; } static gboolean lookup_content (WockyJingleSession *sess, const gchar *name, const gchar *creator, gboolean fail_if_missing, WockyJingleContent **c, GError **error) { WockyJingleSessionPrivate *priv = sess->priv; if (name == NULL) { g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, "'name' attribute unset"); return FALSE; } if (WOCKY_JINGLE_DIALECT_IS_GOOGLE (priv->dialect)) { /* Only the initiator can create contents on GTalk. */ *c = g_hash_table_lookup (priv->initiator_contents, name); } else { /* Versions of Gabble between 0.7.16 and 0.7.28 (inclusive) omitted the * 'creator' attribute from transport-info (and possibly other) stanzas. * We try to detect contacts using such a version of Gabble from their * caps; if 'creator' is missing and the peer has that caps flag, we look * up the content in both hashes. * * While this doesn't deal with the case where the content is found in * both hashes, this isn't a problem in practice: the versions of Gabble * we're working around didn't allow this to happen (they'd either reject * the second stream, or let it replace the first, depending on the phase * of the moon, and get kind of confused in the process), and we try to * pick globally-unique content names. */ if (creator == NULL && wocky_jingle_session_peer_has_cap (sess, WOCKY_QUIRK_OMITS_CONTENT_CREATORS)) { DEBUG ("working around missing 'creator' attribute"); *c = g_hash_table_lookup (priv->initiator_contents, name); if (*c == NULL) *c = g_hash_table_lookup (priv->responder_contents, name); } else if (!wocky_strdiff (creator, "initiator")) { *c = g_hash_table_lookup (priv->initiator_contents, name); } else if (!wocky_strdiff (creator, "responder")) { *c = g_hash_table_lookup (priv->responder_contents, name); } else { g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, "'creator' attribute %s", (creator == NULL ? "missing" : "invalid")); return FALSE; } } if (fail_if_missing && *c == NULL) { g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, "Content '%s' (created by %s) does not exist", name, creator); return FALSE; } return TRUE; } static void _foreach_content (WockyJingleSession *sess, WockyNode *node, gboolean fail_if_missing, ContentHandlerFunc func, gpointer user_data, GError **error) { WockyJingleContent *c; WockyNode *content_node; WockyNodeIter iter; wocky_node_iter_init (&iter, node, "content", NULL); while (wocky_node_iter_next (&iter, &content_node)) { if (!lookup_content (sess, wocky_node_get_attribute (content_node, "name"), wocky_node_get_attribute (content_node, "creator"), fail_if_missing, &c, error)) return; func (sess, c, content_node, user_data, error); if (*error != NULL) return; } } struct idle_content_reject_ctx { WockyJingleSession *session; WockyStanza *msg; }; static gboolean idle_content_reject (gpointer data) { struct idle_content_reject_ctx *ctx = data; wocky_jingle_session_send (ctx->session, ctx->msg); g_object_unref (ctx->session); g_free (ctx); return FALSE; } static void fire_idle_content_reject (WockyJingleSession *sess, const gchar *name, const gchar *creator) { struct idle_content_reject_ctx *ctx = g_new0 (struct idle_content_reject_ctx, 1); WockyNode *sess_node, *node; if (creator == NULL) creator = ""; ctx->session = g_object_ref (sess); ctx->msg = wocky_jingle_session_new_message (ctx->session, WOCKY_JINGLE_ACTION_CONTENT_REJECT, &sess_node); g_debug ("name = %s, initiator = %s", name, creator); node = wocky_node_add_child (sess_node, "content"); wocky_node_set_attributes (node, "name", name, "creator", creator, NULL); /* FIXME: add API for ordering IQs rather than using g_idle_add. */ g_idle_add (idle_content_reject, ctx); } static WockyJingleContent * create_content (WockyJingleSession *sess, GType content_type, WockyJingleMediaType type, WockyJingleContentSenders senders, const gchar *content_ns, const gchar *transport_ns, const gchar *name, WockyNode *content_node, GError **error) { WockyJingleSessionPrivate *priv = sess->priv; WockyJingleContent *c; GHashTable *contents; DEBUG ("session creating new content name %s, type %d", name, type); /* FIXME: media-type is introduced by WockyJingleMediaRTP, not by the * superclass, so this call is unsafe in the general case */ c = g_object_new (content_type, "session", sess, "content-ns", content_ns, "transport-ns", transport_ns, "media-type", type, "name", name, "disposition", "session", "senders", senders, NULL); g_signal_connect (c, "ready", (GCallback) content_ready_cb, sess); g_signal_connect (c, "removed", (GCallback) content_removed_cb, sess); /* if we are called by parser, parse content add */ if (content_node != NULL) { wocky_jingle_content_parse_add (c, content_node, WOCKY_JINGLE_DIALECT_IS_GOOGLE (priv->dialect), error); if (*error != NULL) { g_object_unref (c); return NULL; } /* gtalk streams don't have name, so use whatever Content came up with */ if (name == NULL) name = wocky_jingle_content_get_name (c); } if (priv->local_initiator == wocky_jingle_content_is_created_by_us (c)) { DEBUG ("inserting content %s into initiator_contents", name); contents = priv->initiator_contents; } else { DEBUG ("inserting content %s into responder_contents", name); contents = priv->responder_contents; } /* If the content already existed, either we shouldn't have picked the name * we did (if we're creating it) or _each_content_add should have already * said no. */ g_assert (g_hash_table_lookup (contents, name) == NULL); g_hash_table_insert (contents, g_strdup (name), c); g_signal_emit (sess, signals[NEW_CONTENT], 0, c); return c; } static void _each_content_add (WockyJingleSession *sess, WockyJingleContent *c, WockyNode *content_node, gpointer user_data, GError **error) { WockyJingleSessionPrivate *priv = sess->priv; const gchar *name = wocky_node_get_attribute (content_node, "name"); WockyNode *desc_node = wocky_node_get_child (content_node, "description"); GType content_type = 0; const gchar *content_ns = NULL; if (desc_node != NULL) { content_ns = wocky_node_get_ns (desc_node); DEBUG ("namespace: %s", content_ns); content_type = wocky_jingle_factory_lookup_content_type ( wocky_jingle_session_get_factory (sess), content_ns); } if (content_type == 0) { /* if this is session-initiate, we should return error, otherwise, * we should respond with content-reject */ if (priv->state < WOCKY_JINGLE_STATE_PENDING_INITIATED) g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, "unsupported content type with ns %s", content_ns); else fire_idle_content_reject (sess, name, wocky_node_get_attribute (content_node, "creator")); return; } if (c != NULL) { g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, "content '%s' already exists", name); return; } create_content (sess, content_type, WOCKY_JINGLE_MEDIA_TYPE_NONE, WOCKY_JINGLE_CONTENT_SENDERS_BOTH, content_ns, NULL, NULL, content_node, error); } static void _each_content_remove (WockyJingleSession *sess, WockyJingleContent *c, WockyNode *content_node, gpointer user_data, GError **error) { g_assert (c != NULL); wocky_jingle_content_remove (c, FALSE); } static void _each_content_rejected (WockyJingleSession *sess, WockyJingleContent *c, WockyNode *content_node, gpointer user_data, GError **error) { WockyJingleReason reason = GPOINTER_TO_UINT (user_data); g_assert (c != NULL); g_signal_emit (sess, signals[CONTENT_REJECTED], 0, c, reason, ""); wocky_jingle_content_remove (c, FALSE); } static void _each_content_modify (WockyJingleSession *sess, WockyJingleContent *c, WockyNode *content_node, gpointer user_data, GError **error) { g_assert (c != NULL); wocky_jingle_content_update_senders (c, content_node, error); if (*error != NULL) return; } static void _each_content_replace (WockyJingleSession *sess, WockyJingleContent *c, WockyNode *content_node, gpointer user_data, GError **error) { _each_content_remove (sess, c, content_node, NULL, error); if (*error != NULL) return; _each_content_add (sess, c, content_node, NULL, error); } static void _each_content_accept (WockyJingleSession *sess, WockyJingleContent *c, WockyNode *content_node, gpointer user_data, GError **error) { WockyJingleSessionPrivate *priv = sess->priv; WockyJingleContentState state; g_assert (c != NULL); g_object_get (c, "state", &state, NULL); if (state != WOCKY_JINGLE_CONTENT_STATE_SENT) { #ifdef ENABLE_DEBUG const gchar *name = wocky_node_get_attribute (content_node, "name"); DEBUG ("ignoring content \"%s\"s acceptance for content not in SENT state", name); #endif return; } wocky_jingle_content_parse_accept (c, content_node, WOCKY_JINGLE_DIALECT_IS_GOOGLE (priv->dialect), error); } static void _each_description_info (WockyJingleSession *sess, WockyJingleContent *c, WockyNode *content_node, gpointer user_data, GError **error) { wocky_jingle_content_parse_description_info (c, content_node, error); } static void on_session_initiate (WockyJingleSession *sess, WockyNode *node, GError **error) { WockyJingleSessionPrivate *priv = sess->priv; /* we can't call ourselves at the moment */ if (priv->local_initiator) { /* We ignore initiate from us, and terminate the session immediately * afterwards */ wocky_jingle_session_terminate (sess, WOCKY_JINGLE_REASON_BUSY, NULL, NULL); return; } if ((priv->dialect == WOCKY_JINGLE_DIALECT_GTALK3)) { const gchar *content_ns = NULL; WockyNode *desc_node = wocky_node_get_child (node, "description"); content_ns = wocky_node_get_ns (desc_node); if (!wocky_strdiff (content_ns, WOCKY_XMPP_NS_GOOGLE_SESSION_VIDEO)) { WockyJingleFactory *factory = wocky_jingle_session_get_factory (sess); GType content_type = 0; DEBUG ("GTalk v3 session with audio and video"); /* audio and video content */ content_type = wocky_jingle_factory_lookup_content_type ( factory, content_ns); create_content (sess, content_type, WOCKY_JINGLE_MEDIA_TYPE_VIDEO, WOCKY_JINGLE_CONTENT_SENDERS_BOTH, WOCKY_XMPP_NS_GOOGLE_SESSION_VIDEO, NULL, "video", node, error); content_type = wocky_jingle_factory_lookup_content_type ( factory, WOCKY_XMPP_NS_GOOGLE_SESSION_PHONE); create_content (sess, content_type, WOCKY_JINGLE_MEDIA_TYPE_AUDIO, WOCKY_JINGLE_CONTENT_SENDERS_BOTH, WOCKY_XMPP_NS_GOOGLE_SESSION_PHONE, NULL, "audio", node, error); } else { _each_content_add (sess, NULL, node, NULL, error); } } else if (priv->dialect == WOCKY_JINGLE_DIALECT_GTALK4) { /* in this case we implicitly have just one content */ _each_content_add (sess, NULL, node, NULL, error); } else { _foreach_content (sess, node, FALSE, _each_content_add, NULL, error); } if (*error == NULL) { /* FIXME: contents defined here should always have "session" content * disposition; resolve this as soon as the proper procedure is defined * in XEP-0166. */ set_state (sess, WOCKY_JINGLE_STATE_PENDING_INITIATED, WOCKY_JINGLE_REASON_UNKNOWN, NULL); wocky_jingle_session_send_rtp_info (sess, "ringing"); } } static void on_content_add (WockyJingleSession *sess, WockyNode *node, GError **error) { _foreach_content (sess, node, FALSE, _each_content_add, NULL, error); } static void on_content_modify (WockyJingleSession *sess, WockyNode *node, GError **error) { _foreach_content (sess, node, TRUE, _each_content_modify, NULL, error); } static void on_content_remove (WockyJingleSession *sess, WockyNode *node, GError **error) { _foreach_content (sess, node, TRUE, _each_content_remove, NULL, error); } static void on_content_replace (WockyJingleSession *sess, WockyNode *node, GError **error) { _foreach_content (sess, node, TRUE, _each_content_replace, NULL, error); } static void on_content_reject (WockyJingleSession *sess, WockyNode *node, GError **error) { WockyNode *n = wocky_node_get_child (node, "reason"); WockyJingleReason reason = WOCKY_JINGLE_REASON_UNKNOWN; DEBUG (" "); if (n != NULL) extract_reason (n, &reason, NULL); if (reason == WOCKY_JINGLE_REASON_UNKNOWN) reason = WOCKY_JINGLE_REASON_GENERAL_ERROR; _foreach_content (sess, node, TRUE, _each_content_rejected, GUINT_TO_POINTER (reason), error); } static void on_content_accept (WockyJingleSession *sess, WockyNode *node, GError **error) { _foreach_content (sess, node, TRUE, _each_content_accept, NULL, error); } static void on_session_accept (WockyJingleSession *sess, WockyNode *node, GError **error) { WockyJingleSessionPrivate *priv = sess->priv; DEBUG ("called"); if ((priv->dialect == WOCKY_JINGLE_DIALECT_GTALK3) || (priv->dialect == WOCKY_JINGLE_DIALECT_GTALK4)) { /* Google Talk calls don't have contents per se; they just have * s in different namespaces for audio and video, in the * same stanza. So we need to feed the whole stanza to each * content in turn. */ GList *cs = wocky_jingle_session_get_contents (sess); GList *l; for (l = cs; l != NULL; l = l->next) _each_content_accept (sess, l->data, node, NULL, error); g_list_free (cs); } else { _foreach_content (sess, node, TRUE, _each_content_accept, NULL, error); } if (*error != NULL) return; set_state (sess, WOCKY_JINGLE_STATE_ACTIVE, WOCKY_JINGLE_REASON_UNKNOWN, NULL); /* Make sure each content knows the session is active */ g_list_foreach (wocky_jingle_session_get_contents (sess), (GFunc) g_object_notify, "state"); if (priv->dialect != WOCKY_JINGLE_DIALECT_V032) { /* If this is a dialect that doesn't support , we treat * session-accept as the cue to remove the ringing flag. */ priv->remote_ringing = FALSE; g_signal_emit (sess, signals[REMOTE_STATE_CHANGED], 0); } } static void mute_all_foreach (gpointer key, gpointer value, gpointer mute) { if (G_OBJECT_TYPE (value) == WOCKY_TYPE_JINGLE_MEDIA_RTP) g_object_set (value, "remote-mute", GPOINTER_TO_INT (mute), NULL); } static void mute_all (WockyJingleSession *sess, gboolean mute) { g_hash_table_foreach (sess->priv->initiator_contents, mute_all_foreach, GINT_TO_POINTER (mute)); g_hash_table_foreach (sess->priv->responder_contents, mute_all_foreach, GINT_TO_POINTER (mute)); } static gboolean set_mute (WockyJingleSession *sess, const gchar *name, const gchar *creator, gboolean mute, GError **error) { WockyJingleContent *c; if (name == NULL) { mute_all (sess, mute); return TRUE; } if (!lookup_content (sess, name, creator, TRUE /* fail if missing */, &c, error)) return FALSE; if (G_OBJECT_TYPE (c) != WOCKY_TYPE_JINGLE_MEDIA_RTP) { g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, "content '%s' isn't an RTP session", name); return FALSE; } g_object_set (c, "remote-mute", mute, NULL); return TRUE; } static void set_hold (WockyJingleSession *sess, gboolean hold) { sess->priv->remote_hold = hold; } static void set_ringing (WockyJingleSession *sess, gboolean ringing) { sess->priv->remote_ringing = ringing; } static gboolean handle_payload (WockyJingleSession *sess, WockyNode *payload, gboolean *handled, GError **error) { const gchar *ns = wocky_node_get_ns (payload); const gchar *elt = payload->name; const gchar *name = wocky_node_get_attribute (payload, "name"); const gchar *creator = wocky_node_get_attribute (payload, "creator"); if (wocky_strdiff (ns, WOCKY_XMPP_NS_JINGLE_RTP_INFO)) { *handled = FALSE; return TRUE; } *handled = TRUE; if (!wocky_strdiff (elt, "active")) { /* Clear all states, we're active */ mute_all (sess, FALSE); set_ringing (sess, FALSE); set_hold (sess, FALSE); } else if (!wocky_strdiff (elt, "ringing")) { set_ringing (sess, TRUE); } else if (!wocky_strdiff (elt, "hold")) { set_hold (sess, TRUE); } else if (!wocky_strdiff (elt, "unhold")) { set_hold (sess, FALSE); } /* XEP-0178 says that only and can have a name='' * attribute. */ else if (!wocky_strdiff (elt, "mute")) { return set_mute (sess, name, creator, TRUE, error); } else if (!wocky_strdiff (elt, "unmute")) { return set_mute (sess, name, creator, FALSE, error); } else { g_set_error (error, WOCKY_JINGLE_ERROR, WOCKY_JINGLE_ERROR_UNSUPPORTED_INFO, "<%s> is not known in namespace %s", elt, ns); return FALSE; } return TRUE; } static void on_session_info (WockyJingleSession *sess, WockyNode *node, GError **error) { gboolean understood_a_payload = FALSE; gboolean hit_an_error = FALSE; WockyNodeIter i; WockyNode *n; /* if this is a ping, just ack it. */ if (wocky_node_get_first_child (node) == NULL) return; wocky_node_iter_init (&i, node, NULL, NULL); while (wocky_node_iter_next (&i, &n)) { gboolean handled; GError *e = NULL; if (handle_payload (sess, n, &handled, &e)) { understood_a_payload = understood_a_payload || handled; } else if (hit_an_error) { DEBUG ("already got another error; ignoring %s", e->message); g_error_free (e); } else { DEBUG ("hit an error: %s", e->message); hit_an_error = TRUE; g_propagate_error (error, e); } } /* If we understood something, the remote state (may have) changed. Else, * return an error to the peer. */ if (understood_a_payload) g_signal_emit (sess, signals[REMOTE_STATE_CHANGED], 0); else if (!hit_an_error) g_set_error (error, WOCKY_JINGLE_ERROR, WOCKY_JINGLE_ERROR_UNSUPPORTED_INFO, "no recognized session-info payloads"); } static void on_session_terminate (WockyJingleSession *sess, WockyNode *node, GError **error) { gchar *text = NULL; WockyNode *n = wocky_node_get_child (node, "reason"); WockyJingleReason wocky_jingle_reason = WOCKY_JINGLE_REASON_UNKNOWN; if (n != NULL) extract_reason (n, &wocky_jingle_reason, &text); DEBUG ("remote end terminated the session with reason %s and text '%s'", wocky_jingle_session_get_reason_name (wocky_jingle_reason), (text != NULL ? text : "(none)")); set_state (sess, WOCKY_JINGLE_STATE_ENDED, wocky_jingle_reason, text); g_free (text); } static void on_transport_info (WockyJingleSession *sess, WockyNode *node, GError **error) { WockyJingleSessionPrivate *priv = sess->priv; WockyJingleContent *c = NULL; if (WOCKY_JINGLE_DIALECT_IS_GOOGLE (priv->dialect)) { GHashTableIter iter; gpointer value; if (priv->dialect == WOCKY_JINGLE_DIALECT_GTALK4) { if (!wocky_strdiff (wocky_node_get_attribute (node, "type"), "candidates")) { GList *contents = wocky_jingle_session_get_contents (sess); GList *l; DEBUG ("switching to gtalk3 dialect and retransmiting our candidates"); priv->dialect = WOCKY_JINGLE_DIALECT_GTALK3; for (l = contents; l != NULL; l = l->next) wocky_jingle_content_retransmit_candidates (l->data, TRUE); g_list_free (contents); } else { node = wocky_node_get_child (node, "transport"); if (node == NULL) { g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, "transport-info stanza without a "); return; } } } g_hash_table_iter_init (&iter, priv->initiator_contents); while (g_hash_table_iter_next (&iter, NULL, &value)) { c = value; wocky_jingle_content_parse_transport_info (c, node, error); if (error != NULL && *error != NULL) break; } } else { WockyNodeIter i; WockyNode *content_node; GError *e = NULL; wocky_node_iter_init (&i, node, "content", NULL); while (wocky_node_iter_next (&i, &content_node)) { WockyNode *transport_node; if (lookup_content (sess, wocky_node_get_attribute (content_node, "name"), wocky_node_get_attribute (content_node, "creator"), TRUE /* fail_if_missing */, &c, &e)) { /* we need transport child of content node */ transport_node = wocky_node_get_child ( content_node, "transport"); wocky_jingle_content_parse_transport_info (c, transport_node, &e); } /* Save the first error we encounter, but go through all remaining * contents anyway to try and recover as much info as we can */ if (e != NULL && error != NULL && *error == NULL) { *error = e; e = NULL; } g_clear_error (&e); } } } static void on_transport_accept (WockyJingleSession *sess, WockyNode *node, GError **error) { DEBUG ("Ignoring 'transport-accept' action from peer"); } static void on_description_info (WockyJingleSession *sess, WockyNode *node, GError **error) { _foreach_content (sess, node, TRUE, _each_description_info, NULL, error); } static void on_info (WockyJingleSession *sess, WockyNode *node, GError **error) { WockyJingleSessionPrivate *priv = sess->priv; WockyJingleContent *c = NULL; DEBUG ("received info "); if (WOCKY_JINGLE_DIALECT_IS_GOOGLE (priv->dialect)) { GHashTableIter iter; g_hash_table_iter_init (&iter, priv->initiator_contents); while (g_hash_table_iter_next (&iter, NULL, (gpointer) &c)) { wocky_jingle_content_parse_info (c, node, error); if (error != NULL && *error != NULL) break; } } } static HandlerFunc handlers[] = { NULL, /* for unknown action */ on_content_accept, on_content_add, on_content_modify, on_content_remove, on_content_replace, on_content_reject, on_session_accept, /* jingle_on_session_accept */ on_session_info, on_session_initiate, on_session_terminate, /* jingle_on_session_terminate */ on_transport_info, /* jingle_on_transport_info */ on_transport_accept, on_description_info, on_info }; static void wocky_jingle_state_machine_dance (WockyJingleSession *sess, WockyJingleAction action, WockyNode *node, GError **error) { WockyJingleSessionPrivate *priv = sess->priv; /* parser should've checked this already */ g_assert (action_is_allowed (action, priv->state)); g_assert (handlers[action] != NULL); handlers[action] (sess, node, error); } static WockyJingleDialect detect_google_dialect (WockyNode *session_node) { /* The GTALK3 dialect is the only one that supports video at this time */ if (wocky_node_get_child_ns (session_node, "description", WOCKY_XMPP_NS_GOOGLE_SESSION_VIDEO) != NULL) return WOCKY_JINGLE_DIALECT_GTALK3; /* GTalk4 has a transport item, GTalk3 doesn't */ if (wocky_node_get_child_ns (session_node, "transport", WOCKY_XMPP_NS_GOOGLE_TRANSPORT_P2P) == NULL) return WOCKY_JINGLE_DIALECT_GTALK3; return WOCKY_JINGLE_DIALECT_GTALK4; } static const gchar * wocky_jingle_session_detect_internal ( WockyStanza *stanza, WockyJingleAction *action, WockyJingleDialect *dialect, WockyNode **session_node_out) { const gchar *actxt, *sid; WockyNode *iq_node, *session_node; WockyStanzaSubType sub_type; gboolean google_mode = FALSE; /* all jingle actions are sets */ wocky_stanza_get_type_info (stanza, NULL, &sub_type); if (sub_type != WOCKY_STANZA_SUB_TYPE_SET) return NULL; iq_node = wocky_stanza_get_top_node (stanza); if ((NULL == wocky_stanza_get_from (stanza)) || (NULL == wocky_stanza_get_to (stanza))) return NULL; /* first, we try standard jingle */ session_node = wocky_node_get_child_ns (iq_node, "jingle", WOCKY_XMPP_NS_JINGLE); if (session_node != NULL) { if (dialect != NULL) *dialect = WOCKY_JINGLE_DIALECT_V032; } else { /* then, we try a bit older jingle version */ session_node = wocky_node_get_child_ns (iq_node, "jingle", WOCKY_XMPP_NS_JINGLE015); if (session_node != NULL) { if (dialect != NULL) *dialect = WOCKY_JINGLE_DIALECT_V015; } else { /* next, we try googletalk */ session_node = wocky_node_get_child_ns (iq_node, "session", WOCKY_XMPP_NS_GOOGLE_SESSION); if (session_node != NULL) { if (dialect != NULL) *dialect = detect_google_dialect (session_node); google_mode = TRUE; } else { return NULL; } } } if (google_mode) { actxt = wocky_node_get_attribute (session_node, "type"); sid = wocky_node_get_attribute (session_node, "id"); } else { actxt = wocky_node_get_attribute (session_node, "action"); sid = wocky_node_get_attribute (session_node, "sid"); } if (session_node_out != NULL) *session_node_out = session_node; if (action != NULL) *action = parse_action (actxt); return sid; } const gchar * wocky_jingle_session_detect ( WockyStanza *stanza, WockyJingleAction *action, WockyJingleDialect *dialect) { g_return_val_if_fail (WOCKY_IS_STANZA (stanza), NULL); return wocky_jingle_session_detect_internal (stanza, action, dialect, NULL); } gboolean wocky_jingle_session_parse ( WockyJingleSession *sess, WockyJingleAction action, WockyStanza *stanza, GError **error) { WockyJingleSessionPrivate *priv; WockyNode *iq_node, *session_node; const gchar *from, *action_name; g_return_val_if_fail (WOCKY_IS_JINGLE_SESSION (sess), FALSE); g_return_val_if_fail (WOCKY_IS_STANZA (stanza), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); priv = sess->priv; /* IQ from/to can come in handy */ from = wocky_stanza_get_from (stanza); iq_node = wocky_stanza_get_top_node (stanza); if (action == WOCKY_JINGLE_ACTION_UNKNOWN) { g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, "unknown session action"); return FALSE; } action_name = produce_action (action, priv->dialect); DEBUG ("jingle action '%s' from '%s' in session '%s' dialect %u state %u", action_name, from, priv->sid, priv->dialect, priv->state); switch (priv->dialect) { case WOCKY_JINGLE_DIALECT_V032: session_node = wocky_node_get_child_ns (iq_node, "jingle", WOCKY_XMPP_NS_JINGLE); break; case WOCKY_JINGLE_DIALECT_V015: session_node = wocky_node_get_child_ns (iq_node, "jingle", WOCKY_XMPP_NS_JINGLE015); break; case WOCKY_JINGLE_DIALECT_GTALK3: case WOCKY_JINGLE_DIALECT_GTALK4: session_node = wocky_node_get_child_ns (iq_node, "session", WOCKY_XMPP_NS_GOOGLE_SESSION); break; default: /* just to make gcc happy about dealing with default case */ session_node = NULL; } if (session_node == NULL) { g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, "malformed jingle stanza"); return FALSE; } if (!wocky_jingle_session_defines_action (sess, action)) { g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, "action '%s' unknown (using dialect %u)", action_name, priv->dialect); return FALSE; } if (!action_is_allowed (action, priv->state)) { g_set_error (error, WOCKY_JINGLE_ERROR, WOCKY_JINGLE_ERROR_OUT_OF_ORDER, "action '%s' not allowed in current state", action_name); return FALSE; } wocky_jingle_state_machine_dance (sess, action, session_node, error); if (*error != NULL) return FALSE; return TRUE; } WockyStanza * wocky_jingle_session_new_message (WockyJingleSession *sess, WockyJingleAction action, WockyNode **sess_node) { WockyJingleSessionPrivate *priv = sess->priv; WockyStanza *stanza; WockyNode *session_node; gchar *el = NULL, *ns = NULL; gboolean gtalk_mode = FALSE; g_return_val_if_fail (WOCKY_IS_JINGLE_SESSION (sess), NULL); g_return_val_if_fail (action != WOCKY_JINGLE_ACTION_UNKNOWN, NULL); g_assert ((action == WOCKY_JINGLE_ACTION_SESSION_INITIATE) || (priv->state > WOCKY_JINGLE_STATE_PENDING_CREATED)); switch (priv->dialect) { case WOCKY_JINGLE_DIALECT_V032: el = "jingle"; ns = WOCKY_XMPP_NS_JINGLE; break; case WOCKY_JINGLE_DIALECT_V015: el = "jingle"; ns = WOCKY_XMPP_NS_JINGLE015; break; case WOCKY_JINGLE_DIALECT_GTALK3: case WOCKY_JINGLE_DIALECT_GTALK4: el = "session"; ns = WOCKY_XMPP_NS_GOOGLE_SESSION; gtalk_mode = TRUE; break; case WOCKY_JINGLE_DIALECT_ERROR: g_assert_not_reached (); } stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, priv->peer_jid, '(', el, ':', ns, '*', &session_node, ')', NULL); wocky_node_set_attributes (session_node, "initiator", priv->initiator, (gtalk_mode) ? "id" : "sid", priv->sid, (gtalk_mode) ? "type" : "action", produce_action (action, priv->dialect), NULL); if (sess_node != NULL) *sess_node = session_node; return stanza; } typedef void (*ContentMapperFunc) (WockyJingleSession *sess, WockyJingleContent *c, gpointer user_data); static void _map_initial_contents (WockyJingleSession *sess, ContentMapperFunc mapper, gpointer user_data) { GList *li; GList *contents = wocky_jingle_session_get_contents (sess); for (li = contents; li; li = li->next) { WockyJingleContent *c = WOCKY_JINGLE_CONTENT (li->data); const gchar *disposition = wocky_jingle_content_get_disposition (c); if (!wocky_strdiff (disposition, "session")) mapper (sess, c, user_data); } g_list_free (contents); } static void _check_content_ready (WockyJingleSession *sess, WockyJingleContent *c, gpointer user_data) { gboolean *ready = (gboolean *) user_data; if (!wocky_jingle_content_is_ready (c)) { *ready = FALSE; } } static void _transmit_candidates (WockyJingleSession *sess, WockyJingleContent *c, gpointer user_data) { wocky_jingle_content_retransmit_candidates (c, FALSE); } static void _fill_content (WockyJingleSession *sess, WockyJingleContent *c, gpointer user_data) { WockyNode *sess_node = user_data; WockyNode *transport_node; WockyJingleContentState state; wocky_jingle_content_produce_node (c, sess_node, TRUE, TRUE, &transport_node); wocky_jingle_content_inject_candidates (c, transport_node); g_object_get (c, "state", &state, NULL); if (state == WOCKY_JINGLE_CONTENT_STATE_EMPTY) { g_object_set (c, "state", WOCKY_JINGLE_CONTENT_STATE_SENT, NULL); } else if (state == WOCKY_JINGLE_CONTENT_STATE_NEW) { g_object_set (c, "state", WOCKY_JINGLE_CONTENT_STATE_ACKNOWLEDGED, NULL); } else { DEBUG ("content %p is in state %u", c, state); g_assert_not_reached (); } } /** * wocky_jingle_session_send: * @sess: a session * @stanza: (transfer full): a stanza, of which this function will take ownership * * A shorthand for sending a Jingle IQ without waiting for the reply. */ void wocky_jingle_session_send (WockyJingleSession *sess, WockyStanza *stanza) { g_return_if_fail (WOCKY_IS_JINGLE_SESSION (sess)); g_return_if_fail (WOCKY_IS_STANZA (stanza)); wocky_porter_send_iq_async (sess->priv->porter, stanza, NULL, NULL, NULL); g_object_unref (stanza); } static void _on_initiate_reply ( GObject *source, GAsyncResult *result, gpointer user_data) { WockyPorter *porter = WOCKY_PORTER (source); WockyJingleSession *sess = WOCKY_JINGLE_SESSION (user_data); WockyJingleSessionPrivate *priv = sess->priv; WockyStanza *reply; if (priv->state != WOCKY_JINGLE_STATE_PENDING_INITIATE_SENT) { DEBUG ("Ignoring session-initiate reply; session %p is in state %u.", sess, priv->state); g_object_unref (sess); return; } reply = wocky_porter_send_iq_finish (porter, result, NULL); if (reply != NULL && !wocky_stanza_extract_errors (reply, NULL, NULL, NULL, NULL)) { set_state (sess, WOCKY_JINGLE_STATE_PENDING_INITIATED, 0, NULL); if (priv->dialect != WOCKY_JINGLE_DIALECT_V032) { /* If this is a dialect that doesn't support , we treat the * session-initiate being acked as the cue to say we're ringing. */ priv->remote_ringing = TRUE; g_signal_emit (sess, signals[REMOTE_STATE_CHANGED], 0); } } else { set_state (sess, WOCKY_JINGLE_STATE_ENDED, WOCKY_JINGLE_REASON_UNKNOWN, NULL); } g_clear_object (&reply); g_object_unref (sess); } static void _on_accept_reply ( GObject *source, GAsyncResult *result, gpointer user_data) { WockyPorter *porter = WOCKY_PORTER (source); WockyJingleSession *sess = WOCKY_JINGLE_SESSION (user_data); WockyJingleSessionPrivate *priv = sess->priv; WockyStanza *reply; if (priv->state != WOCKY_JINGLE_STATE_PENDING_ACCEPT_SENT) { DEBUG ("Ignoring session-accept reply; session %p is in state %u.", sess, priv->state); g_object_unref (sess); return; } reply = wocky_porter_send_iq_finish (porter, result, NULL); if (reply != NULL && !wocky_stanza_extract_errors (reply, NULL, NULL, NULL, NULL)) { set_state (sess, WOCKY_JINGLE_STATE_ACTIVE, 0, NULL); wocky_jingle_session_send_rtp_info (sess, "active"); } else { set_state (sess, WOCKY_JINGLE_STATE_ENDED, WOCKY_JINGLE_REASON_UNKNOWN, NULL); } g_clear_object (&reply); g_object_unref (sess); } static void try_session_initiate_or_accept (WockyJingleSession *sess) { WockyJingleSessionPrivate *priv = sess->priv; WockyStanza *msg; WockyNode *sess_node; gboolean contents_ready = TRUE; WockyJingleAction action; WockyJingleState new_state; GAsyncReadyCallback handler; DEBUG ("Trying initiate or accept"); /* If there are no contents yet, we shouldn't have been called at all. */ g_assert (g_hash_table_size (priv->initiator_contents) + g_hash_table_size (priv->responder_contents) > 0); if (priv->local_initiator) { if (priv->state != WOCKY_JINGLE_STATE_PENDING_CREATED) { DEBUG ("session is in state %u, won't try to initiate", priv->state); return; } if (!priv->locally_accepted) { DEBUG ("session not locally accepted yet, not initiating"); return; } action = WOCKY_JINGLE_ACTION_SESSION_INITIATE; new_state = WOCKY_JINGLE_STATE_PENDING_INITIATE_SENT; handler = _on_initiate_reply; } else { if (priv->state != WOCKY_JINGLE_STATE_PENDING_INITIATED) { DEBUG ("session is in state %u, won't try to accept", priv->state); return; } if (!priv->locally_accepted) { DEBUG ("session not locally accepted yet, not accepting"); return; } action = WOCKY_JINGLE_ACTION_SESSION_ACCEPT; new_state = WOCKY_JINGLE_STATE_PENDING_ACCEPT_SENT; handler = _on_accept_reply; } _map_initial_contents (sess, _check_content_ready, &contents_ready); DEBUG ("Contents are ready: %s", contents_ready ? "yes" : "no"); if (!contents_ready) { DEBUG ("Contents not yet ready, not initiating/accepting now.."); return; } if (action == WOCKY_JINGLE_ACTION_SESSION_INITIATE) g_signal_emit (sess, signals[ABOUT_TO_INITIATE], 0); msg = wocky_jingle_session_new_message (sess, action, &sess_node); if (priv->dialect == WOCKY_JINGLE_DIALECT_GTALK3) { gboolean has_video = FALSE; gboolean has_audio = FALSE; GHashTableIter iter; gpointer value; g_hash_table_iter_init (&iter, priv->initiator_contents); while (g_hash_table_iter_next (&iter, NULL, &value)) { WockyJingleMediaType type; g_object_get (value, "media-type", &type, NULL); if (type == WOCKY_JINGLE_MEDIA_TYPE_VIDEO) { has_video = TRUE; } else if (type == WOCKY_JINGLE_MEDIA_TYPE_AUDIO) { has_audio = TRUE; } } if (has_video || has_audio) { sess_node = wocky_node_add_child_ns_q (sess_node, "description", g_quark_from_static_string (has_video ? WOCKY_XMPP_NS_GOOGLE_SESSION_VIDEO : WOCKY_XMPP_NS_GOOGLE_SESSION_PHONE)); } } _map_initial_contents (sess, _fill_content, sess_node); wocky_porter_send_iq_async (priv->porter, msg, NULL, handler, g_object_ref (sess)); g_object_unref (msg); set_state (sess, new_state, 0, NULL); /* now all initial contents can transmit their candidates */ _map_initial_contents (sess, _transmit_candidates, NULL); } /** * set_state: * @sess: a jingle session * @state: the new state for the session * @termination_reason: if @state is WOCKY_JINGLE_STATE_ENDED, the reason the session * ended. Otherwise, must be WOCKY_JINGLE_REASON_UNKNOWN. * @text: if @state is WOCKY_JINGLE_STATE_ENDED, the human-readable reason the session * ended. */ static void set_state (WockyJingleSession *sess, WockyJingleState state, WockyJingleReason termination_reason, const gchar *text) { WockyJingleSessionPrivate *priv = sess->priv; if (state <= priv->state) { DEBUG ("ignoring request to set state from %u back to %u", priv->state, state); return; } if (state != WOCKY_JINGLE_STATE_ENDED) g_assert (termination_reason == WOCKY_JINGLE_REASON_UNKNOWN); DEBUG ("Setting state of JingleSession: %p (priv = %p) from %u to %u", sess, priv, priv->state, state); priv->state = state; g_object_notify (G_OBJECT (sess), "state"); /* If we have an outstanding "you're on hold notification", send it */ if (priv->local_hold && state >= WOCKY_JINGLE_STATE_PENDING_INITIATED && state < WOCKY_JINGLE_STATE_ENDED) wocky_jingle_session_send_held (sess); if (state == WOCKY_JINGLE_STATE_ENDED) g_signal_emit (sess, signals[TERMINATED], 0, priv->locally_terminated, termination_reason, text); } /** * wocky_jingle_session_accept: * @sess: the session. * * For incoming calls, accepts the call. For outgoing calls, indicates that the * initial contents for the call have been created and the offer can be sent to * the peer. * * The acceptance or offer will only be signalled to the peer once all contents * are ready (as returned by wocky_jingle_content_is_ready()). For an RTP * session with #WockyJingleMediaRtp contents, this translates to a media * description and transport candidates having been provided to all contents. */ void wocky_jingle_session_accept (WockyJingleSession *sess) { g_return_if_fail (WOCKY_IS_JINGLE_SESSION (sess)); sess->priv->locally_accepted = TRUE; try_session_initiate_or_accept (sess); } const gchar * wocky_jingle_session_get_reason_name (WockyJingleReason reason) { GEnumClass *klass = g_type_class_ref (wocky_jingle_reason_get_type ()); GEnumValue *enum_value = g_enum_get_value (klass, (gint) reason); g_return_val_if_fail (enum_value != NULL, NULL); return enum_value->value_nick; } /** * wocky_jingle_session_terminate: * @sess: the session * @reason: the reason the session should be terminated * @text: (allow-none): human-readable information about why the session * terminated * @error: Unused, because this function never fails. * * Ends a session. * * If called for an outgoing session which has not yet been signalled to the * peer (perhaps because wocky_jingle_session_accept() has not been called, or * codecs or candidates have not been provided), the session will quietly * terminate without the peer hearing anything about it. * * If called for an already-terminated session, this is a no-op. * * Returns: %TRUE. */ gboolean wocky_jingle_session_terminate (WockyJingleSession *sess, WockyJingleReason reason, const gchar *text, GError **error G_GNUC_UNUSED) { WockyJingleSessionPrivate *priv; const gchar *reason_elt; g_return_val_if_fail (WOCKY_IS_JINGLE_SESSION (sess), FALSE); priv = sess->priv; if (priv->state == WOCKY_JINGLE_STATE_ENDED) { DEBUG ("session already terminated, ignoring terminate request"); return TRUE; } if (reason == WOCKY_JINGLE_REASON_UNKNOWN) reason = (priv->state == WOCKY_JINGLE_STATE_ACTIVE) ? WOCKY_JINGLE_REASON_SUCCESS : WOCKY_JINGLE_REASON_CANCEL; reason_elt = wocky_jingle_session_get_reason_name (reason); if (priv->state != WOCKY_JINGLE_STATE_PENDING_CREATED) { WockyNode *session_node; WockyStanza *msg = wocky_jingle_session_new_message (sess, WOCKY_JINGLE_ACTION_SESSION_TERMINATE, &session_node); if (priv->dialect == WOCKY_JINGLE_DIALECT_V032 && reason_elt != NULL) { WockyNode *r = wocky_node_add_child_with_content (session_node, "reason", NULL); wocky_node_add_child (r, reason_elt); if (text != NULL && *text != '\0') wocky_node_add_child_with_content (r, "text", text); } wocky_jingle_session_send (sess, msg); } /* NOTE: on "terminated", jingle factory and media channel will unref * it, bringing refcount to 0, so dispose will be called, and it * takes care of cleanup */ DEBUG ("we are terminating this session"); priv->locally_terminated = TRUE; set_state (sess, WOCKY_JINGLE_STATE_ENDED, reason, text); return TRUE; } static void _foreach_count_active_contents (gpointer key, gpointer value, gpointer user_data) { WockyJingleContent *c = value; guint *n_contents = user_data; WockyJingleContentState state; g_object_get (c, "state", &state, NULL); if ((state >= WOCKY_JINGLE_CONTENT_STATE_NEW) && (state < WOCKY_JINGLE_CONTENT_STATE_REMOVING)) { *n_contents = *n_contents + 1; } } static gboolean count_active_contents (WockyJingleSession *sess) { WockyJingleSessionPrivate *priv = sess->priv; guint n_contents = 0; g_hash_table_foreach (priv->initiator_contents, _foreach_count_active_contents, &n_contents); g_hash_table_foreach (priv->responder_contents, _foreach_count_active_contents, &n_contents); return n_contents; } static void content_removed_cb (WockyJingleContent *c, gpointer user_data) { WockyJingleSession *sess = WOCKY_JINGLE_SESSION (user_data); WockyJingleSessionPrivate *priv = sess->priv; const gchar *name = wocky_jingle_content_get_name (c); if (wocky_jingle_content_creator_is_initiator (c)) g_hash_table_remove (priv->initiator_contents, name); else g_hash_table_remove (priv->responder_contents, name); if (priv->state == WOCKY_JINGLE_STATE_ENDED) return; if (count_active_contents (sess) == 0) { wocky_jingle_session_terminate (sess, WOCKY_JINGLE_REASON_UNKNOWN, NULL, NULL); } else { /* It's possible the content now removed was * blocking us from creating or accepting the * session, so we might as well try now. */ try_session_initiate_or_accept (sess); } } void wocky_jingle_session_remove_content (WockyJingleSession *sess, WockyJingleContent *c) { g_return_if_fail (WOCKY_IS_JINGLE_SESSION (sess)); g_return_if_fail (WOCKY_IS_JINGLE_CONTENT (c)); if (count_active_contents (sess) > 1) { wocky_jingle_content_remove (c, TRUE); } else { /* session will be terminated when the content gets marked as removed */ DEBUG ("called for last active content, doing session-terminate instead"); wocky_jingle_content_remove (c, FALSE); } } /** * wocky_jingle_session_add_content: * @sess: the session * @mtype: what kind of media will be exchanged on the content * @senders: which directions media should initially flow in. * @name: (allow-none): a descriptive name to use for the content; this is * typically not shown to users * @content_ns: the namespace to use for the content's description * @transport_ns: the namespace of the media transport to use for the call * * Adds a content to the session. Once it has its codecs and transport * candidates filled in, it will be signalled to the peer (either as part of * the session-initiate, if it has not been sent yet, or as a content-add if * @sess has already been initiated). * * Legal values for @content_ns and @transport_ns depend on the Jingle dialect * in use for this session (and in some cases on @mtype); sensible values * depend on the peer's capabilities. * * Returns: (transfer none): the new content, which is guaranteed not to be %NULL. */ WockyJingleContent * wocky_jingle_session_add_content (WockyJingleSession *sess, WockyJingleMediaType mtype, WockyJingleContentSenders senders, const gchar *name, const gchar *content_ns, const gchar *transport_ns) { WockyJingleSessionPrivate *priv; WockyJingleContent *c; GType content_type; GHashTable *contents; guint id; gchar *cname = NULL; g_return_val_if_fail (WOCKY_IS_JINGLE_SESSION (sess), NULL); priv = sess->priv; contents = priv->local_initiator ? priv->initiator_contents : priv->responder_contents; id = g_hash_table_size (contents) + 1; if (name == NULL || *name == '\0') name = (mtype == WOCKY_JINGLE_MEDIA_TYPE_AUDIO ? "Audio" : "Video"); cname = g_strdup (name); while (g_hash_table_lookup (priv->initiator_contents, cname) != NULL || g_hash_table_lookup (priv->responder_contents, cname) != NULL) { g_free (cname); cname = g_strdup_printf ("%s_%d", name, id++); } content_type = wocky_jingle_factory_lookup_content_type ( wocky_jingle_session_get_factory (sess), content_ns); g_assert (content_type != 0); c = create_content (sess, content_type, mtype, senders, content_ns, transport_ns, cname, NULL, NULL); /* The new content better have ended up in the set we thought it would... */ g_assert (g_hash_table_lookup (contents, cname) != NULL); g_free (cname); return c; } /* Get any content. Either we're in google mode (so we only have one content * anyways), or we just need any content type to figure out what use case * we're in (media, ft, etc). */ static WockyJingleContent * _get_any_content (WockyJingleSession *session) { WockyJingleContent *c; GList *li = wocky_jingle_session_get_contents (session); if (li == NULL) return NULL; c = li->data; g_list_free (li); return c; } /* Note: if there are multiple content types, not guaranteed which one will * be returned. Typically, the same GType will know how to handle related * contents found in a session (e.g. media-rtp for audio/video), so that * should not be a problem. Returns 0 if there are no contents yet. */ GType wocky_jingle_session_get_content_type (WockyJingleSession *sess) { WockyJingleContent *c; g_return_val_if_fail (WOCKY_IS_JINGLE_SESSION (sess), G_TYPE_INVALID); c = _get_any_content (sess); if (c == NULL) return 0; return G_OBJECT_TYPE (c); } /* FIXME: probably should make this into a property */ GList * wocky_jingle_session_get_contents (WockyJingleSession *sess) { WockyJingleSessionPrivate *priv; g_return_val_if_fail (WOCKY_IS_JINGLE_SESSION (sess), NULL); priv = sess->priv; return g_list_concat (g_hash_table_get_values (priv->initiator_contents), g_hash_table_get_values (priv->responder_contents)); } const gchar * wocky_jingle_session_get_peer_resource (WockyJingleSession *sess) { g_return_val_if_fail (WOCKY_IS_JINGLE_SESSION (sess), NULL); return sess->priv->peer_resource; } const gchar * wocky_jingle_session_get_initiator (WockyJingleSession *sess) { g_return_val_if_fail (WOCKY_IS_JINGLE_SESSION (sess), NULL); return sess->priv->initiator; } const gchar * wocky_jingle_session_get_sid (WockyJingleSession *sess) { g_return_val_if_fail (WOCKY_IS_JINGLE_SESSION (sess), NULL); return sess->priv->sid; } static void content_ready_cb (WockyJingleContent *c, gpointer user_data) { WockyJingleSession *sess = WOCKY_JINGLE_SESSION (user_data); const gchar *disposition; DEBUG ("called"); disposition = wocky_jingle_content_get_disposition (c); /* This assertion is actually safe, because 'ready' is only emitted by * contents with disposition "session". But this is crazy. */ g_assert (!wocky_strdiff (disposition, "session")); try_session_initiate_or_accept (sess); } static void wocky_jingle_session_send_rtp_info (WockyJingleSession *sess, const gchar *name) { WockyStanza *message; WockyNode *jingle; if (!wocky_jingle_session_defines_action (sess, WOCKY_JINGLE_ACTION_SESSION_INFO)) { DEBUG ("Not sending <%s/>; not using modern Jingle", name); return; } message = wocky_jingle_session_new_message (sess, WOCKY_JINGLE_ACTION_SESSION_INFO, &jingle); wocky_node_add_child_ns_q (jingle, name, g_quark_from_static_string (WOCKY_XMPP_NS_JINGLE_RTP_INFO)); /* This is just informational, so ignoring the reply. */ wocky_jingle_session_send (sess, message); } static void wocky_jingle_session_send_held (WockyJingleSession *sess) { const gchar *s = (sess->priv->local_hold ? "hold" : "unhold"); wocky_jingle_session_send_rtp_info (sess, s); } void wocky_jingle_session_set_local_hold (WockyJingleSession *sess, gboolean held) { g_return_if_fail (WOCKY_IS_JINGLE_SESSION (sess)); g_object_set (sess, "local-hold", held, NULL); } gboolean wocky_jingle_session_get_remote_hold (WockyJingleSession *sess) { g_return_val_if_fail (WOCKY_IS_JINGLE_SESSION (sess), FALSE); return sess->priv->remote_hold; } gboolean wocky_jingle_session_get_remote_ringing (WockyJingleSession *sess) { g_return_val_if_fail (WOCKY_IS_JINGLE_SESSION (sess), FALSE); return sess->priv->remote_ringing; } gboolean wocky_jingle_session_can_modify_contents (WockyJingleSession *sess) { g_return_val_if_fail (WOCKY_IS_JINGLE_SESSION (sess), FALSE); return !WOCKY_JINGLE_DIALECT_IS_GOOGLE (sess->priv->dialect) && !wocky_jingle_session_peer_has_cap (sess, WOCKY_QUIRK_GOOGLE_WEBMAIL_CLIENT); } WockyJingleDialect wocky_jingle_session_get_dialect (WockyJingleSession *sess) { g_return_val_if_fail (WOCKY_IS_JINGLE_SESSION (sess), WOCKY_JINGLE_DIALECT_ERROR); return sess->priv->dialect; } WockyContact * wocky_jingle_session_get_peer_contact (WockyJingleSession *self) { g_return_val_if_fail (WOCKY_IS_JINGLE_SESSION (self), NULL); return self->priv->peer_contact; } /* * wocky_jingle_session_get_peer_jid: * @sess: a jingle session * * Returns: the full JID of the remote contact. */ const gchar * wocky_jingle_session_get_peer_jid (WockyJingleSession *sess) { g_return_val_if_fail (WOCKY_IS_JINGLE_SESSION (sess), NULL); return sess->priv->peer_jid; } WockyJingleFactory * wocky_jingle_session_get_factory (WockyJingleSession *self) { g_return_val_if_fail (WOCKY_IS_JINGLE_SESSION (self), NULL); return self->priv->jingle_factory; } WockyPorter * wocky_jingle_session_get_porter (WockyJingleSession *self) { g_return_val_if_fail (WOCKY_IS_JINGLE_SESSION (self), NULL); return self->priv->porter; } void wocky_jingle_session_acknowledge_iq (WockyJingleSession *self, WockyStanza *stanza) { g_return_if_fail (WOCKY_IS_JINGLE_SESSION (self)); g_return_if_fail (WOCKY_IS_STANZA (stanza)); if (wocky_jingle_session_peer_has_cap (self, WOCKY_QUIRK_GOOGLE_WEBMAIL_CLIENT)) { WockyJingleAction action = WOCKY_JINGLE_ACTION_UNKNOWN; WockyNode *used_node = NULL; /* As of 2013-05-29, the Google webmail client sends a session-initiate * IQ with two child nodes (which is not valid XMPP Core but never mind) * and replies to session-initiate by echoing the child for the dialect * it chose. We have to do the same echoing, otherwise it can't call us. * * It doesn't seem to reply to our other IQs at all; we still reply * here (we'd be violating XMPP Core if we didn't), but we don't * bother putting content in the IQ, to reduce bandwidth. */ if (wocky_jingle_session_detect_internal (stanza, &action, NULL, &used_node) != NULL && action == WOCKY_JINGLE_ACTION_SESSION_INITIATE) { WockyStanza *reply = wocky_stanza_build_iq_result (stanza, NULL); if (reply != NULL) { WockyNode *reply_node = wocky_stanza_get_top_node (reply); reply_node->children = g_slist_append (reply_node->children, _wocky_node_copy (used_node)); wocky_porter_send (self->priv->porter, reply); g_object_unref (reply); return; } } } /* normal Jingle just says "OK" without echoing */ wocky_porter_acknowledge_iq (self->priv->porter, stanza, NULL); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-sasl-digest-md5.c0000664000175000017500000003220412005516162026233 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-sasl-digest-md5.h" #include "wocky-auth-registry.h" #include "wocky-sasl-utils.h" #include #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_AUTH #include "wocky-debug-internal.h" typedef enum { WOCKY_SASL_DIGEST_MD5_STATE_STARTED, WOCKY_SASL_DIGEST_MD5_STATE_SENT_AUTH_RESPONSE, WOCKY_SASL_DIGEST_MD5_STATE_SENT_FINAL_RESPONSE, } WockySaslDigestMd5State; static void auth_handler_iface_init (gpointer g_iface); G_DEFINE_TYPE_WITH_CODE (WockySaslDigestMd5, wocky_sasl_digest_md5, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE ( WOCKY_TYPE_AUTH_HANDLER, auth_handler_iface_init)) enum { PROP_SERVER = 1, PROP_USERNAME, PROP_PASSWORD }; struct _WockySaslDigestMd5Private { WockySaslDigestMd5State state; gchar *username; gchar *password; gchar *server; gchar *digest_md5_rspauth; }; static void wocky_sasl_digest_md5_get_property ( GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockySaslDigestMd5 *self = (WockySaslDigestMd5 *) object; WockySaslDigestMd5Private *priv = self->priv; switch (property_id) { case PROP_USERNAME: g_value_set_string (value, priv->username); break; case PROP_PASSWORD: g_value_set_string (value, priv->password); break; case PROP_SERVER: g_value_set_string (value, priv->server); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void wocky_sasl_digest_md5_set_property ( GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockySaslDigestMd5 *self = (WockySaslDigestMd5 *) object; WockySaslDigestMd5Private *priv = self->priv; switch (property_id) { case PROP_SERVER: g_free (priv->server); priv->server = g_value_dup_string (value); break; case PROP_USERNAME: g_free (priv->username); priv->username = g_value_dup_string (value); break; case PROP_PASSWORD: g_free (priv->password); priv->password = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void wocky_sasl_digest_md5_dispose (GObject *object) { WockySaslDigestMd5 *self = (WockySaslDigestMd5 *) object; WockySaslDigestMd5Private *priv = self->priv; g_free (priv->server); g_free (priv->username); g_free (priv->password); g_free (priv->digest_md5_rspauth); G_OBJECT_CLASS (wocky_sasl_digest_md5_parent_class)->dispose (object); } static void wocky_sasl_digest_md5_class_init ( WockySaslDigestMd5Class *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (WockySaslDigestMd5Private)); object_class->dispose = wocky_sasl_digest_md5_dispose; object_class->set_property = wocky_sasl_digest_md5_set_property; object_class->get_property = wocky_sasl_digest_md5_get_property; g_object_class_install_property (object_class, PROP_SERVER, g_param_spec_string ("server", "server", "The name of the server we're authenticating to", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_USERNAME, g_param_spec_string ("username", "username", "The username to authenticate with", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_PASSWORD, g_param_spec_string ("password", "password", "The password to authenticate with", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); } static gboolean digest_md5_handle_auth_data (WockyAuthHandler *handler, const GString *data, GString **response, GError **error); static gboolean digest_md5_handle_success (WockyAuthHandler *handler, GError **error); static void auth_handler_iface_init (gpointer g_iface) { WockyAuthHandlerIface *iface = g_iface; iface->mechanism = WOCKY_AUTH_MECH_SASL_DIGEST_MD5; iface->plain = FALSE; iface->auth_data_func = digest_md5_handle_auth_data; iface->success_func = digest_md5_handle_success; } static void wocky_sasl_digest_md5_init (WockySaslDigestMd5 *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_SASL_DIGEST_MD5, WockySaslDigestMd5Private); self->priv->state = WOCKY_SASL_DIGEST_MD5_STATE_STARTED; } WockySaslDigestMd5 * wocky_sasl_digest_md5_new ( const gchar *server, const gchar *username, const gchar *password) { return g_object_new (WOCKY_TYPE_SASL_DIGEST_MD5, "server", server, "username", username, "password", password, NULL); } static gchar * strndup_unescaped (const gchar *str, gsize len) { const gchar *s; gchar *d, *ret; ret = g_malloc0 (len + 1); for (s = str, d = ret ; s < (str + len) ; s++, d++) { if (*s == '\\') s++; *d = *s; } return ret; } static GHashTable * digest_md5_challenge_to_hash (const GString * challenge) { GHashTable *result = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); const gchar *keystart, *keyend, *valstart; const gchar *c = challenge->str; gchar *key, *val; do { keystart = c; for (; *c != '\0' && *c != '='; c++) ; if (*c == '\0' || c == keystart) goto error; keyend = c; c++; /* eat any whitespace between the '=' and the '"' */ for (; g_ascii_isspace (*c); c++) ; if (*c == '"') { gboolean esc = FALSE; c++; valstart = c; /* " terminates a quoted value _unless_ we are in a \ escape */ /* \0 always terminates (end of string encountered) */ for (; *c != '\0' && (esc || *c != '"'); c++) { if (esc) esc = FALSE; /* we are in a \ char escape, finish it */ else esc = *c == '\\'; /* is this char \ (ie starting an escape) */ } if (*c == '\0' || c == valstart) goto error; val = strndup_unescaped (valstart, c - valstart); c++; } else { valstart = c; for (; *c != '\0' && *c != ','; c++) ; if (c == valstart) goto error; val = g_strndup (valstart, c - valstart); } /* the key is unguarded by '"' delimiters so any whitespace * * at either end should be discarded as irrelevant */ key = g_strndup (keystart, keyend - keystart); key = g_strstrip (key); DEBUG ("challenge '%s' = '%s'", key, val); g_hash_table_insert (result, key, val); /* eat any whitespace between the '"' and the next ',' */ for (; g_ascii_isspace (*c); c++) ; if (*c == ',') c++; } while (*c != '\0'); return result; error: DEBUG ("Failed to parse challenge: %s", challenge->str); g_hash_table_unref (result); return NULL; } static guint8 * md5_hash (gchar *value) { GChecksum *checksum; guint8 *result; gsize len; len = g_checksum_type_get_length (G_CHECKSUM_MD5); g_assert (len == 16); result = g_malloc (len); checksum = g_checksum_new (G_CHECKSUM_MD5); g_checksum_update (checksum, (guchar *) value, -1); g_checksum_get_digest (checksum, result, &len); g_checksum_free (checksum); g_assert (len == 16); return result; } static gchar * md5_hex_hash (gchar *value, gsize length) { return g_compute_checksum_for_string (G_CHECKSUM_MD5, value, length); } static GString * md5_prepare_response (WockySaslDigestMd5Private *priv, GHashTable *challenge, GError **error) { GString *response = g_string_new (""); const gchar *realm, *nonce; gchar *a1, *a1h, *a2, *a2h, *kd, *kdh; gchar *cnonce = NULL; gchar *tmp; guint8 *digest_md5; gsize len; if (priv->username == NULL || priv->password == NULL) { g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NO_CREDENTIALS, "No username or password provided"); goto error; } DEBUG ("Got username and password"); nonce = g_hash_table_lookup (challenge, "nonce"); if (nonce == NULL || nonce == '\0') { g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, "Server didn't provide a nonce in the challenge"); goto error; } cnonce = sasl_generate_base64_nonce (); /* FIXME challenge can contain multiple realms */ realm = g_hash_table_lookup (challenge, "realm"); if (realm == NULL) { realm = priv->server; } /* FIXME properly escape values */ g_string_append_printf (response, "username=\"%s\"", priv->username); g_string_append_printf (response, ",realm=\"%s\"", realm); g_string_append_printf (response, ",digest-uri=\"xmpp/%s\"", priv->server); g_string_append_printf (response, ",nonce=\"%s\",nc=00000001", nonce); g_string_append_printf (response, ",cnonce=\"%s\"", cnonce); /* FIXME should check if auth is in the cop challenge val */ g_string_append_printf (response, ",qop=auth,charset=utf-8"); tmp = g_strdup_printf ("%s:%s:%s", priv->username, realm, priv->password); digest_md5 = md5_hash (tmp); g_free (tmp); a1 = g_strdup_printf ("0123456789012345:%s:%s", nonce, cnonce); len = strlen (a1); /* MD5 hash is 16 bytes */ memcpy (a1, digest_md5, 16); a1h = md5_hex_hash (a1, len); g_free (digest_md5); a2 = g_strdup_printf ("AUTHENTICATE:xmpp/%s", priv->server); a2h = md5_hex_hash (a2, -1); kd = g_strdup_printf ("%s:%s:00000001:%s:auth:%s", a1h, nonce, cnonce, a2h); kdh = md5_hex_hash (kd, -1); g_string_append_printf (response, ",response=%s", kdh); g_free (kd); g_free (kdh); g_free (a2); g_free (a2h); /* Calculate the response we expect from the server */ a2 = g_strdup_printf (":xmpp/%s", priv->server); a2h = md5_hex_hash (a2, -1); kd = g_strdup_printf ("%s:%s:00000001:%s:auth:%s", a1h, nonce, cnonce, a2h); g_free (priv->digest_md5_rspauth); priv->digest_md5_rspauth = md5_hex_hash (kd, -1); g_free (a1); g_free (a1h); g_free (a2); g_free (a2h); g_free (kd); out: g_free (cnonce); return response; error: g_string_free (response, TRUE); response = NULL; goto out; } static gboolean digest_md5_make_initial_response ( WockySaslDigestMd5Private *priv, GHashTable *challenge, GString **response, GError **error) { g_return_val_if_fail (response != NULL, FALSE); *response = md5_prepare_response (priv, challenge, error); if (*response == NULL) return FALSE; DEBUG ("Prepared response: %s", (*response)->str); priv->state = WOCKY_SASL_DIGEST_MD5_STATE_SENT_AUTH_RESPONSE; return TRUE; } static gboolean digest_md5_check_server_response ( WockySaslDigestMd5Private *priv, GHashTable *challenge, GError **error) { const gchar *rspauth; rspauth = g_hash_table_lookup (challenge, "rspauth"); if (rspauth == NULL) { g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, "Server sent an invalid reply (no rspauth)"); return FALSE; } if (strcmp (priv->digest_md5_rspauth, rspauth)) { g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, "Server sent an invalid reply (rspauth not matching)"); return FALSE; } priv->state = WOCKY_SASL_DIGEST_MD5_STATE_SENT_FINAL_RESPONSE; return TRUE; } static GHashTable * auth_data_to_hash (const GString *challenge, GError **error) { GHashTable *h = NULL; DEBUG ("Got digest-md5 challenge: %s", challenge->str); h = digest_md5_challenge_to_hash (challenge); if (h == NULL) g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, "Server sent invalid auth data"); return h; } static gboolean digest_md5_handle_auth_data (WockyAuthHandler *handler, const GString *data, GString **response, GError **error) { WockySaslDigestMd5 *self = WOCKY_SASL_DIGEST_MD5 (handler); WockySaslDigestMd5Private *priv = self->priv; GHashTable *h; gboolean ret = FALSE; if (data == NULL) { DEBUG ("Expected auth data but didn't get any!"); g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, "Expected auth data from the server, but didn't get any"); return FALSE; } h = auth_data_to_hash (data, error); if (h == NULL) return FALSE; switch (priv->state) { case WOCKY_SASL_DIGEST_MD5_STATE_STARTED: ret = digest_md5_make_initial_response (priv, h, response, error); break; case WOCKY_SASL_DIGEST_MD5_STATE_SENT_AUTH_RESPONSE: ret = digest_md5_check_server_response (priv, h, error); break; default: g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, "Server sent unexpected auth data"); } g_hash_table_unref (h); return ret; } static gboolean digest_md5_handle_success (WockyAuthHandler *handler, GError **error) { WockySaslDigestMd5 *self = WOCKY_SASL_DIGEST_MD5 (handler); WockySaslDigestMd5Private *priv = self->priv; if (priv->state == WOCKY_SASL_DIGEST_MD5_STATE_SENT_FINAL_RESPONSE) return TRUE; g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_INVALID_REPLY, "Server sent success before finishing authentication"); return FALSE; } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-loopback-stream.h0000664000175000017500000000446611720661341026435 0ustar00cassidycassidy00000000000000/* * wocky-loopback-stream.h - Header for WockyLoopbackStream * Copyright (C) 2009-2011 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_LOOPBACK_STREAM_H__ #define __WOCKY_LOOPBACK_STREAM_H__ #include #include G_BEGIN_DECLS typedef struct _WockyLoopbackStream WockyLoopbackStream; typedef struct _WockyLoopbackStreamClass WockyLoopbackStreamClass; typedef struct _WockyLoopbackStreamPrivate WockyLoopbackStreamPrivate; struct _WockyLoopbackStreamClass { GIOStreamClass parent_class; }; struct _WockyLoopbackStream { GIOStream parent; WockyLoopbackStreamPrivate *priv; }; GType wocky_loopback_stream_get_type (void); /* TYPE MACROS */ #define WOCKY_TYPE_LOOPBACK_STREAM \ (wocky_loopback_stream_get_type ()) #define WOCKY_LOOPBACK_STREAM(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_LOOPBACK_STREAM, \ WockyLoopbackStream)) #define WOCKY_LOOPBACK_STREAM_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_LOOPBACK_STREAM, \ WockyLoopbackStreamClass)) #define WOCKY_IS_LOOPBACK_STREAM(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_LOOPBACK_STREAM)) #define WOCKY_IS_LOOPBACK_STREAM_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_LOOPBACK_STREAM)) #define WOCKY_LOOPBACK_STREAM_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_LOOPBACK_STREAM, \ WockyLoopbackStreamClass)) GIOStream * wocky_loopback_stream_new (void); G_END_DECLS #endif /* #ifndef __WOCKY_LOOPBACK_STREAM_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-tls.c0000664000175000017500000016043312332440453024143 0ustar00cassidycassidy00000000000000/* * Wocky TLS integration - GNUTLS implementation * (just named -tls for historical reasons) * * Copyright © 2008 Christian Kellner, Samuel Cormier-Iijima * Copyright © 2008-2009 Codethink Limited * Copyright © 2009 Collabora Limited * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2 of the licence or (at * your option) any later version. * * Authors: Ryan Lortie * Christian Kellner * Samuel Cormier-Iijima * Vivek Dasmohapatra * * Upstream: git://git.gnome.org/gnio * Branched at: 42b00d143fcf644880456d06d3a20b6e990a7fa3 * "toss out everything that moved to glib" * * This file follows the original coding style from upstream, not house * collabora style: It is a copy of unmerged gnio TLS support with the * 'g' prefixes changes to 'wocky' and server-side TLS support added. */ /** * SECTION: wocky-tls * @title: Wocky GnuTLS TLS * @short_description: Establish TLS sessions * * The WOCKY_TLS_DEBUG_LEVEL environment variable can be used to print debug * output from GNU TLS. To enable it, set it to a value from 1 to 9. * Higher values will print more information. See the documentation of * gnutls_global_set_log_level for more details. * * Increasing the value past certain thresholds will also trigger increased * debugging output from within wocky-tls.c as well. * * The WOCKY_GNUTLS_OPTIONS environment variable can be set to a gnutls * priority string [See gnutls-cli(1) or the gnutls_priority_init docs] * to control most tls protocol details. An empty or unset value is roughly * equivalent to a priority string of "SECURE:+COMP-DEFLATE". */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-tls.h" #include #include #include #include #include #include #ifdef ENABLE_PREFER_STREAM_CIPHERS #define DEFAULT_TLS_OPTIONS \ /* start with nothing enabled by default */ \ "NONE:" \ /* enable all the normal algorithms */ \ "+VERS-TLS-ALL:+SIGN-ALL:+MAC-ALL:+CTYPE-ALL:+RSA:" \ /* prefer deflate compression, but fall back to null compression */ \ "+COMP-DEFLATE:+COMP-NULL:" \ /* our preferred stream ciphers */ \ "+ARCFOUR-128:+ARCFOUR-40:" \ /* all the other ciphers */ \ "+AES-128-CBC:+AES-256-CBC:+3DES-CBC:+DES-CBC:+RC2-40:" \ "+CAMELLIA-256-CBC:+CAMELLIA-128-CBC" #else #define DEFAULT_TLS_OPTIONS \ "NORMAL:" /* all secure algorithms */ \ "-COMP-NULL:" /* remove null compression */ \ "+COMP-DEFLATE:" /* prefer deflate */ \ "+COMP-NULL" /* fall back to null */ #endif #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_TLS #define DEBUG_HANDSHAKE_LEVEL 5 #define DEBUG_ASYNC_DETAIL_LEVEL 6 #define VERIFY_STRICT GNUTLS_VERIFY_DO_NOT_ALLOW_SAME #define VERIFY_NORMAL GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT #define VERIFY_LENIENT ( GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT | \ GNUTLS_VERIFY_ALLOW_ANY_X509_V1_CA_CRT | \ GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2 | \ GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5 | \ GNUTLS_VERIFY_DISABLE_TIME_CHECKS | \ GNUTLS_VERIFY_DISABLE_CA_SIGN ) #include "wocky-debug-internal.h" #include "wocky-utils.h" #include #include #include #include #include enum { PROP_S_NONE, PROP_S_STREAM, PROP_S_SERVER, PROP_S_DHBITS, PROP_S_KEYFILE, PROP_S_CERTFILE, }; enum { PROP_C_NONE, PROP_C_SESSION, }; enum { PROP_O_NONE, PROP_O_SESSION }; enum { PROP_I_NONE, PROP_I_SESSION }; typedef struct { gboolean active; gint io_priority; GCancellable *cancellable; GObject *source_object; GAsyncReadyCallback callback; gpointer user_data; gpointer source_tag; GError *error; } WockyTLSJob; typedef enum { WOCKY_TLS_OP_READ, WOCKY_TLS_OP_WRITE } WockyTLSOperation; typedef enum { WOCKY_TLS_OP_STATE_IDLE, WOCKY_TLS_OP_STATE_ACTIVE, WOCKY_TLS_OP_STATE_DONE } WockyTLSOpState; typedef struct { WockyTLSJob job; } WockyTLSJobHandshake; typedef struct { WockyTLSJob job; gconstpointer buffer; gsize count; } WockyTLSJobWrite; typedef struct { WockyTLSJob job; gpointer buffer; gsize count; } WockyTLSJobRead; typedef struct { WockyTLSOpState state; guint8 *buffer; gssize requested; gssize result; GError *error; } WockyTLSOp; typedef GIOStreamClass WockyTLSConnectionClass; typedef GObjectClass WockyTLSSessionClass; typedef GInputStreamClass WockyTLSInputStreamClass; typedef GOutputStreamClass WockyTLSOutputStreamClass; static gnutls_dh_params_t dh_0768 = NULL; static gnutls_dh_params_t dh_1024 = NULL; static gnutls_dh_params_t dh_2048 = NULL; static gnutls_dh_params_t dh_3072 = NULL; static gnutls_dh_params_t dh_4096 = NULL; struct _WockyTLSSession { GObject parent; GIOStream *stream; GCancellable *cancellable; GError *error; gboolean async; /* tls server support */ gboolean server; gnutls_dh_params_t dh_params; guint dh_bits; gchar *key_file; gchar *cert_file; /* frontend jobs */ WockyTLSJobHandshake handshake_job; WockyTLSJobRead read_job; WockyTLSJobWrite write_job; /* backend jobs */ WockyTLSOp read_op; WockyTLSOp write_op; gnutls_session_t session; gnutls_certificate_credentials gnutls_cert_cred; }; typedef struct { GInputStream parent; WockyTLSSession *session; } WockyTLSInputStream; typedef struct { GOutputStream parent; WockyTLSSession *session; } WockyTLSOutputStream; struct _WockyTLSConnection { GIOStream parent; WockyTLSSession *session; WockyTLSInputStream *input; WockyTLSOutputStream *output; }; static guint tls_debug_level = 0; static GType wocky_tls_input_stream_get_type (void); static GType wocky_tls_output_stream_get_type (void); G_DEFINE_TYPE (WockyTLSConnection, wocky_tls_connection, G_TYPE_IO_STREAM); G_DEFINE_TYPE (WockyTLSSession, wocky_tls_session, G_TYPE_OBJECT); G_DEFINE_TYPE (WockyTLSInputStream, wocky_tls_input_stream, G_TYPE_INPUT_STREAM); G_DEFINE_TYPE (WockyTLSOutputStream, wocky_tls_output_stream, G_TYPE_OUTPUT_STREAM); #define WOCKY_TYPE_TLS_INPUT_STREAM (wocky_tls_input_stream_get_type ()) #define WOCKY_TYPE_TLS_OUTPUT_STREAM (wocky_tls_output_stream_get_type ()) #define WOCKY_TLS_INPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ WOCKY_TYPE_TLS_INPUT_STREAM, \ WockyTLSInputStream)) #define WOCKY_TLS_OUTPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ WOCKY_TYPE_TLS_OUTPUT_STREAM, \ WockyTLSOutputStream)) static const gchar *hdesc_to_string (long desc) { #define HDESC(x) case GNUTLS_HANDSHAKE_##x: return #x; break; switch (desc) { HDESC (HELLO_REQUEST); HDESC (CLIENT_HELLO); HDESC (SERVER_HELLO); HDESC (CERTIFICATE_PKT); HDESC (SERVER_KEY_EXCHANGE); HDESC (CERTIFICATE_REQUEST); HDESC (SERVER_HELLO_DONE); HDESC (CERTIFICATE_VERIFY); HDESC (CLIENT_KEY_EXCHANGE); HDESC (FINISHED); HDESC (SUPPLEMENTAL); } return "Unknown State"; } static const gchar *error_to_string (long error) { const gchar *result; result = gnutls_strerror_name (error); if (result != NULL) return result; return "Unknown Error"; } static gboolean wocky_tls_set_error (GError **error, gssize result) { int code = (int) result; if (result < 0) g_set_error (error, WOCKY_TLS_ERROR, 0, "%d: %s", code, error_to_string (code)); return result < 0; } static GSimpleAsyncResult * wocky_tls_job_make_result (WockyTLSJob *job, gssize result) { if (result != GNUTLS_E_AGAIN) { GSimpleAsyncResult *simple; GError *error = NULL; simple = g_simple_async_result_new (job->source_object, job->callback, job->user_data, job->source_tag); if (job->error != NULL) { #ifdef WOCKY_TLS_STRICT_ERROR_ASSERTIONS g_assert (result == GNUTLS_E_PUSH_ERROR || result == GNUTLS_E_PULL_ERROR); #endif g_simple_async_result_set_from_error (simple, job->error); g_error_free (job->error); } else if (wocky_tls_set_error (&error, result)) { g_simple_async_result_set_from_error (simple, error); g_error_free (error); } if (job->cancellable != NULL) g_object_unref (job->cancellable); job->cancellable = NULL; g_object_unref (job->source_object); job->source_object = NULL; job->active = FALSE; return simple; } else { g_assert (job->active); return NULL; } } static void wocky_tls_job_result_gssize (WockyTLSJob *job, gssize result) { GSimpleAsyncResult *simple; if ((simple = wocky_tls_job_make_result (job, result))) { if (result >= 0) g_simple_async_result_set_op_res_gssize (simple, result); g_simple_async_result_complete (simple); g_object_unref (simple); } } static void wocky_tls_job_result_boolean (WockyTLSJob *job, gint result) { GSimpleAsyncResult *simple; if ((simple = wocky_tls_job_make_result (job, result))) { g_simple_async_result_complete (simple); g_object_unref (simple); } } static void wocky_tls_session_try_operation (WockyTLSSession *session, WockyTLSOperation operation) { if (session->handshake_job.job.active) { gint result; DEBUG ("session %p: async job handshake", session); session->async = TRUE; result = gnutls_handshake (session->session); g_assert (result != GNUTLS_E_INTERRUPTED); if (tls_debug_level >= DEBUG_HANDSHAKE_LEVEL) { gnutls_handshake_description_t i; gnutls_handshake_description_t o; DEBUG ("session %p: async job handshake: %d %s", session, result, error_to_string(result)); i = gnutls_handshake_get_last_in (session->session); o = gnutls_handshake_get_last_out (session->session); DEBUG ("session %p: async job handshake: { in: %s; out: %s }", session, hdesc_to_string (i), hdesc_to_string (o)); } session->async = FALSE; wocky_tls_job_result_boolean (&session->handshake_job.job, result); } else if (operation == WOCKY_TLS_OP_READ) { gssize result = 0; if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL) DEBUG ("async job OP_READ"); g_assert (session->read_job.job.active); /* If the read result is 0, the remote end disconnected us, no need to * pull data through gnutls_record_recv in that case */ if (session->read_op.result != 0) { session->async = TRUE; result = gnutls_record_recv (session->session, session->read_job.buffer, session->read_job.count); g_assert (result != GNUTLS_E_INTERRUPTED); session->async = FALSE; } wocky_tls_job_result_gssize (&session->read_job.job, result); } else { gssize result; if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL) DEBUG ("async job OP_WRITE: %"G_GSIZE_FORMAT, session->write_job.count); g_assert (operation == WOCKY_TLS_OP_WRITE); g_assert (session->write_job.job.active); session->async = TRUE; result = gnutls_record_send (session->session, session->write_job.buffer, session->write_job.count); g_assert (result != GNUTLS_E_INTERRUPTED); session->async = FALSE; wocky_tls_job_result_gssize (&session->write_job.job, result); } } static void wocky_tls_job_start (WockyTLSJob *job, gpointer source_object, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag) { g_assert (job->active == FALSE); g_assert (job->cancellable == NULL); /* this is always a circular reference, so it will keep the * session alive for as long as the job is running. */ job->source_object = g_object_ref (source_object); job->io_priority = io_priority; if (cancellable != NULL) job->cancellable = g_object_ref (cancellable); job->callback = callback; job->user_data = user_data; job->source_tag = source_tag; job->error = NULL; job->active = TRUE; } WockyTLSConnection * wocky_tls_session_handshake (WockyTLSSession *session, GCancellable *cancellable, GError **error) { gint result; DEBUG ("sync job handshake"); session->error = NULL; session->cancellable = cancellable; result = gnutls_handshake (session->session); g_assert (result != GNUTLS_E_INTERRUPTED); g_assert (result != GNUTLS_E_AGAIN); session->cancellable = NULL; if (tls_debug_level >= DEBUG_HANDSHAKE_LEVEL) DEBUG ("sync job handshake: %d %s", result, error_to_string (result)); if (session->error != NULL) { g_assert (result == GNUTLS_E_PULL_ERROR || result == GNUTLS_E_PUSH_ERROR); g_propagate_error (error, session->error); return NULL; } else if (wocky_tls_set_error (error, result)) return NULL; return g_object_new (WOCKY_TYPE_TLS_CONNECTION, "session", session, NULL); } /* ************************************************************************* */ /* adding CA certificates lists for peer certificate verification */ void wocky_tls_session_add_ca (WockyTLSSession *session, const gchar *ca_path) { int n = 0; struct stat target; DEBUG ("adding CA CERT path '%s'", (gchar *) ca_path); if (stat (ca_path, &target) != 0) { DEBUG ("CA file '%s': stat failed)", ca_path); return; } if (S_ISDIR (target.st_mode)) { DIR *dir; struct dirent *entry; if ((dir = opendir (ca_path)) == NULL) return; for (entry = readdir (dir); entry != NULL; entry = readdir (dir)) { struct stat file; gchar *path = g_build_path ("/", ca_path, entry->d_name, NULL); if ((stat (path, &file) == 0) && S_ISREG (file.st_mode)) n += gnutls_certificate_set_x509_trust_file ( session->gnutls_cert_cred, path, GNUTLS_X509_FMT_PEM); g_free (path); } DEBUG ("+ %s: %d certs from dir", ca_path, n); closedir (dir); } else if (S_ISREG (target.st_mode)) { n = gnutls_certificate_set_x509_trust_file (session->gnutls_cert_cred, ca_path, GNUTLS_X509_FMT_PEM); DEBUG ("+ %s: %d certs from file", ca_path, n); } } void wocky_tls_session_add_crl (WockyTLSSession *session, const gchar *crl_path) { int n = 0; struct stat target; DEBUG ("adding CRL CERT path '%s'", (gchar *) crl_path); if (stat (crl_path, &target) != 0) { DEBUG ("CRL file '%s': stat failed)", crl_path); return; } if (S_ISDIR (target.st_mode)) { DIR *dir; struct dirent *entry; if ((dir = opendir (crl_path)) == NULL) return; for (entry = readdir (dir); entry != NULL; entry = readdir (dir)) { struct stat file; gchar *path = g_build_path ("/", crl_path, entry->d_name, NULL); if ((stat (path, &file) == 0) && S_ISREG (file.st_mode)) { int x = gnutls_certificate_set_x509_crl_file ( session->gnutls_cert_cred, path, GNUTLS_X509_FMT_PEM); if (x < 0) DEBUG ("Error loading %s: %d %s", path, x, gnutls_strerror (x)); else n += x; } g_free (path); } DEBUG ("+ %s: %d certs from dir", crl_path, n); closedir (dir); } else if (S_ISREG (target.st_mode)) { n = gnutls_certificate_set_x509_trust_file (session->gnutls_cert_cred, crl_path, GNUTLS_X509_FMT_PEM); if (n < 0) DEBUG ("Error loading '%s': %d %s", crl_path, n, gnutls_strerror(n)); else DEBUG ("+ %s: %d certs from file", crl_path, n); } } /* ************************************************************************* */ void wocky_tls_session_handshake_async (WockyTLSSession *session, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { wocky_tls_job_start (&session->handshake_job.job, session, io_priority, cancellable, callback, user_data, wocky_tls_session_handshake_async); wocky_tls_session_try_operation (session, 0); } WockyTLSConnection * wocky_tls_session_handshake_finish (WockyTLSSession *session, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); { GObject *source_object; source_object = g_async_result_get_source_object (result); g_object_unref (source_object); g_return_val_if_fail (G_OBJECT (session) == source_object, NULL); } g_return_val_if_fail (wocky_tls_session_handshake_async == g_simple_async_result_get_source_tag (simple), NULL); if (g_simple_async_result_propagate_error (simple, error)) return NULL; DEBUG ("connection OK"); return g_object_new (WOCKY_TYPE_TLS_CONNECTION, "session", session, NULL); } GPtrArray * wocky_tls_session_get_peers_certificate (WockyTLSSession *session, WockyTLSCertType *type) { guint idx; guint n_peers; const gnutls_datum_t *peers = NULL; GPtrArray *certificates; peers = gnutls_certificate_get_peers (session->session, &n_peers); if (peers == NULL) return NULL; certificates = g_ptr_array_new_with_free_func ((GDestroyNotify) g_array_unref); for (idx = 0; idx < n_peers; idx++) { GArray *cert = g_array_sized_new (TRUE, TRUE, sizeof (guchar), peers[idx].size); g_array_append_vals (cert, peers[idx].data, peers[idx].size); g_ptr_array_add (certificates, cert); } if (type != NULL) { switch (gnutls_certificate_type_get (session->session)) { case GNUTLS_CRT_X509: *type = WOCKY_TLS_CERT_TYPE_X509; break; case GNUTLS_CRT_OPENPGP: *type = WOCKY_TLS_CERT_TYPE_OPENPGP; break; default: *type = WOCKY_TLS_CERT_TYPE_NONE; break; } } return certificates; } static inline gboolean contains_illegal_wildcard (const char *name, int size) { if (name[0] == '*' && name[1] == '.') { name += 2; size -= 2; } if (memchr (name, '*', size) != NULL) return TRUE; return FALSE; } #define OID_X520_COMMON_NAME "2.5.4.3" static gboolean cert_names_are_valid (gnutls_x509_crt_t cert) { char name[256]; size_t size; gboolean found = FALSE; int type = 0; int i = 0; /* GNUTLS allows wildcards anywhere within the certificate name, but XMPP only * permits a single leading "*.". */ for (i = 0; type >= 0; i++) { size = sizeof (name); type = gnutls_x509_crt_get_subject_alt_name (cert, i, name, &size, NULL); switch (type) { case GNUTLS_SAN_DNSNAME: case GNUTLS_SAN_IPADDRESS: found = TRUE; if (contains_illegal_wildcard (name, size)) return FALSE; break; default: break; } } if (!found) { size = sizeof (name); /* cert has no names at all? bizarro! */ if (gnutls_x509_crt_get_dn_by_oid (cert, OID_X520_COMMON_NAME, 0, 0, name, &size) < 0) return FALSE; found = TRUE; if (contains_illegal_wildcard (name, size)) return FALSE; } /* found a name, wasn't a duff wildcard */ return found; } int wocky_tls_session_verify_peer (WockyTLSSession *session, const gchar *peername, GStrv extra_identities, WockyTLSVerificationLevel level, WockyTLSCertStatus *status) { int rval = -1; guint peer_cert_status = 0; gboolean peer_name_ok = TRUE; gnutls_certificate_verify_flags check; /* list gnutls cert error conditions in descending order of noteworthiness * * and map them to wocky cert error conditions */ static const struct { gnutls_certificate_status_t gnutls; WockyTLSCertStatus wocky; } status_map[] = { { GNUTLS_CERT_REVOKED, WOCKY_TLS_CERT_REVOKED }, { GNUTLS_CERT_NOT_ACTIVATED, WOCKY_TLS_CERT_NOT_ACTIVE }, { GNUTLS_CERT_EXPIRED, WOCKY_TLS_CERT_EXPIRED }, { GNUTLS_CERT_SIGNER_NOT_FOUND, WOCKY_TLS_CERT_SIGNER_UNKNOWN }, { GNUTLS_CERT_SIGNER_NOT_CA, WOCKY_TLS_CERT_SIGNER_UNAUTHORISED }, { GNUTLS_CERT_INSECURE_ALGORITHM, WOCKY_TLS_CERT_INSECURE }, { GNUTLS_CERT_INVALID, WOCKY_TLS_CERT_INVALID }, { ~((long) 0), WOCKY_TLS_CERT_UNKNOWN_ERROR }, { 0, WOCKY_TLS_CERT_OK } }; g_assert (status != NULL); *status = WOCKY_TLS_CERT_OK; switch (level) { case WOCKY_TLS_VERIFY_STRICT: check = VERIFY_STRICT; break; case WOCKY_TLS_VERIFY_NORMAL: check = VERIFY_NORMAL; break; case WOCKY_TLS_VERIFY_LENIENT: check = VERIFY_LENIENT; break; default: g_warn_if_reached (); check = VERIFY_STRICT; break; } DEBUG ("setting gnutls verify flags level to: %s", wocky_enum_to_nick (WOCKY_TYPE_TLS_VERIFICATION_LEVEL, level)); gnutls_certificate_set_verify_flags (session->gnutls_cert_cred, check); rval = gnutls_certificate_verify_peers2 (session->session, &peer_cert_status); if (rval != GNUTLS_E_SUCCESS) { switch (rval) { case GNUTLS_E_NO_CERTIFICATE_FOUND: case GNUTLS_E_INVALID_REQUEST: *status = WOCKY_TLS_CERT_NO_CERTIFICATE; break; case GNUTLS_E_INSUFFICIENT_CREDENTIALS: *status = WOCKY_TLS_CERT_INSECURE; break; case GNUTLS_E_CONSTRAINT_ERROR: *status = WOCKY_TLS_CERT_MAYBE_DOS; break; case GNUTLS_E_MEMORY_ERROR: *status = WOCKY_TLS_CERT_INTERNAL_ERROR; break; default: *status = WOCKY_TLS_CERT_UNKNOWN_ERROR; } return rval; } /* if we get this far, we have a structurally valid certificate * * signed by _someone_: check the hostname matches the peername */ if (peername != NULL || extra_identities != NULL) { const gnutls_datum_t *peers; guint n_peers; gnutls_x509_crt_t x509; gnutls_openpgp_crt_t opgp; /* we know these ops must succeed, or verify_peers2 would have * * failed before we got here: We just need to duplicate a bit * * of what it does: */ peers = gnutls_certificate_get_peers (session->session, &n_peers); switch (gnutls_certificate_type_get (session->session)) { case GNUTLS_CRT_X509: DEBUG ("checking X509 cert"); if ((rval = gnutls_x509_crt_init (&x509)) == GNUTLS_E_SUCCESS) { gnutls_x509_crt_import (x509, &peers[0], GNUTLS_X509_FMT_DER); if (peername != NULL) { if (!cert_names_are_valid (x509)) { rval = 0; } else { rval = gnutls_x509_crt_check_hostname (x509, peername); DEBUG ("gnutls_x509_crt_check_hostname: %s -> %d", peername, rval); } } else { rval = 0; } if (rval == 0 && extra_identities != NULL) { if (!cert_names_are_valid (x509)) { rval = 0; } else { gint i; for (i = 0; extra_identities[i] != NULL; i++) { rval = gnutls_x509_crt_check_hostname (x509, extra_identities[i]); DEBUG ("gnutls_x509_crt_check_hostname: %s -> %d", extra_identities[i], rval); if (rval != 0) break; } } } rval = (rval == 0) ? -1 : GNUTLS_E_SUCCESS; gnutls_x509_crt_deinit (x509); } break; case GNUTLS_CRT_OPENPGP: DEBUG ("checking PGP cert"); if ((rval = gnutls_openpgp_crt_init (&opgp)) == GNUTLS_E_SUCCESS) { gnutls_openpgp_crt_import (opgp, &peers[0], GNUTLS_OPENPGP_FMT_RAW); rval = gnutls_openpgp_crt_check_hostname (opgp, peername); DEBUG ("gnutls_openpgp_crt_check_hostname: %s -> %d", peername, rval); if (peername != NULL) { rval = gnutls_openpgp_crt_check_hostname (opgp, peername); DEBUG ("gnutls_openpgp_crt_check_hostname: %s -> %d", peername, rval); } else { rval = 0; } if (rval == 0 && extra_identities != NULL) { gint i; for (i = 0; extra_identities[i] != NULL; i++) { rval = gnutls_openpgp_crt_check_hostname (opgp, extra_identities[i]); DEBUG ("gnutls_openpgp_crt_check_hostname: %s -> %d", extra_identities[i], rval); if (rval != 0) break; } } rval = (rval == 0) ? -1 : GNUTLS_E_SUCCESS; gnutls_openpgp_crt_deinit (opgp); } break; default: /* theoretically, this can't happen if ...verify_peers2 is working: */ DEBUG ("unknown cert type!"); rval = GNUTLS_E_INVALID_REQUEST; } peer_name_ok = (rval == GNUTLS_E_SUCCESS); } DEBUG ("peer_name_ok: %d", peer_name_ok ); /* if the hostname didn't match, we can just bail out with an error here * * otherwise we need to figure out which error (if any) our verification * * call failed with: */ if (!peer_name_ok) *status = WOCKY_TLS_CERT_NAME_MISMATCH; else { /* Gnutls cert checking can return multiple errors bitwise &ed together * * but we are realy only interested in the "most important" error: */ int x; *status = WOCKY_TLS_CERT_OK; for (x = 0; status_map[x].gnutls != 0; x++) { DEBUG ("checking gnutls error %d", status_map[x].gnutls); if (peer_cert_status & status_map[x].gnutls) { DEBUG ("gnutls error %d set", status_map[x].gnutls); *status = status_map[x].wocky; rval = GNUTLS_E_CERTIFICATE_ERROR; break; } } } return rval; } static gssize wocky_tls_input_stream_read (GInputStream *stream, void *buffer, gsize count, GCancellable *cancellable, GError **error) { WockyTLSSession *session = WOCKY_TLS_INPUT_STREAM (stream)->session; gssize result; session->cancellable = cancellable; result = gnutls_record_recv (session->session, buffer, count); g_assert (result != GNUTLS_E_INTERRUPTED); g_assert (result != GNUTLS_E_AGAIN); session->cancellable = NULL; if (session->error != NULL) { g_assert (result == GNUTLS_E_PULL_ERROR); g_propagate_error (error, session->error); return -1; } else if (wocky_tls_set_error (error, result)) return -1; return result; } static void wocky_tls_input_stream_read_async (GInputStream *stream, void *buffer, gsize count, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyTLSSession *session = WOCKY_TLS_INPUT_STREAM (stream)->session; wocky_tls_job_start (&session->read_job.job, stream, io_priority, cancellable, callback, user_data, wocky_tls_input_stream_read_async); session->read_job.buffer = buffer; session->read_job.count = count; wocky_tls_session_try_operation (session, WOCKY_TLS_OP_READ); } static gssize wocky_tls_input_stream_read_finish (GInputStream *stream, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); { GObject *source_object; source_object = g_async_result_get_source_object (result); g_object_unref (source_object); g_return_val_if_fail (G_OBJECT (stream) == source_object, -1); } g_return_val_if_fail (wocky_tls_input_stream_read_async == g_simple_async_result_get_source_tag (simple), -1); if (g_simple_async_result_propagate_error (simple, error)) return -1; return g_simple_async_result_get_op_res_gssize (simple); } static gssize wocky_tls_output_stream_write (GOutputStream *stream, const void *buffer, gsize count, GCancellable *cancellable, GError **error) { WockyTLSSession *session = WOCKY_TLS_OUTPUT_STREAM (stream)->session; gssize result; session->cancellable = cancellable; result = gnutls_record_send (session->session, buffer, count); g_assert (result != GNUTLS_E_INTERRUPTED); g_assert (result != GNUTLS_E_AGAIN); session->cancellable = NULL; if (session->error != NULL) { g_assert (result == GNUTLS_E_PUSH_ERROR); g_propagate_error (error, session->error); return -1; } else if (wocky_tls_set_error (error, result)) return -1; return result; } static void wocky_tls_output_stream_write_async (GOutputStream *stream, const void *buffer, gsize count, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyTLSSession *session = WOCKY_TLS_OUTPUT_STREAM (stream)->session; wocky_tls_job_start (&session->write_job.job, stream, io_priority, cancellable, callback, user_data, wocky_tls_output_stream_write_async); session->write_job.buffer = buffer; session->write_job.count = count; wocky_tls_session_try_operation (session, WOCKY_TLS_OP_WRITE); } static gssize wocky_tls_output_stream_write_finish (GOutputStream *stream, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); { GObject *source_object; source_object = g_async_result_get_source_object (result); g_object_unref (source_object); g_return_val_if_fail (G_OBJECT (stream) == source_object, -1); } g_return_val_if_fail (wocky_tls_output_stream_write_async == g_simple_async_result_get_source_tag (simple), -1); if (g_simple_async_result_propagate_error (simple, error)) return -1; return g_simple_async_result_get_op_res_gssize (simple); } static void wocky_tls_output_stream_init (WockyTLSOutputStream *stream) { } static void wocky_tls_input_stream_init (WockyTLSInputStream *stream) { } static void wocky_tls_output_stream_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { WockyTLSOutputStream *stream = WOCKY_TLS_OUTPUT_STREAM (object); switch (prop_id) { case PROP_C_SESSION: stream->session = g_value_dup_object (value); break; default: g_assert_not_reached (); } } static void wocky_tls_output_stream_constructed (GObject *object) { WockyTLSOutputStream *stream = WOCKY_TLS_OUTPUT_STREAM (object); g_assert (stream->session); } static void wocky_tls_output_stream_finalize (GObject *object) { WockyTLSOutputStream *stream = WOCKY_TLS_OUTPUT_STREAM (object); g_object_unref (stream->session); G_OBJECT_CLASS (wocky_tls_output_stream_parent_class) ->finalize (object); } static void wocky_tls_output_stream_class_init (GOutputStreamClass *class) { GObjectClass *obj_class = G_OBJECT_CLASS (class); class->write_fn = wocky_tls_output_stream_write; class->write_async = wocky_tls_output_stream_write_async; class->write_finish = wocky_tls_output_stream_write_finish; obj_class->set_property = wocky_tls_output_stream_set_property; obj_class->constructed = wocky_tls_output_stream_constructed; obj_class->finalize = wocky_tls_output_stream_finalize; g_object_class_install_property (obj_class, PROP_O_SESSION, g_param_spec_object ("session", "TLS session", "the TLS session object for this stream", WOCKY_TYPE_TLS_SESSION, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void wocky_tls_input_stream_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { WockyTLSInputStream *stream = WOCKY_TLS_INPUT_STREAM (object); switch (prop_id) { case PROP_C_SESSION: stream->session = g_value_dup_object (value); break; default: g_assert_not_reached (); } } static void wocky_tls_input_stream_constructed (GObject *object) { WockyTLSInputStream *stream = WOCKY_TLS_INPUT_STREAM (object); g_assert (stream->session); } static void wocky_tls_input_stream_finalize (GObject *object) { WockyTLSInputStream *stream = WOCKY_TLS_INPUT_STREAM (object); g_object_unref (stream->session); G_OBJECT_CLASS (wocky_tls_input_stream_parent_class) ->finalize (object); } static void wocky_tls_input_stream_class_init (GInputStreamClass *class) { GObjectClass *obj_class = G_OBJECT_CLASS (class); class->read_fn = wocky_tls_input_stream_read; class->read_async = wocky_tls_input_stream_read_async; class->read_finish = wocky_tls_input_stream_read_finish; obj_class->set_property = wocky_tls_input_stream_set_property; obj_class->constructed = wocky_tls_input_stream_constructed; obj_class->finalize = wocky_tls_input_stream_finalize; g_object_class_install_property (obj_class, PROP_I_SESSION, g_param_spec_object ("session", "TLS session", "the TLS session object for this stream", WOCKY_TYPE_TLS_SESSION, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void wocky_tls_connection_init (WockyTLSConnection *connection) { } static void wocky_tls_session_read_ready (GObject *object, GAsyncResult *result, gpointer user_data) { WockyTLSSession *session = WOCKY_TLS_SESSION (user_data); g_assert (session->read_op.state == WOCKY_TLS_OP_STATE_ACTIVE); session->read_op.result = g_input_stream_read_finish (G_INPUT_STREAM (object), result, &session->read_op.error); session->read_op.state = WOCKY_TLS_OP_STATE_DONE; /* don't recurse if the async handler is already running */ if (!session->async) wocky_tls_session_try_operation (session, WOCKY_TLS_OP_READ); } static void wocky_tls_session_write_ready (GObject *object, GAsyncResult *result, gpointer user_data) { WockyTLSSession *session = WOCKY_TLS_SESSION (user_data); gssize ret; g_assert (session->write_op.state == WOCKY_TLS_OP_STATE_ACTIVE); ret = g_output_stream_write_finish (G_OUTPUT_STREAM (object), result, &session->write_op.error); if (ret > 0) { session->write_op.result += ret; if (session->write_op.result < session->write_op.requested) { GOutputStream *stream; WockyTLSJob *active_job; stream = g_io_stream_get_output_stream (session->stream); if (session->handshake_job.job.active) active_job = &session->handshake_job.job; else active_job = &session->write_job.job; g_output_stream_write_async (stream, session->write_op.buffer + session->write_op.result, session->write_op.requested - session->write_op.result, active_job->io_priority, active_job->cancellable, wocky_tls_session_write_ready, session); return; } } else { /* Error or EOF, we're done */ session->write_op.result = ret; } session->write_op.state = WOCKY_TLS_OP_STATE_DONE; /* don't recurse if the async handler is already running */ if (!session->async) wocky_tls_session_try_operation (session, WOCKY_TLS_OP_WRITE); } static ssize_t wocky_tls_session_push_func (gpointer user_data, const void *buffer, size_t count) { WockyTLSSession *session = WOCKY_TLS_SESSION (user_data); GOutputStream *stream; stream = g_io_stream_get_output_stream (session->stream); if (session->async) { WockyTLSJob *active_job; g_assert (session->handshake_job.job.active || session->write_job.job.active); if (session->handshake_job.job.active) active_job = &session->handshake_job.job; else active_job = &session->write_job.job; g_assert (active_job->active); if (session->write_op.state == WOCKY_TLS_OP_STATE_IDLE) { session->write_op.state = WOCKY_TLS_OP_STATE_ACTIVE; session->write_op.buffer = g_memdup (buffer, count); session->write_op.requested = count; session->write_op.error = NULL; session->write_op.result = 0; g_output_stream_write_async (stream, session->write_op.buffer, session->write_op.requested, active_job->io_priority, active_job->cancellable, wocky_tls_session_write_ready, session); if G_UNLIKELY (session->write_op.state != WOCKY_TLS_OP_STATE_ACTIVE) g_warning ("The underlying stream '%s' used by the WockyTLSSession " "called the GAsyncResultCallback recursively. This " "is an error in the underlying implementation: in " "some cases it may lead to unbounded recursion. " "Result callbacks should always be dispatched from " "the mainloop.", G_OBJECT_TYPE_NAME (stream)); } g_assert (session->write_op.state != WOCKY_TLS_OP_STATE_IDLE); g_assert_cmpint (session->write_op.requested, ==, count); g_assert (memcmp (session->write_op.buffer, buffer, count) == 0); if (session->write_op.state == WOCKY_TLS_OP_STATE_DONE) { session->write_op.state = WOCKY_TLS_OP_STATE_IDLE; g_free (session->write_op.buffer); if (session->write_op.result < 0) { active_job->error = session->write_op.error; gnutls_transport_set_errno (session->session, EIO); return -1; } else { g_assert_cmpint (session->write_op.result, <=, count); return session->write_op.result; } } gnutls_transport_set_errno (session->session, EAGAIN); return -1; } else { gssize result; result = g_output_stream_write (stream, buffer, count, session->cancellable, &session->error); if (result < 0) gnutls_transport_set_errno (session->session, EIO); return result; } } static ssize_t wocky_tls_session_pull_func (gpointer user_data, void *buffer, size_t count) { WockyTLSSession *session = WOCKY_TLS_SESSION (user_data); GInputStream *stream; stream = g_io_stream_get_input_stream (session->stream); if (session->async) { WockyTLSJob *active_job; g_assert (session->handshake_job.job.active || session->read_job.job.active); if (session->handshake_job.job.active) active_job = &session->handshake_job.job; else active_job = &session->read_job.job; g_assert (active_job->active); if (session->read_op.state == WOCKY_TLS_OP_STATE_IDLE) { session->read_op.state = WOCKY_TLS_OP_STATE_ACTIVE; session->read_op.buffer = g_malloc (count); session->read_op.requested = count; session->read_op.error = NULL; g_input_stream_read_async (stream, session->read_op.buffer, session->read_op.requested, active_job->io_priority, active_job->cancellable, wocky_tls_session_read_ready, session); if G_UNLIKELY (session->read_op.state != WOCKY_TLS_OP_STATE_ACTIVE) g_warning ("The underlying stream '%s' used by the WockyTLSSession " "called the GAsyncResultCallback recursively. This " "is an error in the underlying implementation: in " "some cases it may lead to unbounded recursion. " "Result callbacks should always be dispatched from " "the mainloop.", G_OBJECT_TYPE_NAME (stream)); } g_assert (session->read_op.state != WOCKY_TLS_OP_STATE_IDLE); g_assert_cmpint (session->read_op.requested, ==, count); if (session->read_op.state == WOCKY_TLS_OP_STATE_DONE) { session->read_op.state = WOCKY_TLS_OP_STATE_IDLE; if (session->read_op.result < 0) { g_free (session->read_op.buffer); session->read_op.buffer = NULL; active_job->error = session->read_op.error; gnutls_transport_set_errno (session->session, EIO); return -1; } else { g_assert_cmpint (session->read_op.result, <=, count); memcpy (buffer, session->read_op.buffer, session->read_op.result); g_free (session->read_op.buffer); session->read_op.buffer = NULL; return session->read_op.result; } } gnutls_transport_set_errno (session->session, EAGAIN); return -1; } else { gssize result; result = g_input_stream_read (stream, buffer, count, session->cancellable, &session->error); if (result < 0) gnutls_transport_set_errno (session->session, EIO); return result; } } static void tls_debug (int level, const char *msg) { DEBUG ("[%d] [%02d] %s", getpid(), level, msg); } static void wocky_tls_session_init (WockyTLSSession *session) { const char *level; guint64 lvl = 0; static gsize initialised; if G_UNLIKELY (g_once_init_enter (&initialised)) { gnutls_global_init (); gnutls_global_set_log_function (tls_debug); g_once_init_leave (&initialised, 1); } if ((level = g_getenv ("WOCKY_TLS_DEBUG_LEVEL")) != NULL) lvl = g_ascii_strtoull (level, NULL, 10); tls_debug_level = lvl; gnutls_global_set_log_level (lvl); } static void wocky_tls_session_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { WockyTLSSession *session = WOCKY_TLS_SESSION (object); switch (prop_id) { case PROP_S_STREAM: session->stream = g_value_dup_object (value); break; case PROP_S_SERVER: session->server = g_value_get_boolean (value); break; case PROP_S_DHBITS: session->dh_bits = g_value_get_uint (value); break; case PROP_S_KEYFILE: session->key_file = g_value_dup_string (value); break; case PROP_S_CERTFILE: session->cert_file = g_value_dup_string (value); break; default: g_assert_not_reached (); } } static const char * tls_options (void) { const char *options = g_getenv ("WOCKY_GNUTLS_OPTIONS"); return (options != NULL && *options != '\0') ? options : DEFAULT_TLS_OPTIONS; } static void wocky_tls_session_constructed (GObject *object) { WockyTLSSession *session = WOCKY_TLS_SESSION (object); gboolean server = session->server; gint code; const gchar *opt = tls_options (); const gchar *pos = NULL; /* gnutls_handshake_set_private_extensions (session->session, 1); */ gnutls_certificate_allocate_credentials (&(session->gnutls_cert_cred)); /* I think this all needs to be done per connection: conceivably the DH parameters could be moved to the global section above, but IANA cryptographer */ if (server) { gnutls_dh_params_t *dhp; if ((session->key_file != NULL) && (session->cert_file != NULL)) { DEBUG ("cert/key pair: %s/%s", session->cert_file, session->key_file); gnutls_certificate_set_x509_key_file (session->gnutls_cert_cred, session->cert_file, session->key_file, GNUTLS_X509_FMT_PEM); } switch (session->dh_bits) { case 768: dhp = &dh_0768; break; case 1024: dhp = &dh_1024; break; case 2048: dhp = &dh_2048; break; case 3072: dhp = &dh_3072; break; case 4096: dhp = &dh_4096; break; default: dhp = &dh_1024; break; } if (*dhp == NULL) { DEBUG ("Initialising DH parameters (%d bits)", session->dh_bits); gnutls_dh_params_init (dhp); gnutls_dh_params_generate2 (*dhp, session->dh_bits); } session->dh_params = *dhp; gnutls_certificate_set_dh_params (session->gnutls_cert_cred, *dhp); gnutls_init (&session->session, GNUTLS_SERVER); } else gnutls_init (&session->session, GNUTLS_CLIENT); code = gnutls_priority_set_direct (session->session, opt, &pos); if (code != GNUTLS_E_SUCCESS) { DEBUG ("could not set priority string: %s", error_to_string (code)); DEBUG (" '%s'", opt); if (pos >= opt) DEBUG (" %*s^", (int) (pos - opt), ""); } else { DEBUG ("priority set to: '%s'", opt); } code = gnutls_credentials_set (session->session, GNUTLS_CRD_CERTIFICATE, session->gnutls_cert_cred); if (code != GNUTLS_E_SUCCESS) DEBUG ("could not set credentials: %s", error_to_string (code)); gnutls_transport_set_push_function (session->session, wocky_tls_session_push_func); gnutls_transport_set_pull_function (session->session, wocky_tls_session_pull_func); gnutls_transport_set_ptr (session->session, session); g_assert (session->stream); } static void wocky_tls_session_finalize (GObject *object) { WockyTLSSession *session = WOCKY_TLS_SESSION (object); gnutls_deinit (session->session); gnutls_certificate_free_credentials (session->gnutls_cert_cred); g_object_unref (session->stream); G_OBJECT_CLASS (wocky_tls_session_parent_class) ->finalize (object); } static void wocky_tls_session_dispose (GObject *object) { WockyTLSSession *session = WOCKY_TLS_SESSION (object); g_free (session->key_file); session->key_file = NULL; g_free (session->cert_file); session->cert_file = NULL; g_free (session->read_op.buffer); session->read_op.buffer = NULL; G_OBJECT_CLASS (wocky_tls_session_parent_class)->dispose (object); } static void wocky_tls_session_class_init (GObjectClass *class) { class->set_property = wocky_tls_session_set_property; class->constructed = wocky_tls_session_constructed; class->finalize = wocky_tls_session_finalize; class->dispose = wocky_tls_session_dispose; g_object_class_install_property (class, PROP_S_STREAM, g_param_spec_object ("base-stream", "base stream", "the stream that TLS communicates over", G_TYPE_IO_STREAM, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property (class, PROP_S_SERVER, g_param_spec_boolean ("server", "server", "whether this is a server", FALSE, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property (class, PROP_S_DHBITS, g_param_spec_uint ("dh-bits", "Diffie-Hellman bits", "Diffie-Hellmann bits: 768, 1024, 2048, 3072 0r 4096", 768, 4096, 1024, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property (class, PROP_S_KEYFILE, g_param_spec_string ("x509-key", "x509 key", "x509 PEM key file", NULL, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property (class, PROP_S_CERTFILE, g_param_spec_string ("x509-cert", "x509 certificate", "x509 PEM certificate file", NULL, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void wocky_tls_connection_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { WockyTLSConnection *connection = WOCKY_TLS_CONNECTION (object); switch (prop_id) { case PROP_C_SESSION: connection->session = g_value_dup_object (value); break; default: g_assert_not_reached (); } } static gboolean wocky_tls_connection_close (GIOStream *stream, GCancellable *cancellable, GError **error) { WockyTLSConnection *connection = WOCKY_TLS_CONNECTION (stream); return g_io_stream_close (connection->session->stream, cancellable, error); } static GInputStream * wocky_tls_connection_get_input_stream (GIOStream *io_stream) { WockyTLSConnection *connection = WOCKY_TLS_CONNECTION (io_stream); if (connection->input == NULL) connection->input = g_object_new (WOCKY_TYPE_TLS_INPUT_STREAM, "session", connection->session, NULL); return (GInputStream *)connection->input; } static GOutputStream * wocky_tls_connection_get_output_stream (GIOStream *io_stream) { WockyTLSConnection *connection = WOCKY_TLS_CONNECTION (io_stream); if (connection->output == NULL) connection->output = g_object_new (WOCKY_TYPE_TLS_OUTPUT_STREAM, "session", connection->session, NULL); return (GOutputStream *)connection->output; } static void wocky_tls_connection_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { switch (prop_id) { default: g_assert_not_reached (); } } static void wocky_tls_connection_constructed (GObject *object) { WockyTLSConnection *connection = WOCKY_TLS_CONNECTION (object); g_assert (connection->session); } static void wocky_tls_connection_finalize (GObject *object) { WockyTLSConnection *connection = WOCKY_TLS_CONNECTION (object); g_object_unref (connection->session); if (connection->input != NULL) g_object_unref (connection->input); if (connection->output != NULL) g_object_unref (connection->output); G_OBJECT_CLASS (wocky_tls_connection_parent_class) ->finalize (object); } static void wocky_tls_connection_class_init (WockyTLSConnectionClass *class) { GObjectClass *gobject_class = G_OBJECT_CLASS (class); GIOStreamClass *stream_class = G_IO_STREAM_CLASS (class); gobject_class->get_property = wocky_tls_connection_get_property; gobject_class->set_property = wocky_tls_connection_set_property; gobject_class->constructed = wocky_tls_connection_constructed; gobject_class->finalize = wocky_tls_connection_finalize; g_object_class_install_property (gobject_class, PROP_C_SESSION, g_param_spec_object ("session", "TLS session", "the TLS session object for this connection", WOCKY_TYPE_TLS_SESSION, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); stream_class->get_input_stream = wocky_tls_connection_get_input_stream; stream_class->get_output_stream = wocky_tls_connection_get_output_stream; stream_class->close_fn = wocky_tls_connection_close; } WockyTLSSession * wocky_tls_session_new (GIOStream *stream) { return g_object_new (WOCKY_TYPE_TLS_SESSION, "base-stream", stream, "server", FALSE, NULL); } /** * wocky_tls_session_server_new: * @stream: a GIOStream on which we expect to receive the client TLS handshake * @dhbits: size of the DH parameters (see gnutls for valid settings) * @key: the path to the X509 PEM key file * @cert: the path to the X509 PEM certificate * * Create a new TLS server session * * Returns: a #WockyTLSSession object */ WockyTLSSession * wocky_tls_session_server_new (GIOStream *stream, guint dhbits, const gchar* key, const gchar* cert) { if (dhbits == 0) dhbits = 1024; return g_object_new (WOCKY_TYPE_TLS_SESSION, "base-stream", stream, "dh-bits", dhbits, "x509-key", key, "x509-cert", cert, "server", TRUE, NULL); } /* this file is "borrowed" from an unmerged gnio feature: */ /* Local Variables: */ /* c-file-style: "gnu" */ /* End: */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-resource-contact.c0000664000175000017500000001545311720661341026623 0ustar00cassidycassidy00000000000000/* * wocky-resource-contact.c - Source for WockyResourceContact * Copyright (C) 2009 Collabora Ltd. * @author Guillaume Desmottes * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** * SECTION: wocky-resource-contact * @title: WockyResourceContact * @short_description: * @include: wocky/wocky-resource-contact.h * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-resource-contact.h" #include #include #include #ifdef HAVE_UNISTD_H # include #endif #include #include "wocky-signals-marshal.h" #include "wocky-utils.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_ROSTER #include "wocky-debug-internal.h" G_DEFINE_TYPE (WockyResourceContact, wocky_resource_contact, WOCKY_TYPE_CONTACT) /* properties */ enum { PROP_RESOURCE = 1, PROP_BARE_CONTACT, }; /* signal enum */ enum { LAST_SIGNAL, }; /* static guint signals[LAST_SIGNAL] = {0}; */ /* private structure */ struct _WockyResourceContactPrivate { gboolean dispose_has_run; gchar *resource; WockyBareContact *bare_contact; }; static void wocky_resource_contact_init (WockyResourceContact *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_RESOURCE_CONTACT, WockyResourceContactPrivate); } static void wocky_resource_contact_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyResourceContact *self = WOCKY_RESOURCE_CONTACT (object); WockyResourceContactPrivate *priv = self->priv; switch (property_id) { case PROP_RESOURCE: priv->resource = g_value_dup_string (value); break; case PROP_BARE_CONTACT: priv->bare_contact = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_resource_contact_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyResourceContact *self = WOCKY_RESOURCE_CONTACT (object); WockyResourceContactPrivate *priv = self->priv; switch (property_id) { case PROP_RESOURCE: g_value_set_string (value, priv->resource); break; case PROP_BARE_CONTACT: g_value_set_object (value, priv->bare_contact); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_resource_contact_constructed (GObject *object) { WockyResourceContact *self = WOCKY_RESOURCE_CONTACT (object); WockyResourceContactPrivate *priv = self->priv; g_assert (priv->resource != NULL); g_assert (priv->bare_contact != NULL); } static void wocky_resource_contact_dispose (GObject *object) { WockyResourceContact *self = WOCKY_RESOURCE_CONTACT (object); WockyResourceContactPrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; g_object_unref (priv->bare_contact); if (G_OBJECT_CLASS (wocky_resource_contact_parent_class)->dispose) G_OBJECT_CLASS (wocky_resource_contact_parent_class)->dispose (object); } static void wocky_resource_contact_finalize (GObject *object) { WockyResourceContact *self = WOCKY_RESOURCE_CONTACT (object); WockyResourceContactPrivate *priv = self->priv; g_free (priv->resource); G_OBJECT_CLASS (wocky_resource_contact_parent_class)->finalize (object); } static gchar * wocky_resource_contact_dup_jid (WockyContact *contact) { WockyResourceContact *self = WOCKY_RESOURCE_CONTACT (contact); const gchar *bare = wocky_bare_contact_get_jid (self->priv->bare_contact); return g_strdup_printf ("%s/%s", bare, self->priv->resource); } static void wocky_resource_contact_class_init ( WockyResourceContactClass *wocky_resource_contact_class) { GObjectClass *object_class = G_OBJECT_CLASS (wocky_resource_contact_class); WockyContactClass *contact_class = WOCKY_CONTACT_CLASS (wocky_resource_contact_class); GParamSpec *spec; g_type_class_add_private (wocky_resource_contact_class, sizeof (WockyResourceContactPrivate)); object_class->constructed = wocky_resource_contact_constructed; object_class->set_property = wocky_resource_contact_set_property; object_class->get_property = wocky_resource_contact_get_property; object_class->dispose = wocky_resource_contact_dispose; object_class->finalize = wocky_resource_contact_finalize; contact_class->dup_jid = wocky_resource_contact_dup_jid; /** * WockyResourceContact:resource: * * The resource of the contact. */ spec = g_param_spec_string ("resource", "Contact resource", "Contact resource", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_RESOURCE, spec); /** * WockyResourceContact:bare-contact: * * The #WockyBareContact associated with this #WockyResourceContact */ spec = g_param_spec_object ("bare-contact", "Bare contact", "the WockyBareContact associated with this WockyResourceContact", WOCKY_TYPE_BARE_CONTACT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_BARE_CONTACT, spec); } WockyResourceContact * wocky_resource_contact_new (WockyBareContact *bare, const gchar *resource) { return g_object_new (WOCKY_TYPE_RESOURCE_CONTACT, "bare-contact", bare, "resource", resource, NULL); } const gchar * wocky_resource_contact_get_resource (WockyResourceContact *self) { WockyResourceContactPrivate *priv = self->priv; return priv->resource; } WockyBareContact * wocky_resource_contact_get_bare_contact (WockyResourceContact *self) { WockyResourceContactPrivate *priv = self->priv; return priv->bare_contact; } gboolean wocky_resource_contact_equal (WockyResourceContact *a, WockyResourceContact *b) { if (a == NULL || b == NULL) return FALSE; if (wocky_strdiff (wocky_resource_contact_get_resource (a), wocky_resource_contact_get_resource (b))) return FALSE; return wocky_bare_contact_equal (wocky_resource_contact_get_bare_contact (a), wocky_resource_contact_get_bare_contact (b)); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-porter.h0000664000175000017500000002521611720661341024661 0ustar00cassidycassidy00000000000000/* * wocky-porter.h - Header for WockyPorter * Copyright (C) 2009-2011 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_PORTER_H__ #define __WOCKY_PORTER_H__ #include #include #include "wocky-stanza.h" G_BEGIN_DECLS /** * WockyPorterError: * @WOCKY_PORTER_ERROR_NOT_STARTED : The #WockyPorter has not been started yet * @WOCKY_PORTER_ERROR_CLOSING : The #WockyPorter is closing * @WOCKY_PORTER_ERROR_CLOSED : The #WockyPorter is closed * @WOCKY_PORTER_ERROR_NOT_IQ : The #WockyStanza is not an IQ * @WOCKY_PORTER_ERROR_FORCIBLY_CLOSED : The #WockyPorter has been forced to * close * * The #WockyPorter specific errors. */ typedef enum { WOCKY_PORTER_ERROR_NOT_STARTED, WOCKY_PORTER_ERROR_CLOSING, WOCKY_PORTER_ERROR_CLOSED, WOCKY_PORTER_ERROR_NOT_IQ, WOCKY_PORTER_ERROR_FORCIBLY_CLOSED, } WockyPorterError; GQuark wocky_porter_error_quark (void); /** * WOCKY_PORTER_ERROR: * * Get access to the error quark of the xmpp porter. */ #define WOCKY_PORTER_ERROR (wocky_porter_error_quark ()) GType wocky_porter_get_type (void); /* type macros */ #define WOCKY_TYPE_PORTER \ (wocky_porter_get_type ()) #define WOCKY_PORTER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), WOCKY_TYPE_PORTER, \ WockyPorter)) #define WOCKY_IS_PORTER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WOCKY_TYPE_PORTER)) #define WOCKY_PORTER_GET_INTERFACE(inst) \ (G_TYPE_INSTANCE_GET_INTERFACE ((inst), WOCKY_TYPE_PORTER, \ WockyPorterInterface)) typedef struct _WockyPorter WockyPorter; typedef struct _WockyPorterInterface WockyPorterInterface; #define WOCKY_PORTER_HANDLER_PRIORITY_MIN 0 #define WOCKY_PORTER_HANDLER_PRIORITY_NORMAL (guint) (G_MAXUINT / 2) #define WOCKY_PORTER_HANDLER_PRIORITY_MAX G_MAXUINT /** * WockyPorterHandlerFunc: * @porter: the #WockyPorter dispatching the #WockyStanza * @stanza: the #WockyStanza being dispatched * @user_data: the data passed when the handler has been registered * * Handler called when a matching stanza has been received by the * #WockyPorter. * * If a handler returns %TRUE, this means that it has taken responsibility * for handling the stanza and (if applicable) sending a reply. * * If a handler returns %FALSE, this indicates that it has declined to process * the stanza. The next handler (if any) is invoked. * * A handler must not assume that @stanza will continue to exist after the * handler has returned, unless it has taken a reference to @stanza using * g_object_ref(). * * Returns: %TRUE if the stanza has been handled, %FALSE if not */ typedef gboolean (* WockyPorterHandlerFunc) ( WockyPorter *porter, WockyStanza *stanza, gpointer user_data); /** * WockyPorterInterface: * @parent_iface: Fields shared with #GTypeInterface. * @get_full_jid: Return the full JID of the user according to the * porter; see wocky_porter_get_full_jid() for more details. * @get_bare_jid: Return the bare JID of the user according to the * porter; see wocky_porter_get_full_jid() for more details. * @get_resource: Return the resource of the user according to the * porter; see wocky_porter_get_full_jid() for more details. * @start: Start the porter; see wocky_porter_start() for more * details. * @send_async: Start an asynchronous stanza send operation; see * wocky_porter_send_async() for more details. * @send_finish: Finish an asynchronous stanza send operation; see * wocky_porter_send_finish() for more details. * @register_handler_from_by_stanza: Register a stanza handler from a * specific contact; see * wocky_porter_register_handler_from_by_stanza() for more details. * @register_handler_from_anyone_by_stanza: Register a stanza hander * from any contact; see * wocky_porter_register_handler_from_anyone_by_stanza() for more * details. * @unregister_handler: Unregister a stanza handler; see * wocky_porter_unregister_handler() for more details. * @close_async: Start an asynchronous porter close operation; see * wocky_porter_close_async() for more details. * @close_finish: Finish an asynchronous porter close operation; see * wocky_porter_close_finish() for more details. * @send_iq_async: Start an asynchronous IQ stanza send operation; see * wocky_porter_send_iq_async() for more details. * @send_iq_finish: Finish an asynchronous IQ stanza send operation; * see wocky_porter_send_iq_finish() for more details. * @force_close_async: Start an asynchronous porter force close * operation; see wocky_porter_force_close_async() for more details. * @force_close_finish: Finish an asynchronous porter force close * operation; see wocky_porter_force_close_finish() for more details. * * The vtable for a porter implementation. */ struct _WockyPorterInterface { GTypeInterface parent_iface; const gchar * (*get_full_jid) (WockyPorter *self); const gchar * (*get_bare_jid) (WockyPorter *self); const gchar * (*get_resource) (WockyPorter *self); void (*start) (WockyPorter *porter); void (*send_async) (WockyPorter *porter, WockyStanza *stanza, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean (*send_finish) (WockyPorter *porter, GAsyncResult *result, GError **error); guint (*register_handler_from_by_stanza) ( WockyPorter *self, WockyStanzaType type, WockyStanzaSubType sub_type, const gchar *from, guint priority, WockyPorterHandlerFunc callback, gpointer user_data, WockyStanza *stanza); guint (*register_handler_from_anyone_by_stanza) ( WockyPorter *self, WockyStanzaType type, WockyStanzaSubType sub_type, guint priority, WockyPorterHandlerFunc callback, gpointer user_data, WockyStanza *stanza); void (*unregister_handler) (WockyPorter *self, guint id); void (*close_async) (WockyPorter *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean (*close_finish) (WockyPorter *self, GAsyncResult *result, GError **error); void (*send_iq_async) (WockyPorter *porter, WockyStanza *stanza, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); WockyStanza * (*send_iq_finish) (WockyPorter *porter, GAsyncResult *result, GError **error); void (*force_close_async) (WockyPorter *porter, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean (*force_close_finish) (WockyPorter *porter, GAsyncResult *result, GError **error); }; void wocky_porter_start (WockyPorter *porter); const gchar * wocky_porter_get_full_jid (WockyPorter *self); const gchar * wocky_porter_get_bare_jid (WockyPorter *self); const gchar * wocky_porter_get_resource (WockyPorter *self); void wocky_porter_send_async (WockyPorter *porter, WockyStanza *stanza, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_porter_send_finish ( WockyPorter *porter, GAsyncResult *result, GError **error); void wocky_porter_send (WockyPorter *porter, WockyStanza *stanza); guint wocky_porter_register_handler_from_va (WockyPorter *self, WockyStanzaType type, WockyStanzaSubType sub_type, const gchar *from, guint priority, WockyPorterHandlerFunc callback, gpointer user_data, va_list ap); guint wocky_porter_register_handler_from_by_stanza (WockyPorter *self, WockyStanzaType type, WockyStanzaSubType sub_type, const gchar *from, guint priority, WockyPorterHandlerFunc callback, gpointer user_data, WockyStanza *stanza); guint wocky_porter_register_handler_from (WockyPorter *self, WockyStanzaType type, WockyStanzaSubType sub_type, const gchar *from, guint priority, WockyPorterHandlerFunc callback, gpointer user_data, ...) G_GNUC_NULL_TERMINATED; guint wocky_porter_register_handler_from_anyone_va ( WockyPorter *self, WockyStanzaType type, WockyStanzaSubType sub_type, guint priority, WockyPorterHandlerFunc callback, gpointer user_data, va_list ap); guint wocky_porter_register_handler_from_anyone_by_stanza ( WockyPorter *self, WockyStanzaType type, WockyStanzaSubType sub_type, guint priority, WockyPorterHandlerFunc callback, gpointer user_data, WockyStanza *stanza); guint wocky_porter_register_handler_from_anyone ( WockyPorter *self, WockyStanzaType type, WockyStanzaSubType sub_type, guint priority, WockyPorterHandlerFunc callback, gpointer user_data, ...) G_GNUC_NULL_TERMINATED; void wocky_porter_unregister_handler (WockyPorter *porter, guint id); void wocky_porter_close_async (WockyPorter *porter, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_porter_close_finish (WockyPorter *porter, GAsyncResult *result, GError **error); void wocky_porter_send_iq_async (WockyPorter *porter, WockyStanza *stanza, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); WockyStanza * wocky_porter_send_iq_finish ( WockyPorter *porter, GAsyncResult *result, GError **error) G_GNUC_WARN_UNUSED_RESULT; void wocky_porter_acknowledge_iq ( WockyPorter *porter, WockyStanza *stanza, ...) G_GNUC_NULL_TERMINATED; void wocky_porter_send_iq_error ( WockyPorter *porter, WockyStanza *stanza, WockyXmppError error_code, const gchar *message); void wocky_porter_send_iq_gerror ( WockyPorter *porter, WockyStanza *stanza, const GError *error); void wocky_porter_force_close_async (WockyPorter *porter, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_porter_force_close_finish ( WockyPorter *porter, GAsyncResult *result, GError **error); G_END_DECLS #endif /* #ifndef __WOCKY_PORTER_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jingle-types.h0000664000175000017500000001302612212322440025743 0ustar00cassidycassidy00000000000000/* * wocky-jingle-types.h - Header for Jingle-related enums and typedefs * Copyright © 2008–2012 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_JINGLE_TYPES_H__ #define __WOCKY_JINGLE_TYPES_H__ typedef struct _WockyJingleFactory WockyJingleFactory; typedef struct _WockyJingleSession WockyJingleSession; typedef struct _WockyJingleContent WockyJingleContent; typedef struct _WockyJingleTransportGoogle WockyJingleTransportGoogle; typedef struct _WockyJingleTransportRawUdp WockyJingleTransportRawUdp; typedef struct _WockyJingleTransportIceUdp WockyJingleTransportIceUdp; typedef struct _WockyJingleMediaRtp WockyJingleMediaRtp; typedef struct _WockyJingleCandidate WockyJingleCandidate; typedef enum { /*< skip >*/ /* not a jingle message */ WOCKY_JINGLE_DIALECT_ERROR, /* old libjingle3 gtalk variant */ WOCKY_JINGLE_DIALECT_GTALK3, /* new gtalk variant */ WOCKY_JINGLE_DIALECT_GTALK4, /* jingle in the old 0.15 version days */ WOCKY_JINGLE_DIALECT_V015, /* current jingle standard */ WOCKY_JINGLE_DIALECT_V032 } WockyJingleDialect; #define WOCKY_JINGLE_DIALECT_IS_GOOGLE(d)\ ((d == WOCKY_JINGLE_DIALECT_GTALK3) || (d == WOCKY_JINGLE_DIALECT_GTALK4)) /** * WockyJingleState: * @WOCKY_JINGLE_STATE_PENDING_CREATED: on outgoing sessions, no offer has been * sent to the peer yet. * @WOCKY_JINGLE_STATE_PENDING_INITIATE_SENT: on outgoing sessions, we have sent * the session-initiate and are awaiting the peer's acknowledgement. * @WOCKY_JINGLE_STATE_PENDING_INITIATED: on outgoing sessions, the peer has * received our session-initiate and we're waiting for them to accept; on * incoming sessions, the peer is waiting for us to accept. * @WOCKY_JINGLE_STATE_PENDING_ACCEPT_SENT: on incoming sessions, we have sent * session-accept and are waiting for the peer to acknowledge it. * @WOCKY_JINGLE_STATE_ACTIVE: the session is active. * @WOCKY_JINGLE_STATE_ENDED: the session has ended. The * #WockyJingleSession::terminated signal describes how the session ended. * * Possible states of a #WockyJingleSession. */ typedef enum { /*< skip >*/ /*< private >*/ WOCKY_JINGLE_STATE_INVALID = -1, /*< public >*/ WOCKY_JINGLE_STATE_PENDING_CREATED = 0, WOCKY_JINGLE_STATE_PENDING_INITIATE_SENT, WOCKY_JINGLE_STATE_PENDING_INITIATED, WOCKY_JINGLE_STATE_PENDING_ACCEPT_SENT, WOCKY_JINGLE_STATE_ACTIVE, WOCKY_JINGLE_STATE_ENDED, /*< private >*/ WOCKY_N_JINGLE_STATES } WockyJingleState; typedef enum { /*< skip >*/ WOCKY_JINGLE_ACTION_UNKNOWN, WOCKY_JINGLE_ACTION_CONTENT_ACCEPT, WOCKY_JINGLE_ACTION_CONTENT_ADD, WOCKY_JINGLE_ACTION_CONTENT_MODIFY, WOCKY_JINGLE_ACTION_CONTENT_REMOVE, WOCKY_JINGLE_ACTION_CONTENT_REPLACE, WOCKY_JINGLE_ACTION_CONTENT_REJECT, WOCKY_JINGLE_ACTION_SESSION_ACCEPT, WOCKY_JINGLE_ACTION_SESSION_INFO, WOCKY_JINGLE_ACTION_SESSION_INITIATE, WOCKY_JINGLE_ACTION_SESSION_TERMINATE, WOCKY_JINGLE_ACTION_TRANSPORT_INFO, WOCKY_JINGLE_ACTION_TRANSPORT_ACCEPT, WOCKY_JINGLE_ACTION_DESCRIPTION_INFO, WOCKY_JINGLE_ACTION_INFO } WockyJingleAction; typedef enum { /*< skip >*/ WOCKY_JINGLE_CONTENT_SENDERS_NONE, WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR, WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER, WOCKY_JINGLE_CONTENT_SENDERS_BOTH } WockyJingleContentSenders; typedef enum { /*< skip >*/ JINGLE_TRANSPORT_UNKNOWN, JINGLE_TRANSPORT_GOOGLE_P2P, JINGLE_TRANSPORT_RAW_UDP, JINGLE_TRANSPORT_ICE_UDP, } WockyJingleTransportType; typedef enum { /*< skip >*/ WOCKY_JINGLE_TRANSPORT_PROTOCOL_UDP, WOCKY_JINGLE_TRANSPORT_PROTOCOL_TCP } WockyJingleTransportProtocol; typedef enum { /*< skip >*/ WOCKY_JINGLE_CANDIDATE_TYPE_LOCAL, WOCKY_JINGLE_CANDIDATE_TYPE_STUN, WOCKY_JINGLE_CANDIDATE_TYPE_RELAY } WockyJingleCandidateType; /** * WockyJingleReason: * @WOCKY_JINGLE_REASON_UNKNOWN: no known reason * * The reason for a Jingle action occurring—specifically, the reason for * terminating a call. See XEP-0166 Jingle * §7.4 for definitions of the codes. */ typedef enum { WOCKY_JINGLE_REASON_UNKNOWN, WOCKY_JINGLE_REASON_ALTERNATIVE_SESSION, WOCKY_JINGLE_REASON_BUSY, WOCKY_JINGLE_REASON_CANCEL, WOCKY_JINGLE_REASON_CONNECTIVITY_ERROR, WOCKY_JINGLE_REASON_DECLINE, WOCKY_JINGLE_REASON_EXPIRED, WOCKY_JINGLE_REASON_FAILED_APPLICATION, WOCKY_JINGLE_REASON_FAILED_TRANSPORT, WOCKY_JINGLE_REASON_GENERAL_ERROR, WOCKY_JINGLE_REASON_GONE, WOCKY_JINGLE_REASON_INCOMPATIBLE_PARAMETERS, WOCKY_JINGLE_REASON_MEDIA_ERROR, WOCKY_JINGLE_REASON_SECURITY_ERROR, WOCKY_JINGLE_REASON_SUCCESS, WOCKY_JINGLE_REASON_TIMEOUT, WOCKY_JINGLE_REASON_UNSUPPORTED_APPLICATIONS, WOCKY_JINGLE_REASON_UNSUPPORTED_TRANSPORTS } WockyJingleReason; #endif /* __WOCKY_JINGLE_TYPES_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-stanza.h0000664000175000017500000001616412212322440024637 0ustar00cassidycassidy00000000000000/* * wocky-stanza.h - Header for WockyStanza * Copyright (C) 2006-2010 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_STANZA_H__ #define __WOCKY_STANZA_H__ #include #include #include "wocky-node-tree.h" #include "wocky-xmpp-error.h" #include "wocky-contact.h" G_BEGIN_DECLS typedef struct _WockyStanza WockyStanza; /** * WockyStanzaClass: * * The class of a #WockyStanza. */ typedef struct _WockyStanzaClass WockyStanzaClass; typedef struct _WockyStanzaPrivate WockyStanzaPrivate; struct _WockyStanzaClass { /**/ WockyNodeTreeClass parent_class; }; struct _WockyStanza { /**/ WockyNodeTree parent; WockyStanzaPrivate *priv; }; GType wocky_stanza_get_type (void); /* TYPE MACROS */ #define WOCKY_TYPE_STANZA \ (wocky_stanza_get_type ()) #define WOCKY_STANZA(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_STANZA, \ WockyStanza)) #define WOCKY_STANZA_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_STANZA, WockyStanzaClass)) #define WOCKY_IS_STANZA(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_STANZA)) #define WOCKY_IS_STANZA_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_STANZA)) #define WOCKY_STANZA_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_STANZA, WockyStanzaClass)) /** * WockyStanzaType: * @WOCKY_STANZA_TYPE_NONE: no stanza type * @WOCKY_STANZA_TYPE_MESSAGE: <message/> stanza * @WOCKY_STANZA_TYPE_PRESENCE: <presence/> stanza * @WOCKY_STANZA_TYPE_IQ: <iq/> stanza * @WOCKY_STANZA_TYPE_STREAM: <stream/> stanza * @WOCKY_STANZA_TYPE_STREAM_FEATURES: <stream:features/> stanza * @WOCKY_STANZA_TYPE_AUTH: <auth/> stanza * @WOCKY_STANZA_TYPE_CHALLENGE: <challenge/> stanza * @WOCKY_STANZA_TYPE_RESPONSE: <response/> stanza * @WOCKY_STANZA_TYPE_SUCCESS: <success/> stanza * @WOCKY_STANZA_TYPE_FAILURE: <failure/> stanza * @WOCKY_STANZA_TYPE_STREAM_ERROR: <stream:error/> stanza * @WOCKY_STANZA_TYPE_UNKNOWN: unknown stanza type * * XMPP stanza types. */ typedef enum { WOCKY_STANZA_TYPE_NONE, WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_TYPE_PRESENCE, WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_TYPE_STREAM, WOCKY_STANZA_TYPE_STREAM_FEATURES, WOCKY_STANZA_TYPE_AUTH, WOCKY_STANZA_TYPE_CHALLENGE, WOCKY_STANZA_TYPE_RESPONSE, WOCKY_STANZA_TYPE_SUCCESS, WOCKY_STANZA_TYPE_FAILURE, WOCKY_STANZA_TYPE_STREAM_ERROR, WOCKY_STANZA_TYPE_UNKNOWN, /*< private >*/ NUM_WOCKY_STANZA_TYPE } WockyStanzaType; /** * WockyStanzaSubType: * @WOCKY_STANZA_SUB_TYPE_NONE: no sub type * @WOCKY_STANZA_SUB_TYPE_AVAILABLE: "available" stanza sub type * @WOCKY_STANZA_SUB_TYPE_NORMAL: "normal" stanza sub type * @WOCKY_STANZA_SUB_TYPE_CHAT: "chat" stanza sub type * @WOCKY_STANZA_SUB_TYPE_GROUPCHAT: "groupchat" stanza sub type * @WOCKY_STANZA_SUB_TYPE_HEADLINE: "headline" stanza sub type * @WOCKY_STANZA_SUB_TYPE_UNAVAILABLE: "unavailable" stanza sub type * @WOCKY_STANZA_SUB_TYPE_PROBE: "probe" stanza sub type * @WOCKY_STANZA_SUB_TYPE_SUBSCRIBE: "subscribe" stanza sub type * @WOCKY_STANZA_SUB_TYPE_UNSUBSCRIBE: "unsubscribe" stanza sub type * @WOCKY_STANZA_SUB_TYPE_SUBSCRIBED: "subscribed" stanza sub type * @WOCKY_STANZA_SUB_TYPE_UNSUBSCRIBED: "unsubscribed" stanza sub type * @WOCKY_STANZA_SUB_TYPE_GET: "get" stanza sub type * @WOCKY_STANZA_SUB_TYPE_SET: "set" stanza sub type * @WOCKY_STANZA_SUB_TYPE_RESULT: "result" stanza sub type * @WOCKY_STANZA_SUB_TYPE_ERROR: "error" stanza sub type * @WOCKY_STANZA_SUB_TYPE_UNKNOWN: unknown stanza sub type * * XMPP stanza sub types. */ typedef enum { WOCKY_STANZA_SUB_TYPE_NONE, WOCKY_STANZA_SUB_TYPE_AVAILABLE, WOCKY_STANZA_SUB_TYPE_NORMAL, WOCKY_STANZA_SUB_TYPE_CHAT, WOCKY_STANZA_SUB_TYPE_GROUPCHAT, WOCKY_STANZA_SUB_TYPE_HEADLINE, WOCKY_STANZA_SUB_TYPE_UNAVAILABLE, WOCKY_STANZA_SUB_TYPE_PROBE, WOCKY_STANZA_SUB_TYPE_SUBSCRIBE, WOCKY_STANZA_SUB_TYPE_UNSUBSCRIBE, WOCKY_STANZA_SUB_TYPE_SUBSCRIBED, WOCKY_STANZA_SUB_TYPE_UNSUBSCRIBED, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_STANZA_SUB_TYPE_RESULT, WOCKY_STANZA_SUB_TYPE_ERROR, WOCKY_STANZA_SUB_TYPE_UNKNOWN, /*< private >*/ NUM_WOCKY_STANZA_SUB_TYPE } WockyStanzaSubType; WockyStanza * wocky_stanza_new (const gchar *name, const gchar *ns); WockyStanza * wocky_stanza_copy (WockyStanza *old); WockyNode *wocky_stanza_get_top_node (WockyStanza *self); WockyStanza * wocky_stanza_build (WockyStanzaType type, WockyStanzaSubType sub_type, const gchar *from, const gchar *to, ...) G_GNUC_NULL_TERMINATED; WockyStanza * wocky_stanza_build_to_contact (WockyStanzaType type, WockyStanzaSubType sub_type, const gchar *from, WockyContact *to, ...) G_GNUC_NULL_TERMINATED; void wocky_stanza_get_type_info (WockyStanza *stanza, WockyStanzaType *type, WockyStanzaSubType *sub_type); gboolean wocky_stanza_has_type (WockyStanza *stanza, WockyStanzaType expected_type); const gchar *wocky_stanza_get_from (WockyStanza *self); const gchar *wocky_stanza_get_to (WockyStanza *self); WockyStanza * wocky_stanza_build_va (WockyStanzaType type, WockyStanzaSubType sub_type, const gchar *from, const gchar *to, va_list ap); WockyStanza * wocky_stanza_build_iq_result (WockyStanza *iq, ...) G_GNUC_NULL_TERMINATED; WockyStanza *wocky_stanza_build_iq_result_va ( WockyStanza *iq, va_list ap); WockyStanza * wocky_stanza_build_iq_error (WockyStanza *iq, ...) G_GNUC_NULL_TERMINATED; WockyStanza *wocky_stanza_build_iq_error_va ( WockyStanza *iq, va_list ap); gboolean wocky_stanza_extract_errors (WockyStanza *stanza, WockyXmppErrorType *type, GError **core, GError **specialized, WockyNode **specialized_node); gboolean wocky_stanza_extract_stream_error (WockyStanza *stanza, GError **stream_error); WockyContact * wocky_stanza_get_to_contact (WockyStanza *self); WockyContact * wocky_stanza_get_from_contact (WockyStanza *self); void wocky_stanza_set_to_contact (WockyStanza *self, WockyContact *contact); void wocky_stanza_set_from_contact (WockyStanza *self, WockyContact *contact); G_END_DECLS #endif /* #ifndef __WOCKY_STANZA_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-heartbeat-source.h0000664000175000017500000000262711720661341026604 0ustar00cassidycassidy00000000000000/* * wocky-heartbeat-source.h: header for a GSource wrapping libiphb. * Copyright © 2010 Collabora Ltd. * Copyright © 2010 Nokia Corporation * @author Will Thompson * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_COMPILATION) # error "This is an internal header." #endif #ifndef WOCKY_HEARTBEAT_SOURCE_H #define WOCKY_HEARTBEAT_SOURCE_H #include G_BEGIN_DECLS typedef void (*WockyHeartbeatCallback) ( gpointer user_data); GSource *wocky_heartbeat_source_new ( guint max_interval); void wocky_heartbeat_source_update_interval ( GSource *source, guint max_interval); G_END_DECLS #endif /* WOCKY_HEARTBEAT_SOURCE_H */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jingle-transport-iceudp.h0000664000175000017500000000503712212322440030105 0ustar00cassidycassidy00000000000000/* * wocky-jingle-transport-iceudp.h - Header for WockyJingleTransportIceUdp * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __JINGLE_TRANSPORT_ICEUDP_H__ #define __JINGLE_TRANSPORT_ICEUDP_H__ #include #include "wocky-jingle-types.h" G_BEGIN_DECLS typedef struct _WockyJingleTransportIceUdpClass WockyJingleTransportIceUdpClass; GType wocky_jingle_transport_iceudp_get_type (void); /* TYPE MACROS */ #define WOCKY_TYPE_JINGLE_TRANSPORT_ICEUDP \ (wocky_jingle_transport_iceudp_get_type ()) #define WOCKY_JINGLE_TRANSPORT_ICEUDP(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_JINGLE_TRANSPORT_ICEUDP, \ WockyJingleTransportIceUdp)) #define WOCKY_JINGLE_TRANSPORT_ICEUDP_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_JINGLE_TRANSPORT_ICEUDP, \ WockyJingleTransportIceUdpClass)) #define WOCKY_IS_JINGLE_TRANSPORT_ICEUDP(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_JINGLE_TRANSPORT_ICEUDP)) #define WOCKY_IS_JINGLE_TRANSPORT_ICEUDP_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_JINGLE_TRANSPORT_ICEUDP)) #define WOCKY_JINGLE_TRANSPORT_ICEUDP_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_JINGLE_TRANSPORT_ICEUDP, \ WockyJingleTransportIceUdpClass)) struct _WockyJingleTransportIceUdpClass { GObjectClass parent_class; }; typedef struct _WockyJingleTransportIceUdpPrivate WockyJingleTransportIceUdpPrivate; struct _WockyJingleTransportIceUdp { GObject parent; WockyJingleTransportIceUdpPrivate *priv; }; void jingle_transport_iceudp_register (WockyJingleFactory *factory); G_END_DECLS #endif /* __JINGLE_TRANSPORT_ICEUDP_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-pubsub-node.h0000664000175000017500000001320412212322440025552 0ustar00cassidycassidy00000000000000/* * wocky-pubsub-node.h - Header of WockyPubsubNode * Copyright (C) 2009 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_PUBSUB_NODE_H__ #define __WOCKY_PUBSUB_NODE_H__ #include #include #include "wocky-enumtypes.h" #include "wocky-types.h" #include "wocky-session.h" #include "wocky-pubsub-service.h" G_BEGIN_DECLS /** * WockyPubsubNodeClass: * * The class of a #WockyPubsubNode. */ typedef struct _WockyPubsubNodeClass WockyPubsubNodeClass; typedef struct _WockyPubsubNodePrivate WockyPubsubNodePrivate; struct _WockyPubsubNodeClass { /**/ GObjectClass parent_class; }; struct _WockyPubsubNode { /**/ GObject parent; WockyPubsubNodePrivate *priv; }; GType wocky_pubsub_node_get_type (void); #define WOCKY_TYPE_PUBSUB_NODE \ (wocky_pubsub_node_get_type ()) #define WOCKY_PUBSUB_NODE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_PUBSUB_NODE, \ WockyPubsubNode)) #define WOCKY_PUBSUB_NODE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_PUBSUB_NODE, \ WockyPubsubNodeClass)) #define WOCKY_IS_PUBSUB_NODE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_PUBSUB_NODE)) #define WOCKY_IS_PUBSUB_NODE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_PUBSUB_NODE)) #define WOCKY_PUBSUB_NODE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_PUBSUB_NODE, \ WockyPubsubNodeClass)) const gchar * wocky_pubsub_node_get_name (WockyPubsubNode *self); WockyStanza *wocky_pubsub_node_make_publish_stanza (WockyPubsubNode *self, WockyNode **pubsub_out, WockyNode **publish_out, WockyNode **item_out); void wocky_pubsub_node_subscribe_async (WockyPubsubNode *self, const gchar *jid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); WockyPubsubSubscription *wocky_pubsub_node_subscribe_finish ( WockyPubsubNode *self, GAsyncResult *result, GError **error); void wocky_pubsub_node_unsubscribe_async (WockyPubsubNode *self, const gchar *jid, const gchar *subid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_pubsub_node_unsubscribe_finish ( WockyPubsubNode *self, GAsyncResult *result, GError **error); void wocky_pubsub_node_delete_async (WockyPubsubNode *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_pubsub_node_delete_finish (WockyPubsubNode *self, GAsyncResult *result, GError **error); void wocky_pubsub_node_list_subscribers_async ( WockyPubsubNode *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_pubsub_node_list_subscribers_finish ( WockyPubsubNode *self, GAsyncResult *result, GList **subscribers, GError **error); /*< prefix=WOCKY_PUBSUB_AFFILIATION >*/ typedef enum { WOCKY_PUBSUB_AFFILIATION_OWNER, WOCKY_PUBSUB_AFFILIATION_PUBLISHER, WOCKY_PUBSUB_AFFILIATION_PUBLISH_ONLY, WOCKY_PUBSUB_AFFILIATION_MEMBER, WOCKY_PUBSUB_AFFILIATION_NONE, WOCKY_PUBSUB_AFFILIATION_OUTCAST } WockyPubsubAffiliationState; typedef struct _WockyPubsubAffiliation WockyPubsubAffiliation; struct _WockyPubsubAffiliation { /*< public >*/ WockyPubsubNode *node; gchar *jid; WockyPubsubAffiliationState state; }; #define WOCKY_TYPE_PUBSUB_AFFILIATION \ (wocky_pubsub_affiliation_get_type ()) GType wocky_pubsub_affiliation_get_type (void); WockyPubsubAffiliation *wocky_pubsub_affiliation_new ( WockyPubsubNode *node, const gchar *jid, WockyPubsubAffiliationState state); WockyPubsubAffiliation *wocky_pubsub_affiliation_copy ( WockyPubsubAffiliation *aff); void wocky_pubsub_affiliation_free (WockyPubsubAffiliation *aff); GList *wocky_pubsub_affiliation_list_copy (GList *affs); void wocky_pubsub_affiliation_list_free (GList *affs); void wocky_pubsub_node_list_affiliates_async ( WockyPubsubNode *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_pubsub_node_list_affiliates_finish ( WockyPubsubNode *self, GAsyncResult *result, GList **affiliates, GError **error); void wocky_pubsub_node_modify_affiliates_async ( WockyPubsubNode *self, GList *affiliates, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_pubsub_node_modify_affiliates_finish ( WockyPubsubNode *self, GAsyncResult *result, GError **error); void wocky_pubsub_node_get_configuration_async ( WockyPubsubNode *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); WockyDataForm *wocky_pubsub_node_get_configuration_finish ( WockyPubsubNode *self, GAsyncResult *result, GError **error); G_END_DECLS #endif /* __WOCKY_PUBSUB_NODE_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-debug.h0000664000175000017500000000247012212322440024420 0ustar00cassidycassidy00000000000000#if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_DEBUG_H__ #define __WOCKY_DEBUG_H__ G_BEGIN_DECLS typedef enum { /*< private > */ WOCKY_DEBUG_TRANSPORT = 1 << 0, WOCKY_DEBUG_NET = 1 << 1, WOCKY_DEBUG_XMPP_READER = 1 << 2, WOCKY_DEBUG_XMPP_WRITER = 1 << 3, WOCKY_DEBUG_AUTH = 1 << 4, WOCKY_DEBUG_SSL = 1 << 5, WOCKY_DEBUG_RMULTICAST = 1 << 6, WOCKY_DEBUG_RMULTICAST_SENDER = 1 << 7, WOCKY_DEBUG_MUC_CONNECTION = 1 << 8, WOCKY_DEBUG_BYTESTREAM = 1 << 9, WOCKY_DEBUG_FILE_TRANSFER = 1 << 10, WOCKY_DEBUG_PORTER = 1 << 11, WOCKY_DEBUG_CONNECTOR = 1 << 12, WOCKY_DEBUG_ROSTER = 1 << 13, WOCKY_DEBUG_TLS = 1 << 14, WOCKY_DEBUG_PUBSUB = 1 << 15, WOCKY_DEBUG_DATA_FORM = 1 << 16, WOCKY_DEBUG_PING = 1 << 17, WOCKY_DEBUG_HEARTBEAT = 1 << 18, WOCKY_DEBUG_PRESENCE = 1 << 19, WOCKY_DEBUG_CONNECTION_FACTORY= 1 << 20, WOCKY_DEBUG_JINGLE = 1 << 21, } WockyDebugFlags; #define WOCKY_DEBUG_XMPP (WOCKY_DEBUG_XMPP_READER | WOCKY_DEBUG_XMPP_WRITER) void wocky_debug_set_flags (WockyDebugFlags flags); G_END_DECLS #endif telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-c2s-porter.h0000664000175000017500000000727711720661341025355 0ustar00cassidycassidy00000000000000/* * wocky-c2s-porter.h - Header for WockyC2SPorter * Copyright (C) 2009-2011 Collabora Ltd. * @author Guillaume Desmottes * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_C2S_PORTER_H__ #define __WOCKY_C2S_PORTER_H__ #include #include "wocky-xmpp-connection.h" #include "wocky-stanza.h" #include "wocky-porter.h" G_BEGIN_DECLS /** * WockyC2SPorter: * * An object providing a convenient wrapper around a #WockyXmppConnection to * send and receive stanzas. */ typedef struct _WockyC2SPorter WockyC2SPorter; /** * WockyC2SPorterClass: * * The class of a #WockyC2SPorter. */ typedef struct _WockyC2SPorterClass WockyC2SPorterClass; typedef struct _WockyC2SPorterPrivate WockyC2SPorterPrivate; struct _WockyC2SPorterClass { /**/ GObjectClass parent_class; }; struct _WockyC2SPorter { /**/ GObject parent; WockyC2SPorterPrivate *priv; }; GType wocky_c2s_porter_get_type (void); /* TYPE MACROS */ #define WOCKY_TYPE_C2S_PORTER \ (wocky_c2s_porter_get_type ()) #define WOCKY_C2S_PORTER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_C2S_PORTER, \ WockyC2SPorter)) #define WOCKY_C2S_PORTER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_C2S_PORTER, \ WockyC2SPorterClass)) #define WOCKY_IS_C2S_PORTER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_C2S_PORTER)) #define WOCKY_IS_C2S_PORTER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_C2S_PORTER)) #define WOCKY_C2S_PORTER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_C2S_PORTER, \ WockyC2SPorterClass)) WockyPorter * wocky_c2s_porter_new (WockyXmppConnection *connection, const gchar *full_jid); void wocky_c2s_porter_send_whitespace_ping_async ( WockyC2SPorter *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_c2s_porter_send_whitespace_ping_finish ( WockyC2SPorter *self, GAsyncResult *result, GError **error); guint wocky_c2s_porter_register_handler_from_server_va ( WockyC2SPorter *self, WockyStanzaType type, WockyStanzaSubType sub_type, guint priority, WockyPorterHandlerFunc callback, gpointer user_data, va_list ap); guint wocky_c2s_porter_register_handler_from_server_by_stanza ( WockyC2SPorter *self, WockyStanzaType type, WockyStanzaSubType sub_type, guint priority, WockyPorterHandlerFunc callback, gpointer user_data, WockyStanza *stanza); guint wocky_c2s_porter_register_handler_from_server ( WockyC2SPorter *self, WockyStanzaType type, WockyStanzaSubType sub_type, guint priority, WockyPorterHandlerFunc callback, gpointer user_data, ...) G_GNUC_NULL_TERMINATED; void wocky_c2s_porter_enable_power_saving_mode (WockyC2SPorter *porter, gboolean enable); G_END_DECLS #endif /* #ifndef __WOCKY_C2S_PORTER_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-pubsub-service.h0000664000175000017500000001177412212322440026277 0ustar00cassidycassidy00000000000000/* * wocky-pubsub-service.h - Header of WockyPubsubService * Copyright (C) 2009 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_PUBSUB_SERVICE_H__ #define __WOCKY_PUBSUB_SERVICE_H__ #include #include #include "wocky-enumtypes.h" #include "wocky-stanza.h" #include "wocky-session.h" #include "wocky-types.h" #include "wocky-data-form.h" G_BEGIN_DECLS typedef struct _WockyPubsubService WockyPubsubService; typedef struct _WockyPubsubServiceClass WockyPubsubServiceClass; typedef struct _WockyPubsubServicePrivate WockyPubsubServicePrivate; /** * WockyPubsubServiceError: * @WOCKY_PUBSUB_SERVICE_ERROR_WRONG_REPLY: A wrong reply was received * * #WockyPubsubService specific errors. */ typedef enum { WOCKY_PUBSUB_SERVICE_ERROR_WRONG_REPLY, } WockyPubsubServiceError; GQuark wocky_pubsub_service_error_quark (void); #define WOCKY_PUBSUB_SERVICE_ERROR (wocky_pubsub_service_error_quark ()) struct _WockyPubsubServiceClass { GObjectClass parent_class; GType node_object_type; }; struct _WockyPubsubService { GObject parent; WockyPubsubServicePrivate *priv; }; GType wocky_pubsub_service_get_type (void); #define WOCKY_TYPE_PUBSUB_SERVICE \ (wocky_pubsub_service_get_type ()) #define WOCKY_PUBSUB_SERVICE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_PUBSUB_SERVICE, \ WockyPubsubService)) #define WOCKY_PUBSUB_SERVICE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_PUBSUB_SERVICE, \ WockyPubsubServiceClass)) #define WOCKY_IS_PUBSUB_SERVICE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_PUBSUB_SERVICE)) #define WOCKY_IS_PUBSUB_SERVICE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_PUBSUB_SERVICE)) #define WOCKY_PUBSUB_SERVICE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_PUBSUB_SERVICE, \ WockyPubsubServiceClass)) WockyPubsubService * wocky_pubsub_service_new (WockySession *session, const gchar *jid); WockyPubsubNode * wocky_pubsub_service_ensure_node (WockyPubsubService *self, const gchar *name); WockyPubsubNode * wocky_pubsub_service_lookup_node (WockyPubsubService *self, const gchar *name); void wocky_pubsub_service_get_default_node_configuration_async ( WockyPubsubService *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); WockyDataForm * wocky_pubsub_service_get_default_node_configuration_finish ( WockyPubsubService *self, GAsyncResult *result, GError **error); void wocky_pubsub_service_retrieve_subscriptions_async ( WockyPubsubService *self, WockyPubsubNode *node, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_pubsub_service_retrieve_subscriptions_finish ( WockyPubsubService *self, GAsyncResult *result, GList **subscriptions, GError **error); void wocky_pubsub_service_create_node_async (WockyPubsubService *self, const gchar *name, WockyDataForm *config, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); WockyPubsubNode * wocky_pubsub_service_create_node_finish ( WockyPubsubService *self, GAsyncResult *result, GError **error); /*< prefix=WOCKY_PUBSUB_SUBSCRIPTION >*/ typedef enum { WOCKY_PUBSUB_SUBSCRIPTION_NONE, WOCKY_PUBSUB_SUBSCRIPTION_PENDING, WOCKY_PUBSUB_SUBSCRIPTION_SUBSCRIBED, WOCKY_PUBSUB_SUBSCRIPTION_UNCONFIGURED } WockyPubsubSubscriptionState; typedef struct { /*< public >*/ WockyPubsubNode *node; gchar *jid; WockyPubsubSubscriptionState state; gchar *subid; } WockyPubsubSubscription; #define WOCKY_TYPE_PUBSUB_SUBSCRIPTION \ (wocky_pubsub_subscription_get_type ()) GType wocky_pubsub_subscription_get_type (void); WockyPubsubSubscription *wocky_pubsub_subscription_new ( WockyPubsubNode *node, const gchar *jid, WockyPubsubSubscriptionState state, const gchar *subid); WockyPubsubSubscription *wocky_pubsub_subscription_copy ( WockyPubsubSubscription *sub); void wocky_pubsub_subscription_free (WockyPubsubSubscription *sub); GList *wocky_pubsub_subscription_list_copy (GList *subs); void wocky_pubsub_subscription_list_free (GList *subs); G_END_DECLS #endif /* __WOCKY_PUBSUB_SERVICE_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jingle-session.h0000664000175000017500000001172312212322440026264 0ustar00cassidycassidy00000000000000/* * wocky-jingle-session.h - Header for WockyJingleSession * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __JINGLE_SESSION_H__ #define __JINGLE_SESSION_H__ #include #include "wocky-jingle-content.h" #include "wocky-jingle-factory.h" #include "wocky-jingle-types.h" G_BEGIN_DECLS typedef struct _WockyJingleSessionClass WockyJingleSessionClass; GType wocky_jingle_session_get_type (void); /* TYPE MACROS */ #define WOCKY_TYPE_JINGLE_SESSION \ (wocky_jingle_session_get_type ()) #define WOCKY_JINGLE_SESSION(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_JINGLE_SESSION, \ WockyJingleSession)) #define WOCKY_JINGLE_SESSION_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_JINGLE_SESSION, \ WockyJingleSessionClass)) #define WOCKY_IS_JINGLE_SESSION(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_JINGLE_SESSION)) #define WOCKY_IS_JINGLE_SESSION_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_JINGLE_SESSION)) #define WOCKY_JINGLE_SESSION_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_JINGLE_SESSION, \ WockyJingleSessionClass)) struct _WockyJingleSessionClass { GObjectClass parent_class; }; typedef struct _WockyJingleSessionPrivate WockyJingleSessionPrivate; struct _WockyJingleSession { GObject parent; WockyJingleSessionPrivate *priv; }; WockyJingleSession *wocky_jingle_session_new ( WockyJingleFactory *factory, WockyPorter *porter, const gchar *session_id, gboolean local_initiator, WockyContact *peer, WockyJingleDialect dialect, gboolean local_hold); const gchar * wocky_jingle_session_detect (WockyStanza *stanza, WockyJingleAction *action, WockyJingleDialect *dialect); gboolean wocky_jingle_session_parse (WockyJingleSession *sess, WockyJingleAction action, WockyStanza *stanza, GError **error); WockyStanza *wocky_jingle_session_new_message (WockyJingleSession *sess, WockyJingleAction action, WockyNode **sess_node); void wocky_jingle_session_accept (WockyJingleSession *sess); gboolean wocky_jingle_session_terminate (WockyJingleSession *sess, WockyJingleReason reason, const gchar *text, GError **error); void wocky_jingle_session_remove_content (WockyJingleSession *sess, WockyJingleContent *c); WockyJingleContent * wocky_jingle_session_add_content (WockyJingleSession *sess, WockyJingleMediaType mtype, WockyJingleContentSenders senders, const char *name, const gchar *content_ns, const gchar *transport_ns); GType wocky_jingle_session_get_content_type (WockyJingleSession *); GList *wocky_jingle_session_get_contents (WockyJingleSession *sess); const gchar *wocky_jingle_session_get_peer_resource ( WockyJingleSession *sess); const gchar *wocky_jingle_session_get_initiator ( WockyJingleSession *sess); const gchar *wocky_jingle_session_get_sid (WockyJingleSession *sess); WockyJingleDialect wocky_jingle_session_get_dialect (WockyJingleSession *sess); gboolean wocky_jingle_session_can_modify_contents (WockyJingleSession *sess); gboolean wocky_jingle_session_peer_has_cap ( WockyJingleSession *self, const gchar *cap_or_quirk); void wocky_jingle_session_send ( WockyJingleSession *sess, WockyStanza *stanza); void wocky_jingle_session_set_local_hold (WockyJingleSession *sess, gboolean held); gboolean wocky_jingle_session_get_remote_hold (WockyJingleSession *sess); gboolean wocky_jingle_session_get_remote_ringing (WockyJingleSession *sess); gboolean wocky_jingle_session_defines_action (WockyJingleSession *sess, WockyJingleAction action); WockyContact *wocky_jingle_session_get_peer_contact (WockyJingleSession *self); const gchar *wocky_jingle_session_get_peer_jid (WockyJingleSession *sess); const gchar *wocky_jingle_session_get_reason_name (WockyJingleReason reason); WockyJingleFactory *wocky_jingle_session_get_factory (WockyJingleSession *self); WockyPorter *wocky_jingle_session_get_porter (WockyJingleSession *self); void wocky_jingle_session_acknowledge_iq (WockyJingleSession *self, WockyStanza *stanza); G_END_DECLS #endif /* __JINGLE_SESSION_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-sasl-plain.c0000664000175000017500000001053312005516162025375 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-sasl-plain.h" #include "wocky-auth-registry.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_AUTH #include "wocky-debug-internal.h" static void auth_handler_iface_init (gpointer g_iface); G_DEFINE_TYPE_WITH_CODE (WockySaslPlain, wocky_sasl_plain, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (WOCKY_TYPE_AUTH_HANDLER, auth_handler_iface_init)) enum { PROP_USERNAME = 1, PROP_PASSWORD }; struct _WockySaslPlainPrivate { gchar *username; gchar *password; }; static void wocky_sasl_plain_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockySaslPlain *self = WOCKY_SASL_PLAIN (object); WockySaslPlainPrivate *priv = self->priv; switch (property_id) { case PROP_USERNAME: g_value_set_string (value, priv->username); break; case PROP_PASSWORD: g_value_set_string (value, priv->password); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void wocky_sasl_plain_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockySaslPlain *self = WOCKY_SASL_PLAIN (object); WockySaslPlainPrivate *priv = self->priv; switch (property_id) { case PROP_USERNAME: g_free (priv->username); priv->username = g_value_dup_string (value); break; case PROP_PASSWORD: g_free (priv->password); priv->password = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void wocky_sasl_plain_dispose (GObject *object) { WockySaslPlain *self = WOCKY_SASL_PLAIN (object); WockySaslPlainPrivate *priv = self->priv; g_free (priv->username); g_free (priv->password); G_OBJECT_CLASS (wocky_sasl_plain_parent_class)->dispose (object); } static void wocky_sasl_plain_class_init (WockySaslPlainClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (WockySaslPlainPrivate)); object_class->get_property = wocky_sasl_plain_get_property; object_class->set_property = wocky_sasl_plain_set_property; object_class->dispose = wocky_sasl_plain_dispose; g_object_class_install_property (object_class, PROP_USERNAME, g_param_spec_string ("username", "username", "The username to authenticate with", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_PASSWORD, g_param_spec_string ("password", "password", "The password to authenticate with", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); } static gboolean plain_initial_response (WockyAuthHandler *handler, GString **initial_data, GError **error); static void auth_handler_iface_init (gpointer g_iface) { WockyAuthHandlerIface *iface = g_iface; iface->mechanism = WOCKY_AUTH_MECH_SASL_PLAIN; iface->plain = TRUE; iface->initial_response_func = plain_initial_response; } static void wocky_sasl_plain_init (WockySaslPlain *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE ( self, WOCKY_TYPE_SASL_PLAIN, WockySaslPlainPrivate); } WockySaslPlain * wocky_sasl_plain_new (const gchar *username, const gchar *password) { return g_object_new (WOCKY_TYPE_SASL_PLAIN, "username", username, "password", password, NULL); } static GString * plain_generate_initial_response (const gchar *username, const gchar *password) { GString *str = g_string_new (""); g_string_append_c (str, '\0'); g_string_append (str, username); g_string_append_c (str, '\0'); g_string_append (str, password); return str; } static gboolean plain_initial_response (WockyAuthHandler *handler, GString **initial_data, GError **error) { WockySaslPlain *self = WOCKY_SASL_PLAIN (handler); WockySaslPlainPrivate *priv = self->priv; if (priv->username == NULL || priv->password == NULL) { g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NO_CREDENTIALS, "No username or password provided"); return FALSE; } DEBUG ("Got username and password"); *initial_data = plain_generate_initial_response (priv->username, priv->password); return TRUE; } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-auth-registry.c0000664000175000017500000003576012212322440026144 0ustar00cassidycassidy00000000000000/* wocky-auth-registry.c */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-auth-registry.h" #include "wocky-auth-handler.h" #include "wocky-sasl-scram.h" #include "wocky-sasl-digest-md5.h" #include "wocky-sasl-plain.h" #include "wocky-jabber-auth-password.h" #include "wocky-jabber-auth-digest.h" #include "wocky-utils.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_AUTH #include "wocky-debug-internal.h" G_DEFINE_TYPE (WockyAuthRegistry, wocky_auth_registry, G_TYPE_OBJECT) /* private structure */ struct _WockyAuthRegistryPrivate { gboolean dispose_has_run; WockyAuthHandler *handler; GSList *handlers; }; static void wocky_auth_registry_start_auth_async_func (WockyAuthRegistry *self, GSList *mechanisms, gboolean allow_plain, gboolean is_secure_channel, const gchar *username, const gchar *password, const gchar *server, const gchar *session_id, GAsyncReadyCallback callback, gpointer user_data); static gboolean wocky_auth_registry_start_auth_finish_func ( WockyAuthRegistry *self, GAsyncResult *result, WockyAuthRegistryStartData **start_data, GError **error); static void wocky_auth_registry_challenge_async_func (WockyAuthRegistry *self, const GString *challenge_data, GAsyncReadyCallback callback, gpointer user_data); static gboolean wocky_auth_registry_challenge_finish_func ( WockyAuthRegistry *self, GAsyncResult *result, GString **response, GError **error); static void wocky_auth_registry_success_async_func (WockyAuthRegistry *self, GAsyncReadyCallback callback, gpointer user_data); static gboolean wocky_auth_registry_success_finish_func ( WockyAuthRegistry *self, GAsyncResult *result, GError **error); GQuark wocky_auth_error_quark (void) { static GQuark quark = 0; if (!quark) quark = g_quark_from_static_string ("wocky_auth_error"); return quark; } static void wocky_auth_registry_constructed (GObject *object) { } static void wocky_auth_registry_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { switch (property_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void wocky_auth_registry_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { switch (property_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void wocky_auth_registry_dispose (GObject *object) { WockyAuthRegistry *self = WOCKY_AUTH_REGISTRY (object); WockyAuthRegistryPrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; /* release any references held by the object here */ if (priv->handler != NULL) { g_object_unref (priv->handler); } if (priv->handlers != NULL) { g_slist_foreach (priv->handlers, (GFunc) g_object_unref, NULL); g_slist_free (priv->handlers); } G_OBJECT_CLASS (wocky_auth_registry_parent_class)->dispose (object); } static void wocky_auth_registry_finalize (GObject *object) { G_OBJECT_CLASS (wocky_auth_registry_parent_class)->finalize (object); } static void wocky_auth_registry_class_init (WockyAuthRegistryClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (WockyAuthRegistryPrivate)); object_class->constructed = wocky_auth_registry_constructed; object_class->get_property = wocky_auth_registry_get_property; object_class->set_property = wocky_auth_registry_set_property; object_class->dispose = wocky_auth_registry_dispose; object_class->finalize = wocky_auth_registry_finalize; klass->start_auth_async_func = wocky_auth_registry_start_auth_async_func; klass->start_auth_finish_func = wocky_auth_registry_start_auth_finish_func; klass->challenge_async_func = wocky_auth_registry_challenge_async_func; klass->challenge_finish_func = wocky_auth_registry_challenge_finish_func; klass->success_async_func = wocky_auth_registry_success_async_func; klass->success_finish_func = wocky_auth_registry_success_finish_func; klass->failure_func = NULL; } static void wocky_auth_registry_init (WockyAuthRegistry *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_AUTH_REGISTRY, WockyAuthRegistryPrivate); } WockyAuthRegistry * wocky_auth_registry_new (void) { return g_object_new (WOCKY_TYPE_AUTH_REGISTRY, NULL); } static gboolean wocky_auth_registry_has_mechanism ( GSList *list, const gchar *mech) { return (g_slist_find_custom (list, mech, (GCompareFunc) g_strcmp0) != NULL); } WockyAuthRegistryStartData * wocky_auth_registry_start_data_new (const gchar *mechanism, const GString *initial_response) { WockyAuthRegistryStartData *start_data = g_slice_new0 ( WockyAuthRegistryStartData); start_data->mechanism = g_strdup (mechanism); start_data->initial_response = wocky_g_string_dup (initial_response); return start_data; } WockyAuthRegistryStartData * wocky_auth_registry_start_data_dup (WockyAuthRegistryStartData *start_data) { return wocky_auth_registry_start_data_new ( start_data->mechanism, start_data->initial_response); } void wocky_auth_registry_start_data_free (WockyAuthRegistryStartData *start_data) { g_free (start_data->mechanism); if (start_data->initial_response != NULL) g_string_free (start_data->initial_response, TRUE); g_slice_free (WockyAuthRegistryStartData, start_data); } static gboolean wocky_auth_registry_select_handler (WockyAuthRegistry *self, GSList *mechanisms, gboolean allow_plain, const gchar *username, const gchar *password, const gchar *server, const gchar *session_id, WockyAuthHandler **out_handler) { WockyAuthRegistryPrivate *priv = self->priv; GSList *k; for (k = priv->handlers; k != NULL; k = k->next) { WockyAuthHandler *handler = k->data; const gchar *handler_mech = wocky_auth_handler_get_mechanism (handler); if (wocky_auth_handler_is_plain (handler) && !allow_plain) continue; if (wocky_auth_registry_has_mechanism (mechanisms, handler_mech)) { if (out_handler != NULL) *out_handler = g_object_ref (handler); return TRUE; } } if (wocky_auth_registry_has_mechanism (mechanisms, WOCKY_AUTH_MECH_SASL_SCRAM_SHA_1)) { if (out_handler != NULL) { /* XXX: check for username and password here? */ DEBUG ("Choosing SCRAM-SHA-1 as auth mechanism"); *out_handler = WOCKY_AUTH_HANDLER (wocky_sasl_scram_new ( server, username, password)); } return TRUE; } if (wocky_auth_registry_has_mechanism (mechanisms, WOCKY_AUTH_MECH_SASL_DIGEST_MD5)) { if (out_handler != NULL) { /* XXX: check for username and password here? */ *out_handler = WOCKY_AUTH_HANDLER (wocky_sasl_digest_md5_new ( server, username, password)); } return TRUE; } if (wocky_auth_registry_has_mechanism (mechanisms, WOCKY_AUTH_MECH_JABBER_DIGEST)) { if (out_handler != NULL) { *out_handler = WOCKY_AUTH_HANDLER (wocky_jabber_auth_digest_new ( session_id, password)); } return TRUE; } if (allow_plain && wocky_auth_registry_has_mechanism (mechanisms, WOCKY_AUTH_MECH_SASL_PLAIN)) { if (out_handler != NULL) { /* XXX: check for username and password here? */ DEBUG ("Choosing PLAIN as auth mechanism"); *out_handler = WOCKY_AUTH_HANDLER (wocky_sasl_plain_new ( username, password)); } return TRUE; } if (allow_plain && wocky_auth_registry_has_mechanism (mechanisms, WOCKY_AUTH_MECH_JABBER_PASSWORD)) { if (out_handler != NULL) { *out_handler = WOCKY_AUTH_HANDLER (wocky_jabber_auth_password_new ( password)); } return TRUE; } if (out_handler) *out_handler = NULL; return FALSE; } static void wocky_auth_registry_start_auth_async_func (WockyAuthRegistry *self, GSList *mechanisms, gboolean allow_plain, gboolean is_secure_channel, const gchar *username, const gchar *password, const gchar *server, const gchar *session_id, GAsyncReadyCallback callback, gpointer user_data) { WockyAuthRegistryPrivate *priv = self->priv; GSimpleAsyncResult *result; result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_auth_registry_start_auth_async); g_assert (priv->handler == NULL); if (!wocky_auth_registry_select_handler (self, mechanisms, allow_plain, username, password, server, session_id, &priv->handler)) { g_simple_async_result_set_error (result, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NO_SUPPORTED_MECHANISMS, "No supported mechanisms found"); } else { GString *initial_data; GError *error = NULL; if (!wocky_auth_handler_get_initial_response (priv->handler, &initial_data, &error)) { g_simple_async_result_set_from_error (result, error); g_error_free (error); } else { WockyAuthRegistryStartData *start_data = wocky_auth_registry_start_data_new ( wocky_auth_handler_get_mechanism (priv->handler), initial_data); g_simple_async_result_set_op_res_gpointer (result, start_data, (GDestroyNotify) wocky_auth_registry_start_data_free); wocky_g_string_free (initial_data); } } g_simple_async_result_complete_in_idle (result); g_object_unref (result); } void wocky_auth_registry_start_auth_async (WockyAuthRegistry *self, GSList *mechanisms, gboolean allow_plain, gboolean is_secure_channel, const gchar *username, const gchar *password, const gchar *server, const gchar *session_id, GAsyncReadyCallback callback, gpointer user_data) { WockyAuthRegistryClass *cls = WOCKY_AUTH_REGISTRY_GET_CLASS (self); cls->start_auth_async_func (self, mechanisms, allow_plain, is_secure_channel, username, password, server, session_id, callback, user_data); } gboolean wocky_auth_registry_start_auth_finish (WockyAuthRegistry *self, GAsyncResult *result, WockyAuthRegistryStartData **start_data, GError **error) { WockyAuthRegistryClass *cls = WOCKY_AUTH_REGISTRY_GET_CLASS (self); return cls->start_auth_finish_func (self, result, start_data, error); } static gboolean wocky_auth_registry_start_auth_finish_func (WockyAuthRegistry *self, GAsyncResult *result, WockyAuthRegistryStartData **start_data, GError **error) { wocky_implement_finish_copy_pointer (self, wocky_auth_registry_start_auth_async, wocky_auth_registry_start_data_dup, start_data); } static void wocky_auth_registry_challenge_async_func (WockyAuthRegistry *self, const GString *challenge_data, GAsyncReadyCallback callback, gpointer user_data) { WockyAuthRegistryPrivate *priv = self->priv; GString *response = NULL; GError *error = NULL; GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_auth_registry_challenge_async); g_assert (priv->handler != NULL); if (!wocky_auth_handler_handle_auth_data (priv->handler, challenge_data, &response, &error)) { g_simple_async_result_set_from_error (result, error); g_error_free (error); } else { g_simple_async_result_set_op_res_gpointer (result, response, (GDestroyNotify) wocky_g_string_free); } g_simple_async_result_complete_in_idle (result); g_object_unref (result); } void wocky_auth_registry_challenge_async (WockyAuthRegistry *self, const GString *challenge_data, GAsyncReadyCallback callback, gpointer user_data) { WockyAuthRegistryClass *cls = WOCKY_AUTH_REGISTRY_GET_CLASS (self); cls->challenge_async_func (self, challenge_data, callback, user_data); } gboolean wocky_auth_registry_challenge_finish (WockyAuthRegistry *self, GAsyncResult *result, GString **response, GError **error) { WockyAuthRegistryClass *cls = WOCKY_AUTH_REGISTRY_GET_CLASS (self); return cls->challenge_finish_func (self, result, response, error); } static gboolean wocky_auth_registry_challenge_finish_func (WockyAuthRegistry *self, GAsyncResult *result, GString **response, GError **error) { wocky_implement_finish_copy_pointer (self, wocky_auth_registry_challenge_async, wocky_g_string_dup, response); } static void wocky_auth_registry_success_async_func (WockyAuthRegistry *self, GAsyncReadyCallback callback, gpointer user_data) { WockyAuthRegistryPrivate *priv = self->priv; GError *error = NULL; GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_auth_registry_success_async); g_assert (priv->handler != NULL); if (!wocky_auth_handler_handle_success (priv->handler, &error)) { g_simple_async_result_set_from_error (result, error); g_error_free (error); } g_simple_async_result_complete_in_idle (result); g_object_unref (result); } void wocky_auth_registry_success_async (WockyAuthRegistry *self, GAsyncReadyCallback callback, gpointer user_data) { WockyAuthRegistryClass *cls = WOCKY_AUTH_REGISTRY_GET_CLASS (self); cls->success_async_func (self, callback, user_data); } gboolean wocky_auth_registry_success_finish (WockyAuthRegistry *self, GAsyncResult *result, GError **error) { WockyAuthRegistryClass *cls = WOCKY_AUTH_REGISTRY_GET_CLASS (self); return cls->success_finish_func (self, result, error); } static gboolean wocky_auth_registry_success_finish_func (WockyAuthRegistry *self, GAsyncResult *result, GError **error) { wocky_implement_finish_void (self, wocky_auth_registry_success_async); } void wocky_auth_registry_failure (WockyAuthRegistry *self, GError *error) { WockyAuthRegistryClass *cls = WOCKY_AUTH_REGISTRY_GET_CLASS (self); if (cls->failure_func != NULL) cls->failure_func (self, error); } void wocky_auth_registry_add_handler (WockyAuthRegistry *self, WockyAuthHandler *handler) { WockyAuthRegistryPrivate *priv = self->priv; g_object_ref (handler); priv->handlers = g_slist_append (priv->handlers, handler); } /** * wocky_auth_registry_supports_one_of: * @self: a #WockyAuthRegistry * @allow_plain: Whether auth in plain text is allowed * @mechanisms: a #GSList of gchar* of auth mechanisms * * Checks whether at least one of @mechanisms is supported by Wocky. At present, * Wocky itself only implements password-based authentication mechanisms. * * Returns: %TRUE if one of the @mechanisms is supported by wocky, * %FALSE otherwise. */ gboolean wocky_auth_registry_supports_one_of (WockyAuthRegistry *self, GSList *mechanisms, gboolean allow_plain) { return wocky_auth_registry_select_handler (self, mechanisms, allow_plain, NULL, NULL, NULL, NULL, NULL); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-openssl.c0000664000175000017500000020010712212322440025005 0ustar00cassidycassidy00000000000000/* * Copyright © 2008 Christian Kellner, Samuel Cormier-Iijima * Copyright © 2008-2009 Codethink Limited * Copyright © 2009-2010 Collabora Limited * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2 of the licence or (at * your option) any later version. * * Authors: Vivek Dasmohapatra * Ryan Lortie * Christian Kellner * Samuel Cormier-Iijima * * Based on wocky-tls.c, which was in turn based on an unmerged gnio feature. * See wocky-tls.c for details. * * This file follows the original coding style from upstream, not collabora * house style. See wocky-tls.c for details. */ /** * SECTION: wocky-tls * @title: Wocky OpenSSL TLS * @short_description: Establish TLS sessions * * The WOCKY_TLS_DEBUG_LEVEL environment variable can be used to print debug * output from OpenSSL. To enable it, set it to a value from 1 to 9. * Higher values will print more information. * * Increasing the value past certain thresholds will also trigger increased * debugging output from within wocky-openssl.c as well. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-tls.h" /* Apparently an implicit requirement of OpenSSL's headers... */ #ifdef G_OS_WIN32 #include #endif #include #include #include #ifdef HAVE_UNISTD_H # include #endif #include #include #include #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_TLS #define DEBUG_HANDSHAKE_LEVEL 5 #define DEBUG_ASYNC_DETAIL_LEVEL 6 #include "wocky-debug-internal.h" #include "wocky-utils.h" #include #include #include #include #include #include /* SSL_CTX_set_cipher_list() allows to restrict/alter the list of supported * ciphers; see ciphers(1) for documentation on the format. * Usually the normal ciphers are ok, but on mobile phones we prefer RC4 as * it decreases the size of packets. The bandwidth difference is tiny, but * the difference in power consumption between small and very small packets * can be significant on 3G. */ #ifdef ENABLE_PREFER_STREAM_CIPHERS #define CIPHER_LIST \ "RC4-SHA:" \ "RC4-MD5:" \ "ECDHE-RSA-RC4-SHA:" \ "ECDHE-ECDSA-RC4-SHA:" \ "ECDH-RSA-RC4-SHA:" \ "ECDH-ECDSA-RC4-SHA:" \ "PSK-RC4-SHA:" \ "ALL" /* fall-back to all the other algorithms */ #endif enum { PROP_S_NONE, PROP_S_STREAM, PROP_S_SERVER, PROP_S_DHBITS, PROP_S_KEYFILE, PROP_S_CERTFILE, }; enum { PROP_C_NONE, PROP_C_SESSION, }; enum { PROP_O_NONE, PROP_O_SESSION }; enum { PROP_I_NONE, PROP_I_SESSION }; typedef enum { WOCKY_TLS_OP_HANDSHAKE, WOCKY_TLS_OP_READ, WOCKY_TLS_OP_WRITE } WockyTLSOperation; /* from openssl docs: not clear if this is exported as a constant by openssl */ #define MAX_SSLV3_BLOCK_SIZE 0x4000 typedef struct { gboolean active; gint io_priority; GCancellable *cancellable; GObject *source_object; GAsyncReadyCallback callback; gpointer user_data; gpointer source_tag; GError *error; gboolean sync_complete; gchar *buffer; gsize count; gchar rbuf[MAX_SSLV3_BLOCK_SIZE]; } WockyTLSJob; typedef struct { WockyTLSJob job; gulong state; gboolean done; } WockyTLSHandshake; typedef GIOStreamClass WockyTLSConnectionClass; typedef GObjectClass WockyTLSSessionClass; typedef GInputStreamClass WockyTLSInputStreamClass; typedef GOutputStreamClass WockyTLSOutputStreamClass; struct _WockyTLSSession { GObject parent; GIOStream *stream; GCancellable *cancellable; GError *error; gboolean async; /* tls server support */ gboolean server; guint dh_bits; gchar *key_file; gchar *cert_file; /* frontend jobs */ struct { WockyTLSHandshake handshake; WockyTLSJob read; WockyTLSJob write; } job; /* openssl structures */ BIO *rbio; BIO *wbio; SSL_METHOD *method; SSL_CTX *ctx; SSL *ssl; }; typedef struct { GInputStream parent; WockyTLSSession *session; } WockyTLSInputStream; typedef struct { GOutputStream parent; WockyTLSSession *session; } WockyTLSOutputStream; struct _WockyTLSConnection { GIOStream parent; WockyTLSSession *session; WockyTLSInputStream *input; WockyTLSOutputStream *output; }; DH * get_dh4096 (void); DH * get_dh2048 (void); DH * get_dh1024 (void); DH * get_dh512 (void); static guint tls_debug_level = 0; static GType wocky_tls_input_stream_get_type (void); static GType wocky_tls_output_stream_get_type (void); G_DEFINE_TYPE (WockyTLSConnection, wocky_tls_connection, G_TYPE_IO_STREAM); G_DEFINE_TYPE (WockyTLSSession, wocky_tls_session, G_TYPE_OBJECT); G_DEFINE_TYPE (WockyTLSInputStream, wocky_tls_input_stream, G_TYPE_INPUT_STREAM); G_DEFINE_TYPE (WockyTLSOutputStream, wocky_tls_output_stream, G_TYPE_OUTPUT_STREAM); #define WOCKY_TYPE_TLS_INPUT_STREAM (wocky_tls_input_stream_get_type ()) #define WOCKY_TYPE_TLS_OUTPUT_STREAM (wocky_tls_output_stream_get_type ()) #define WOCKY_TLS_INPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ WOCKY_TYPE_TLS_INPUT_STREAM, \ WockyTLSInputStream)) #define WOCKY_TLS_OUTPUT_STREAM(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ WOCKY_TYPE_TLS_OUTPUT_STREAM, \ WockyTLSOutputStream)) /* Ok: This function tries to retrieve the error that caused a problem from * * bottom of the openssl error stack: The errnum argument is the error code * * returned by the last openssl operation which MAY NOT have come from the * * openssl error stack (cf SSL_get_error) and which MAY be SSL_ERROR_NONE: * * it's not supposed to be SSL_ERROR_NONE if a problem occurred, but this is * * not actually guaranteed anywhere so we have to check for it here: */ static const gchar *error_to_string (long error) { static gchar ssl_error[256]; int e; int x; /* SSL_ERROR_NONE from ERR_get_error means we have emptied the stack, * * in which case we should back up and use the last error we saw: */ for (e = x = error; x != SSL_ERROR_NONE; x = ERR_get_error ()) e = x; /* we found an error in the stack, or were passed one in errnum: */ if (e != SSL_ERROR_NONE) { ERR_error_string_n ((gulong) e, ssl_error, sizeof (ssl_error)); return ssl_error; } /* No useful/informative/relevant error found */ return NULL; } static GSimpleAsyncResult * wocky_tls_job_make_result (WockyTLSJob *job, gssize result) { GSimpleAsyncResult *simple; simple = g_simple_async_result_new (job->source_object, job->callback, job->user_data, job->source_tag); if (job->error != NULL) { DEBUG ("setting error from job '%s'", job->error->message); g_simple_async_result_set_from_error (simple, job->error); g_error_free (job->error); job->error = NULL; } if (job->source_object != NULL) g_object_unref (job->source_object); job->source_object = NULL; if (job->cancellable != NULL) g_object_unref (job->cancellable); job->cancellable = NULL; job->active = FALSE; return simple; } static void wocky_tls_job_result_gssize (WockyTLSJob *job, gssize result) { GSimpleAsyncResult *simple; if ((simple = wocky_tls_job_make_result (job, result))) { if (result >= 0) g_simple_async_result_set_op_res_gssize (simple, result); g_simple_async_result_complete (simple); g_object_unref (simple); } } /* only used for handshake results: read + write use result_gssize */ static void wocky_tls_job_result_boolean (WockyTLSJob *job, gint result) { GSimpleAsyncResult *simple; if ((simple = wocky_tls_job_make_result (job, result))) { g_simple_async_result_complete (simple); g_object_unref (simple); } } /* ************************************************************************* */ static void wocky_tls_session_try_operation (WockyTLSSession *session, WockyTLSOperation operation); static void wocky_tls_session_write_ready (GObject *object, GAsyncResult *result, gpointer user_data); static void wocky_tls_session_read_ready (GObject *object, GAsyncResult *result, gpointer user_data); /* writes to the internal BIO should always succeed, so we should never * receive SSL_ERROR_WANT_WRITE: reads, on the other hand, obviously * depend on how much data we have buffered, so SSL_ERROR_WANT_READ can * clearly happen */ static void handshake_write (WockyTLSSession *session) { gchar *wbuf; WockyTLSJob *handshake = &(session->job.handshake.job); GCancellable *cancel = handshake->cancellable; gint prio = handshake->io_priority; GOutputStream *output = g_io_stream_get_output_stream (session->stream); long wsize = BIO_get_mem_data (session->wbio, &wbuf); if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL) DEBUG (""); g_output_stream_write_async (output, wbuf, wsize, prio, cancel, wocky_tls_session_write_ready, session); } static void handshake_read (WockyTLSSession *session) { GInputStream *input = g_io_stream_get_input_stream (session->stream); WockyTLSJob *handshake = (WockyTLSJob *) &session->job.handshake.job; if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL) DEBUG (""); g_input_stream_read_async (input, &(handshake->rbuf), MAX_SSLV3_BLOCK_SIZE, handshake->io_priority, handshake->cancellable, wocky_tls_session_read_ready, session); } static int ssl_handshake (WockyTLSSession *session) { gint result = 1; gulong errnum = SSL_ERROR_NONE; gboolean want_read = FALSE; gboolean want_write = FALSE; const gchar *errstr = NULL; gboolean done = session->job.handshake.done; gboolean fatal = FALSE; if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL) DEBUG (""); if (!done) { const gchar *method; if (session->server) { method = "SSL_accept"; result = SSL_accept (session->ssl); } else { method = "SSL_connect"; result = SSL_connect (session->ssl); } errnum = SSL_get_error (session->ssl, result); done = (result == 1); errstr = error_to_string (errnum); fatal = (errnum != SSL_ERROR_WANT_READ && errnum != SSL_ERROR_WANT_WRITE && errnum != SSL_ERROR_NONE); DEBUG ("%s - result: %d; error: %ld", method, result, errnum); DEBUG ("%s : %s", method, errstr); } /* buffered write data means we need to write */ want_write = BIO_pending (session->wbio) > 0; /* check to see if there's data waiting to go out: * * since writes to a BIO should always succeed, it is possible to * * have buffered write data after a successful return, but not * * possible to be waiting on a read, since SSL_connect should not * * return success if waiting for data to come in */ if (done) { session->job.handshake.done = TRUE; if (!want_write) { DEBUG ("Handshake completed"); errnum = session->job.handshake.state = SSL_ERROR_NONE; } else { DEBUG ("Handshake completed (IO incomplete)"); g_assert (errnum != SSL_ERROR_WANT_READ); errnum = SSL_ERROR_WANT_WRITE; } } else { DEBUG ("Handshake state: %ld", errnum); session->job.handshake.state = errnum; want_read = (errnum == SSL_ERROR_WANT_READ); } /* sif we want both a write (buffered data in the BIO) AND a read * * (SSL_ERROR_WANT_READ) then this will happen when the handshake_write * * invokes wocky_tls_session_write_ready which will in turn call * * wocky_tls_session_try_operation which will re-enter handshake * * and then proceed to fall back through to this block of code */ if (!fatal) { DEBUG ("want write: %d; want read: %d;", want_write, want_read); if (want_write) handshake_write (session); else if (want_read) handshake_read (session); else wocky_tls_session_try_operation (session, WOCKY_TLS_OP_HANDSHAKE); } else { DEBUG ("Handshake failed: [%d:%ld] %s", result, errnum, errstr); if (session->job.handshake.job.error != NULL) { g_error_free (session->job.handshake.job.error); session->job.handshake.job.error = NULL; } g_set_error (&(session->job.handshake.job.error), WOCKY_TLS_ERROR, result, "Handshake failed: %s", errstr); wocky_tls_session_try_operation (session, WOCKY_TLS_OP_HANDSHAKE); } return errnum; } static void ssl_fill (WockyTLSSession *session) { GInputStream *input = g_io_stream_get_input_stream (session->stream); gchar *rbuf = session->job.read.rbuf; gint prio = session->job.read.io_priority; GCancellable *cancel = session->job.read.cancellable; if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL) DEBUG (""); g_input_stream_read_async (input, rbuf, MAX_SSLV3_BLOCK_SIZE, prio, cancel, wocky_tls_session_read_ready, session); } static void ssl_flush (WockyTLSSession *session) { long wsize; gchar *wbuf; gint prio = session->job.read.io_priority; GOutputStream *output = g_io_stream_get_output_stream (session->stream); GCancellable *cancel = session->job.read.cancellable; if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL) DEBUG (""); wsize = BIO_get_mem_data (session->wbio, &wbuf); if (wsize > 0) g_output_stream_write_async (output, wbuf, wsize, prio, cancel, wocky_tls_session_write_ready, session); } /* FALSE indicates we should go round again and try to get more data */ static gboolean ssl_read_is_complete (WockyTLSSession *session, gint result) { /* if the job error is set, we should bail out now, we have failed * * otherwise: * * a -ve return with an SSL error of WANT_READ implies an incomplete * * crypto record: we need to go round again and get more data * * or: * * a 0 return means the SSL connection was shut down cleanly */ if ((session->job.read.error == NULL) && (result <= 0)) { int err = SSL_get_error (session->ssl, result); switch (err) { case SSL_ERROR_WANT_READ: DEBUG ("Incomplete SSL record, read again"); return FALSE; case SSL_ERROR_WANT_WRITE: g_warning ("read caused write: unsupported TLS re-negotiation?"); /* deliberately falling through to the default case, having logged a * more specific warning. */ default: g_set_error (&session->job.read.error, WOCKY_TLS_ERROR, err, "OpenSSL read: protocol error %d", err); } } return TRUE; } static void wocky_tls_session_try_operation (WockyTLSSession *session, WockyTLSOperation operation) { WockyTLSJob *handshake = &(session->job.handshake.job); if (handshake->active || operation == WOCKY_TLS_OP_HANDSHAKE) { gint result = session->job.handshake.state; DEBUG ("async job handshake"); if (tls_debug_level >= DEBUG_HANDSHAKE_LEVEL) DEBUG ("async job handshake: %d", result); switch (result) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: DEBUG ("Handshake incomplete..."); ssl_handshake (session); break; case SSL_ERROR_NONE: DEBUG ("Handshake complete (success): %d", result); wocky_tls_job_result_boolean (handshake, result); break; default: DEBUG ("Handshake complete (failure): %d", result); if (handshake->error == NULL) handshake->error = g_error_new (WOCKY_TLS_ERROR, result, "Handshake Error"); wocky_tls_job_result_boolean (handshake, result); } } else if (operation == WOCKY_TLS_OP_READ) { gssize result = 0; gulong pending = 0; gsize wanted = 0; if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL) DEBUG ("async job OP_READ"); /* cipherbytes in the BIO != clearbytes after SSL_read */ wanted = session->job.read.count; pending = (gulong)BIO_pending (session->rbio); result = SSL_read (session->ssl, session->job.read.buffer, wanted); DEBUG ("read %" G_GSSIZE_FORMAT " clearbytes (from %ld cipherbytes)", result, pending); if (ssl_read_is_complete (session, result)) wocky_tls_job_result_gssize (&session->job.read, result); else ssl_fill (session); } else { /* we have no useful way of mapping SSL cipherbytes to raw * * clearbytes: it should always be a complete write unless * * there's been a network error, in which case the utility * * of a byte count is debatable anyway */ gssize result = session->job.write.count; if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL) DEBUG ("async job OP_WRITE"); g_assert (operation == WOCKY_TLS_OP_WRITE); DEBUG ("wrote %" G_GSSIZE_FORMAT " clearbytes", result); wocky_tls_job_result_gssize (&session->job.write, result); } } static void wocky_tls_job_start (WockyTLSJob *job, gpointer source_object, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, gpointer source_tag) { g_assert (job->active == FALSE); g_assert (job->cancellable == NULL); /* this is always a circular reference, so it will keep the * session alive for as long as the job is running. */ job->source_object = g_object_ref (source_object); job->io_priority = io_priority; if (cancellable != NULL) job->cancellable = g_object_ref (cancellable); job->callback = callback; job->user_data = user_data; job->source_tag = source_tag; job->error = NULL; job->active = TRUE; } typedef gint (*ssl_handler) (SSL *ssl); WockyTLSConnection * wocky_tls_session_handshake (WockyTLSSession *session, GCancellable *cancellable, GError **error) { gint result = -1; gboolean go = TRUE; gboolean done = FALSE; ssl_handler handler = session->server ? SSL_accept : SSL_connect; gboolean want_write = FALSE; gboolean want_read = FALSE; gint errnum = SSL_ERROR_NONE; const gchar *errstr = NULL; while (go) { DEBUG ("sync SSL handshake loop"); if (!done) { result = handler (session->ssl); errnum = SSL_get_error (session->ssl, result); done = (result == 1); DEBUG ("SSL_%s: %d:%d", (handler == SSL_accept) ? "accept" : "connect", result, errnum); if (errnum != SSL_ERROR_NONE && errnum != SSL_ERROR_WANT_READ && errnum != SSL_ERROR_WANT_WRITE) { errstr = error_to_string (errnum); DEBUG ("SSL handshake error: [%d:%d] %s", result, errnum, errstr); } } want_write = BIO_pending (session->wbio) > 0; want_read = (errnum == SSL_ERROR_WANT_READ); if (want_write) { gchar *wbuf; GOutputStream *out = g_io_stream_get_output_stream (session->stream); long wsize = BIO_get_mem_data (session->wbio, &wbuf); gssize sent = 0; DEBUG ("sending %ld cipherbytes", wsize); if (wsize > 0) sent = g_output_stream_write (out, wbuf, wsize, NULL, error); DEBUG ("sent %" G_GSSIZE_FORMAT " cipherbytes", sent); (void) BIO_reset (session->wbio); } if (want_read) { char rbuf[MAX_SSLV3_BLOCK_SIZE]; GInputStream *in = g_io_stream_get_input_stream (session->stream); gssize bytes = g_input_stream_read (in, &rbuf, sizeof(rbuf), NULL, error); DEBUG ("read %" G_GSSIZE_FORMAT " cipherbytes", bytes); BIO_write (session->rbio, &rbuf, bytes); } switch (errnum) { case SSL_ERROR_WANT_WRITE: /* WANT_WRITE is theoretically impossible, but what the hell */ case SSL_ERROR_WANT_READ: break; case SSL_ERROR_NONE: DEBUG ("handshake complete, all IO done"); go = FALSE; break; default: DEBUG ("SSL handshake error: [%d:%d] %s", result, errnum, errstr); *error = g_error_new (WOCKY_TLS_ERROR, errnum, "Handshake: %s", errstr); go = FALSE; } } if (done) return g_object_new (WOCKY_TYPE_TLS_CONNECTION, "session", session, NULL); return NULL; } /* ************************************************************************* */ /* adding CA certificates & CRL lists for peer certificate verification */ void wocky_tls_session_add_ca (WockyTLSSession *session, const gchar *path) { gboolean ok = FALSE; if (!g_file_test (path, G_FILE_TEST_EXISTS)) { DEBUG ("CA file or path '%s' not accessible", path); return; } if (g_file_test (path, G_FILE_TEST_IS_DIR)) { DEBUG ("Loading CA directory"); ok = SSL_CTX_load_verify_locations (session->ctx, NULL, path); } if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) { DEBUG ("Loading CA file"); ok = SSL_CTX_load_verify_locations (session->ctx, path, NULL); } if (!ok) { gulong e, f; for (f = e = ERR_get_error (); e != 0; e = ERR_get_error ()) f = e; DEBUG ("CA '%s' failed: %s", path, ERR_error_string (f, NULL)); } else DEBUG ("CA '%s' loaded", path); } void wocky_tls_session_add_crl (WockyTLSSession *session, const gchar *path) { gboolean ok = FALSE; if (!g_file_test (path, G_FILE_TEST_EXISTS)) { DEBUG ("CRL file or path '%s' not accessible", path); return; } if (g_file_test (path, G_FILE_TEST_IS_DIR)) { X509_STORE *store = SSL_CTX_get_cert_store (session->ctx); X509_LOOKUP_METHOD *method = X509_LOOKUP_hash_dir (); X509_LOOKUP *lookup = X509_STORE_add_lookup (store, method); DEBUG ("Loading CRL directory"); ok = X509_LOOKUP_add_dir (lookup, path, X509_FILETYPE_PEM) == 1; } if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) { X509_STORE *store = SSL_CTX_get_cert_store (session->ctx); X509_LOOKUP_METHOD *method = X509_LOOKUP_file (); X509_LOOKUP *lookup = X509_STORE_add_lookup (store, method); DEBUG ("Loading CRL file"); ok = X509_LOOKUP_load_file (lookup, path, X509_FILETYPE_PEM) == 1; } if (!ok) { gulong e, f; for (f = e = ERR_get_error (); e != 0; e = ERR_get_error ()) f = e; DEBUG ("'%s' failed: %s\n", path, ERR_error_string (f, NULL)); } else DEBUG ("'%s' loaded\n", path); } /* ************************************************************************* */ void wocky_tls_session_handshake_async (WockyTLSSession *session, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { DEBUG (""); wocky_tls_job_start (&session->job.handshake.job, session, io_priority, cancellable, callback, user_data, wocky_tls_session_handshake_async); ssl_handshake (session); } WockyTLSConnection * wocky_tls_session_handshake_finish (WockyTLSSession *session, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); DEBUG (""); { GObject *source_object; source_object = g_async_result_get_source_object (result); g_object_unref (source_object); g_return_val_if_fail (G_OBJECT (session) == source_object, NULL); } g_return_val_if_fail (wocky_tls_session_handshake_async == g_simple_async_result_get_source_tag (simple), NULL); if (g_simple_async_result_propagate_error (simple, error)) return NULL; DEBUG ("connection OK"); return g_object_new (WOCKY_TYPE_TLS_CONNECTION, "session", session, NULL); } static gboolean compare_wildcarded_hostname (const char *hostname, const char *certname) { DEBUG ("%s ~ %s", hostname, certname); if (g_ascii_strcasecmp (hostname, certname) == 0) return TRUE; /* We only allow leading '*.' wildcards. See the final bullet point of XMPP * Core §13.7.1.2.1 * : * * DNS domain names in server certificates MAY contain the wildcard * character '*' as the complete left-most label within the identifier. */ if (g_str_has_prefix (certname, "*.")) { const gchar *certname_tail = certname + 2; const gchar *hostname_tail = index (hostname, '.'); if (hostname_tail == NULL) return FALSE; hostname_tail++; DEBUG ("%s ~ %s", hostname_tail, certname_tail); return g_ascii_strcasecmp (hostname_tail, certname_tail) == 0; } return FALSE; } static gboolean check_peer_name (const char *target, X509 *cert) { int i; gboolean rval = FALSE; X509_NAME *subject = X509_get_subject_name (cert); X509_CINF *ci = cert->cert_info; static const long nid[] = { NID_commonName, NID_subject_alt_name, NID_undef }; /* first, see if the x509 name contains the info we want: */ for (i = 0; nid[i] != NID_undef; i++) { gssize len = X509_NAME_get_text_by_NID (subject, nid[i], NULL, -1); if (len > 0) { char *cname = g_new0 (gchar, len + 1); X509_NAME_get_text_by_NID (subject, nid[i], cname, len + 1); DEBUG ("got cname '%s' from x509 name, nid #%u", cname, i); rval = compare_wildcarded_hostname (target, cname); g_free (cname); } } /* ok, if that failed, we need to dive into the guts of the x509 structure * * and extract the subject_alt_name from the x509 v3 extensions: if that * * extension is present, and a string, use that. If it is present, and * * a multi-value stack, trawl it for the "DNS" entry and use that */ if (!rval && (ci->extensions != NULL)) for (i = 0; i < sk_X509_EXTENSION_num(ci->extensions) && !rval; i++) { X509_EXTENSION *ext = sk_X509_EXTENSION_value (ci->extensions, i); ASN1_OBJECT *obj = X509_EXTENSION_get_object (ext); X509V3_EXT_METHOD *convert = NULL; long ni = OBJ_obj2nid (obj); const guchar *p; char *value = NULL; int len = ext->value->length; void *ext_str = NULL; if (ni != NID_subject_alt_name) continue; /* OpenSSL >= 1.0 returns a const here, but we need to be also * * compatible with older versions that return a non-const value, * * hence the cast */ if ((convert = (X509V3_EXT_METHOD *) X509V3_EXT_get (ext)) == NULL) continue; p = ext->value->data; ext_str = ((convert->it != NULL) ? ASN1_item_d2i (NULL, &p, len, ASN1_ITEM_ptr(convert->it)) : convert->d2i (NULL, &p, len) ); if (ext_str == NULL) continue; if (convert->i2s != NULL) { value = convert->i2s (convert, ext_str); DEBUG ("got cname '%s' from subject_alt_name, which is a string", value); rval = compare_wildcarded_hostname (target, value); OPENSSL_free (value); } else if (convert->i2v != NULL) { int j; STACK_OF(CONF_VALUE) *nval = convert->i2v(convert, ext_str, NULL); for (j = 0; j < sk_CONF_VALUE_num (nval); j++) { CONF_VALUE *v = sk_CONF_VALUE_value(nval, j); if (!wocky_strdiff (v->name, "DNS")) { DEBUG ("Got cname '%s' from subject_alt_name, which is a " "multi-value stack with a 'DNS' entry", v->value); rval = compare_wildcarded_hostname (target, v->value); } } sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); } if (convert->it) ASN1_item_free (ext_str, ASN1_ITEM_ptr (convert->it)); else convert->ext_free (ext_str); } return rval; } static gboolean check_peer_names (const char *peer_name, GStrv extra_identities, X509 *cert) { gboolean tried = FALSE; if (peer_name != NULL) { if (check_peer_name (peer_name, cert)) return TRUE; tried = TRUE; } if (extra_identities != NULL) { gint i; for (i = 0; extra_identities[i] != NULL; i++) { if (wocky_strdiff (extra_identities[i], peer_name)) { if (check_peer_name (extra_identities[i], cert)) return TRUE; tried = TRUE; } } } /* If no peer names were passed it means we didn't want to check the * certificate against anything. * If some attempts were made then it means the check failed. */ return !tried; } GPtrArray * wocky_tls_session_get_peers_certificate (WockyTLSSession *session, WockyTLSCertType *type) { STACK_OF(X509) *cert_chain = NULL; guint cls = 0; GPtrArray *certificates; certificates = g_ptr_array_new_with_free_func ((GDestroyNotify) g_array_unref); cert_chain = SSL_get_peer_cert_chain (session->ssl); if (cert_chain == NULL) return NULL; if (type != NULL) *type = WOCKY_TLS_CERT_TYPE_X509; cls = sk_X509_num (cert_chain); for (guint i = 0; i < cls; i++) { GArray *certificate; X509 *peer; gint peer_len; guchar *peer_buffer; peer = sk_X509_value (cert_chain, i); peer_len = i2d_X509 (peer, NULL); certificate = g_array_sized_new (TRUE, TRUE, sizeof (guchar), peer_len); peer_buffer = g_malloc (peer_len); i2d_X509 (peer, &peer_buffer); peer_buffer -= peer_len; g_array_append_vals (certificate, peer_buffer, peer_len); g_ptr_array_add (certificates, certificate); g_free (peer_buffer); } return certificates; } static WockyTLSCertStatus _cert_status (WockyTLSSession *session, int ssl_code, WockyTLSVerificationLevel level, int old_code) { switch (ssl_code) { case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: return WOCKY_TLS_CERT_SIGNER_UNKNOWN; break; case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: case X509_V_ERR_CERT_SIGNATURE_FAILURE: case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: case X509_V_ERR_INVALID_PURPOSE: case X509_V_ERR_CERT_REJECTED: case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: return WOCKY_TLS_CERT_INVALID; break; case X509_V_ERR_CERT_REVOKED: return WOCKY_TLS_CERT_REVOKED; break; case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: case X509_V_ERR_CERT_NOT_YET_VALID: return WOCKY_TLS_CERT_NOT_ACTIVE; break; case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: case X509_V_ERR_CERT_HAS_EXPIRED: return WOCKY_TLS_CERT_EXPIRED; break; case X509_V_ERR_OUT_OF_MEM: return WOCKY_TLS_CERT_INTERNAL_ERROR; break; case X509_V_ERR_INVALID_CA: case X509_V_ERR_CERT_UNTRUSTED: case X509_V_ERR_AKID_SKID_MISMATCH: case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: return WOCKY_TLS_CERT_SIGNER_UNAUTHORISED; break; case X509_V_ERR_PATH_LENGTH_EXCEEDED: return WOCKY_TLS_CERT_MAYBE_DOS; break; case X509_V_ERR_UNABLE_TO_GET_CRL: /* if we are in STRICT mode, being unable to see the CRL is a * terminal condition: in NORMAL or LENIENT we can live with it. * Also, if we re-tried and got the same error, we're just going * to loop indefinitely, so bail out with the original error. * NOTE: 'unable to fetch' a CRL is not the same as CRL invalidated * the certificate, or we'd just turn the CRL checks off when in * NORMAL or LENIENT mode */ if (level == WOCKY_TLS_VERIFY_STRICT || old_code == X509_V_ERR_UNABLE_TO_GET_CRL) { return WOCKY_TLS_CERT_INSECURE; } else { WockyTLSCertStatus status = WOCKY_TLS_CERT_OK; X509_STORE_CTX *xctx = X509_STORE_CTX_new(); X509_STORE *store = SSL_CTX_get_cert_store(session->ctx); X509 *cert = SSL_get_peer_certificate (session->ssl); STACK_OF(X509) *chain = SSL_get_peer_cert_chain (session->ssl); long old_flags = store->param->flags; long new_flags = old_flags; DEBUG("No CRL available, but not in strict mode - re-verifying"); new_flags &= ~(X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); store->param->flags = new_flags; X509_STORE_CTX_init (xctx, store, cert, chain); X509_STORE_CTX_set_flags (xctx, new_flags); if( X509_verify_cert (xctx) < 1 ) { int new_code = X509_STORE_CTX_get_error (xctx); status = _cert_status (session, new_code, level, ssl_code); } store->param->flags = old_flags; X509_STORE_CTX_free (xctx); X509_free (cert); return status; } break; default: return WOCKY_TLS_CERT_UNKNOWN_ERROR; } } int wocky_tls_session_verify_peer (WockyTLSSession *session, const gchar *peername, GStrv extra_identities, WockyTLSVerificationLevel level, WockyTLSCertStatus *status) { int rval = -1; X509 *cert; gboolean lenient = (level == WOCKY_TLS_VERIFY_LENIENT); DEBUG (""); g_assert (status != NULL); *status = WOCKY_TLS_CERT_OK; switch (level) { case WOCKY_TLS_VERIFY_STRICT: case WOCKY_TLS_VERIFY_NORMAL: case WOCKY_TLS_VERIFY_LENIENT: break; default: g_warn_if_reached (); level = WOCKY_TLS_VERIFY_STRICT; } DEBUG ("setting ssl verify flags level to: %s", wocky_enum_to_nick (WOCKY_TYPE_TLS_VERIFICATION_LEVEL, level)); cert = SSL_get_peer_certificate (session->ssl); rval = SSL_get_verify_result (session->ssl); DEBUG ("X509 cert: %p; verified: %d", cert, rval); /* If no certificate is presented, SSL_get_verify_result() always returns * X509_V_OK. This is listed as a bug in `man 3 SSL_get_verify_result`. To * future-proof against that bug being fixed, we don't assume that behaviour. */ if (cert == NULL) { if (lenient) { *status = WOCKY_TLS_CERT_OK; return X509_V_OK; } else if (rval == X509_V_OK) { DEBUG ("Anonymous SSL handshake"); rval = X509_V_ERR_CERT_UNTRUSTED; } } else if (!check_peer_names (peername, extra_identities, cert)) { /* Irrespective of whether the certificate is valid, if it's for the * wrong host that's arguably a more useful error condition to report. */ *status = WOCKY_TLS_CERT_NAME_MISMATCH; return X509_V_ERR_APPLICATION_VERIFICATION; } if (rval != X509_V_OK) { DEBUG ("cert verification error: %d", rval); *status = _cert_status (session, rval, level, X509_V_OK); /* some conditions are to be ignored when lenient, others still matter */ if (lenient) switch (*status) { case WOCKY_TLS_CERT_INTERNAL_ERROR: case WOCKY_TLS_CERT_REVOKED: case WOCKY_TLS_CERT_MAYBE_DOS: DEBUG ("this error matters, even though we're in lenient mode"); break; default: DEBUG ("ignoring errors: we're in lenient mode"); rval = X509_V_OK; *status = WOCKY_TLS_CERT_OK; } } return rval; } static gssize wocky_tls_input_stream_read (GInputStream *stream, void *buffer, gsize count, GCancellable *cancellable, GError **error) { /* WockyTLSSession *session = WOCKY_TLS_INPUT_STREAM (stream)->session; */ DEBUG ("sync read - not implmented"); g_assert_not_reached (); return 0; } static void wocky_tls_input_stream_read_async (GInputStream *stream, void *buffer, gsize count, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyTLSSession *session = WOCKY_TLS_INPUT_STREAM (stream)->session; int ret; if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL) DEBUG (""); g_assert (session->job.read.active == FALSE); /* It is possible for a complete SSL record to be present in the read BIO * * already as a result of a previous read, since SSL_read may extract * * just the first complete record, or some or all of them: * * as a result, we may not want to issue an actual read request as the * * data we are expecting may already have been read, causing us to wait * * until the next block of data arrives over the network (which may not * * ever happen): short-circuit the actual read if this is the case: */ ret = SSL_read (session->ssl, buffer, count); if (ssl_read_is_complete (session, ret)) { GSimpleAsyncResult *r; if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL) DEBUG ("already have %d clearbytes buffered", ret); r = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, wocky_tls_input_stream_read_async); if (session->job.read.error == NULL) g_simple_async_result_set_op_res_gssize (r, ret); else g_simple_async_result_set_from_error (r, session->job.read.error); g_simple_async_result_complete_in_idle (r); g_object_unref (r); return; } wocky_tls_job_start (&session->job.read, stream, io_priority, cancellable, callback, user_data, wocky_tls_input_stream_read_async); session->job.read.buffer = buffer; session->job.read.count = count; ssl_fill (session); } static gssize wocky_tls_input_stream_read_finish (GInputStream *stream, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL) DEBUG (""); g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (stream), wocky_tls_input_stream_read_async), -1); if (g_simple_async_result_propagate_error (simple, error)) return -1; return g_simple_async_result_get_op_res_gssize (simple); } static gssize wocky_tls_output_stream_write (GOutputStream *stream, const void *buffer, gsize count, GCancellable *cancellable, GError **error) { /* WockyTLSSession *session = WOCKY_TLS_OUTPUT_STREAM (stream)->session; */ DEBUG ("sync write - not implemented"); g_assert_not_reached (); return 0; } static void wocky_tls_output_stream_write_async (GOutputStream *stream, const void *buffer, gsize count, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { int code; WockyTLSSession *session = WOCKY_TLS_OUTPUT_STREAM (stream)->session; DEBUG ("%" G_GSIZE_FORMAT " clearbytes to send", count); wocky_tls_job_start (&session->job.write, stream, io_priority, cancellable, callback, user_data, wocky_tls_output_stream_write_async); session->job.write.count = count; code = SSL_write (session->ssl, buffer, count); if (code < 0) { int error = SSL_get_error (session->ssl, code); switch (error) { case SSL_ERROR_WANT_WRITE: DEBUG ("Incomplete SSL write to BIO (theoretically impossible)"); ssl_flush (session); return; case SSL_ERROR_WANT_READ: g_warning ("write caused read: unsupported TLS re-negotiation?"); /* deliberately falling through to the default case, having logged a * more specific warning. */ default: DEBUG ("SSL write failed, setting error %d", error); /* if we haven't already generated an error, set one here: */ if(session->job.write.error == NULL) session->job.write.error = g_error_new (WOCKY_TLS_ERROR, error, "OpenSSL write: protocol error %d", error); wocky_tls_session_try_operation (session, WOCKY_TLS_OP_WRITE); return; } } ssl_flush (session); } static gssize wocky_tls_output_stream_write_finish (GOutputStream *stream, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL) DEBUG (""); { GObject *source_object; source_object = g_async_result_get_source_object (result); g_object_unref (source_object); g_return_val_if_fail (G_OBJECT (stream) == source_object, -1); } g_return_val_if_fail (wocky_tls_output_stream_write_async == g_simple_async_result_get_source_tag (simple), -1); if (g_simple_async_result_propagate_error (simple, error)) return -1; return g_simple_async_result_get_op_res_gssize (simple); } static void wocky_tls_output_stream_init (WockyTLSOutputStream *stream) { } static void wocky_tls_input_stream_init (WockyTLSInputStream *stream) { } static void wocky_tls_output_stream_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { WockyTLSOutputStream *stream = WOCKY_TLS_OUTPUT_STREAM (object); switch (prop_id) { case PROP_C_SESSION: stream->session = g_value_dup_object (value); break; default: g_assert_not_reached (); } } static void wocky_tls_output_stream_constructed (GObject *object) { WockyTLSOutputStream *stream = WOCKY_TLS_OUTPUT_STREAM (object); g_assert (stream->session); } static void wocky_tls_output_stream_finalize (GObject *object) { WockyTLSOutputStream *stream = WOCKY_TLS_OUTPUT_STREAM (object); g_object_unref (stream->session); G_OBJECT_CLASS (wocky_tls_output_stream_parent_class) ->finalize (object); } static void wocky_tls_output_stream_class_init (GOutputStreamClass *class) { GObjectClass *obj_class = G_OBJECT_CLASS (class); class->write_fn = wocky_tls_output_stream_write; class->write_async = wocky_tls_output_stream_write_async; class->write_finish = wocky_tls_output_stream_write_finish; obj_class->set_property = wocky_tls_output_stream_set_property; obj_class->constructed = wocky_tls_output_stream_constructed; obj_class->finalize = wocky_tls_output_stream_finalize; g_object_class_install_property (obj_class, PROP_O_SESSION, g_param_spec_object ("session", "TLS session", "the TLS session object for this stream", WOCKY_TYPE_TLS_SESSION, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void wocky_tls_input_stream_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { WockyTLSInputStream *stream = WOCKY_TLS_INPUT_STREAM (object); switch (prop_id) { case PROP_C_SESSION: stream->session = g_value_dup_object (value); break; default: g_assert_not_reached (); } } static void wocky_tls_input_stream_constructed (GObject *object) { WockyTLSInputStream *stream = WOCKY_TLS_INPUT_STREAM (object); g_assert (stream->session); } static void wocky_tls_input_stream_finalize (GObject *object) { WockyTLSInputStream *stream = WOCKY_TLS_INPUT_STREAM (object); g_object_unref (stream->session); G_OBJECT_CLASS (wocky_tls_input_stream_parent_class) ->finalize (object); } static void wocky_tls_input_stream_class_init (GInputStreamClass *class) { GObjectClass *obj_class = G_OBJECT_CLASS (class); class->read_fn = wocky_tls_input_stream_read; class->read_async = wocky_tls_input_stream_read_async; class->read_finish = wocky_tls_input_stream_read_finish; obj_class->set_property = wocky_tls_input_stream_set_property; obj_class->constructed = wocky_tls_input_stream_constructed; obj_class->finalize = wocky_tls_input_stream_finalize; g_object_class_install_property (obj_class, PROP_I_SESSION, g_param_spec_object ("session", "TLS session", "the TLS session object for this stream", WOCKY_TYPE_TLS_SESSION, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void wocky_tls_connection_init (WockyTLSConnection *connection) { } static void wocky_tls_session_read_ready (GObject *object, GAsyncResult *result, gpointer user_data) { WockyTLSSession *session = WOCKY_TLS_SESSION (user_data); GInputStream *input = G_INPUT_STREAM (object); GError **error = &(session->job.read.error); gssize rsize = 0; gchar *buf = session->job.handshake.job.active ? session->job.handshake.job.rbuf : session->job.read.rbuf; if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL) DEBUG (""); rsize = g_input_stream_read_finish (input, result, error); if (rsize > 0) { int x; int y; DEBUG ("received %" G_GSSIZE_FORMAT " cipherbytes, filling SSL BIO", rsize); BIO_write (session->rbio, buf, rsize); if (tls_debug_level > DEBUG_ASYNC_DETAIL_LEVEL + 1) for (x = 0; x < rsize; x += 16) { for (y = 0; y < 16 && x + y < rsize; y++) { char c = *(buf + x + y); char d = (g_ascii_isprint (c) && g_ascii_isgraph (c)) ? c : '.'; fprintf (stderr, "%02x %c ", c & 0xff, d); } fprintf (stderr, "\n"); } } /* note that we never issue a read of 0, so this _must_ be EOF (0) * * or a fatal error (-ve rval) */ else if (session->job.handshake.job.active) { if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL) DEBUG("read SSL cipherbytes (handshake) failed: %" G_GSSIZE_FORMAT, rsize); session->job.handshake.state = SSL_ERROR_SSL; } else { DEBUG ("read of SSL cipherbytes failed: %" G_GSSIZE_FORMAT, rsize); if ((*error != NULL) && ((*error)->domain == g_io_error_quark ())) { /* if there were any errors we could ignore, we'd do it like this: * * g_error_free (*error); *error = NULL; */ DEBUG ("failed op: [%d] %s", (*error)->code, (*error)->message); } /* in order for non-handshake reads to return an error properly * * we need to make sure the error in the job is set */ else if (*error == NULL) { *error = g_error_new (WOCKY_TLS_ERROR, SSL_ERROR_SSL, "unknown error"); } } wocky_tls_session_try_operation (session, WOCKY_TLS_OP_READ); } static void wocky_tls_session_write_ready (GObject *object, GAsyncResult *result, gpointer user_data) { WockyTLSSession *session = WOCKY_TLS_SESSION (user_data); gint buffered = BIO_pending (session->wbio); gssize written; if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL) DEBUG (""); written = g_output_stream_write_finish (G_OUTPUT_STREAM (object), result, &(session->job.write.error)); if (written == buffered) { DEBUG ("%d bytes written, clearing write BIO", buffered); (void) BIO_reset (session->wbio); wocky_tls_session_try_operation (session, WOCKY_TLS_OP_WRITE); } else { gchar *buffer; long bsize = BIO_get_mem_data (session->wbio, &buffer); long psize = bsize - written; /* scrub the data we did manage to write from our buffer */ if (written > 0) { gchar *pending = g_memdup (buffer + written, psize); (void) BIO_reset (session->wbio); (void) BIO_write (session->wbio, pending, psize); g_free (pending); } if (session->job.write.error != NULL) { if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL) DEBUG ("Incomplete async write [%" G_GSSIZE_FORMAT "/%d bytes]: " "%s:%u %s", written, buffered, g_quark_to_string (session->job.write.error->domain), session->job.write.error->code, session->job.write.error->message); /* if we have a non-fatal error, erase it try again */ if (g_error_matches (session->job.write.error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) g_clear_error (&(session->job.write.error)); } /* no error here means retry the operation; otherwise bail out */ if (session->job.write.error == NULL) ssl_flush (session); else wocky_tls_session_try_operation (session, WOCKY_TLS_OP_WRITE); } } static void wocky_tls_session_init (WockyTLSSession *session) { const char *level; guint lvl = 0; static gsize initialised; if G_UNLIKELY (g_once_init_enter (&initialised)) { gint malloc_init_succeeded; DEBUG ("initialising SSL library and error strings"); malloc_init_succeeded = CRYPTO_malloc_init (); g_warn_if_fail (malloc_init_succeeded); SSL_library_init (); SSL_load_error_strings (); OpenSSL_add_all_algorithms(); ENGINE_load_builtin_engines (); g_once_init_leave (&initialised, 1); } if ((level = getenv ("WOCKY_TLS_DEBUG_LEVEL")) != NULL) lvl = atoi (level); tls_debug_level = lvl; } static void wocky_tls_session_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { WockyTLSSession *session = WOCKY_TLS_SESSION (object); switch (prop_id) { case PROP_S_STREAM: session->stream = g_value_dup_object (value); break; case PROP_S_SERVER: session->server = g_value_get_boolean (value); break; case PROP_S_DHBITS: session->dh_bits = g_value_get_uint (value); break; case PROP_S_KEYFILE: session->key_file = g_value_dup_string (value); break; case PROP_S_CERTFILE: session->cert_file = g_value_dup_string (value); break; default: g_assert_not_reached (); } } static void set_dh_parameters (WockyTLSSession *session) { DH *dh; switch (session->dh_bits) { case 4096: DEBUG ("get_dh4096"); dh = get_dh4096 (); break; case 2048: DEBUG ("get_dh2048"); dh = get_dh2048 (); break; case 1024: DEBUG ("get_dh1024"); dh = get_dh1024 (); break; case 512: DEBUG ("get_dh512"); dh = get_dh512 (); break; default: DEBUG ("Bad dh-bits setting: %d, reset to 1024", session->dh_bits); dh = get_dh1024 (); } SSL_CTX_set_tmp_dh (session->ctx, dh); DH_free (dh); } static void set_ecdh_key (WockyTLSSession *session) { EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_sect163r2); if (ecdh == NULL) { DEBUG ("unable to create elliptical crypto key for sect163r2 curve"); return; } SSL_CTX_set_tmp_ecdh (session->ctx,ecdh); EC_KEY_free (ecdh); } static void wocky_tls_session_constructed (GObject *object) { WockyTLSSession *session = WOCKY_TLS_SESSION (object); if (session->server) { DEBUG ("I'm a server; using TLSv1_server_method"); /* OpenSSL >= 1.0 returns a const here, but we need to be also * * compatible with older versions that return a non-const value, * * hence the cast */ session->method = (SSL_METHOD *) TLSv1_server_method (); } else { DEBUG ("I'm a client; using TLSv1_client_method"); session->method = (SSL_METHOD *) TLSv1_client_method (); } session->ctx = SSL_CTX_new (session->method); if (!SSL_CTX_set_default_verify_paths (session->ctx)) g_warning ("SSL_CTX_set_default_verify_paths() failed"); /* verification will be done manually after the handshake: */ SSL_CTX_set_verify (session->ctx, SSL_VERIFY_NONE, NULL); SSL_CTX_set_options (session->ctx, SSL_OP_CIPHER_SERVER_PREFERENCE | /* It is usually safe to use SSL_OP_ALL to enable the bug workaround * options if compatibility with somewhat broken implementations is * desired. */ SSL_OP_ALL | /* Set the NO_TICKET option on the context to be kind to the Google Talk * server, which seems unwilling to handle empty session tickets due to a * bug in Java. * * See http://twistedmatrix.com/trac/ticket/3463 and * http://loudmouth.lighthouseapp.com/projects/17276/tickets/28. */ SSL_OP_NO_TICKET | /* SSLv2 is excessively quaint. We shouldn't be using it anyway, since * we're using TLSv1 methods, but... */ SSL_OP_NO_SSLv2); X509_STORE_set_flags (SSL_CTX_get_cert_store (session->ctx), X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); #ifdef CIPHER_LIST SSL_CTX_set_cipher_list (session->ctx, CIPHER_LIST); #endif if (session->server) { set_dh_parameters (session); set_ecdh_key (session); } if ((session->key_file != NULL) && (session->cert_file != NULL)) { long errnum; DEBUG ("cert: %s", session->cert_file); DEBUG ("key : %s", session->key_file); SSL_CTX_use_certificate_file (session->ctx, session->cert_file, SSL_FILETYPE_PEM); SSL_CTX_use_PrivateKey_file (session->ctx, session->key_file, SSL_FILETYPE_PEM); if (!SSL_CTX_check_private_key (session->ctx)) { errnum = ERR_get_error (); DEBUG ("cert/key check: %ld %s", errnum, error_to_string (errnum)); } else DEBUG ("certificate loaded"); } session->ssl = SSL_new (session->ctx); session->rbio = BIO_new (BIO_s_mem ()); session->wbio = BIO_new (BIO_s_mem ()); if (session->rbio == NULL) g_error ("Could not allocate memory BIO for SSL reads"); if (session->wbio == NULL) g_error ("Could not allocate memory BIO for SSL writes"); if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL) { int x = 0; const char *c = SSL_get_cipher_list (session->ssl, x); for (; c != NULL; c = SSL_get_cipher_list (session->ssl, ++x)) DEBUG ("%03d: %s", x, c); } if (tls_debug_level >= DEBUG_ASYNC_DETAIL_LEVEL) { BIO_set_callback (session->rbio, BIO_debug_callback); BIO_set_callback (session->wbio, BIO_debug_callback); } BIO_set_mem_eof_return (session->rbio, -1); SSL_set_bio (session->ssl, session->rbio, session->wbio); DEBUG ("done"); } static void wocky_tls_session_finalize (GObject *object) { WockyTLSSession *session = WOCKY_TLS_SESSION (object); /* the BIOs are freed by this call */ SSL_free (session->ssl); /* free (session->method); handled by SSL_CTX_free */ session->method = NULL; SSL_CTX_free (session->ctx); session->ctx = NULL; g_object_unref (session->stream); G_OBJECT_CLASS (wocky_tls_session_parent_class)->finalize (object); } static void wocky_tls_session_dispose (GObject *object) { WockyTLSSession *session = WOCKY_TLS_SESSION (object); g_free (session->key_file); session->key_file = NULL; g_free (session->cert_file); session->cert_file = NULL; G_OBJECT_CLASS (wocky_tls_session_parent_class)->dispose (object); } static void wocky_tls_session_class_init (GObjectClass *class) { class->set_property = wocky_tls_session_set_property; class->constructed = wocky_tls_session_constructed; class->finalize = wocky_tls_session_finalize; class->dispose = wocky_tls_session_dispose; g_object_class_install_property (class, PROP_S_STREAM, g_param_spec_object ("base-stream", "base stream", "the stream that TLS communicates over", G_TYPE_IO_STREAM, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property (class, PROP_S_SERVER, g_param_spec_boolean ("server", "server", "whether this is a server", FALSE, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property (class, PROP_S_DHBITS, g_param_spec_uint ("dh-bits", "Diffie-Hellman bits", "Diffie-Hellmann bits: 512, 1024, 2048, or 4096", 512, 4096, 1024, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property (class, PROP_S_KEYFILE, g_param_spec_string ("x509-key", "x509 key", "x509 PEM key file", NULL, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); g_object_class_install_property (class, PROP_S_CERTFILE, g_param_spec_string ("x509-cert", "x509 certificate", "x509 PEM certificate file", NULL, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); } static void wocky_tls_connection_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { WockyTLSConnection *connection = WOCKY_TLS_CONNECTION (object); switch (prop_id) { case PROP_C_SESSION: connection->session = g_value_dup_object (value); break; default: g_assert_not_reached (); } } static gboolean wocky_tls_connection_close (GIOStream *stream, GCancellable *cancellable, GError **error) { WockyTLSConnection *connection = WOCKY_TLS_CONNECTION (stream); return g_io_stream_close (connection->session->stream, cancellable, error); } static GInputStream * wocky_tls_connection_get_input_stream (GIOStream *io_stream) { WockyTLSConnection *connection = WOCKY_TLS_CONNECTION (io_stream); if (connection->input == NULL) connection->input = g_object_new (WOCKY_TYPE_TLS_INPUT_STREAM, "session", connection->session, NULL); return (GInputStream *)connection->input; } static GOutputStream * wocky_tls_connection_get_output_stream (GIOStream *io_stream) { WockyTLSConnection *connection = WOCKY_TLS_CONNECTION (io_stream); if (connection->output == NULL) connection->output = g_object_new (WOCKY_TYPE_TLS_OUTPUT_STREAM, "session", connection->session, NULL); return (GOutputStream *)connection->output; } static void wocky_tls_connection_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { switch (prop_id) { default: g_assert_not_reached (); } } static void wocky_tls_connection_constructed (GObject *object) { WockyTLSConnection *connection = WOCKY_TLS_CONNECTION (object); g_assert (connection->session); } static void wocky_tls_connection_finalize (GObject *object) { WockyTLSConnection *connection = WOCKY_TLS_CONNECTION (object); g_object_unref (connection->session); if (connection->input != NULL) g_object_unref (connection->input); if (connection->output != NULL) g_object_unref (connection->output); G_OBJECT_CLASS (wocky_tls_connection_parent_class) ->finalize (object); } static void wocky_tls_connection_class_init (WockyTLSConnectionClass *class) { GObjectClass *gobject_class = G_OBJECT_CLASS (class); GIOStreamClass *stream_class = G_IO_STREAM_CLASS (class); gobject_class->get_property = wocky_tls_connection_get_property; gobject_class->set_property = wocky_tls_connection_set_property; gobject_class->constructed = wocky_tls_connection_constructed; gobject_class->finalize = wocky_tls_connection_finalize; g_object_class_install_property (gobject_class, PROP_C_SESSION, g_param_spec_object ("session", "TLS session", "the TLS session object for this connection", WOCKY_TYPE_TLS_SESSION, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); stream_class->get_input_stream = wocky_tls_connection_get_input_stream; stream_class->get_output_stream = wocky_tls_connection_get_output_stream; stream_class->close_fn = wocky_tls_connection_close; } WockyTLSSession * wocky_tls_session_new (GIOStream *stream) { return g_object_new (WOCKY_TYPE_TLS_SESSION, "base-stream", stream, "server", FALSE, NULL); } /** * wocky_tls_session_server_new: * @stream: a GIOStream on which we expect to receive the client TLS handshake * @dhbits: size of the DH parameters * @key: the path to the X509 PEM key file * @cert: the path to the X509 PEM certificate * * Create a new TLS server session * * Returns: a #WockyTLSSession object */ WockyTLSSession * wocky_tls_session_server_new (GIOStream *stream, guint dhbits, const gchar* key, const gchar* cert) { if (dhbits == 0) dhbits = 1024; return g_object_new (WOCKY_TYPE_TLS_SESSION, "base-stream", stream, "dh-bits", dhbits, "x509-key", key, "x509-cert", cert, "server", TRUE, NULL); } /* this file is "borrowed" from an unmerged gnio feature: */ /* Local Variables: */ /* c-file-style: "gnu" */ /* End: */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-xmpp-reader.c0000664000175000017500000005451012212322440025553 0ustar00cassidycassidy00000000000000/* * wocky-xmpp-reader.c - Source for WockyXmppReader * Copyright (C) 2006,2009 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** * SECTION: wocky-xmpp-reader * @title: WockyXmppReader * @short_description: Xmpp XML to stanza deserializer * * The #WockyXmppReader deserializes XML to #WockyStanzas, * misc, other */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "wocky-xmpp-reader.h" #include "wocky-signals-marshal.h" #include "wocky-utils.h" #include "wocky-namespaces.h" #include "wocky-stanza.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_XMPP_READER #include "wocky-debug-internal.h" /* properties */ enum { PROP_STREAMING_MODE = 1, PROP_DEFAULT_NAMESPACE, PROP_TO, PROP_FROM, PROP_VERSION, PROP_LANG, PROP_ID, }; G_DEFINE_TYPE (WockyXmppReader, wocky_xmpp_reader, G_TYPE_OBJECT) /* Parser prototypes */ static void _start_element_ns (void *user_data, const xmlChar *localname, const xmlChar *prefix, const xmlChar *uri, int nb_namespaces, const xmlChar **namespaces, int nb_attributes, int nb_defaulted, const xmlChar **attributes); static void _end_element_ns (void *user_data, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI); static void _characters (void *user_data, const xmlChar *ch, int len); static void _error (void *user_data, xmlErrorPtr error); static xmlSAXHandler parser_handler = { /* internalSubset */ NULL, /* isStandalone */ NULL, /* hasInternalSubset */ NULL, /* hasExternalSubset */ NULL, /* resolveEntity */ NULL, /* getEntity */ NULL, /* entityDecl */ NULL, /* notationDecl */ NULL, /* attributeDecl */ NULL, /* elementDecl */ NULL, /* unparsedEntityDecl */ NULL, /* setDocumentLocator */ NULL, /* startDocument */ NULL, /* endDocument */ NULL, /* startElement */ NULL, /* endElement */ NULL, /* reference */ NULL, /* characters */ _characters, /* ignorableWhitespace */ NULL, /* processingInstruction */ NULL, /* comment */ NULL, /* warning */ NULL, /* error */ NULL, /* fatalError */ NULL, /* getParameterEntity */ NULL, /* cdataBlock */ NULL, /* externalSubset */ NULL, /* initialized */ XML_SAX2_MAGIC, /* _private */ NULL, /* startElementNs */ _start_element_ns, /* endElementNs */ _end_element_ns, /* serror */ _error }; /* private structure */ struct _WockyXmppReaderPrivate { xmlParserCtxtPtr parser; guint depth; WockyStanza *stanza; WockyNode *node; GQueue *nodes; gchar *to; gchar *from; gchar *version; gchar *lang; gchar *id; gboolean dispose_has_run; GError *error /* defeat the coding style checker... */; gboolean stream_mode; gchar *default_namespace; GQueue *stanzas; WockyXmppReaderState state; }; /** * wocky_xmpp_reader_error_quark * * Get the error quark used by the reader. * * Returns: the quark for reader errors. */ GQuark wocky_xmpp_reader_error_quark (void) { static GQuark quark = 0; if (quark == 0) quark = g_quark_from_static_string ("wocky-xmpp-reader-error"); return quark; } /* clear parser state */ static void wocky_xmpp_reader_clear_parser_state (WockyXmppReader *self) { WockyXmppReaderPrivate *priv = self->priv; while (!g_queue_is_empty (priv->stanzas)) { gpointer stanza; stanza = g_queue_pop_head (priv->stanzas); if (stanza != NULL) g_object_unref (stanza); } if (priv->stanza != NULL) g_object_unref (priv->stanza); priv->stanza = NULL; g_queue_clear (priv->nodes); priv->node = NULL; priv->depth = 0; g_free (priv->to); priv->to = NULL; g_free (priv->from); priv->from = NULL; g_free (priv->lang); priv->lang = NULL; g_free (priv->version); priv->version = NULL; g_free (priv->id); priv->id = NULL; if (priv->error != NULL) g_error_free (priv->error); priv->error = NULL; if (priv->parser != NULL) xmlFreeParserCtxt (priv->parser); priv->parser = NULL; priv->state = WOCKY_XMPP_READER_STATE_CLOSED; } static void wocky_init_xml_parser (WockyXmppReader *obj) { WockyXmppReaderPrivate *priv = obj->priv; priv->parser = xmlCreatePushParserCtxt (&parser_handler, obj, NULL, 0, NULL); xmlCtxtUseOptions (priv->parser, XML_PARSE_NOENT); priv->state = priv->stream_mode ? WOCKY_XMPP_READER_STATE_INITIAL : WOCKY_XMPP_READER_STATE_OPENED; } static void wocky_xmpp_reader_constructed (GObject *obj) { wocky_init_xml_parser (WOCKY_XMPP_READER (obj)); } static void wocky_xmpp_reader_init (WockyXmppReader *self) { WockyXmppReaderPrivate *priv; self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_XMPP_READER, WockyXmppReaderPrivate); priv = self->priv; priv->nodes = g_queue_new (); priv->stanzas = g_queue_new (); } static void wocky_xmpp_reader_dispose (GObject *object); static void wocky_xmpp_reader_finalize (GObject *object); static void wocky_xmpp_reader_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec); static void wocky_xmpp_reader_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec); static void wocky_xmpp_reader_class_init (WockyXmppReaderClass *wocky_xmpp_reader_class) { GObjectClass *object_class = G_OBJECT_CLASS (wocky_xmpp_reader_class); GParamSpec *param_spec; g_type_class_add_private (wocky_xmpp_reader_class, sizeof (WockyXmppReaderPrivate)); wocky_xmpp_reader_class->stream_element_name = "stream"; wocky_xmpp_reader_class->stream_element_ns = WOCKY_XMPP_NS_STREAM; object_class->constructed = wocky_xmpp_reader_constructed; object_class->dispose = wocky_xmpp_reader_dispose; object_class->finalize = wocky_xmpp_reader_finalize; object_class->set_property = wocky_xmpp_reader_set_property; object_class->get_property = wocky_xmpp_reader_get_property; param_spec = g_param_spec_boolean ("streaming-mode", "streaming-mode", "Whether the xml to be read is one big stream or separate documents", TRUE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_STREAMING_MODE, param_spec); param_spec = g_param_spec_string ("default-namespace", "default namespace", "The default namespace for the root element of the document. " "Only meaningful if streaming-mode is FALSE.", "", G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_DEFAULT_NAMESPACE, param_spec); param_spec = g_param_spec_string ("to", "to", "to attribute in the xml stream opening", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_TO, param_spec); param_spec = g_param_spec_string ("from", "from", "from attribute in the xml stream opening", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_FROM, param_spec); param_spec = g_param_spec_string ("version", "version", "version attribute in the xml stream opening", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_VERSION, param_spec); param_spec = g_param_spec_string ("lang", "lang", "xml:lang attribute in the xml stream opening", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_LANG, param_spec); param_spec = g_param_spec_string ("id", "ID", "id attribute in the xml stream opening", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ID, param_spec); } void wocky_xmpp_reader_dispose (GObject *object) { WockyXmppReader *self = WOCKY_XMPP_READER (object); WockyXmppReaderPrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; /* release any references held by the object here */ wocky_xmpp_reader_clear_parser_state (self); if (G_OBJECT_CLASS (wocky_xmpp_reader_parent_class)->dispose) G_OBJECT_CLASS (wocky_xmpp_reader_parent_class)->dispose (object); } void wocky_xmpp_reader_finalize (GObject *object) { WockyXmppReader *self = WOCKY_XMPP_READER (object); WockyXmppReaderPrivate *priv = self->priv; /* free any data held directly by the object here */ g_queue_free (priv->stanzas); g_queue_free (priv->nodes); if (priv->error != NULL) g_error_free (priv->error); G_OBJECT_CLASS (wocky_xmpp_reader_parent_class)->finalize (object); } static void wocky_xmpp_reader_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyXmppReader *reader = WOCKY_XMPP_READER (object); WockyXmppReaderPrivate *priv = reader->priv; switch (property_id) { case PROP_STREAMING_MODE: priv->stream_mode = g_value_get_boolean (value); break; case PROP_DEFAULT_NAMESPACE: g_free (priv->default_namespace); priv->default_namespace = g_value_dup_string (value); if (priv->default_namespace == NULL) priv->default_namespace = g_strdup (""); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_xmpp_reader_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyXmppReader *reader = WOCKY_XMPP_READER (object); WockyXmppReaderPrivate *priv = reader->priv; switch (property_id) { case PROP_STREAMING_MODE: g_value_set_boolean (value, priv->stream_mode); break; case PROP_DEFAULT_NAMESPACE: g_value_set_string (value, priv->default_namespace); break; case PROP_FROM: g_value_set_string (value, priv->from); break; case PROP_TO: g_value_set_string (value, priv->to); break; case PROP_LANG: g_value_set_string (value, priv->lang); break; case PROP_VERSION: g_value_set_string (value, priv->version); break; case PROP_ID: g_value_set_string (value, priv->id); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } /** * wocky_xmpp_reader_new: * * Convenience function to create a new #WockyXmppReader. * * Returns: a new #WockyXmppReader */ WockyXmppReader * wocky_xmpp_reader_new (void) { return g_object_new (WOCKY_TYPE_XMPP_READER, NULL); } /** * wocky_xmpp_reader_new_no_stream: * * Convenience function to create a new #WockyXmppReader that has streaming * mode disabled. * * Returns: a new #WockyXmppReader in non-streaming mode */ WockyXmppReader * wocky_xmpp_reader_new_no_stream (void) { return g_object_new (WOCKY_TYPE_XMPP_READER, "streaming-mode", FALSE, NULL); } /** * wocky_xmpp_reader_new_no_stream_ns: * @default_namespace: default XML namespace to apply to the top-level element * * Create a new #WockyXmppReader, with #WockyXmppReader:streaming-mode disabled * and the specified #WockyXmppReader:default-namespace. * * Returns: (transfer full): a new #WockyXmppReader in non-streaming mode. */ WockyXmppReader * wocky_xmpp_reader_new_no_stream_ns ( const gchar *default_namespace) { return g_object_new (WOCKY_TYPE_XMPP_READER, "streaming-mode", FALSE, "default-namespace", default_namespace, NULL); } static void handle_stream_open ( WockyXmppReader *self, const gchar *localname, const gchar *uri, const gchar *prefix, int nb_attributes, const xmlChar **attributes) { WockyXmppReaderClass *klass = WOCKY_XMPP_READER_GET_CLASS (self); WockyXmppReaderPrivate *priv = self->priv; int i; if (wocky_strdiff (klass->stream_element_name, localname) || wocky_strdiff (klass->stream_element_ns, uri)) { priv->error = g_error_new (WOCKY_XMPP_READER_ERROR, WOCKY_XMPP_READER_ERROR_INVALID_STREAM_START, "Invalid start of the XMPP stream " "(expected <%s xmlns=%s>, got <%s xmlns=%s>)", klass->stream_element_name, klass->stream_element_ns, localname, uri); g_queue_push_tail (priv->stanzas, NULL); return; } DEBUG ("Received stream opening: %s, prefix: %s, uri: %s", localname, prefix != NULL ? prefix : "", uri != NULL ? uri : ""); priv->state = WOCKY_XMPP_READER_STATE_OPENED; for (i = 0; i < nb_attributes * 5; i+=5) { /* attr_name and attr_value are guaranteed non-NULL; attr_prefix and * attr_uri may be NULL. */ const gchar *attr_name = (const gchar *) attributes[i]; const gchar *attr_prefix = (const gchar *) attributes[i+1]; const gchar *attr_uri = (const gchar *) attributes[i+2]; gsize value_len = attributes[i+4] - attributes[i+3]; gchar *attr_value = g_strndup ( (const gchar *) attributes[i+3], value_len); DEBUG ("Stream opening attribute: %s = '%s' (prefix: %s, uri: %s)", attr_name, attr_value, attr_prefix != NULL ? attr_prefix : "", attr_uri != NULL ? attr_uri : ""); if (!strcmp (attr_name, "to")) { g_free (priv->to); priv->to = attr_value; } else if (!strcmp (attr_name, "from")) { g_free (priv->from); priv->from = attr_value; } else if (!strcmp (attr_name, "version")) { g_free (priv->version); priv->version = attr_value; } else if (!strcmp (attr_name, "lang") && !wocky_strdiff (attr_prefix, "xml")) { g_free (priv->lang); priv->lang = attr_value; } else if (!strcmp (attr_name, "id")) { g_free (priv->id); priv->id = attr_value; } else { g_free (attr_value); } } priv->depth++; } static void handle_regular_element ( WockyXmppReader *self, const gchar *localname, const gchar *uri, int nb_attributes, const xmlChar **attributes) { WockyXmppReaderPrivate *priv = self->priv; int i; if (priv->stanza == NULL) { if (uri != NULL) { priv->stanza = wocky_stanza_new (localname, uri); } else { /* This can only happy in non-streaming mode when the top node * of the document doesn't have a namespace. */ DEBUG ("Stanza without a namespace, using default namespace '%s'", priv->default_namespace); priv->stanza = wocky_stanza_new (localname, priv->default_namespace); } priv->node = wocky_stanza_get_top_node (priv->stanza); } else { g_queue_push_tail (priv->nodes, priv->node); priv->node = wocky_node_add_child_ns (priv->node, localname, uri); } for (i = 0; i < nb_attributes * 5; i+=5) { /* attr_name and attr_value are guaranteed non-NULL; attr_prefix and * attr_uri may be NULL. */ const gchar *attr_name = (const gchar *) attributes[i]; const gchar *attr_prefix = (const gchar *) attributes[i+1]; const gchar *attr_uri = (const gchar *) attributes[i+2]; /* Not NULL-terminated! */ const gchar *attr_value = (const gchar *) attributes[i+3]; gsize value_len = attributes[i+4] - attributes[i+3]; if (!wocky_strdiff (attr_prefix, "xml") && !wocky_strdiff (attr_name, "lang")) { wocky_node_set_language_n (priv->node, attr_value, value_len); } else { /* preserve the prefix, if any was received */ if (attr_prefix != NULL) { GQuark ns = g_quark_from_string (attr_uri); wocky_node_attribute_ns_set_prefix (ns, attr_prefix); } wocky_node_set_attribute_n_ns (priv->node, attr_name, attr_value, value_len, attr_uri); } } priv->depth++; } static void _start_element_ns (void *user_data, const xmlChar *localname, const xmlChar *prefix, const xmlChar *ns_uri, int nb_namespaces, const xmlChar **namespaces, int nb_attributes, int nb_defaulted, const xmlChar **attributes) { WockyXmppReader *self = WOCKY_XMPP_READER (user_data); WockyXmppReaderPrivate *priv = self->priv; gchar *uri = NULL; if (ns_uri != NULL) uri = g_strstrip (g_strdup ((const gchar *) ns_uri)); if (priv->stream_mode && G_UNLIKELY (priv->depth == 0)) handle_stream_open (self, (const gchar *) localname, uri, (const gchar *) prefix, nb_attributes, attributes); else handle_regular_element (self, (const gchar *) localname, uri, nb_attributes, attributes); g_free (uri); } static void _characters (void *user_data, const xmlChar *ch, int len) { WockyXmppReader *self = WOCKY_XMPP_READER (user_data); WockyXmppReaderPrivate *priv = self->priv; if (priv->node != NULL) { wocky_node_append_content_n (priv->node, (const gchar *)ch, (gsize)len); } } static void _end_element_ns (void *user_data, const xmlChar *localname, const xmlChar *prefix, const xmlChar *uri) { WockyXmppReader *self = WOCKY_XMPP_READER (user_data); WockyXmppReaderPrivate *priv = self->priv; priv->depth--; if (priv->stream_mode && priv->depth == 0) { DEBUG ("Stream ended"); g_queue_push_tail (priv->stanzas, NULL); } else if (priv->depth == (priv->stream_mode ? 1 : 0)) { g_assert (g_queue_get_length (priv->nodes) == 0); DEBUG_STANZA (priv->stanza, "Received stanza"); g_queue_push_tail (priv->stanzas, priv->stanza); priv->stanza = NULL; priv->node = NULL; } else { priv->node = (WockyNode *) g_queue_pop_tail (priv->nodes); } } static void _error (void *user_data, xmlErrorPtr error) { WockyXmppReader *self = WOCKY_XMPP_READER (user_data); WockyXmppReaderPrivate *priv = self->priv; if (error->level < XML_ERR_FATAL) { DEBUG ("Ignoring parser %s: %s", error->level == XML_ERR_WARNING ? "warning" : "recoverable error", error->message); return; } priv->error = g_error_new_literal (WOCKY_XMPP_READER_ERROR, WOCKY_XMPP_READER_ERROR_PARSE_ERROR, error->message); DEBUG ("Parsing failed %s", error->message); g_queue_push_tail (priv->stanzas, NULL); } /** * wocky_xmpp_reader_get_state: * @reader: a #WockyXmppReader * * Returns: The current state of the reader */ WockyXmppReaderState wocky_xmpp_reader_get_state (WockyXmppReader *reader) { WockyXmppReaderPrivate *priv = reader->priv; return priv->state; } /* When the end of stream is reached the parser puts a NULL entry on the * queue. When that's the only entry left, go into either closed or ready state * (depending if an error was hit) */ static void wocky_xmpp_reader_check_eos (WockyXmppReader *reader) { WockyXmppReaderPrivate *priv = reader->priv; if (!g_queue_is_empty (priv->stanzas) && g_queue_peek_head (priv->stanzas) == NULL) { priv->state = priv->error ? WOCKY_XMPP_READER_STATE_ERROR : WOCKY_XMPP_READER_STATE_CLOSED; } } /** * wocky_xmpp_reader_push: * @reader: a WockyXmppReader * @data: Data to read * @length: Size of @data * * Push an amount of data to parse. */ void wocky_xmpp_reader_push (WockyXmppReader *reader, const guint8 *data, gsize length) { WockyXmppReaderPrivate *priv = reader->priv; xmlParserCtxtPtr parser; g_return_if_fail (priv->state < WOCKY_XMPP_READER_STATE_CLOSED); #ifdef ENABLE_DEBUG wocky_debug (WOCKY_DEBUG_NET, "Parsing chunk: %.*s", (int)length, data); #endif parser = priv->parser; xmlParseChunk (parser, (const char*)data, length, FALSE); wocky_xmpp_reader_check_eos (reader); } /** * wocky_xmpp_reader_peek_stanza: * @reader: a #WockyXmppReader * * Returns the first #WockyStanza available from reader or NULL * if there are no available stanzas. The stanza is not removed from the * readers queue * * Returns: One #WockyStanza or NULL if there are no available stanzas. The * stanza is owned by the #WockyXmppReader */ WockyStanza * wocky_xmpp_reader_peek_stanza (WockyXmppReader *reader) { WockyXmppReaderPrivate *priv = reader->priv; return g_queue_peek_head (priv->stanzas); } /** * wocky_xmpp_reader_pop_stanza: * @reader: a #WockyXmppReader * * Gets one #WockyStanza out of the reader or NULL if there are no * available stanzas. * * Returns: One #WockyStanza or NULL if there are no available stanzas. * Caller owns the returned stanza. */ WockyStanza * wocky_xmpp_reader_pop_stanza (WockyXmppReader *reader) { WockyXmppReaderPrivate *priv = reader->priv; WockyStanza *s; if (g_queue_is_empty (priv->stanzas)) return NULL; s = g_queue_pop_head (priv->stanzas); wocky_xmpp_reader_check_eos (reader); if (!priv->stream_mode) { priv->state = WOCKY_XMPP_READER_STATE_CLOSED; } return s; } /** * wocky_xmpp_reader_get_error: * @reader: a #WockyXmppReader * * Get the error from the reader * * Returns: A copy of the error as encountered by the reader or NULL if there * was no error. Free after use. */ GError * wocky_xmpp_reader_get_error (WockyXmppReader *reader) { WockyXmppReaderPrivate *priv = reader->priv; return priv->error == NULL ? NULL : g_error_copy (priv->error); } /** * wocky_xmpp_reader_reset: * @reader: a #WockyXmppReader * * Reset the xml parser. * */ void wocky_xmpp_reader_reset (WockyXmppReader *reader) { DEBUG ("Resetting the xmpp reader"); wocky_xmpp_reader_clear_parser_state (reader); wocky_init_xml_parser (reader); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-xep-0115-capabilities.c0000664000175000017500000000434412005516162027144 0ustar00cassidycassidy00000000000000/* * wocky-xep-0115-capabilities.c - interface for holding capabilities * of contacts * * Copyright (C) 2011-2012 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "wocky-xep-0115-capabilities.h" #include "wocky-contact.h" G_DEFINE_INTERFACE (WockyXep0115Capabilities, wocky_xep_0115_capabilities, G_TYPE_OBJECT); static void wocky_xep_0115_capabilities_default_init ( WockyXep0115CapabilitiesInterface *interface) { GType iface_type = G_TYPE_FROM_INTERFACE (interface); static gsize initialization_value = 0; if (g_once_init_enter (&initialization_value)) { g_signal_new ("capabilities-changed", iface_type, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); g_once_init_leave (&initialization_value, 1); } } const GPtrArray * wocky_xep_0115_capabilities_get_data_forms ( WockyXep0115Capabilities *contact) { WockyXep0115CapabilitiesInterface *iface = WOCKY_XEP_0115_CAPABILITIES_GET_INTERFACE (contact); WockyXep0115CapabilitiesGetDataFormsFunc method = iface->get_data_forms; if (method != NULL) return method (contact); return NULL; } gboolean wocky_xep_0115_capabilities_has_feature ( WockyXep0115Capabilities *contact, const gchar *feature) { WockyXep0115CapabilitiesInterface *iface = WOCKY_XEP_0115_CAPABILITIES_GET_INTERFACE (contact); WockyXep0115CapabilitiesHasFeatureFunc method = iface->has_feature; if (method != NULL) return method (contact, feature); return FALSE; } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky.h0000664000175000017500000000603712212322440023337 0ustar00cassidycassidy00000000000000/* * wocky.h - Header for general functions * Copyright (C) 2009 Collabora Ltd. * @author Guillaume Desmottes * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __WOCKY_H__ #define __WOCKY_H__ #include #define WOCKY_H_INSIDE #include "wocky-auth-handler.h" #include "wocky-auth-registry.h" #include "wocky-bare-contact.h" #include "wocky-c2s-porter.h" #include "wocky-caps-cache.h" #include "wocky-caps-hash.h" #include "wocky-connector.h" #include "wocky-contact-factory.h" #include "wocky-contact.h" #include "wocky-data-form.h" #include "wocky-debug.h" #include "wocky-disco-identity.h" #include "wocky-enumtypes.h" #include "wocky-jabber-auth-digest.h" #include "wocky-jabber-auth.h" #include "wocky-jabber-auth-password.h" #include "wocky-jingle-content.h" #include "wocky-jingle-factory.h" #include "wocky-jingle-info.h" #include "wocky-jingle-media-rtp.h" #include "wocky-jingle-session.h" #include "wocky-jingle-transport-google.h" #include "wocky-jingle-transport-iceudp.h" #include "wocky-jingle-transport-iface.h" #include "wocky-jingle-transport-rawudp.h" #include "wocky-jingle-types.h" #include "wocky-ll-connection-factory.h" #include "wocky-ll-connector.h" #include "wocky-ll-contact.h" #include "wocky-loopback-stream.h" #include "wocky-meta-porter.h" #include "wocky-muc.h" #include "wocky-namespaces.h" #include "wocky-node.h" #include "wocky-node-tree.h" #include "wocky-pep-service.h" #include "wocky-ping.h" #include "wocky-porter.h" #include "wocky-pubsub-helpers.h" #include "wocky-pubsub-node.h" #include "wocky-pubsub-node-protected.h" #include "wocky-pubsub-service.h" #include "wocky-pubsub-service-protected.h" #include "wocky-resource-contact.h" #include "wocky-roster.h" #include "wocky-sasl-auth.h" #include "wocky-sasl-digest-md5.h" #include "wocky-sasl-plain.h" #include "wocky-sasl-scram.h" #include "wocky-sasl-utils.h" #include "wocky-session.h" #include "wocky-stanza.h" #include "wocky-tls-connector.h" #include "wocky-tls.h" #include "wocky-tls-handler.h" #include "wocky-types.h" #include "wocky-utils.h" #include "wocky-xep-0115-capabilities.h" #include "wocky-xmpp-connection.h" #include "wocky-xmpp-error.h" #include "wocky-xmpp-reader.h" #include "wocky-xmpp-writer.h" #undef WOCKY_H_INSIDE G_BEGIN_DECLS void wocky_init (void); void wocky_deinit (void); G_END_DECLS #endif /* #ifndef __WOCKY_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-xmpp-error.c0000664000175000017500000005202512212322440025441 0ustar00cassidycassidy00000000000000/* * wocky-xmpp-error.c - Source for Wocky's XMPP error handling API * Copyright (C) 2006-2009 Collabora Ltd. * Copyright (C) 2006 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-xmpp-error.h" #include #include #include "wocky-namespaces.h" #include "wocky-utils.h" /* Definitions of XMPP core stanza errors, as per RFC 3920 §9.3; plus the * corresponding legacy error codes as described by XEP-0086. */ #define MAX_LEGACY_ERRORS 3 typedef struct { const gchar *description; WockyXmppErrorType type; const guint16 legacy_errors[MAX_LEGACY_ERRORS]; } XmppErrorSpec; static const XmppErrorSpec xmpp_errors[NUM_WOCKY_XMPP_ERRORS] = { /* undefined-condition */ { "application-specific condition", WOCKY_XMPP_ERROR_TYPE_CANCEL, { 500, 0, }, }, /* redirect */ { "the recipient or server is redirecting requests for this information " "to another entity", WOCKY_XMPP_ERROR_TYPE_MODIFY, { 302, 0, }, }, /* gone */ { "the recipient or server can no longer be contacted at this address", WOCKY_XMPP_ERROR_TYPE_MODIFY, { 302, 0, }, }, /* bad-request */ { "the sender has sent XML that is malformed or that cannot be processed", WOCKY_XMPP_ERROR_TYPE_MODIFY, { 400, 0, }, }, /* unexpected-request */ { "the recipient or server understood the request but was not expecting " "it at this time", WOCKY_XMPP_ERROR_TYPE_WAIT, { 400, 0, }, }, /* jid-malformed */ { "the sending entity has provided or communicated an XMPP address or " "aspect thereof (e.g., a resource identifier) that does not adhere " "to the syntax defined in Addressing Scheme (Section 3)", WOCKY_XMPP_ERROR_TYPE_MODIFY, { 400, 0, }, }, /* not-authorized */ { "the sender must provide proper credentials before being allowed to " "perform the action, or has provided improper credentials", WOCKY_XMPP_ERROR_TYPE_AUTH, { 401, 0, }, }, /* payment-required */ { "the requesting entity is not authorized to access the requested " "service because payment is required", WOCKY_XMPP_ERROR_TYPE_AUTH, { 402, 0, }, }, /* forbidden */ { "the requesting entity does not possess the required permissions to " "perform the action", WOCKY_XMPP_ERROR_TYPE_AUTH, { 403, 0, }, }, /* item-not-found */ { "the addressed JID or item requested cannot be found", WOCKY_XMPP_ERROR_TYPE_CANCEL, { 404, 0, }, }, /* recipient-unavailable */ { "the intended recipient is temporarily unavailable", WOCKY_XMPP_ERROR_TYPE_WAIT, { 404, 0, }, }, /* remote-server-not-found */ { "a remote server or service specified as part or all of the JID of the " "intended recipient (or required to fulfill a request) could not be " "contacted within a reasonable amount of time", WOCKY_XMPP_ERROR_TYPE_CANCEL, { 404, 0, }, }, /* not-allowed */ { "the recipient or server does not allow any entity to perform the action", WOCKY_XMPP_ERROR_TYPE_CANCEL, { 405, 0, }, }, /* not-acceptable */ { "the recipient or server understands the request but is refusing to " "process it because it does not meet criteria defined by the recipient " "or server (e.g., a local policy regarding acceptable words in messages)", WOCKY_XMPP_ERROR_TYPE_MODIFY, { 406, 0, }, }, /* registration-required */ { "the requesting entity is not authorized to access the requested service " "because registration is required", WOCKY_XMPP_ERROR_TYPE_AUTH, { 407, 0, }, }, /* subscription-required */ { "the requesting entity is not authorized to access the requested service " "because a subscription is required", WOCKY_XMPP_ERROR_TYPE_AUTH, { 407, 0, }, }, /* remote-server-timeout */ { "a remote server or service specified as part or all of the JID of the " "intended recipient (or required to fulfill a request) could not be " "contacted within a reasonable amount of time", WOCKY_XMPP_ERROR_TYPE_WAIT, { 504, 408, 0, }, }, /* conflict */ { "access cannot be granted because an existing resource or session exists " "with the same name or address", WOCKY_XMPP_ERROR_TYPE_CANCEL, { 409, 0, }, }, /* internal-server-error */ { "the server could not process the stanza because of a misconfiguration " "or an otherwise-undefined internal server error", WOCKY_XMPP_ERROR_TYPE_WAIT, { 500, 0, }, }, /* resource-constraint */ { "the server or recipient lacks the system resources necessary to service " "the request", WOCKY_XMPP_ERROR_TYPE_WAIT, { 500, 0, }, }, /* feature-not-implemented */ { "the feature requested is not implemented by the recipient or server and " "therefore cannot be processed", WOCKY_XMPP_ERROR_TYPE_CANCEL, { 501, 0, }, }, /* service-unavailable */ { "the server or recipient does not currently provide the requested " "service", WOCKY_XMPP_ERROR_TYPE_CANCEL, { 503, 502, 510, }, }, /* policy-violation */ { "the entity has violated some local service policy (e.g., a message " "contains words that are prohibited by the service)", /* TODO: should support either MODIFY or WAIT depending on the policy * being violated */ WOCKY_XMPP_ERROR_TYPE_MODIFY, { 406, 0, }, }, }; GQuark wocky_xmpp_error_quark (void) { static GQuark quark = 0; if (quark == 0) quark = g_quark_from_static_string (WOCKY_XMPP_NS_STANZAS); return quark; } /** * wocky_xmpp_error_string: * @error: a core stanza error * * * * Returns: the name of the tag corresponding to @error */ const gchar * wocky_xmpp_error_string (WockyXmppError error) { return wocky_enum_to_nick (WOCKY_TYPE_XMPP_ERROR, error); } /** * wocky_xmpp_error_description: * @error: a core stanza error * * * * Returns: a description of the error, in English, as specified in XMPP Core */ const gchar * wocky_xmpp_error_description (WockyXmppError error) { if (error < NUM_WOCKY_XMPP_ERRORS) return xmpp_errors[error].description; else return NULL; } static GList *error_domains = NULL; /** * wocky_xmpp_error_register_domain * @domain: a description of the error domain * * Registers a new set of application-specific stanza errors. This allows * GErrors in that domain to be passed to wocky_stanza_error_to_node(), and to * be recognized and returned by wocky_xmpp_error_extract() (and * wocky_stanza_extract_errors(), by extension). */ void wocky_xmpp_error_register_domain (WockyXmppErrorDomain *domain) { error_domains = g_list_prepend (error_domains, domain); } static WockyXmppErrorDomain * xmpp_error_find_domain (GQuark domain) { GList *l; for (l = error_domains; l != NULL; l = l->next) { WockyXmppErrorDomain *d = l->data; if (d->domain == domain) return d; } return NULL; } /** * wocky_xmpp_stanza_error_to_string: * @error: an error in the domain %WOCKY_XMPP_ERROR, or another domain * registered with wocky_xmpp_error_register_domain() (such as * %WOCKY_JINGLE_ERROR). * * Returns the name of the XMPP stanza error element represented by @error. * This is intended for use in debugging messages, with %GErrors returned by * wocky_stanza_extract_errors(). * * Returns: the error code as a string, or %NULL if * error->domain is not known to Wocky. */ const gchar * wocky_xmpp_stanza_error_to_string (GError *error) { g_return_val_if_fail (error != NULL, NULL); if (error->domain == WOCKY_XMPP_ERROR) { return wocky_enum_to_nick (WOCKY_TYPE_XMPP_ERROR, error->code); } else { WockyXmppErrorDomain *domain = xmpp_error_find_domain (error->domain); if (domain != NULL) return wocky_enum_to_nick (domain->enum_type, error->code); else return NULL; } } /* Static, but bears documenting. * * xmpp_error_from_node_for_ns: * @node: a node believed to contain an error child * @ns: the namespace for errors corresponding to @enum_type * @enum_type: a GEnum of error codes * @code: location at which to store an error code * * Scans @node's children for nodes in @ns whose name corresponds to a nickname * of a value of @enum_type, storing the value in @code if found. * * Returns: %TRUE if an error code was retrieved. */ static gboolean xmpp_error_from_node_for_ns ( WockyNode *node, GQuark ns, GType enum_type, gint *code) { GSList *l; for (l = node->children; l != NULL; l = l->next) { WockyNode *child = l->data; if (wocky_node_has_ns_q (child, ns) && wocky_enum_from_nick (enum_type, child->name, code)) return TRUE; } return FALSE; } /* Attempts to divine a WockyXmppError from a legacy numeric code='' attribute */ static WockyXmppError xmpp_error_from_code (WockyNode *error_node, WockyXmppErrorType *type) { const gchar *code = wocky_node_get_attribute (error_node, "code"); gint error_code, i, j; if (code == NULL) goto out; error_code = atoi (code); /* skip UNDEFINED_CONDITION, we want code 500 to be translated * to INTERNAL_SERVER_ERROR */ for (i = 1; i < NUM_WOCKY_XMPP_ERRORS; i++) { const XmppErrorSpec *spec = &xmpp_errors[i]; for (j = 0; j < MAX_LEGACY_ERRORS; j++) { gint cur_code = spec->legacy_errors[j]; if (cur_code == 0) break; if (cur_code == error_code) { if (type != NULL) *type = spec->type; return i; } } } out: if (type != NULL) *type = WOCKY_XMPP_ERROR_TYPE_CANCEL; return WOCKY_XMPP_ERROR_UNDEFINED_CONDITION; } /** * wocky_xmpp_error_extract: * @error: the <error/> child of a stanza with type='error' * @type: location at which to store the error type * @core: location at which to store an error in the domain #WOCKY_XMPP_ERROR * @specialized: location at which to store an error in an application-specific * domain, if one is found * @specialized_node: location at which to store the node representing an * application-specific error, if one is found * * Given an <error/> node, breaks it down into values describing the error. * @type and @core are guaranteed to be set; @specialized and @specialized_node * will be set if a recognised application-specific error is found, and the * latter will be set to %NULL if no application-specific error is found. * * Any or all of the out parameters may be %NULL to ignore the value. The * value stored in @specialized_node is borrowed from @stanza, and is only * valid as long as the latter is alive. */ void wocky_xmpp_error_extract (WockyNode *error, WockyXmppErrorType *type, GError **core, GError **specialized, WockyNode **specialized_node) { gboolean found_core_error = FALSE; gint core_code = WOCKY_XMPP_ERROR_UNDEFINED_CONDITION; GQuark specialized_domain = 0; gint specialized_code; gboolean have_specialized = FALSE; WockyNode *specialized_node_tmp = NULL; const gchar *message = NULL; GSList *l; g_return_if_fail (!wocky_strdiff (error->name, "error")); /* The type='' attributes being present and one of the defined five is a * MUST; if the other party is getting XMPP *that* wrong, 'cancel' seems like * a sensible default. (If the other party only uses legacy error codes, the * call to xmpp_error_from_code() below will try to improve on that default.) */ if (type != NULL) { const gchar *type_attr = wocky_node_get_attribute (error, "type"); gint type_i; if (type_attr != NULL && wocky_enum_from_nick (WOCKY_TYPE_XMPP_ERROR_TYPE, type_attr, &type_i)) { *type = type_i; /* Don't let the xmpp_error_from_code() path below clobber the valid * type we found. */ type = NULL; } else { *type = WOCKY_XMPP_ERROR_TYPE_CANCEL; } } for (l = error->children; l != NULL; l = g_slist_next (l)) { WockyNode *child = l->data; if (child->ns == WOCKY_XMPP_ERROR) { if (!wocky_strdiff (child->name, "text")) { message = child->content; } else if (!found_core_error) { /* See if the element is a XMPP Core stanza error we know about, * given that we haven't found one yet. */ found_core_error = wocky_enum_from_nick (WOCKY_TYPE_XMPP_ERROR, child->name, &core_code); } } else if (specialized_node_tmp == NULL) { WockyXmppErrorDomain *domain; specialized_node_tmp = child; /* This could be a specialized error; let's check if it's in a * namespace we know about, and if so that it's an element name we * know. */ domain = xmpp_error_find_domain (child->ns); if (domain != NULL) { specialized_domain = child->ns; if (wocky_enum_from_nick (domain->enum_type, child->name, &specialized_code)) { have_specialized = TRUE; } } } } /* If we don't have an XMPP Core stanza error yet, maybe the peer uses Þe * Olde Numeric Error Codes. */ if (!found_core_error) core_code = xmpp_error_from_code (error, type); /* okay, time to make some errors */ if (message == NULL) message = ""; g_set_error_literal (core, WOCKY_XMPP_ERROR, core_code, message); if (have_specialized) g_set_error_literal (specialized, specialized_domain, specialized_code, message); if (specialized_node != NULL) *specialized_node = specialized_node_tmp; } /** * wocky_g_error_to_node: * @error: an error in the domain #WOCKY_XMPP_ERROR, or in an * application-specific domain registered with * wocky_xmpp_error_register_domain() * @parent_node: the node to which to add an error (such as an IQ error) * * Adds an <error/> node to a stanza corresponding * to the error described by @error. If @error is in a domain other * than #WOCKY_XMPP_ERROR, both the application-specific error name * and the error from #WOCKY_XMPP_ERROR will be created. See RFC 3902 * (XMPP Core) §9.3, “Stanza Errors”. * * There is currently no way to override the type='' of an XMPP Core stanza * error without creating an application-specific error code which does so. * * Returns: the newly-created node */ WockyNode * wocky_stanza_error_to_node (const GError *error, WockyNode *parent_node) { WockyNode *error_node; WockyXmppErrorDomain *domain = NULL; WockyXmppError core_error; const XmppErrorSpec *spec; WockyXmppErrorType type; gchar str[6]; g_return_val_if_fail (parent_node != NULL, NULL); error_node = wocky_node_add_child (parent_node, "error"); g_return_val_if_fail (error != NULL, error_node); if (error->domain == WOCKY_XMPP_ERROR) { core_error = error->code; spec = &(xmpp_errors[core_error]); type = spec->type; } else { WockyXmppErrorSpecialization *s; domain = xmpp_error_find_domain (error->domain); g_return_val_if_fail (domain != NULL, error_node); /* This will crash if you mess up and pass a code that's not in the * domain. */ s = &(domain->codes[error->code]); core_error = s->specializes; spec = &(xmpp_errors[core_error]); if (s->override_type) type = s->type; else type = spec->type; } sprintf (str, "%d", spec->legacy_errors[0]); wocky_node_set_attribute (error_node, "code", str); wocky_node_set_attribute (error_node, "type", wocky_enum_to_nick (WOCKY_TYPE_XMPP_ERROR_TYPE, type)); wocky_node_add_child_ns (error_node, wocky_xmpp_error_string (core_error), WOCKY_XMPP_NS_STANZAS); if (domain != NULL) { const gchar *name = wocky_enum_to_nick (domain->enum_type, error->code); wocky_node_add_child_ns_q (error_node, name, domain->domain); } if (error->message != NULL && *error->message != '\0') wocky_node_add_child_with_content_ns (error_node, "text", error->message, WOCKY_XMPP_NS_STANZAS); return error_node; } /** * wocky_xmpp_stream_error_quark * * Get the error quark used for stream errors * * Returns: the quark for stream errors. */ GQuark wocky_xmpp_stream_error_quark (void) { static GQuark quark = 0; if (quark == 0) quark = g_quark_from_static_string (WOCKY_XMPP_NS_STREAMS); return quark; } /** * wocky_xmpp_stream_error_from_node: * @error: the root node of a #WOCKY_STANZA_TYPE_STREAM_ERROR stanza * * Returns: a GError in the #WOCKY_XMPP_STREAM_ERROR domain. */ GError * wocky_xmpp_stream_error_from_node (WockyNode *error) { gint code = WOCKY_XMPP_STREAM_ERROR_UNKNOWN; const gchar *message = NULL; /* Ignore the return value; we have a default. */ xmpp_error_from_node_for_ns (error, WOCKY_XMPP_STREAM_ERROR, WOCKY_TYPE_XMPP_STREAM_ERROR, &code); message = wocky_node_get_content_from_child_ns (error, "text", WOCKY_XMPP_NS_STREAMS); if (message == NULL) message = ""; return g_error_new_literal (WOCKY_XMPP_STREAM_ERROR, code, message); } /* Built-in specialized error domains */ GQuark wocky_jingle_error_quark (void) { static GQuark quark = 0; if (quark == 0) quark = g_quark_from_static_string (WOCKY_XMPP_NS_JINGLE_ERRORS); return quark; } static WockyXmppErrorDomain * jingle_error_get_domain (void) { static WockyXmppErrorSpecialization codes[] = { /* out-of-order */ { "The request cannot occur at this point in the state machine (e.g., " "session-initiate after session-accept).", WOCKY_XMPP_ERROR_UNEXPECTED_REQUEST, FALSE }, /* tie-break */ { "The request is rejected because it was sent while the initiator was " "awaiting a reply on a similar request.", WOCKY_XMPP_ERROR_CONFLICT, FALSE }, /* unknown-session */ { "The 'sid' attribute specifies a session that is unknown to the " "recipient (e.g., no longer live according to the recipient's state " "machine because the recipient previously terminated the session).", WOCKY_XMPP_ERROR_ITEM_NOT_FOUND, FALSE }, /* unsupported-info */ { "The recipient does not support the informational payload of a " "session-info action.", WOCKY_XMPP_ERROR_FEATURE_NOT_IMPLEMENTED, FALSE } }; static WockyXmppErrorDomain jingle_errors = { 0, }; if (G_UNLIKELY (jingle_errors.domain == 0)) { jingle_errors.domain = WOCKY_JINGLE_ERROR; jingle_errors.enum_type = WOCKY_TYPE_JINGLE_ERROR; jingle_errors.codes = codes; } return &jingle_errors; } GQuark wocky_si_error_quark (void) { static GQuark quark = 0; if (quark == 0) quark = g_quark_from_static_string (WOCKY_XMPP_NS_SI); return quark; } static WockyXmppErrorDomain * si_error_get_domain (void) { static WockyXmppErrorSpecialization codes[] = { /* no-valid-streams */ { "None of the available streams are acceptable.", WOCKY_XMPP_ERROR_BAD_REQUEST, TRUE, WOCKY_XMPP_ERROR_TYPE_CANCEL }, /* bad-profile */ { "The profile is not understood or invalid. The profile MAY supply a " "profile-specific error condition.", WOCKY_XMPP_ERROR_BAD_REQUEST, TRUE, WOCKY_XMPP_ERROR_TYPE_MODIFY } }; static WockyXmppErrorDomain si_errors = { 0, }; if (G_UNLIKELY (si_errors.domain == 0)) { si_errors.domain = WOCKY_SI_ERROR; si_errors.enum_type = WOCKY_TYPE_SI_ERROR; si_errors.codes = codes; } return &si_errors; } void wocky_xmpp_error_init () { if (error_domains == NULL) { /* Register standard domains */ wocky_xmpp_error_register_domain (jingle_error_get_domain ()); wocky_xmpp_error_register_domain (si_error_get_domain ()); } } void wocky_xmpp_error_deinit () { g_list_free (error_domains); error_domains = NULL; } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-xep-0115-capabilities.h0000664000175000017500000000514112005516162027145 0ustar00cassidycassidy00000000000000/* * wocky-xep-0115-capabilities.h - interface for holding capabilities * of contacts * * Copyright (C) 2011-2012 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_XEP_0115_CAPABILITIES_H__ #define __WOCKY_XEP_0115_CAPABILITIES_H__ #include G_BEGIN_DECLS #define WOCKY_TYPE_XEP_0115_CAPABILITIES \ (wocky_xep_0115_capabilities_get_type ()) #define WOCKY_XEP_0115_CAPABILITIES(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ WOCKY_TYPE_XEP_0115_CAPABILITIES, WockyXep0115Capabilities)) #define WOCKY_IS_XEP_0115_CAPABILITIES(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ WOCKY_TYPE_XEP_0115_CAPABILITIES)) #define WOCKY_XEP_0115_CAPABILITIES_GET_INTERFACE(obj) \ (G_TYPE_INSTANCE_GET_INTERFACE ((obj), \ WOCKY_TYPE_XEP_0115_CAPABILITIES, WockyXep0115CapabilitiesInterface)) typedef struct _WockyXep0115Capabilities WockyXep0115Capabilities; typedef struct _WockyXep0115CapabilitiesInterface WockyXep0115CapabilitiesInterface; /* virtual methods */ typedef const GPtrArray * (*WockyXep0115CapabilitiesGetDataFormsFunc) ( WockyXep0115Capabilities *contact); typedef gboolean (*WockyXep0115CapabilitiesHasFeatureFunc) ( WockyXep0115Capabilities *contact, const gchar *feature); const GPtrArray * wocky_xep_0115_capabilities_get_data_forms ( WockyXep0115Capabilities *contact); gboolean wocky_xep_0115_capabilities_has_feature ( WockyXep0115Capabilities *contact, const gchar *feature); struct _WockyXep0115CapabilitiesInterface { GTypeInterface parent; /* TODO: capability enumeration and identities! */ WockyXep0115CapabilitiesGetDataFormsFunc get_data_forms; WockyXep0115CapabilitiesHasFeatureFunc has_feature; }; GType wocky_xep_0115_capabilities_get_type (void); G_END_DECLS #endif /* WOCKY_XEP_0115_CAPABILITIES_H */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-google-relay.h0000664000175000017500000000307612212322440025723 0ustar00cassidycassidy00000000000000/* * google-relay.h - Header for WockyGoogleRelaySession * * Copyright (C) 2006-2008 Collabora Ltd. * Copyright (C) 2011 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_COMPILATION) # error "This is an internal header." #endif #ifndef __WOCKY_GOOGLE_RELAY_H__ #define __WOCKY_GOOGLE_RELAY_H__ #include #include "wocky-jingle-info.h" G_BEGIN_DECLS typedef struct _WockyGoogleRelayResolver WockyGoogleRelayResolver; WockyGoogleRelayResolver * wocky_google_relay_resolver_new (void); void wocky_google_relay_resolver_destroy (WockyGoogleRelayResolver *self); void wocky_google_relay_resolver_resolve (WockyGoogleRelayResolver *self, guint requests_to_do, const gchar *server, guint16 port, const gchar *token, WockyJingleInfoRelaySessionCb callback, gpointer user_data); G_END_DECLS #endif /* __WOCKY_GOOGLE_RELAY_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-types.h0000664000175000017500000000257611720661341024516 0ustar00cassidycassidy00000000000000/* * wocky-contact.h - Header for Wocky type definitions * Copyright (C) 2009 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_TYPES_H__ #define __WOCKY_TYPES_H__ #include G_BEGIN_DECLS typedef struct _WockyBareContact WockyBareContact; typedef struct _WockyLLContact WockyLLContact; typedef struct _WockyNodeTree WockyNodeTree; typedef struct _WockyResourceContact WockyResourceContact; typedef struct _WockySession WockySession; typedef struct _WockyPubsubNode WockyPubsubNode; G_END_DECLS #endif /* #ifndef __WOCKY_TYPES_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-xmpp-error.h0000664000175000017500000003707012212322440025451 0ustar00cassidycassidy00000000000000/* * wocky-xmpp-error.h - Header for Wocky's XMPP error handling API * Copyright (C) 2006-2009 Collabora Ltd. * Copyright (C) 2006 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_XMPP_ERROR_H__ #define __WOCKY_XMPP_ERROR_H__ #include #include #include "wocky-enumtypes.h" #include "wocky-node.h" /** * WockyXmppErrorType: * @WOCKY_XMPP_ERROR_TYPE_CANCEL: do not retry (the error is * unrecoverable) * @WOCKY_XMPP_ERROR_TYPE_CONTINUE: proceed (the condition was only a * warning) * @WOCKY_XMPP_ERROR_TYPE_MODIFY: retry after changing the data sent * @WOCKY_XMPP_ERROR_TYPE_AUTH: retry after providing credentials * @WOCKY_XMPP_ERROR_TYPE_WAIT: retry after waiting (the error is * temporary) * * XMPP error types as described in RFC 3920 §9.3.2. */ /*< prefix=WOCKY_XMPP_ERROR_TYPE >*/ typedef enum { WOCKY_XMPP_ERROR_TYPE_CANCEL, WOCKY_XMPP_ERROR_TYPE_CONTINUE, WOCKY_XMPP_ERROR_TYPE_MODIFY, WOCKY_XMPP_ERROR_TYPE_AUTH, WOCKY_XMPP_ERROR_TYPE_WAIT } WockyXmppErrorType; /** * WockyXmppError: * @WOCKY_XMPP_ERROR_UNDEFINED_CONDITION: the error condition is not one * of those defined by the other conditions in this list * @WOCKY_XMPP_ERROR_REDIRECT: the recipient or server is redirecting * requests for this information to another entity * @WOCKY_XMPP_ERROR_GONE: the recipient or server can no longer be * contacted at this address * @WOCKY_XMPP_ERROR_BAD_REQUEST: the sender has sent XML that is * malformed or that cannot be processed * @WOCKY_XMPP_ERROR_UNEXPECTED_REQUEST: the recipient or server * understood the request but was not expecting it at this time * @WOCKY_XMPP_ERROR_JID_MALFORMED: the sending entity has provided or * communicated an XMPP address * @WOCKY_XMPP_ERROR_NOT_AUTHORIZED: the sender must provide proper * credentials before being allowed to perform the action, or has * provided improper credentials * @WOCKY_XMPP_ERROR_PAYMENT_REQUIRED: the requesting entity is not * authorized to access the requested service because payment is * required. This code is no longer defined in RFC 6120, the current version * of XMPP Core. It's preserved here for interoperability, but new * applications should not send it. * @WOCKY_XMPP_ERROR_FORBIDDEN: the requesting entity does not possess * the required permissions to perform the action * @WOCKY_XMPP_ERROR_ITEM_NOT_FOUND: the addressed JID or item requested * cannot be found * @WOCKY_XMPP_ERROR_RECIPIENT_UNAVAILABLE: the intended recipient is * temporarily unavailable * @WOCKY_XMPP_ERROR_REMOTE_SERVER_NOT_FOUND: a remote server or * service specified as part or all of the JID of the intended * recipient does not exist * @WOCKY_XMPP_ERROR_NOT_ALLOWED: the recipient or server does not * allow any entity to perform the action * @WOCKY_XMPP_ERROR_NOT_ACCEPTABLE: the recipient or server * understands the request but is refusing to process it because it * does not meet criteria defined by the recipient or server * @WOCKY_XMPP_ERROR_REGISTRATION_REQUIRED: the requesting entity is * not authorized to access the requested service because * registration is required * @WOCKY_XMPP_ERROR_SUBSCRIPTION_REQUIRED: the requesting entity is * not authorized to access the requested service because a * subscription is required * @WOCKY_XMPP_ERROR_REMOTE_SERVER_TIMEOUT: a remote server or service * specified as part or all of the JID of the intended recipient (or * required to fulfill a request) could not be contacted within a * reasonable amount of time * @WOCKY_XMPP_ERROR_CONFLICT: access cannot be granted because an * existing resource or session exists with the same name or address * @WOCKY_XMPP_ERROR_INTERNAL_SERVER_ERROR: the server could not * process the stanza because of a misconfiguration or an * otherwise-undefined internal server error * @WOCKY_XMPP_ERROR_RESOURCE_CONSTRAINT: the server or recipient lacks * the system resources necessary to service the request * @WOCKY_XMPP_ERROR_FEATURE_NOT_IMPLEMENTED: the feature requested is * not implemented by the recipient or server and therefore cannot * be processed * @WOCKY_XMPP_ERROR_SERVICE_UNAVAILABLE: the server or recipient does * not currently provide the requested service * @WOCKY_XMPP_ERROR_POLICY_VIOLATION: the entity has violated some local * service policy (e.g., a message contains words that are prohibited by the * service) and the server MAY choose to specify the policy as the text of * the error or in an application-specific condition element; the associated * error type SHOULD be %WOCKY_XMPP_ERROR_TYPE_MODIFY or * %WOCKY_XMPP_ERROR_TYPE_WAIT depending on the policy being violated. * * Possible stanza-level errors, as defined by RFC 6210 * §8.3.3. */ /*< prefix=WOCKY_XMPP_ERROR >*/ typedef enum { WOCKY_XMPP_ERROR_UNDEFINED_CONDITION = 0, /* 500 */ WOCKY_XMPP_ERROR_REDIRECT, /* 302 */ WOCKY_XMPP_ERROR_GONE, /* 302 */ WOCKY_XMPP_ERROR_BAD_REQUEST, /* 400 */ WOCKY_XMPP_ERROR_UNEXPECTED_REQUEST, /* 400 */ WOCKY_XMPP_ERROR_JID_MALFORMED, /* 400 */ WOCKY_XMPP_ERROR_NOT_AUTHORIZED, /* 401 */ WOCKY_XMPP_ERROR_PAYMENT_REQUIRED, /* 402 */ WOCKY_XMPP_ERROR_FORBIDDEN, /* 403 */ WOCKY_XMPP_ERROR_ITEM_NOT_FOUND, /* 404 */ WOCKY_XMPP_ERROR_RECIPIENT_UNAVAILABLE, /* 404 */ WOCKY_XMPP_ERROR_REMOTE_SERVER_NOT_FOUND, /* 404 */ WOCKY_XMPP_ERROR_NOT_ALLOWED, /* 405 */ WOCKY_XMPP_ERROR_NOT_ACCEPTABLE, /* 406 */ WOCKY_XMPP_ERROR_REGISTRATION_REQUIRED, /* 407 */ WOCKY_XMPP_ERROR_SUBSCRIPTION_REQUIRED, /* 407 */ WOCKY_XMPP_ERROR_REMOTE_SERVER_TIMEOUT, /* 408, 504 */ WOCKY_XMPP_ERROR_CONFLICT, /* 409 */ WOCKY_XMPP_ERROR_INTERNAL_SERVER_ERROR, /* 500 */ WOCKY_XMPP_ERROR_RESOURCE_CONSTRAINT, /* 500 */ WOCKY_XMPP_ERROR_FEATURE_NOT_IMPLEMENTED, /* 501 */ WOCKY_XMPP_ERROR_SERVICE_UNAVAILABLE, /* 502, 503, 510 */ WOCKY_XMPP_ERROR_POLICY_VIOLATION, /*< private >*/ NUM_WOCKY_XMPP_ERRORS /*< skip >*/ /* don't want this in the GEnum */ } WockyXmppError; GQuark wocky_xmpp_error_quark (void); #define WOCKY_XMPP_ERROR (wocky_xmpp_error_quark ()) /** * WockyXmppErrorSpecialization: * @description: description of the error * @specializes: which #WockyXmppError this error specializes * @override_type: %TRUE if @type should be used, or %FALSE if the * default error type for @specializes should be used * @type: the XMPP error type * * A struct to represent a specialization of an existing * #WockyXmppError member. */ typedef struct _WockyXmppErrorSpecialization WockyXmppErrorSpecialization; struct _WockyXmppErrorSpecialization { const gchar *description; WockyXmppError specializes; gboolean override_type; WockyXmppErrorType type; }; /** * WockyXmppErrorDomain: * @domain: a #GQuark of the error domain * @enum_type: the #GType of the error enum * @codes: a %NULL-terminated array of of #WockyXmppErrorSpecializations * * A struct to represent extra XMPP error domains added. */ typedef struct _WockyXmppErrorDomain WockyXmppErrorDomain; struct _WockyXmppErrorDomain { GQuark domain; GType enum_type; WockyXmppErrorSpecialization *codes; }; void wocky_xmpp_error_register_domain (WockyXmppErrorDomain *domain); /** * WockyJingleError: * @WOCKY_JINGLE_ERROR_OUT_OF_ORDER: the request cannot occur at this * point in the state machine * @WOCKY_JINGLE_ERROR_TIE_BREAK: the request is rejected because it * was sent while the initiator was awaiting a reply on a similar * request * @WOCKY_JINGLE_ERROR_UNKNOWN_SESSION: the 'sid' attribute specifies * a session that is unknown to the recipient * @WOCKY_JINGLE_ERROR_UNSUPPORTED_INFO: the recipient does not * support the informational payload of a session-info action. * * Jingle specific errors. */ /*< prefix=WOCKY_JINGLE_ERROR >*/ typedef enum { WOCKY_JINGLE_ERROR_OUT_OF_ORDER, WOCKY_JINGLE_ERROR_TIE_BREAK, WOCKY_JINGLE_ERROR_UNKNOWN_SESSION, WOCKY_JINGLE_ERROR_UNSUPPORTED_INFO } WockyJingleError; GQuark wocky_jingle_error_quark (void); #define WOCKY_JINGLE_ERROR (wocky_jingle_error_quark ()) /** * WockySIError: * @WOCKY_SI_ERROR_NO_VALID_STREAMS: none of the available streams are * acceptable * @WOCKY_SI_ERROR_BAD_PROFILE: the profile is not understood or * invalid * * SI specific errors. */ /*< prefix=WOCKY_SI_ERROR >*/ typedef enum { WOCKY_SI_ERROR_NO_VALID_STREAMS, WOCKY_SI_ERROR_BAD_PROFILE } WockySIError; GQuark wocky_si_error_quark (void); #define WOCKY_SI_ERROR (wocky_si_error_quark ()) /** * WockyXmppStreamError: * @WOCKY_XMPP_STREAM_ERROR_BAD_FORMAT: the entity has sent XML that * cannot be processed * @WOCKY_XMPP_STREAM_ERROR_BAD_NAMESPACE_PREFIX: the entity has sent * a namespace prefix that is unsupported, or has sent no namespace * prefix on an element that requires such a prefix * @WOCKY_XMPP_STREAM_ERROR_CONFLICT: the server is closing the active * stream for this entity because a new stream has been initiated * that conflicts with the existing stream * @WOCKY_XMPP_STREAM_ERROR_CONNECTION_TIMEOUT: the entity has not * generated any traffic over the stream for some period of time * @WOCKY_XMPP_STREAM_ERROR_HOST_GONE: the value of the 'to' attribute * provided by the initiating entity in the stream header * corresponds to a hostname that is no longer hosted by the server * @WOCKY_XMPP_STREAM_ERROR_HOST_UNKNOWN: the value of the 'to' * attribute provided by the initiating entity in the stream header * does not correspond to a hostname that is hosted by the server * @WOCKY_XMPP_STREAM_ERROR_IMPROPER_ADDRESSING: a stanza sent between * two servers lacks a 'to' or 'from' attribute (or the attribute * has no value) * @WOCKY_XMPP_STREAM_ERROR_INTERNAL_SERVER_ERROR: the server has * experienced a misconfiguration or an otherwise-undefined internal * error that prevents it from servicing the stream * @WOCKY_XMPP_STREAM_ERROR_INVALID_FROM: the JID or hostname provided * in a 'from' address does not match an authorized JID or validated * domain negotiated between servers via SASL or dialback, or * between a client and a server via authentication and resource * binding * @WOCKY_XMPP_STREAM_ERROR_INVALID_ID: the stream ID or dialback ID * is invalid or does not match an ID previously provided * @WOCKY_XMPP_STREAM_ERROR_INVALID_NAMESPACE: the streams namespace * name is something other than "http://etherx.jabber.org/streams" * or the dialback namespace name is something other than * "jabber:server:dialback" * @WOCKY_XMPP_STREAM_ERROR_INVALID_XML: the entity has sent invalid * XML over the stream to a server that performs validation * @WOCKY_XMPP_STREAM_ERROR_NOT_AUTHORIZED: the entity has attempted * to send data before the stream has been authenticated, or * otherwise is not authorized to perform an action related to * stream negotiation * @WOCKY_XMPP_STREAM_ERROR_POLICY_VIOLATION: the entity has violated * some local service policy * @WOCKY_XMPP_STREAM_ERROR_REMOTE_CONNECTION_FAILED: the server is * unable to properly connect to a remote entity that is required * for authentication or authorization * @WOCKY_XMPP_STREAM_ERROR_RESOURCE_CONSTRAINT: the server lacks the * system resources necessary to service the stream * @WOCKY_XMPP_STREAM_ERROR_RESTRICTED_XML: the entity has attempted * to send restricted XML features such as a comment, processing * instruction, DTD, entity reference, or unescaped character * @WOCKY_XMPP_STREAM_ERROR_SEE_OTHER_HOST: the server will not * provide service to the initiating entity but is redirecting * traffic to another host * @WOCKY_XMPP_STREAM_ERROR_SYSTEM_SHUTDOWN: the server is being shut * down and all active streams are being closed * @WOCKY_XMPP_STREAM_ERROR_UNDEFINED_CONDITION: the error condition * is not one of those defined by the other conditions in this list * @WOCKY_XMPP_STREAM_ERROR_UNSUPPORTED_ENCODING: the initiating * entity has encoded the stream in an encoding that is not * supported by the server * @WOCKY_XMPP_STREAM_ERROR_UNSUPPORTED_STANZA_TYPE: the initiating * entity has sent a first-level child of the stream that is not * supported by the server * @WOCKY_XMPP_STREAM_ERROR_UNSUPPORTED_VERSION: the value of the * 'version' attribute provided by the initiating entity in the * stream header specifies a version of XMPP that is not supported * by the server * @WOCKY_XMPP_STREAM_ERROR_XML_NOT_WELL_FORMED: the initiating entity * has sent XML that is not well-formed * @WOCKY_XMPP_STREAM_ERROR_UNKNOWN: an unknown stream error * * Stream-level error conditions as described in RFC 3920 §4.7.3. */ /*< prefix=WOCKY_XMPP_STREAM_ERROR >*/ typedef enum { WOCKY_XMPP_STREAM_ERROR_BAD_FORMAT, WOCKY_XMPP_STREAM_ERROR_BAD_NAMESPACE_PREFIX, WOCKY_XMPP_STREAM_ERROR_CONFLICT, WOCKY_XMPP_STREAM_ERROR_CONNECTION_TIMEOUT, WOCKY_XMPP_STREAM_ERROR_HOST_GONE, WOCKY_XMPP_STREAM_ERROR_HOST_UNKNOWN, WOCKY_XMPP_STREAM_ERROR_IMPROPER_ADDRESSING, WOCKY_XMPP_STREAM_ERROR_INTERNAL_SERVER_ERROR, WOCKY_XMPP_STREAM_ERROR_INVALID_FROM, WOCKY_XMPP_STREAM_ERROR_INVALID_ID, WOCKY_XMPP_STREAM_ERROR_INVALID_NAMESPACE, WOCKY_XMPP_STREAM_ERROR_INVALID_XML, WOCKY_XMPP_STREAM_ERROR_NOT_AUTHORIZED, WOCKY_XMPP_STREAM_ERROR_POLICY_VIOLATION, WOCKY_XMPP_STREAM_ERROR_REMOTE_CONNECTION_FAILED, WOCKY_XMPP_STREAM_ERROR_RESOURCE_CONSTRAINT, WOCKY_XMPP_STREAM_ERROR_RESTRICTED_XML, WOCKY_XMPP_STREAM_ERROR_SEE_OTHER_HOST, WOCKY_XMPP_STREAM_ERROR_SYSTEM_SHUTDOWN, WOCKY_XMPP_STREAM_ERROR_UNDEFINED_CONDITION, WOCKY_XMPP_STREAM_ERROR_UNSUPPORTED_ENCODING, WOCKY_XMPP_STREAM_ERROR_UNSUPPORTED_STANZA_TYPE, WOCKY_XMPP_STREAM_ERROR_UNSUPPORTED_VERSION, WOCKY_XMPP_STREAM_ERROR_XML_NOT_WELL_FORMED, WOCKY_XMPP_STREAM_ERROR_UNKNOWN, } WockyXmppStreamError; GQuark wocky_xmpp_stream_error_quark (void); /** * WOCKY_XMPP_STREAM_ERROR: * * Get access to the error quark of the xmpp stream errors. */ #define WOCKY_XMPP_STREAM_ERROR (wocky_xmpp_stream_error_quark ()) const gchar *wocky_xmpp_error_string (WockyXmppError error); const gchar *wocky_xmpp_error_description (WockyXmppError error); GError *wocky_xmpp_stream_error_from_node (WockyNode *error); WockyNode *wocky_stanza_error_to_node (const GError *error, WockyNode *parent_node); const gchar *wocky_xmpp_stanza_error_to_string (GError *error); void wocky_xmpp_error_extract (WockyNode *error, WockyXmppErrorType *type, GError **core, GError **specialized, WockyNode **specialized_node); void wocky_xmpp_error_init (void); void wocky_xmpp_error_deinit (void); #endif /* __WOCKY_XMPP_ERROR_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-google-relay.c0000664000175000017500000002040212212322440025706 0ustar00cassidycassidy00000000000000/* * google-relay.c - Support for Google relays for Jingle * * Copyright (C) 2006-2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "wocky-google-relay.h" #include #ifdef ENABLE_GOOGLE_RELAY #include #endif #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_JINGLE #ifdef G_OS_WIN32 #undef ERROR #endif #include "wocky-debug-internal.h" #define RELAY_HTTP_TIMEOUT 5 struct _WockyGoogleRelayResolver { #ifdef ENABLE_GOOGLE_RELAY SoupSession *soup; #else GObject *soup; #endif }; typedef struct { GPtrArray *relays; guint component; guint requests_to_do; WockyJingleInfoRelaySessionCb callback; gpointer user_data; } RelaySessionData; static RelaySessionData * relay_session_data_new (guint requests_to_do, WockyJingleInfoRelaySessionCb callback, gpointer user_data) { RelaySessionData *rsd = g_slice_new0 (RelaySessionData); rsd->relays = g_ptr_array_sized_new (requests_to_do); g_ptr_array_set_free_func (rsd->relays, (GDestroyNotify) wocky_jingle_relay_free); rsd->component = 1; rsd->requests_to_do = requests_to_do; rsd->callback = callback; rsd->user_data = user_data; return rsd; } /* This is a GSourceFunc */ static gboolean relay_session_data_call (gpointer p) { RelaySessionData *rsd = p; g_assert (rsd->callback != NULL); rsd->callback (rsd->relays, rsd->user_data); return FALSE; } /* This is a GDestroyNotify */ static void relay_session_data_destroy (gpointer p) { RelaySessionData *rsd = p; g_ptr_array_unref (rsd->relays); g_slice_free (RelaySessionData, rsd); } #ifdef ENABLE_GOOGLE_RELAY static void translate_relay_info (GPtrArray *relays, const gchar *relay_ip, const gchar *username, const gchar *password, WockyJingleRelayType relay_type, const gchar *port_string, guint component) { guint64 portll; guint port; if (port_string == NULL) { DEBUG ("no relay port for %u found", relay_type); return; } portll = g_ascii_strtoull (port_string, NULL, 10); if (portll == 0 || portll > G_MAXUINT16) { DEBUG ("failed to parse relay port '%s' for %u", port_string, relay_type); return; } port = (guint) portll; DEBUG ("type=%u ip=%s port=%u username=%s password=%s component=%u", relay_type, relay_ip, port, username, password, component); g_ptr_array_add (relays, wocky_jingle_relay_new (relay_type, relay_ip, port, username, password, component)); } static void on_http_response (SoupSession *soup, SoupMessage *msg, gpointer user_data) { RelaySessionData *rsd = user_data; if (msg->status_code != 200) { DEBUG ("Google session creation failed, relaying not used: %d %s", msg->status_code, msg->reason_phrase); } else { /* parse a=b lines into GHashTable * (key, value both borrowed from items of the strv 'lines') */ GHashTable *map = g_hash_table_new (g_str_hash, g_str_equal); gchar **lines; guint i; const gchar *relay_ip; const gchar *relay_udp_port; const gchar *relay_tcp_port; const gchar *relay_ssltcp_port; const gchar *username; const gchar *password; gchar *escaped_str; escaped_str = g_strescape (msg->response_body->data, "\r\n"); DEBUG ("Response from Google:\n====\n%s\n====", escaped_str); g_free (escaped_str); lines = g_strsplit (msg->response_body->data, "\n", 0); if (lines != NULL) { for (i = 0; lines[i] != NULL; i++) { gchar *delim = strchr (lines[i], '='); size_t len; if (delim == NULL || delim == lines[i]) { /* ignore empty keys or lines without '=' */ continue; } len = strlen (lines[i]); if (lines[i][len - 1] == '\r') { lines[i][len - 1] = '\0'; } *delim = '\0'; g_hash_table_insert (map, lines[i], delim + 1); } } relay_ip = g_hash_table_lookup (map, "relay.ip"); relay_udp_port = g_hash_table_lookup (map, "relay.udp_port"); relay_tcp_port = g_hash_table_lookup (map, "relay.tcp_port"); relay_ssltcp_port = g_hash_table_lookup (map, "relay.ssltcp_port"); username = g_hash_table_lookup (map, "username"); password = g_hash_table_lookup (map, "password"); if (relay_ip == NULL) { DEBUG ("No relay.ip found"); } else if (username == NULL) { DEBUG ("No username found"); } else if (password == NULL) { DEBUG ("No password found"); } else { translate_relay_info (rsd->relays, relay_ip, username, password, WOCKY_JINGLE_RELAY_TYPE_UDP, relay_udp_port, rsd->component); translate_relay_info (rsd->relays, relay_ip, username, password, WOCKY_JINGLE_RELAY_TYPE_TCP, relay_tcp_port, rsd->component); translate_relay_info (rsd->relays, relay_ip, username, password, WOCKY_JINGLE_RELAY_TYPE_TLS, relay_ssltcp_port, rsd->component); } g_strfreev (lines); g_hash_table_unref (map); } rsd->component++; if ((--rsd->requests_to_do) == 0) { relay_session_data_call (rsd); relay_session_data_destroy (rsd); } } #endif /* ENABLE_GOOGLE_RELAY */ WockyGoogleRelayResolver * wocky_google_relay_resolver_new (void) { WockyGoogleRelayResolver *resolver = g_slice_new0 (WockyGoogleRelayResolver); #ifdef ENABLE_GOOGLE_RELAY resolver->soup = soup_session_async_new (); /* If we don't get answer in a few seconds, relay won't do * us much help anyways. */ g_object_set (resolver->soup, "timeout", RELAY_HTTP_TIMEOUT, NULL); #endif return resolver; } void wocky_google_relay_resolver_destroy (WockyGoogleRelayResolver *self) { g_clear_object (&self->soup); g_slice_free (WockyGoogleRelayResolver, self); } void wocky_google_relay_resolver_resolve (WockyGoogleRelayResolver *self, guint components, const gchar *server, guint16 port, const gchar *token, WockyJingleInfoRelaySessionCb callback, gpointer user_data) { RelaySessionData *rsd = relay_session_data_new (components, callback, user_data); #ifdef ENABLE_GOOGLE_RELAY gchar *url; guint i; if (server == NULL) { DEBUG ("No relay server provided, not creating google relay session"); g_idle_add_full (G_PRIORITY_DEFAULT, relay_session_data_call, rsd, relay_session_data_destroy); return; } if (token == NULL) { DEBUG ("No relay token provided, not creating google relay session"); g_idle_add_full (G_PRIORITY_DEFAULT, relay_session_data_call, rsd, relay_session_data_destroy); return; } url = g_strdup_printf ("http://%s:%u/create_session", server, (guint) port); for (i = 0; i < components; i++) { SoupMessage *msg = soup_message_new ("GET", url); DEBUG ("Trying to create a new relay session on %s", url); /* libjingle sets both headers, so shall we */ soup_message_headers_append (msg->request_headers, "X-Talk-Google-Relay-Auth", token); soup_message_headers_append (msg->request_headers, "X-Google-Relay-Auth", token); soup_session_queue_message (self->soup, msg, on_http_response, rsd); } g_free (url); #else /* !ENABLE_GOOGLE_RELAY */ DEBUG ("Google relay service is not supported"); g_idle_add_full (G_PRIORITY_DEFAULT, relay_session_data_call, rsd, relay_session_data_destroy); #endif } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-meta-porter.c0000664000175000017500000014024712212322440025571 0ustar00cassidycassidy00000000000000/* * wocky-meta-porter.c - Source for WockyMetaPorter * Copyright (C) 2011 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the tubesplied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-meta-porter.h" #include #include #include #ifdef G_OS_WIN32 #include #include #include typedef uint32_t u_int32_t; typedef uint16_t u_int16_t; #else #include #include #endif #include "wocky-ll-connection-factory.h" #include "wocky-contact-factory.h" #include "wocky-c2s-porter.h" #include "wocky-utils.h" #include "wocky-ll-contact.h" #include "wocky-ll-connector.h" #include "wocky-loopback-stream.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_PORTER #include "wocky-debug-internal.h" static void wocky_porter_iface_init (gpointer g_iface, gpointer iface_data); G_DEFINE_TYPE_WITH_CODE (WockyMetaPorter, wocky_meta_porter, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (WOCKY_TYPE_PORTER, wocky_porter_iface_init)); /* properties */ enum { PROP_JID = 1, PROP_CONTACT_FACTORY, PROP_CONNECTION, PROP_RESOURCE, }; #define PORTER_JID_QUARK \ (g_quark_from_static_string ("wocky-meta-porter-c2s-jid")) /* private structure */ struct _WockyMetaPorterPrivate { gchar *jid; WockyContactFactory *contact_factory; WockyLLConnectionFactory *connection_factory; /* owned (gchar *) jid => owned (PorterData *) */ GHashTable *porters; /* guint handler id => owned (StanzaHandler *) */ GHashTable *handlers; GSocketService *listener; guint16 port; guint next_handler_id; }; typedef struct { WockyMetaPorter *self; WockyContact *contact; /* owned */ WockyPorter *porter; /* also owned, for convenience */ gchar *jid; guint refcount; guint timeout_id; } PorterData; typedef struct { WockyMetaPorter *self; WockyContact *contact; /* weak reffed WockyPorter* => handler ID */ GHashTable *porters; WockyStanzaType type; WockyStanzaSubType sub_type; guint priority; WockyPorterHandlerFunc callback; gpointer user_data; WockyStanza *stanza; } StanzaHandler; GQuark wocky_meta_porter_error_quark (void) { static GQuark quark = 0; if (!quark) quark = g_quark_from_static_string ( "wocky_meta_porter_error"); return quark; } static void register_porter_handlers (WockyMetaPorter *self, WockyPorter *porter, WockyContact *contact); static void disconnect_porter_signal_handlers (WockyPorter *porter, PorterData *data); static void porter_data_free (gpointer data) { PorterData *p = data; if (p->porter != NULL) { /* We have to make sure we disconnect the handlers or ::closing * will be fired by close_async, then the callback will unref * p->porter before we have a chance to do it outselves. */ disconnect_porter_signal_handlers (p->porter, p); wocky_porter_close_async (p->porter, NULL, NULL, NULL); g_object_unref (p->porter); } if (p->timeout_id > 0) g_source_remove (p->timeout_id); g_free (p->jid); g_slice_free (PorterData, data); } static void porter_closed_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { WockyPorter *porter = WOCKY_PORTER (source_object); GError *error = NULL; PorterData *data = user_data; if (!wocky_porter_close_finish (porter, result, &error)) { DEBUG ("Failed to close porter to '%s': %s", data->jid, error->message); g_clear_error (&error); } else { DEBUG ("Closed porter to '%s'", data->jid); } porter_data_free (data); } static gboolean porter_timeout_cb (gpointer d) { PorterData *data = d; WockyMetaPorterPrivate *priv = data->self->priv; data->timeout_id = 0; g_hash_table_steal (priv->porters, data->contact); /* we need to unref this ourselves as we just stole it from the hash * table */ g_object_unref (data->contact); if (data->porter != NULL) wocky_porter_close_async (data->porter, NULL, porter_closed_cb, data); else porter_data_free (data); return FALSE; } static void porter_closing_cb (WockyPorter *porter, PorterData *data); static void porter_remote_closed_cb (WockyPorter *porter, PorterData *data); static void porter_remote_error_cb (WockyPorter *porter, GQuark domain, gint code, const gchar *msg, PorterData *data); static void porter_sending_cb ( WockyC2SPorter *child_porter, WockyStanza *stanza, PorterData *data); static void disconnect_porter_signal_handlers (WockyPorter *porter, PorterData *data) { g_signal_handlers_disconnect_by_func (porter, porter_remote_closed_cb, data); g_signal_handlers_disconnect_by_func (porter, porter_closing_cb, data); g_signal_handlers_disconnect_by_func (porter, porter_remote_error_cb, data); g_signal_handlers_disconnect_by_func (porter, porter_sending_cb, data); } static void porter_closing_cb (WockyPorter *porter, PorterData *data) { DEBUG ("porter to '%s' closing, remove it from our records", data->jid); /* Don't stop the porter timeout here because that means if a * connection is never opened to the contact again the PorterData * struct will stick around until the meta porter is disposed. */ disconnect_porter_signal_handlers (porter, data); if (data->porter != NULL) g_object_unref (data->porter); data->porter = NULL; } static void porter_remote_closed_cb (WockyPorter *porter, PorterData *data) { DEBUG ("porter closed by remote, remove it from our records"); porter_closing_cb (porter, data); } static void porter_remote_error_cb (WockyPorter *porter, GQuark domain, gint code, const gchar *msg, PorterData *data) { DEBUG ("remote error in porter, close it"); wocky_porter_force_close_async (porter, NULL, NULL, NULL); porter_closing_cb (porter, data); } static void porter_sending_cb ( WockyC2SPorter *child_porter, WockyStanza *stanza, PorterData *data) { g_signal_emit_by_name (data->self, "sending", stanza); } static void maybe_start_timeout (PorterData *data) { if (data->refcount == 0) { /* if we've already got a timeout going let's cancel it and get * a new one going instead of having two. */ if (data->timeout_id > 0) g_source_remove (data->timeout_id); DEBUG ("Started porter timeout..."); data->timeout_id = g_timeout_add_seconds (5, porter_timeout_cb, data); } } static WockyPorter * create_porter (WockyMetaPorter *self, WockyXmppConnection *connection, WockyContact *contact) { WockyMetaPorterPrivate *priv = self->priv; PorterData *data; data = g_hash_table_lookup (priv->porters, contact); if (data != NULL) { if (data->porter != NULL) { /* close the new one; this function is meant to have stolen * a reference to the connection so we don't need to unref * it. It will ref itself for the duration of this close * call. */ wocky_xmpp_connection_send_close_async (connection, NULL, NULL, NULL); return data->porter; } else { data->porter = wocky_c2s_porter_new (connection, priv->jid); } } else { data = g_slice_new0 (PorterData); data->self = self; data->contact = contact; /* already will be reffed as the key */ data->jid = wocky_contact_dup_jid (contact); data->porter = wocky_c2s_porter_new (connection, priv->jid); data->refcount = 0; data->timeout_id = 0; g_hash_table_insert (priv->porters, g_object_ref (contact), data); } /* we need to set this so when we get a stanza in from a porter with * no from attribute we can find the real originating contact. The * StanzaHandler struct doesn't reference the PorterData struct, so * we simply store its jid here now. */ g_object_set_qdata_full (G_OBJECT (data->porter), PORTER_JID_QUARK, g_strdup (data->jid), g_free); g_signal_connect (data->porter, "closing", G_CALLBACK (porter_closing_cb), data); g_signal_connect (data->porter, "remote-closed", G_CALLBACK (porter_remote_closed_cb), data); g_signal_connect (data->porter, "remote-error", G_CALLBACK (porter_remote_error_cb), data); g_signal_connect (data->porter, "sending", G_CALLBACK (porter_sending_cb), data); register_porter_handlers (self, data->porter, contact); wocky_porter_start (data->porter); /* maybe start the timeout */ maybe_start_timeout (data); return data->porter; } /** * wocky_meta_porter_hold: * @porter: a #WockyMetaPorter * @contact: a #WockyContact * * Increases the hold count of the porter to @contact by * one. This means that if there is a connection open to @contact then * it will not disconnected after a timeout. Note that calling this * function does not mean a connection will be opened. The hold * count on a contact survives across connections. * * To decrement the hold count of the porter to @contact, one * must call wocky_meta_porter_unhold(). */ void wocky_meta_porter_hold (WockyMetaPorter *self, WockyContact *contact) { WockyMetaPorterPrivate *priv = self->priv; PorterData *data; g_return_if_fail (WOCKY_IS_META_PORTER (self)); data = g_hash_table_lookup (priv->porters, contact); if (data == NULL) { data = g_slice_new0 (PorterData); data->self = self; data->contact = contact; data->jid = wocky_contact_dup_jid (contact); data->porter = NULL; data->refcount = 0; data->timeout_id = 0; g_hash_table_insert (priv->porters, g_object_ref (contact), data); } DEBUG ("Porter to '%s' refcount %u --> %u", data->jid, data->refcount, data->refcount + 1); data->refcount++; if (data->timeout_id > 0) { g_source_remove (data->timeout_id); data->timeout_id = 0; } } /** * wocky_meta_porter_unhold: * @porter: a #WockyMetaPorter * @contact: a #WockyContact * * Decreases the hold count of the porter to @contact by * one. This means that if there is a connection open to @contact and * the hold count is zero, a connection timeout will be * started. */ void wocky_meta_porter_unhold (WockyMetaPorter *self, WockyContact *contact) { WockyMetaPorterPrivate *priv; PorterData *data; g_return_if_fail (WOCKY_IS_META_PORTER (self)); priv = self->priv; data = g_hash_table_lookup (priv->porters, contact); if (data == NULL) return; DEBUG ("Porter to '%s' refcount %u --> %u", data->jid, data->refcount, data->refcount - 1); data->refcount--; maybe_start_timeout (data); } static void wocky_meta_porter_init (WockyMetaPorter *self) { WockyMetaPorterPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_META_PORTER, WockyMetaPorterPrivate); self->priv = priv; } /* FIXME: these two functions are a hack until we get the * normalization of v6-in-v4 addresses in GLib. See bgo#646082 */ union BigSockAddr { struct sockaddr_in s4; struct sockaddr_in6 s6; struct sockaddr_storage storage; }; static void normalize_sockaddr (union BigSockAddr *addr) { if (addr->s6.sin6_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED (&(addr->s6.sin6_addr))) { /* Normalize to ipv4 address */ u_int32_t addr_big_endian; u_int16_t port; memcpy (&addr_big_endian, addr->s6.sin6_addr.s6_addr + 12, 4); port = addr->s6.sin6_port; addr->s4.sin_family = AF_INET; addr->s4.sin_addr.s_addr = addr_big_endian; addr->s4.sin_port = port; } } static GSocketAddress * normalize_address (GSocketAddress *addr) { union BigSockAddr ss; if (g_socket_address_get_family (addr) != G_SOCKET_FAMILY_IPV6) return addr; if (!g_socket_address_to_native (addr, &(ss.storage), sizeof (ss.storage), NULL)) return addr; g_object_unref (addr); normalize_sockaddr (&ss); return g_socket_address_new_from_native (&(ss.storage), sizeof (ss.storage)); } static void new_connection_connect_cb (GObject *source, GAsyncResult *result, gpointer user_data) { WockyLLConnector *connector = WOCKY_LL_CONNECTOR (source); WockyXmppConnection *connection; GError *error = NULL; WockyMetaPorter *self = user_data; WockyMetaPorterPrivate *priv = self->priv; GList *contacts, *l; WockyLLContact *contact = NULL; gchar *from; connection = wocky_ll_connector_finish (connector, result, &from, &error); if (connection == NULL) { DEBUG ("connection error: %s", error->message); g_clear_error (&error); goto out; } if (from != NULL) { contact = wocky_contact_factory_ensure_ll_contact (priv->contact_factory, from); } if (contact == NULL) { GSocketConnection *socket_connection; GSocketAddress *socket_address; GInetAddress *addr; /* we didn't get a from attribute in the stream open */ g_object_get (connection, "base-stream", &socket_connection, NULL); socket_address = g_socket_connection_get_remote_address ( socket_connection, NULL); socket_address = normalize_address (socket_address); addr = g_inet_socket_address_get_address ( G_INET_SOCKET_ADDRESS (socket_address)); contacts = wocky_contact_factory_get_ll_contacts (priv->contact_factory); for (l = contacts; l != NULL; l = l->next) { WockyLLContact *c = l->data; if (wocky_ll_contact_has_address (c, addr)) { contact = g_object_ref (c); break; } } g_list_free (contacts); g_object_unref (socket_address); g_object_unref (socket_connection); } if (contact != NULL) { create_porter (self, connection, WOCKY_CONTACT (contact)); } else { DEBUG ("Failed to find contact for new connection, let it close"); } g_object_unref (connection); out: g_object_unref (self); } static gboolean _new_connection (GSocketService *service, GSocketConnection *socket_connection, GObject *source_object, gpointer user_data) { WockyMetaPorter *self = user_data; GSocketAddress *addr; GInetAddress *inet_address; gchar *str; GError *error = NULL; addr = g_socket_connection_get_remote_address ( socket_connection, &error); if (addr == NULL) { DEBUG ("New connection, but failed to get remote address " "so ignoring: %s", error->message); g_clear_error (&error); return FALSE; } addr = normalize_address (addr); inet_address = g_inet_socket_address_get_address ( G_INET_SOCKET_ADDRESS (addr)); str = g_inet_address_to_string (inet_address); DEBUG ("New connection from %s!", str); wocky_ll_connector_incoming_async (G_IO_STREAM (socket_connection), NULL, new_connection_connect_cb, g_object_ref (self)); g_free (str); g_object_unref (addr); return TRUE; } static void stanza_handler_porter_disposed_cb (gpointer data, GObject *porter); static void free_handler (gpointer data) { StanzaHandler *handler = data; GHashTableIter iter; gpointer key, value; g_hash_table_iter_init (&iter, handler->porters); while (g_hash_table_iter_next (&iter, &key, &value)) { WockyPorter *porter = key; guint id = GPOINTER_TO_UINT (value); wocky_porter_unregister_handler (porter, id); g_object_weak_unref (G_OBJECT (porter), stanza_handler_porter_disposed_cb, handler); } g_hash_table_unref (handler->porters); if (handler->contact != NULL) g_object_unref (handler->contact); if (handler->stanza != NULL) g_object_unref (handler->stanza); g_slice_free (StanzaHandler, handler); } static void loopback_recv_open_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { WockyXmppConnection *connection = WOCKY_XMPP_CONNECTION (source_object); WockyMetaPorter *self = user_data; WockyMetaPorterPrivate *priv = self->priv; WockyLLContact *contact; GError *error = NULL; if (!wocky_xmpp_connection_recv_open_finish (connection, result, NULL, NULL, NULL, NULL, NULL, &error)) { DEBUG ("Failed to receive stream open from loopback stream: %s", error->message); g_clear_error (&error); g_object_unref (connection); return; } contact = wocky_contact_factory_ensure_ll_contact ( priv->contact_factory, priv->jid); /* the ref, the porter and the connection will all be freed when the * meta porter is freed */ create_porter (self, connection, WOCKY_CONTACT (contact)); wocky_meta_porter_hold (self, WOCKY_CONTACT (contact)); g_object_unref (contact); g_object_unref (connection); } static void loopback_sent_open_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { WockyXmppConnection *connection = WOCKY_XMPP_CONNECTION (source_object); WockyMetaPorter *self = user_data; GError *error = NULL; if (!wocky_xmpp_connection_send_open_finish (connection, result, &error)) { DEBUG ("Failed to send stream open to loopback stream: %s", error->message); g_clear_error (&error); g_object_unref (connection); return; } wocky_xmpp_connection_recv_open_async (connection, NULL, loopback_recv_open_cb, self); } static void create_loopback_porter (WockyMetaPorter *self) { WockyMetaPorterPrivate *priv = self->priv; GIOStream *stream; WockyXmppConnection *connection; if (priv->jid == NULL) return; stream = wocky_loopback_stream_new (); connection = wocky_xmpp_connection_new (stream); /* really simple connector */ wocky_xmpp_connection_send_open_async (connection, NULL, NULL, NULL, NULL, NULL, NULL, loopback_sent_open_cb, self); g_object_unref (stream); } static void wocky_meta_porter_constructed (GObject *obj) { WockyMetaPorter *self = WOCKY_META_PORTER (obj); WockyMetaPorterPrivate *priv = self->priv; if (G_OBJECT_CLASS (wocky_meta_porter_parent_class)->constructed) G_OBJECT_CLASS (wocky_meta_porter_parent_class)->constructed (obj); priv->listener = g_socket_service_new (); g_signal_connect (priv->listener, "incoming", G_CALLBACK (_new_connection), self); priv->next_handler_id = 1; priv->connection_factory = wocky_ll_connection_factory_new (); priv->porters = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, porter_data_free); priv->handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, free_handler); /* Create the loopback porter */ if (priv->jid != NULL) create_loopback_porter (self); } static void wocky_meta_porter_finalize (GObject *object) { WockyMetaPorter *self = WOCKY_META_PORTER (object); WockyMetaPorterPrivate *priv = self->priv; g_free (priv->jid); priv->jid = NULL; if (G_OBJECT_CLASS (wocky_meta_porter_parent_class)->finalize) G_OBJECT_CLASS (wocky_meta_porter_parent_class)->finalize (object); } static void wocky_meta_porter_dispose (GObject *object) { WockyMetaPorter *self = WOCKY_META_PORTER (object); WockyMetaPorterPrivate *priv = self->priv; g_object_unref (priv->contact_factory); g_object_unref (priv->connection_factory); g_socket_service_stop (priv->listener); g_object_unref (priv->listener); g_hash_table_unref (priv->porters); g_hash_table_unref (priv->handlers); if (G_OBJECT_CLASS (wocky_meta_porter_parent_class)->dispose) G_OBJECT_CLASS (wocky_meta_porter_parent_class)->dispose (object); } static void wocky_meta_porter_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyMetaPorter *self = WOCKY_META_PORTER (object); WockyMetaPorterPrivate *priv = self->priv; switch (property_id) { case PROP_JID: g_value_set_string (value, priv->jid); break; case PROP_CONTACT_FACTORY: g_value_set_object (value, priv->contact_factory); break; case PROP_CONNECTION: /* nothing; just here to implement WockyPorter */ g_value_set_object (value, NULL); break; case PROP_RESOURCE: /* nothing; just here to implement WockyPorter */ g_value_set_string (value, NULL); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_meta_porter_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyMetaPorter *self = WOCKY_META_PORTER (object); WockyMetaPorterPrivate *priv = self->priv; switch (property_id) { case PROP_JID: priv->jid = g_value_dup_string (value); break; case PROP_CONTACT_FACTORY: priv->contact_factory = g_value_dup_object (value); break; case PROP_CONNECTION: /* nothing; just here to implement WockyPorter */ break; case PROP_RESOURCE: /* nothing; just here to implement WockyPorter */ break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_meta_porter_class_init ( WockyMetaPorterClass *wocky_meta_porter_class) { GObjectClass *object_class = G_OBJECT_CLASS (wocky_meta_porter_class); GParamSpec *param_spec; g_type_class_add_private (wocky_meta_porter_class, sizeof (WockyMetaPorterPrivate)); object_class->dispose = wocky_meta_porter_dispose; object_class->finalize = wocky_meta_porter_finalize; object_class->constructed = wocky_meta_porter_constructed; object_class->get_property = wocky_meta_porter_get_property; object_class->set_property = wocky_meta_porter_set_property; /** * WockyMetaPorter:contact-factory: * * The #WockyContactFactory object in use by this meta porter. */ param_spec = g_param_spec_object ("contact-factory", "Contact factory", "WockyContactFactory object in use", WOCKY_TYPE_CONTACT_FACTORY, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONTACT_FACTORY, param_spec); g_object_class_override_property (object_class, PROP_CONNECTION, "connection"); g_object_class_override_property (object_class, PROP_JID, "full-jid"); g_object_class_override_property (object_class, PROP_JID, "bare-jid"); g_object_class_override_property (object_class, PROP_RESOURCE, "resource"); } /** * wocky_meta_porter_new: * @jid: the JID of the local user, or %NULL * @contact_factory: a #WockyContactFactory object * * Convenience function to create a new #WockyMetaPorter object. The * JID can be set later by using wocky_meta_porter_set_jid(). * * Returns: a new #WockyMetaPorter */ WockyPorter * wocky_meta_porter_new (const gchar *jid, WockyContactFactory *contact_factory) { g_return_val_if_fail (WOCKY_IS_CONTACT_FACTORY (contact_factory), NULL); return g_object_new (WOCKY_TYPE_META_PORTER, "full-jid", jid, "contact-factory", contact_factory, NULL); } static const gchar * wocky_meta_porter_get_jid (WockyPorter *porter) { WockyMetaPorter *self; g_return_val_if_fail (WOCKY_IS_META_PORTER (porter), NULL); self = (WockyMetaPorter *) porter; return self->priv->jid; } static const gchar * wocky_meta_porter_get_resource (WockyPorter *porter) { return NULL; } typedef void (*OpenPorterIfNecessaryFunc) (WockyMetaPorter *self, WockyPorter *porter, GCancellable *cancellable, const GError *error, GSimpleAsyncResult *simple, gpointer user_data); typedef struct { WockyMetaPorter *self; WockyLLContact *contact; OpenPorterIfNecessaryFunc callback; GCancellable *cancellable; GSimpleAsyncResult *simple; gpointer user_data; } OpenPorterData; static void made_connection_connect_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { WockyLLConnector *connector = WOCKY_LL_CONNECTOR (source_object); WockyXmppConnection *connection; GError *error = NULL; OpenPorterData *data = user_data; WockyPorter *porter; connection = wocky_ll_connector_finish (connector, result, NULL, &error); if (connection == NULL) { DEBUG ("failed to connect: %s", error->message); data->callback (data->self, NULL, NULL, error, data->simple, data->user_data); g_clear_error (&error); goto out; } DEBUG ("connected"); porter = create_porter (data->self, connection, WOCKY_CONTACT (data->contact)); data->callback (data->self, porter, data->cancellable, NULL, data->simple, data->user_data); g_object_unref (connection); out: g_object_unref (data->contact); g_slice_free (OpenPorterData, data); } static void make_connection_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { WockyLLConnectionFactory *factory = WOCKY_LL_CONNECTION_FACTORY (source_object); WockyXmppConnection *connection; GError *error = NULL; OpenPorterData *data = user_data; WockyMetaPorterPrivate *priv = data->self->priv; gchar *jid; connection = wocky_ll_connection_factory_make_connection_finish (factory, result, &error); if (connection == NULL) { DEBUG ("making connection failed: %s", error->message); data->callback (data->self, NULL, NULL, error, data->simple, data->user_data); g_clear_error (&error); g_object_unref (data->contact); g_slice_free (OpenPorterData, data); return; } jid = wocky_contact_dup_jid (WOCKY_CONTACT (data->contact)); wocky_ll_connector_outgoing_async (connection, priv->jid, jid, data->cancellable, made_connection_connect_cb, data); g_free (jid); } /* Convenience function to call @callback with a porter and do all the * handling the creating a porter if necessary. */ static void open_porter_if_necessary (WockyMetaPorter *self, WockyLLContact *contact, GCancellable *cancellable, OpenPorterIfNecessaryFunc callback, GSimpleAsyncResult *simple, gpointer user_data) { WockyMetaPorterPrivate *priv = self->priv; PorterData *porter_data = g_hash_table_lookup (priv->porters, contact); OpenPorterData *data; if (porter_data != NULL && porter_data->porter != NULL) { callback (self, porter_data->porter, cancellable, NULL, simple, user_data); return; } data = g_slice_new0 (OpenPorterData); data->self = self; data->contact = g_object_ref (contact); data->callback = callback; data->cancellable = cancellable; data->simple = simple; data->user_data = user_data; wocky_ll_connection_factory_make_connection_async (priv->connection_factory, contact, cancellable, make_connection_cb, data); } static void meta_porter_send_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { GSimpleAsyncResult *simple = user_data; GError *error = NULL; if (!wocky_porter_send_finish (WOCKY_PORTER (source_object), result, &error)) { g_simple_async_result_set_from_error (simple, error); g_clear_error (&error); } g_simple_async_result_complete (simple); g_object_unref (simple); } static void meta_porter_send_got_porter_cb (WockyMetaPorter *self, WockyPorter *porter, GCancellable *cancellable, const GError *error, GSimpleAsyncResult *simple, gpointer user_data) { WockyStanza *stanza = user_data; if (error != NULL) { g_simple_async_result_set_from_error (simple, error); g_simple_async_result_complete (simple); g_object_unref (simple); } else { wocky_porter_send_async (porter, stanza, cancellable, meta_porter_send_cb, simple); } g_object_unref (stanza); } static void wocky_meta_porter_send_async (WockyPorter *porter, WockyStanza *stanza, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyMetaPorter *self = WOCKY_META_PORTER (porter); WockyMetaPorterPrivate *priv = self->priv; GSimpleAsyncResult *simple; WockyContact *to; simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_meta_porter_send_async); to = wocky_stanza_get_to_contact (stanza); g_return_if_fail (WOCKY_IS_LL_CONTACT (to)); /* stamp on from if there is none */ if (wocky_stanza_get_from (stanza) == NULL) { wocky_node_set_attribute (wocky_stanza_get_top_node (stanza), "from", priv->jid); } open_porter_if_necessary (self, WOCKY_LL_CONTACT (to), cancellable, meta_porter_send_got_porter_cb, simple, g_object_ref (stanza)); } static gboolean wocky_meta_porter_send_finish (WockyPorter *self, GAsyncResult *result, GError **error) { g_return_val_if_fail (WOCKY_IS_META_PORTER (self), FALSE); wocky_implement_finish_void (self, wocky_meta_porter_send_async); } static guint16 wocky_meta_porter_listen (WockyMetaPorter *self, GError **error) { WockyMetaPorterPrivate *priv = self->priv; guint16 port; /* The port 5298 is preferred to remain compatible with old versions of * iChat. Try a few close to it, and if those fail, use a random port. */ for (port = 5298; port < 5300; port++) { GError *e = NULL; if (g_socket_listener_add_inet_port (G_SOCKET_LISTENER (priv->listener), port, NULL, &e)) break; if (!g_error_matches (e, G_IO_ERROR, G_IO_ERROR_ADDRESS_IN_USE)) { g_propagate_error (error, e); return 0; } g_clear_error (&e); } if (port < 5300) return port; return g_socket_listener_add_any_inet_port (G_SOCKET_LISTENER (priv->listener), NULL, error); } static void wocky_meta_porter_start (WockyPorter *porter) { WockyMetaPorter *self = WOCKY_META_PORTER (porter); WockyMetaPorterPrivate *priv = self->priv; GError *error = NULL; guint16 port; port = wocky_meta_porter_listen (self, &error); if (error != NULL) { DEBUG ("Failed to listen: %s", error->message); g_clear_error (&error); return; } DEBUG ("listening on port %u", port); g_socket_service_start (G_SOCKET_SERVICE (priv->listener)); priv->port = port; } static gboolean porter_handler_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { StanzaHandler *handler = user_data; WockyMetaPorter *self = handler->self; WockyMetaPorterPrivate *priv = self->priv; WockyLLContact *contact; const gchar *from; /* prefer the from attribute over ignoring it and using the porter * JID */ from = wocky_stanza_get_from (stanza); if (from == NULL) from = g_object_get_qdata (G_OBJECT (porter), PORTER_JID_QUARK); contact = wocky_contact_factory_ensure_ll_contact ( priv->contact_factory, from); wocky_stanza_set_from_contact (stanza, WOCKY_CONTACT (contact)); g_object_unref (contact); return handler->callback (WOCKY_PORTER (handler->self), stanza, handler->user_data); } static void stanza_handler_porter_disposed_cb (gpointer data, GObject *porter) { StanzaHandler *handler = data; g_hash_table_remove (handler->porters, porter); } static void register_porter_handler (StanzaHandler *handler, WockyPorter *porter) { guint id; g_assert (g_hash_table_lookup (handler->porters, porter) == NULL); /* If handler->contact is not NULL, we know that this c2s porter is a * connection to them, so we still don't need to tell it to match the sender. */ id = wocky_porter_register_handler_from_anyone_by_stanza (porter, handler->type, handler->sub_type, handler->priority, porter_handler_cb, handler, handler->stanza); g_hash_table_insert (handler->porters, porter, GUINT_TO_POINTER (id)); g_object_weak_ref (G_OBJECT (porter), stanza_handler_porter_disposed_cb, handler); } static void register_porter_handlers (WockyMetaPorter *self, WockyPorter *porter, WockyContact *contact) { WockyMetaPorterPrivate *priv = self->priv; GList *handlers, *l; handlers = g_hash_table_get_values (priv->handlers); for (l = handlers; l != NULL; l = l->next) { StanzaHandler *handler = l->data; if (contact == handler->contact || handler->contact == NULL) register_porter_handler (handler, porter); } g_list_free (handlers); } static StanzaHandler * stanza_handler_new (WockyMetaPorter *self, WockyLLContact *contact, WockyStanzaType type, WockyStanzaSubType sub_type, guint priority, WockyPorterHandlerFunc callback, gpointer user_data, WockyStanza *stanza) { StanzaHandler *out = g_slice_new0 (StanzaHandler); out->self = self; out->porters = g_hash_table_new (NULL, NULL); if (contact != NULL) out->contact = g_object_ref (contact); out->type = type; out->sub_type = sub_type; out->priority = priority; out->callback = callback; out->user_data = user_data; if (stanza != NULL) out->stanza = g_object_ref (stanza); return out; } static guint wocky_meta_porter_register_handler_from_by_stanza (WockyPorter *porter, WockyStanzaType type, WockyStanzaSubType sub_type, const gchar *jid, guint priority, WockyPorterHandlerFunc callback, gpointer user_data, WockyStanza *stanza) { WockyMetaPorter *self = WOCKY_META_PORTER (porter); WockyMetaPorterPrivate *priv = self->priv; PorterData *porter_data; guint id; StanzaHandler *handler; WockyLLContact *from; g_return_val_if_fail (jid != NULL, 0); from = wocky_contact_factory_lookup_ll_contact ( priv->contact_factory, jid); g_return_val_if_fail (WOCKY_IS_LL_CONTACT (from), 0); handler = stanza_handler_new (self, from, type, sub_type, priority, callback, user_data, stanza); id = priv->next_handler_id++; porter_data = g_hash_table_lookup (priv->porters, from); if (porter_data != NULL && porter_data->porter != NULL) register_porter_handler (handler, porter_data->porter); g_hash_table_insert (priv->handlers, GUINT_TO_POINTER (id), handler); return id; } static guint wocky_meta_porter_register_handler_from_anyone_by_stanza (WockyPorter *porter, WockyStanzaType type, WockyStanzaSubType sub_type, guint priority, WockyPorterHandlerFunc callback, gpointer user_data, WockyStanza *stanza) { WockyMetaPorter *self = WOCKY_META_PORTER (porter); WockyMetaPorterPrivate *priv = self->priv; PorterData *porter_data; guint id; StanzaHandler *handler; GList *porters, *l; handler = stanza_handler_new (self, NULL, type, sub_type, priority, callback, user_data, stanza); id = priv->next_handler_id++; /* register on all porters */ porters = g_hash_table_get_values (priv->porters); for (l = porters; l != NULL; l = l->next) { porter_data = l->data; if (porter_data->porter != NULL) register_porter_handler (handler, porter_data->porter); } g_list_free (porters); g_hash_table_insert (priv->handlers, GUINT_TO_POINTER (id), handler); return id; } static void wocky_meta_porter_unregister_handler (WockyPorter *porter, guint id) { WockyMetaPorter *self = WOCKY_META_PORTER (porter); WockyMetaPorterPrivate *priv = self->priv; g_hash_table_remove (priv->handlers, GUINT_TO_POINTER (id)); } typedef gboolean (* ClosePorterFinishFunc) (WockyPorter *, GAsyncResult *, GError **); typedef void (* ClosePorterAsyncFunc) (WockyPorter *, GCancellable *, GAsyncReadyCallback, gpointer); typedef struct { GSimpleAsyncResult *simple; guint remaining; gboolean failed; ClosePorterFinishFunc close_finish; } ClosePorterData; static void porter_close_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { WockyPorter *porter = WOCKY_PORTER (source_object); GError *error = NULL; ClosePorterData *data = user_data; if (!data->close_finish (porter, result, &error)) { DEBUG ("Failed to close porter: %s", error->message); g_clear_error (&error); data->failed = TRUE; } data->remaining--; if (data->remaining > 0) return; /* all porters have now replied */ if (data->failed) { g_simple_async_result_set_error (data->simple, WOCKY_META_PORTER_ERROR, WOCKY_META_PORTER_ERROR_FAILED_TO_CLOSE, "Failed to close at least one porter"); } g_simple_async_result_complete (data->simple); g_object_unref (data->simple); g_slice_free (ClosePorterData, data); } static void close_all_porters (WockyMetaPorter *self, ClosePorterAsyncFunc close_async_func, ClosePorterFinishFunc close_finish_func, gpointer source_tag, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyMetaPorterPrivate *priv = self->priv; GSimpleAsyncResult *simple; GList *porters, *l; gboolean close_called = FALSE; porters = g_hash_table_get_values (priv->porters); simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data, source_tag); g_signal_emit_by_name (self, "closing"); if (porters != NULL) { ClosePorterData *data = g_slice_new0 (ClosePorterData); data->close_finish = close_finish_func; data->remaining = 0; data->simple = simple; for (l = porters; l != NULL; l = l->next) { PorterData *porter_data = l->data; /* NULL if there's a refcount but no porter */ if (porter_data->porter == NULL) continue; data->remaining++; close_called = TRUE; close_async_func (porter_data->porter, cancellable, porter_close_cb, data); } /* Actually, none of the PorterData structs had C2S porters */ if (!close_called) g_slice_free (ClosePorterData, data); } if (!close_called) { /* there were no porters to close anyway */ g_simple_async_result_complete (simple); g_object_unref (simple); } g_list_free (porters); } static void wocky_meta_porter_close_async (WockyPorter *porter, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyMetaPorter *self = WOCKY_META_PORTER (porter); close_all_porters (self, wocky_porter_close_async, wocky_porter_close_finish, wocky_meta_porter_close_async, cancellable, callback, user_data); } static gboolean wocky_meta_porter_close_finish (WockyPorter *self, GAsyncResult *result, GError **error) { wocky_implement_finish_void (self, wocky_meta_porter_close_async); } typedef struct { WockyMetaPorter *self; /* already reffed by simple */ GSimpleAsyncResult *simple; WockyContact *contact; } SendIQData; static void meta_porter_send_iq_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { SendIQData *data = user_data; GSimpleAsyncResult *simple = data->simple; GError *error = NULL; WockyStanza *stanza; stanza = wocky_porter_send_iq_finish (WOCKY_PORTER (source_object), result, &error); if (stanza == NULL) { g_simple_async_result_set_from_error (simple, error); g_clear_error (&error); } else { wocky_stanza_set_from_contact (stanza, data->contact); g_simple_async_result_set_op_res_gpointer (simple, stanza, g_object_unref); } g_simple_async_result_complete (simple); wocky_meta_porter_unhold (data->self, data->contact); /* unref simple here as we depend on it holding potentially the last * ref on self */ g_object_unref (data->simple); g_object_unref (data->contact); g_slice_free (SendIQData, data); } static void meta_porter_send_iq_got_porter_cb (WockyMetaPorter *self, WockyPorter *porter, GCancellable *cancellable, const GError *error, GSimpleAsyncResult *simple, gpointer user_data) { WockyStanza *stanza = user_data; WockyContact *contact; contact = wocky_stanza_get_to_contact (stanza); if (error != NULL) { g_simple_async_result_set_from_error (simple, error); g_simple_async_result_complete (simple); wocky_meta_porter_unhold (self, contact); /* unref simple here as we depend on it potentially holding the * last ref to self */ g_object_unref (simple); } else { SendIQData *data = g_slice_new0 (SendIQData); data->self = self; data->simple = simple; data->contact = g_object_ref (contact); wocky_porter_send_iq_async (porter, stanza, cancellable, meta_porter_send_iq_cb, data); } g_object_unref (stanza); } static void wocky_meta_porter_send_iq_async (WockyPorter *porter, WockyStanza *stanza, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyMetaPorter *self = WOCKY_META_PORTER (porter); WockyMetaPorterPrivate *priv = self->priv; GSimpleAsyncResult *simple; WockyContact *to; to = wocky_stanza_get_to_contact (stanza); g_return_if_fail (WOCKY_IS_LL_CONTACT (to)); simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_meta_porter_send_iq_async); wocky_meta_porter_hold (self, to); /* stamp on from if there is none */ if (wocky_node_get_attribute (wocky_stanza_get_top_node (stanza), "from") == NULL) { wocky_node_set_attribute (wocky_stanza_get_top_node (stanza), "from", priv->jid); } open_porter_if_necessary (self, WOCKY_LL_CONTACT (to), cancellable, meta_porter_send_iq_got_porter_cb, simple, g_object_ref (stanza)); } static WockyStanza * wocky_meta_porter_send_iq_finish (WockyPorter *self, GAsyncResult *result, GError **error) { wocky_implement_finish_return_copy_pointer (self, wocky_meta_porter_send_iq_async, g_object_ref); } static void wocky_meta_porter_force_close_async (WockyPorter *porter, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyMetaPorter *self = WOCKY_META_PORTER (porter); close_all_porters (self, wocky_porter_force_close_async, wocky_porter_force_close_finish, wocky_meta_porter_force_close_async, cancellable, callback, user_data); } static gboolean wocky_meta_porter_force_close_finish (WockyPorter *self, GAsyncResult *result, GError **error) { wocky_implement_finish_void (self, wocky_meta_porter_force_close_async); } /** * wocky_meta_porter_get_port: * @porter: a #WockyMetaPorter * * Returns the port @porter is listening in on for new incoming XMPP * connections, or 0 if it has not been started yet with * wocky_porter_start(). * * Returns: the port @porter is listening in on for new incoming XMPP * connections, or 0 if it has not been started. */ guint16 wocky_meta_porter_get_port (WockyMetaPorter *self) { g_return_val_if_fail (WOCKY_IS_META_PORTER (self), 0); return self->priv->port; } /** * wocky_meta_porter_set_jid: * @porter: a #WockyMetaPorter * @jid: a new JID * * Changes the local JID according to @porter. Note that this function * can only be called once, and only if %NULL was passed to * wocky_meta_porter_new() when creating @porter. Calling it again * will be a no-op. */ void wocky_meta_porter_set_jid (WockyMetaPorter *self, const gchar *jid) { WockyMetaPorterPrivate *priv; g_return_if_fail (WOCKY_IS_META_PORTER (self)); priv = self->priv; /* You cannot set the meta porter JID again */ g_return_if_fail (priv->jid == NULL); /* don't try and change existing porter's JIDs */ priv->jid = g_strdup (jid); /* now we can do this */ create_loopback_porter (self); } static void meta_porter_open_got_porter_cb (WockyMetaPorter *self, WockyPorter *porter, GCancellable *cancellable, const GError *error, GSimpleAsyncResult *simple, gpointer user_data) { WockyContact *contact = user_data; if (error != NULL) { g_simple_async_result_set_from_error (simple, error); wocky_meta_porter_unhold (self, contact); } g_simple_async_result_complete (simple); g_object_unref (contact); g_object_unref (simple); } /** * wocky_meta_porter_open_async: * @porter: a #WockyMetaPorter * @contact: the #WockyLLContact * @cancellable: an optional #GCancellable, or %NULL * @callback: a callback to be called * @user_data: data for @callback * * Make an asynchronous request to open a connection to @contact if * one is not already open. The hold count of the porter to * @contact will be incrememented and so after completion * wocky_meta_porter_unhold() should be called on contact to release * the hold. * * When the request is complete, @callback will be called and the user * should call wocky_meta_porter_open_finish() to finish the request. */ void wocky_meta_porter_open_async (WockyMetaPorter *self, WockyLLContact *contact, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *simple; g_return_if_fail (WOCKY_IS_META_PORTER (self)); g_return_if_fail (WOCKY_IS_LL_CONTACT (contact)); g_return_if_fail (callback != NULL); simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_meta_porter_open_async); wocky_meta_porter_hold (self, WOCKY_CONTACT (contact)); open_porter_if_necessary (self, contact, cancellable, meta_porter_open_got_porter_cb, simple, g_object_ref (contact)); } /** * wocky_meta_porter_open_finish: * @porter: a #WockyMetaPorter * @result: the #GAsyncResult * @error: an optional #GError location to store an error message * * Finishes an asynchronous request to open a connection if one is not * already open. See wocky_meta_porter_open_async() for more details. * * Returns: %TRUE if the operation was a success, otherwise %FALSE */ gboolean wocky_meta_porter_open_finish (WockyMetaPorter *self, GAsyncResult *result, GError **error) { wocky_implement_finish_void (self, wocky_meta_porter_open_async); } /** * wocky_meta_porter_borrow_connection: * @porter: a #WockyMetaPorter * @contact: the #WockyContact * * Borrow the #GSocketConnection of the porter to @contact, if one * exists, otherwise %NULL will be returned. * Note that the connection returned should be reffed using * g_object_ref() if it needs to be kept. However, it will still be * operated on by the underlying #WockyXmppConnection object so can * close spontaneously unless wocky_meta_porter_hold() is called with * @contact. * * Returns: the #GSocketConnection or %NULL if no connection is open */ GSocketConnection * wocky_meta_porter_borrow_connection (WockyMetaPorter *self, WockyLLContact *contact) { WockyMetaPorterPrivate *priv; PorterData *porter_data; GSocketConnection *socket_conn; WockyXmppConnection *xmpp_conn; g_return_val_if_fail (WOCKY_IS_META_PORTER (self), NULL); g_return_val_if_fail (WOCKY_IS_LL_CONTACT (contact), NULL); priv = self->priv; porter_data = g_hash_table_lookup (priv->porters, contact); if (porter_data == NULL || porter_data->porter == NULL) return NULL; /* splendid, the connection is already open */ g_object_get (porter_data->porter, "connection", &xmpp_conn, NULL); /* will give it a new ref */ g_object_get (xmpp_conn, "base-stream", &socket_conn, NULL); /* we take back the ref */ g_object_unref (socket_conn); g_object_unref (xmpp_conn); /* but this will still be alive */ return socket_conn; } static void wocky_porter_iface_init (gpointer g_iface, gpointer iface_data) { WockyPorterInterface *iface = g_iface; iface->get_full_jid = wocky_meta_porter_get_jid; iface->get_bare_jid = wocky_meta_porter_get_jid; /* a dummy implementation to return NULL so if someone calls it on * us it won't assert */ iface->get_resource = wocky_meta_porter_get_resource; iface->start = wocky_meta_porter_start; iface->send_async = wocky_meta_porter_send_async; iface->send_finish = wocky_meta_porter_send_finish; iface->register_handler_from_by_stanza = wocky_meta_porter_register_handler_from_by_stanza; iface->register_handler_from_anyone_by_stanza = wocky_meta_porter_register_handler_from_anyone_by_stanza; iface->unregister_handler = wocky_meta_porter_unregister_handler; iface->close_async = wocky_meta_porter_close_async; iface->close_finish = wocky_meta_porter_close_finish; iface->send_iq_async = wocky_meta_porter_send_iq_async; iface->send_iq_finish = wocky_meta_porter_send_iq_finish; iface->force_close_async = wocky_meta_porter_force_close_async; iface->force_close_finish = wocky_meta_porter_force_close_finish; } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-bare-contact.h0000664000175000017500000000715611720661341025713 0ustar00cassidycassidy00000000000000/* * wocky-bare-contact.h - Header for WockyBareContact * Copyright (C) 2009 Collabora Ltd. * @author Jonny Lamb * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_BARE_CONTACT_H__ #define __WOCKY_BARE_CONTACT_H__ #include #include "wocky-types.h" #include "wocky-contact.h" #include "wocky-roster.h" G_BEGIN_DECLS /** * WockyBareContactClass: * * The class of a #WockyBareContact. */ typedef struct _WockyBareContactClass WockyBareContactClass; typedef struct _WockyBareContactPrivate WockyBareContactPrivate; struct _WockyBareContactClass { /**/ WockyContactClass parent_class; }; struct _WockyBareContact { /**/ WockyContact parent; WockyBareContactPrivate *priv; }; GType wocky_bare_contact_get_type (void); #define WOCKY_TYPE_BARE_CONTACT \ (wocky_bare_contact_get_type ()) #define WOCKY_BARE_CONTACT(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_BARE_CONTACT, \ WockyBareContact)) #define WOCKY_BARE_CONTACT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_BARE_CONTACT, \ WockyBareContactClass)) #define WOCKY_IS_BARE_CONTACT(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_BARE_CONTACT)) #define WOCKY_IS_BARE_CONTACT_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_BARE_CONTACT)) #define WOCKY_BARE_CONTACT_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_BARE_CONTACT, \ WockyBareContactClass)) WockyBareContact * wocky_bare_contact_new (const gchar *jid); const gchar *wocky_bare_contact_get_jid (WockyBareContact *contact); const gchar *wocky_bare_contact_get_name (WockyBareContact *contact); void wocky_bare_contact_set_name (WockyBareContact *contact, const gchar *name); WockyRosterSubscriptionFlags wocky_bare_contact_get_subscription ( WockyBareContact *contact); void wocky_bare_contact_set_subscription (WockyBareContact *contact, WockyRosterSubscriptionFlags subscription); const gchar * const *wocky_bare_contact_get_groups (WockyBareContact *contact); void wocky_bare_contact_set_groups (WockyBareContact *contact, gchar **groups); gboolean wocky_bare_contact_equal (WockyBareContact *a, WockyBareContact *b); void wocky_bare_contact_add_group (WockyBareContact *contact, const gchar *group); gboolean wocky_bare_contact_in_group (WockyBareContact *contact, const gchar *group); void wocky_bare_contact_remove_group (WockyBareContact *contact, const gchar *group); WockyBareContact * wocky_bare_contact_copy (WockyBareContact *contact); void wocky_bare_contact_debug_print (WockyBareContact *contact); void wocky_bare_contact_add_resource (WockyBareContact *contact, WockyResourceContact *resource); GSList * wocky_bare_contact_get_resources (WockyBareContact *contact); G_END_DECLS #endif /* #ifndef __WOCKY_BARE_CONTACT_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-openssl-dh1024.c0000664000175000017500000000217512005516162025720 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #ifndef HEADER_DH_H #include #endif DH *get_dh1024(void); DH *get_dh1024(void) { static unsigned char dh1024_p[]={ 0xF4,0x88,0xFD,0x58,0x4E,0x49,0xDB,0xCD,0x20,0xB4,0x9D,0xE4, 0x91,0x07,0x36,0x6B,0x33,0x6C,0x38,0x0D,0x45,0x1D,0x0F,0x7C, 0x88,0xB3,0x1C,0x7C,0x5B,0x2D,0x8E,0xF6,0xF3,0xC9,0x23,0xC0, 0x43,0xF0,0xA5,0x5B,0x18,0x8D,0x8E,0xBB,0x55,0x8C,0xB8,0x5D, 0x38,0xD3,0x34,0xFD,0x7C,0x17,0x57,0x43,0xA3,0x1D,0x18,0x6C, 0xDE,0x33,0x21,0x2C,0xB5,0x2A,0xFF,0x3C,0xE1,0xB1,0x29,0x40, 0x18,0x11,0x8D,0x7C,0x84,0xA7,0x0A,0x72,0xD6,0x86,0xC4,0x03, 0x19,0xC8,0x07,0x29,0x7A,0xCA,0x95,0x0C,0xD9,0x96,0x9F,0xAB, 0xD0,0x0A,0x50,0x9B,0x02,0x46,0xD3,0x08,0x3D,0x66,0xA4,0x5D, 0x41,0x9F,0x9C,0x7C,0xBD,0x89,0x4B,0x22,0x19,0x26,0xBA,0xAB, 0xA2,0x5E,0xC3,0x55,0xE9,0x2F,0x78,0xC7, }; static unsigned char dh1024_g[]={ 0x02, }; DH *dh; if ((dh=DH_new()) == NULL) return(NULL); dh->p=BN_bin2bn(dh1024_p,sizeof(dh1024_p),NULL); dh->g=BN_bin2bn(dh1024_g,sizeof(dh1024_g),NULL); if ((dh->p == NULL) || (dh->g == NULL)) { DH_free(dh); return(NULL); } return(dh); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-bare-contact.c0000664000175000017500000004305011720661341025677 0ustar00cassidycassidy00000000000000/* * wocky-bare-contact.c - Source for WockyBareContact * Copyright (C) 2009 Collabora Ltd. * @author Jonny Lamb * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** * SECTION: wocky-bare-contact * @title: WockyBareContact * @short_description: Wrapper around a roster item. * @include: wocky/wocky-bare-contact.h * * Stores information regarding a roster item and provides a higher level API * for altering its details. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-bare-contact.h" #include #include #include #ifdef HAVE_UNISTD_H # include #endif #include #include "wocky-signals-marshal.h" #include "wocky-utils.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_ROSTER #include "wocky-debug-internal.h" G_DEFINE_TYPE (WockyBareContact, wocky_bare_contact, WOCKY_TYPE_CONTACT) /* properties */ enum { PROP_JID = 1, PROP_NAME, PROP_SUBSCRIPTION, PROP_GROUPS, }; /* signal enum */ enum { LAST_SIGNAL, }; /* static guint signals[LAST_SIGNAL] = {0}; */ /* private structure */ struct _WockyBareContactPrivate { gboolean dispose_has_run; gchar *jid; gchar *name; WockyRosterSubscriptionFlags subscription; gchar **groups; /* list of weak reffed (WockyResourceContact *) * Each WockyResourceContact has a ref on its WockyBareContact so we don't * have to keep a ref on it. */ GSList *resources; }; static void wocky_bare_contact_init (WockyBareContact *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_BARE_CONTACT, WockyBareContactPrivate); self->priv->resources = NULL; } static void wocky_bare_contact_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyBareContact *self = WOCKY_BARE_CONTACT (object); WockyBareContactPrivate *priv = self->priv; switch (property_id) { case PROP_JID: priv->jid = g_value_dup_string (value); break; case PROP_NAME: wocky_bare_contact_set_name (WOCKY_BARE_CONTACT (object), g_value_get_string (value)); break; case PROP_SUBSCRIPTION: priv->subscription = g_value_get_uint (value); break; case PROP_GROUPS: priv->groups = g_value_dup_boxed (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_bare_contact_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyBareContact *self = WOCKY_BARE_CONTACT (object); WockyBareContactPrivate *priv = self->priv; switch (property_id) { case PROP_JID: g_value_set_string (value, priv->jid); break; case PROP_NAME: g_value_set_string (value, priv->name); break; case PROP_SUBSCRIPTION: g_value_set_uint (value, priv->subscription); break; case PROP_GROUPS: g_value_set_boxed (value, priv->groups); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_bare_contact_constructed (GObject *object) { WockyBareContact *self = WOCKY_BARE_CONTACT (object); WockyBareContactPrivate *priv = self->priv; g_assert (priv->jid != NULL); } static void resource_disposed_cb (gpointer user_data, GObject *resource) { WockyBareContact *self = WOCKY_BARE_CONTACT (user_data); WockyBareContactPrivate *priv = self->priv; priv->resources = g_slist_remove (priv->resources, resource); } static void wocky_bare_contact_dispose (GObject *object) { WockyBareContact *self = WOCKY_BARE_CONTACT (object); WockyBareContactPrivate *priv = self->priv; GSList *l; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; for (l = priv->resources; l != NULL; l = g_slist_next (l)) { g_object_weak_unref (G_OBJECT (l->data), resource_disposed_cb, self); } if (G_OBJECT_CLASS (wocky_bare_contact_parent_class)->dispose) G_OBJECT_CLASS (wocky_bare_contact_parent_class)->dispose (object); } static void wocky_bare_contact_finalize (GObject *object) { WockyBareContact *self = WOCKY_BARE_CONTACT (object); WockyBareContactPrivate *priv = self->priv; if (priv->jid != NULL) g_free (priv->jid); if (priv->name != NULL) g_free (priv->name); if (priv->groups != NULL) g_strfreev (priv->groups); g_slist_free (priv->resources); G_OBJECT_CLASS (wocky_bare_contact_parent_class)->finalize (object); } static gchar * bare_contact_dup_jid (WockyContact *contact) { return g_strdup (wocky_bare_contact_get_jid (WOCKY_BARE_CONTACT (contact))); } static void wocky_bare_contact_class_init (WockyBareContactClass *wocky_bare_contact_class) { GObjectClass *object_class = G_OBJECT_CLASS (wocky_bare_contact_class); WockyContactClass *contact_class = WOCKY_CONTACT_CLASS (wocky_bare_contact_class); GParamSpec *spec; g_type_class_add_private (wocky_bare_contact_class, sizeof (WockyBareContactPrivate)); object_class->constructed = wocky_bare_contact_constructed; object_class->set_property = wocky_bare_contact_set_property; object_class->get_property = wocky_bare_contact_get_property; object_class->dispose = wocky_bare_contact_dispose; object_class->finalize = wocky_bare_contact_finalize; contact_class->dup_jid = bare_contact_dup_jid; /** * WockyBareContact:jid: * * The contact's bare JID, according to the roster. */ spec = g_param_spec_string ("jid", "Contact JID", "Contact JID", "", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_JID, spec); /** * WockyBareContact:name: * * The contact's name, according to the roster. */ spec = g_param_spec_string ("name", "Contact Name", "Contact Name", "", G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_NAME, spec); /** * WockyBareContact:subscription: * * The subscription type of the contact, according to the roster. */ spec = g_param_spec_uint ("subscription", "Contact Subscription", "Contact Subscription", 0, LAST_WOCKY_ROSTER_SUBSCRIPTION_TYPE, WOCKY_ROSTER_SUBSCRIPTION_TYPE_NONE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SUBSCRIPTION, spec); /** * WockyBareContact:groups: * * A list of the contact's groups, according to the roster. */ spec = g_param_spec_boxed ("groups", "Contact Groups", "Contact Groups", G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_GROUPS, spec); } /** * wocky_bare_contact_new: * @jid: the JID of the contact to create * * Creates a new #WockyBareContact for a given JID. * * Returns: a newly constructed #WockyBareContact */ WockyBareContact * wocky_bare_contact_new (const gchar *jid) { return g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", jid, NULL); } /** * wocky_bare_contact_get_jid: * @contact: a #WockyBareContact instance * * Returns the JID of the contact wrapped by @contact. * * Returns: @contact's JID. */ const gchar * wocky_bare_contact_get_jid (WockyBareContact *contact) { WockyBareContactPrivate *priv; g_return_val_if_fail (WOCKY_IS_BARE_CONTACT (contact), NULL); priv = contact->priv; return priv->jid; } /** * wocky_bare_contact_get_name: * @contact: #WockyBareContact instance * * Returns the name of the contact wrapped by @contact. * * Returns: @contact's name */ const gchar * wocky_bare_contact_get_name (WockyBareContact *contact) { WockyBareContactPrivate *priv; g_return_val_if_fail (WOCKY_IS_BARE_CONTACT (contact), NULL); priv = contact->priv; return priv->name; } /* FIXME: document that wocky_bare_contact_set_* shouldn't be used by users */ /** * wocky_bare_contact_set_name: * @contact: a #WockyBareContact instance * @name: the name to set @contact * * Sets @contact's name to @name. * */ void wocky_bare_contact_set_name (WockyBareContact *contact, const gchar *name) { WockyBareContactPrivate *priv; g_return_if_fail (WOCKY_IS_BARE_CONTACT (contact)); priv = contact->priv; if (!wocky_strdiff (priv->name, name)) return; g_free (priv->name); priv->name = g_strdup (name); g_object_notify (G_OBJECT (contact), "name"); } /** * wocky_bare_contact_get_subscription: * @contact: a #WockyBareContact instance * * Gets the subscription type @contact has. * * Returns: @contact's subscription. */ WockyRosterSubscriptionFlags wocky_bare_contact_get_subscription (WockyBareContact *contact) { WockyBareContactPrivate *priv; g_return_val_if_fail (WOCKY_IS_BARE_CONTACT (contact), WOCKY_ROSTER_SUBSCRIPTION_TYPE_NONE); priv = contact->priv; return priv->subscription; } /** * wocky_bare_contact_set_subscription: * @contact: a #WockyBareContact instance * @subscription: the new subscription type * * Sets the subscription of @contact. * */ void wocky_bare_contact_set_subscription (WockyBareContact *contact, WockyRosterSubscriptionFlags subscription) { WockyBareContactPrivate *priv; g_return_if_fail (WOCKY_IS_BARE_CONTACT (contact)); priv = contact->priv; if (priv->subscription == subscription) return; priv->subscription = subscription; g_object_notify (G_OBJECT (contact), "subscription"); } /** * wocky_bare_contact_get_groups: * @contact: a #WockyBareContact instance * * Returns the list of the groups of @contact. * * Returns: a list of @contact's groups */ const gchar * const * wocky_bare_contact_get_groups (WockyBareContact *contact) { WockyBareContactPrivate *priv; g_return_val_if_fail (WOCKY_IS_BARE_CONTACT (contact), NULL); priv = contact->priv; return (const gchar * const *) priv->groups; } static gint cmp_str (gchar **a, gchar **b) { return strcmp (*a, *b); } static GPtrArray * sort_groups (GStrv groups) { GPtrArray *arr; guint i; arr = g_ptr_array_sized_new (g_strv_length (groups)); for (i = 0; groups[i] != NULL; i++) { g_ptr_array_add (arr, groups[i]); } g_ptr_array_sort (arr, (GCompareFunc) cmp_str); return arr; } static gboolean groups_equal (const gchar * const * groups_a, const gchar * const * groups_b) { GPtrArray *arr_a, *arr_b; guint i; gboolean result = TRUE; if (groups_a == NULL && groups_b == NULL) return TRUE; if (groups_a == NULL || groups_b == NULL) return FALSE; if (g_strv_length ((GStrv) groups_a) != g_strv_length ((GStrv) groups_b)) return FALSE; /* Sort both groups array and then compare elements one by one */ arr_a = sort_groups ((GStrv) groups_a); arr_b = sort_groups ((GStrv) groups_b); for (i = 0; i != arr_a->len && result; i++) { const gchar *a = g_ptr_array_index (arr_a, i); const gchar *b = g_ptr_array_index (arr_b, i); if (wocky_strdiff (a, b)) result = FALSE; } g_ptr_array_unref (arr_a); g_ptr_array_unref (arr_b); return result; } /** * wocky_bare_contact_set_groups: * @contact: a #WockyBareContact instance * @groups: a list of groups * * Sets @contact's groups. * */ void wocky_bare_contact_set_groups (WockyBareContact *contact, gchar **groups) { WockyBareContactPrivate *priv; g_return_if_fail (WOCKY_IS_BARE_CONTACT (contact)); priv = contact->priv; if (groups_equal ((const gchar * const *) groups, (const gchar * const *) priv->groups)) return; if (priv->groups != NULL) g_strfreev (priv->groups); priv->groups = g_strdupv (groups); g_object_notify (G_OBJECT (contact), "groups"); } /** * wocky_bare_contact_equal: * @a: a #WockyBareContact instance * @b: a #WockyBareContact instance to compare with @a * * Compares whether two #WockyBareContact instances refer to the same * roster item. * * Returns: #TRUE if the two contacts match. */ gboolean wocky_bare_contact_equal (WockyBareContact *a, WockyBareContact *b) { const gchar * const * groups_a; const gchar * const * groups_b; if (a == NULL || b == NULL) return FALSE; if (wocky_strdiff (wocky_bare_contact_get_jid (a), wocky_bare_contact_get_jid (b))) return FALSE; if (wocky_strdiff (wocky_bare_contact_get_name (a), wocky_bare_contact_get_name (b))) return FALSE; if (wocky_bare_contact_get_subscription (a) != wocky_bare_contact_get_subscription (b)) return FALSE; groups_a = wocky_bare_contact_get_groups (a); groups_b = wocky_bare_contact_get_groups (b); return groups_equal (groups_a, groups_b); } /** * wocky_bare_contact_add_group: * @contact: a #WockyBareContact instance * @group: a group * * Adds @group to contact's groups. */ void wocky_bare_contact_add_group (WockyBareContact *self, const gchar *group) { WockyBareContactPrivate *priv = self->priv; GPtrArray *arr; gboolean group_already_present = FALSE; if (priv->groups != NULL) { guint len, i; len = g_strv_length (priv->groups); arr = g_ptr_array_sized_new (len + 2); for (i = 0; priv->groups[i] != NULL; i++) { g_ptr_array_add (arr, g_strdup (priv->groups[i])); if (!wocky_strdiff (priv->groups[i], group)) /* Don't add the group twice */ group_already_present = TRUE; } g_strfreev (priv->groups); } else { arr = g_ptr_array_sized_new (2); } if (!group_already_present) g_ptr_array_add (arr, g_strdup (group)); /* Add trailing NULL */ g_ptr_array_add (arr, NULL); priv->groups = (GStrv) g_ptr_array_free (arr, FALSE); } /** * wocky_bare_contact_in_group: * @contact: a #WockyBareContact instance * @group: a group * * Determines whether the given contact is in @group. * * Returns: #TRUE if the contact is in the given group. */ gboolean wocky_bare_contact_in_group (WockyBareContact *self, const gchar *group) { WockyBareContactPrivate *priv = self->priv; guint i; if (priv->groups == NULL) return FALSE; for (i = 0; priv->groups[i] != NULL; i++) { if (!wocky_strdiff (priv->groups[i], group)) return TRUE; } return FALSE; } /** * wocky_bare_contact_remove_group: * @contact: a #WockyBareContact instance * @group: a group * * Removes @group from the contact's groups. */ void wocky_bare_contact_remove_group (WockyBareContact *self, const gchar *group) { WockyBareContactPrivate *priv = self->priv; GPtrArray *arr; guint len, i; if (priv->groups == NULL) return; len = g_strv_length (priv->groups); arr = g_ptr_array_sized_new (len); for (i = 0; priv->groups[i] != NULL; i++) { if (!wocky_strdiff (priv->groups[i], group)) continue; g_ptr_array_add (arr, g_strdup (priv->groups[i])); } g_strfreev (priv->groups); /* Add trailing NULL */ g_ptr_array_add (arr, NULL); priv->groups = (GStrv) g_ptr_array_free (arr, FALSE); } /** * wocky_bare_contact_copy: * @contact: a #WockyBareContact instance * * Convenience function to obtain a copy of the given #WockyBareContact. * * Returns: a newly created #WockyBareContact which is a copy of the given * one. */ WockyBareContact * wocky_bare_contact_copy (WockyBareContact *contact) { return g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", wocky_bare_contact_get_jid (contact), "name", wocky_bare_contact_get_name (contact), "subscription", wocky_bare_contact_get_subscription (contact), "groups", wocky_bare_contact_get_groups (contact), NULL); } /** * wocky_bare_contact_debug_print: * @contact: a #WockyBareContact instance * * Prints debug information for the given #WockyBareContact. */ void wocky_bare_contact_debug_print (WockyBareContact *self) { WockyBareContactPrivate *priv = self->priv; guint i; DEBUG ("Contact: %s Name: %s Subscription: %s Groups:", priv->jid, priv->name, wocky_roster_subscription_to_string (priv->subscription)); for (i = 0; priv->groups[i] != NULL; i++) DEBUG (" - %s", priv->groups[i]); } /** * wocky_bare_contact_add_resource: * @contact: a #WockyBareContact instance * @resource: a #WockyResourceContact instance * * Adds @resource to the contact's resources. * The #WockyBareContact instance doesn't assume a reference to @resource. */ void wocky_bare_contact_add_resource (WockyBareContact *self, WockyResourceContact *resource) { WockyBareContactPrivate *priv = self->priv; g_object_weak_ref (G_OBJECT (resource), resource_disposed_cb, self); priv->resources = g_slist_append (priv->resources, resource); } /** * wocky_bare_contact_get_resources: * @contact: a #WockyBareContact instance * * Gets a #GSList of all the contact's resources. * You should call #g_slist_free on the list when done with it. * * Returns: a #GSList of #WockyResourceContact objects. */ GSList * wocky_bare_contact_get_resources (WockyBareContact *self) { WockyBareContactPrivate *priv = self->priv; return g_slist_copy (priv->resources); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-disco-identity.h0000664000175000017500000000460611720661341026276 0ustar00cassidycassidy00000000000000/* * wocky-disco-identity.h — utility API representing a Disco Identity * Copyright © 2010 Collabora Ltd. * Copyright © 2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_DISCO_IDENTITY_H__ #define __WOCKY_DISCO_IDENTITY_H__ #include G_BEGIN_DECLS typedef struct _WockyDiscoIdentity WockyDiscoIdentity; /** * WockyDiscoIdentity: * @category: the identity category * @type: the identity type * @lang: the identity language * @name: the identity name * * A structure used to hold information regarding an identity from a * disco reply as described in XEP-0030. */ struct _WockyDiscoIdentity { gchar *category; gchar *type; gchar *lang; gchar *name; }; #define WOCKY_TYPE_DISCO_IDENTITY (wocky_disco_identity_get_type ()) GType wocky_disco_identity_get_type (void); WockyDiscoIdentity *wocky_disco_identity_new (const gchar *category, const gchar *type, const gchar *lang, const gchar *name) G_GNUC_WARN_UNUSED_RESULT; WockyDiscoIdentity *wocky_disco_identity_copy ( const WockyDiscoIdentity *source) G_GNUC_WARN_UNUSED_RESULT; void wocky_disco_identity_free (WockyDiscoIdentity *identity); gint wocky_disco_identity_cmp (WockyDiscoIdentity *left, WockyDiscoIdentity *right); /* array of WockyDiscoIdentity helper methods */ GPtrArray * wocky_disco_identity_array_new (void) G_GNUC_WARN_UNUSED_RESULT; GPtrArray * wocky_disco_identity_array_copy (const GPtrArray *source) G_GNUC_WARN_UNUSED_RESULT; void wocky_disco_identity_array_free (GPtrArray *arr); G_END_DECLS #endif /* #ifndef __WOCKY_DISCO_IDENTITY_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jingle-transport-iface.h0000664000175000017500000001047312332440453027713 0ustar00cassidycassidy00000000000000/* * wocky-jingle-transport-iface.h - Header for WockyJingleTransportIface * Copyright (C) 2007-2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_JINGLE_TRANSPORT_IFACE_H__ #define __WOCKY_JINGLE_TRANSPORT_IFACE_H__ #include #include "wocky-jingle-factory.h" #include "wocky-jingle-types.h" G_BEGIN_DECLS typedef enum { WOCKY_JINGLE_TRANSPORT_STATE_DISCONNECTED, WOCKY_JINGLE_TRANSPORT_STATE_CONNECTING, WOCKY_JINGLE_TRANSPORT_STATE_CONNECTED } WockyJingleTransportState; typedef struct _WockyJingleTransportIface WockyJingleTransportIface; typedef struct _WockyJingleTransportIfaceClass WockyJingleTransportIfaceClass; struct _WockyJingleTransportIfaceClass { GTypeInterface parent; void (*parse_candidates) (WockyJingleTransportIface *, WockyNode *, GError **); void (*new_local_candidates) (WockyJingleTransportIface *, GList *); void (*inject_candidates) (WockyJingleTransportIface *, WockyNode *transport_node); void (*send_candidates) (WockyJingleTransportIface *, gboolean all); gboolean (*can_accept) (WockyJingleTransportIface *); GList * (*get_remote_candidates) (WockyJingleTransportIface *); GList * (*get_local_candidates) (WockyJingleTransportIface *); gboolean (*get_credentials) (WockyJingleTransportIface *, gchar **ufrag, gchar **pwd); WockyJingleTransportType (*get_transport_type) (void); }; GType wocky_jingle_transport_iface_get_type (void); /* TYPE MACROS */ #define WOCKY_TYPE_JINGLE_TRANSPORT_IFACE \ (wocky_jingle_transport_iface_get_type ()) #define WOCKY_JINGLE_TRANSPORT_IFACE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_JINGLE_TRANSPORT_IFACE, WockyJingleTransportIface)) #define WOCKY_IS_JINGLE_TRANSPORT_IFACE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_JINGLE_TRANSPORT_IFACE)) #define WOCKY_JINGLE_TRANSPORT_IFACE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_INTERFACE ((obj), WOCKY_TYPE_JINGLE_TRANSPORT_IFACE,\ WockyJingleTransportIfaceClass)) void wocky_jingle_transport_iface_parse_candidates (WockyJingleTransportIface *, WockyNode *, GError **); void wocky_jingle_transport_iface_new_local_candidates ( WockyJingleTransportIface *self, GList *candidates); void wocky_jingle_transport_iface_inject_candidates ( WockyJingleTransportIface *self, WockyNode *transport_node); void wocky_jingle_transport_iface_send_candidates ( WockyJingleTransportIface *self, gboolean all); gboolean wocky_jingle_transport_iface_can_accept ( WockyJingleTransportIface *self); GList *wocky_jingle_transport_iface_get_remote_candidates (WockyJingleTransportIface *); GList *wocky_jingle_transport_iface_get_local_candidates (WockyJingleTransportIface *); WockyJingleTransportType wocky_jingle_transport_iface_get_transport_type (WockyJingleTransportIface *); gboolean jingle_transport_get_credentials (WockyJingleTransportIface *, gchar **ufrag, gchar **pwd); WockyJingleTransportIface *wocky_jingle_transport_iface_new ( GType type, WockyJingleContent *content, const gchar *transport_ns); WockyJingleCandidate *wocky_jingle_candidate_new (WockyJingleTransportProtocol protocol, WockyJingleCandidateType type, const gchar *id, int component, const gchar *address, int port, int generation, int preference, const gchar *username, const gchar *password, int network); void wocky_jingle_candidate_free (WockyJingleCandidate *c); void jingle_transport_free_candidates (GList *candidates); G_END_DECLS #endif /* #ifndef __WOCKY_JINGLE_TRANSPORT_IFACE_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-roster.c0000664000175000017500000011402512005516162024651 0ustar00cassidycassidy00000000000000/* * wocky-roster.c - Source for WockyRoster * Copyright (C) 2009 Collabora Ltd. * @author Jonny Lamb * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** * SECTION: wocky-roster * @title: WockyRoster * @short_description: TODO * * TODO */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "wocky-roster.h" #include "wocky-bare-contact.h" #include "wocky-c2s-porter.h" #include "wocky-namespaces.h" #include "wocky-stanza.h" #include "wocky-utils.h" #include "wocky-signals-marshal.h" #include "wocky-contact-factory.h" #include "wocky-porter.h" #include "wocky-session.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_ROSTER #include "wocky-debug-internal.h" #define GOOGLE_ROSTER_VERSION "2" G_DEFINE_TYPE (WockyRoster, wocky_roster, G_TYPE_OBJECT) typedef struct { WockyRoster *self; /* The result of the already-sent operation */ /* List of GSimpleAsyncResult to which an IQ has been sent to the server and * that will be completed once we receive the reply of this IQ. */ GSList *flying_operations; gchar *jid; /* The future name of the contact, or NULL to not change it */ gchar *new_name; /* (const gchar *) => TRUE * Each key is a group to add to the contact */ GHashTable *groups_to_add; /* owned (gchar *) => TRUE * Each key is a group to remove from the contact */ GHashTable *groups_to_remove; /* TRUE if a 'add' operation is waiting */ gboolean add_contact; /* TRUE if a 'remove' operation is waiting */ gboolean remove_contact; /* List of GSimpleAsyncResult that will be completed once the changes stored * in this PendingOperation structure will have be completed */ GSList *waiting_operations; } PendingOperation; static PendingOperation * pending_operation_new (WockyRoster *self, GSimpleAsyncResult *result, const gchar *jid) { PendingOperation *pending = g_slice_new0 (PendingOperation); g_assert (self != NULL); g_assert (result != NULL); g_assert (jid != NULL); pending->self = g_object_ref (self); pending->flying_operations = g_slist_append (pending->flying_operations, result); pending->jid = g_strdup (jid); pending->groups_to_add = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); pending->groups_to_remove = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); return pending; } static void pending_operation_free (PendingOperation *pending) { g_object_unref (pending->self); g_free (pending->new_name); g_free (pending->jid); g_slist_foreach (pending->flying_operations, (GFunc) g_object_unref, NULL); g_slist_free (pending->flying_operations); g_slist_foreach (pending->waiting_operations, (GFunc) g_object_unref, NULL); g_slist_free (pending->waiting_operations); g_hash_table_unref (pending->groups_to_add); g_hash_table_unref (pending->groups_to_remove); g_slice_free (PendingOperation, pending); } static void pending_operation_set_new_name (PendingOperation *pending, const gchar *name) { g_free (pending->new_name); pending->new_name = g_strdup (name); } static void pending_operation_set_groups (PendingOperation *pending, GStrv groups) { guint i; g_hash_table_remove_all (pending->groups_to_add); g_hash_table_remove_all (pending->groups_to_remove); for (i = 0; groups[i] != NULL; i++) g_hash_table_insert (pending->groups_to_add, g_strdup (groups[i]), GUINT_TO_POINTER (TRUE)); } static void pending_operation_add_group (PendingOperation *pending, const gchar *group) { g_hash_table_insert (pending->groups_to_add, g_strdup (group), GUINT_TO_POINTER (TRUE)); g_hash_table_remove (pending->groups_to_remove, group); } static void pending_operation_remove_group (PendingOperation *pending, const gchar *group) { g_hash_table_insert (pending->groups_to_remove, g_strdup (group), GUINT_TO_POINTER (TRUE)); g_hash_table_remove (pending->groups_to_add, group); } static void pending_operation_set_add (PendingOperation *pending) { pending->add_contact = TRUE; pending->remove_contact = FALSE; } static void pending_operation_set_remove (PendingOperation *pending) { pending->add_contact = FALSE; pending->remove_contact = TRUE; } static void pending_operation_add_waiting_operation (PendingOperation *pending, GSimpleAsyncResult *result) { pending->waiting_operations = g_slist_append (pending->waiting_operations, result); } static gboolean pending_operation_has_changes (PendingOperation *pending) { if (pending->new_name != NULL) return TRUE; if (g_hash_table_size (pending->groups_to_add) > 0) return TRUE; if (g_hash_table_size (pending->groups_to_remove) > 0) return TRUE; if (pending->add_contact) return TRUE; if (pending->remove_contact) return TRUE; return FALSE; } /* Called when the flying operations have been completed and the IQ to complete * the waiting operations has been sent. */ static void pending_operation_reset (PendingOperation *pending) { /* Free old flying operations */ g_slist_foreach (pending->flying_operations, (GFunc) g_object_unref, NULL); g_slist_free (pending->flying_operations); /* Previously waiting operations are now flying */ pending->flying_operations = pending->waiting_operations; pending->waiting_operations = NULL; } /* properties */ enum { PROP_SESSION = 1, }; /* signal enum */ enum { ADDED, REMOVED, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL] = {0}; /* private structure */ struct _WockyRosterPrivate { WockySession *session; WockyPorter *porter; WockyContactFactory *contact_factory; /* owned (gchar *) => reffed (WockyBareContact *) */ GHashTable *items; guint iq_cb; /* owned (gchar *) => owned (PendingOperation *) * When an edit attempt is "in-flight", we store a PendingOperation * in * this hash table which will be used to store required edits until the one * we already sent is acknowledged. This prevents some race conditions. */ GHashTable *pending_operations; GSimpleAsyncResult *fetch_result; gboolean dispose_has_run; }; /** * wocky_roster_error_quark * * Get the error quark used by the roster. * * Returns: the quark for roster errors. */ GQuark wocky_roster_error_quark (void) { static GQuark quark = 0; if (quark == 0) quark = g_quark_from_static_string ("wocky-roster-error"); return quark; } static void change_roster_iq_cb (GObject *source_object, GAsyncResult *send_iq_res, gpointer user_data); static void wocky_roster_init (WockyRoster *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_ROSTER, WockyRosterPrivate); } static void wocky_roster_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyRoster *self = WOCKY_ROSTER (object); WockyRosterPrivate *priv = self->priv; switch (property_id) { case PROP_SESSION: /* Don't keep a ref on the session at the session keeps a ref on the * roster */ priv->session = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_roster_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyRoster *self = WOCKY_ROSTER (object); WockyRosterPrivate *priv = self->priv; switch (property_id) { case PROP_SESSION: g_value_set_object (value, priv->session); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } const gchar * wocky_roster_subscription_to_string (WockyRosterSubscriptionFlags subscription) { switch (subscription) { case WOCKY_ROSTER_SUBSCRIPTION_TYPE_NONE: return "none"; case WOCKY_ROSTER_SUBSCRIPTION_TYPE_TO: return "to"; case WOCKY_ROSTER_SUBSCRIPTION_TYPE_FROM: return "from"; case WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH: return "both"; default: g_assert_not_reached (); return NULL; } } static void remove_item (WockyRoster *self, const gchar *jid) { WockyRosterPrivate *priv = self->priv; WockyBareContact *contact; contact = g_hash_table_lookup (priv->items, jid); if (contact == NULL) { DEBUG ("%s is not in the roster; can't remove it", jid); return; } /* Removing the contact from the hash table will unref it. Keep it a ref * while firing the 'removed' signal. */ g_object_ref (contact); g_hash_table_remove (priv->items, jid); g_signal_emit (self, signals[REMOVED], 0, contact); g_object_unref (contact); } static gboolean roster_update (WockyRoster *self, WockyStanza *stanza, gboolean fire_signals, GError **error) { WockyRosterPrivate *priv = self->priv; WockyNode *query_node; GSList *j; /* Check stanza contains query node. */ query_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (stanza), "query", WOCKY_XMPP_NS_ROSTER); if (query_node == NULL) { g_set_error_literal (error, WOCKY_ROSTER_ERROR, WOCKY_ROSTER_ERROR_INVALID_STANZA, "IQ does not have query node"); return FALSE; } /* Iterate through item nodes. */ for (j = query_node->children; j; j = j->next) { const gchar *jid; WockyNode *n = (WockyNode *) j->data; WockyBareContact *contact = NULL; const gchar *subscription; WockyRosterSubscriptionFlags subscription_type; GPtrArray *groups_arr; GStrv groups = { NULL }; GSList *l; if (wocky_strdiff (n->name, "item")) { DEBUG ("Node %s is not item, skipping", n->name); continue; } jid = wocky_node_get_attribute (n, "jid"); if (jid == NULL) { DEBUG ("Node %s has no jid attribute, skipping", n->name); continue; } if (strchr (jid, '/') != NULL) { DEBUG ("Item node has resource in jid, skipping"); continue; } /* Parse item. */ subscription = wocky_node_get_attribute (n, "subscription"); if (!wocky_strdiff (subscription, "to")) subscription_type = WOCKY_ROSTER_SUBSCRIPTION_TYPE_TO; else if (!wocky_strdiff (subscription, "from")) subscription_type = WOCKY_ROSTER_SUBSCRIPTION_TYPE_FROM; else if (!wocky_strdiff (subscription, "both")) subscription_type = WOCKY_ROSTER_SUBSCRIPTION_TYPE_BOTH; else if (!wocky_strdiff (subscription, "none")) subscription_type = WOCKY_ROSTER_SUBSCRIPTION_TYPE_NONE; else if (!wocky_strdiff (subscription, "remove")) { remove_item (self, jid); continue; } else { DEBUG ("Unknown subscription: %s; ignoring", subscription); continue; } groups_arr = g_ptr_array_new (); /* Look for "group" nodes */ for (l = n->children; l != NULL; l = g_slist_next (l)) { WockyNode *node = (WockyNode *) l->data; if (wocky_strdiff (node->name, "group")) continue; g_ptr_array_add (groups_arr, g_strdup (node->content)); } /* Add trailing NULL */ g_ptr_array_add (groups_arr, NULL); groups = (GStrv) g_ptr_array_free (groups_arr, FALSE); contact = g_hash_table_lookup (priv->items, jid); if (contact != NULL) { /* Contact already exists; update. */ wocky_bare_contact_set_name (contact, wocky_node_get_attribute (n, "name")); wocky_bare_contact_set_subscription (contact, subscription_type); wocky_bare_contact_set_groups (contact, groups); } else { /* Create a new contact. */ contact = wocky_contact_factory_ensure_bare_contact ( priv->contact_factory, jid); g_object_set (contact, "name", wocky_node_get_attribute (n, "name"), "subscription", subscription_type, "groups", groups, NULL); g_hash_table_insert (priv->items, g_strdup (jid), contact); DEBUG ("New contact added:"); wocky_bare_contact_debug_print (contact); if (fire_signals) g_signal_emit (self, signals[ADDED], 0, contact); } g_strfreev (groups); } return TRUE; } static gboolean roster_iq_handler_set_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { WockyRoster *self = WOCKY_ROSTER (user_data); GError *error = NULL; WockyStanza *reply; if (!roster_update (self, stanza, TRUE, &error)) { DEBUG ("Failed to update roster: %s", error ? error->message : "no message"); g_error_free (error); reply = wocky_stanza_build_iq_error (stanza, NULL); } else { /* ack */ reply = wocky_stanza_build_iq_result (stanza, NULL); } if (reply != NULL) { wocky_porter_send (porter, reply); g_object_unref (reply); } return TRUE; } static void wocky_roster_constructed (GObject *object) { WockyRoster *self = WOCKY_ROSTER (object); WockyRosterPrivate *priv = self->priv; priv->items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); priv->pending_operations = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) pending_operation_free); g_assert (priv->session != NULL); priv->porter = wocky_session_get_porter (priv->session); g_assert (priv->porter != NULL); g_object_ref (priv->porter); priv->iq_cb = wocky_c2s_porter_register_handler_from_server ( WOCKY_C2S_PORTER (priv->porter), WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, roster_iq_handler_set_cb, self, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, ')', NULL); priv->contact_factory = wocky_session_get_contact_factory (priv->session); g_assert (priv->contact_factory != NULL); g_object_ref (priv->contact_factory); } static void wocky_roster_dispose (GObject *object) { WockyRoster *self = WOCKY_ROSTER (object); WockyRosterPrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; if (priv->iq_cb != 0) { wocky_porter_unregister_handler (priv->porter, priv->iq_cb); priv->iq_cb = 0; } g_object_unref (priv->porter); g_object_unref (priv->contact_factory); if (G_OBJECT_CLASS (wocky_roster_parent_class)->dispose) G_OBJECT_CLASS (wocky_roster_parent_class)->dispose (object); } static void wocky_roster_finalize (GObject *object) { WockyRoster *self = WOCKY_ROSTER (object); WockyRosterPrivate *priv = self->priv; g_hash_table_unref (priv->items); g_hash_table_unref (priv->pending_operations); G_OBJECT_CLASS (wocky_roster_parent_class)->finalize (object); } static void wocky_roster_class_init (WockyRosterClass *wocky_roster_class) { GObjectClass *object_class = G_OBJECT_CLASS (wocky_roster_class); GParamSpec *spec; g_type_class_add_private (wocky_roster_class, sizeof (WockyRosterPrivate)); object_class->constructed = wocky_roster_constructed; object_class->set_property = wocky_roster_set_property; object_class->get_property = wocky_roster_get_property; object_class->dispose = wocky_roster_dispose; object_class->finalize = wocky_roster_finalize; spec = g_param_spec_object ("session", "Wocky session", "the wocky session used by this roster", WOCKY_TYPE_SESSION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SESSION, spec); signals[ADDED] = g_signal_new ("added", G_OBJECT_CLASS_TYPE (wocky_roster_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); signals[REMOVED] = g_signal_new ("removed", G_OBJECT_CLASS_TYPE (wocky_roster_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); } WockyRoster * wocky_roster_new (WockySession *session) { g_return_val_if_fail (WOCKY_IS_SESSION (session), NULL); return g_object_new (WOCKY_TYPE_ROSTER, "session", session, NULL); } static void roster_fetch_roster_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; WockyStanza *iq; WockyRoster *self = WOCKY_ROSTER (user_data); WockyRosterPrivate *priv = self->priv; iq = wocky_porter_send_iq_finish (WOCKY_PORTER (source_object), res, &error); if (iq == NULL) goto out; if (!roster_update (self, iq, FALSE, &error)) goto out; out: if (error != NULL) { g_simple_async_result_set_from_error (priv->fetch_result, error); g_error_free (error); } if (iq != NULL) g_object_unref (iq); g_simple_async_result_complete (priv->fetch_result); g_object_unref (priv->fetch_result); priv->fetch_result = NULL; } void wocky_roster_fetch_roster_async (WockyRoster *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyRosterPrivate *priv; WockyStanza *iq; g_return_if_fail (WOCKY_IS_ROSTER (self)); priv = self->priv; if (priv->fetch_result != NULL) { g_simple_async_report_error_in_idle (G_OBJECT (self), callback, user_data, G_IO_ERROR, G_IO_ERROR_PENDING, "Another fetch operation is pending"); return; } iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, NULL, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, ')', NULL); priv->fetch_result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_roster_fetch_roster_async); wocky_porter_send_iq_async (priv->porter, iq, cancellable, roster_fetch_roster_cb, self); g_object_unref (iq); } gboolean wocky_roster_fetch_roster_finish (WockyRoster *self, GAsyncResult *result, GError **error) { if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) return FALSE; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), wocky_roster_fetch_roster_async), FALSE); return TRUE; } WockyBareContact * wocky_roster_get_contact (WockyRoster *self, const gchar *jid) { WockyRosterPrivate *priv = self->priv; return g_hash_table_lookup (priv->items, jid); } GSList * wocky_roster_get_all_contacts (WockyRoster *self) { WockyRosterPrivate *priv = self->priv; GSList *result = NULL; GHashTableIter iter; gpointer value; g_hash_table_iter_init (&iter, priv->items); while (g_hash_table_iter_next (&iter, NULL, &value)) { result = g_slist_prepend (result, g_object_ref (value)); } return result; } /* Build an IQ set stanza containing the current state of the contact. * If not NULL, item_node will contain a pointer on the "item" node */ static WockyStanza * build_iq_for_contact (WockyBareContact *contact, WockyNode **item_node) { WockyStanza *iq; WockyNode *item = NULL; const gchar *jid, *name; const gchar * const *groups; guint i; WockyRosterSubscriptionFlags subscription; jid = wocky_bare_contact_get_jid (contact); g_return_val_if_fail (jid != NULL, NULL); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, '(', "item", '*', &item, '@', "jid", jid, ')', ')', NULL); g_assert (item != NULL); name = wocky_bare_contact_get_name (contact); if (name != NULL) { wocky_node_set_attribute (item, "name", name); } subscription = wocky_bare_contact_get_subscription (contact); if (subscription != WOCKY_ROSTER_SUBSCRIPTION_TYPE_NONE) { wocky_node_set_attribute (item, "subscription", wocky_roster_subscription_to_string (subscription)); } groups = wocky_bare_contact_get_groups (contact); for (i = 0; groups != NULL && groups[i] != NULL; i++) { WockyNode *group; group = wocky_node_add_child (item, "group"); wocky_node_set_content (group, groups[i]); } if (item_node != NULL) *item_node = item; return iq; } static WockyStanza * build_remove_contact_iq (WockyBareContact *contact) { return wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL, '(', "query", ':', WOCKY_XMPP_NS_ROSTER, '(', "item", '@', "jid", wocky_bare_contact_get_jid (contact), '@', "subscription", "remove", ')', ')', NULL); } static WockyStanza * build_iq_for_pending (WockyRoster *self, PendingOperation *pending) { WockyRosterPrivate *priv = self->priv; WockyBareContact *contact, *tmp; WockyStanza *iq; GHashTableIter iter; gpointer group; contact = g_hash_table_lookup (priv->items, pending->jid); if (!pending_operation_has_changes (pending)) { /* Nothing to change */ return NULL; } /* There is no sense to try to add and remove a contact at the same time */ g_assert (!pending->add_contact || !pending->remove_contact); if (contact == NULL) { if (pending->remove_contact) { DEBUG ("Contact %s was already removed", pending->jid); return NULL; } else if (!pending->add_contact) { GSList *l; DEBUG ("contact is not in the roster any more"); for (l = pending->waiting_operations; l != NULL; l = g_slist_next (l)) { GSimpleAsyncResult *result = (GSimpleAsyncResult *) l->data; g_simple_async_result_set_error (result, WOCKY_ROSTER_ERROR, WOCKY_ROSTER_ERROR_NOT_IN_ROSTER, "Contact %s is not in the roster any more", pending->jid); } return NULL; } tmp = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", pending->jid, NULL); } else { if (pending->remove_contact) { DEBUG ("Remove contact %s", pending->jid); return build_remove_contact_iq (contact); } tmp = wocky_bare_contact_copy (contact); } if (pending->new_name != NULL) wocky_bare_contact_set_name (tmp, pending->new_name); g_hash_table_iter_init (&iter, pending->groups_to_add); while (g_hash_table_iter_next (&iter, &group, NULL)) { wocky_bare_contact_add_group (tmp, (const gchar *) group); } g_hash_table_iter_init (&iter, pending->groups_to_remove); while (g_hash_table_iter_next (&iter, &group, NULL)) { wocky_bare_contact_remove_group (tmp, (const gchar *) group); } if (wocky_bare_contact_equal (contact, tmp)) { DEBUG ("No change needed"); g_object_unref (tmp); return NULL; } iq = build_iq_for_contact (tmp, NULL); g_object_unref (tmp); return iq; } static void waiting_operations_completed (WockyRoster *self, PendingOperation *pending) { GSList *l; for (l = pending->waiting_operations; l != NULL; l = g_slist_next (l)) { GSimpleAsyncResult *result = (GSimpleAsyncResult *) l->data; g_simple_async_result_complete (result); } } static void flying_operation_completed (PendingOperation *pending, GError *error) { WockyRoster *self = pending->self; WockyRosterPrivate *priv = self->priv; WockyStanza *iq; GSList *l; /* Flying operations are completed */ for (l = pending->flying_operations; l != NULL; l = g_slist_next (l)) { GSimpleAsyncResult *result = (GSimpleAsyncResult *) l->data; if (error != NULL) g_simple_async_result_set_from_error (result, error); g_simple_async_result_complete (result); } if (g_slist_length (pending->waiting_operations) == 0) { /* No waiting operation, we are done */ DEBUG ("No waiting operations"); g_hash_table_remove (priv->pending_operations, pending->jid); return; } iq = build_iq_for_pending (self, pending); if (iq == NULL) { /* No need to send an IQ; complete waiting operations right now */ DEBUG ("No need to send an IQ; complete waiting operations"); waiting_operations_completed (self, pending); g_hash_table_remove (priv->pending_operations, pending->jid); return; } pending_operation_reset (pending); wocky_porter_send_iq_async (priv->porter, iq, NULL, change_roster_iq_cb, pending); g_object_unref (iq); } static void change_roster_iq_cb (GObject *source_object, GAsyncResult *send_iq_res, gpointer user_data) { PendingOperation *pending = (PendingOperation *) user_data; WockyStanza *reply; GError *error = NULL; reply = wocky_porter_send_iq_finish (WOCKY_PORTER (source_object), send_iq_res, &error); if (reply == NULL) goto out; wocky_stanza_extract_errors (reply, NULL, &error, NULL, NULL); /* According to the XMPP RFC, the server has to send a roster upgrade to * each client (including the one which requested the change) before * replying to the 'set' stanza. We upgraded our list of contacts when this * notification has been received. * We can't really check that this upgrade has been actually receive as we * could receive other notifications from the server due to other clients * actions. So we just have to trust the server on this. */ out: if (reply != NULL) g_object_unref (reply); flying_operation_completed (pending, error); if (error != NULL) g_error_free (error); } static PendingOperation * get_pending_operation (WockyRoster *self, const gchar *jid) { WockyRosterPrivate *priv = self->priv; DEBUG ("Look for pending operation with contact %s", jid); return g_hash_table_lookup (priv->pending_operations, jid); } /* Creates a new PendingOperation structure and associates it with the given * jid. This function is used when starting a edit operation while there is no * flying operation with this contact atm. The PendingOperation won't contain * any information as this operation is going to be sent right away and so * doesn't have to be queued. */ static PendingOperation * add_pending_operation (WockyRoster *self, const gchar *jid, GSimpleAsyncResult *result) { WockyRosterPrivate *priv = self->priv; PendingOperation *pending = pending_operation_new (self, result, jid); DEBUG ("Add pending operation for %s", jid); g_hash_table_insert (priv->pending_operations, g_strdup (jid), pending); return pending; } void wocky_roster_add_contact_async (WockyRoster *self, const gchar *jid, const gchar *name, const gchar * const * groups, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyRosterPrivate *priv = self->priv; WockyStanza *iq; GSimpleAsyncResult *result; WockyBareContact *contact, *existing_contact; PendingOperation *pending; g_return_if_fail (jid != NULL); result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_roster_add_contact_async); pending = get_pending_operation (self, jid); if (pending != NULL) { DEBUG ("Another operation is pending for contact %s; queuing this one", jid); pending_operation_set_new_name (pending, name); pending_operation_set_groups (pending, (GStrv) groups); pending_operation_add_waiting_operation (pending, result); pending_operation_set_add (pending); return; } contact = g_object_new (WOCKY_TYPE_BARE_CONTACT, "jid", jid, NULL); if (name != NULL) wocky_bare_contact_set_name (contact, name); if (groups != NULL) wocky_bare_contact_set_groups (contact, (gchar **) groups); existing_contact = g_hash_table_lookup (priv->items, jid); if (existing_contact != NULL) { /* contact is already in the roster. Check if we need to change him. */ if (wocky_bare_contact_equal (contact, existing_contact)) { DEBUG ("Contact %s is already present in the roster; " "no need to change him", jid); g_simple_async_result_complete_in_idle (result); g_object_unref (contact); g_object_unref (result); return; } } iq = build_iq_for_contact (contact, NULL); pending = add_pending_operation (self, jid, result); wocky_porter_send_iq_async (priv->porter, iq, cancellable, change_roster_iq_cb, pending); /* A new contact object will be created and added when we'll receive the * server push notification. */ g_object_unref (contact); g_object_unref (iq); } gboolean wocky_roster_add_contact_finish (WockyRoster *self, GAsyncResult *result, GError **error) { if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) return FALSE; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), wocky_roster_add_contact_async), FALSE); return TRUE; } static gboolean is_contact (gpointer key, gpointer value, gpointer contact) { return value == contact; } static gboolean contact_in_roster (WockyRoster *self, WockyBareContact *contact) { WockyRosterPrivate *priv = self->priv; return g_hash_table_find (priv->items, is_contact, contact) != NULL; } void wocky_roster_remove_contact_async (WockyRoster *self, WockyBareContact *contact, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyRosterPrivate *priv = self->priv; WockyStanza *iq; GSimpleAsyncResult *result; PendingOperation *pending; const gchar *jid; g_return_if_fail (contact != NULL); jid = wocky_bare_contact_get_jid (contact); result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_roster_remove_contact_async); pending = get_pending_operation (self, jid); if (pending != NULL) { DEBUG ("Another operation is pending for contact %s; queuing this one", jid); pending_operation_set_remove (pending); pending_operation_add_waiting_operation (pending, result); return; } if (!contact_in_roster (self, contact)) { DEBUG ("Contact %s is not in the roster", wocky_bare_contact_get_jid ( contact)); g_simple_async_result_complete_in_idle (result); g_object_unref (result); return; } pending = add_pending_operation (self, jid, result); iq = build_remove_contact_iq (contact); wocky_porter_send_iq_async (priv->porter, iq, cancellable, change_roster_iq_cb, pending); g_object_unref (iq); } gboolean wocky_roster_remove_contact_finish (WockyRoster *self, GAsyncResult *result, GError **error) { if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) return FALSE; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), wocky_roster_remove_contact_async), FALSE); return TRUE; } void wocky_roster_change_contact_name_async (WockyRoster *self, WockyBareContact *contact, const gchar *name, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyRosterPrivate *priv = self->priv; WockyStanza *iq; WockyNode *item; GSimpleAsyncResult *result; PendingOperation *pending; const gchar *jid; g_return_if_fail (contact != NULL); jid = wocky_bare_contact_get_jid (contact); result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_roster_change_contact_name_async); pending = get_pending_operation (self, jid); if (pending != NULL) { DEBUG ("Another operation is pending for contact %s; queuing this one", jid); pending_operation_set_new_name (pending, name); pending_operation_add_waiting_operation (pending, result); return; } if (!contact_in_roster (self, contact)) { g_simple_async_report_error_in_idle (G_OBJECT (self), callback, user_data, WOCKY_ROSTER_ERROR, WOCKY_ROSTER_ERROR_NOT_IN_ROSTER, "Contact %s is not in the roster", wocky_bare_contact_get_jid (contact)); g_object_unref (result); return; } if (!wocky_strdiff (wocky_bare_contact_get_name (contact), name)) { DEBUG ("No need to change name; complete immediately"); g_simple_async_result_complete_in_idle (result); g_object_unref (result); return; } pending = add_pending_operation (self, jid, result); iq = build_iq_for_contact (contact, &item); /* set new name */ wocky_node_set_attribute (item, "name", name); wocky_porter_send_iq_async (priv->porter, iq, cancellable, change_roster_iq_cb, pending); g_object_unref (iq); } gboolean wocky_roster_change_contact_name_finish (WockyRoster *self, GAsyncResult *result, GError **error) { if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) return FALSE; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), wocky_roster_change_contact_name_async), FALSE); return TRUE; } void wocky_roster_contact_add_group_async (WockyRoster *self, WockyBareContact *contact, const gchar *group, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyRosterPrivate *priv = self->priv; WockyStanza *iq; WockyNode *item, *group_node; GSimpleAsyncResult *result; PendingOperation *pending; const gchar *jid; g_return_if_fail (contact != NULL); jid = wocky_bare_contact_get_jid (contact); result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_roster_contact_add_group_async); pending = get_pending_operation (self, jid); if (pending != NULL) { DEBUG ("Another operation is pending for contact %s; queuing this one", jid); pending_operation_add_group (pending, group); pending_operation_add_waiting_operation (pending, result); return; } if (!contact_in_roster (self, contact)) { g_simple_async_report_error_in_idle (G_OBJECT (self), callback, user_data, WOCKY_ROSTER_ERROR, WOCKY_ROSTER_ERROR_NOT_IN_ROSTER, "Contact %s is not in the roster", jid); g_object_unref (result); return; } if (wocky_bare_contact_in_group (contact, group)) { DEBUG ("Contact %s in already in group %s; complete immediately", wocky_bare_contact_get_jid (contact), group); g_simple_async_result_complete_in_idle (result); g_object_unref (result); return; } pending = add_pending_operation (self, jid, result); iq = build_iq_for_contact (contact, &item); /* add new group */ group_node = wocky_node_add_child (item, "group"); wocky_node_set_content (group_node, group); wocky_porter_send_iq_async (priv->porter, iq, cancellable, change_roster_iq_cb, pending); g_object_unref (iq); } gboolean wocky_roster_contact_add_group_finish (WockyRoster *self, GAsyncResult *result, GError **error) { if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) return FALSE; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), wocky_roster_contact_add_group_async), FALSE); return TRUE; } void wocky_roster_contact_remove_group_async (WockyRoster *self, WockyBareContact *contact, const gchar *group, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyRosterPrivate *priv = self->priv; WockyStanza *iq; WockyNode *item; GSimpleAsyncResult *result; GSList *l; PendingOperation *pending; const gchar *jid; g_return_if_fail (contact != NULL); jid = wocky_bare_contact_get_jid (contact); result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_roster_contact_remove_group_async); pending = get_pending_operation (self, jid); if (pending != NULL) { DEBUG ("Another operation is pending for contact %s; queuing this one", jid); pending_operation_remove_group (pending, group); pending_operation_add_waiting_operation (pending, result); return; } if (!contact_in_roster (self, contact)) { g_simple_async_report_error_in_idle (G_OBJECT (self), callback, user_data, WOCKY_ROSTER_ERROR, WOCKY_ROSTER_ERROR_NOT_IN_ROSTER, "Contact %s is not in the roster", jid); g_object_unref (result); return; } if (!wocky_bare_contact_in_group (contact, group)) { DEBUG ("Contact %s is not in group %s; complete immediately", jid, group); g_simple_async_result_complete_in_idle (result); g_object_unref (result); return; } pending = add_pending_operation (self, jid, result); iq = build_iq_for_contact (contact, &item); /* remove the group */ /* FIXME: should we add a wocky_node_remove_child () ? */ for (l = item->children; l != NULL; l = g_slist_next (l)) { WockyNode *group_node = (WockyNode *) l->data; if (wocky_strdiff (group_node->name, "group")) continue; if (!wocky_strdiff (group_node->content, group)) { wocky_node_free (group_node); item->children = g_slist_delete_link (item->children, l); break; } } wocky_porter_send_iq_async (priv->porter, iq, cancellable, change_roster_iq_cb, pending); g_object_unref (iq); } gboolean wocky_roster_contact_remove_group_finish (WockyRoster *self, GAsyncResult *result, GError **error) { if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) return FALSE; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), wocky_roster_contact_remove_group_async), FALSE); return TRUE; } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-ll-connector.c0000664000175000017500000003536711720661341025750 0ustar00cassidycassidy00000000000000/* * wocky-ll-connector.c - Source for WockyLLConnector * Copyright (C) 2011 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "wocky-ll-connector.h" #include "wocky-utils.h" #include "wocky-namespaces.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_CONNECTOR #include "wocky-debug-internal.h" static void initable_iface_init (gpointer, gpointer); G_DEFINE_TYPE_WITH_CODE (WockyLLConnector, wocky_ll_connector, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, initable_iface_init)) enum { PROP_STREAM = 1, PROP_CONNECTION, PROP_LOCAL_JID, PROP_REMOTE_JID, PROP_INCOMING, }; /* private structure */ struct _WockyLLConnectorPrivate { GIOStream *stream; WockyXmppConnection *connection; gchar *local_jid; gchar *remote_jid; gboolean incoming; gchar *from; GSimpleAsyncResult *simple; GCancellable *cancellable; }; GQuark wocky_ll_connector_error_quark (void) { static GQuark quark = 0; if (!quark) quark = g_quark_from_static_string ( "wocky_ll_connector_error"); return quark; } static void wocky_ll_connector_init (WockyLLConnector *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_LL_CONNECTOR, WockyLLConnectorPrivate); } static void wocky_ll_connector_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyLLConnector *connector = WOCKY_LL_CONNECTOR (object); WockyLLConnectorPrivate *priv = connector->priv; switch (property_id) { case PROP_STREAM: priv->stream = g_value_get_object (value); break; case PROP_CONNECTION: priv->connection = g_value_get_object (value); break; case PROP_LOCAL_JID: priv->local_jid = g_value_dup_string (value); break; case PROP_REMOTE_JID: priv->remote_jid = g_value_dup_string (value); break; case PROP_INCOMING: priv->incoming = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_ll_connector_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyLLConnector *connector = WOCKY_LL_CONNECTOR (object); WockyLLConnectorPrivate *priv = connector->priv; switch (property_id) { case PROP_STREAM: g_value_set_object (value, priv->stream); break; case PROP_CONNECTION: g_value_set_object (value, priv->connection); break; case PROP_LOCAL_JID: g_value_set_string (value, priv->local_jid); break; case PROP_REMOTE_JID: g_value_set_string (value, priv->remote_jid); break; case PROP_INCOMING: g_value_set_boolean (value, priv->incoming); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_ll_connector_dispose (GObject *object) { WockyLLConnector *self = WOCKY_LL_CONNECTOR (object); WockyLLConnectorPrivate *priv = self->priv; DEBUG ("dispose called"); g_object_unref (priv->connection); priv->connection = NULL; g_free (priv->local_jid); priv->local_jid = NULL; g_free (priv->remote_jid); priv->remote_jid = NULL; g_free (priv->from); priv->from = NULL; if (priv->cancellable != NULL) { g_object_unref (priv->cancellable); priv->cancellable = NULL; } if (G_OBJECT_CLASS (wocky_ll_connector_parent_class)->dispose) G_OBJECT_CLASS (wocky_ll_connector_parent_class)->dispose (object); } static void wocky_ll_connector_constructed (GObject *object) { WockyLLConnector *self = WOCKY_LL_CONNECTOR (object); WockyLLConnectorPrivate *priv = self->priv; if (G_OBJECT_CLASS (wocky_ll_connector_parent_class)->constructed) G_OBJECT_CLASS (wocky_ll_connector_parent_class)->constructed (object); if (priv->connection == NULL) priv->connection = wocky_xmpp_connection_new (priv->stream); } static void wocky_ll_connector_class_init ( WockyLLConnectorClass *wocky_ll_connector_class) { GObjectClass *object_class = G_OBJECT_CLASS (wocky_ll_connector_class); GParamSpec *spec; object_class->get_property = wocky_ll_connector_get_property; object_class->set_property = wocky_ll_connector_set_property; object_class->dispose = wocky_ll_connector_dispose; object_class->constructed = wocky_ll_connector_constructed; spec = g_param_spec_object ("stream", "XMPP stream", "The XMPP stream", G_TYPE_IO_STREAM, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_STREAM, spec); spec = g_param_spec_object ("connection", "XMPP connection", "The XMPP connection", WOCKY_TYPE_XMPP_CONNECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONNECTION, spec); spec = g_param_spec_string ("local-jid", "User's JID", "Local user's XMPP JID", "", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_LOCAL_JID, spec); spec = g_param_spec_string ("remote-jid", "Contact's JID", "Remote contact's XMPP JID", "", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_REMOTE_JID, spec); spec = g_param_spec_boolean ("incoming", "Incoming", "Whether the connection is incoming", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INCOMING, spec); g_type_class_add_private (wocky_ll_connector_class, sizeof (WockyLLConnectorPrivate)); } /** * wocky_ll_connector_incoming_async: * @stream: a #GIOStream * @cancellable: an optional #GCancellable, or %NULL * @callback: a function to call when the operation is complete * @user_data: data to pass to @callback * * Start an asychronous connect operation with an incoming link-local * connection by negotiating the stream open stanzas and sending * stream features. * * The ownership of @stream is taken by the connector. * * When the operation is complete, @callback will be called and it * should call wocky_ll_connector_finish(). */ void wocky_ll_connector_incoming_async ( GIOStream *stream, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_async_initable_new_async (WOCKY_TYPE_LL_CONNECTOR, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "stream", stream, "incoming", TRUE, NULL); } /** * wocky_ll_connector_outgoing_async: * @connection: a #WockyXmppConnection * @local_jid: the JID of the local user * @remote_jid: the JID of the remote contact * @cancellable: an optional #GCancellable, or %NULL * @callback: a function to call when the operation is complete * @user_data: data to pass to @callback * * Start an asychronous connect operation with an outgoing link-local * connection by negotiating the stream open stanzas and sending * stream features. * * The ownership of @connection is taken by the connector. * * When the operation is complete, @callback will be called and it * should call wocky_ll_connector_finish(). */ void wocky_ll_connector_outgoing_async ( WockyXmppConnection *connection, const gchar *local_jid, const gchar *remote_jid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_async_initable_new_async (WOCKY_TYPE_LL_CONNECTOR, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "connection", connection, "local-jid", local_jid, "remote-jid", remote_jid, "incoming", FALSE, NULL); } static void features_sent_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { WockyXmppConnection *connection = WOCKY_XMPP_CONNECTION (source_object); WockyLLConnector *self = user_data; WockyLLConnectorPrivate *priv = self->priv; GError *error = NULL; if (!wocky_xmpp_connection_send_stanza_finish (connection, result, &error)) { DEBUG ("Failed to send stream features: %s", error->message); g_simple_async_result_set_error (priv->simple, WOCKY_LL_CONNECTOR_ERROR, WOCKY_LL_CONNECTOR_ERROR_FAILED_TO_SEND_STANZA, "Failed to send stream features: %s", error->message); g_clear_error (&error); } g_simple_async_result_complete (priv->simple); g_object_unref (priv->simple); priv->simple = NULL; g_object_unref (self); } static void send_open_cb (GObject *source_object, GAsyncResult *result, gpointer user_data); static void recv_open_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { WockyXmppConnection *connection = WOCKY_XMPP_CONNECTION (source_object); GError *error = NULL; WockyLLConnector *self = user_data; WockyLLConnectorPrivate *priv = self->priv; gchar *from = NULL; if (!wocky_xmpp_connection_recv_open_finish (connection, result, NULL, &from, NULL, NULL, NULL, &error)) { DEBUG ("Failed to receive stream open: %s", error->message); g_simple_async_result_set_error (priv->simple, WOCKY_LL_CONNECTOR_ERROR, WOCKY_LL_CONNECTOR_ERROR_FAILED_TO_RECEIVE_STANZA, "Failed to receive stream open: %s", error->message); g_clear_error (&error); g_simple_async_result_complete (priv->simple); g_object_unref (priv->simple); priv->simple = NULL; return; } if (!priv->incoming) { WockyStanza *features; DEBUG ("connected, sending stream features but not " "expecting anything back"); features = wocky_stanza_new ("features", WOCKY_XMPP_NS_STREAM); wocky_xmpp_connection_send_stanza_async (connection, features, NULL, features_sent_cb, self); g_object_unref (features); } else { DEBUG ("stream opened from %s, sending open back", from != NULL ? from : ""); wocky_xmpp_connection_send_open_async (connection, from, priv->local_jid, "1.0", NULL, NULL, priv->cancellable, send_open_cb, self); } priv->from = from; } static void send_open_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { WockyXmppConnection *connection = WOCKY_XMPP_CONNECTION (source_object); GError *error = NULL; WockyLLConnector *self = user_data; WockyLLConnectorPrivate *priv = self->priv; if (!wocky_xmpp_connection_send_open_finish (connection, result, &error)) { DEBUG ("Failed to send stream open: %s", error->message); g_simple_async_result_set_error (priv->simple, WOCKY_LL_CONNECTOR_ERROR, WOCKY_LL_CONNECTOR_ERROR_FAILED_TO_SEND_STANZA, "Failed to send stream open: %s", error->message); g_clear_error (&error); g_simple_async_result_complete (priv->simple); g_object_unref (priv->simple); priv->simple = NULL; return; } if (!priv->incoming) { DEBUG ("successfully sent stream open, now waiting for other side to too"); wocky_xmpp_connection_recv_open_async (connection, priv->cancellable, recv_open_cb, self); } else { WockyStanza *features; DEBUG ("connected, sending stream features but not " "expecting anything back"); features = wocky_stanza_new ("features", WOCKY_XMPP_NS_STREAM); wocky_xmpp_connection_send_stanza_async (connection, features, NULL, features_sent_cb, self); g_object_unref (features); } } /** * wocky_ll_connector_finish: * @connector: a #WockyLLConnector * @result: a #GAsyncResult * @from: a location to store the remote user's JID, or %NULL * @error: a location to save errors to, or %NULL to ignore * * Gets the result of the asynchronous connect request. * * Returns: the connected #WockyXmppConnection which should be freed * using g_object_unref(), or %NULL on error */ WockyXmppConnection * wocky_ll_connector_finish (WockyLLConnector *self, GAsyncResult *result, gchar **from, GError **error) { WockyLLConnectorPrivate *priv = self->priv; if (g_async_initable_new_finish (G_ASYNC_INITABLE (self), result, error) == NULL) return NULL; if (from != NULL) *from = g_strdup (priv->from); return g_object_ref (priv->connection); } static void wocky_ll_connector_init_async (GAsyncInitable *initable, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyLLConnector *self = WOCKY_LL_CONNECTOR (initable); WockyLLConnectorPrivate *priv = self->priv; g_return_if_fail (priv->simple == NULL); priv->simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_ll_connector_init_async); if (cancellable != NULL) priv->cancellable = g_object_ref (cancellable); if (priv->incoming) { /* we need to wait for stream open first */ wocky_xmpp_connection_recv_open_async (priv->connection, priv->cancellable, recv_open_cb, self); } else { /* we need to send stream open first */ wocky_xmpp_connection_send_open_async (priv->connection, priv->remote_jid, priv->local_jid, "1.0", NULL, NULL, priv->cancellable, send_open_cb, self); } } static gboolean wocky_ll_connector_init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error) { WockyLLConnector *self = WOCKY_LL_CONNECTOR (initable); GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); WockyLLConnectorPrivate *priv = self->priv; g_return_val_if_fail (priv->simple == simple, FALSE); if (g_simple_async_result_propagate_error (simple, error)) return FALSE; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), wocky_ll_connector_init_async), FALSE); return TRUE; } static void initable_iface_init (gpointer g_iface, gpointer data) { GAsyncInitableIface *iface = g_iface; iface->init_async = wocky_ll_connector_init_async; iface->init_finish = wocky_ll_connector_init_finish; } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jingle-info.h0000664000175000017500000000730612212322440025536 0ustar00cassidycassidy00000000000000/* * wocky-jingle-info.h - exciting times with Google's jingleinfo extension * Copyright © 2008–2012 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef WOCKY_JINGLE_INFO_H #define WOCKY_JINGLE_INFO_H #include #include "wocky-porter.h" typedef struct _WockyJingleInfo WockyJingleInfo; typedef struct _WockyJingleInfoClass WockyJingleInfoClass; typedef struct _WockyJingleInfoPrivate WockyJingleInfoPrivate; struct _WockyJingleInfoClass { GObjectClass parent_class; }; struct _WockyJingleInfo { GObject parent; WockyJingleInfoPrivate *priv; }; GType wocky_jingle_info_get_type (void); WockyJingleInfo *wocky_jingle_info_new ( WockyPorter *porter); void wocky_jingle_info_take_stun_server ( WockyJingleInfo *self, gchar *stun_server, guint16 stun_port, gboolean is_fallback); void wocky_jingle_info_send_request ( WockyJingleInfo *self, gboolean google_jingleinfo_supported); typedef struct { gchar *address; guint16 port; } WockyStunServer; GList *wocky_jingle_info_get_stun_servers ( WockyJingleInfo *self); const gchar *wocky_jingle_info_get_google_relay_token ( WockyJingleInfo *self); typedef enum { WOCKY_JINGLE_RELAY_TYPE_UDP, WOCKY_JINGLE_RELAY_TYPE_TCP, WOCKY_JINGLE_RELAY_TYPE_TLS } WockyJingleRelayType; #define WOCKY_N_JINGLE_RELAY_TYPES 3 typedef struct { WockyJingleRelayType type; gchar *ip; guint port; gchar *username; gchar *password; guint component; } WockyJingleRelay; WockyJingleRelay *wocky_jingle_relay_new ( WockyJingleRelayType type, const gchar *ip, guint port, const gchar *username, const gchar *password, guint component); void wocky_jingle_relay_free (WockyJingleRelay *relay); /* * @relays: (element-type WockyJingleRelay) (transfer none): a possibly-empty * array of WockyJingleRelay structs. */ typedef void (*WockyJingleInfoRelaySessionCb) ( GPtrArray *relays, gpointer user_data); void wocky_jingle_info_create_google_relay_session ( WockyJingleInfo *self, guint components, WockyJingleInfoRelaySessionCb callback, gpointer user_data); void wocky_jingle_info_set_test_mode (void); /* TYPE MACROS */ #define WOCKY_TYPE_JINGLE_INFO \ (wocky_jingle_info_get_type ()) #define WOCKY_JINGLE_INFO(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_JINGLE_INFO, WockyJingleInfo)) #define WOCKY_JINGLE_INFO_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_JINGLE_INFO,\ WockyJingleInfoClass)) #define WOCKY_IS_JINGLE_INFO(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_JINGLE_INFO)) #define WOCKY_IS_JINGLE_INFO_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_JINGLE_INFO)) #define WOCKY_JINGLE_INFO_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_JINGLE_INFO, \ WockyJingleInfoClass)) #endif /* WOCKY_JINGLE_INFO_H */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jingle-info.c0000664000175000017500000004623312332440077025545 0ustar00cassidycassidy00000000000000/* * wocky-jingle-info.c - exciting times with Google's jingleinfo extension * Copyright © 2008–2012 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "wocky-jingle-info.h" #include "wocky-jingle-info-internal.h" #include #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_JINGLE #include "wocky-debug-internal.h" #include "wocky-google-relay.h" #include "wocky-enumtypes.h" #include "wocky-signals-marshal.h" #include "wocky-namespaces.h" #include "wocky-utils.h" #include "wocky-c2s-porter.h" static gboolean jingle_info_cb ( WockyPorter *porter, WockyStanza *stanza, gpointer user_data); struct _WockyJingleInfoPrivate { WockyPorter *porter; guint jingle_info_handler_id; gchar *jid_domain; WockyGoogleRelayResolver *google_resolver; WockyStunServer *stun_server; WockyStunServer *fallback_stun_server; gchar *relay_token; /* TRUE if the user has not explicitly specified a STUN server, and hence * we should ask the XMPP server for one; FALSE if not. */ gboolean get_stun_from_jingle; gchar *relay_server; guint16 relay_http_port; guint16 relay_udp; guint16 relay_tcp; guint16 relay_ssltcp; }; enum { PROP_PORTER = 1, }; enum { STUN_SERVER_CHANGED = 0, N_SIGNALS }; static guint signals[N_SIGNALS]; static gboolean test_mode = FALSE; void wocky_jingle_info_set_test_mode (void) { test_mode = TRUE; } static WockyStunServer * wocky_stun_server_new ( gchar *address, guint16 port) { WockyStunServer stun_server = { address, port }; return g_slice_dup (WockyStunServer, &stun_server); } static void wocky_stun_server_free (WockyStunServer *stun_server) { if (stun_server != NULL) { g_free (stun_server->address); g_slice_free (WockyStunServer, stun_server); } } G_DEFINE_TYPE (WockyJingleInfo, wocky_jingle_info, G_TYPE_OBJECT) static void wocky_jingle_info_init (WockyJingleInfo *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_JINGLE_INFO, WockyJingleInfoPrivate); self->priv->relay_http_port = 80; self->priv->get_stun_from_jingle = TRUE; } static void wocky_jingle_info_get_property ( GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyJingleInfo *self = WOCKY_JINGLE_INFO (object); WockyJingleInfoPrivate *priv = self->priv; switch (property_id) { case PROP_PORTER: g_value_set_object (value, priv->porter); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void wocky_jingle_info_set_property ( GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyJingleInfo *self = WOCKY_JINGLE_INFO (object); WockyJingleInfoPrivate *priv = self->priv; switch (property_id) { case PROP_PORTER: g_assert (priv->porter == NULL); priv->porter = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void wocky_jingle_info_constructed (GObject *object) { WockyJingleInfo *self = WOCKY_JINGLE_INFO (object); WockyJingleInfoPrivate *priv = self->priv; GObjectClass *parent_class = wocky_jingle_info_parent_class; if (parent_class->constructed != NULL) parent_class->constructed (object); g_assert (priv->porter != NULL); if (!wocky_decode_jid (wocky_porter_get_bare_jid (priv->porter), NULL, &priv->jid_domain, NULL)) g_assert_not_reached (); } static void wocky_jingle_info_dispose (GObject *object) { WockyJingleInfo *self = WOCKY_JINGLE_INFO (object); WockyJingleInfoPrivate *priv = self->priv; GObjectClass *parent_class = wocky_jingle_info_parent_class; if (priv->porter != NULL) { if (priv->jingle_info_handler_id != 0) wocky_porter_unregister_handler (priv->porter, priv->jingle_info_handler_id); g_clear_object (&priv->porter); } if (priv->google_resolver != NULL) { wocky_google_relay_resolver_destroy (priv->google_resolver); priv->google_resolver = NULL; } g_free (priv->jid_domain); priv->jid_domain = NULL; wocky_stun_server_free (priv->stun_server); priv->stun_server = NULL; wocky_stun_server_free (priv->fallback_stun_server); priv->fallback_stun_server = NULL; g_free (priv->relay_token); priv->relay_token = NULL; g_free (priv->relay_server); priv->relay_server = NULL; if (parent_class->dispose != NULL) parent_class->dispose (object); } static void wocky_jingle_info_class_init (WockyJingleInfoClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GParamSpec *param_spec; object_class->get_property = wocky_jingle_info_get_property; object_class->set_property = wocky_jingle_info_set_property; object_class->constructed = wocky_jingle_info_constructed; object_class->dispose = wocky_jingle_info_dispose; g_type_class_add_private (klass, sizeof (WockyJingleInfoPrivate)); param_spec = g_param_spec_object ("porter", "WockyC2SPorter", "Porter for the current connection", WOCKY_TYPE_C2S_PORTER, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_PORTER, param_spec); signals[STUN_SERVER_CHANGED] = g_signal_new ("stun-server-changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__STRING_UINT, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_UINT); } WockyJingleInfo * wocky_jingle_info_new ( WockyPorter *porter) { return g_object_new (WOCKY_TYPE_JINGLE_INFO, "porter", porter, NULL); } typedef struct { WockyJingleInfo *factory; gchar *stun_server; guint16 stun_port; WockyStunServerSource source; GCancellable *cancellable; } PendingStunServer; static void pending_stun_server_free (gpointer p) { PendingStunServer *data = p; if (data->factory != NULL) g_object_remove_weak_pointer (G_OBJECT (data->factory), (gpointer)&data->factory); g_object_unref (data->cancellable); g_free (data->stun_server); g_slice_free (PendingStunServer, p); } static void stun_server_resolved_cb (GObject *resolver, GAsyncResult *result, gpointer user_data) { PendingStunServer *data = user_data; WockyJingleInfo *self = data->factory; GError *e = NULL; WockyStunServer *stun_server; gchar *address; GList *entries; if (self != NULL) g_object_weak_unref (G_OBJECT (self), (GWeakNotify)g_cancellable_cancel, data->cancellable); entries = g_resolver_lookup_by_name_finish ( G_RESOLVER (resolver), result, &e); if (entries == NULL) { DEBUG ("Failed to resolve STUN server %s:%u: %s", data->stun_server, data->stun_port, e->message); g_error_free (e); goto out; } address = g_inet_address_to_string (entries->data); g_resolver_free_addresses (entries); DEBUG ("Resolved STUN server %s:%u to %s:%u", data->stun_server, data->stun_port, address, data->stun_port); if (self == NULL) { g_free (address); goto out; } stun_server = wocky_stun_server_new (address, data->stun_port); if (data->source == WOCKY_STUN_SERVER_FALLBACK) { wocky_stun_server_free (self->priv->fallback_stun_server); self->priv->fallback_stun_server = stun_server; } else { wocky_stun_server_free (self->priv->stun_server); self->priv->stun_server = stun_server; g_signal_emit (self, signals[STUN_SERVER_CHANGED], 0, stun_server, data->stun_port); } out: pending_stun_server_free (data); g_object_unref (resolver); } static void wocky_jingle_info_take_stun_server_internal ( WockyJingleInfo *self, gchar *stun_server, guint16 stun_port, WockyStunServerSource source) { GResolver *resolver; PendingStunServer *data; if (stun_server == NULL) return; if (source == WOCKY_STUN_SERVER_USER_SPECIFIED) self->priv->get_stun_from_jingle = FALSE; resolver = g_resolver_get_default (); data = g_slice_new0 (PendingStunServer); DEBUG ("Resolving %s STUN server %s:%u", wocky_enum_to_nick (WOCKY_TYPE_STUN_SERVER_SOURCE, data->source), stun_server, stun_port); data->factory = self; g_object_add_weak_pointer (G_OBJECT (self), (gpointer *) &data->factory); data->stun_server = stun_server; data->stun_port = stun_port; data->source = source; data->cancellable = g_cancellable_new (); g_object_weak_ref (G_OBJECT (self), (GWeakNotify)g_cancellable_cancel, data->cancellable); g_resolver_lookup_by_name_async (resolver, stun_server, data->cancellable, stun_server_resolved_cb, data); } /* * wocky_jingle_info_take_stun_server: * @self: a #WockyJingleInfo object * @stun_server: (transfer full): the STUN server's address * @stun_port: the STUN server's port * @is_fallback: %TRUE if this is a last resort; %FALSE if this STUN server was * provided by the user (whether by explicitly setting one, or by asking the * user's XMPP server). */ void wocky_jingle_info_take_stun_server ( WockyJingleInfo *self, gchar *stun_server, guint16 stun_port, gboolean is_fallback) { WockyStunServerSource source = is_fallback ? WOCKY_STUN_SERVER_FALLBACK : WOCKY_STUN_SERVER_USER_SPECIFIED; wocky_jingle_info_take_stun_server_internal (self, stun_server, stun_port, source); } static void got_jingle_info_stanza ( WockyJingleInfo *self, WockyStanza *stanza) { WockyNode *node, *query_node; query_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (stanza), "query", WOCKY_XMPP_NS_GOOGLE_JINGLE_INFO); if (query_node == NULL) return; if (self->priv->get_stun_from_jingle) node = wocky_node_get_child (query_node, "stun"); else node = NULL; if (node != NULL) { WockyNodeIter iter; /* TODO: use more than just the first stun server returned. */ wocky_node_iter_init (&iter, node, "server", NULL); if (wocky_node_iter_next (&iter, &node)) { const gchar *server; const gchar *port_attr; guint port = 0; server = wocky_node_get_attribute (node, "host"); port_attr = wocky_node_get_attribute (node, "udp"); if (port_attr != NULL) port = atoi (port_attr); if (server != NULL && port_attr != NULL && port > 0 && port <= G_MAXUINT16) { DEBUG ("jingle info: got stun server %s, port %u", server, port); wocky_jingle_info_take_stun_server_internal (self, g_strdup (server), port, WOCKY_STUN_SERVER_DISCOVERED); } } } #ifdef ENABLE_GOOGLE_RELAY node = wocky_node_get_child (query_node, "relay"); if (node != NULL) { WockyNode *subnode = wocky_node_get_child (node, "token"); if (subnode != NULL) { const gchar *token = subnode->content; if (token != NULL) { DEBUG ("jingle info: got Google relay token %s", token); g_free (self->priv->relay_token); self->priv->relay_token = g_strdup (token); } } subnode = wocky_node_get_child (node, "server"); if (subnode != NULL) { const gchar *server; const gchar *port; server = wocky_node_get_attribute (subnode, "host"); if (server != NULL) { DEBUG ("jingle info: got relay server %s", server); g_free (self->priv->relay_server); self->priv->relay_server = g_strdup (server); } if (test_mode) { /* this is not part of the real protocol, but we can't listen on * port 80 in an unprivileged regression test */ port = wocky_node_get_attribute (subnode, "gabble-test-http-port"); if (port != NULL) { DEBUG ("jingle info: diverting 'Google' HTTP requests to " "port %s", port); self->priv->relay_http_port = atoi (port); } } /* FIXME: these are not really actually used anywhere at * the moment, because we get the same info when creating * relay session. */ port = wocky_node_get_attribute (subnode, "udp"); if (port != NULL) { DEBUG ("jingle info: got relay udp port %s", port); self->priv->relay_udp = atoi (port); } port = wocky_node_get_attribute (subnode, "tcp"); if (port != NULL) { DEBUG ("jingle info: got relay tcp port %s", port); self->priv->relay_tcp = atoi (port); } port = wocky_node_get_attribute (subnode, "tcpssl"); if (port != NULL) { DEBUG ("jingle info: got relay tcpssl port %s", port); self->priv->relay_ssltcp = atoi (port); } } } #endif /* ENABLE_GOOGLE_RELAY */ } static gboolean jingle_info_cb ( WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { WockyJingleInfo *self = WOCKY_JINGLE_INFO (user_data); got_jingle_info_stanza (self, stanza); wocky_porter_acknowledge_iq (porter, stanza, NULL); return TRUE; } static void jingle_info_reply_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { WockyPorter *porter = WOCKY_PORTER (source); WockyJingleInfo *self = WOCKY_JINGLE_INFO (user_data); WockyStanza *reply = NULL; GError *error = NULL; reply = wocky_porter_send_iq_finish (porter, result, &error); if (reply != NULL && !wocky_stanza_extract_errors (reply, NULL, &error, NULL, NULL)) { got_jingle_info_stanza (self, reply); } else { DEBUG ("jingle info request failed: %s", error->message); g_clear_error (&error); } g_clear_object (&reply); g_object_unref (self); } static void wocky_jingle_info_send_google_request ( WockyJingleInfo *self) { WockyJingleInfoPrivate *priv = self->priv; WockyStanza *stanza = wocky_stanza_build ( WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, wocky_porter_get_bare_jid (priv->porter), '(', "query", ':', WOCKY_XMPP_NS_GOOGLE_JINGLE_INFO, ')', NULL); wocky_porter_send_iq_async (priv->porter, stanza, NULL, jingle_info_reply_cb, g_object_ref (self)); g_object_unref (stanza); priv->jingle_info_handler_id = wocky_c2s_porter_register_handler_from_server ( WOCKY_C2S_PORTER (priv->porter), WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, jingle_info_cb, self, '(', "query", ':', WOCKY_XMPP_NS_GOOGLE_JINGLE_INFO, ')', NULL); } static void discover_stun_servers_cb (GObject *resolver, GAsyncResult *result, gpointer user_data) { WockyJingleInfo *self = WOCKY_JINGLE_INFO (user_data); WockyJingleInfoPrivate *priv = self->priv; GError *error = NULL; GList *targets; targets = g_resolver_lookup_service_finish (G_RESOLVER (resolver), result, &error); if (error != NULL) { DEBUG ("Failed to discover STUN servers on %s: %s", priv->jid_domain, error->message); g_clear_error (&error); } else { DEBUG ("Discovered %d STUN servers on %s", g_list_length (targets), priv->jid_domain); /* TODO: use more than just the first. */ if (targets != NULL) { GSrvTarget *target = targets->data; const gchar *hostname = g_srv_target_get_hostname (target); guint16 port = g_srv_target_get_port (target); DEBUG ("Found STUN server: %s:%d", hostname, port); wocky_jingle_info_take_stun_server (self, g_strdup (hostname), port, FALSE); } g_resolver_free_targets (targets); } g_object_unref (resolver); g_object_unref (self); } static void wocky_jingle_info_lookup_srv ( WockyJingleInfo *self) { WockyJingleInfoPrivate *priv = self->priv; GResolver *resolver; g_assert (priv->jid_domain != NULL); DEBUG ("Discovering STUN servers on %s", priv->jid_domain); resolver = g_resolver_get_default (); g_resolver_lookup_service_async (resolver, "stun", "udp", priv->jid_domain, NULL, discover_stun_servers_cb, g_object_ref (self)); } void wocky_jingle_info_send_request ( WockyJingleInfo *self, gboolean google_jingleinfo_supported) { /* FIXME: we probably don't want to send either query if the user specified a * stun server (that is, get_stun_from_jingle is FALSE). */ if (google_jingleinfo_supported) wocky_jingle_info_send_google_request (self); else wocky_jingle_info_lookup_srv (self); } /* * wocky_jingle_info_get_stun_servers: * * Grabs the currently known and resolved stun servers. * * Returns: (transfer container): a list of WockyJingleInfo structs */ GList * wocky_jingle_info_get_stun_servers ( WockyJingleInfo *self) { WockyJingleInfoPrivate *priv = self->priv; GQueue stun_servers = G_QUEUE_INIT; if (priv->stun_server != NULL) g_queue_push_head (&stun_servers, priv->stun_server); /* Only add the fallback server as a last resort. */ if (stun_servers.length == 0 && priv->fallback_stun_server != NULL) g_queue_push_tail (&stun_servers, priv->fallback_stun_server); return stun_servers.head; } const gchar * wocky_jingle_info_get_google_relay_token ( WockyJingleInfo *self) { return self->priv->relay_token; } WockyJingleRelay * wocky_jingle_relay_new ( WockyJingleRelayType type, const gchar *ip, guint port, const gchar *username, const gchar *password, guint component) { WockyJingleRelay ret = { type, g_strdup (ip), port, g_strdup (username), g_strdup (password), component }; return g_slice_dup (WockyJingleRelay, &ret); } void wocky_jingle_relay_free (WockyJingleRelay *relay) { g_free (relay->ip); g_free (relay->username); g_free (relay->password); g_slice_free (WockyJingleRelay, relay); } void wocky_jingle_info_create_google_relay_session ( WockyJingleInfo *self, guint components, WockyJingleInfoRelaySessionCb callback, gpointer user_data) { WockyJingleInfoPrivate *priv = self->priv; g_return_if_fail (callback != NULL); if (priv->google_resolver == NULL) { priv->google_resolver = wocky_google_relay_resolver_new (); } wocky_google_relay_resolver_resolve (priv->google_resolver, components, priv->relay_server, priv->relay_http_port, priv->relay_token, callback, user_data); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-pubsub-helpers.h0000664000175000017500000000464112005516162026302 0ustar00cassidycassidy00000000000000/* * wocky-pubsub-internal.h — header for PubSub helper functions * Copyright © 2009–2012 Collabora Ltd. * Copyright © 2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef WOCKY_PUBSUB_HELPERS_H #define WOCKY_PUBSUB_HELPERS_H #include #include "wocky-stanza.h" WockyStanza * wocky_pubsub_make_event_stanza ( const gchar *node, const gchar *from, WockyNode **item_out); WockyStanza *wocky_pubsub_make_stanza ( const gchar *service, WockyStanzaSubType sub_type, const gchar *pubsub_ns, const gchar *action_name, WockyNode **pubsub_node, WockyNode **action_node); WockyStanza *wocky_pubsub_make_publish_stanza ( const gchar *service, const gchar *node, WockyNode **pubsub_out, WockyNode **publish_out, WockyNode **item_out); void wocky_send_ll_pep_event (WockySession *session, WockyStanza *stanza); gboolean wocky_pubsub_distill_iq_reply (GObject *source, GAsyncResult *res, const gchar *pubsub_ns, const gchar *child_name, WockyNodeTree **child_out, GError **error); gboolean wocky_pubsub_distill_ambivalent_iq_reply (GObject *source, GAsyncResult *res, const gchar *pubsub_ns, const gchar *child_name, WockyNodeTree **child_out, GError **error); gboolean wocky_pubsub_distill_void_iq_reply (GObject *source, GAsyncResult *res, GError **error); gboolean wocky_pubsub_distill_stanza (WockyStanza *result, const gchar *pubsub_ns, const gchar *child_name, gboolean body_optional, WockyNodeTree **child_out, GError **error); #endif /* WOCKY_PUBSUB_HELPERS_H */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky.c0000664000175000017500000000340312005516162023332 0ustar00cassidycassidy00000000000000/* * wocky.c - General functions * Copyright (C) 2009 Collabora Ltd. * @author Guillaume Desmottes * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "wocky.h" #include "wocky-node.h" #include "wocky-xmpp-error.h" /** * wocky_init: * * Initializes the Wocky library. * * This function should be called before calling any other Wocky functions. */ void wocky_init (void) { xmlInitParser (); wocky_node_init (); wocky_xmpp_error_init (); } /** * wocky_deinit: * * Clean up any resources created by Wocky in wocky_init(). * * It is normally not needed to call this function in a normal application * as the resources will automatically be freed when the program terminates. * This function is therefore mostly used by testsuites and other memory * profiling tools. * * After this call Wocky (including this method) should not be used anymore. */ void wocky_deinit (void) { xmlCleanupParser (); wocky_node_deinit (); wocky_xmpp_error_deinit (); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-openssl-dh4096.c0000664000175000017500000000613512005516162025734 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #ifndef HEADER_DH_H #include #endif DH *get_dh4096(void); DH *get_dh4096(void) { static unsigned char dh4096_p[]={ 0xFA,0x14,0x72,0x52,0xC1,0x4D,0xE1,0x5A,0x49,0xD4,0xEF,0x09, 0x2D,0xC0,0xA8,0xFD,0x55,0xAB,0xD7,0xD9,0x37,0x04,0x28,0x09, 0xE2,0xE9,0x3E,0x77,0xE2,0xA1,0x7A,0x18,0xDD,0x46,0xA3,0x43, 0x37,0x23,0x90,0x97,0xF3,0x0E,0xC9,0x03,0x50,0x7D,0x65,0xCF, 0x78,0x62,0xA6,0x3A,0x62,0x22,0x83,0xA1,0x2F,0xFE,0x79,0xBA, 0x35,0xFF,0x59,0xD8,0x1D,0x61,0xDD,0x1E,0x21,0x13,0x17,0xFE, 0xCD,0x38,0x87,0x9E,0xF5,0x4F,0x79,0x10,0x61,0x8D,0xD4,0x22, 0xF3,0x5A,0xED,0x5D,0xEA,0x21,0xE9,0x33,0x6B,0x48,0x12,0x0A, 0x20,0x77,0xD4,0x25,0x60,0x61,0xDE,0xF6,0xB4,0x4F,0x1C,0x63, 0x40,0x8B,0x3A,0x21,0x93,0x8B,0x79,0x53,0x51,0x2C,0xCA,0xB3, 0x7B,0x29,0x56,0xA8,0xC7,0xF8,0xF4,0x7B,0x08,0x5E,0xA6,0xDC, 0xA2,0x45,0x12,0x56,0xDD,0x41,0x92,0xF2,0xDD,0x5B,0x8F,0x23, 0xF0,0xF3,0xEF,0xE4,0x3B,0x0A,0x44,0xDD,0xED,0x96,0x84,0xF1, 0xA8,0x32,0x46,0xA3,0xDB,0x4A,0xBE,0x3D,0x45,0xBA,0x4E,0xF8, 0x03,0xE5,0xDD,0x6B,0x59,0x0D,0x84,0x1E,0xCA,0x16,0x5A,0x8C, 0xC8,0xDF,0x7C,0x54,0x44,0xC4,0x27,0xA7,0x3B,0x2A,0x97,0xCE, 0xA3,0x7D,0x26,0x9C,0xAD,0xF4,0xC2,0xAC,0x37,0x4B,0xC3,0xAD, 0x68,0x84,0x7F,0x99,0xA6,0x17,0xEF,0x6B,0x46,0x3A,0x7A,0x36, 0x7A,0x11,0x43,0x92,0xAD,0xE9,0x9C,0xFB,0x44,0x6C,0x3D,0x82, 0x49,0xCC,0x5C,0x6A,0x52,0x42,0xF8,0x42,0xFB,0x44,0xF9,0x39, 0x73,0xFB,0x60,0x79,0x3B,0xC2,0x9E,0x0B,0xDC,0xD4,0xA6,0x67, 0xF7,0x66,0x3F,0xFC,0x42,0x3B,0x1B,0xDB,0x4F,0x66,0xDC,0xA5, 0x8F,0x66,0xF9,0xEA,0xC1,0xED,0x31,0xFB,0x48,0xA1,0x82,0x7D, 0xF8,0xE0,0xCC,0xB1,0xC7,0x03,0xE4,0xF8,0xB3,0xFE,0xB7,0xA3, 0x13,0x73,0xA6,0x7B,0xC1,0x0E,0x39,0xC7,0x94,0x48,0x26,0x00, 0x85,0x79,0xFC,0x6F,0x7A,0xAF,0xC5,0x52,0x35,0x75,0xD7,0x75, 0xA4,0x40,0xFA,0x14,0x74,0x61,0x16,0xF2,0xEB,0x67,0x11,0x6F, 0x04,0x43,0x3D,0x11,0x14,0x4C,0xA7,0x94,0x2A,0x39,0xA1,0xC9, 0x90,0xCF,0x83,0xC6,0xFF,0x02,0x8F,0xA3,0x2A,0xAC,0x26,0xDF, 0x0B,0x8B,0xBE,0x64,0x4A,0xF1,0xA1,0xDC,0xEE,0xBA,0xC8,0x03, 0x82,0xF6,0x62,0x2C,0x5D,0xB6,0xBB,0x13,0x19,0x6E,0x86,0xC5, 0x5B,0x2B,0x5E,0x3A,0xF3,0xB3,0x28,0x6B,0x70,0x71,0x3A,0x8E, 0xFF,0x5C,0x15,0xE6,0x02,0xA4,0xCE,0xED,0x59,0x56,0xCC,0x15, 0x51,0x07,0x79,0x1A,0x0F,0x25,0x26,0x27,0x30,0xA9,0x15,0xB2, 0xC8,0xD4,0x5C,0xCC,0x30,0xE8,0x1B,0xD8,0xD5,0x0F,0x19,0xA8, 0x80,0xA4,0xC7,0x01,0xAA,0x8B,0xBA,0x53,0xBB,0x47,0xC2,0x1F, 0x6B,0x54,0xB0,0x17,0x60,0xED,0x79,0x21,0x95,0xB6,0x05,0x84, 0x37,0xC8,0x03,0xA4,0xDD,0xD1,0x06,0x69,0x8F,0x4C,0x39,0xE0, 0xC8,0x5D,0x83,0x1D,0xBE,0x6A,0x9A,0x99,0xF3,0x9F,0x0B,0x45, 0x29,0xD4,0xCB,0x29,0x66,0xEE,0x1E,0x7E,0x3D,0xD7,0x13,0x4E, 0xDB,0x90,0x90,0x58,0xCB,0x5E,0x9B,0xCD,0x2E,0x2B,0x0F,0xA9, 0x4E,0x78,0xAC,0x05,0x11,0x7F,0xE3,0x9E,0x27,0xD4,0x99,0xE1, 0xB9,0xBD,0x78,0xE1,0x84,0x41,0xA0,0xDF, }; static unsigned char dh4096_g[]={ 0x02, }; DH *dh; if ((dh=DH_new()) == NULL) return(NULL); dh->p=BN_bin2bn(dh4096_p,sizeof(dh4096_p),NULL); dh->g=BN_bin2bn(dh4096_g,sizeof(dh4096_g),NULL); if ((dh->p == NULL) || (dh->g == NULL)) { DH_free(dh); return(NULL); } return(dh); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-xmpp-reader.h0000664000175000017500000001013012212322440025546 0ustar00cassidycassidy00000000000000/* * wocky-xmpp-reader.h - Header for WockyXmppReader * Copyright (C) 2006,2009 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_XMPP_READER_H__ #define __WOCKY_XMPP_READER_H__ #include #include "wocky-enumtypes.h" #include "wocky-stanza.h" G_BEGIN_DECLS typedef struct _WockyXmppReader WockyXmppReader; /** * WockyXmppReaderClass: * * The class of a #WockyXmppReader. */ typedef struct _WockyXmppReaderClass WockyXmppReaderClass; typedef struct _WockyXmppReaderPrivate WockyXmppReaderPrivate; struct _WockyXmppReaderClass { /**/ GObjectClass parent_class; /**/ const gchar *stream_element_name; const gchar *stream_element_ns; }; struct _WockyXmppReader { /**/ GObject parent; WockyXmppReaderPrivate *priv; }; /** * WockyXmppReaderState: * @WOCKY_XMPP_READER_STATE_INITIAL : initial state * @WOCKY_XMPP_READER_STATE_OPENED : stream is open * @WOCKY_XMPP_READER_STATE_CLOSED : stream has been closed * @WOCKY_XMPP_READER_STATE_ERROR : stream reader hit an error * * The possible states a reader can be in. */ typedef enum { WOCKY_XMPP_READER_STATE_INITIAL, WOCKY_XMPP_READER_STATE_OPENED, WOCKY_XMPP_READER_STATE_CLOSED, WOCKY_XMPP_READER_STATE_ERROR, } WockyXmppReaderState; /** * WockyXmppReaderError: * @WOCKY_XMPP_READER_ERROR_INVALID_STREAM_START : invalid start of xmpp stream * @WOCKY_XMPP_READER_ERROR_PARSE_ERROR : error in parsing the XML * * The different errors that can occur while reading a stream */ typedef enum { WOCKY_XMPP_READER_ERROR_INVALID_STREAM_START, WOCKY_XMPP_READER_ERROR_PARSE_ERROR, } WockyXmppReaderError; GQuark wocky_xmpp_reader_error_quark (void); /** * WOCKY_XMPP_READER_ERROR: * * Get access to the error quark of the reader. */ #define WOCKY_XMPP_READER_ERROR (wocky_xmpp_reader_error_quark ()) GType wocky_xmpp_reader_get_type (void); /* TYPE MACROS */ #define WOCKY_TYPE_XMPP_READER \ (wocky_xmpp_reader_get_type ()) #define WOCKY_XMPP_READER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_XMPP_READER, \ WockyXmppReader)) #define WOCKY_XMPP_READER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_XMPP_READER, \ WockyXmppReaderClass)) #define WOCKY_IS_XMPP_READER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_XMPP_READER)) #define WOCKY_IS_XMPP_READER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_XMPP_READER)) #define WOCKY_XMPP_READER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_XMPP_READER, \ WockyXmppReaderClass)) WockyXmppReader * wocky_xmpp_reader_new (void); WockyXmppReader * wocky_xmpp_reader_new_no_stream (void); WockyXmppReader * wocky_xmpp_reader_new_no_stream_ns ( const gchar *default_namespace); WockyXmppReaderState wocky_xmpp_reader_get_state (WockyXmppReader *reader); void wocky_xmpp_reader_push (WockyXmppReader *reader, const guint8 *data, gsize length); WockyStanza *wocky_xmpp_reader_pop_stanza (WockyXmppReader *reader); WockyStanza *wocky_xmpp_reader_peek_stanza (WockyXmppReader *reader); GError *wocky_xmpp_reader_get_error (WockyXmppReader *reader); void wocky_xmpp_reader_reset (WockyXmppReader *reader); G_END_DECLS #endif /* #ifndef __WOCKY_XMPP_READER_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jingle-transport-google.h0000664000175000017500000000525512212322440030112 0ustar00cassidycassidy00000000000000/* * wocky-jingle-transport-google.h - Header for WockyJingleTransportGoogle * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __JINGLE_TRANSPORT_GOOGLE_H__ #define __JINGLE_TRANSPORT_GOOGLE_H__ #include #include "wocky-jingle-types.h" G_BEGIN_DECLS typedef struct _WockyJingleTransportGoogleClass WockyJingleTransportGoogleClass; GType wocky_jingle_transport_google_get_type (void); /* TYPE MACROS */ #define WOCKY_TYPE_JINGLE_TRANSPORT_GOOGLE \ (wocky_jingle_transport_google_get_type ()) #define WOCKY_JINGLE_TRANSPORT_GOOGLE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_JINGLE_TRANSPORT_GOOGLE, \ WockyJingleTransportGoogle)) #define WOCKY_JINGLE_TRANSPORT_GOOGLE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_JINGLE_TRANSPORT_GOOGLE, \ WockyJingleTransportGoogleClass)) #define WOCKY_IS_JINGLE_TRANSPORT_GOOGLE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_JINGLE_TRANSPORT_GOOGLE)) #define WOCKY_IS_JINGLE_TRANSPORT_GOOGLE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_JINGLE_TRANSPORT_GOOGLE)) #define WOCKY_JINGLE_TRANSPORT_GOOGLE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_JINGLE_TRANSPORT_GOOGLE, \ WockyJingleTransportGoogleClass)) struct _WockyJingleTransportGoogleClass { GObjectClass parent_class; }; typedef struct _WockyJingleTransportGooglePrivate WockyJingleTransportGooglePrivate; struct _WockyJingleTransportGoogle { GObject parent; WockyJingleTransportGooglePrivate *priv; }; void jingle_transport_google_register (WockyJingleFactory *factory); gboolean jingle_transport_google_set_component_name ( WockyJingleTransportGoogle *transport, const gchar *name, guint component_id); G_END_DECLS #endif /* __JINGLE_TRANSPORT_GOOGLE_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jingle-factory.h0000664000175000017500000000606712212322440026255 0ustar00cassidycassidy00000000000000/* * wocky-jingle-factory.h - Header for WockyJingleFactory * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __JINGLE_FACTORY_H__ #define __JINGLE_FACTORY_H__ #include #include "wocky-jingle-info.h" #include "wocky-jingle-types.h" G_BEGIN_DECLS typedef struct _WockyJingleFactoryClass WockyJingleFactoryClass; GType wocky_jingle_factory_get_type (void); /* TYPE MACROS */ #define WOCKY_TYPE_JINGLE_FACTORY \ (wocky_jingle_factory_get_type ()) #define WOCKY_JINGLE_FACTORY(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_JINGLE_FACTORY, \ WockyJingleFactory)) #define WOCKY_JINGLE_FACTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_JINGLE_FACTORY, \ WockyJingleFactoryClass)) #define WOCKY_IS_JINGLE_FACTORY(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_JINGLE_FACTORY)) #define WOCKY_IS_JINGLE_FACTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_JINGLE_FACTORY)) #define WOCKY_JINGLE_FACTORY_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_JINGLE_FACTORY, \ WockyJingleFactoryClass)) struct _WockyJingleFactoryClass { GObjectClass parent_class; }; typedef struct _WockyJingleFactoryPrivate WockyJingleFactoryPrivate; struct _WockyJingleFactory { GObject parent; WockyJingleFactoryPrivate *priv; }; WockyJingleFactory *wocky_jingle_factory_new ( WockySession *session); void wocky_jingle_factory_stop (WockyJingleFactory *self); void wocky_jingle_factory_register_content_type (WockyJingleFactory *self, gchar *xmlns, GType content_type); GType wocky_jingle_factory_lookup_content_type (WockyJingleFactory *self, const gchar *xmlns); void wocky_jingle_factory_register_transport (WockyJingleFactory *self, gchar *xmlns, GType transport_type); GType wocky_jingle_factory_lookup_transport (WockyJingleFactory *self, const gchar *xmlns); WockyJingleSession *wocky_jingle_factory_create_session ( WockyJingleFactory *fac, const gchar *jid, WockyJingleDialect dialect, gboolean local_hold); WockyJingleInfo *wocky_jingle_factory_get_jingle_info ( WockyJingleFactory *fac); G_END_DECLS #endif /* __JINGLE_FACTORY_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-tls.h0000664000175000017500000001120412212322440024127 0ustar00cassidycassidy00000000000000/* * Copyright © 2008 Christian Kellner, Samuel Cormier-Iijima * Copyright © 2008-2009 Codethink Limited * Copyright © 2009 Collabora Limited * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2 of the licence or (at * your option) any later version. * * Authors: Ryan Lortie * Christian Kellner * Samuel Cormier-Iijima * Vivek Dasmohapatra * * Upstream: git://git.gnome.org/gnio * Branched at: 42b00d143fcf644880456d06d3a20b6e990a7fa3 * "toss out everything that moved to glib" * * This file follows the orignal coding style from upstream, not house * collabora style: It is a copy of unmerged gnio TLS support with the * 'g' prefixes changes to 'wocky' and server-side TLS support added. * */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef _wocky_tls_h_ #define _wocky_tls_h_ #include #include "wocky-enumtypes.h" #define WOCKY_TYPE_TLS_CONNECTION (wocky_tls_connection_get_type ()) #define WOCKY_TYPE_TLS_SESSION (wocky_tls_session_get_type ()) #define WOCKY_TLS_SESSION(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ WOCKY_TYPE_TLS_SESSION, WockyTLSSession)) #define WOCKY_TLS_CONNECTION(inst)(G_TYPE_CHECK_INSTANCE_CAST ((inst), \ WOCKY_TYPE_TLS_CONNECTION, \ WockyTLSConnection)) typedef struct _WockyTLSConnection WockyTLSConnection; typedef struct _WockyTLSSession WockyTLSSession; typedef enum { WOCKY_TLS_VERIFY_STRICT = 0, WOCKY_TLS_VERIFY_NORMAL, WOCKY_TLS_VERIFY_LENIENT, } WockyTLSVerificationLevel; GQuark wocky_tls_cert_error_quark (void); #define WOCKY_TLS_CERT_ERROR (wocky_tls_cert_error_quark ()) GQuark wocky_tls_error_quark (void); #define WOCKY_TLS_ERROR (wocky_tls_error_quark ()) typedef enum { WOCKY_TLS_CERT_OK = 0, WOCKY_TLS_CERT_INVALID, WOCKY_TLS_CERT_NAME_MISMATCH, WOCKY_TLS_CERT_REVOKED, WOCKY_TLS_CERT_SIGNER_UNKNOWN, WOCKY_TLS_CERT_SIGNER_UNAUTHORISED, WOCKY_TLS_CERT_INSECURE, WOCKY_TLS_CERT_NOT_ACTIVE, WOCKY_TLS_CERT_EXPIRED, WOCKY_TLS_CERT_NO_CERTIFICATE, WOCKY_TLS_CERT_MAYBE_DOS, WOCKY_TLS_CERT_INTERNAL_ERROR, WOCKY_TLS_CERT_UNKNOWN_ERROR, } WockyTLSCertStatus; typedef enum { WOCKY_TLS_CERT_TYPE_NONE = 0, WOCKY_TLS_CERT_TYPE_X509, WOCKY_TLS_CERT_TYPE_OPENPGP, } WockyTLSCertType; GType wocky_tls_connection_get_type (void); GType wocky_tls_session_get_type (void); int wocky_tls_session_verify_peer (WockyTLSSession *session, const gchar *peername, GStrv extra_identities, WockyTLSVerificationLevel level, WockyTLSCertStatus *status); GPtrArray *wocky_tls_session_get_peers_certificate (WockyTLSSession *session, WockyTLSCertType *type); WockyTLSConnection *wocky_tls_session_handshake (WockyTLSSession *session, GCancellable *cancellable, GError **error); void wocky_tls_session_handshake_async (WockyTLSSession *session, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); WockyTLSConnection * wocky_tls_session_handshake_finish (WockyTLSSession *session, GAsyncResult *result, GError **error); void wocky_tls_session_add_ca (WockyTLSSession *session, const gchar *path); void wocky_tls_session_add_crl (WockyTLSSession *session, const gchar *path); WockyTLSSession *wocky_tls_session_new (GIOStream *stream); WockyTLSSession *wocky_tls_session_server_new (GIOStream *stream, guint dhbits, const gchar* key, const gchar* cert); #endif /* _wocky_tls_h_ */ /* this file is "borrowed" from an unmerged gnio feature: */ /* Local Variables: */ /* c-file-style: "gnu" */ /* End: */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-http-proxy.h0000664000175000017500000000353011720661341025477 0ustar00cassidycassidy00000000000000 /* wocky-http-proxy.h: Header for WockyHttpProxy * * Copyright (C) 2010 Collabora, Ltd. * @author Nicolas Dufresne * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_COMPILATION) # error "This is an internal header." #endif #ifndef _WOCKY_HTTP_PROXY_H_ #define _WOCKY_HTTP_PROXY_H_ #include G_BEGIN_DECLS #define WOCKY_TYPE_HTTP_PROXY (_wocky_http_proxy_get_type ()) #define WOCKY_HTTP_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), WOCKY_TYPE_HTTP_PROXY, WockyHttpProxy)) #define WOCKY_HTTP_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), WOCKY_TYPE_HTTP_PROXY, WockyHttpProxyClass)) #define WOCKY_IS_HTTP_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), WOCKY_TYPE_HTTP_PROXY)) #define WOCKY_IS_HTTP_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), WOCKY_TYPE_HTTP_PROXY)) #define WOCKY_HTTP_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), WOCKY_TYPE_HTTP_PROXY, WockyHttpProxyClass)) typedef struct _WockyHttpProxy WockyHttpProxy; typedef struct _WockyHttpProxyClass WockyHttpProxyClass; GType _wocky_http_proxy_get_type (void); G_END_DECLS #endif /* _WOCKY_HTTP_PROXY_H_ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jabber-auth.c0000664000175000017500000004320412212322440025511 0ustar00cassidycassidy00000000000000/* * wocky-jabber-auth.c - Source for WockyJabberAuth * Copyright (C) 2009-2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "wocky-jabber-auth.h" #include "wocky-signals-marshal.h" #include "wocky-namespaces.h" #include "wocky-utils.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_AUTH #include "wocky-debug-internal.h" G_DEFINE_TYPE(WockyJabberAuth, wocky_jabber_auth, G_TYPE_OBJECT) enum { PROP_SESSION_ID = 1, PROP_USERNAME, PROP_RESOURCE, PROP_PASSWORD, PROP_CONNECTION, PROP_AUTH_REGISTRY, }; /* private structure */ struct _WockyJabberAuthPrivate { gboolean dispose_has_run; WockyXmppConnection *connection; gchar *username; gchar *resource; gchar *password; gchar *session_id; GCancellable *cancel; GSimpleAsyncResult *result; WockyAuthRegistry *auth_registry; gboolean allow_plain; gboolean is_secure; }; static void wocky_jabber_auth_init (WockyJabberAuth *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_JABBER_AUTH, WockyJabberAuthPrivate); } static void wocky_jabber_auth_dispose (GObject *object); static void wocky_jabber_auth_finalize (GObject *object); static void wocky_jabber_auth_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyJabberAuth *self = WOCKY_JABBER_AUTH (object); WockyJabberAuthPrivate *priv = self->priv; switch (property_id) { case PROP_SESSION_ID: g_free (priv->session_id); priv->session_id = g_value_dup_string (value); break; case PROP_USERNAME: g_free (priv->username); priv->username = g_value_dup_string (value); break; case PROP_RESOURCE: g_free (priv->resource); priv->resource = g_value_dup_string (value); break; case PROP_PASSWORD: g_free (priv->password); priv->password = g_value_dup_string (value); break; case PROP_CONNECTION: priv->connection = g_value_dup_object (value); break; case PROP_AUTH_REGISTRY: if (g_value_get_object (value) == NULL) priv->auth_registry = wocky_auth_registry_new (); else priv->auth_registry = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_jabber_auth_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyJabberAuth *self = WOCKY_JABBER_AUTH (object); WockyJabberAuthPrivate *priv = self->priv; switch (property_id) { case PROP_SESSION_ID: g_value_set_string (value, priv->session_id); break; case PROP_CONNECTION: g_value_set_object (value, priv->connection); break; case PROP_AUTH_REGISTRY: g_value_set_object (value, priv->auth_registry); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_jabber_auth_class_init (WockyJabberAuthClass *wocky_jabber_auth_class) { GObjectClass *object_class = G_OBJECT_CLASS (wocky_jabber_auth_class); GParamSpec *spec; g_type_class_add_private (wocky_jabber_auth_class, sizeof (WockyJabberAuthPrivate)); object_class->set_property = wocky_jabber_auth_set_property; object_class->get_property = wocky_jabber_auth_get_property; spec = g_param_spec_string ("session-id", "session-id", "The XMPP session ID", NULL, G_PARAM_READWRITE|G_PARAM_CONSTRUCT); g_object_class_install_property (object_class, PROP_SESSION_ID, spec); spec = g_param_spec_string ("username", "username", "The username to authenticate with", NULL, G_PARAM_WRITABLE|G_PARAM_CONSTRUCT); g_object_class_install_property (object_class, PROP_USERNAME, spec); spec = g_param_spec_string ("resource", "resource", "The XMPP resource to bind to", NULL, G_PARAM_WRITABLE|G_PARAM_CONSTRUCT); g_object_class_install_property (object_class, PROP_RESOURCE, spec); spec = g_param_spec_string ("password", "password", "The password to authenticate with", NULL, G_PARAM_WRITABLE|G_PARAM_CONSTRUCT); g_object_class_install_property (object_class, PROP_PASSWORD, spec); spec = g_param_spec_object ("connection", "connection", "The Xmpp connection to user", WOCKY_TYPE_XMPP_CONNECTION, G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_CONNECTION, spec); spec = g_param_spec_object ("auth-registry", "Authentication Registry", "Authentication Registry", WOCKY_TYPE_AUTH_REGISTRY, G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_AUTH_REGISTRY, spec); object_class->dispose = wocky_jabber_auth_dispose; object_class->finalize = wocky_jabber_auth_finalize; } void wocky_jabber_auth_dispose (GObject *object) { WockyJabberAuth *self = WOCKY_JABBER_AUTH (object); WockyJabberAuthPrivate *priv = self->priv; if (priv->connection != NULL) g_object_unref (priv->connection); if (priv->auth_registry != NULL) g_object_unref (priv->auth_registry); if (G_OBJECT_CLASS (wocky_jabber_auth_parent_class)->dispose) G_OBJECT_CLASS (wocky_jabber_auth_parent_class)->dispose (object); } void wocky_jabber_auth_finalize (GObject *object) { WockyJabberAuth *self = WOCKY_JABBER_AUTH (object); WockyJabberAuthPrivate *priv = self->priv; /* free any data held directly by the object here */ g_free (priv->session_id); g_free (priv->username); g_free (priv->resource); g_free (priv->password); G_OBJECT_CLASS (wocky_jabber_auth_parent_class)->finalize (object); } static void auth_reset (WockyJabberAuth *self) { WockyJabberAuthPrivate *priv = self->priv; g_free (priv->session_id); priv->session_id = NULL; if (priv->connection != NULL) { g_object_unref (priv->connection); priv->connection = NULL; } if (priv->cancel != NULL) { g_object_unref (priv->cancel); priv->cancel = NULL; } } static void auth_succeeded (WockyJabberAuth *self) { WockyJabberAuthPrivate *priv = self->priv; GSimpleAsyncResult *r; DEBUG ("Authentication succeeded"); auth_reset (self); r = priv->result; priv->result = NULL; g_simple_async_result_complete (r); g_object_unref (r); } static void auth_failed (WockyJabberAuth *self, gint code, const gchar *format, ...) { gchar *message; va_list args; GSimpleAsyncResult *r; GError *error = NULL; WockyJabberAuthPrivate *priv = self->priv; auth_reset (self); va_start (args, format); message = g_strdup_vprintf (format, args); va_end (args); DEBUG ("Authentication failed!: %s", message); r = priv->result; priv->result = NULL; error = g_error_new_literal (WOCKY_AUTH_ERROR, code, message); g_simple_async_result_set_from_error (r, error); wocky_auth_registry_failure (priv->auth_registry, error); g_simple_async_result_complete (r); g_object_unref (r); g_error_free (error); g_free (message); } static gboolean stream_error (WockyJabberAuth *self, WockyStanza *stanza) { GError *error = NULL; if (stanza == NULL) { auth_failed (self, WOCKY_AUTH_ERROR_CONNRESET, "Disconnected"); return TRUE; } if (wocky_stanza_extract_stream_error (stanza, &error)) { auth_failed (self, WOCKY_AUTH_ERROR_STREAM, "%s: %s", wocky_enum_to_nick (WOCKY_TYPE_XMPP_STREAM_ERROR, error->code), error->message); g_error_free (error); return TRUE; } return FALSE; } WockyJabberAuth * wocky_jabber_auth_new (const gchar *session_id, const gchar *username, const gchar *resource, const gchar *password, WockyXmppConnection *connection, WockyAuthRegistry *auth_registry) { return g_object_new (WOCKY_TYPE_JABBER_AUTH, "session-id", session_id, "username", username, "resource", resource, "password", password, "connection", connection, "auth-registry", auth_registry, NULL); } gboolean wocky_jabber_auth_authenticate_finish (WockyJabberAuth *self, GAsyncResult *result, GError **error) { wocky_implement_finish_void (self, wocky_jabber_auth_authenticate_async); } static void wocky_jabber_auth_success_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { WockyJabberAuth *self = (WockyJabberAuth *) user_data; WockyJabberAuthPrivate *priv = self->priv; GError *error = NULL; if (!wocky_auth_registry_success_finish (priv->auth_registry, res, &error)) { auth_failed (self, error->code, error->message); g_error_free (error); } else { auth_succeeded (self); } } static void jabber_auth_reply (GObject *source, GAsyncResult *res, gpointer user_data) { WockyJabberAuth *self = (WockyJabberAuth *) user_data; WockyJabberAuthPrivate *priv = self->priv; WockyXmppConnection *conn = priv->connection; GError *error = NULL; WockyStanza *reply = NULL; WockyStanzaType type = WOCKY_STANZA_TYPE_NONE; WockyStanzaSubType sub = WOCKY_STANZA_SUB_TYPE_NONE; DEBUG (""); reply = wocky_xmpp_connection_recv_stanza_finish (conn, res, &error); if (stream_error (self, reply)) return; wocky_stanza_get_type_info (reply, &type, &sub); if (type != WOCKY_STANZA_TYPE_IQ) { auth_failed (self, WOCKY_AUTH_ERROR_INVALID_REPLY, "Jabber Auth Reply: Response Invalid"); goto out; } switch (sub) { WockyAuthError code; case WOCKY_STANZA_SUB_TYPE_ERROR: wocky_stanza_extract_errors (reply, NULL, &error, NULL, NULL); switch (error->code) { case WOCKY_XMPP_ERROR_NOT_AUTHORIZED: code = WOCKY_AUTH_ERROR_NOT_AUTHORIZED; break; case WOCKY_XMPP_ERROR_CONFLICT: code = WOCKY_AUTH_ERROR_RESOURCE_CONFLICT; break; case WOCKY_XMPP_ERROR_NOT_ACCEPTABLE: code = WOCKY_AUTH_ERROR_NO_CREDENTIALS; break; default: code = WOCKY_AUTH_ERROR_FAILURE; } auth_failed (self, code, "Authentication failed: %s", error->message); g_clear_error (&error); break; case WOCKY_STANZA_SUB_TYPE_RESULT: wocky_auth_registry_success_async (priv->auth_registry, wocky_jabber_auth_success_cb, self); break; default: auth_failed (self, WOCKY_AUTH_ERROR_INVALID_REPLY, "Bizarre response to Jabber Auth request"); break; } out: g_object_unref (reply); } static void jabber_auth_query (GObject *source, GAsyncResult *res, gpointer user_data) { WockyJabberAuth *self = (WockyJabberAuth *) user_data; WockyJabberAuthPrivate *priv = self->priv; WockyXmppConnection *conn = priv->connection; GError *error = NULL; DEBUG (""); if (!wocky_xmpp_connection_send_stanza_finish (conn, res, &error)) { auth_failed (self, error->code, "Jabber Auth IQ Set: %s", error->message); g_error_free (error); return; } wocky_xmpp_connection_recv_stanza_async (conn, priv->cancel, jabber_auth_reply, user_data); } static void wocky_jabber_auth_start_cb (GObject *source, GAsyncResult *res, gpointer user_data) { WockyJabberAuth *self = (WockyJabberAuth *) user_data; WockyJabberAuthPrivate *priv = self->priv; WockyXmppConnection *conn = priv->connection; gchar *iqid; WockyStanza *iq; const gchar *auth_field; GError *error = NULL; WockyAuthRegistryStartData *start_data = NULL; if (!wocky_auth_registry_start_auth_finish (priv->auth_registry, res, &start_data, &error)) { auth_failed (self, error->code, error->message); g_error_free (error); return; } g_assert (start_data->mechanism != NULL); g_assert (start_data->initial_response != NULL); if (g_strcmp0 (start_data->mechanism, "X-WOCKY-JABBER-PASSWORD") == 0) auth_field = "password"; else auth_field = "digest"; iqid = wocky_xmpp_connection_new_id (conn); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, NULL, '@', "id", iqid, '(', "query", ':', WOCKY_JABBER_NS_AUTH, '(', "username", '$', priv->username, ')', '(', auth_field, '$', start_data->initial_response->str, ')', '(', "resource", '$', priv->resource, ')', ')', NULL); wocky_xmpp_connection_send_stanza_async (conn, iq, priv->cancel, jabber_auth_query, self); g_free (iqid); g_object_unref (iq); wocky_auth_registry_start_data_free (start_data); } static void jabber_auth_fields (GObject *source, GAsyncResult *res, gpointer user_data) { WockyJabberAuth *self = (WockyJabberAuth *) user_data; WockyJabberAuthPrivate *priv = self->priv; WockyXmppConnection *conn = priv->connection; GError *error = NULL; WockyStanza *fields = NULL; WockyStanzaType type = WOCKY_STANZA_TYPE_NONE; WockyStanzaSubType sub = WOCKY_STANZA_SUB_TYPE_NONE; fields = wocky_xmpp_connection_recv_stanza_finish (conn, res, &error); if (stream_error (self, fields)) return; wocky_stanza_get_type_info (fields, &type, &sub); if (type != WOCKY_STANZA_TYPE_IQ) { auth_failed (self, WOCKY_AUTH_ERROR_FAILURE, "Jabber Auth Init: Response Invalid"); goto out; } switch (sub) { WockyNode *node = NULL; WockyAuthError code; case WOCKY_STANZA_SUB_TYPE_ERROR: wocky_stanza_extract_errors (fields, NULL, &error, NULL, NULL); if (error->code == WOCKY_XMPP_ERROR_SERVICE_UNAVAILABLE) code = WOCKY_AUTH_ERROR_NOT_SUPPORTED; else code = WOCKY_AUTH_ERROR_FAILURE; auth_failed (self, code, "Jabber Auth: %s %s", wocky_xmpp_error_string (error->code), error->message); g_clear_error (&error); break; case WOCKY_STANZA_SUB_TYPE_RESULT: node = wocky_stanza_get_top_node (fields); node = wocky_node_get_child_ns (node, "query", WOCKY_JABBER_NS_AUTH); if ((node != NULL) && (wocky_node_get_child (node, "resource") != NULL) && (wocky_node_get_child (node, "username") != NULL)) { GSList *mechanisms = NULL; if (wocky_node_get_child (node, "password") != NULL) mechanisms = g_slist_append (mechanisms, WOCKY_AUTH_MECH_JABBER_PASSWORD); if (wocky_node_get_child (node, "digest") != NULL) mechanisms = g_slist_append (mechanisms, WOCKY_AUTH_MECH_JABBER_DIGEST); wocky_auth_registry_start_auth_async (priv->auth_registry, mechanisms, priv->allow_plain, priv->is_secure, priv->username, priv->password, NULL, priv->session_id, wocky_jabber_auth_start_cb, self); g_slist_free (mechanisms); } break; default: auth_failed (self, WOCKY_AUTH_ERROR_FAILURE, "Bizarre response to Jabber Auth request"); break; } out: g_object_unref (fields); } static void jabber_auth_init_sent (GObject *source, GAsyncResult *res, gpointer user_data) { WockyJabberAuth *self = (WockyJabberAuth *) user_data; WockyJabberAuthPrivate *priv = self->priv; WockyXmppConnection *conn = priv->connection; GError *error = NULL; DEBUG (""); if (!wocky_xmpp_connection_send_stanza_finish (conn, res, &error)) { auth_failed (self, error->code, error->message); g_error_free (error); return; } wocky_xmpp_connection_recv_stanza_async (conn, priv->cancel, jabber_auth_fields, user_data); } /* Initiate jabber auth. features should contain the stream features stanza as * receiver from the session_id */ void wocky_jabber_auth_authenticate_async (WockyJabberAuth *self, gboolean allow_plain, gboolean is_secure, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyJabberAuthPrivate *priv = self->priv; WockyXmppConnection *conn = priv->connection; gchar *id = wocky_xmpp_connection_new_id (conn); WockyStanza *iq = NULL; DEBUG (""); priv->allow_plain = allow_plain; priv->is_secure = is_secure; priv->result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_jabber_auth_authenticate_async); if (cancellable != NULL) priv->cancel = g_object_ref (cancellable); iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, NULL, '@', "id", id, '(', "query", ':', WOCKY_JABBER_NS_AUTH, /* This is a workaround for * : while * doesn't require * us to include a username, it seems to be required by jabberd 1.4. */ '(', "username", '$', priv->username, ')', ')', NULL); wocky_xmpp_connection_send_stanza_async (conn, iq, priv->cancel, jabber_auth_init_sent, self); g_free (id); g_object_unref (iq); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-ll-connector.h0000664000175000017500000000570411720661341025745 0ustar00cassidycassidy00000000000000/* * wocky-ll-connector.h - Header for WockyLLConnector * Copyright (C) 2011 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_LL_CONNECTOR_H__ #define __WOCKY_LL_CONNECTOR_H__ #include #include #include "wocky-xmpp-connection.h" G_BEGIN_DECLS typedef struct _WockyLLConnector WockyLLConnector; typedef struct _WockyLLConnectorClass WockyLLConnectorClass; typedef struct _WockyLLConnectorPrivate WockyLLConnectorPrivate; typedef enum { WOCKY_LL_CONNECTOR_ERROR_FAILED_TO_SEND_STANZA, WOCKY_LL_CONNECTOR_ERROR_FAILED_TO_RECEIVE_STANZA, } WockyLLConnectorError; GQuark wocky_ll_connector_error_quark (void); #define WOCKY_LL_CONNECTOR_ERROR (wocky_ll_connector_error_quark ()) struct _WockyLLConnectorClass { GObjectClass parent_class; }; struct _WockyLLConnector { GObject parent; WockyLLConnectorPrivate *priv; }; GType wocky_ll_connector_get_type (void); #define WOCKY_TYPE_LL_CONNECTOR \ (wocky_ll_connector_get_type ()) #define WOCKY_LL_CONNECTOR(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_LL_CONNECTOR, \ WockyLLConnector)) #define WOCKY_LL_CONNECTOR_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_LL_CONNECTOR, \ WockyLLConnectorClass)) #define WOCKY_IS_LL_CONNECTOR(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_LL_CONNECTOR)) #define WOCKY_IS_LL_CONNECTOR_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_LL_CONNECTOR)) #define WOCKY_LL_CONNECTOR_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_LL_CONNECTOR, \ WockyLLConnectorClass)) void wocky_ll_connector_incoming_async ( GIOStream *stream, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); void wocky_ll_connector_outgoing_async ( WockyXmppConnection *connection, const gchar *local_jid, const gchar *remote_jid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); WockyXmppConnection * wocky_ll_connector_finish ( WockyLLConnector *connector, GAsyncResult *result, gchar **from, GError **error); G_END_DECLS #endif /* #ifndef __WOCKY_LL_CONNECTOR_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-connector.h0000664000175000017500000001532212212322440025324 0ustar00cassidycassidy00000000000000/* * wocky-connector.h - Header for WockyConnector * Copyright (C) 2009 Collabora Ltd. * @author Vivek Dasmohapatra * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_CONNECTOR_H__ #define __WOCKY_CONNECTOR_H__ #include #include "wocky-enumtypes.h" #include "wocky-sasl-auth.h" #include "wocky-xmpp-connection.h" #include "wocky-stanza.h" #include "wocky-tls.h" #include "wocky-tls-handler.h" G_BEGIN_DECLS typedef struct _WockyConnector WockyConnector; /** * WockyConnectorClass: * * The class of a #WockyConnector. */ typedef struct _WockyConnectorClass WockyConnectorClass; typedef struct _WockyConnectorPrivate WockyConnectorPrivate; /** * WockyConnectorError: * @WOCKY_CONNECTOR_ERROR_UNKNOWN: Unexpected error condition * @WOCKY_CONNECTOR_ERROR_IN_PROGRESS: Connection already underway * @WOCKY_CONNECTOR_ERROR_BAD_JID: JID is invalid * @WOCKY_CONNECTOR_ERROR_NON_XMPP_V1_SERVER: XMPP version < 1 * @WOCKY_CONNECTOR_ERROR_BAD_FEATURES: Feature stanza invalid * @WOCKY_CONNECTOR_ERROR_TLS_UNAVAILABLE: TLS unavailable * @WOCKY_CONNECTOR_ERROR_TLS_REFUSED: TLS refused by server * @WOCKY_CONNECTOR_ERROR_TLS_SESSION_FAILED: TLS handshake failed * @WOCKY_CONNECTOR_ERROR_BIND_UNAVAILABLE: Bind not available * @WOCKY_CONNECTOR_ERROR_BIND_FAILED: Bind failed * @WOCKY_CONNECTOR_ERROR_BIND_INVALID: Bind args invalid * @WOCKY_CONNECTOR_ERROR_BIND_DENIED: Bind not allowed * @WOCKY_CONNECTOR_ERROR_BIND_CONFLICT: Bind resource in use * @WOCKY_CONNECTOR_ERROR_BIND_REJECTED: Bind error (generic) * @WOCKY_CONNECTOR_ERROR_SESSION_FAILED: Session failed * @WOCKY_CONNECTOR_ERROR_SESSION_DENIED: Session refused by server * @WOCKY_CONNECTOR_ERROR_SESSION_CONFLICT: Session not allowed * @WOCKY_CONNECTOR_ERROR_SESSION_REJECTED: Session error * @WOCKY_CONNECTOR_ERROR_INSECURE: Insufficent security for requested * operation * @WOCKY_CONNECTOR_ERROR_REGISTRATION_FAILED: Account registration * error * @WOCKY_CONNECTOR_ERROR_REGISTRATION_UNAVAILABLE: Account * registration not available * @WOCKY_CONNECTOR_ERROR_REGISTRATION_UNSUPPORTED: Account * registration not implemented * @WOCKY_CONNECTOR_ERROR_REGISTRATION_EMPTY: Account registration * makes no sense * @WOCKY_CONNECTOR_ERROR_REGISTRATION_CONFLICT: Account already * registered * @WOCKY_CONNECTOR_ERROR_REGISTRATION_REJECTED: Account registration * rejected * @WOCKY_CONNECTOR_ERROR_UNREGISTER_FAILED: Account cancellation * failed * @WOCKY_CONNECTOR_ERROR_UNREGISTER_DENIED: Account cancellation * refused * * The #WockyConnector specific errors that can occur while * connecting. */ typedef enum { WOCKY_CONNECTOR_ERROR_UNKNOWN, WOCKY_CONNECTOR_ERROR_IN_PROGRESS, WOCKY_CONNECTOR_ERROR_BAD_JID, WOCKY_CONNECTOR_ERROR_NON_XMPP_V1_SERVER, WOCKY_CONNECTOR_ERROR_BAD_FEATURES, WOCKY_CONNECTOR_ERROR_TLS_UNAVAILABLE, WOCKY_CONNECTOR_ERROR_TLS_REFUSED, WOCKY_CONNECTOR_ERROR_TLS_SESSION_FAILED, WOCKY_CONNECTOR_ERROR_BIND_UNAVAILABLE, WOCKY_CONNECTOR_ERROR_BIND_FAILED, WOCKY_CONNECTOR_ERROR_BIND_INVALID, WOCKY_CONNECTOR_ERROR_BIND_DENIED, WOCKY_CONNECTOR_ERROR_BIND_CONFLICT, WOCKY_CONNECTOR_ERROR_BIND_REJECTED, WOCKY_CONNECTOR_ERROR_SESSION_FAILED, WOCKY_CONNECTOR_ERROR_SESSION_DENIED, WOCKY_CONNECTOR_ERROR_SESSION_CONFLICT, WOCKY_CONNECTOR_ERROR_SESSION_REJECTED, WOCKY_CONNECTOR_ERROR_INSECURE, WOCKY_CONNECTOR_ERROR_REGISTRATION_FAILED, WOCKY_CONNECTOR_ERROR_REGISTRATION_UNAVAILABLE, WOCKY_CONNECTOR_ERROR_REGISTRATION_UNSUPPORTED, WOCKY_CONNECTOR_ERROR_REGISTRATION_EMPTY, WOCKY_CONNECTOR_ERROR_REGISTRATION_CONFLICT, WOCKY_CONNECTOR_ERROR_REGISTRATION_REJECTED, WOCKY_CONNECTOR_ERROR_UNREGISTER_FAILED, WOCKY_CONNECTOR_ERROR_UNREGISTER_DENIED, } WockyConnectorError; GQuark wocky_connector_error_quark (void); /** * WOCKY_CONNECTOR_ERROR: * * Get access to the error quark of the connector. */ #define WOCKY_CONNECTOR_ERROR (wocky_connector_error_quark ()) struct _WockyConnectorClass { /**/ GObjectClass parent_class; }; struct _WockyConnector { /**/ GObject parent; WockyConnectorPrivate *priv; }; GType wocky_connector_get_type (void); /* TYPE MACROS */ #define WOCKY_TYPE_CONNECTOR (wocky_connector_get_type ()) #define WOCKY_CONNECTOR(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), WOCKY_TYPE_CONNECTOR, WockyConnector)) #define WOCKY_CONNECTOR_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), WOCKY_TYPE_CONNECTOR, WockyXmppConnector)) #define WOCKY_IS_CONNECTOR(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WOCKY_TYPE_CONNECTOR)) #define WOCKY_IS_CONNECTOR_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), WOCKY_TYPE_CONNECTOR)) #define WOCKY_CONNECTOR_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_CONNECTOR, WockyConnectorClass)) WockyXmppConnection *wocky_connector_connect_finish (WockyConnector *self, GAsyncResult *res, gchar **jid, gchar **sid, GError **error); WockyXmppConnection *wocky_connector_register_finish (WockyConnector *self, GAsyncResult *res, gchar **jid, gchar **sid, GError **error); void wocky_connector_connect_async (WockyConnector *self, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer user_data); WockyConnector *wocky_connector_new (const gchar *jid, const gchar *pass, const gchar *resource, WockyAuthRegistry *auth_registry, WockyTLSHandler *tls_handler); void wocky_connector_register_async (WockyConnector *self, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer user_data); void wocky_connector_unregister_async (WockyConnector *self, GCancellable *cancellable, GAsyncReadyCallback cb, gpointer user_data); gboolean wocky_connector_unregister_finish (WockyConnector *self, GAsyncResult *res, GError **error); void wocky_connector_set_auth_registry (WockyConnector *self, WockyAuthRegistry *registry); G_END_DECLS #endif /* #ifndef __WOCKY_CONNECTOR_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-muc.h0000664000175000017500000002347412212322440024125 0ustar00cassidycassidy00000000000000/* * wocky-xmpp-connection.h - Header for WockyMuc * Copyright © 2009 Collabora Ltd. * @author Vivek Dasmohapatra * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_MUC_H__ #define __WOCKY_MUC_H__ #include #include "wocky-enumtypes.h" #include "wocky-namespaces.h" #include "wocky-porter.h" G_BEGIN_DECLS typedef struct _WockyMuc WockyMuc; /** * WockyMucClass: * * The class of a #WockyMuc. */ typedef struct _WockyMucClass WockyMucClass; typedef struct _WockyMucPrivate WockyMucPrivate; /** * WockyMucStatusCode: * @WOCKY_MUC_CODE_UNKNOWN: Unknown code * @WOCKY_MUC_CODE_ONYMOUS: Room entered is not anonymous * @WOCKY_MUC_CODE_AF_CHANGE_OOB: Affiliation changed when not present * @WOCKY_MUC_CODE_CFG_SHOW_UNAVAILABLE: Unavailable members visible * @WOCKY_MUC_CODE_CFG_HIDE_UNAVAILABLE: Unavailable members invisible * @WOCKY_MUC_CODE_CFG_NONPRIVACY: Non-privacy config change * @WOCKY_MUC_CODE_OWN_PRESENCE: User's own presence * @WOCKY_MUC_CODE_CFG_LOGGING_ENABLED: Logging enabled * @WOCKY_MUC_CODE_CFG_LOGGING_DISABLED: Logging disabled * @WOCKY_MUC_CODE_CFG_ONYMOUS: Room is now non-anonymous * @WOCKY_MUC_CODE_CFG_SEMIONYMOUS: Room is now semi-anonymous * @WOCKY_MUC_CODE_CFG_ANONYMOUS: Room is now fully-anonymous * @WOCKY_MUC_CODE_NEW_ROOM: Room created (eg by joining) * @WOCKY_MUC_CODE_NICK_CHANGE_FORCED: Service enforced nick change * @WOCKY_MUC_CODE_BANNED: User has been banned * @WOCKY_MUC_CODE_NICK_CHANGE_USER: User's nick changed * @WOCKY_MUC_CODE_KICKED: Kicked from the room * @WOCKY_MUC_CODE_KICKED_AFFILIATION: Kicked (affiliation change) * @WOCKY_MUC_CODE_KICKED_ROOM_PRIVATISED: Kicked (room is now * members-only) * @WOCKY_MUC_CODE_KICKED_SHUTDOWN: Kicked (shutdown) * * MUC status codes, as defined by XEP-0045 * §15.6. */ typedef enum { WOCKY_MUC_CODE_UNKNOWN = 0, WOCKY_MUC_CODE_ONYMOUS = 1 << 0, WOCKY_MUC_CODE_AF_CHANGE_OOB = 1 << 1, WOCKY_MUC_CODE_CFG_SHOW_UNAVAILABLE = 1 << 2, WOCKY_MUC_CODE_CFG_HIDE_UNAVAILABLE = 1 << 3, WOCKY_MUC_CODE_CFG_NONPRIVACY = 1 << 4, WOCKY_MUC_CODE_OWN_PRESENCE = 1 << 5, WOCKY_MUC_CODE_CFG_LOGGING_ENABLED = 1 << 6, WOCKY_MUC_CODE_CFG_LOGGING_DISABLED = 1 << 7, WOCKY_MUC_CODE_CFG_ONYMOUS = 1 << 8, WOCKY_MUC_CODE_CFG_SEMIONYMOUS = 1 << 9, WOCKY_MUC_CODE_CFG_ANONYMOUS = 1 << 10, WOCKY_MUC_CODE_NEW_ROOM = 1 << 11, WOCKY_MUC_CODE_NICK_CHANGE_FORCED = 1 << 12, WOCKY_MUC_CODE_BANNED = 1 << 13, WOCKY_MUC_CODE_NICK_CHANGE_USER = 1 << 14, WOCKY_MUC_CODE_KICKED = 1 << 15, WOCKY_MUC_CODE_KICKED_AFFILIATION = 1 << 16, WOCKY_MUC_CODE_KICKED_ROOM_PRIVATISED = 1 << 17, WOCKY_MUC_CODE_KICKED_SHUTDOWN = 1 << 18, } WockyMucStatusCode; /** * WockyMucRole: * @WOCKY_MUC_ROLE_NONE: no role * @WOCKY_MUC_ROLE_VISITOR: visitor role * @WOCKY_MUC_ROLE_PARTICIPANT: participant role * @WOCKY_MUC_ROLE_MODERATOR: moderator role * * #WockyMuc roles as described in XEP-0045 §5.1. */ typedef enum { WOCKY_MUC_ROLE_NONE = 0, WOCKY_MUC_ROLE_VISITOR, WOCKY_MUC_ROLE_PARTICIPANT, WOCKY_MUC_ROLE_MODERATOR } WockyMucRole; /** * WockyMucAffiliation: * @WOCKY_MUC_AFFILIATION_OUTCAST: outcast affiliation * @WOCKY_MUC_AFFILIATION_NONE: no affiliation * @WOCKY_MUC_AFFILIATION_MEMBER: member affiliation * @WOCKY_MUC_AFFILIATION_ADMIN: admin affiliation * @WOCKY_MUC_AFFILIATION_OWNER: owner affiliation * * #WockyMuc affiliations as described in XEP-0045 §5.2. */ typedef enum { WOCKY_MUC_AFFILIATION_OUTCAST = -1, WOCKY_MUC_AFFILIATION_NONE = 0, WOCKY_MUC_AFFILIATION_MEMBER, WOCKY_MUC_AFFILIATION_ADMIN, WOCKY_MUC_AFFILIATION_OWNER, } WockyMucAffiliation; /** * WockyMucFeature: * @WOCKY_MUC_MODERN: the MUC is modern, as documented in XEP-0045 * @WOCKY_MUC_FORM_REGISTER: the MUC has support for the muc#register FORM_TYPE * @WOCKY_MUC_FORM_ROOMCONFIG: the MUC has support for the muc#register FORM_TYPE * @WOCKY_MUC_FORM_ROOMINFO: the MUC has support for the muc#register FORM_TYPE * @WOCKY_MUC_HIDDEN: the MUC is hidden * @WOCKY_MUC_MEMBERSONLY: only members can join this MUC * @WOCKY_MUC_MODERATED: the MUC is moderated * @WOCKY_MUC_NONANONYMOUS: the MUC is non-anonymous * @WOCKY_MUC_OPEN: the MUC is open * @WOCKY_MUC_PASSWORDPROTECTED: the MUC is password protected * @WOCKY_MUC_PERSISTENT: the MUC is persistent * @WOCKY_MUC_PUBLIC: the MUC is public * @WOCKY_MUC_ROOMS: the MUC has a list of MUC rooms * @WOCKY_MUC_SEMIANONYMOUS: the MUC is semi-anonymous * @WOCKY_MUC_TEMPORARY: the MUC is temporary * @WOCKY_MUC_UNMODERATED: the MUC is unmoderated * @WOCKY_MUC_UNSECURED: the MUC is unsecured * @WOCKY_MUC_OBSOLETE: the MUC has obsolete groupchat 1.0 features * * #WockyMuc feature flags. */ typedef enum { WOCKY_MUC_MODERN = 1, WOCKY_MUC_FORM_REGISTER = (1 << 1), WOCKY_MUC_FORM_ROOMCONFIG = (1 << 2), WOCKY_MUC_FORM_ROOMINFO = (1 << 3), WOCKY_MUC_HIDDEN = (1 << 4), WOCKY_MUC_MEMBERSONLY = (1 << 5), WOCKY_MUC_MODERATED = (1 << 6), WOCKY_MUC_NONANONYMOUS = (1 << 7), WOCKY_MUC_OPEN = (1 << 8), WOCKY_MUC_PASSWORDPROTECTED = (1 << 9), WOCKY_MUC_PERSISTENT = (1 << 10), WOCKY_MUC_PUBLIC = (1 << 11), WOCKY_MUC_ROOMS = (1 << 12), WOCKY_MUC_SEMIANONYMOUS = (1 << 13), WOCKY_MUC_TEMPORARY = (1 << 14), WOCKY_MUC_UNMODERATED = (1 << 15), WOCKY_MUC_UNSECURED = (1 << 16), WOCKY_MUC_OBSOLETE = (1 << 17), } WockyMucFeature; /** * WockyMucMsgType: * @WOCKY_MUC_MSG_NONE: no message type * @WOCKY_MUC_MSG_NORMAL: a normal message * @WOCKY_MUC_MSG_ACTION: an action message * @WOCKY_MUC_MSG_NOTICE: a notice message * * XMPP MUC message types. */ typedef enum { WOCKY_MUC_MSG_NONE, WOCKY_MUC_MSG_NORMAL, WOCKY_MUC_MSG_ACTION, WOCKY_MUC_MSG_NOTICE, } WockyMucMsgType; /** * WockyMucMsgState: * @WOCKY_MUC_MSG_STATE_NONE: no message state applies * @WOCKY_MUC_MSG_STATE_ACTIVE: the contact in the MUC is active * @WOCKY_MUC_MSG_STATE_COMPOSING: the contact in the MUC is composing * a message * @WOCKY_MUC_MSG_STATE_INACTIVE: the contact in the MUC is inactive * @WOCKY_MUC_MSG_STATE_PAUSED: the contact in the MUC has paused * composing a message * * XMPP MUC message states as documeted in XEP-0085. */ typedef enum { WOCKY_MUC_MSG_STATE_NONE = -1, WOCKY_MUC_MSG_STATE_ACTIVE, WOCKY_MUC_MSG_STATE_COMPOSING, WOCKY_MUC_MSG_STATE_INACTIVE, WOCKY_MUC_MSG_STATE_PAUSED, } WockyMucMsgState; /** * WockyMucState: * @WOCKY_MUC_CREATED: the #WockyMuc has been created * @WOCKY_MUC_INITIATED: the MUC has been initiated on the server * @WOCKY_MUC_AUTH: the user is authenticating with the MUC * @WOCKY_MUC_JOINED: the user has joined the MUC and can chat * @WOCKY_MUC_ENDED: the MUC has ended * * #WockyMuc states. */ typedef enum { WOCKY_MUC_CREATED = 0, WOCKY_MUC_INITIATED, WOCKY_MUC_AUTH, WOCKY_MUC_JOINED, WOCKY_MUC_ENDED, } WockyMucState; /** * WockyMucMember: * @from: the JID of the member (room@server/nick) * @jid: the JID of the owner (owner@domain/resource) * @nick: the nickname of the member * @role: the #WockyMucRole of the member * @affiliation: the #WockyMucAffiliation of the member * @status: the user set status string * @presence_stanza: the #WockyStanza that was received regarding the * member's presence */ typedef struct { gchar *from; /* room@service/nick */ gchar *jid; /* owner@domain/resource */ gchar *nick; /* nick */ WockyMucRole role; WockyMucAffiliation affiliation; gchar *status; /* user set status string */ WockyStanza *presence_stanza; } WockyMucMember; GType wocky_muc_get_type (void); struct _WockyMuc { /**/ GObject parent; WockyMucPrivate *priv; }; struct _WockyMucClass { /**/ GObjectClass parent_class; }; /* TYPE MACROS */ #define WOCKY_TYPE_MUC (wocky_muc_get_type ()) #define WOCKY_MUC(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), WOCKY_TYPE_MUC, WockyMuc)) #define WOCKY_MUC_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), WOCKY_TYPE_MUC, WockyXmppMuc)) #define WOCKY_IS_MUC(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WOCKY_TYPE_MUC)) #define WOCKY_IS_MUC_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), WOCKY_TYPE_MUC)) #define WOCKY_MUC_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_MUC, WockyMucClass)) /* disco info */ void wocky_muc_disco_info_async (WockyMuc *muc, GAsyncReadyCallback callback, GCancellable *cancel, gpointer data); gboolean wocky_muc_disco_info_finish (WockyMuc *muc, GAsyncResult *res, GError **error); /* presence */ WockyStanza *wocky_muc_create_presence (WockyMuc *muc, WockyStanzaSubType type, const gchar *status); /* join */ void wocky_muc_join (WockyMuc *muc, GCancellable *cancel); /* meta data */ const gchar * wocky_muc_jid (WockyMuc *muc); const gchar * wocky_muc_user (WockyMuc *muc); WockyMucRole wocky_muc_role (WockyMuc *muc); WockyMucAffiliation wocky_muc_affiliation (WockyMuc *muc); GHashTable * wocky_muc_members (WockyMuc *muc); WockyMucState wocky_muc_get_state (WockyMuc *muc); G_END_DECLS #endif /* __WOCKY_MUC_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jingle-content.c0000664000175000017500000011747412332440003026257 0ustar00cassidycassidy00000000000000/* * wocky-jingle-content.c - Source for WockyJingleContent * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "wocky-jingle-content.h" #include #include #include #include #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_JINGLE #include "wocky-debug-internal.h" #include "wocky-jingle-factory.h" #include "wocky-jingle-session.h" #include "wocky-jingle-transport-iface.h" #include "wocky-jingle-transport-google.h" #include "wocky-jingle-media-rtp.h" #include "wocky-namespaces.h" #include "wocky-signals-marshal.h" #include "wocky-utils.h" /* signal enum */ enum { READY, NEW_CANDIDATES, REMOVED, NEW_SHARE_CHANNEL, COMPLETED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; /* properties */ enum { PROP_SESSION = 1, PROP_CONTENT_NS, PROP_TRANSPORT_NS, PROP_NAME, PROP_SENDERS, PROP_STATE, PROP_DISPOSITION, PROP_LOCALLY_CREATED, LAST_PROPERTY }; struct _WockyJingleContentPrivate { gchar *name; gchar *creator; gboolean created_by_us; WockyJingleContentState state; WockyJingleContentSenders senders; gchar *content_ns; gchar *transport_ns; gchar *disposition; WockyJingleTransportIface *transport; /* Whether we've got the codecs (intersection) ready. */ gboolean media_ready; /* Whether we have at least one local candidate. */ gboolean have_local_candidates; guint gtalk4_event_id; guint last_share_channel_component_id; gboolean dispose_has_run; }; #define DEFAULT_CONTENT_TIMEOUT 60000 /* lookup tables */ G_DEFINE_TYPE(WockyJingleContent, wocky_jingle_content, G_TYPE_OBJECT); static void new_transport_candidates_cb (WockyJingleTransportIface *trans, GList *candidates, WockyJingleContent *content); static void _maybe_ready (WockyJingleContent *self); static void transport_created (WockyJingleContent *c); static void wocky_jingle_content_init (WockyJingleContent *obj) { WockyJingleContentPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, WOCKY_TYPE_JINGLE_CONTENT, WockyJingleContentPrivate); obj->priv = priv; DEBUG ("%p", obj); priv->state = WOCKY_JINGLE_CONTENT_STATE_EMPTY; priv->created_by_us = TRUE; priv->media_ready = FALSE; priv->have_local_candidates = FALSE; priv->gtalk4_event_id = 0; priv->dispose_has_run = FALSE; obj->session = NULL; } static void wocky_jingle_content_dispose (GObject *object) { WockyJingleContent *content = WOCKY_JINGLE_CONTENT (object); WockyJingleContentPrivate *priv = content->priv; if (priv->dispose_has_run) return; DEBUG ("%p", object); priv->dispose_has_run = TRUE; if (priv->gtalk4_event_id != 0) { g_source_remove (priv->gtalk4_event_id); priv->gtalk4_event_id = 0; } g_free (priv->name); priv->name = NULL; g_free (priv->creator); priv->creator = NULL; g_free (priv->content_ns); priv->content_ns = NULL; g_free (priv->transport_ns); priv->transport_ns = NULL; g_free (priv->disposition); priv->disposition = NULL; if (G_OBJECT_CLASS (wocky_jingle_content_parent_class)->dispose) G_OBJECT_CLASS (wocky_jingle_content_parent_class)->dispose (object); } static void wocky_jingle_content_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyJingleContent *self = WOCKY_JINGLE_CONTENT (object); WockyJingleContentPrivate *priv = self->priv; switch (property_id) { case PROP_SESSION: g_value_set_object (value, self->session); break; case PROP_NAME: g_value_set_string (value, priv->name); break; case PROP_SENDERS: g_value_set_uint (value, priv->senders); break; case PROP_STATE: g_value_set_uint (value, priv->state); break; case PROP_CONTENT_NS: g_value_set_string (value, priv->content_ns); break; case PROP_TRANSPORT_NS: g_value_set_string (value, priv->transport_ns); break; case PROP_DISPOSITION: g_value_set_string (value, priv->disposition); break; case PROP_LOCALLY_CREATED: g_value_set_boolean (value, priv->created_by_us); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_jingle_content_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyJingleContent *self = WOCKY_JINGLE_CONTENT (object); WockyJingleContentPrivate *priv = self->priv; switch (property_id) { case PROP_SESSION: self->session = g_value_get_object (value); break; case PROP_CONTENT_NS: g_free (priv->content_ns); priv->content_ns = g_value_dup_string (value); break; case PROP_TRANSPORT_NS: g_free (priv->transport_ns); priv->transport_ns = g_value_dup_string (value); /* We can't switch transports. */ g_assert (priv->transport == NULL); if (priv->transport_ns != NULL) { GType transport_type = wocky_jingle_factory_lookup_transport ( wocky_jingle_session_get_factory (self->session), priv->transport_ns); g_assert (transport_type != 0); priv->transport = wocky_jingle_transport_iface_new (transport_type, self, priv->transport_ns); g_signal_connect (priv->transport, "new-candidates", (GCallback) new_transport_candidates_cb, self); transport_created (self); } break; case PROP_NAME: /* can't rename */ g_assert (priv->name == NULL); priv->name = g_value_dup_string (value); break; case PROP_SENDERS: priv->senders = g_value_get_uint (value); break; case PROP_STATE: priv->state = g_value_get_uint (value); break; case PROP_DISPOSITION: g_assert (priv->disposition == NULL); priv->disposition = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static WockyJingleContentSenders get_default_senders_real (WockyJingleContent *c) { return WOCKY_JINGLE_CONTENT_SENDERS_BOTH; } static void wocky_jingle_content_class_init (WockyJingleContentClass *cls) { GParamSpec *param_spec; GObjectClass *object_class = G_OBJECT_CLASS (cls); g_type_class_add_private (cls, sizeof (WockyJingleContentPrivate)); object_class->get_property = wocky_jingle_content_get_property; object_class->set_property = wocky_jingle_content_set_property; object_class->dispose = wocky_jingle_content_dispose; cls->get_default_senders = get_default_senders_real; /* property definitions */ param_spec = g_param_spec_object ("session", "WockyJingleSession object", "Jingle session object that owns this content.", WOCKY_TYPE_JINGLE_SESSION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SESSION, param_spec); param_spec = g_param_spec_string ("name", "Content name", "A unique content name in the session.", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_NAME, param_spec); param_spec = g_param_spec_string ("content-ns", "Content namespace", "Namespace identifying the content type.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONTENT_NS, param_spec); param_spec = g_param_spec_string ("transport-ns", "Transport namespace", "Namespace identifying the transport type.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_TRANSPORT_NS, param_spec); param_spec = g_param_spec_uint ("senders", "Stream senders", "Valid senders for the stream.", 0, G_MAXUINT32, WOCKY_JINGLE_CONTENT_SENDERS_NONE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SENDERS, param_spec); param_spec = g_param_spec_uint ("state", "Content state", "The current state that the content is in.", 0, G_MAXUINT32, WOCKY_JINGLE_CONTENT_STATE_EMPTY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_STATE, param_spec); param_spec = g_param_spec_string ("disposition", "Content disposition", "Distinguishes between 'session' and other contents.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_DISPOSITION, param_spec); param_spec = g_param_spec_boolean ("locally-created", "Locally created", "True if the content was created by the local client.", FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_LOCALLY_CREATED, param_spec); /* signal definitions */ signals[READY] = g_signal_new ("ready", G_OBJECT_CLASS_TYPE (cls), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * WockyJingleContent::new-candidates: * @content: the content * @candidates: (type GList) (element-type WockyJingleCandidate): a #GList of new candidates * * Emitted when new candidates are received from the peer. */ signals[NEW_CANDIDATES] = g_signal_new ( "new-candidates", G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[NEW_SHARE_CHANNEL] = g_signal_new ( "new-share-channel", G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__STRING_UINT, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_UINT); signals[COMPLETED] = g_signal_new ( "completed", G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /* This signal serves as notification that the WockyJingleContent is now * meaningless; everything holding a reference should drop it after receiving * 'removed'. */ signals[REMOVED] = g_signal_new ("removed", G_OBJECT_CLASS_TYPE (cls), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } static WockyJingleContentSenders get_default_senders (WockyJingleContent *c) { WockyJingleContentSenders (*virtual_method)(WockyJingleContent *) = \ WOCKY_JINGLE_CONTENT_GET_CLASS (c)->get_default_senders; g_assert (virtual_method != NULL); return virtual_method (c); } static WockyJingleContentSenders parse_senders (const gchar *txt) { if (txt == NULL) return WOCKY_JINGLE_CONTENT_SENDERS_NONE; if (!wocky_strdiff (txt, "initiator")) return WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR; else if (!wocky_strdiff (txt, "responder")) return WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER; else if (!wocky_strdiff (txt, "both")) return WOCKY_JINGLE_CONTENT_SENDERS_BOTH; return WOCKY_JINGLE_CONTENT_SENDERS_NONE; } static const gchar * produce_senders (WockyJingleContentSenders senders) { switch (senders) { case WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR: return "initiator"; case WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER: return "responder"; case WOCKY_JINGLE_CONTENT_SENDERS_BOTH: return "both"; default: DEBUG ("invalid content senders %u", senders); g_assert_not_reached (); } /* to make gcc not complain */ return NULL; } #define SET_BAD_REQ(txt) \ g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, txt) static void new_transport_candidates_cb (WockyJingleTransportIface *trans, GList *candidates, WockyJingleContent *content) { /* just pass the signal on */ g_signal_emit (content, signals[NEW_CANDIDATES], 0, candidates); } static void transport_created (WockyJingleContent *c) { void (*virtual_method)(WockyJingleContent *, WockyJingleTransportIface *) = \ WOCKY_JINGLE_CONTENT_GET_CLASS (c)->transport_created; if (virtual_method != NULL) virtual_method (c, c->priv->transport); } static void parse_description (WockyJingleContent *c, WockyNode *desc_node, GError **error) { void (*virtual_method)(WockyJingleContent *, WockyNode *, GError **) = WOCKY_JINGLE_CONTENT_GET_CLASS (c)->parse_description; g_assert (virtual_method != NULL); virtual_method (c, desc_node, error); } static gboolean send_gtalk4_transport_accept (gpointer user_data) { WockyJingleContent *c = WOCKY_JINGLE_CONTENT (user_data); WockyJingleContentPrivate *priv = c->priv; WockyNode *sess_node; WockyStanza *msg = wocky_jingle_session_new_message (c->session, WOCKY_JINGLE_ACTION_TRANSPORT_ACCEPT, &sess_node); DEBUG ("Sending Gtalk4 'transport-accept' message to peer"); wocky_node_add_child_ns (sess_node, "transport", priv->transport_ns); wocky_jingle_session_send (c->session, msg); priv->gtalk4_event_id = 0; return FALSE; } void wocky_jingle_content_parse_add (WockyJingleContent *c, WockyNode *content_node, gboolean google_mode, GError **error) { WockyJingleContentPrivate *priv = c->priv; const gchar *name, *creator, *senders, *disposition; WockyNode *trans_node, *desc_node; GType transport_type = 0; WockyJingleTransportIface *trans = NULL; WockyJingleDialect dialect = wocky_jingle_session_get_dialect (c->session); priv->created_by_us = FALSE; desc_node = wocky_node_get_child (content_node, "description"); trans_node = wocky_node_get_child (content_node, "transport"); creator = wocky_node_get_attribute (content_node, "creator"); name = wocky_node_get_attribute (content_node, "name"); senders = wocky_node_get_attribute (content_node, "senders"); g_assert (priv->transport_ns == NULL); if (google_mode) { if (creator == NULL) creator = "initiator"; /* the google protocols don't give the contents names, so put in a dummy * value if none was set by the session*/ if (priv->name == NULL) name = priv->name = g_strdup ("gtalk"); else name = priv->name; if (trans_node == NULL) { /* gtalk lj0.3 assumes google-p2p transport */ DEBUG ("detected GTalk3 dialect"); dialect = WOCKY_JINGLE_DIALECT_GTALK3; g_object_set (c->session, "dialect", WOCKY_JINGLE_DIALECT_GTALK3, NULL); transport_type = wocky_jingle_factory_lookup_transport ( wocky_jingle_session_get_factory (c->session), ""); /* in practice we do support gtalk-p2p, so this can't happen */ if (G_UNLIKELY (transport_type == 0)) { SET_BAD_REQ ("gtalk-p2p transport unsupported"); return; } priv->transport_ns = g_strdup (""); } } else { if (creator == NULL && wocky_jingle_session_peer_has_cap (c->session, WOCKY_QUIRK_GOOGLE_WEBMAIL_CLIENT)) { if (wocky_jingle_content_creator_is_initiator (c)) creator = "initiator"; else creator = "responder"; DEBUG ("Working around GMail omitting creator=''; assuming '%s'", creator); } if ((trans_node == NULL) || (creator == NULL) || (name == NULL)) { SET_BAD_REQ ("missing required content attributes or elements"); return; } /* In proper protocols the name comes from the stanza */ g_assert (priv->name == NULL); priv->name = g_strdup (name); } /* if we didn't set it to google-p2p implicitly already, detect it */ if (transport_type == 0) { const gchar *ns = wocky_node_get_ns (trans_node); transport_type = wocky_jingle_factory_lookup_transport ( wocky_jingle_session_get_factory (c->session), ns); if (transport_type == 0) { SET_BAD_REQ ("unsupported content transport"); return; } priv->transport_ns = g_strdup (ns); } if (senders == NULL) priv->senders = get_default_senders (c); else priv->senders = parse_senders (senders); if (priv->senders == WOCKY_JINGLE_CONTENT_SENDERS_NONE) { SET_BAD_REQ ("invalid content senders"); return; } parse_description (c, desc_node, error); if (*error != NULL) return; disposition = wocky_node_get_attribute (content_node, "disposition"); if (disposition == NULL) disposition = "session"; if (wocky_strdiff (disposition, priv->disposition)) { g_free (priv->disposition); priv->disposition = g_strdup (disposition); } DEBUG ("content creating new transport type %s", g_type_name (transport_type)); trans = wocky_jingle_transport_iface_new (transport_type, c, priv->transport_ns); g_signal_connect (trans, "new-candidates", (GCallback) new_transport_candidates_cb, c); /* Depending on transport, there may be initial candidates specified here */ if (trans_node != NULL) { wocky_jingle_transport_iface_parse_candidates (trans, trans_node, error); if (*error) { g_object_unref (trans); return; } } g_assert (priv->transport == NULL); priv->transport = trans; transport_created (c); g_assert (priv->creator == NULL); priv->creator = g_strdup (creator); priv->state = WOCKY_JINGLE_CONTENT_STATE_NEW; /* GTalk4 seems to require "transport-accept" for acknowledging * the transport type. wjt confirms that this is apparently necessary for * incoming calls to work. */ if (dialect == WOCKY_JINGLE_DIALECT_GTALK4) priv->gtalk4_event_id = g_idle_add (send_gtalk4_transport_accept, c); return; } static guint new_share_channel (WockyJingleContent *c, const gchar *name) { WockyJingleContentPrivate *priv = c->priv; WockyJingleTransportGoogle *gtrans = NULL; if (priv->transport && WOCKY_IS_JINGLE_TRANSPORT_GOOGLE (priv->transport)) { guint id = priv->last_share_channel_component_id + 1; gtrans = WOCKY_JINGLE_TRANSPORT_GOOGLE (priv->transport); if (!jingle_transport_google_set_component_name (gtrans, name, id)) return 0; priv->last_share_channel_component_id++; DEBUG ("New Share channel '%s' with id : %d", name, id); g_signal_emit (c, signals[NEW_SHARE_CHANNEL], 0, name, id); return priv->last_share_channel_component_id; } return 0; } guint wocky_jingle_content_create_share_channel (WockyJingleContent *self, const gchar *name) { WockyJingleContentPrivate *priv = self->priv; WockyNode *sess_node, *channel_node; WockyStanza *msg = NULL; /* Send the info action before creating the channel, in case candidates need to be sent on the signal emit. It doesn't matter if the channel already exists anyways... */ msg = wocky_jingle_session_new_message (self->session, WOCKY_JINGLE_ACTION_INFO, &sess_node); DEBUG ("Sending 'info' message to peer : channel %s", name); channel_node = wocky_node_add_child_ns (sess_node, "channel", priv->content_ns); wocky_node_set_attribute (channel_node, "name", name); wocky_jingle_session_send (self->session, msg); return new_share_channel (self, name); } void wocky_jingle_content_send_complete (WockyJingleContent *self) { WockyJingleContentPrivate *priv = self->priv; WockyNode *sess_node; WockyStanza *msg = NULL; msg = wocky_jingle_session_new_message (self->session, WOCKY_JINGLE_ACTION_INFO, &sess_node); DEBUG ("Sending 'info' message to peer : complete"); wocky_node_add_child_ns (sess_node, "complete", priv->content_ns); wocky_jingle_session_send (self->session, msg); } void wocky_jingle_content_parse_info (WockyJingleContent *c, WockyNode *content_node, GError **error) { WockyNode *channel_node; WockyNode *complete_node; channel_node = wocky_node_get_child (content_node, "channel"); complete_node = wocky_node_get_child (content_node, "complete"); DEBUG ("parsing info message : %p - %p", channel_node, complete_node); if (channel_node) { const gchar *name; name = wocky_node_get_attribute (channel_node, "name"); if (name != NULL) new_share_channel (c, name); } else if (complete_node) { g_signal_emit (c, signals[COMPLETED], 0); } } void wocky_jingle_content_parse_accept (WockyJingleContent *c, WockyNode *content_node, gboolean google_mode, GError **error) { WockyJingleContentPrivate *priv = c->priv; const gchar *senders; WockyNode *trans_node, *desc_node; WockyJingleDialect dialect = wocky_jingle_session_get_dialect (c->session); WockyJingleContentSenders newsenders; desc_node = wocky_node_get_child (content_node, "description"); trans_node = wocky_node_get_child (content_node, "transport"); senders = wocky_node_get_attribute (content_node, "senders"); if (WOCKY_IS_JINGLE_MEDIA_RTP (c) && WOCKY_JINGLE_DIALECT_IS_GOOGLE (dialect) && trans_node == NULL) { DEBUG ("no transport node, assuming GTalk3 dialect"); /* gtalk lj0.3 assumes google-p2p transport */ g_object_set (c->session, "dialect", WOCKY_JINGLE_DIALECT_GTALK3, NULL); } if (senders == NULL) newsenders = get_default_senders (c); else newsenders = parse_senders (senders); if (newsenders == WOCKY_JINGLE_CONTENT_SENDERS_NONE) { SET_BAD_REQ ("invalid content senders"); return; } if (newsenders != priv->senders) { DEBUG ("changing senders from %s to %s", produce_senders (priv->senders), produce_senders (newsenders)); priv->senders = newsenders; g_object_notify ((GObject *) c, "senders"); } parse_description (c, desc_node, error); if (*error != NULL) return; priv->state = WOCKY_JINGLE_CONTENT_STATE_ACKNOWLEDGED; g_object_notify ((GObject *) c, "state"); if (trans_node != NULL) { wocky_jingle_transport_iface_parse_candidates (priv->transport, trans_node, NULL); } } void wocky_jingle_content_parse_description_info (WockyJingleContent *c, WockyNode *content_node, GError **error) { WockyJingleContentPrivate *priv = c->priv; WockyNode *desc_node; desc_node = wocky_node_get_child (content_node, "description"); if (desc_node == NULL) { SET_BAD_REQ ("invalid description-info action"); return; } if (priv->created_by_us && priv->state < WOCKY_JINGLE_CONTENT_STATE_ACKNOWLEDGED) { /* The stream was created by us and the other side didn't acknowledge it * yet, thus we don't have their codec information, thus the * description-info isn't meaningful and can be ignored */ DEBUG ("Ignoring description-info as we didn't receive the codecs yet"); return; } parse_description (c, desc_node, error); } void wocky_jingle_content_produce_node (WockyJingleContent *c, WockyNode *parent, gboolean include_description, gboolean include_transport, WockyNode **trans_node_out) { WockyJingleContentPrivate *priv = c->priv; WockyNode *content_node, *trans_node; WockyJingleDialect dialect = wocky_jingle_session_get_dialect (c->session); void (*produce_desc)(WockyJingleContent *, WockyNode *) = WOCKY_JINGLE_CONTENT_GET_CLASS (c)->produce_description; if ((dialect == WOCKY_JINGLE_DIALECT_GTALK3) || (dialect == WOCKY_JINGLE_DIALECT_GTALK4)) { content_node = parent; } else { content_node = wocky_node_add_child (parent, "content"); wocky_node_set_attributes (content_node, "name", priv->name, "senders", produce_senders (priv->senders), NULL); if (wocky_jingle_content_creator_is_initiator (c)) wocky_node_set_attribute (content_node, "creator", "initiator"); else wocky_node_set_attribute (content_node, "creator", "responder"); } if (include_description) produce_desc (c, content_node); if (include_transport) { if (dialect == WOCKY_JINGLE_DIALECT_GTALK3) { /* GTalk 03 doesn't use a transport, but assumes gtalk-p2p */ trans_node = parent; } else { trans_node = wocky_node_add_child_ns (content_node, "transport", priv->transport_ns); } if (trans_node_out != NULL) *trans_node_out = trans_node; } } void wocky_jingle_content_update_senders (WockyJingleContent *c, WockyNode *content_node, GError **error) { WockyJingleContentPrivate *priv = c->priv; WockyJingleContentSenders senders; senders = parse_senders (wocky_node_get_attribute (content_node, "senders")); if (senders == WOCKY_JINGLE_CONTENT_SENDERS_NONE) { SET_BAD_REQ ("invalid content senders in stream"); return; } priv->senders = senders; g_object_notify ((GObject *) c, "senders"); } void wocky_jingle_content_parse_transport_info (WockyJingleContent *self, WockyNode *trans_node, GError **error) { WockyJingleContentPrivate *priv = self->priv; wocky_jingle_transport_iface_parse_candidates (priv->transport, trans_node, error); } /** * wocky_jingle_content_add_candidates: * @self: the content * @li: (element-type WockyJingleCandidate) (transfer full): a list of * #WockyJingleCandidate structs, allocated with wocky_jingle_candidate_new(). * * Adds the candidates listed in @li to the content, communicating them to the * peer if appropriate. */ void wocky_jingle_content_add_candidates (WockyJingleContent *self, GList *li) { WockyJingleContentPrivate *priv = self->priv; DEBUG ("called content: %s created_by_us: %d", priv->name, priv->created_by_us); if (li == NULL) return; wocky_jingle_transport_iface_new_local_candidates (priv->transport, li); if (!priv->have_local_candidates) { priv->have_local_candidates = TRUE; /* Maybe we were waiting for at least one candidate? */ _maybe_ready (self); } /* If the content exists on the wire, let the transport send this candidate * if it wants to. */ if (priv->state > WOCKY_JINGLE_CONTENT_STATE_EMPTY) wocky_jingle_transport_iface_send_candidates (priv->transport, FALSE); } /* Returns whether the content is ready to be signalled (initiated, for local * streams, or acknowledged, for remote streams. */ gboolean wocky_jingle_content_is_ready (WockyJingleContent *self) { WockyJingleContentPrivate *priv = self->priv; if (priv->created_by_us) { /* If it's created by us, media ready, not signalled, and we have * at least one local candidate, it's ready to be added. */ if (priv->media_ready && priv->state == WOCKY_JINGLE_CONTENT_STATE_EMPTY && (!WOCKY_IS_JINGLE_MEDIA_RTP (self) || priv->have_local_candidates)) return TRUE; } else { /* If it's created by peer, media and transports ready, * and not acknowledged yet, it's ready for acceptance. */ if (priv->media_ready && priv->state == WOCKY_JINGLE_CONTENT_STATE_NEW && (!WOCKY_IS_JINGLE_MEDIA_RTP (self) || wocky_jingle_transport_iface_can_accept (priv->transport))) return TRUE; } return FALSE; } static void send_content_add_or_accept (WockyJingleContent *self) { WockyJingleContentPrivate *priv = self->priv; WockyStanza *msg; WockyNode *sess_node, *transport_node; WockyJingleAction action; WockyJingleContentState new_state = WOCKY_JINGLE_CONTENT_STATE_EMPTY; g_assert (wocky_jingle_content_is_ready (self)); if (priv->created_by_us) { /* TODO: set a timer for acknowledgement */ action = WOCKY_JINGLE_ACTION_CONTENT_ADD; new_state = WOCKY_JINGLE_CONTENT_STATE_SENT; } else { action = WOCKY_JINGLE_ACTION_CONTENT_ACCEPT; new_state = WOCKY_JINGLE_CONTENT_STATE_ACKNOWLEDGED; } msg = wocky_jingle_session_new_message (self->session, action, &sess_node); wocky_jingle_content_produce_node (self, sess_node, TRUE, TRUE, &transport_node); wocky_jingle_transport_iface_inject_candidates (priv->transport, transport_node); wocky_jingle_session_send (self->session, msg); priv->state = new_state; g_object_notify (G_OBJECT (self), "state"); } static void _maybe_ready (WockyJingleContent *self) { WockyJingleContentPrivate *priv = self->priv; WockyJingleState state; if (!wocky_jingle_content_is_ready (self)) return; /* If content disposition is session and session * is not yet acknowledged/active, we signall * the readiness to the session and let it take * care of it. Otherwise, we can deal with it * ourselves. */ g_object_get (self->session, "state", &state, NULL); if (!wocky_strdiff (priv->disposition, "session") && (state < WOCKY_JINGLE_STATE_PENDING_ACCEPT_SENT)) { /* Notify the session that we're ready for * session-initiate/session-accept */ g_signal_emit (self, signals[READY], 0); } else { if (state >= WOCKY_JINGLE_STATE_PENDING_INITIATE_SENT) { send_content_add_or_accept (self); /* if neccessary, transmit the candidates */ wocky_jingle_transport_iface_send_candidates (priv->transport, FALSE); } else { /* non session-disposition content ready without session * being initiated at all? */ DEBUG ("session not initiated yet, ignoring non-session ready content"); return; } } } void wocky_jingle_content_maybe_send_description (WockyJingleContent *self) { WockyJingleContentPrivate *priv = self->priv; /* If we didn't send the content yet there is no reason to send a * description-info to update it */ if (priv->state < WOCKY_JINGLE_CONTENT_STATE_SENT) return; if (wocky_jingle_session_defines_action (self->session, WOCKY_JINGLE_ACTION_DESCRIPTION_INFO)) { WockyNode *sess_node; WockyStanza *msg = wocky_jingle_session_new_message (self->session, WOCKY_JINGLE_ACTION_DESCRIPTION_INFO, &sess_node); wocky_jingle_content_produce_node (self, sess_node, TRUE, FALSE, NULL); wocky_jingle_session_send (self->session, msg); } else { DEBUG ("not sending description-info, speaking an old dialect"); } } /* Used when session-initiate is sent (so all initial contents transmit their * candidates), and when we detect gtalk3 after we've transmitted some * candidates. */ void wocky_jingle_content_retransmit_candidates (WockyJingleContent *self, gboolean all) { wocky_jingle_transport_iface_send_candidates (self->priv->transport, all); } void wocky_jingle_content_inject_candidates (WockyJingleContent *self, WockyNode *transport_node) { wocky_jingle_transport_iface_inject_candidates (self->priv->transport, transport_node); } /* Called by a subclass when the media is ready (e.g. we got local codecs) */ void _wocky_jingle_content_set_media_ready (WockyJingleContent *self) { WockyJingleContentPrivate *priv = self->priv; DEBUG ("media ready on content: %s created_by_us: %d", priv->name, priv->created_by_us); priv->media_ready = TRUE; _maybe_ready (self); } void wocky_jingle_content_set_transport_state (WockyJingleContent *self, WockyJingleTransportState state) { WockyJingleContentPrivate *priv = self->priv; g_object_set (priv->transport, "state", state, NULL); _maybe_ready (self); } GList * wocky_jingle_content_get_remote_candidates (WockyJingleContent *c) { WockyJingleContentPrivate *priv = c->priv; return wocky_jingle_transport_iface_get_remote_candidates (priv->transport); } GList * wocky_jingle_content_get_local_candidates (WockyJingleContent *c) { WockyJingleContentPrivate *priv = c->priv; return wocky_jingle_transport_iface_get_local_candidates (priv->transport); } gboolean wocky_jingle_content_get_credentials (WockyJingleContent *c, gchar **ufrag, gchar **pwd) { WockyJingleContentPrivate *priv = c->priv; return jingle_transport_get_credentials (priv->transport, ufrag, pwd); } gboolean wocky_jingle_content_change_direction (WockyJingleContent *c, WockyJingleContentSenders senders) { WockyJingleContentPrivate *priv = c->priv; WockyStanza *msg; WockyNode *sess_node; WockyJingleDialect dialect = wocky_jingle_session_get_dialect (c->session); if (senders == priv->senders) return TRUE; priv->senders = senders; g_object_notify (G_OBJECT (c), "senders"); if (WOCKY_JINGLE_DIALECT_IS_GOOGLE (dialect)) { DEBUG ("ignoring direction change request for GTalk stream"); return FALSE; } if (priv->state >= WOCKY_JINGLE_CONTENT_STATE_SENT) { msg = wocky_jingle_session_new_message (c->session, WOCKY_JINGLE_ACTION_CONTENT_MODIFY, &sess_node); wocky_jingle_content_produce_node (c, sess_node, FALSE, FALSE, NULL); wocky_jingle_session_send (c->session, msg); } /* FIXME: actually check whether remote end accepts our content-modify */ return TRUE; } static void _on_remove_reply ( GObject *source, GAsyncResult *result, gpointer user_data) { WockyJingleContent *c = WOCKY_JINGLE_CONTENT (user_data); WockyJingleContentPrivate *priv = c->priv; g_assert (priv->state == WOCKY_JINGLE_CONTENT_STATE_REMOVING); DEBUG ("%p", c); /* Everything holding a reference to a content should drop it after receiving * 'removed'. */ g_signal_emit (c, signals[REMOVED], 0); g_object_unref (c); } static void _content_remove (WockyJingleContent *c, gboolean signal_peer, WockyJingleReason reason) { WockyJingleContentPrivate *priv = c->priv; WockyStanza *msg; WockyNode *sess_node; DEBUG ("called for %p (%s)", c, priv->name); /* If we were already signalled and removal is not a side-effect of * something else (sesssion termination, or removal by peer), * we have to signal removal to the peer. */ if (signal_peer && (priv->state != WOCKY_JINGLE_CONTENT_STATE_EMPTY)) { if (priv->state == WOCKY_JINGLE_CONTENT_STATE_REMOVING) { DEBUG ("ignoring request to remove content which is already being removed"); return; } priv->state = WOCKY_JINGLE_CONTENT_STATE_REMOVING; g_object_notify ((GObject *) c, "state"); msg = wocky_jingle_session_new_message (c->session, reason == WOCKY_JINGLE_REASON_UNKNOWN ? WOCKY_JINGLE_ACTION_CONTENT_REMOVE : WOCKY_JINGLE_ACTION_CONTENT_REJECT, &sess_node); if (reason != WOCKY_JINGLE_REASON_UNKNOWN) { WockyNode *reason_node = wocky_node_add_child_with_content (sess_node, "reason", NULL); wocky_node_add_child_with_content (reason_node, wocky_jingle_session_get_reason_name (reason), NULL); } wocky_jingle_content_produce_node (c, sess_node, FALSE, FALSE, NULL); wocky_porter_send_iq_async (wocky_jingle_session_get_porter (c->session), msg, NULL, _on_remove_reply, g_object_ref (c)); g_object_unref (msg); } else { DEBUG ("signalling removed with %u refs", G_OBJECT (c)->ref_count); /* Everything holding a reference to a content should drop it after receiving * 'removed'. */ g_signal_emit (c, signals[REMOVED], 0); } } void wocky_jingle_content_remove (WockyJingleContent *c, gboolean signal_peer) { _content_remove (c, signal_peer, WOCKY_JINGLE_REASON_UNKNOWN); } void wocky_jingle_content_reject (WockyJingleContent *c, WockyJingleReason reason) { _content_remove (c, TRUE, reason); } gboolean wocky_jingle_content_is_created_by_us (WockyJingleContent *c) { return c->priv->created_by_us; } gboolean wocky_jingle_content_creator_is_initiator (WockyJingleContent *c) { gboolean session_created_by_us; g_object_get (c->session, "local-initiator", &session_created_by_us, NULL); return (c->priv->created_by_us == session_created_by_us); } const gchar * wocky_jingle_content_get_name (WockyJingleContent *self) { return self->priv->name; } const gchar * wocky_jingle_content_get_ns (WockyJingleContent *self) { return self->priv->content_ns; } const gchar * wocky_jingle_content_get_transport_ns (WockyJingleContent *self) { return self->priv->transport_ns; } const gchar * wocky_jingle_content_get_disposition (WockyJingleContent *self) { return self->priv->disposition; } WockyJingleTransportType wocky_jingle_content_get_transport_type (WockyJingleContent *c) { return wocky_jingle_transport_iface_get_transport_type (c->priv->transport); } static gboolean jingle_content_has_direction (WockyJingleContent *self, gboolean sending) { WockyJingleContentPrivate *priv = self->priv; gboolean initiated_by_us; g_object_get (self->session, "local-initiator", &initiated_by_us, NULL); switch (priv->senders) { case WOCKY_JINGLE_CONTENT_SENDERS_BOTH: return TRUE; case WOCKY_JINGLE_CONTENT_SENDERS_NONE: return FALSE; case WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR: return sending ? initiated_by_us : !initiated_by_us; case WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER: return sending ? !initiated_by_us : initiated_by_us; } return FALSE; } gboolean wocky_jingle_content_sending (WockyJingleContent *self) { return jingle_content_has_direction (self, TRUE); } gboolean wocky_jingle_content_receiving (WockyJingleContent *self) { return jingle_content_has_direction (self, FALSE); } void wocky_jingle_content_set_sending (WockyJingleContent *self, gboolean send) { WockyJingleContentPrivate *priv = self->priv; WockyJingleContentSenders senders; gboolean initiated_by_us; if (send == wocky_jingle_content_sending (self)) return; g_object_get (self->session, "local-initiator", &initiated_by_us, NULL); if (send) { if (priv->senders == WOCKY_JINGLE_CONTENT_SENDERS_NONE) senders = (initiated_by_us ? WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR : WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER); else senders = WOCKY_JINGLE_CONTENT_SENDERS_BOTH; } else { if (priv->senders == WOCKY_JINGLE_CONTENT_SENDERS_BOTH) senders = (initiated_by_us ? WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER : WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR); else senders = WOCKY_JINGLE_CONTENT_SENDERS_NONE; } if (senders == WOCKY_JINGLE_CONTENT_SENDERS_NONE) wocky_jingle_content_remove (self, TRUE); else wocky_jingle_content_change_direction (self, senders); } void wocky_jingle_content_request_receiving (WockyJingleContent *self, gboolean receive) { WockyJingleContentPrivate *priv = self->priv; WockyJingleContentSenders senders; gboolean initiated_by_us; if (receive == wocky_jingle_content_receiving (self)) return; g_object_get (self->session, "local-initiator", &initiated_by_us, NULL); if (receive) { if (priv->senders == WOCKY_JINGLE_CONTENT_SENDERS_NONE) senders = (initiated_by_us ? WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER : WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR); else senders = WOCKY_JINGLE_CONTENT_SENDERS_BOTH; } else { if (priv->senders == WOCKY_JINGLE_CONTENT_SENDERS_BOTH) senders = (initiated_by_us ? WOCKY_JINGLE_CONTENT_SENDERS_INITIATOR : WOCKY_JINGLE_CONTENT_SENDERS_RESPONDER); else senders = WOCKY_JINGLE_CONTENT_SENDERS_NONE; } if (senders == WOCKY_JINGLE_CONTENT_SENDERS_NONE) wocky_jingle_content_remove (self, TRUE); else wocky_jingle_content_change_direction (self, senders); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-sasl-auth.c0000664000175000017500000004545712212322440025242 0ustar00cassidycassidy00000000000000/* * wocky-sasl-auth.c - Source for WockySaslAuth * Copyright (C) 2006-2009 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "wocky-sasl-auth.h" #include "wocky-signals-marshal.h" #include "wocky-namespaces.h" #include "wocky-utils.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_AUTH #include "wocky-debug-internal.h" G_DEFINE_TYPE(WockySaslAuth, wocky_sasl_auth, G_TYPE_OBJECT) enum { PROP_SERVER = 1, PROP_USERNAME, PROP_PASSWORD, PROP_CONNECTION, PROP_AUTH_REGISTRY, }; /* private structure */ struct _WockySaslAuthPrivate { gboolean dispose_has_run; WockyXmppConnection *connection; gchar *username; gchar *password; gchar *server; GCancellable *cancel; GSimpleAsyncResult *result; WockyAuthRegistry *auth_registry; }; static void sasl_auth_stanza_received (GObject *source, GAsyncResult *res, gpointer user_data); static void wocky_sasl_auth_init (WockySaslAuth *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_SASL_AUTH, WockySaslAuthPrivate); } static void wocky_sasl_auth_dispose (GObject *object); static void wocky_sasl_auth_finalize (GObject *object); static void wocky_sasl_auth_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockySaslAuth *sasl = WOCKY_SASL_AUTH (object); WockySaslAuthPrivate *priv = sasl->priv; switch (property_id) { case PROP_SERVER: g_free (priv->server); priv->server = g_value_dup_string (value); break; case PROP_USERNAME: g_free (priv->username); priv->username = g_value_dup_string (value); break; case PROP_PASSWORD: g_free (priv->password); priv->password = g_value_dup_string (value); break; case PROP_CONNECTION: priv->connection = g_value_dup_object (value); break; case PROP_AUTH_REGISTRY: if (g_value_get_object (value) == NULL) priv->auth_registry = wocky_auth_registry_new (); else priv->auth_registry = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_sasl_auth_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockySaslAuth *sasl = WOCKY_SASL_AUTH (object); WockySaslAuthPrivate *priv = sasl->priv; switch (property_id) { case PROP_SERVER: g_value_set_string (value, priv->server); break; case PROP_CONNECTION: g_value_set_object (value, priv->connection); break; case PROP_AUTH_REGISTRY: g_value_set_object (value, priv->auth_registry); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_sasl_auth_class_init (WockySaslAuthClass *wocky_sasl_auth_class) { GObjectClass *object_class = G_OBJECT_CLASS (wocky_sasl_auth_class); GParamSpec *spec; g_type_class_add_private (wocky_sasl_auth_class, sizeof (WockySaslAuthPrivate)); object_class->set_property = wocky_sasl_auth_set_property; object_class->get_property = wocky_sasl_auth_get_property; spec = g_param_spec_string ("server", "server", "The name of the server", NULL, G_PARAM_READWRITE|G_PARAM_CONSTRUCT); g_object_class_install_property (object_class, PROP_SERVER, spec); spec = g_param_spec_string ("username", "username", "The username to authenticate with", NULL, G_PARAM_WRITABLE|G_PARAM_CONSTRUCT); g_object_class_install_property (object_class, PROP_USERNAME, spec); spec = g_param_spec_string ("password", "password", "The password to authenticate with", NULL, G_PARAM_WRITABLE|G_PARAM_CONSTRUCT); g_object_class_install_property (object_class, PROP_PASSWORD, spec); spec = g_param_spec_object ("connection", "connection", "The Xmpp connection to user", WOCKY_TYPE_XMPP_CONNECTION, G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_CONNECTION, spec); spec = g_param_spec_object ("auth-registry", "Authentication Registry", "Authentication Registry", WOCKY_TYPE_AUTH_REGISTRY, G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY); g_object_class_install_property (object_class, PROP_AUTH_REGISTRY, spec); object_class->dispose = wocky_sasl_auth_dispose; object_class->finalize = wocky_sasl_auth_finalize; } void wocky_sasl_auth_dispose (GObject *object) { WockySaslAuth *self = WOCKY_SASL_AUTH (object); WockySaslAuthPrivate *priv = self->priv; if (priv->connection != NULL) g_object_unref (priv->connection); if (priv->auth_registry != NULL) g_object_unref (priv->auth_registry); if (G_OBJECT_CLASS (wocky_sasl_auth_parent_class)->dispose) G_OBJECT_CLASS (wocky_sasl_auth_parent_class)->dispose (object); } void wocky_sasl_auth_finalize (GObject *object) { WockySaslAuth *self = WOCKY_SASL_AUTH (object); WockySaslAuthPrivate *priv = self->priv; /* free any data held directly by the object here */ g_free (priv->server); g_free (priv->username); g_free (priv->password); G_OBJECT_CLASS (wocky_sasl_auth_parent_class)->finalize (object); } static void auth_reset (WockySaslAuth *sasl) { WockySaslAuthPrivate *priv = sasl->priv; g_free (priv->server); priv->server = NULL; if (priv->connection != NULL) { g_object_unref (priv->connection); priv->connection = NULL; } if (priv->cancel != NULL) { g_object_unref (priv->cancel); priv->cancel = NULL; } } static void auth_succeeded (WockySaslAuth *sasl) { WockySaslAuthPrivate *priv = sasl->priv; GSimpleAsyncResult *r; DEBUG ("Authentication succeeded"); auth_reset (sasl); r = priv->result; priv->result = NULL; g_simple_async_result_complete (r); g_object_unref (r); } static void auth_failed (WockySaslAuth *sasl, gint code, const gchar *format, ...) { gchar *message; va_list args; GSimpleAsyncResult *r; GError *error = NULL; WockySaslAuthPrivate *priv = sasl->priv; auth_reset (sasl); va_start (args, format); message = g_strdup_vprintf (format, args); va_end (args); DEBUG ("Authentication failed!: %s", message); r = priv->result; priv->result = NULL; error = g_error_new_literal (WOCKY_AUTH_ERROR, code, message); g_simple_async_result_set_from_error (r, error); wocky_auth_registry_failure (priv->auth_registry, error); g_simple_async_result_complete (r); g_object_unref (r); g_error_free (error); g_free (message); } static gboolean stream_error (WockySaslAuth *sasl, WockyStanza *stanza) { WockySaslAuthPrivate *priv = sasl->priv; GError *error = NULL; if (stanza == NULL) { auth_failed (sasl, WOCKY_AUTH_ERROR_CONNRESET, "Disconnected"); return TRUE; } if (wocky_stanza_extract_stream_error (stanza, &error)) { auth_failed (sasl, WOCKY_AUTH_ERROR_STREAM, "%s: %s", wocky_enum_to_nick (WOCKY_TYPE_XMPP_STREAM_ERROR, error->code), error->message); g_error_free (error); return TRUE; } if (g_cancellable_is_cancelled (priv->cancel)) { /* We got disconnected but we still had this stanza to process. Don't * bother with it. */ auth_failed (sasl, WOCKY_AUTH_ERROR_CONNRESET, "Disconnected"); return TRUE; } return FALSE; } WockySaslAuth * wocky_sasl_auth_new (const gchar *server, const gchar *username, const gchar *password, WockyXmppConnection *connection, WockyAuthRegistry *auth_registry) { return g_object_new (WOCKY_TYPE_SASL_AUTH, "server", server, "username", username, "password", password, "connection", connection, "auth-registry", auth_registry, NULL); } static GSList * wocky_sasl_auth_mechanisms_to_list (WockyNode *mechanisms) { GSList *result = NULL; WockyNode *mechanism; WockyNodeIter iter; if (mechanisms == NULL) return NULL; wocky_node_iter_init (&iter, mechanisms, "mechanism", NULL); while (wocky_node_iter_next (&iter, &mechanism)) result = g_slist_append (result, g_strdup (mechanism->content)); return result; } static void sasl_auth_got_failure (WockySaslAuth *sasl, WockyStanza *stanza, GError **error) { WockyNode *reason = NULL; if (wocky_stanza_get_top_node (stanza)->children != NULL) { /* TODO add a wocky xmpp node utility to either get the first child or * iterate the children list */ reason = (WockyNode *) wocky_stanza_get_top_node (stanza)->children->data; } /* TODO Handle the different error cases in a different way. i.e. * make it clear for the user if it's credentials were wrong, if the server * just has a temporary error or if the authentication procedure itself was * at fault (too weak, invalid mech etc) */ g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_FAILURE, "Authentication failed: %s", reason == NULL ? "Unknown reason" : reason->name); } static GString * wocky_sasl_auth_decode_challenge (const gchar *challenge) { gchar *challenge_str; GString *challenge_data; gsize len; if (challenge == NULL) return g_string_new_len ("", 0); challenge_str = (gchar *) g_base64_decode (challenge, &len); challenge_data = g_string_new_len (challenge_str, len); g_free (challenge_str); return challenge_data; } static gchar * wocky_sasl_auth_encode_response (const GString *response_data) { if (response_data != NULL && response_data->len > 0) return g_base64_encode ((guchar *) response_data->str, response_data->len); return NULL; } static void wocky_sasl_auth_success_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { WockySaslAuth *self = (WockySaslAuth *) user_data; WockySaslAuthPrivate *priv = self->priv; GError *error = NULL; if (!wocky_auth_registry_success_finish (priv->auth_registry, res, &error)) { auth_failed (self, error->code, error->message); g_error_free (error); } else { auth_succeeded (self); } } static void wocky_sasl_auth_response_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { WockySaslAuth *self = (WockySaslAuth *) user_data; WockySaslAuthPrivate *priv = self->priv; WockyStanza *response_stanza; GString *response_data = NULL; gchar *response; GError *error = NULL; if (!wocky_auth_registry_challenge_finish (priv->auth_registry, res, &response_data, &error)) { auth_failed (self, error->code, error->message); g_error_free (error); return; } response = wocky_sasl_auth_encode_response (response_data); response_stanza = wocky_stanza_new ("response", WOCKY_XMPP_NS_SASL_AUTH); wocky_node_set_content (wocky_stanza_get_top_node (response_stanza), response); /* FIXME handle send error */ wocky_xmpp_connection_send_stanza_async ( priv->connection, response_stanza, NULL, NULL, NULL); wocky_xmpp_connection_recv_stanza_async (priv->connection, NULL, sasl_auth_stanza_received, self); if (response_data != NULL) g_string_free (response_data, TRUE); g_free (response); g_object_unref (response_stanza); } static void wocky_sasl_auth_success_response_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { WockySaslAuth *self = (WockySaslAuth *) user_data; WockySaslAuthPrivate *priv = self->priv; GError *error = NULL; GString *response_data; if (!wocky_auth_registry_challenge_finish (priv->auth_registry, res, &response_data, &error)) { auth_failed (self, error->code, error->message); g_error_free (error); return; } if (response_data != NULL) { auth_failed (self, WOCKY_AUTH_ERROR_INVALID_REPLY, "Got success from the server while we still had more data to " "send"); g_string_free (response_data, TRUE); return; } wocky_auth_registry_success_async (priv->auth_registry, wocky_sasl_auth_success_cb, self); } static void sasl_auth_stanza_received (GObject *source, GAsyncResult *res, gpointer user_data) { WockySaslAuth *sasl = WOCKY_SASL_AUTH (user_data); WockySaslAuthPrivate *priv = sasl->priv; WockyStanza *stanza; GError *error = NULL; stanza = wocky_xmpp_connection_recv_stanza_finish ( WOCKY_XMPP_CONNECTION (priv->connection), res, NULL); if (stream_error (sasl, stanza)) return; if (wocky_strdiff ( wocky_node_get_ns (wocky_stanza_get_top_node (stanza)), WOCKY_XMPP_NS_SASL_AUTH)) { auth_failed (sasl, WOCKY_AUTH_ERROR_INVALID_REPLY, "Server sent a reply not in the %s namespace", WOCKY_XMPP_NS_SASL_AUTH); return; } /* If the SASL async result is _complete()d in the handler, the SASL object * * will be unref'd, which means the ref count could fall to zero while we * * are still using it. grab aref to it and drop it after we are sure that * * we don't need it anymore: */ g_object_ref (sasl); if (!wocky_strdiff (wocky_stanza_get_top_node (stanza)->name, "challenge")) { GString *challenge; challenge = wocky_sasl_auth_decode_challenge ( wocky_stanza_get_top_node (stanza)->content); wocky_auth_registry_challenge_async (priv->auth_registry, challenge, wocky_sasl_auth_response_cb, sasl); g_string_free (challenge, TRUE); } else if (!wocky_strdiff (wocky_stanza_get_top_node (stanza)->name, "success")) { if (wocky_stanza_get_top_node (stanza)->content != NULL) { GString *challenge; challenge = wocky_sasl_auth_decode_challenge ( wocky_stanza_get_top_node (stanza)->content); wocky_auth_registry_challenge_async (priv->auth_registry, challenge, wocky_sasl_auth_success_response_cb, sasl); g_string_free (challenge, TRUE); } else { wocky_auth_registry_success_async (priv->auth_registry, wocky_sasl_auth_success_cb, sasl); } } else if (!wocky_strdiff (wocky_stanza_get_top_node (stanza)->name, "failure")) { sasl_auth_got_failure (sasl, stanza, &error); g_assert (error != NULL); auth_failed (sasl, error->code, error->message); g_error_free (error); } else { auth_failed (sasl, WOCKY_AUTH_ERROR_INVALID_REPLY, "Server sent an invalid reply (%s)", wocky_stanza_get_top_node (stanza)->name); } g_object_unref (sasl); g_object_unref (stanza); return; } static void sasl_auth_stanza_sent (GObject *source, GAsyncResult *res, gpointer user_data) { GError *error = NULL; WockyXmppConnection *connection = WOCKY_XMPP_CONNECTION (source); WockySaslAuth *self = user_data; WockySaslAuthPrivate *priv = self->priv; if (!wocky_xmpp_connection_send_stanza_finish (connection, res, &error)) { auth_failed (self, error->code, error->message); g_error_free (error); return; } wocky_xmpp_connection_recv_stanza_async (priv->connection, priv->cancel, sasl_auth_stanza_received, self); } gboolean wocky_sasl_auth_authenticate_finish (WockySaslAuth *sasl, GAsyncResult *result, GError **error) { wocky_implement_finish_void (sasl, wocky_sasl_auth_authenticate_async); } static void wocky_sasl_auth_start_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { WockySaslAuth *self = (WockySaslAuth *) user_data; WockySaslAuthPrivate *priv = self->priv; WockyStanza *stanza; GError *error = NULL; WockyAuthRegistryStartData *start_data = NULL; if (!wocky_auth_registry_start_auth_finish (priv->auth_registry, res, &start_data, &error)) { auth_failed (self, error->code, error->message); g_error_free (error); return; } stanza = wocky_stanza_new ("auth", WOCKY_XMPP_NS_SASL_AUTH); /* google JID domain discovery - client sets a namespaced attribute */ wocky_node_set_attribute_ns (wocky_stanza_get_top_node (stanza), "client-uses-full-bind-result", "true", WOCKY_GOOGLE_NS_AUTH); if (start_data->initial_response != NULL) { gchar *initial_response_str = wocky_sasl_auth_encode_response ( start_data->initial_response); wocky_node_set_content ( wocky_stanza_get_top_node (stanza), initial_response_str); g_free (initial_response_str); } wocky_node_set_attribute (wocky_stanza_get_top_node (stanza), "mechanism", start_data->mechanism); wocky_xmpp_connection_send_stanza_async (priv->connection, stanza, priv->cancel, sasl_auth_stanza_sent, self); wocky_auth_registry_start_data_free (start_data); g_object_unref (stanza); } /* Initiate sasl auth. features should contain the stream features stanza as * receiver from the server */ void wocky_sasl_auth_authenticate_async (WockySaslAuth *sasl, WockyStanza *features, gboolean allow_plain, gboolean is_secure, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockySaslAuthPrivate *priv = sasl->priv; WockyNode *mech_node; GSList *mechanisms, *t; g_assert (sasl != NULL); g_assert (features != NULL); mech_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (features), "mechanisms", WOCKY_XMPP_NS_SASL_AUTH); mechanisms = wocky_sasl_auth_mechanisms_to_list (mech_node); if (G_UNLIKELY (mechanisms == NULL)) { g_simple_async_report_error_in_idle (G_OBJECT (sasl), callback, user_data, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NOT_SUPPORTED, "Server doesn't have any sasl mechanisms"); goto out; } priv->result = g_simple_async_result_new (G_OBJECT (sasl), callback, user_data, wocky_sasl_auth_authenticate_async); if (cancellable != NULL) priv->cancel = g_object_ref (cancellable); wocky_auth_registry_start_auth_async (priv->auth_registry, mechanisms, allow_plain, is_secure, priv->username, priv->password, priv->server, NULL, wocky_sasl_auth_start_cb, sasl); out: for (t = mechanisms ; t != NULL; t = g_slist_next (t)) { g_free (t->data); } g_slist_free (mechanisms); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jabber-auth-password.c0000664000175000017500000000734412005516162027364 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-jabber-auth-password.h" #include "wocky-auth-registry.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_AUTH #include "wocky-debug-internal.h" static void auth_handler_iface_init (gpointer g_iface); G_DEFINE_TYPE_WITH_CODE (WockyJabberAuthPassword, wocky_jabber_auth_password, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (WOCKY_TYPE_AUTH_HANDLER, auth_handler_iface_init)) enum { PROP_PASSWORD = 1 }; struct _WockyJabberAuthPasswordPrivate { gchar *password; }; static void wocky_jabber_auth_password_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyJabberAuthPassword *self = WOCKY_JABBER_AUTH_PASSWORD (object); WockyJabberAuthPasswordPrivate *priv = self->priv; switch (property_id) { case PROP_PASSWORD: g_value_set_string (value, priv->password); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void wocky_jabber_auth_password_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyJabberAuthPassword *self = WOCKY_JABBER_AUTH_PASSWORD (object); WockyJabberAuthPasswordPrivate *priv = self->priv; switch (property_id) { case PROP_PASSWORD: g_free (priv->password); priv->password = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void wocky_jabber_auth_password_dispose (GObject *object) { WockyJabberAuthPassword *self = WOCKY_JABBER_AUTH_PASSWORD (object); WockyJabberAuthPasswordPrivate *priv = self->priv; g_free (priv->password); G_OBJECT_CLASS (wocky_jabber_auth_password_parent_class)->dispose (object); } static void wocky_jabber_auth_password_class_init (WockyJabberAuthPasswordClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (WockyJabberAuthPasswordPrivate)); object_class->get_property = wocky_jabber_auth_password_get_property; object_class->set_property = wocky_jabber_auth_password_set_property; object_class->dispose = wocky_jabber_auth_password_dispose; g_object_class_install_property (object_class, PROP_PASSWORD, g_param_spec_string ("password", "password", "The password to authenticate with", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); } static gboolean password_initial_response (WockyAuthHandler *handler, GString **initial_data, GError **error); static void auth_handler_iface_init (gpointer g_iface) { WockyAuthHandlerIface *iface = g_iface; iface->mechanism = WOCKY_AUTH_MECH_JABBER_PASSWORD; iface->plain = TRUE; iface->initial_response_func = password_initial_response; } static void wocky_jabber_auth_password_init (WockyJabberAuthPassword *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE ( self, WOCKY_TYPE_JABBER_AUTH_PASSWORD, WockyJabberAuthPasswordPrivate); } WockyJabberAuthPassword * wocky_jabber_auth_password_new (const gchar *password) { return g_object_new (WOCKY_TYPE_JABBER_AUTH_PASSWORD, "password", password, NULL); } static gboolean password_initial_response (WockyAuthHandler *handler, GString **initial_data, GError **error) { WockyJabberAuthPassword *self = WOCKY_JABBER_AUTH_PASSWORD (handler); WockyJabberAuthPasswordPrivate *priv = self->priv; if (priv->password == NULL) { g_set_error (error, WOCKY_AUTH_ERROR, WOCKY_AUTH_ERROR_NO_CREDENTIALS, "No password provided"); return FALSE; } DEBUG ("Got password"); *initial_data = g_string_new (priv->password); return TRUE; } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-caps-cache.h0000664000175000017500000000521311720661341025330 0ustar00cassidycassidy00000000000000/* * wocky-caps-cache.h - Header for WockyCapsCache * Copyright (C) 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_CAPS_CACHE_H__ #define __WOCKY_CAPS_CACHE_H__ #include #include "wocky-node-tree.h" G_BEGIN_DECLS /** * WockyCapsCache: * * An object providing a permanent cache for capabilities. */ typedef struct _WockyCapsCache WockyCapsCache; /** * WockyCapsCacheClass: * * The class of a #WockyCapsCache. */ typedef struct _WockyCapsCacheClass WockyCapsCacheClass; typedef struct _WockyCapsCachePrivate WockyCapsCachePrivate; #define WOCKY_TYPE_CAPS_CACHE wocky_caps_cache_get_type() #define WOCKY_CAPS_CACHE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), WOCKY_TYPE_CAPS_CACHE, \ WockyCapsCache)) #define WOCKY_CAPS_CACHE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), WOCKY_TYPE_CAPS_CACHE, \ WockyCapsCacheClass)) #define WOCKY_IS_CAPS_CACHE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WOCKY_TYPE_CAPS_CACHE)) #define WOCKY_IS_CAPS_CACHE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), WOCKY_TYPE_CAPS_CACHE)) #define WOCKY_CAPS_CACHE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_CAPS_CACHE, \ WockyCapsCacheClass)) struct _WockyCapsCache { /**/ GObject parent; WockyCapsCachePrivate *priv; }; struct _WockyCapsCacheClass { /**/ GObjectClass parent_class; }; GType wocky_caps_cache_get_type (void); WockyNodeTree *wocky_caps_cache_lookup (WockyCapsCache *self, const gchar *node); void wocky_caps_cache_insert (WockyCapsCache *self, const gchar *node, WockyNodeTree *query_node); WockyCapsCache * wocky_caps_cache_new (const gchar *path); WockyCapsCache * wocky_caps_cache_dup_shared (void); void wocky_caps_cache_free_shared (void); G_END_DECLS #endif /* ifndef __WOCKY_CAPS_CACHE_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jingle-transport-rawudp.c0000664000175000017500000003014112212322440030123 0ustar00cassidycassidy00000000000000/* * wocky-jingle-transport-rawudp.c - Source for WockyJingleTransportRawUdp * * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "wocky-jingle-transport-rawudp.h" #include #include #include #include #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_JINGLE #include "wocky-debug-internal.h" #include "wocky-jingle-content.h" #include "wocky-jingle-factory.h" #include "wocky-jingle-session.h" #include "wocky-namespaces.h" static void transport_iface_init (gpointer g_iface, gpointer iface_data); G_DEFINE_TYPE_WITH_CODE (WockyJingleTransportRawUdp, wocky_jingle_transport_rawudp, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (WOCKY_TYPE_JINGLE_TRANSPORT_IFACE, transport_iface_init)); /* signal enum */ enum { NEW_CANDIDATES, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; /* properties */ enum { PROP_CONTENT = 1, PROP_TRANSPORT_NS, PROP_STATE, LAST_PROPERTY }; struct _WockyJingleTransportRawUdpPrivate { WockyJingleContent *content; WockyJingleTransportState state; gchar *transport_ns; GList *local_candidates; GList *remote_candidates; gboolean dispose_has_run; }; static void wocky_jingle_transport_rawudp_init (WockyJingleTransportRawUdp *obj) { WockyJingleTransportRawUdpPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, WOCKY_TYPE_JINGLE_TRANSPORT_RAWUDP, WockyJingleTransportRawUdpPrivate); obj->priv = priv; priv->dispose_has_run = FALSE; } static void wocky_jingle_transport_rawudp_dispose (GObject *object) { WockyJingleTransportRawUdp *trans = WOCKY_JINGLE_TRANSPORT_RAWUDP (object); WockyJingleTransportRawUdpPrivate *priv = trans->priv; if (priv->dispose_has_run) return; DEBUG ("dispose called"); priv->dispose_has_run = TRUE; jingle_transport_free_candidates (priv->remote_candidates); priv->remote_candidates = NULL; jingle_transport_free_candidates (priv->local_candidates); priv->local_candidates = NULL; g_free (priv->transport_ns); priv->transport_ns = NULL; if (G_OBJECT_CLASS (wocky_jingle_transport_rawudp_parent_class)->dispose) G_OBJECT_CLASS (wocky_jingle_transport_rawudp_parent_class)->dispose (object); } static void wocky_jingle_transport_rawudp_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyJingleTransportRawUdp *trans = WOCKY_JINGLE_TRANSPORT_RAWUDP (object); WockyJingleTransportRawUdpPrivate *priv = trans->priv; switch (property_id) { case PROP_CONTENT: g_value_set_object (value, priv->content); break; case PROP_TRANSPORT_NS: g_value_set_string (value, priv->transport_ns); break; case PROP_STATE: g_value_set_uint (value, priv->state); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_jingle_transport_rawudp_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyJingleTransportRawUdp *trans = WOCKY_JINGLE_TRANSPORT_RAWUDP (object); WockyJingleTransportRawUdpPrivate *priv = trans->priv; switch (property_id) { case PROP_CONTENT: priv->content = g_value_get_object (value); break; case PROP_TRANSPORT_NS: g_free (priv->transport_ns); priv->transport_ns = g_value_dup_string (value); break; case PROP_STATE: priv->state = g_value_get_uint (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_jingle_transport_rawudp_class_init (WockyJingleTransportRawUdpClass *cls) { GObjectClass *object_class = G_OBJECT_CLASS (cls); GParamSpec *param_spec; g_type_class_add_private (cls, sizeof (WockyJingleTransportRawUdpPrivate)); object_class->get_property = wocky_jingle_transport_rawudp_get_property; object_class->set_property = wocky_jingle_transport_rawudp_set_property; object_class->dispose = wocky_jingle_transport_rawudp_dispose; /* property definitions */ param_spec = g_param_spec_object ("content", "WockyJingleContent object", "Jingle content object using this transport.", WOCKY_TYPE_JINGLE_CONTENT, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_CONTENT, param_spec); param_spec = g_param_spec_string ("transport-ns", "Transport namespace", "Namespace identifying the transport type.", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_TRANSPORT_NS, param_spec); param_spec = g_param_spec_uint ("state", "Connection state for the transport.", "Enum specifying the connection state of the transport.", WOCKY_JINGLE_TRANSPORT_STATE_DISCONNECTED, WOCKY_JINGLE_TRANSPORT_STATE_CONNECTED, WOCKY_JINGLE_TRANSPORT_STATE_DISCONNECTED, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_STATE, param_spec); /* signal definitions */ signals[NEW_CANDIDATES] = g_signal_new ( "new-candidates", G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); } static void parse_candidates (WockyJingleTransportIface *obj, WockyNode *transport_node, GError **error) { WockyJingleTransportRawUdp *t = WOCKY_JINGLE_TRANSPORT_RAWUDP (obj); WockyJingleTransportRawUdpPrivate *priv = t->priv; GList *candidates = NULL; WockyNodeIter i; WockyNode *node; DEBUG ("called"); if (priv->remote_candidates != NULL) { DEBUG ("already have raw udp candidates, ignoring extra ones"); return; } wocky_node_iter_init (&i, transport_node, "candidate", NULL); while (wocky_node_iter_next (&i, &node)) { const gchar *id, *ip, *str; guint port, gen, component = 1; WockyJingleCandidate *c; str = wocky_node_get_attribute (node, "component"); if (str != NULL) component = atoi (str); if ((component != 1) && (component != 2)) { DEBUG ("Ignoring non-RTP/RTCP component %d", component); continue; } id = wocky_node_get_attribute (node, "id"); if (id == NULL) break; ip = wocky_node_get_attribute (node, "ip"); if (ip == NULL) break; str = wocky_node_get_attribute (node, "port"); if (str == NULL) break; port = atoi (str); str = wocky_node_get_attribute (node, "generation"); if (str == NULL) break; gen = atoi (str); c = wocky_jingle_candidate_new (WOCKY_JINGLE_TRANSPORT_PROTOCOL_UDP, WOCKY_JINGLE_CANDIDATE_TYPE_LOCAL, id, component, ip, port, gen, 1.0, NULL, NULL, 0); candidates = g_list_append (candidates, c); } if (wocky_node_iter_next (&i, NULL)) { DEBUG ("not all nodes were processed, reporting error"); /* rollback these */ jingle_transport_free_candidates (candidates); g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, "invalid candidate"); return; } DEBUG ("emitting %d new remote candidates", g_list_length (candidates)); g_signal_emit (obj, signals[NEW_CANDIDATES], 0, candidates); priv->remote_candidates = candidates; } static void inject_candidates (WockyJingleTransportIface *obj, WockyNode *transport_node) { WockyJingleTransportRawUdp *self = WOCKY_JINGLE_TRANSPORT_RAWUDP (obj); WockyJingleTransportRawUdpPrivate *priv = self->priv; WockyJingleCandidate *c; GList *li; gchar port_str[16], comp_str[16]; WockyNode *cnode; /* If we don't have the local candidates yet, we should've waited with * the session initiation, or can_accept would have returned FALSE. */ g_assert (priv->local_candidates != NULL); for (li = priv->local_candidates; li != NULL; li = li->next) { c = (WockyJingleCandidate *) li->data; sprintf (port_str, "%d", c->port); sprintf (comp_str, "%d", c->component); cnode = wocky_node_add_child (transport_node, "candidate"); wocky_node_set_attributes (cnode, "ip", c->address, "port", port_str, "generation", "0", "id", c->id, "component", comp_str, NULL); } } /* Takes in a list of slice-allocated WockyJingleCandidate structs */ static void new_local_candidates (WockyJingleTransportIface *obj, GList *new_candidates) { WockyJingleTransportRawUdp *transport = WOCKY_JINGLE_TRANSPORT_RAWUDP (obj); WockyJingleTransportRawUdpPrivate *priv = transport->priv; if (priv->local_candidates != NULL) { DEBUG ("ignoring new local candidates for RAW UDP"); jingle_transport_free_candidates (new_candidates); return; } priv->local_candidates = new_candidates; } static gboolean can_accept (WockyJingleTransportIface *iface) { WockyJingleTransportRawUdp *self = WOCKY_JINGLE_TRANSPORT_RAWUDP (iface); return (self->priv->local_candidates != NULL); } static GList * get_local_candidates (WockyJingleTransportIface *iface) { WockyJingleTransportRawUdp *transport = WOCKY_JINGLE_TRANSPORT_RAWUDP (iface); WockyJingleTransportRawUdpPrivate *priv = transport->priv; return priv->local_candidates; } static GList * get_remote_candidates (WockyJingleTransportIface *iface) { WockyJingleTransportRawUdp *transport = WOCKY_JINGLE_TRANSPORT_RAWUDP (iface); WockyJingleTransportRawUdpPrivate *priv = transport->priv; return priv->remote_candidates; } static WockyJingleTransportType get_transport_type (void) { DEBUG ("called"); return JINGLE_TRANSPORT_RAW_UDP; } static void transport_iface_init (gpointer g_iface, gpointer iface_data) { WockyJingleTransportIfaceClass *klass = (WockyJingleTransportIfaceClass *) g_iface; klass->parse_candidates = parse_candidates; klass->new_local_candidates = new_local_candidates; klass->inject_candidates = inject_candidates; /* Not implementing _send: XEP-0177 says that the candidates live in * content-{add,accept}, not in transport-info. */ klass->can_accept = can_accept; klass->get_remote_candidates = get_remote_candidates; klass->get_local_candidates = get_local_candidates; klass->get_transport_type = get_transport_type; } void jingle_transport_rawudp_register (WockyJingleFactory *factory) { wocky_jingle_factory_register_transport (factory, WOCKY_XMPP_NS_JINGLE_TRANSPORT_RAWUDP, WOCKY_TYPE_JINGLE_TRANSPORT_RAWUDP); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-openssl-dh2048.c0000664000175000017500000000343612005516162025730 0ustar00cassidycassidy00000000000000#ifdef HAVE_CONFIG_H #include "config.h" #endif #ifndef HEADER_DH_H #include #endif DH *get_dh2048(void); DH *get_dh2048(void) { static unsigned char dh2048_p[]={ 0xF6,0x42,0x57,0xB7,0x08,0x7F,0x08,0x17,0x72,0xA2,0xBA,0xD6, 0xA9,0x42,0xF3,0x05,0xE8,0xF9,0x53,0x11,0x39,0x4F,0xB6,0xF1, 0x6E,0xB9,0x4B,0x38,0x20,0xDA,0x01,0xA7,0x56,0xA3,0x14,0xE9, 0x8F,0x40,0x55,0xF3,0xD0,0x07,0xC6,0xCB,0x43,0xA9,0x94,0xAD, 0xF7,0x4C,0x64,0x86,0x49,0xF8,0x0C,0x83,0xBD,0x65,0xE9,0x17, 0xD4,0xA1,0xD3,0x50,0xF8,0xF5,0x59,0x5F,0xDC,0x76,0x52,0x4F, 0x3D,0x3D,0x8D,0xDB,0xCE,0x99,0xE1,0x57,0x92,0x59,0xCD,0xFD, 0xB8,0xAE,0x74,0x4F,0xC5,0xFC,0x76,0xBC,0x83,0xC5,0x47,0x30, 0x61,0xCE,0x7C,0xC9,0x66,0xFF,0x15,0xF9,0xBB,0xFD,0x91,0x5E, 0xC7,0x01,0xAA,0xD3,0x5B,0x9E,0x8D,0xA0,0xA5,0x72,0x3A,0xD4, 0x1A,0xF0,0xBF,0x46,0x00,0x58,0x2B,0xE5,0xF4,0x88,0xFD,0x58, 0x4E,0x49,0xDB,0xCD,0x20,0xB4,0x9D,0xE4,0x91,0x07,0x36,0x6B, 0x33,0x6C,0x38,0x0D,0x45,0x1D,0x0F,0x7C,0x88,0xB3,0x1C,0x7C, 0x5B,0x2D,0x8E,0xF6,0xF3,0xC9,0x23,0xC0,0x43,0xF0,0xA5,0x5B, 0x18,0x8D,0x8E,0xBB,0x55,0x8C,0xB8,0x5D,0x38,0xD3,0x34,0xFD, 0x7C,0x17,0x57,0x43,0xA3,0x1D,0x18,0x6C,0xDE,0x33,0x21,0x2C, 0xB5,0x2A,0xFF,0x3C,0xE1,0xB1,0x29,0x40,0x18,0x11,0x8D,0x7C, 0x84,0xA7,0x0A,0x72,0xD6,0x86,0xC4,0x03,0x19,0xC8,0x07,0x29, 0x7A,0xCA,0x95,0x0C,0xD9,0x96,0x9F,0xAB,0xD0,0x0A,0x50,0x9B, 0x02,0x46,0xD3,0x08,0x3D,0x66,0xA4,0x5D,0x41,0x9F,0x9C,0x7C, 0xBD,0x89,0x4B,0x22,0x19,0x26,0xBA,0xAB,0xA2,0x5E,0xC3,0x55, 0xE9,0x32,0x0B,0x3B, }; static unsigned char dh2048_g[]={ 0x02, }; DH *dh; if ((dh=DH_new()) == NULL) return(NULL); dh->p=BN_bin2bn(dh2048_p,sizeof(dh2048_p),NULL); dh->g=BN_bin2bn(dh2048_g,sizeof(dh2048_g),NULL); if ((dh->p == NULL) || (dh->g == NULL)) { DH_free(dh); return(NULL); } return(dh); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-porter.c0000664000175000017500000007673212212322440024654 0ustar00cassidycassidy00000000000000/* * wocky-porter.c - Source for WockyPorter * Copyright (C) 2009-2011 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-porter.h" #include "wocky-signals-marshal.h" #include "wocky-xmpp-connection.h" G_DEFINE_INTERFACE (WockyPorter, wocky_porter, G_TYPE_OBJECT) static void wocky_porter_default_init (WockyPorterInterface *iface) { GType iface_type = G_TYPE_FROM_INTERFACE (iface); static gsize initialization_value = 0; GParamSpec *spec; if (g_once_init_enter (&initialization_value)) { /** * WockyPorter:connection: * * The underlying #WockyXmppConnection wrapped by the #WockyPorter */ spec = g_param_spec_object ("connection", "XMPP connection", "the XMPP connection used by this porter", WOCKY_TYPE_XMPP_CONNECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (iface, spec); /** * WockyPorter:full-jid: * * The user's full JID (node@domain/resource). */ spec = g_param_spec_string ("full-jid", "Full JID", "The user's own full JID (node@domain/resource)", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (iface, spec); /** * WockyPorter:bare-jid: * * The user's bare JID (node@domain). */ spec = g_param_spec_string ("bare-jid", "Bare JID", "The user's own bare JID (node@domain)", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (iface, spec); /** * WockyPorter:resource: * * The resource part of the user's full JID, or %NULL if their full JID does * not contain a resource at all. */ spec = g_param_spec_string ("resource", "Resource", "The user's resource", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_interface_install_property (iface, spec); /** * WockyPorter::remote-closed: * @porter: the object on which the signal is emitted * * The ::remote-closed signal is emitted when the other side closed the XMPP * stream. */ g_signal_new ("remote-closed", iface_type, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * WockyPorter::remote-error: * @porter: the object on which the signal is emitted * @domain: error domain (a #GQuark) * @code: error code * @message: human-readable informative error message * * The ::remote-error signal is emitted when an error has been detected * on the XMPP stream. */ g_signal_new ("remote-error", iface_type, G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__UINT_INT_STRING, G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_INT, G_TYPE_STRING); /** * WockyPorter::closing: * @porter: the object on which the signal is emitted * * The ::closing signal is emitted when the #WockyPorter starts to close its * XMPP connection. Once this signal has been emitted, the #WockyPorter * can't be used to send stanzas any more. */ g_signal_new ("closing", iface_type, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * WockyPorter::sending: * @porter: the object on which the signal is emitted * @stanza: the #WockyStanza being sent, or %NULL if @porter is just * sending whitespace * * The ::sending signal is emitted whenever #WockyPorter sends data * on the XMPP connection. */ g_signal_new ("sending", iface_type, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, WOCKY_TYPE_STANZA); g_once_init_leave (&initialization_value, 1); } } /** * wocky_porter_error_quark: * * Get the error quark used by the porter. * * Returns: the quark for porter errors. */ GQuark wocky_porter_error_quark (void) { static GQuark quark = 0; if (quark == 0) quark = g_quark_from_static_string ("wocky-porter-error"); return quark; } /** * wocky_porter_get_full_jid: (skip) * @self: a porter * * * * Returns: (transfer none): the value of #WockyPorter:full-jid */ const gchar * wocky_porter_get_full_jid (WockyPorter *self) { WockyPorterInterface *iface; g_return_val_if_fail (WOCKY_IS_PORTER (self), NULL); iface = WOCKY_PORTER_GET_INTERFACE (self); g_assert (iface->get_full_jid != NULL); return iface->get_full_jid (self); } /** * wocky_porter_get_bare_jid: (skip) * @self: a porter * * * * Returns: (transfer none): the value of #WockyPorter:bare-jid */ const gchar * wocky_porter_get_bare_jid (WockyPorter *self) { WockyPorterInterface *iface; g_return_val_if_fail (WOCKY_IS_PORTER (self), NULL); iface = WOCKY_PORTER_GET_INTERFACE (self); g_assert (iface->get_bare_jid != NULL); return iface->get_bare_jid (self); } /** * wocky_porter_get_resource: (skip) * @self: a porter * * * * Returns: (transfer none): the value of #WockyPorter:resource */ const gchar * wocky_porter_get_resource (WockyPorter *self) { WockyPorterInterface *iface; g_return_val_if_fail (WOCKY_IS_PORTER (self), NULL); iface = WOCKY_PORTER_GET_INTERFACE (self); g_assert (iface->get_resource != NULL); return iface->get_resource (self); } /** * wocky_porter_start: * @porter: a #WockyPorter * * Start a #WockyPorter to make it read and dispatch incoming stanzas. */ void wocky_porter_start (WockyPorter *self) { WockyPorterInterface *iface; g_return_if_fail (WOCKY_IS_PORTER (self)); iface = WOCKY_PORTER_GET_INTERFACE (self); g_assert (iface->start != NULL); iface->start (self); } /** * wocky_porter_send_async: * @porter: a #WockyPorter * @stanza: the #WockyStanza to send * @cancellable: optional #GCancellable object, %NULL to ignore * @callback: callback to call when the request is satisfied * @user_data: the data to pass to callback function * * Request asynchronous sending of a #WockyStanza. * When the stanza has been sent callback will be called. * You can then call wocky_porter_send_finish() to get the result * of the operation. */ void wocky_porter_send_async (WockyPorter *self, WockyStanza *stanza, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyPorterInterface *iface; g_return_if_fail (WOCKY_IS_PORTER (self)); iface = WOCKY_PORTER_GET_INTERFACE (self); g_assert (iface->send_async != NULL); iface->send_async (self, stanza, cancellable, callback, user_data); } /** * wocky_porter_send_finish: * @porter: a #WockyPorter * @result: a #GAsyncResult * @error: a #GError location to store the error occuring, or %NULL to * ignore. * * Finishes sending a #WockyStanza. * * Returns: %TRUE on success or %FALSE on error. */ gboolean wocky_porter_send_finish (WockyPorter *self, GAsyncResult *result, GError **error) { WockyPorterInterface *iface; g_return_val_if_fail (WOCKY_IS_PORTER (self), FALSE); iface = WOCKY_PORTER_GET_INTERFACE (self); g_assert (iface->send_finish != NULL); return iface->send_finish (self, result, error); } /** * wocky_porter_send: * @porter: a #WockyPorter * @stanza: the #WockyStanza to send * * Send a #WockyStanza. This is a convenient function to not have to * call wocky_porter_send_async() with lot of %NULL arguments if you * don't care to know when the stanza has been actually sent. */ void wocky_porter_send (WockyPorter *porter, WockyStanza *stanza) { wocky_porter_send_async (porter, stanza, NULL, NULL, NULL); } /** * wocky_porter_register_handler_from_va: * @self: A #WockyPorter instance (passed to @callback). * @type: The type of stanza to be handled, or WOCKY_STANZA_TYPE_NONE to match * any type of stanza. * @sub_type: The subtype of stanza to be handled, or * WOCKY_STANZA_SUB_TYPE_NONE to match any type of stanza. * @from: the JID whose messages this handler is intended for (may not be * %NULL) * @priority: a priority between %WOCKY_PORTER_HANDLER_PRIORITY_MIN and * %WOCKY_PORTER_HANDLER_PRIORITY_MAX (often * %WOCKY_PORTER_HANDLER_PRIORITY_NORMAL). Handlers with a higher priority * (larger number) are called first. * @callback: A #WockyPorterHandlerFunc, which should return %FALSE to decline * the stanza (Wocky will continue to the next handler, if any), or %TRUE to * stop further processing. * @user_data: Passed to @callback. * @ap: a wocky_stanza_build() specification. The handler * will match a stanza only if the stanza received is a superset of the one * passed to this function, as per wocky_node_is_superset(). * * A va_list version of wocky_porter_register_handler_from(); see * that function for more details. * * Returns: a non-zero ID for use with wocky_porter_unregister_handler(). */ guint wocky_porter_register_handler_from_va (WockyPorter *self, WockyStanzaType type, WockyStanzaSubType sub_type, const gchar *from, guint priority, WockyPorterHandlerFunc callback, gpointer user_data, va_list ap) { guint ret; WockyStanza *stanza; g_return_val_if_fail (WOCKY_IS_PORTER (self), 0); g_return_val_if_fail (from != NULL, 0); if (type == WOCKY_STANZA_TYPE_NONE) { stanza = NULL; g_return_val_if_fail ( (va_arg (ap, WockyNodeBuildTag) == 0) && "Pattern-matching is not supported when matching stanzas " "of any type", 0); } else { stanza = wocky_stanza_build_va (type, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, ap); g_assert (stanza != NULL); } ret = wocky_porter_register_handler_from_by_stanza (self, type, sub_type, from, priority, callback, user_data, stanza); if (stanza != NULL) g_object_unref (stanza); return ret; } /** * wocky_porter_register_handler_from_by_stanza: * @self: A #WockyPorter instance (passed to @callback). * @type: The type of stanza to be handled, or WOCKY_STANZA_TYPE_NONE to match * any type of stanza. * @sub_type: The subtype of stanza to be handled, or * WOCKY_STANZA_SUB_TYPE_NONE to match any type of stanza. * @from: the JID whose messages this handler is intended for (may not be * %NULL) * @priority: a priority between %WOCKY_PORTER_HANDLER_PRIORITY_MIN and * %WOCKY_PORTER_HANDLER_PRIORITY_MAX (often * %WOCKY_PORTER_HANDLER_PRIORITY_NORMAL). Handlers with a higher priority * (larger number) are called first. * @callback: A #WockyPorterHandlerFunc, which should return %FALSE to decline * the stanza (Wocky will continue to the next handler, if any), or %TRUE to * stop further processing. * @user_data: Passed to @callback. * @stanza: a #WockyStanza. The handler will match a stanza only if * the stanza received is a superset of the one passed to this * function, as per wocky_node_is_superset(). * * A #WockyStanza version of wocky_porter_register_handler_from(); see * that function for more details. * * Returns: a non-zero ID for use with wocky_porter_unregister_handler(). */ guint wocky_porter_register_handler_from_by_stanza (WockyPorter *self, WockyStanzaType type, WockyStanzaSubType sub_type, const gchar *from, guint priority, WockyPorterHandlerFunc callback, gpointer user_data, WockyStanza *stanza) { WockyPorterInterface *iface; g_return_val_if_fail (WOCKY_IS_PORTER (self), 0); g_return_val_if_fail (from != NULL, 0); if (type == WOCKY_STANZA_TYPE_NONE) g_return_val_if_fail (stanza == NULL, 0); else g_return_val_if_fail (WOCKY_IS_STANZA (stanza), 0); iface = WOCKY_PORTER_GET_INTERFACE (self); g_assert (iface->register_handler_from_by_stanza != NULL); return iface->register_handler_from_by_stanza (self, type, sub_type, from, priority, callback, user_data, stanza); } /** * wocky_porter_register_handler_from: * @self: A #WockyPorter instance (passed to @callback). * @type: The type of stanza to be handled, or WOCKY_STANZA_TYPE_NONE to match * any type of stanza. * @sub_type: The subtype of stanza to be handled, or * WOCKY_STANZA_SUB_TYPE_NONE to match any type of stanza. * @from: the JID whose messages this handler is intended for (may not be * %NULL) * @priority: a priority between %WOCKY_PORTER_HANDLER_PRIORITY_MIN and * %WOCKY_PORTER_HANDLER_PRIORITY_MAX (often * %WOCKY_PORTER_HANDLER_PRIORITY_NORMAL). Handlers with a higher priority * (larger number) are called first. * @callback: A #WockyPorterHandlerFunc, which should return %FALSE to decline * the stanza (Wocky will continue to the next handler, if any), or %TRUE to * stop further processing. * @user_data: Passed to @callback. * @...: a wocky_stanza_build() specification. The handler * will match a stanza only if the stanza received is a superset of the one * passed to this function, as per wocky_node_is_superset(). * * Register a new stanza handler. * Stanza handlers are called when the Porter receives a new stanza matching * the rules of the handler. Matching handlers are sorted by priority and are * called until one claims to have handled the stanza (by returning %TRUE). * * If @from is a bare JID, then the resource of the JID in the from attribute * will be ignored: In other words, a handler registered against a bare JID * will match all stanzas from a JID with the same node * and domain: * "foo@bar.org" will match * "foo@bar.org", * "foo@bar.org/moose" and so forth. * * To register an IQ handler from Juliet for all the Jingle stanzas related * to one Jingle session: * * |[ * id = wocky_porter_register_handler_from (porter, * WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, * "juliet@example.com/Balcony", * WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, * jingle_cb, * '(', "jingle", * ':', "urn:xmpp:jingle:1", * '@', "sid", "my_sid", * ')', NULL); * ]| * * To match stanzas from any sender, see * wocky_porter_register_handler_from_anyone(). If the porter is a * #WockyC2SPorter, one can match stanzas sent by the server; see * wocky_c2s_porter_register_handler_from_server(). * * Returns: a non-zero ID for use with wocky_porter_unregister_handler(). */ guint wocky_porter_register_handler_from (WockyPorter *self, WockyStanzaType type, WockyStanzaSubType sub_type, const gchar *from, guint priority, WockyPorterHandlerFunc callback, gpointer user_data, ...) { va_list ap; guint ret; g_return_val_if_fail (WOCKY_IS_PORTER (self), 0); g_return_val_if_fail (from != NULL, 0); va_start (ap, user_data); ret = wocky_porter_register_handler_from_va (self, type, sub_type, from, priority, callback, user_data, ap); va_end (ap); return ret; } /** * wocky_porter_register_handler_from_anyone_va: * @self: A #WockyPorter instance (passed to @callback). * @type: The type of stanza to be handled, or WOCKY_STANZA_TYPE_NONE to match * any type of stanza. * @sub_type: The subtype of stanza to be handled, or * WOCKY_STANZA_SUB_TYPE_NONE to match any type of stanza. * @priority: a priority between %WOCKY_PORTER_HANDLER_PRIORITY_MIN and * %WOCKY_PORTER_HANDLER_PRIORITY_MAX (often * %WOCKY_PORTER_HANDLER_PRIORITY_NORMAL). Handlers with a higher priority * (larger number) are called first. * @callback: A #WockyPorterHandlerFunc, which should return %FALSE to decline * the stanza (Wocky will continue to the next handler, if any), or %TRUE to * stop further processing. * @user_data: Passed to @callback. * @ap: a wocky_stanza_build() specification. The handler * will match a stanza only if the stanza received is a superset of the one * passed to this function, as per wocky_node_is_superset(). * * A va_list version of * wocky_porter_register_handler_from_anyone(); see that function for more * details. * * Returns: a non-zero ID for use with wocky_porter_unregister_handler(). */ guint wocky_porter_register_handler_from_anyone_va ( WockyPorter *self, WockyStanzaType type, WockyStanzaSubType sub_type, guint priority, WockyPorterHandlerFunc callback, gpointer user_data, va_list ap) { guint ret; WockyStanza *stanza; g_return_val_if_fail (WOCKY_IS_PORTER (self), 0); if (type == WOCKY_STANZA_TYPE_NONE) { stanza = NULL; g_return_val_if_fail ( (va_arg (ap, WockyNodeBuildTag) == 0) && "Pattern-matching is not supported when matching stanzas " "of any type", 0); } else { stanza = wocky_stanza_build_va (type, WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, ap); g_assert (stanza != NULL); } ret = wocky_porter_register_handler_from_anyone_by_stanza (self, type, sub_type, priority, callback, user_data, stanza); if (stanza != NULL) g_object_unref (stanza); return ret; } /** * wocky_porter_register_handler_from_anyone_by_stanza: * @self: A #WockyPorter instance (passed to @callback). * @type: The type of stanza to be handled, or WOCKY_STANZA_TYPE_NONE to match * any type of stanza. * @sub_type: The subtype of stanza to be handled, or * WOCKY_STANZA_SUB_TYPE_NONE to match any type of stanza. * @priority: a priority between %WOCKY_PORTER_HANDLER_PRIORITY_MIN and * %WOCKY_PORTER_HANDLER_PRIORITY_MAX (often * %WOCKY_PORTER_HANDLER_PRIORITY_NORMAL). Handlers with a higher priority * (larger number) are called first. * @callback: A #WockyPorterHandlerFunc, which should return %FALSE to decline * the stanza (Wocky will continue to the next handler, if any), or %TRUE to * stop further processing. * @user_data: Passed to @callback. * @stanza: a #WockyStanza. The handler will match a stanza only if * the stanza received is a superset of the one passed to this * function, as per wocky_node_is_superset(). * * A #WockyStanza version of * wocky_porter_register_handler_from_anyone(); see that function for * more details. * * Returns: a non-zero ID for use with wocky_porter_unregister_handler(). */ guint wocky_porter_register_handler_from_anyone_by_stanza ( WockyPorter *self, WockyStanzaType type, WockyStanzaSubType sub_type, guint priority, WockyPorterHandlerFunc callback, gpointer user_data, WockyStanza *stanza) { WockyPorterInterface *iface; g_return_val_if_fail (WOCKY_IS_PORTER (self), 0); if (type == WOCKY_STANZA_TYPE_NONE) g_return_val_if_fail (stanza == NULL, 0); else g_return_val_if_fail (WOCKY_IS_STANZA (stanza), 0); iface = WOCKY_PORTER_GET_INTERFACE (self); g_assert (iface->register_handler_from_anyone_by_stanza != NULL); return iface->register_handler_from_anyone_by_stanza (self, type, sub_type, priority, callback, user_data, stanza); } /** * wocky_porter_register_handler_from_anyone: * @self: A #WockyPorter instance (passed to @callback). * @type: The type of stanza to be handled, or WOCKY_STANZA_TYPE_NONE to match * any type of stanza. * @sub_type: The subtype of stanza to be handled, or * WOCKY_STANZA_SUB_TYPE_NONE to match any type of stanza. * @priority: a priority between %WOCKY_PORTER_HANDLER_PRIORITY_MIN and * %WOCKY_PORTER_HANDLER_PRIORITY_MAX (often * %WOCKY_PORTER_HANDLER_PRIORITY_NORMAL). Handlers with a higher priority * (larger number) are called first. * @callback: A #WockyPorterHandlerFunc, which should return %FALSE to decline * the stanza (Wocky will continue to the next handler, if any), or %TRUE to * stop further processing. * @user_data: Passed to @callback. * @...: a wocky_stanza_build() specification. The handler * will match a stanza only if the stanza received is a superset of the one * passed to this function, as per wocky_node_is_superset(). * * Registers a handler for incoming stanzas from anyone, including those where * the from attribute is missing. * * For example, to register a handler matching all message stanzas received * from anyone, call: * * |[ * id = wocky_porter_register_handler (porter, * WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, NULL, * WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, message_received_cb, NULL, * NULL); * ]| * * As a more interesting example, the following matches incoming PEP * notifications for contacts' geolocation information: * * |[ * id = wocky_porter_register_handler_from_anyone (porter, * WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, * WOCKY_PORTER_HANDLER_PRIORITY_MAX, * msg_event_cb, self, * '(', "event", * ':', WOCKY_XMPP_NS_PUBSUB_EVENT, * '(', "items", * '@', "node", "http://jabber.org/protocol/geoloc", * ')', * ')', * NULL); * ]| * * Returns: a non-zero ID for use with wocky_porter_unregister_handler(). */ guint wocky_porter_register_handler_from_anyone ( WockyPorter *self, WockyStanzaType type, WockyStanzaSubType sub_type, guint priority, WockyPorterHandlerFunc callback, gpointer user_data, ...) { va_list ap; guint ret; g_return_val_if_fail (WOCKY_IS_PORTER (self), 0); va_start (ap, user_data); ret = wocky_porter_register_handler_from_anyone_va (self, type, sub_type, priority, callback, user_data, ap); va_end (ap); return ret; } /** * wocky_porter_unregister_handler: * @porter: a #WockyPorter * @id: the id of the handler to unregister * * Unregister a registered handler. This handler won't be called when * receiving stanzas anymore. */ void wocky_porter_unregister_handler (WockyPorter *self, guint id) { WockyPorterInterface *iface; g_return_if_fail (WOCKY_IS_PORTER (self)); iface = WOCKY_PORTER_GET_INTERFACE (self); g_assert (iface->unregister_handler != NULL); iface->unregister_handler (self, id); } /** * wocky_porter_close_async: * @porter: a #WockyPorter * @cancellable: optional #GCancellable object, %NULL to ignore * @callback: callback to call when the request is satisfied * @user_data: the data to pass to callback function * * Request asynchronous closing of a #WockyPorter. This fires the * WockyPorter::closing signal, flushes the sending queue, closes the XMPP * stream and waits that the other side closes the XMPP stream as well. * When this is done, @callback is called. * You can then call wocky_porter_close_finish() to get the result of * the operation. */ void wocky_porter_close_async (WockyPorter *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyPorterInterface *iface; g_return_if_fail (WOCKY_IS_PORTER (self)); iface = WOCKY_PORTER_GET_INTERFACE (self); g_assert (iface->close_async != NULL); iface->close_async (self, cancellable, callback, user_data); } /** * wocky_porter_close_finish: * @porter: a #WockyPorter * @result: a #GAsyncResult * @error: a #GError location to store the error occuring, or %NULL to ignore. * * Finishes a close operation. * * Returns: %TRUE on success or %FALSE on error. */ gboolean wocky_porter_close_finish (WockyPorter *self, GAsyncResult *result, GError **error) { WockyPorterInterface *iface; g_return_val_if_fail (WOCKY_IS_PORTER (self), FALSE); iface = WOCKY_PORTER_GET_INTERFACE (self); g_assert (iface->close_finish != NULL); return iface->close_finish (self, result, error); } /** * wocky_porter_send_iq_async: * @porter: a #WockyPorter * @stanza: the #WockyStanza to send * @cancellable: optional #GCancellable object, %NULL to ignore * @callback: callback to call when the request is satisfied * @user_data: the data to pass to callback function * * Request asynchronous sending of a #WockyStanza of type * %WOCKY_STANZA_TYPE_IQ and sub-type %WOCKY_STANZA_SUB_TYPE_GET or * %WOCKY_STANZA_SUB_TYPE_SET. * When the reply to this IQ has been received callback will be called. * You can then call #wocky_porter_send_iq_finish to get the reply stanza. */ void wocky_porter_send_iq_async (WockyPorter *self, WockyStanza *stanza, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyPorterInterface *iface; g_return_if_fail (WOCKY_IS_PORTER (self)); iface = WOCKY_PORTER_GET_INTERFACE (self); g_assert (iface->send_iq_async != NULL); iface->send_iq_async (self, stanza, cancellable, callback, user_data); } /** * wocky_porter_send_iq_finish: * @porter: a #WockyPorter * @result: a #GAsyncResult * @error: a #GError location to store the error occuring, or %NULL to ignore. * * Get the reply of an IQ query. * * Returns: a reffed #WockyStanza on success, %NULL on error */ WockyStanza * wocky_porter_send_iq_finish (WockyPorter *self, GAsyncResult *result, GError **error) { WockyPorterInterface *iface; g_return_val_if_fail (WOCKY_IS_PORTER (self), FALSE); iface = WOCKY_PORTER_GET_INTERFACE (self); g_assert (iface->send_iq_finish != NULL); return iface->send_iq_finish (self, result, error); } /** * wocky_porter_acknowledge_iq: * @porter: a #WockyPorter * @stanza: a stanza of type #WOCKY_STANZA_TYPE_IQ and sub-type either * #WOCKY_STANZA_SUB_TYPE_SET or #WOCKY_STANZA_SUB_TYPE_GET * @...: a wocky_stanza_build() specification; pass %NULL to include no * body in the reply. * * Sends an acknowledgement for @stanza back to the sender, as a shorthand for * calling wocky_stanza_build_iq_result() and wocky_porter_send(). */ void wocky_porter_acknowledge_iq ( WockyPorter *porter, WockyStanza *stanza, ...) { WockyStanzaType type; WockyStanzaSubType sub_type; WockyStanza *result; va_list ap; g_return_if_fail (WOCKY_IS_PORTER (porter)); g_return_if_fail (WOCKY_IS_STANZA (stanza)); wocky_stanza_get_type_info (stanza, &type, &sub_type); g_return_if_fail (type == WOCKY_STANZA_TYPE_IQ); g_return_if_fail (sub_type == WOCKY_STANZA_SUB_TYPE_GET || sub_type == WOCKY_STANZA_SUB_TYPE_SET); va_start (ap, stanza); result = wocky_stanza_build_iq_result_va (stanza, ap); va_end (ap); if (result != NULL) { wocky_porter_send (porter, result); g_object_unref (result); } } /** * wocky_porter_send_iq_error: * @porter: the porter whence @stanza came * @stanza: a stanza of type %WOCKY_STANZA_TYPE_IQ and sub-type either * #WOCKY_STANZA_SUB_TYPE_SET or #WOCKY_STANZA_SUB_TYPE_GET * @error_code: an XMPP Core stanza error code * @message: (allow-none): an optional error message to include with the reply. * * Sends an error reply for @stanza back to its sender, with the given * @error_code and @message, and including the child element from the original * stanza. * * To send error replies with more detailed error elements, see * wocky_porter_send_iq_gerror(), or use wocky_stanza_build_iq_error() and * wocky_porter_send() directly, possibly using wocky_stanza_error_to_node() to * construct the error element. */ void wocky_porter_send_iq_error ( WockyPorter *porter, WockyStanza *stanza, WockyXmppError error_code, const gchar *message) { WockyStanzaType type; WockyStanzaSubType sub_type; GError *error = NULL; g_return_if_fail (WOCKY_IS_PORTER (porter)); g_return_if_fail (WOCKY_IS_STANZA (stanza)); wocky_stanza_get_type_info (stanza, &type, &sub_type); g_return_if_fail (type == WOCKY_STANZA_TYPE_IQ); g_return_if_fail (sub_type == WOCKY_STANZA_SUB_TYPE_GET || sub_type == WOCKY_STANZA_SUB_TYPE_SET); g_return_if_fail (error_code < NUM_WOCKY_XMPP_ERRORS); error = g_error_new_literal (WOCKY_XMPP_ERROR, error_code, message != NULL ? message : ""); wocky_porter_send_iq_gerror (porter, stanza, error); g_clear_error (&error); } /** * wocky_porter_send_iq_gerror: * @porter: the porter whence @stanza came * @stanza: a stanza of type %WOCKY_STANZA_TYPE_IQ and sub-type either * #WOCKY_STANZA_SUB_TYPE_SET or #WOCKY_STANZA_SUB_TYPE_GET * @error: an error whose domain is either %WOCKY_XMPP_ERROR, some other stanza * error domain supplied with Wocky (such as %WOCKY_JINGLE_ERROR or * %WOCKY_SI_ERROR), or a custom domain registered with * wocky_xmpp_error_register_domain() * * Sends an error reply for @stanza back to its sender, building the * <error/> element from the given @error. To send error * replies with simple XMPP Core stanza errors in the %WOCKY_XMPP_ERROR domain, * wocky_porter_send_iq_error() may be more convenient to use. */ void wocky_porter_send_iq_gerror ( WockyPorter *porter, WockyStanza *stanza, const GError *error) { WockyStanzaType type; WockyStanzaSubType sub_type; WockyStanza *result; WockyNode *result_node; g_return_if_fail (WOCKY_IS_PORTER (porter)); g_return_if_fail (WOCKY_IS_STANZA (stanza)); g_return_if_fail (error != NULL); wocky_stanza_get_type_info (stanza, &type, &sub_type); g_return_if_fail (type == WOCKY_STANZA_TYPE_IQ); g_return_if_fail (sub_type == WOCKY_STANZA_SUB_TYPE_GET || sub_type == WOCKY_STANZA_SUB_TYPE_SET); result = wocky_stanza_build_iq_error (stanza, '*', &result_node, NULL); if (result != NULL) { /* RFC3920 §9.2.3 dictates: * An IQ stanza of type "error" … MUST include an child. */ wocky_stanza_error_to_node (error, result_node); wocky_porter_send (porter, result); g_object_unref (result); } } /** * wocky_porter_force_close_async: * @porter: a #WockyPorter * @cancellable: optional #GCancellable object, %NULL to ignore * @callback: callback to call when the request is satisfied * @user_data: the data to pass to callback function * * Force the #WockyPorter to close the TCP connection of the underlying * #WockyXmppConnection. * If a close operation is pending, it will be completed with the * %WOCKY_PORTER_ERROR_FORCIBLY_CLOSED error. * When the connection has been closed, @callback will be called. * You can then call wocky_porter_force_close_finish() to get the result of * the operation. */ void wocky_porter_force_close_async (WockyPorter *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyPorterInterface *iface; g_return_if_fail (WOCKY_IS_PORTER (self)); iface = WOCKY_PORTER_GET_INTERFACE (self); g_assert (iface->force_close_async != NULL); iface->force_close_async (self, cancellable, callback, user_data); } /** * wocky_porter_force_close_finish: * @porter: a #WockyPorter * @result: a #GAsyncResult * @error: a #GError location to store the error occuring, or %NULL to ignore. * * Finishes a force close operation. * * Returns: %TRUE on success or %FALSE on error. */ gboolean wocky_porter_force_close_finish ( WockyPorter *self, GAsyncResult *result, GError **error) { WockyPorterInterface *iface; g_return_val_if_fail (WOCKY_IS_PORTER (self), FALSE); iface = WOCKY_PORTER_GET_INTERFACE (self); g_assert (iface->force_close_finish != NULL); return iface->force_close_finish (self, result, error); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-meta-porter.h0000664000175000017500000000630611720661341025604 0ustar00cassidycassidy00000000000000/* * wocky-meta-porter.h - Header for WockyMetaPorter * Copyright (C) 2011 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the tubesplied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_META_PORTER_H__ #define __WOCKY_META_PORTER_H__ #include #include #include "wocky-contact-factory.h" #include "wocky-porter.h" G_BEGIN_DECLS typedef struct _WockyMetaPorter WockyMetaPorter; typedef struct _WockyMetaPorterClass WockyMetaPorterClass; typedef struct _WockyMetaPorterPrivate WockyMetaPorterPrivate; typedef enum { WOCKY_META_PORTER_ERROR_NO_CONTACT_ADDRESS, WOCKY_META_PORTER_ERROR_FAILED_TO_CLOSE, } WockyMetaPorterError; GQuark wocky_meta_porter_error_quark (void); #define WOCKY_META_PORTER_ERROR (wocky_meta_porter_error_quark ()) struct _WockyMetaPorterClass { GObjectClass parent_class; }; struct _WockyMetaPorter { GObject parent; WockyMetaPorterPrivate *priv; }; GType wocky_meta_porter_get_type (void); /* TYPE MACROS */ #define WOCKY_TYPE_META_PORTER \ (wocky_meta_porter_get_type ()) #define WOCKY_META_PORTER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_META_PORTER, \ WockyMetaPorter)) #define WOCKY_META_PORTER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_META_PORTER, \ WockyMetaPorterClass)) #define WOCKY_IS_META_PORTER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_META_PORTER)) #define WOCKY_IS_META_PORTER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_META_PORTER)) #define WOCKY_META_PORTER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_META_PORTER, \ WockyMetaPorterClass)) WockyPorter * wocky_meta_porter_new (const gchar *jid, WockyContactFactory *contact_factory); guint16 wocky_meta_porter_get_port (WockyMetaPorter *porter); void wocky_meta_porter_hold (WockyMetaPorter *porter, WockyContact *contact); void wocky_meta_porter_unhold (WockyMetaPorter *porter, WockyContact *contact); void wocky_meta_porter_set_jid (WockyMetaPorter *porter, const gchar *jid); void wocky_meta_porter_open_async (WockyMetaPorter *porter, WockyLLContact *contact, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean wocky_meta_porter_open_finish (WockyMetaPorter *porter, GAsyncResult *result, GError **error); GSocketConnection * wocky_meta_porter_borrow_connection (WockyMetaPorter *porter, WockyLLContact *contact); #endif /* #ifndef __WOCKY_META_PORTER_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-node-tree.h0000664000175000017500000000511611720661341025225 0ustar00cassidycassidy00000000000000/* * wocky-node-tree.h - Header for WockyNodeTree * Copyright (C) 2006-2010 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_NODE_TREE_H__ #define __WOCKY_NODE_TREE_H__ #include #include #include "wocky-node.h" #include "wocky-types.h" #include "wocky-xmpp-error.h" G_BEGIN_DECLS /** * WockyNodeTreeClass: * * The class of a #WockyNodeTree. */ typedef struct _WockyNodeTreeClass WockyNodeTreeClass; typedef struct _WockyNodeTreePrivate WockyNodeTreePrivate; struct _WockyNodeTreeClass { /**/ GObjectClass parent_class; }; struct _WockyNodeTree { /**/ GObject parent; WockyNodeTreePrivate *priv; }; GType wocky_node_tree_get_type (void); /* TYPE MACROS */ #define WOCKY_TYPE_NODE_TREE \ (wocky_node_tree_get_type ()) #define WOCKY_NODE_TREE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_NODE_TREE, \ WockyNodeTree)) #define WOCKY_NODE_TREE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_NODE_TREE, \ WockyNodeTreeClass)) #define WOCKY_IS_NODE_TREE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_NODE_TREE)) #define WOCKY_IS_NODE_TREE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_NODE_TREE)) #define WOCKY_NODE_TREE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_NODE_TREE, \ WockyNodeTreeClass)) WockyNodeTree *wocky_node_tree_new (const gchar *name, const gchar *ns, ...) G_GNUC_NULL_TERMINATED; WockyNodeTree *wocky_node_tree_new_va (const gchar *name, const char *ns, va_list va); WockyNodeTree *wocky_node_tree_new_from_node (WockyNode *node); WockyNode *wocky_node_tree_get_top_node (WockyNodeTree *self); G_END_DECLS #endif /* #ifndef __WOCKY_NODE_TREE_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-jingle-transport-iceudp.c0000664000175000017500000004354312212322440030104 0ustar00cassidycassidy00000000000000/* * wocky-jingle-transport-iceudp.c - Source for WockyJingleTransportIceUdp * * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "wocky-jingle-transport-iceudp.h" #include #include #include #include #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_JINGLE #include "wocky-debug-internal.h" #include "wocky-jingle-content.h" #include "wocky-jingle-factory.h" #include "wocky-jingle-session.h" #include "wocky-namespaces.h" #include "wocky-utils.h" static void transport_iface_init (gpointer g_iface, gpointer iface_data); G_DEFINE_TYPE_WITH_CODE (WockyJingleTransportIceUdp, wocky_jingle_transport_iceudp, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (WOCKY_TYPE_JINGLE_TRANSPORT_IFACE, transport_iface_init)); /* signal enum */ enum { NEW_CANDIDATES, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; /* properties */ enum { PROP_CONTENT = 1, PROP_TRANSPORT_NS, PROP_STATE, LAST_PROPERTY }; struct _WockyJingleTransportIceUdpPrivate { WockyJingleContent *content; WockyJingleTransportState state; gchar *transport_ns; GList *local_candidates; /* A pointer into "local_candidates" list to mark the * candidates that are still not transmitted, or NULL * if all of them are transmitted. */ GList *pending_candidates; GList *remote_candidates; gchar *ufrag; gchar *pwd; /* next ID to send with a candidate */ int id_sequence; gboolean dispose_has_run; }; static void wocky_jingle_transport_iceudp_init (WockyJingleTransportIceUdp *obj) { WockyJingleTransportIceUdpPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, WOCKY_TYPE_JINGLE_TRANSPORT_ICEUDP, WockyJingleTransportIceUdpPrivate); obj->priv = priv; priv->id_sequence = 1; priv->dispose_has_run = FALSE; } static void wocky_jingle_transport_iceudp_dispose (GObject *object) { WockyJingleTransportIceUdp *trans = WOCKY_JINGLE_TRANSPORT_ICEUDP (object); WockyJingleTransportIceUdpPrivate *priv = trans->priv; if (priv->dispose_has_run) return; DEBUG ("dispose called"); priv->dispose_has_run = TRUE; jingle_transport_free_candidates (priv->remote_candidates); priv->remote_candidates = NULL; jingle_transport_free_candidates (priv->local_candidates); priv->local_candidates = NULL; g_free (priv->transport_ns); priv->transport_ns = NULL; g_free (priv->ufrag); priv->ufrag = NULL; g_free (priv->pwd); priv->pwd = NULL; if (G_OBJECT_CLASS (wocky_jingle_transport_iceudp_parent_class)->dispose) G_OBJECT_CLASS (wocky_jingle_transport_iceudp_parent_class)->dispose (object); } static void wocky_jingle_transport_iceudp_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyJingleTransportIceUdp *trans = WOCKY_JINGLE_TRANSPORT_ICEUDP (object); WockyJingleTransportIceUdpPrivate *priv = trans->priv; switch (property_id) { case PROP_CONTENT: g_value_set_object (value, priv->content); break; case PROP_TRANSPORT_NS: g_value_set_string (value, priv->transport_ns); break; case PROP_STATE: g_value_set_uint (value, priv->state); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_jingle_transport_iceudp_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyJingleTransportIceUdp *trans = WOCKY_JINGLE_TRANSPORT_ICEUDP (object); WockyJingleTransportIceUdpPrivate *priv = trans->priv; switch (property_id) { case PROP_CONTENT: priv->content = g_value_get_object (value); break; case PROP_TRANSPORT_NS: g_free (priv->transport_ns); priv->transport_ns = g_value_dup_string (value); break; case PROP_STATE: priv->state = g_value_get_uint (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_jingle_transport_iceudp_class_init (WockyJingleTransportIceUdpClass *cls) { GObjectClass *object_class = G_OBJECT_CLASS (cls); GParamSpec *param_spec; g_type_class_add_private (cls, sizeof (WockyJingleTransportIceUdpPrivate)); object_class->get_property = wocky_jingle_transport_iceudp_get_property; object_class->set_property = wocky_jingle_transport_iceudp_set_property; object_class->dispose = wocky_jingle_transport_iceudp_dispose; /* property definitions */ param_spec = g_param_spec_object ("content", "WockyJingleContent object", "Jingle content object using this transport.", WOCKY_TYPE_JINGLE_CONTENT, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_CONTENT, param_spec); param_spec = g_param_spec_string ("transport-ns", "Transport namespace", "Namespace identifying the transport type.", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_TRANSPORT_NS, param_spec); param_spec = g_param_spec_uint ("state", "Connection state for the transport.", "Enum specifying the connection state of the transport.", WOCKY_JINGLE_TRANSPORT_STATE_DISCONNECTED, WOCKY_JINGLE_TRANSPORT_STATE_CONNECTED, WOCKY_JINGLE_TRANSPORT_STATE_DISCONNECTED, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); g_object_class_install_property (object_class, PROP_STATE, param_spec); /* signal definitions */ signals[NEW_CANDIDATES] = g_signal_new ( "new-candidates", G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); } static void parse_candidates (WockyJingleTransportIface *obj, WockyNode *transport_node, GError **error) { WockyJingleTransportIceUdp *t = WOCKY_JINGLE_TRANSPORT_ICEUDP (obj); WockyJingleTransportIceUdpPrivate *priv = t->priv; gboolean node_contains_a_candidate = FALSE; GList *candidates = NULL; WockyNodeIter i; WockyNode *node; DEBUG ("called"); wocky_node_iter_init (&i, transport_node, "candidate", NULL); while (wocky_node_iter_next (&i, &node)) { const gchar *id, *address, *user, *pass, *str; guint port, net, gen, component = 1; gdouble pref; WockyJingleTransportProtocol proto; WockyJingleCandidateType ctype; WockyJingleCandidate *c; node_contains_a_candidate = TRUE; id = wocky_node_get_attribute (node, "foundation"); if (id == NULL) { DEBUG ("candidate doesn't contain foundation"); continue; } address = wocky_node_get_attribute (node, "ip"); if (address == NULL) { DEBUG ("candidate doesn't contain ip"); continue; } str = wocky_node_get_attribute (node, "port"); if (str == NULL) { DEBUG ("candidate doesn't contain port"); continue; } port = atoi (str); str = wocky_node_get_attribute (node, "protocol"); if (str == NULL) { DEBUG ("candidate doesn't contain protocol"); continue; } if (!wocky_strdiff (str, "udp")) { proto = WOCKY_JINGLE_TRANSPORT_PROTOCOL_UDP; } else { /* unknown protocol */ DEBUG ("unknown protocol: %s", str); continue; } str = wocky_node_get_attribute (node, "priority"); if (str == NULL) { DEBUG ("candidate doesn't contain priority"); continue; } pref = g_ascii_strtod (str, NULL); str = wocky_node_get_attribute (node, "type"); if (str == NULL) { DEBUG ("candidate doesn't contain type"); continue; } if (!wocky_strdiff (str, "host")) { ctype = WOCKY_JINGLE_CANDIDATE_TYPE_LOCAL; } else if (!wocky_strdiff (str, "srflx") || !wocky_strdiff (str, "prflx")) { /* FIXME Strictly speaking a prflx candidate should be a different * type, but the TP spec has now way to distinguish and it doesn't * matter much anyway.. */ ctype = WOCKY_JINGLE_CANDIDATE_TYPE_STUN; } else if (!wocky_strdiff (str, "relay")) { ctype = WOCKY_JINGLE_CANDIDATE_TYPE_RELAY; } else { /* unknown candidate type */ DEBUG ("unknown candidate type: %s", str); continue; } user = wocky_node_get_attribute (transport_node, "ufrag"); if (user == NULL) { DEBUG ("transport doesn't contain ufrag"); continue; } pass = wocky_node_get_attribute (transport_node, "pwd"); if (pass == NULL) { DEBUG ("transport doesn't contain pwd"); continue; } str = wocky_node_get_attribute (node, "network"); if (str == NULL) { DEBUG ("candidate doesn't contain network"); continue; } net = atoi (str); str = wocky_node_get_attribute (node, "generation"); if (str == NULL) { DEBUG ("candidate doesn't contain generation"); continue; } gen = atoi (str); str = wocky_node_get_attribute (node, "component"); if (str == NULL) { DEBUG ("candidate doesn't contain component"); continue; } component = atoi (str); if (priv->ufrag == NULL || strcmp (priv->ufrag, user)) { g_free (priv->ufrag); priv->ufrag = g_strdup (user); } if (priv->pwd == NULL || strcmp (priv->pwd, pass)) { g_free (priv->pwd); priv->pwd = g_strdup (pass); } c = wocky_jingle_candidate_new (proto, ctype, id, component, address, port, gen, pref, user, pass, net); candidates = g_list_append (candidates, c); } if (candidates == NULL) { if (node_contains_a_candidate) { DEBUG_NODE (transport_node, "couldn't parse any of the given candidates"); g_set_error (error, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST, "could not parse any of the given candidates"); } else { DEBUG ("no candidates in this stanza"); } } else { DEBUG ("emitting %d new remote candidates", g_list_length (candidates)); g_signal_emit (obj, signals[NEW_CANDIDATES], 0, candidates); priv->remote_candidates = g_list_concat (priv->remote_candidates, candidates); } } static void inject_candidates (WockyJingleTransportIface *obj, WockyNode *transport_node) { WockyJingleTransportIceUdp *self = WOCKY_JINGLE_TRANSPORT_ICEUDP (obj); WockyJingleTransportIceUdpPrivate *priv = self->priv; const gchar *username = NULL; for (; priv->pending_candidates != NULL; priv->pending_candidates = priv->pending_candidates->next) { WockyJingleCandidate *c = (WockyJingleCandidate *) priv->pending_candidates->data; gchar port_str[16], pref_str[16], comp_str[16], id_str[16], *type_str, *proto_str; WockyNode *cnode; if (username == NULL) { username = c->username; } else if (wocky_strdiff (username, c->username)) { DEBUG ("found a candidate with a different username (%s not %s); " "will send in a separate batch", c->username, username); break; } sprintf (pref_str, "%d", c->preference); sprintf (port_str, "%d", c->port); sprintf (comp_str, "%d", c->component); sprintf (id_str, "%d", priv->id_sequence++); switch (c->type) { case WOCKY_JINGLE_CANDIDATE_TYPE_LOCAL: type_str = "host"; break; case WOCKY_JINGLE_CANDIDATE_TYPE_STUN: type_str = "srflx"; break; case WOCKY_JINGLE_CANDIDATE_TYPE_RELAY: type_str = "relay"; break; default: DEBUG ("skipping candidate with unknown type %u", c->type); continue; } switch (c->protocol) { case WOCKY_JINGLE_TRANSPORT_PROTOCOL_UDP: proto_str = "udp"; break; case WOCKY_JINGLE_TRANSPORT_PROTOCOL_TCP: DEBUG ("ignoring TCP candidate"); continue; default: DEBUG ("skipping candidate with unknown protocol %u", c->protocol); continue; } wocky_node_set_attributes (transport_node, "ufrag", c->username, "pwd", c->password, NULL); cnode = wocky_node_add_child (transport_node, "candidate"); wocky_node_set_attributes (cnode, "ip", c->address, "port", port_str, "priority", pref_str, "protocol", proto_str, "type", type_str, "component", comp_str, "foundation", c->id, "id", id_str, "network", "0", "generation", "0", NULL); } } /* We never have to retransmit candidates we've already sent, so we ignore * @all. */ static void send_candidates (WockyJingleTransportIface *iface, gboolean all G_GNUC_UNUSED) { WockyJingleTransportIceUdp *self = WOCKY_JINGLE_TRANSPORT_ICEUDP (iface); WockyJingleTransportIceUdpPrivate *priv = self->priv; while (priv->pending_candidates != NULL) { WockyNode *trans_node, *sess_node; WockyStanza *msg; msg = wocky_jingle_session_new_message (priv->content->session, WOCKY_JINGLE_ACTION_TRANSPORT_INFO, &sess_node); wocky_jingle_content_produce_node (priv->content, sess_node, FALSE, TRUE, &trans_node); inject_candidates (iface, trans_node); wocky_porter_send_iq_async ( wocky_jingle_session_get_porter (priv->content->session), msg, NULL, NULL, NULL); g_object_unref (msg); } DEBUG ("sent all pending candidates"); } /* Takes in a list of slice-allocated WockyJingleCandidate structs */ static void new_local_candidates (WockyJingleTransportIface *obj, GList *new_candidates) { WockyJingleTransportIceUdp *transport = WOCKY_JINGLE_TRANSPORT_ICEUDP (obj); WockyJingleTransportIceUdpPrivate *priv = transport->priv; priv->local_candidates = g_list_concat (priv->local_candidates, new_candidates); /* If all previous candidates have been signalled, set the new * ones as pending. If there are existing pending candidates, * the new ones will just be appended to that list. */ if (priv->pending_candidates == NULL) priv->pending_candidates = new_candidates; } static GList * get_remote_candidates (WockyJingleTransportIface *iface) { WockyJingleTransportIceUdp *transport = WOCKY_JINGLE_TRANSPORT_ICEUDP (iface); WockyJingleTransportIceUdpPrivate *priv = transport->priv; return priv->remote_candidates; } static GList * get_local_candidates (WockyJingleTransportIface *iface) { WockyJingleTransportIceUdp *transport = WOCKY_JINGLE_TRANSPORT_ICEUDP (iface); WockyJingleTransportIceUdpPrivate *priv = transport->priv; return priv->local_candidates; } static WockyJingleTransportType get_transport_type (void) { return JINGLE_TRANSPORT_ICE_UDP; } static gboolean get_credentials (WockyJingleTransportIface *iface, gchar **ufrag, gchar **pwd) { WockyJingleTransportIceUdp *transport = WOCKY_JINGLE_TRANSPORT_ICEUDP (iface); WockyJingleTransportIceUdpPrivate *priv = transport->priv; if (!priv->ufrag || !priv->pwd) return FALSE; if (ufrag) *ufrag = priv->ufrag; if (pwd) *pwd = priv->pwd; return TRUE; } static void transport_iface_init (gpointer g_iface, gpointer iface_data) { WockyJingleTransportIfaceClass *klass = (WockyJingleTransportIfaceClass *) g_iface; klass->parse_candidates = parse_candidates; klass->new_local_candidates = new_local_candidates; klass->inject_candidates = inject_candidates; klass->send_candidates = send_candidates; klass->get_remote_candidates = get_remote_candidates; klass->get_local_candidates = get_local_candidates; klass->get_transport_type = get_transport_type; klass->get_credentials = get_credentials; } void jingle_transport_iceudp_register (WockyJingleFactory *factory) { wocky_jingle_factory_register_transport (factory, WOCKY_XMPP_NS_JINGLE_TRANSPORT_ICEUDP, WOCKY_TYPE_JINGLE_TRANSPORT_ICEUDP); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-pubsub-node.c0000664000175000017500000010747012212322440025556 0ustar00cassidycassidy00000000000000/* * wocky-pubsub-node.c - WockyPubsubNode * Copyright (C) 2009 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-pubsub-node.h" #include "wocky-pubsub-node-protected.h" #include "wocky-pubsub-node-internal.h" #include "wocky-namespaces.h" #include "wocky-porter.h" #include "wocky-pubsub-helpers.h" #include "wocky-pubsub-service-protected.h" #include "wocky-signals-marshal.h" #include "wocky-utils.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_PUBSUB #include "wocky-debug-internal.h" G_DEFINE_TYPE (WockyPubsubNode, wocky_pubsub_node, G_TYPE_OBJECT) enum { SIG_EVENT_RECEIVED, SIG_SUB_STATE_CHANGED, SIG_DELETED, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL] = {0}; enum { PROP_SERVICE = 1, PROP_NAME, }; /* private structure */ struct _WockyPubsubNodePrivate { WockyPubsubService *service; WockyPorter *porter; gchar *service_jid; gchar *name; gboolean dispose_has_run; }; static void wocky_pubsub_node_init (WockyPubsubNode *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_PUBSUB_NODE, WockyPubsubNodePrivate); } static void wocky_pubsub_node_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyPubsubNode *self = WOCKY_PUBSUB_NODE (object); WockyPubsubNodePrivate *priv = self->priv; switch (property_id) { case PROP_SERVICE: priv->service = g_value_dup_object (value); break; case PROP_NAME: priv->name = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_pubsub_node_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyPubsubNode *self = WOCKY_PUBSUB_NODE (object); WockyPubsubNodePrivate *priv = self->priv; switch (property_id) { case PROP_SERVICE: g_value_set_object (value, priv->service); break; case PROP_NAME: g_value_set_string (value, priv->name); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_pubsub_node_dispose (GObject *object) { WockyPubsubNode *self = WOCKY_PUBSUB_NODE (object); WockyPubsubNodePrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; g_object_unref (priv->service); g_object_unref (priv->porter); if (G_OBJECT_CLASS (wocky_pubsub_node_parent_class)->dispose) G_OBJECT_CLASS (wocky_pubsub_node_parent_class)->dispose (object); } static void wocky_pubsub_node_finalize (GObject *object) { WockyPubsubNode *self = WOCKY_PUBSUB_NODE (object); WockyPubsubNodePrivate *priv = self->priv; g_free (priv->name); g_free (priv->service_jid); G_OBJECT_CLASS (wocky_pubsub_node_parent_class)->finalize (object); } static void wocky_pubsub_node_constructed (GObject *object) { WockyPubsubNode *self = WOCKY_PUBSUB_NODE (object); WockyPubsubNodePrivate *priv = self->priv; WockySession *session; g_assert (priv->service != NULL); g_assert (priv->name != NULL); g_object_get (priv->service, "jid", &(priv->service_jid), "session", &session, NULL); g_assert (priv->service_jid != NULL); g_assert (session != NULL); priv->porter = wocky_session_get_porter (session); g_object_ref (priv->porter); g_object_unref (session); } static void wocky_pubsub_node_emit_event_received ( WockyPubsubNode *self, WockyStanza *event_stanza, WockyNode *event_node, WockyNode *items_node, GList *items) { g_signal_emit (self, signals[SIG_EVENT_RECEIVED], 0, event_stanza, event_node, items_node, items); } static void wocky_pubsub_node_emit_subscription_state_changed ( WockyPubsubNode *self, WockyStanza *stanza, WockyNode *event_node, WockyNode *subscription_node, WockyPubsubSubscription *subscription) { g_signal_emit (self, signals[SIG_SUB_STATE_CHANGED], 0, stanza, event_node, subscription_node, subscription); } static void wocky_pubsub_node_emit_deleted ( WockyPubsubNode *self, WockyStanza *stanza, WockyNode *event_node, WockyNode *delete_node) { g_signal_emit (self, signals[SIG_DELETED], 0, stanza, event_node, delete_node); } static void wocky_pubsub_node_class_init ( WockyPubsubNodeClass *wocky_pubsub_node_class) { GObjectClass *object_class = G_OBJECT_CLASS (wocky_pubsub_node_class); GType ctype = G_OBJECT_CLASS_TYPE (wocky_pubsub_node_class); GParamSpec *param_spec; g_type_class_add_private (wocky_pubsub_node_class, sizeof (WockyPubsubNodePrivate)); object_class->set_property = wocky_pubsub_node_set_property; object_class->get_property = wocky_pubsub_node_get_property; object_class->dispose = wocky_pubsub_node_dispose; object_class->finalize = wocky_pubsub_node_finalize; object_class->constructed = wocky_pubsub_node_constructed; param_spec = g_param_spec_object ("service", "service", "the Wocky Pubsub service associated with this pubsub node", WOCKY_TYPE_PUBSUB_SERVICE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SERVICE, param_spec); param_spec = g_param_spec_string ("name", "name", "The name of the pubsub node", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_NAME, param_spec); /** * WockyPubsubNode::event-received: * @node: a pubsub node * @event_stanza: the message/event stanza in its entirity * @event_node: the event node from the stanza * @items_node: the items node from the stanza * @items: a list of WockyNode *s for each item child of @items_node */ signals[SIG_EVENT_RECEIVED] = g_signal_new ("event-received", ctype, 0, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT_POINTER_POINTER_POINTER, G_TYPE_NONE, 4, WOCKY_TYPE_STANZA, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER); /** * WockyPubsubNode::subscription-state-changed: * @node: a pubsub node * @stanza: the message/event stanza in its entirety * @event_node: the event node from @stanza * @subscription_node: the subscription node from @stanza * @subscription: subscription information parsed from @subscription_node */ signals[SIG_SUB_STATE_CHANGED] = g_signal_new ("subscription-state-changed", ctype, G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT_POINTER_POINTER_BOXED, G_TYPE_NONE, 4, WOCKY_TYPE_STANZA, G_TYPE_POINTER, G_TYPE_POINTER, WOCKY_TYPE_PUBSUB_SUBSCRIPTION); /** * WockyPubsubNode::deleted * @node: a pubsub node * @stanza: the message/event stanza in its entirety * @event_node: the event node from @stanza * @delete_node: the delete node from @stanza * * Emitted when a notification of this node's deletion is received from the * server. */ signals[SIG_DELETED] = g_signal_new ("deleted", ctype, G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT_POINTER_POINTER, G_TYPE_NONE, 3, WOCKY_TYPE_STANZA, G_TYPE_POINTER, G_TYPE_POINTER); } static void pubsub_node_handle_items_event (WockyPubsubNode *self, WockyStanza *event_stanza, WockyNode *event_node, WockyNode *items_node) { WockyNode *item_node; GQueue items = G_QUEUE_INIT; WockyNodeIter iter; wocky_node_iter_init (&iter, items_node, "item", NULL); while (wocky_node_iter_next (&iter, &item_node)) g_queue_push_tail (&items, item_node); DEBUG_STANZA (event_stanza, "extracted %u items", items.length); wocky_pubsub_node_emit_event_received (self, event_stanza, event_node, items_node, items.head); g_queue_clear (&items); } static void pubsub_node_handle_subscription_event (WockyPubsubNode *self, WockyStanza *event_stanza, WockyNode *event_node, WockyNode *subscription_node) { WockyPubsubNodePrivate *priv = self->priv; WockyPubsubSubscription *sub; GError *error = NULL; sub = wocky_pubsub_service_parse_subscription (priv->service, subscription_node, NULL, &error); if (sub == NULL) { DEBUG ("received unparseable subscription state change notification: %s", error->message); g_clear_error (&error); } else { wocky_pubsub_node_emit_subscription_state_changed (self, event_stanza, event_node, subscription_node, sub); wocky_pubsub_subscription_free (sub); } } static const WockyPubsubNodeEventMapping mappings[] = { { "items", pubsub_node_handle_items_event, }, { "subscription", pubsub_node_handle_subscription_event, }, { "delete", wocky_pubsub_node_emit_deleted, }, { NULL, } }; const WockyPubsubNodeEventMapping * _wocky_pubsub_node_get_event_mappings (guint *n_mappings) { if (n_mappings != NULL) *n_mappings = G_N_ELEMENTS (mappings) - 1; return mappings; } const gchar * wocky_pubsub_node_get_name (WockyPubsubNode *self) { WockyPubsubNodePrivate *priv = self->priv; return priv->name; } WockyStanza * wocky_pubsub_node_make_publish_stanza (WockyPubsubNode *self, WockyNode **pubsub_out, WockyNode **publish_out, WockyNode **item_out) { WockyPubsubNodePrivate *priv = self->priv; return wocky_pubsub_make_publish_stanza (priv->service_jid, priv->name, pubsub_out, publish_out, item_out); } static WockyStanza * pubsub_node_make_action_stanza (WockyPubsubNode *self, WockyStanzaSubType sub_type, const gchar *pubsub_ns, const gchar *action_name, const gchar *jid, WockyNode **pubsub_node, WockyNode **action_node) { WockyPubsubNodePrivate *priv = self->priv; WockyStanza *stanza; WockyNode *action; g_assert (pubsub_ns != NULL); g_assert (action_name != NULL); stanza = wocky_pubsub_make_stanza (priv->service_jid, sub_type, pubsub_ns, action_name, pubsub_node, &action); wocky_node_set_attribute (action, "node", priv->name); if (jid != NULL) wocky_node_set_attribute (action, "jid", jid); if (action_node != NULL) *action_node = action; return stanza; } WockyStanza * wocky_pubsub_node_make_subscribe_stanza (WockyPubsubNode *self, const gchar *jid, WockyNode **pubsub_node, WockyNode **subscribe_node) { /* TODO: when the connection/porter/session/something knows our own JID, we * should provide an easy way to say “my bare JID” or “my full JID”. Could be * really evil and use 0x1 and 0x3 or something on the assumption that those * will never be strings.... */ g_return_val_if_fail (jid != NULL, NULL); return pubsub_node_make_action_stanza (self, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_XMPP_NS_PUBSUB, "subscribe", jid, pubsub_node, subscribe_node); } static void subscribe_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); WockyPubsubNode *self = WOCKY_PUBSUB_NODE ( g_async_result_get_source_object (user_data)); WockyPubsubNodePrivate *priv = self->priv; WockyNodeTree *sub_tree; WockyPubsubSubscription *sub = NULL; GError *error = NULL; if (wocky_pubsub_distill_iq_reply (source, res, WOCKY_XMPP_NS_PUBSUB, "subscription", &sub_tree, &error)) { WockyNode *subscription_node = wocky_node_tree_get_top_node (sub_tree); sub = wocky_pubsub_service_parse_subscription (priv->service, subscription_node, NULL, &error); g_object_unref (sub_tree); } if (sub != NULL) { g_simple_async_result_set_op_res_gpointer (simple, sub, (GDestroyNotify) wocky_pubsub_subscription_free); } else { g_simple_async_result_set_from_error (simple, error); g_clear_error (&error); } g_simple_async_result_complete (simple); g_object_unref (simple); g_object_unref (self); } /** * wocky_pubsub_node_subscribe_async: * @self: a pubsub node * @jid: the JID to use as the subscribed JID (usually the connection's bare or * full JID); may not be %NULL * @cancellable: optional GCancellable object, %NULL to ignore * @callback: a callback to call when the request is completed * @user_data: data to pass to @callback * * Attempts to subscribe to @self. */ void wocky_pubsub_node_subscribe_async (WockyPubsubNode *self, const gchar *jid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyPubsubNodePrivate *priv = self->priv; GSimpleAsyncResult *simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_pubsub_node_subscribe_async); WockyStanza *stanza; g_return_if_fail (jid != NULL); stanza = wocky_pubsub_node_make_subscribe_stanza (self, jid, NULL, NULL); wocky_porter_send_iq_async (priv->porter, stanza, cancellable, subscribe_cb, simple); g_object_unref (stanza); } WockyPubsubSubscription * wocky_pubsub_node_subscribe_finish (WockyPubsubNode *self, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), wocky_pubsub_node_subscribe_async), NULL); simple = (GSimpleAsyncResult *) result; if (g_simple_async_result_propagate_error (simple, error)) return NULL; else return wocky_pubsub_subscription_copy ( g_simple_async_result_get_op_res_gpointer (simple)); } WockyStanza * wocky_pubsub_node_make_unsubscribe_stanza (WockyPubsubNode *self, const gchar *jid, const gchar *subid, WockyNode **pubsub_node, WockyNode **unsubscribe_node) { WockyStanza *stanza; WockyNode *unsubscribe; /* TODO: when the connection/porter/session/something knows our own JID, we * should provide an easy way to say “my bare JID” or “my full JID”. Could be * really evil and use 0x1 and 0x3 or something on the assumption that those * will never be strings.... */ g_return_val_if_fail (jid != NULL, NULL); stanza = pubsub_node_make_action_stanza (self, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_XMPP_NS_PUBSUB, "unsubscribe", jid, pubsub_node, &unsubscribe); if (subid != NULL) wocky_node_set_attribute (unsubscribe, "subid", subid); if (unsubscribe_node != NULL) *unsubscribe_node = unsubscribe; return stanza; } static void pubsub_node_void_iq_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); GError *error = NULL; if (!wocky_pubsub_distill_void_iq_reply (source, res, &error)) { g_simple_async_result_set_from_error (simple, error); g_clear_error (&error); } g_simple_async_result_complete (simple); g_object_unref (simple); } /** * wocky_pubsub_node_unsubscribe_async: * @self: a pubsub node * @jid: the JID subscribed to @self (usually the connection's bare or * full JID); may not be %NULL * @subid: the identifier associated with the subscription * @cancellable: optional GCancellable object, %NULL to ignore * @callback: a callback to call when the request is completed * @user_data: data to pass to @callback * * Attempts to unsubscribe from @self. */ void wocky_pubsub_node_unsubscribe_async (WockyPubsubNode *self, const gchar *jid, const gchar *subid, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyPubsubNodePrivate *priv = self->priv; GSimpleAsyncResult *simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_pubsub_node_unsubscribe_async); WockyStanza *stanza; g_return_if_fail (jid != NULL); stanza = wocky_pubsub_node_make_unsubscribe_stanza (self, jid, subid, NULL, NULL); wocky_porter_send_iq_async (priv->porter, stanza, cancellable, pubsub_node_void_iq_cb, simple); g_object_unref (stanza); } gboolean wocky_pubsub_node_unsubscribe_finish (WockyPubsubNode *self, GAsyncResult *result, GError **error) { wocky_implement_finish_void (self, wocky_pubsub_node_unsubscribe_async); } WockyStanza * wocky_pubsub_node_make_delete_stanza ( WockyPubsubNode *self, WockyNode **pubsub_node, WockyNode **delete_node) { return pubsub_node_make_action_stanza (self, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_XMPP_NS_PUBSUB_OWNER, "delete", NULL, pubsub_node, delete_node); } void wocky_pubsub_node_delete_async (WockyPubsubNode *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyPubsubNodePrivate *priv = self->priv; WockyStanza *stanza; GSimpleAsyncResult *result; stanza = wocky_pubsub_node_make_delete_stanza (self, NULL, NULL); result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_pubsub_node_delete_async); wocky_porter_send_iq_async (priv->porter, stanza, NULL, pubsub_node_void_iq_cb, result); g_object_unref (stanza); } gboolean wocky_pubsub_node_delete_finish (WockyPubsubNode *self, GAsyncResult *result, GError **error) { wocky_implement_finish_void (self, wocky_pubsub_node_delete_async); } WockyStanza * wocky_pubsub_node_make_list_subscribers_stanza ( WockyPubsubNode *self, WockyNode **pubsub_node, WockyNode **subscriptions_node) { return pubsub_node_make_action_stanza (self, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_XMPP_NS_PUBSUB_OWNER, "subscriptions", NULL, pubsub_node, subscriptions_node); } static void list_subscribers_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); WockyPubsubNode *self = WOCKY_PUBSUB_NODE ( g_async_result_get_source_object (user_data)); WockyPubsubNodePrivate *priv = self->priv; WockyNodeTree *subs_tree; GError *error = NULL; if (wocky_pubsub_distill_iq_reply (source, res, WOCKY_XMPP_NS_PUBSUB_OWNER, "subscriptions", &subs_tree, &error)) { GList *subs = wocky_pubsub_service_parse_subscriptions (priv->service, wocky_node_tree_get_top_node (subs_tree), NULL); g_simple_async_result_set_op_res_gpointer (simple, subs, (GDestroyNotify) wocky_pubsub_subscription_list_free); g_object_unref (subs_tree); } else { g_simple_async_result_set_from_error (simple, error); g_clear_error (&error); } g_simple_async_result_complete (simple); g_object_unref (simple); g_object_unref (self); } /** * wocky_pubsub_node_list_subscribers_async: * @self: a pubsub node * @cancellable: optional #GCancellable object * @callback: function to call when the subscribers have been retrieved or an * error has occured * @user_data: data to pass to @callback. * * Retrieves the list of subscriptions to a node you own. @callback may * complete the call using wocky_pubsub_node_list_subscribers_finish(). * * (A note on naming: this is §8.8.1 — Retrieve Subscriptions List — in * XEP-0060, not to be confused with §5.6 — Retrieve Subscriptions. The * different terminology in Wocky is intended to help disambiguate!) */ void wocky_pubsub_node_list_subscribers_async ( WockyPubsubNode *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyPubsubNodePrivate *priv = self->priv; GSimpleAsyncResult *simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_pubsub_node_list_subscribers_async); WockyStanza *stanza; stanza = wocky_pubsub_node_make_list_subscribers_stanza (self, NULL, NULL); wocky_porter_send_iq_async (priv->porter, stanza, cancellable, list_subscribers_cb, simple); g_object_unref (stanza); } /** * wocky_pubsub_node_list_subscribers_finish: * @self: a pubsub node * @result: the result passed to a callback * @subscribers: location at which to store a list of #WockyPubsubSubscription * pointers, or %NULL * @error: location at which to store an error, or %NULL * * Completes a call to wocky_pubsub_node_list_subscribers_async(). The list * returned in @subscribers should be freed with * wocky_pubsub_subscription_list_free() when it is no longer needed. * * Returns: %TRUE if the list of subscribers was successfully retrieved; %FALSE * and sets @error if an error occured. */ gboolean wocky_pubsub_node_list_subscribers_finish ( WockyPubsubNode *self, GAsyncResult *result, GList **subscribers, GError **error) { wocky_implement_finish_copy_pointer (self, wocky_pubsub_node_list_subscribers_async, wocky_pubsub_subscription_list_copy, subscribers); } WockyStanza * wocky_pubsub_node_make_list_affiliates_stanza ( WockyPubsubNode *self, WockyNode **pubsub_node, WockyNode **affiliations_node) { return pubsub_node_make_action_stanza (self, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_XMPP_NS_PUBSUB_OWNER, "affiliations", NULL, pubsub_node, affiliations_node); } GList * wocky_pubsub_node_parse_affiliations ( WockyPubsubNode *self, WockyNode *affiliations_node) { GQueue affs = G_QUEUE_INIT; WockyNodeIter i; WockyNode *n; wocky_node_iter_init (&i, affiliations_node, "affiliation", NULL); while (wocky_node_iter_next (&i, &n)) { const gchar *jid = wocky_node_get_attribute (n, "jid"); const gchar *affiliation = wocky_node_get_attribute (n, "affiliation"); gint state; if (jid == NULL) { DEBUG (" missing jid=''; skipping"); continue; } if (affiliation == NULL) { DEBUG (" missing affiliation=''; skipping"); continue; } if (!wocky_enum_from_nick (WOCKY_TYPE_PUBSUB_AFFILIATION_STATE, affiliation, &state)) { DEBUG ("unknown affiliation '%s'; skipping", affiliation); continue; } g_queue_push_tail (&affs, wocky_pubsub_affiliation_new (self, jid, state)); } return affs.head; } static void list_affiliates_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); WockyPubsubNode *self = WOCKY_PUBSUB_NODE ( g_async_result_get_source_object (user_data)); WockyNodeTree *affs_tree; GError *error = NULL; if (wocky_pubsub_distill_iq_reply (source, res, WOCKY_XMPP_NS_PUBSUB_OWNER, "affiliations", &affs_tree, &error)) { WockyNode *affiliations_node = wocky_node_tree_get_top_node (affs_tree); g_simple_async_result_set_op_res_gpointer (simple, wocky_pubsub_node_parse_affiliations (self, affiliations_node), (GDestroyNotify) wocky_pubsub_affiliation_list_free); g_object_unref (affs_tree); } else { g_simple_async_result_set_from_error (simple, error); g_clear_error (&error); } g_simple_async_result_complete (simple); g_object_unref (simple); g_object_unref (self); } /** * wocky_pubsub_node_list_affiliates_async: * @self: a pubsub node * @cancellable: optional #GCancellable object * @callback: function to call when the affiliates have been retrieved or an * error has occured * @user_data: data to pass to @callback. * * Retrieves the list of entities affilied to a node you own. @callback may * complete the call using wocky_pubsub_node_list_affiliates_finish(). * * (A note on naming: this is §8.9.1 — Retrieve Affiliations List — in * XEP-0060, not to be confused with §5.7 — Retrieve Affiliations. The * slightly different terminology in Wocky is intended to help disambiguate!) */ void wocky_pubsub_node_list_affiliates_async ( WockyPubsubNode *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyPubsubNodePrivate *priv = self->priv; GSimpleAsyncResult *simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_pubsub_node_list_affiliates_async); WockyStanza *stanza; stanza = wocky_pubsub_node_make_list_affiliates_stanza (self, NULL, NULL); wocky_porter_send_iq_async (priv->porter, stanza, cancellable, list_affiliates_cb, simple); g_object_unref (stanza); } /** * wocky_pubsub_node_list_affiliates_finish: * @self: a pubsub node * @result: the result passed to a callback * @affiliates: location at which to store a list of #WockyPubsubAffiliation * pointers, or %NULL * @error: location at which to store an error, or %NULL * * Completes a call to wocky_pubsub_node_list_affiliates_async(). The list * returned in @affiliates should be freed with * wocky_pubsub_affiliation_list_free() when it is no longer needed. * * Returns: %TRUE if the list of subscribers was successfully retrieved; %FALSE * and sets @error if an error occured. */ gboolean wocky_pubsub_node_list_affiliates_finish ( WockyPubsubNode *self, GAsyncResult *result, GList **affiliates, GError **error) { wocky_implement_finish_copy_pointer (self, wocky_pubsub_node_list_affiliates_async, wocky_pubsub_affiliation_list_copy, affiliates); } /** * wocky_pubsub_node_make_modify_affiliates_stanza: * @self: a pubsub node * @affiliates: a list of #WockyPubsubAffiliation structures, describing only * the affiliations which should be changed. * @pubsub_node: location at which to store a pointer to the <pubsub/> * node, or %NULL * @affiliations_node: location at which to store a pointer to the * <affiliations/> node, or %NULL * * Returns: an IQ stanza to modify the entities affiliated to a node that you * own. */ WockyStanza * wocky_pubsub_node_make_modify_affiliates_stanza ( WockyPubsubNode *self, GList *affiliates, WockyNode **pubsub_node, WockyNode **affiliations_node) { WockyStanza *stanza; WockyNode *affiliations; GList *l; stanza = pubsub_node_make_action_stanza (self, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_XMPP_NS_PUBSUB_OWNER, "affiliations", NULL, pubsub_node, &affiliations); for (l = affiliates; l != NULL; l = l->next) { const WockyPubsubAffiliation *aff = l->data; WockyNode *affiliation = wocky_node_add_child (affiliations, "affiliation"); const gchar *state = wocky_enum_to_nick ( WOCKY_TYPE_PUBSUB_AFFILIATION_STATE, aff->state); if (aff->jid == NULL) { g_warning ("Affiliate JID may not be NULL"); continue; } if (state == NULL) { g_warning ("Invalid WockyPubsubAffiliationState %u", aff->state); continue; } /* Let's allow the API user to leave node as NULL in each element in the * list of updates, given that we know which node they want to update. * But if they *do* specify it, it'd better be this node. */ if (aff->node != NULL && aff->node != self) { g_warning ("Tried to update affiliates for %s, passing a " "WockyPubsubAffiliation for %s", wocky_pubsub_node_get_name (self), wocky_pubsub_node_get_name (aff->node)); continue; } wocky_node_set_attribute (affiliation, "jid", aff->jid); wocky_node_set_attribute (affiliation, "affiliation", state); } if (affiliations_node != NULL) *affiliations_node = affiliations; return stanza; } /** * wocky_pubsub_node_modify_affiliates_async: * @self: a pubsub node * @affiliates: a list of #WockyPubsubAffiliation structures, describing only * the affiliations which should be changed. * @cancellable: optional GCancellable object, %NULL to ignore * @callback: a callback to call when the request is completed * @user_data: data to pass to @callback * * Modifies the entities affiliated to a node that you own. */ void wocky_pubsub_node_modify_affiliates_async ( WockyPubsubNode *self, GList *affiliates, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyPubsubNodePrivate *priv = self->priv; GSimpleAsyncResult *simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_pubsub_node_modify_affiliates_async); WockyStanza *stanza; stanza = wocky_pubsub_node_make_modify_affiliates_stanza ( self, affiliates, NULL, NULL); wocky_porter_send_iq_async (priv->porter, stanza, cancellable, pubsub_node_void_iq_cb, simple); g_object_unref (stanza); } /** * wocky_pubsub_node_modify_affiliates_finish: * @self: a node * @result: the result * @error: location at which to store an error, if one occurred. * * Complete a call to wocky_pubsub_node_modify_affiliates_async(). * * Returns: %TRUE if the affiliates were successfully modified; %FALSE and sets * @error otherwise. */ gboolean wocky_pubsub_node_modify_affiliates_finish ( WockyPubsubNode *self, GAsyncResult *result, GError **error) { wocky_implement_finish_void (self, wocky_pubsub_node_modify_affiliates_async); } /** * wocky_pubsub_node_make_get_configuration_stanza: * @self: a pubsub node * @pubsub_node: location at which to store a pointer to the <pubsub/> * node, or %NULL * @configure_node: location at which to store a pointer to the * <configure/> node, or %NULL * * Returns: an IQ stanza to retrieve the configuration of @self */ WockyStanza * wocky_pubsub_node_make_get_configuration_stanza ( WockyPubsubNode *self, WockyNode **pubsub_node, WockyNode **configure_node) { return pubsub_node_make_action_stanza (self, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_XMPP_NS_PUBSUB_OWNER, "configure", NULL, pubsub_node, configure_node); } static void get_configuration_iq_cb (GObject *source, GAsyncResult *result, gpointer user_data) { GSimpleAsyncResult *simple = user_data; WockyNodeTree *conf_tree; WockyDataForm *form = NULL; GError *error = NULL; if (wocky_pubsub_distill_iq_reply (source, result, WOCKY_XMPP_NS_PUBSUB_OWNER, "configure", &conf_tree, &error)) { form = wocky_data_form_new_from_form ( wocky_node_tree_get_top_node (conf_tree), &error); g_object_unref (conf_tree); } if (form != NULL) { g_simple_async_result_set_op_res_gpointer (simple, form, g_object_unref); } else { g_simple_async_result_set_from_error (simple, error); g_clear_error (&error); } g_simple_async_result_complete (simple); g_object_unref (simple); } /** * wocky_pubsub_node_get_configuration_async: * @self: a node * @cancellable: optional GCancellable object, %NULL to ignore * @callback: a callback to call when the request is completed * @user_data: data to pass to @callback * * Retrieves the current configuration for a node owned by the user. */ void wocky_pubsub_node_get_configuration_async ( WockyPubsubNode *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyPubsubNodePrivate *priv = self->priv; GSimpleAsyncResult *simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_pubsub_node_get_configuration_async); WockyStanza *stanza; stanza = wocky_pubsub_node_make_get_configuration_stanza ( self, NULL, NULL); wocky_porter_send_iq_async (priv->porter, stanza, cancellable, get_configuration_iq_cb, simple); g_object_unref (stanza); } /** * wocky_pubsub_node_get_configuration_finish: * @self: a node * @result: the result * @error: location at which to store an error, if one occurred. * * Complete a call to wocky_pubsub_node_get_configuration_async(). * * Returns: a form representing the node configuration on success; %NULL and * sets @error otherwise */ WockyDataForm * wocky_pubsub_node_get_configuration_finish ( WockyPubsubNode *self, GAsyncResult *result, GError **error) { wocky_implement_finish_return_copy_pointer (self, wocky_pubsub_node_get_configuration_async, g_object_ref); } WockyPorter * wocky_pubsub_node_get_porter (WockyPubsubNode *self) { WockyPubsubNodePrivate *priv = self->priv; return priv->porter; } /* WockyPubsubAffiliation boilerplate */ /** * WockyPubsubAffiliation: * @node: the node to which this affiliation relates * @jid: the bare JID affiliated to @node * @state: the state of @jid's affiliation to @node * * Represents an affiliation to a node, as returned by * wocky_pubsub_node_list_affiliates_finish(). */ /** * WockyPubsubAffiliationState: * @WOCKY_PUBSUB_AFFILIATION_OWNER: Owner * @WOCKY_PUBSUB_AFFILIATION_PUBLISHER: Publisher * @WOCKY_PUBSUB_AFFILIATION_PUBLISH_ONLY: Publish-Only * @WOCKY_PUBSUB_AFFILIATION_MEMBER: Member * @WOCKY_PUBSUB_AFFILIATION_NONE: None * @WOCKY_PUBSUB_AFFILIATION_OUTCAST: Outcast * * Possible affiliations to a PubSub node, which determine privileges an entity * has. See XEP-0060 * §4.1 for the details. */ GType wocky_pubsub_affiliation_get_type (void) { static GType t = 0; if (G_UNLIKELY (t == 0)) t = g_boxed_type_register_static ("WockyPubsubAffiliation", (GBoxedCopyFunc) wocky_pubsub_affiliation_copy, (GBoxedFreeFunc) wocky_pubsub_affiliation_free); return t; } /** * wocky_pubsub_affiliation_new: * @node: a node * @jid: the JID affiliated to @node * @state: the state of @jid's affiliation to @node * * * * Returns: a new structure representing an affiliation, which should * ultimately be freed with wocky_pubsub_affiliation_free() */ WockyPubsubAffiliation * wocky_pubsub_affiliation_new ( WockyPubsubNode *node, const gchar *jid, WockyPubsubAffiliationState state) { WockyPubsubAffiliation aff = { NULL, g_strdup (jid), state }; g_return_val_if_fail (node != NULL, NULL); aff.node = g_object_ref (node); return g_slice_dup (WockyPubsubAffiliation, &aff); } /** * wocky_pubsub_affiliation_copy: * @aff: an existing affiliation structure * * * * Returns: a duplicate of @aff; the duplicate should ultimately be freed * with wocky_pubsub_affiliation_free() */ WockyPubsubAffiliation * wocky_pubsub_affiliation_copy ( WockyPubsubAffiliation *aff) { g_return_val_if_fail (aff != NULL, NULL); return wocky_pubsub_affiliation_new (aff->node, aff->jid, aff->state); } /** * wocky_pubsub_affiliation_free: * @aff: an affiliation * * Frees an affiliation, previously allocated with * wocky_pubsub_affiliation_new() or wocky_pubsub_affiliation_copy() */ void wocky_pubsub_affiliation_free (WockyPubsubAffiliation *aff) { g_return_if_fail (aff != NULL); g_object_unref (aff->node); g_free (aff->jid); g_slice_free (WockyPubsubAffiliation, aff); } /** * wocky_pubsub_affiliation_list_copy: * @affs: a list of #WockyPubsubAffiliation * * Shorthand for manually copying @affs, duplicating each element with * wocky_pubsub_affiliation_copy(). * * Returns: a deep copy of @affs, which should ultimately be freed with * wocky_pubsub_affiliation_list_free(). */ GList * wocky_pubsub_affiliation_list_copy (GList *affs) { return wocky_list_deep_copy ( (GBoxedCopyFunc) wocky_pubsub_affiliation_copy, affs); } /** * wocky_pubsub_affiliation_list_free: * @affs: a list of #WockyPubsubAffiliation * * Frees a list of WockyPubsubAffiliation structures, as shorthand for calling * wocky_pubsub_affiliation_free() for each element, followed by g_list_free(). */ void wocky_pubsub_affiliation_list_free (GList *affs) { g_list_foreach (affs, (GFunc) wocky_pubsub_affiliation_free, NULL); g_list_free (affs); } telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-pubsub-service.c0000664000175000017500000007447412020062007026275 0ustar00cassidycassidy00000000000000/* * wocky-pubsub-service.c - WockyPubsubService * Copyright (C) 2009 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-pubsub-service.h" #include "wocky-pubsub-service-protected.h" #include "wocky-porter.h" #include "wocky-utils.h" #include "wocky-pubsub-helpers.h" #include "wocky-pubsub-node.h" #include "wocky-pubsub-node-protected.h" #include "wocky-pubsub-node-internal.h" #include "wocky-namespaces.h" #include "wocky-signals-marshal.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_PUBSUB #include "wocky-debug-internal.h" static gboolean pubsub_service_propagate_event (WockyPorter *porter, WockyStanza *event_stanza, gpointer user_data); G_DEFINE_TYPE (WockyPubsubService, wocky_pubsub_service, G_TYPE_OBJECT) /* signal enum */ enum { SIG_EVENT_RECEIVED, SIG_SUB_STATE_CHANGED, SIG_NODE_DELETED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; enum { PROP_SESSION = 1, PROP_JID, }; /* private structure */ typedef struct _EventTrampoline EventTrampoline; struct _EventTrampoline { const WockyPubsubNodeEventMapping *mapping; WockyPubsubService *self; guint handler_id; }; struct _WockyPubsubServicePrivate { WockySession *session; WockyPorter *porter; gchar *jid; /* owned (gchar *) => weak reffed (WockyPubsubNode *) */ GHashTable *nodes; /* slice-allocated (EventTrampoline *) s, used for handlers */ GPtrArray *trampolines; gboolean dispose_has_run; }; GQuark wocky_pubsub_service_error_quark (void) { static GQuark quark = 0; if (quark == 0) quark = g_quark_from_static_string ("wocky-pubsub-service-error"); return quark; } static void wocky_pubsub_service_init (WockyPubsubService *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_PUBSUB_SERVICE, WockyPubsubServicePrivate); self->priv->nodes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); } static void wocky_pubsub_service_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyPubsubService *self = WOCKY_PUBSUB_SERVICE (object); WockyPubsubServicePrivate *priv = self->priv; switch (property_id) { case PROP_SESSION: priv->session = g_value_get_object (value); break; case PROP_JID: priv->jid = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_pubsub_service_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyPubsubService *self = WOCKY_PUBSUB_SERVICE (object); WockyPubsubServicePrivate *priv = self->priv; switch (property_id) { case PROP_SESSION: g_value_set_object (value, priv->session); break; case PROP_JID: g_value_set_string (value, priv->jid); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_pubsub_service_dispose (GObject *object) { WockyPubsubService *self = WOCKY_PUBSUB_SERVICE (object); WockyPubsubServicePrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; if (priv->porter != NULL) { guint i; for (i = 0; i < priv->trampolines->len; i++) { EventTrampoline *t = g_ptr_array_index (priv->trampolines, i); wocky_porter_unregister_handler (priv->porter, t->handler_id); g_slice_free (EventTrampoline, t); } g_ptr_array_unref (priv->trampolines); priv->trampolines = NULL; g_object_unref (priv->porter); priv->porter = NULL; } if (G_OBJECT_CLASS (wocky_pubsub_service_parent_class)->dispose) G_OBJECT_CLASS (wocky_pubsub_service_parent_class)->dispose (object); } static void wocky_pubsub_service_finalize (GObject *object) { WockyPubsubService *self = WOCKY_PUBSUB_SERVICE (object); WockyPubsubServicePrivate *priv = self->priv; g_free (priv->jid); g_hash_table_unref (priv->nodes); G_OBJECT_CLASS (wocky_pubsub_service_parent_class)->finalize (object); } static void wocky_pubsub_service_constructed (GObject *object) { WockyPubsubService *self = WOCKY_PUBSUB_SERVICE (object); WockyPubsubServicePrivate *priv = self->priv; const WockyPubsubNodeEventMapping *m; guint n_mappings; g_assert (priv->session != NULL); g_assert (priv->jid != NULL); priv->porter = wocky_session_get_porter (priv->session); g_object_ref (priv->porter); m = _wocky_pubsub_node_get_event_mappings (&n_mappings); priv->trampolines = g_ptr_array_sized_new (n_mappings); for (; m->action != NULL; m++) { EventTrampoline *t = g_slice_new (EventTrampoline); t->mapping = m; t->self = self; t->handler_id = wocky_porter_register_handler_from (priv->porter, WOCKY_STANZA_TYPE_MESSAGE, WOCKY_STANZA_SUB_TYPE_NONE, priv->jid, WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, pubsub_service_propagate_event, t, '(', "event", ':', WOCKY_XMPP_NS_PUBSUB_EVENT, '(', m->action, ')', ')', NULL); g_ptr_array_add (priv->trampolines, t); } } static void wocky_pubsub_service_class_init ( WockyPubsubServiceClass *wocky_pubsub_service_class) { GObjectClass *object_class = G_OBJECT_CLASS (wocky_pubsub_service_class); GType ctype = G_OBJECT_CLASS_TYPE (wocky_pubsub_service_class); GParamSpec *param_spec; g_type_class_add_private (wocky_pubsub_service_class, sizeof (WockyPubsubServicePrivate)); object_class->set_property = wocky_pubsub_service_set_property; object_class->get_property = wocky_pubsub_service_get_property; object_class->dispose = wocky_pubsub_service_dispose; object_class->finalize = wocky_pubsub_service_finalize; object_class->constructed = wocky_pubsub_service_constructed; param_spec = g_param_spec_object ("session", "session", "the Wocky Session associated with this pubsub service", WOCKY_TYPE_SESSION, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_SESSION, param_spec); param_spec = g_param_spec_string ("jid", "jid", "The jid of the pubsub service", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_JID, param_spec); /** * WockyPubsubService::event-received: * @service: a pubsub service * @node: the node on @service for which an event has been received * wire * @event_stanza: the message/event stanza in its entirity * @event_node: the event node from the stanza * @items_node: the items node from the stanza * @items: a list of WockyNode *s for each item child of @items_node * * Emitted when an event is received for a node. */ signals[SIG_EVENT_RECEIVED] = g_signal_new ("event-received", ctype, 0, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT_OBJECT_POINTER_POINTER_POINTER, G_TYPE_NONE, 5, WOCKY_TYPE_PUBSUB_NODE, WOCKY_TYPE_STANZA, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER); /** * WockyPubsubService::subscription-state-changed: * @service: a pubsub service * @node: a pubsub node for which the subscription state has changed * @stanza: the message/event stanza in its entirety * @event_node: the event node from @stanza * @subscription_node: the subscription node from @stanza * @subscription: subscription information parsed from @subscription_node */ signals[SIG_SUB_STATE_CHANGED] = g_signal_new ("subscription-state-changed", ctype, G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT_OBJECT_POINTER_POINTER_BOXED, G_TYPE_NONE, 5, WOCKY_TYPE_PUBSUB_NODE, WOCKY_TYPE_STANZA, G_TYPE_POINTER, G_TYPE_POINTER, WOCKY_TYPE_PUBSUB_SUBSCRIPTION); /** * WockyPubsubService::node-deleted * @node: a pubsub node * @stanza: the message/event stanza in its entirety * @event_node: the event node from @stanza * @delete_node: the delete node from @stanza * * Emitted when a notification of a node's deletion is received from the * server. */ signals[SIG_NODE_DELETED] = g_signal_new ("node-deleted", ctype, G_SIGNAL_RUN_LAST, 0, NULL, NULL, _wocky_signals_marshal_VOID__OBJECT_OBJECT_POINTER_POINTER, G_TYPE_NONE, 4, WOCKY_TYPE_PUBSUB_NODE, WOCKY_TYPE_STANZA, G_TYPE_POINTER, G_TYPE_POINTER); wocky_pubsub_service_class->node_object_type = WOCKY_TYPE_PUBSUB_NODE; } WockyPubsubService * wocky_pubsub_service_new (WockySession *session, const gchar *jid) { return g_object_new (WOCKY_TYPE_PUBSUB_SERVICE, "session", session, "jid", jid, NULL); } static gboolean remove_node (gpointer key, gpointer value, gpointer node) { return value == node; } /* Called when a WockyPubsubNode has been disposed so we can remove it from * the hash table. */ static void node_disposed_cb (gpointer user_data, GObject *node) { WockyPubsubService *self = WOCKY_PUBSUB_SERVICE (user_data); WockyPubsubServicePrivate *priv = self->priv; g_hash_table_foreach_remove (priv->nodes, remove_node, node); } static void pubsub_service_node_event_received_cb ( WockyPubsubNode *node, WockyStanza *event_stanza, WockyNode *event_node, WockyNode *items_node, GList *items, gpointer user_data) { WockyPubsubService *self = WOCKY_PUBSUB_SERVICE (user_data); g_signal_emit (self, signals[SIG_EVENT_RECEIVED], 0, node, event_stanza, event_node, items_node, items); } static void pubsub_service_node_subscription_state_changed_cb ( WockyPubsubNode *node, WockyStanza *stanza, WockyNode *event_node, WockyNode *subscription_node, WockyPubsubSubscription *subscription, gpointer user_data) { WockyPubsubService *self = WOCKY_PUBSUB_SERVICE (user_data); g_signal_emit (self, signals[SIG_SUB_STATE_CHANGED], 0, node, stanza, event_node, subscription_node, subscription); } static void pubsub_service_node_deleted_cb ( WockyPubsubNode *node, WockyStanza *stanza, WockyNode *event_node, WockyNode *delete_node, gpointer user_data) { WockyPubsubService *self = WOCKY_PUBSUB_SERVICE (user_data); g_signal_emit (self, signals[SIG_NODE_DELETED], 0, node, stanza, event_node, delete_node); } static WockyPubsubNode * pubsub_service_create_node (WockyPubsubService *self, const gchar *name) { WockyPubsubServicePrivate *priv = self->priv; WockyPubsubServiceClass *class = WOCKY_PUBSUB_SERVICE_GET_CLASS (self); WockyPubsubNode *node; g_return_val_if_fail ( g_type_is_a (class->node_object_type, WOCKY_TYPE_PUBSUB_NODE), NULL); node = g_object_new (class->node_object_type, "service", self, "name", name, NULL); g_object_weak_ref (G_OBJECT (node), node_disposed_cb, self); g_hash_table_insert (priv->nodes, g_strdup (name), node); /* It's safe to never explicitly disconnect these handlers: the node holds a * reference to the service, so the service will always outlive the node. */ g_signal_connect (node, "event-received", (GCallback) pubsub_service_node_event_received_cb, self); g_signal_connect (node, "subscription-state-changed", (GCallback) pubsub_service_node_subscription_state_changed_cb, self); g_signal_connect (node, "deleted", (GCallback) pubsub_service_node_deleted_cb, self); return node; } /** * wocky_pubsub_service_ensure_node: * @self: a pubsub service * @name: the name of a node on @self * * Fetches or creates an object representing a node on the pubsub service. Note * that this does not ensure that a node exists on the server; it merely * ensures a local representation. * * Returns: a new reference to an object representing a node named @name on * @self */ WockyPubsubNode * wocky_pubsub_service_ensure_node (WockyPubsubService *self, const gchar *name) { WockyPubsubServicePrivate *priv = self->priv; WockyPubsubNode *node; node = g_hash_table_lookup (priv->nodes, name); if (node != NULL) return g_object_ref (node); else return pubsub_service_create_node (self, name); } /** * wocky_pubsub_service_lookup_node: * @self: a pubsub service * @name: the name of a node on @self * * Fetches an object representing a node on a pubsub service, if the object * already exists; if not, returns %NULL. Note that this does not check whether * a node exists on the server; it only checks for a local representation. * * Returns: a borrowed reference to a node, or %NULL */ WockyPubsubNode * wocky_pubsub_service_lookup_node (WockyPubsubService *self, const gchar *name) { WockyPubsubServicePrivate *priv = self->priv; return g_hash_table_lookup (priv->nodes, name); } static gboolean pubsub_service_propagate_event (WockyPorter *porter, WockyStanza *event_stanza, gpointer user_data) { EventTrampoline *trampoline = user_data; WockyPubsubService *self = trampoline->self; WockyNode *event_node, *action_node; const gchar *node_name; WockyPubsubNode *node; g_assert (WOCKY_IS_PUBSUB_SERVICE (self)); event_node = wocky_node_get_child_ns ( wocky_stanza_get_top_node (event_stanza), "event", WOCKY_XMPP_NS_PUBSUB_EVENT); g_return_val_if_fail (event_node != NULL, FALSE); action_node = wocky_node_get_child (event_node, trampoline->mapping->action); g_return_val_if_fail (action_node != NULL, FALSE); node_name = wocky_node_get_attribute (action_node, "node"); if (node_name == NULL) { DEBUG_STANZA (event_stanza, "no node='' attribute on <%s/>", trampoline->mapping->action); return FALSE; } node = wocky_pubsub_service_ensure_node (self, node_name); trampoline->mapping->method (node, event_stanza, event_node, action_node); g_object_unref (node); return TRUE; } static void default_configuration_iq_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); GError *error = NULL; WockyNodeTree *default_tree; WockyDataForm *form; if (wocky_pubsub_distill_iq_reply (source, res, WOCKY_XMPP_NS_PUBSUB_OWNER, "default", &default_tree, &error)) { form = wocky_data_form_new_from_form ( wocky_node_tree_get_top_node (default_tree), &error); if (form != NULL) g_simple_async_result_set_op_res_gpointer (result, form, NULL); g_object_unref (default_tree); } if (error != NULL) { g_simple_async_result_set_from_error (result, error); g_clear_error (&error); } g_simple_async_result_complete (result); g_object_unref (result); } void wocky_pubsub_service_get_default_node_configuration_async ( WockyPubsubService *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyPubsubServicePrivate *priv = self->priv; WockyStanza *stanza; GSimpleAsyncResult *result; stanza = wocky_pubsub_make_stanza (priv->jid, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_XMPP_NS_PUBSUB_OWNER, "default", NULL, NULL); result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_pubsub_service_get_default_node_configuration_async); wocky_porter_send_iq_async (priv->porter, stanza, NULL, default_configuration_iq_cb, result); g_object_unref (stanza); } WockyDataForm * wocky_pubsub_service_get_default_node_configuration_finish ( WockyPubsubService *self, GAsyncResult *result, GError **error) { if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) return NULL; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), wocky_pubsub_service_get_default_node_configuration_async), NULL); return g_simple_async_result_get_op_res_gpointer ( G_SIMPLE_ASYNC_RESULT (result)); } WockyPubsubSubscription * wocky_pubsub_service_parse_subscription (WockyPubsubService *self, WockyNode *subscription_node, const gchar *parent_node_attr, GError **error) { const gchar *node; const gchar *jid = wocky_node_get_attribute (subscription_node, "jid"); const gchar *subscription = wocky_node_get_attribute (subscription_node, "subscription"); const gchar *subid = wocky_node_get_attribute (subscription_node, "subid"); WockyPubsubNode *node_obj; gint state; WockyPubsubSubscription *sub; if (parent_node_attr != NULL) node = parent_node_attr; else node = wocky_node_get_attribute (subscription_node, "node"); #define FAIL_IF_NULL(attr) \ if (attr == NULL) \ { \ g_set_error (error, WOCKY_PUBSUB_SERVICE_ERROR, \ WOCKY_PUBSUB_SERVICE_ERROR_WRONG_REPLY, \ " missing " #attr "='' attribute"); \ return NULL; \ } FAIL_IF_NULL (node); FAIL_IF_NULL (jid); FAIL_IF_NULL (subscription); /* subid is technically a MUST if the service supports it, but... */ #undef FAIL_IF_NULL if (!wocky_enum_from_nick (WOCKY_TYPE_PUBSUB_SUBSCRIPTION_STATE, subscription, &state)) { g_set_error (error, WOCKY_PUBSUB_SERVICE_ERROR, WOCKY_PUBSUB_SERVICE_ERROR_WRONG_REPLY, "subscription='%s' is not a valid state", subscription); return NULL; } node_obj = wocky_pubsub_service_ensure_node (self, node); sub = wocky_pubsub_subscription_new (node_obj, jid, state, subid); g_object_unref (node_obj); return sub; } GList * wocky_pubsub_service_parse_subscriptions (WockyPubsubService *self, WockyNode *subscriptions_node, GList **subscription_nodes) { const gchar *parent_node_attr = wocky_node_get_attribute ( subscriptions_node, "node"); GQueue subs = G_QUEUE_INIT; GQueue sub_nodes = G_QUEUE_INIT; WockyNode *n; WockyNodeIter i; wocky_node_iter_init (&i, subscriptions_node, "subscription", NULL); while (wocky_node_iter_next (&i, &n)) { GError *error = NULL; WockyPubsubSubscription *sub = wocky_pubsub_service_parse_subscription ( self, n, parent_node_attr, &error); if (sub != NULL) { g_queue_push_tail (&subs, sub); g_queue_push_tail (&sub_nodes, n); } else { DEBUG ("%s", error->message); g_clear_error (&error); } } if (subscription_nodes == NULL) g_queue_clear (&sub_nodes); else *subscription_nodes = sub_nodes.head; return subs.head; } static void receive_subscriptions_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); WockyPubsubService *self = WOCKY_PUBSUB_SERVICE ( g_async_result_get_source_object (user_data)); WockyNodeTree *subs_tree; GError *error = NULL; if (wocky_pubsub_distill_iq_reply (source, res, WOCKY_XMPP_NS_PUBSUB, "subscriptions", &subs_tree, &error)) { GList *subs = wocky_pubsub_service_parse_subscriptions (self, wocky_node_tree_get_top_node (subs_tree), NULL); g_simple_async_result_set_op_res_gpointer (simple, subs, (GDestroyNotify) wocky_pubsub_subscription_list_free); g_object_unref (subs_tree); } else { g_simple_async_result_set_from_error (simple, error); g_clear_error (&error); } g_simple_async_result_complete (simple); g_object_unref (simple); g_object_unref (self); } WockyStanza * wocky_pubsub_service_create_retrieve_subscriptions_stanza ( WockyPubsubService *self, WockyPubsubNode *node, WockyNode **pubsub_node, WockyNode **subscriptions_node) { WockyPubsubServicePrivate *priv = self->priv; WockyStanza *stanza; WockyNode *subscriptions; stanza = wocky_pubsub_make_stanza (priv->jid, WOCKY_STANZA_SUB_TYPE_GET, WOCKY_XMPP_NS_PUBSUB, "subscriptions", pubsub_node, &subscriptions); if (node != NULL) wocky_node_set_attribute (subscriptions, "node", wocky_pubsub_node_get_name (node)); if (subscriptions_node != NULL) *subscriptions_node = subscriptions; return stanza; } void wocky_pubsub_service_retrieve_subscriptions_async ( WockyPubsubService *self, WockyPubsubNode *node, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyPubsubServicePrivate *priv = self->priv; GSimpleAsyncResult *simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_pubsub_service_retrieve_subscriptions_async); WockyStanza *stanza; stanza = wocky_pubsub_service_create_retrieve_subscriptions_stanza (self, node, NULL, NULL); wocky_porter_send_iq_async (priv->porter, stanza, cancellable, receive_subscriptions_cb, simple); g_object_unref (stanza); } gboolean wocky_pubsub_service_retrieve_subscriptions_finish ( WockyPubsubService *self, GAsyncResult *result, GList **subscriptions, GError **error) { wocky_implement_finish_copy_pointer (self, wocky_pubsub_service_retrieve_subscriptions_async, wocky_pubsub_subscription_list_copy, subscriptions); } /** * wocky_pubsub_service_handle_create_node_reply: * @self: a pubsub service * @create_tree: the <create/> tree from the reply to an attempt to * create a node, or %NULL if none was present in the reply. * @requested_name: the name we asked the server to use for the node, or %NULL * if we requested an instant node * @error: location at which to store an error * * Handles the body of a reply to a create node request. This is * ever-so-slightly involved, because the server is allowed to omit the body of * the reply if you specified a node name and it created a node with that name, * but it may also tell you "hey, you asked for 'ringo', but I gave you * 'george'". Good times. * * Returns: a pubsub node if the reply made sense, or %NULL with @error set if * not. */ WockyPubsubNode * wocky_pubsub_service_handle_create_node_reply ( WockyPubsubService *self, WockyNodeTree *create_tree, const gchar *requested_name, GError **error) { WockyPubsubNode *node = NULL; const gchar *name = NULL; if (create_tree != NULL) { /* If the reply contained , it'd better contain the * nodeID. */ name = wocky_node_get_attribute ( wocky_node_tree_get_top_node (create_tree), "node"); if (name == NULL) g_set_error (error, WOCKY_PUBSUB_SERVICE_ERROR, WOCKY_PUBSUB_SERVICE_ERROR_WRONG_REPLY, "reply doesn't contain node='' attribute"); } else if (requested_name == NULL) { g_set_error (error, WOCKY_PUBSUB_SERVICE_ERROR, WOCKY_PUBSUB_SERVICE_ERROR_WRONG_REPLY, "requested an instant node, but the server did not report the " "newly-created node's name"); } else { name = requested_name; } if (name != NULL) { node = wocky_pubsub_service_ensure_node (self, name); DEBUG ("node %s created\n", name); } return node; } static void create_node_iq_cb (GObject *source, GAsyncResult *res, gpointer user_data) { GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data); WockyPubsubService *self; WockyPubsubNode *node = NULL; const gchar *requested_name; WockyNodeTree *create_tree; GError *error = NULL; self = WOCKY_PUBSUB_SERVICE (g_async_result_get_source_object (user_data)); requested_name = g_object_get_data ((GObject *) result, "requested-name"); if (wocky_pubsub_distill_ambivalent_iq_reply (source, res, WOCKY_XMPP_NS_PUBSUB, "create", &create_tree, &error)) { node = wocky_pubsub_service_handle_create_node_reply (self, create_tree, requested_name, &error); if (create_tree != NULL) g_object_unref (create_tree); } if (node != NULL) { /* 'result' steals our reference to 'node' */ g_simple_async_result_set_op_res_gpointer (result, node, g_object_unref); } else { g_assert (error != NULL); g_simple_async_result_set_from_error (result, error); g_clear_error (&error); } g_simple_async_result_complete (result); g_object_unref (result); g_object_unref (self); } WockyStanza * wocky_pubsub_service_create_create_node_stanza ( WockyPubsubService *self, const gchar *name, WockyDataForm *config, WockyNode **pubsub_node, WockyNode **create_node) { WockyPubsubServicePrivate *priv = self->priv; WockyStanza *stanza; WockyNode *pubsub, *create; stanza = wocky_pubsub_make_stanza (priv->jid, WOCKY_STANZA_SUB_TYPE_SET, WOCKY_XMPP_NS_PUBSUB, "create", &pubsub, &create); if (name != NULL) wocky_node_set_attribute (create, "node", name); if (config != NULL) wocky_data_form_submit (config, wocky_node_add_child (pubsub, "configure")); if (pubsub_node != NULL) *pubsub_node = pubsub; if (create_node != NULL) *create_node = create; return stanza; } void wocky_pubsub_service_create_node_async (WockyPubsubService *self, const gchar *name, WockyDataForm *config, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { WockyPubsubServicePrivate *priv = self->priv; WockyStanza *stanza = wocky_pubsub_service_create_create_node_stanza ( self, name, config, NULL, NULL); GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, wocky_pubsub_service_create_node_async); g_object_set_data_full ((GObject *) result, "requested-name", g_strdup (name), g_free); wocky_porter_send_iq_async (priv->porter, stanza, NULL, create_node_iq_cb, result); g_object_unref (stanza); } WockyPubsubNode * wocky_pubsub_service_create_node_finish (WockyPubsubService *self, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple; WockyPubsubNode *node; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), wocky_pubsub_service_create_node_async), NULL); simple = (GSimpleAsyncResult *) result; if (g_simple_async_result_propagate_error (simple, error)) return NULL; node = WOCKY_PUBSUB_NODE (g_simple_async_result_get_op_res_gpointer (simple)); return g_object_ref (node); } WockyPorter * wocky_pubsub_service_get_porter (WockyPubsubService *self) { WockyPubsubServicePrivate *priv = self->priv; return priv->porter; } WockyPubsubSubscription * wocky_pubsub_subscription_new ( WockyPubsubNode *node, const gchar *jid, WockyPubsubSubscriptionState state, const gchar *subid) { WockyPubsubSubscription *sub = g_slice_new (WockyPubsubSubscription); sub->node = g_object_ref (node); sub->jid = g_strdup (jid); sub->state = state; sub->subid = g_strdup (subid); return sub; } WockyPubsubSubscription * wocky_pubsub_subscription_copy (WockyPubsubSubscription *sub) { g_return_val_if_fail (sub != NULL, NULL); return wocky_pubsub_subscription_new (sub->node, sub->jid, sub->state, sub->subid); } void wocky_pubsub_subscription_free (WockyPubsubSubscription *sub) { g_return_if_fail (sub != NULL); g_object_unref (sub->node); g_free (sub->jid); g_free (sub->subid); g_slice_free (WockyPubsubSubscription, sub); } GList * wocky_pubsub_subscription_list_copy (GList *subs) { return wocky_list_deep_copy ((GBoxedCopyFunc) wocky_pubsub_subscription_copy, subs); } void wocky_pubsub_subscription_list_free (GList *subs) { g_list_foreach (subs, (GFunc) wocky_pubsub_subscription_free, NULL); g_list_free (subs); } GType wocky_pubsub_subscription_get_type (void) { static GType t = 0; if (G_UNLIKELY (t == 0)) t = g_boxed_type_register_static ("WockyPubsubSubscription", (GBoxedCopyFunc) wocky_pubsub_subscription_copy, (GBoxedFreeFunc) wocky_pubsub_subscription_free); return t; } /** * WockyPubsubServiceClass: * @parent_class: parent * @node_object_type: the subtype of #WOCKY_TYPE_PUBSUB_NODE to be created by * wocky_pubsub_service_ensure_node() * * The class structure for the #WockyPubsubService type. */ /** * WockyPubsubSubscription: * @node: a PubSub node * @jid: the JID which is subscribed to @node. This may be a bare JID, or a * full JID with a resource, depending on which was specified when * subscribing to @node. See XEP-0060 §6.1 Subscribe to a Node * @state: the state of this subscription * @subid: a unique identifier for this subscription, if a JID is subscribed to * a node multiple times, or %NULL if there is no such identifier. See * XEP-0060 §6.1.6 “Multiple Subscriptions” * * Represents a subscription to a node on a pubsub service, as seen when * listing your own subscriptions on a service with * wocky_pubsub_service_retrieve_subscriptions_async() or subscribing to a node * with wocky_pubsub_node_subscribe_async(). */ /** * WockyPubsubSubscriptionState: * @WOCKY_PUBSUB_SUBSCRIPTION_NONE: The node MUST NOT send event notifications * or payloads to the Entity. * @WOCKY_PUBSUB_SUBSCRIPTION_PENDING: An entity has requested to subscribe to * a node and the request has not yet been approved by a node owner. The node * MUST NOT send event notifications or payloads to the entity while it is in * this state. * @WOCKY_PUBSUB_SUBSCRIPTION_SUBSCRIBED: An entity has subscribed but its * subscription options have not yet been configured. The node MAY send event * notifications or payloads to the entity while it is in this state. The * service MAY timeout unconfigured subscriptions. * @WOCKY_PUBSUB_SUBSCRIPTION_UNCONFIGURED: An entity is subscribed to a node. * The node MUST send all event notifications (and, if configured, payloads) * to the entity while it is in this state (subject to subscriber * configuration and content filtering). * * Describes the state of a subscription to a node. Definitions are taken from * XEP-0060 * §4.2. */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-pep-service.h0000664000175000017500000000600211720661341025560 0ustar00cassidycassidy00000000000000/* * wocky-pep-service.h - Header of WockyPepService * Copyright © 2009, 2012 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_PEP_SERVICE_H__ #define __WOCKY_PEP_SERVICE_H__ #include #include #include "wocky-stanza.h" #include "wocky-session.h" G_BEGIN_DECLS /** * WockyPepService: * * Object to aid with looking up PEP nodes and listening for changes. */ typedef struct _WockyPepService WockyPepService; /** * WockyPepServiceClass: * * The class of a #WockyPepService. */ typedef struct _WockyPepServiceClass WockyPepServiceClass; typedef struct _WockyPepServicePrivate WockyPepServicePrivate; struct _WockyPepServiceClass { /**/ GObjectClass parent_class; }; struct _WockyPepService { /**/ GObject parent; WockyPepServicePrivate *priv; }; GType wocky_pep_service_get_type (void); #define WOCKY_TYPE_PEP_SERVICE \ (wocky_pep_service_get_type ()) #define WOCKY_PEP_SERVICE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_PEP_SERVICE, \ WockyPepService)) #define WOCKY_PEP_SERVICE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_PEP_SERVICE, \ WockyPepServiceClass)) #define WOCKY_IS_PEP_SERVICE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_PEP_SERVICE)) #define WOCKY_IS_PEP_SERVICE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_PEP_SERVICE)) #define WOCKY_PEP_SERVICE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_PEP_SERVICE, \ WockyPepServiceClass)) WockyPepService * wocky_pep_service_new (const gchar *node, gboolean subscribe) G_GNUC_WARN_UNUSED_RESULT; void wocky_pep_service_start (WockyPepService *self, WockySession *session); void wocky_pep_service_get_async (WockyPepService *self, WockyBareContact *contact, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); WockyStanza * wocky_pep_service_get_finish (WockyPepService *self, GAsyncResult *result, WockyNode **item, GError **error) G_GNUC_WARN_UNUSED_RESULT; WockyStanza * wocky_pep_service_make_publish_stanza (WockyPepService *self, WockyNode **item) G_GNUC_WARN_UNUSED_RESULT; G_END_DECLS #endif /* __WOCKY_PEP_SERVICE_H__ */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-sasl-plain.h0000664000175000017500000000244011720661341025403 0ustar00cassidycassidy00000000000000#if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef _WOCKY_SASL_PLAIN_H #define _WOCKY_SASL_PLAIN_H #include #include "wocky-auth-handler.h" G_BEGIN_DECLS #define WOCKY_TYPE_SASL_PLAIN wocky_sasl_plain_get_type() #define WOCKY_SASL_PLAIN(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), WOCKY_TYPE_SASL_PLAIN, WockySaslPlain)) #define WOCKY_SASL_PLAIN_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), WOCKY_TYPE_SASL_PLAIN, \ WockySaslPlainClass)) #define WOCKY_IS_SASL_PLAIN(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WOCKY_TYPE_SASL_PLAIN)) #define WOCKY_IS_SASL_PLAIN_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), WOCKY_TYPE_SASL_PLAIN)) #define WOCKY_SASL_PLAIN_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_SASL_PLAIN, \ WockySaslPlainClass)) typedef struct _WockySaslPlainPrivate WockySaslPlainPrivate; typedef struct { GObject parent; WockySaslPlainPrivate *priv; } WockySaslPlain; typedef struct { GObjectClass parent_class; } WockySaslPlainClass; GType wocky_sasl_plain_get_type (void); WockySaslPlain *wocky_sasl_plain_new ( const gchar *username, const gchar *password); G_END_DECLS #endif /* defined _WOCKY_SASL_PLAIN_H */ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/Makefile.in0000664000175000017500000013111112332443664024106 0ustar00cassidycassidy00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ DIST_COMMON = $(top_srcdir)/tools/flymake.mk \ $(top_srcdir)/tools/check-coding-style.mk \ $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/wocky-uninstalled.pc.in $(srcdir)/wocky.pc.in \ $(top_srcdir)/depcomp $(am__libwocky_la_HEADERS_DIST) @USING_OPENSSL_TRUE@am__append_1 = $(OPENSSL_SRC) @USING_OPENSSL_TRUE@am__append_2 = $(GNUTLS_SRC) @USING_OPENSSL_FALSE@am__append_3 = $(GNUTLS_SRC) @USING_OPENSSL_FALSE@am__append_4 = $(OPENSSL_SRC) @HAVE_GIO_PROXY_TRUE@am__append_5 = $(PROXY_SRC) @HAVE_GIO_PROXY_FALSE@am__append_6 = $(PROXY_SRC) subdir = wocky ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/as-compiler-flag.m4 \ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/tp-compiler-flag.m4 \ $(top_srcdir)/m4/tp-compiler-warnings.m4 \ $(top_srcdir)/m4/wocky-gcov.m4 $(top_srcdir)/m4/wocky-lcov.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = wocky-uninstalled.pc wocky.pc CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \ "$(DESTDIR)$(libwocky_ladir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) am__DEPENDENCIES_1 = libwocky_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am__libwocky_la_SOURCES_DIST = wocky.c wocky-auth-handler.c \ wocky-auth-registry.c wocky-bare-contact.c wocky-c2s-porter.c \ wocky-caps-cache.c wocky-ll-connection-factory.c \ wocky-caps-hash.c wocky-connector.c wocky-contact.c \ wocky-contact-factory.c wocky-data-form.c wocky-debug.c \ wocky-debug-internal.h wocky-disco-identity.c \ wocky-heartbeat-source.c wocky-heartbeat-source.h \ wocky-google-relay.c wocky-jabber-auth.c \ wocky-jabber-auth-digest.c wocky-jabber-auth-password.c \ wocky-jingle-content.c wocky-jingle-factory.c \ wocky-jingle-info.c wocky-jingle-media-rtp.c \ wocky-jingle-session.c wocky-jingle-transport-google.c \ wocky-jingle-transport-iceudp.c wocky-jingle-transport-iface.c \ wocky-jingle-transport-rawudp.c wocky-ll-connector.c \ wocky-ll-contact.c wocky-loopback-stream.c wocky-meta-porter.c \ wocky-muc.c wocky-node.c wocky-node-private.h \ wocky-node-tree.c wocky-pep-service.c wocky-ping.c \ wocky-porter.c wocky-pubsub-helpers.c wocky-pubsub-node.c \ wocky-pubsub-node-internal.h wocky-pubsub-service.c \ wocky-resource-contact.c wocky-roster.c wocky-sasl-auth.c \ wocky-sasl-digest-md5.c wocky-sasl-scram.c wocky-sasl-utils.c \ wocky-sasl-plain.c wocky-session.c wocky-stanza.c \ wocky-utils.c wocky-tls-common.c wocky-tls-handler.c \ wocky-tls-connector.c wocky-xep-0115-capabilities.c \ wocky-xmpp-connection.c wocky-xmpp-error.c wocky-xmpp-reader.c \ wocky-xmpp-writer.c wocky-openssl.c wocky-openssl-dh512.c \ wocky-openssl-dh1024.c wocky-openssl-dh2048.c \ wocky-openssl-dh4096.c wocky-tls.c wocky-http-proxy.h \ wocky-http-proxy.c wocky-enumtypes.c wocky-signals-marshal.c \ wocky-signals-marshal.list wocky.h wocky-auth-handler.h \ wocky-auth-registry.h wocky-bare-contact.h wocky-c2s-porter.h \ wocky-caps-cache.h wocky-ll-connection-factory.h \ wocky-caps-hash.h wocky-connector.h wocky-contact.h \ wocky-contact-factory.h wocky-data-form.h wocky-debug.h \ wocky-disco-identity.h wocky-google-relay.h \ wocky-jabber-auth.h wocky-jabber-auth-digest.h \ wocky-jabber-auth-password.h wocky-jingle-content.h \ wocky-jingle-factory.h wocky-jingle-info-internal.h \ wocky-jingle-info.h wocky-jingle-media-rtp.h \ wocky-jingle-session.h wocky-jingle-transport-google.h \ wocky-jingle-transport-iceudp.h wocky-jingle-transport-iface.h \ wocky-jingle-transport-rawudp.h wocky-jingle-types.h \ wocky-ll-connector.h wocky-ll-contact.h \ wocky-loopback-stream.h wocky-meta-porter.h wocky-muc.h \ wocky-namespaces.h wocky-node.h wocky-node-tree.h \ wocky-pep-service.h wocky-ping.h wocky-porter.h \ wocky-pubsub-helpers.h wocky-pubsub-node.h \ wocky-pubsub-node-protected.h wocky-pubsub-service.h \ wocky-pubsub-service-protected.h wocky-resource-contact.h \ wocky-roster.h wocky-sasl-auth.h wocky-sasl-utils.h \ wocky-sasl-digest-md5.h wocky-sasl-scram.h wocky-sasl-plain.h \ wocky-session.h wocky-stanza.h wocky-tls.h wocky-tls-handler.h \ wocky-tls-connector.h wocky-types.h wocky-utils.h \ wocky-xep-0115-capabilities.h wocky-xmpp-connection.h \ wocky-xmpp-error.h wocky-xmpp-reader.h wocky-xmpp-writer.h \ wocky-enumtypes.h wocky-signals-marshal.h am__objects_1 = wocky-openssl.lo wocky-openssl-dh512.lo \ wocky-openssl-dh1024.lo wocky-openssl-dh2048.lo \ wocky-openssl-dh4096.lo @USING_OPENSSL_TRUE@am__objects_2 = $(am__objects_1) am__objects_3 = wocky-tls.lo @USING_OPENSSL_FALSE@am__objects_4 = $(am__objects_3) am__objects_5 = wocky-http-proxy.lo @HAVE_GIO_PROXY_TRUE@am__objects_6 = $(am__objects_5) am__objects_7 = wocky.lo wocky-auth-handler.lo wocky-auth-registry.lo \ wocky-bare-contact.lo wocky-c2s-porter.lo wocky-caps-cache.lo \ wocky-ll-connection-factory.lo wocky-caps-hash.lo \ wocky-connector.lo wocky-contact.lo wocky-contact-factory.lo \ wocky-data-form.lo wocky-debug.lo wocky-disco-identity.lo \ wocky-heartbeat-source.lo wocky-google-relay.lo \ wocky-jabber-auth.lo wocky-jabber-auth-digest.lo \ wocky-jabber-auth-password.lo wocky-jingle-content.lo \ wocky-jingle-factory.lo wocky-jingle-info.lo \ wocky-jingle-media-rtp.lo wocky-jingle-session.lo \ wocky-jingle-transport-google.lo \ wocky-jingle-transport-iceudp.lo \ wocky-jingle-transport-iface.lo \ wocky-jingle-transport-rawudp.lo wocky-ll-connector.lo \ wocky-ll-contact.lo wocky-loopback-stream.lo \ wocky-meta-porter.lo wocky-muc.lo wocky-node.lo \ wocky-node-tree.lo wocky-pep-service.lo wocky-ping.lo \ wocky-porter.lo wocky-pubsub-helpers.lo wocky-pubsub-node.lo \ wocky-pubsub-service.lo wocky-resource-contact.lo \ wocky-roster.lo wocky-sasl-auth.lo wocky-sasl-digest-md5.lo \ wocky-sasl-scram.lo wocky-sasl-utils.lo wocky-sasl-plain.lo \ wocky-session.lo wocky-stanza.lo wocky-utils.lo \ wocky-tls-common.lo wocky-tls-handler.lo \ wocky-tls-connector.lo wocky-xep-0115-capabilities.lo \ wocky-xmpp-connection.lo wocky-xmpp-error.lo \ wocky-xmpp-reader.lo wocky-xmpp-writer.lo $(am__objects_2) \ $(am__objects_4) $(am__objects_6) am__objects_8 = wocky-enumtypes.lo wocky-signals-marshal.lo am__objects_9 = am_libwocky_la_OBJECTS = $(am__objects_7) $(am__objects_8) \ $(am__objects_9) $(am__objects_9) libwocky_la_OBJECTS = $(am_libwocky_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libwocky_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libwocky_la_LDFLAGS) $(LDFLAGS) -o $@ @ENABLE_SHARED_SUFFIX_FALSE@am_libwocky_la_rpath = @ENABLE_SHARED_SUFFIX_TRUE@am_libwocky_la_rpath = -rpath $(libdir) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libwocky_la_SOURCES) DIST_SOURCES = $(am__libwocky_la_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgconfig_DATA) am__libwocky_la_HEADERS_DIST = wocky.h wocky-auth-handler.h \ wocky-auth-registry.h wocky-bare-contact.h wocky-c2s-porter.h \ wocky-caps-cache.h wocky-ll-connection-factory.h \ wocky-caps-hash.h wocky-connector.h wocky-contact.h \ wocky-contact-factory.h wocky-data-form.h wocky-debug.h \ wocky-disco-identity.h wocky-google-relay.h \ wocky-jabber-auth.h wocky-jabber-auth-digest.h \ wocky-jabber-auth-password.h wocky-jingle-content.h \ wocky-jingle-factory.h wocky-jingle-info-internal.h \ wocky-jingle-info.h wocky-jingle-media-rtp.h \ wocky-jingle-session.h wocky-jingle-transport-google.h \ wocky-jingle-transport-iceudp.h wocky-jingle-transport-iface.h \ wocky-jingle-transport-rawudp.h wocky-jingle-types.h \ wocky-ll-connector.h wocky-ll-contact.h \ wocky-loopback-stream.h wocky-meta-porter.h wocky-muc.h \ wocky-namespaces.h wocky-node.h wocky-node-tree.h \ wocky-pep-service.h wocky-ping.h wocky-porter.h \ wocky-pubsub-helpers.h wocky-pubsub-node.h \ wocky-pubsub-node-protected.h wocky-pubsub-service.h \ wocky-pubsub-service-protected.h wocky-resource-contact.h \ wocky-roster.h wocky-sasl-auth.h wocky-sasl-utils.h \ wocky-sasl-digest-md5.h wocky-sasl-scram.h wocky-sasl-plain.h \ wocky-session.h wocky-stanza.h wocky-tls.h wocky-tls-handler.h \ wocky-tls-connector.h wocky-types.h wocky-utils.h \ wocky-xep-0115-capabilities.h wocky-xmpp-connection.h \ wocky-xmpp-error.h wocky-xmpp-reader.h wocky-xmpp-writer.h \ wocky-enumtypes.h wocky-signals-marshal.h HEADERS = $(libwocky_la_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_CODING_STYLE_CHECKS = @ENABLE_CODING_STYLE_CHECKS@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ FFLAGS = @FFLAGS@ FGREP = @FGREP@ GCOV = @GCOV@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_LIBS = @GCOV_LIBS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_FOR_STREAM_CIPHERS_CFLAGS = @GNUTLS_FOR_STREAM_CIPHERS_CFLAGS@ GNUTLS_FOR_STREAM_CIPHERS_LIBS = @GNUTLS_FOR_STREAM_CIPHERS_LIBS@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HEADER_DIR = @HEADER_DIR@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LCOV_PATH = @LCOV_PATH@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBIPHB_CFLAGS = @LIBIPHB_CFLAGS@ LIBIPHB_LIBS = @LIBIPHB_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBSASL2_CFLAGS = @LIBSASL2_CFLAGS@ LIBSASL2_LIBS = @LIBSASL2_LIBS@ LIBTOOL = @LIBTOOL@ LIBXML2_CFLAGS = @LIBXML2_CFLAGS@ LIBXML2_LIBS = @LIBXML2_LIBS@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MOSTLYCLEANFILES = @MOSTLYCLEANFILES@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHARED_SUFFIX = @SHARED_SUFFIX@ SHELL = @SHELL@ SOUP_CFLAGS = @SOUP_CFLAGS@ SOUP_LIBS = @SOUP_LIBS@ SQLITE_CFLAGS = @SQLITE_CFLAGS@ SQLITE_LIBS = @SQLITE_LIBS@ STRIP = @STRIP@ TLS_CFLAGS = @TLS_CFLAGS@ TLS_LIBS = @TLS_LIBS@ VERSION = @VERSION@ WOCKY_CFLAGS = @WOCKY_CFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ have_gcov = @have_gcov@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @ENABLE_SHARED_SUFFIX_TRUE@lib_LTLIBRARIES = libwocky.la @ENABLE_SHARED_SUFFIX_TRUE@libwocky_la_LDFLAGS = \ @ENABLE_SHARED_SUFFIX_TRUE@ -no-undefined \ @ENABLE_SHARED_SUFFIX_TRUE@ -release $(SHARED_SUFFIX) \ @ENABLE_SHARED_SUFFIX_TRUE@ $(NULL) @ENABLE_SHARED_SUFFIX_FALSE@noinst_LTLIBRARIES = libwocky.la EXTRA_DIST = $(am__append_2) $(am__append_4) $(am__append_6) enumtype_sources = \ $(srcdir)/wocky-auth-registry.h \ $(srcdir)/wocky-connector.h \ $(srcdir)/wocky-data-form.h \ $(srcdir)/wocky-jingle-info-internal.h \ $(srcdir)/wocky-jingle-types.h \ $(srcdir)/wocky-muc.h \ $(srcdir)/wocky-pubsub-node.h \ $(srcdir)/wocky-pubsub-service.h \ $(srcdir)/wocky-tls.h \ $(srcdir)/wocky-xmpp-error.h \ $(srcdir)/wocky-xmpp-reader.h built_headers = \ wocky-enumtypes.h \ wocky-signals-marshal.h built_sources = \ wocky-enumtypes.c \ wocky-signals-marshal.c \ wocky-signals-marshal.list BUILT_SOURCES = $(built_headers) $(built_sources) OPENSSL_SRC = \ wocky-openssl.c \ wocky-openssl-dh512.c \ wocky-openssl-dh1024.c \ wocky-openssl-dh2048.c \ wocky-openssl-dh4096.c GNUTLS_SRC = wocky-tls.c PROXY_SRC = \ wocky-http-proxy.h \ wocky-http-proxy.c handwritten_headers = \ wocky.h \ wocky-auth-handler.h \ wocky-auth-registry.h \ wocky-bare-contact.h \ wocky-c2s-porter.h \ wocky-caps-cache.h \ wocky-ll-connection-factory.h \ wocky-caps-hash.h \ wocky-connector.h \ wocky-contact.h \ wocky-contact-factory.h \ wocky-data-form.h \ wocky-debug.h \ wocky-disco-identity.h \ wocky-google-relay.h \ wocky-jabber-auth.h \ wocky-jabber-auth-digest.h \ wocky-jabber-auth-password.h \ wocky-jingle-content.h \ wocky-jingle-factory.h \ wocky-jingle-info-internal.h \ wocky-jingle-info.h \ wocky-jingle-media-rtp.h \ wocky-jingle-session.h \ wocky-jingle-transport-google.h \ wocky-jingle-transport-iceudp.h \ wocky-jingle-transport-iface.h \ wocky-jingle-transport-rawudp.h \ wocky-jingle-types.h \ wocky-ll-connector.h \ wocky-ll-contact.h \ wocky-loopback-stream.h \ wocky-meta-porter.h \ wocky-muc.h \ wocky-namespaces.h \ wocky-node.h \ wocky-node-tree.h \ wocky-pep-service.h \ wocky-ping.h \ wocky-porter.h \ wocky-pubsub-helpers.h \ wocky-pubsub-node.h \ wocky-pubsub-node-protected.h \ wocky-pubsub-service.h \ wocky-pubsub-service-protected.h \ wocky-resource-contact.h \ wocky-roster.h \ wocky-sasl-auth.h \ wocky-sasl-utils.h \ wocky-sasl-digest-md5.h \ wocky-sasl-scram.h \ wocky-sasl-plain.h \ wocky-session.h \ wocky-stanza.h \ wocky-tls.h \ wocky-tls-handler.h \ wocky-tls-connector.h \ wocky-types.h \ wocky-utils.h \ wocky-xep-0115-capabilities.h \ wocky-xmpp-connection.h \ wocky-xmpp-error.h \ wocky-xmpp-reader.h \ wocky-xmpp-writer.h handwritten_sources = wocky.c wocky-auth-handler.c \ wocky-auth-registry.c wocky-bare-contact.c wocky-c2s-porter.c \ wocky-caps-cache.c wocky-ll-connection-factory.c \ wocky-caps-hash.c wocky-connector.c wocky-contact.c \ wocky-contact-factory.c wocky-data-form.c wocky-debug.c \ wocky-debug-internal.h wocky-disco-identity.c \ wocky-heartbeat-source.c wocky-heartbeat-source.h \ wocky-google-relay.c wocky-jabber-auth.c \ wocky-jabber-auth-digest.c wocky-jabber-auth-password.c \ wocky-jingle-content.c wocky-jingle-factory.c \ wocky-jingle-info.c wocky-jingle-media-rtp.c \ wocky-jingle-session.c wocky-jingle-transport-google.c \ wocky-jingle-transport-iceudp.c wocky-jingle-transport-iface.c \ wocky-jingle-transport-rawudp.c wocky-ll-connector.c \ wocky-ll-contact.c wocky-loopback-stream.c wocky-meta-porter.c \ wocky-muc.c wocky-node.c wocky-node-private.h \ wocky-node-tree.c wocky-pep-service.c wocky-ping.c \ wocky-porter.c wocky-pubsub-helpers.c wocky-pubsub-node.c \ wocky-pubsub-node-internal.h wocky-pubsub-service.c \ wocky-resource-contact.c wocky-roster.c wocky-sasl-auth.c \ wocky-sasl-digest-md5.c wocky-sasl-scram.c wocky-sasl-utils.c \ wocky-sasl-plain.c wocky-session.c wocky-stanza.c \ wocky-utils.c wocky-tls-common.c wocky-tls-handler.c \ wocky-tls-connector.c wocky-xep-0115-capabilities.c \ wocky-xmpp-connection.c wocky-xmpp-error.c wocky-xmpp-reader.c \ wocky-xmpp-writer.c $(am__append_1) $(am__append_3) \ $(am__append_5) libwocky_la_SOURCES = $(handwritten_sources) $(built_sources) \ $(handwritten_headers) $(built_headers) @INSTALL_HEADERS_TRUE@libwocky_la_HEADERS = $(handwritten_headers) $(built_headers) @INSTALL_HEADERS_TRUE@libwocky_ladir = $(HEADER_DIR)/wocky @ENABLE_SHARED_SUFFIX_TRUE@@INSTALL_HEADERS_TRUE@pkgconfigdir = ${libdir}/pkgconfig @ENABLE_SHARED_SUFFIX_TRUE@@INSTALL_HEADERS_TRUE@pkgconfig_DATA = wocky.pc # Coding style checks check_c_sources = \ $(filter-out wocky-openssl%, \ $(filter-out wocky-tls.%, \ $(handwritten_sources) $(handwritten_headers) \ ) \ ) CLEANFILES = $(built_sources) $(built_headers) AM_CFLAGS = $(ERROR_CFLAGS) $(GCOV_CFLAGS) \ @GLIB_CFLAGS@ @LIBXML2_CFLAGS@ @SQLITE_CFLAGS@ @TLS_CFLAGS@ \ @LIBIPHB_CFLAGS@ \ @SOUP_CFLAGS@ \ -DG_LOG_DOMAIN=\"wocky\" \ -DWOCKY_COMPILATION libwocky_la_LIBADD = \ $(GCOV_LIBS) \ @GLIB_LIBS@ \ @LIBXML2_LIBS@ \ @SQLITE_LIBS@ \ @TLS_LIBS@ \ @LIBIPHB_LIBS@ \ @SOUP_LIBS@ \ $(NULL) all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/tools/flymake.mk $(top_srcdir)/tools/check-coding-style.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu wocky/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu wocky/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/tools/flymake.mk $(top_srcdir)/tools/check-coding-style.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): wocky-uninstalled.pc: $(top_builddir)/config.status $(srcdir)/wocky-uninstalled.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ wocky.pc: $(top_builddir)/config.status $(srcdir)/wocky.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libwocky.la: $(libwocky_la_OBJECTS) $(libwocky_la_DEPENDENCIES) $(EXTRA_libwocky_la_DEPENDENCIES) $(AM_V_CCLD)$(libwocky_la_LINK) $(am_libwocky_la_rpath) $(libwocky_la_OBJECTS) $(libwocky_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-auth-handler.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-auth-registry.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-bare-contact.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-c2s-porter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-caps-cache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-caps-hash.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-connector.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-contact-factory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-contact.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-data-form.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-debug.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-disco-identity.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-enumtypes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-google-relay.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-heartbeat-source.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-http-proxy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-jabber-auth-digest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-jabber-auth-password.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-jabber-auth.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-jingle-content.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-jingle-factory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-jingle-info.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-jingle-media-rtp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-jingle-session.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-jingle-transport-google.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-jingle-transport-iceudp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-jingle-transport-iface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-jingle-transport-rawudp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-ll-connection-factory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-ll-connector.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-ll-contact.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-loopback-stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-meta-porter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-muc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-node-tree.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-node.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-openssl-dh1024.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-openssl-dh2048.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-openssl-dh4096.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-openssl-dh512.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-openssl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-pep-service.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-ping.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-porter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-pubsub-helpers.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-pubsub-node.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-pubsub-service.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-resource-contact.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-roster.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-sasl-auth.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-sasl-digest-md5.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-sasl-plain.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-sasl-scram.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-sasl-utils.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-session.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-signals-marshal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-stanza.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-tls-common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-tls-connector.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-tls-handler.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-tls.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-utils.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-xep-0115-capabilities.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-xmpp-connection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-xmpp-error.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-xmpp-reader.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky-xmpp-writer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wocky.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ done uninstall-pkgconfigDATA: @$(NORMAL_UNINSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) install-libwocky_laHEADERS: $(libwocky_la_HEADERS) @$(NORMAL_INSTALL) @list='$(libwocky_la_HEADERS)'; test -n "$(libwocky_ladir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libwocky_ladir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libwocky_ladir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libwocky_ladir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libwocky_ladir)" || exit $$?; \ done uninstall-libwocky_laHEADERS: @$(NORMAL_UNINSTALL) @list='$(libwocky_la_HEADERS)'; test -n "$(libwocky_ladir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libwocky_ladir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(libwocky_ladir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-libwocky_laHEADERS install-pkgconfigDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES uninstall-libwocky_laHEADERS \ uninstall-pkgconfigDATA .MAKE: all check check-am install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am check-local clean \ clean-generic clean-libLTLIBRARIES clean-libtool \ clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am dist-hook \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES \ install-libwocky_laHEADERS install-man install-pdf \ install-pdf-am install-pkgconfigDATA install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-libLTLIBRARIES uninstall-libwocky_laHEADERS \ uninstall-pkgconfigDATA check-syntax: $(CC) $(AM_CPPFLAGS) $(AM_CFLAGS) -fsyntax-only $(CHK_SOURCES) .PHONY: check-syntax check-coding-style: @fail=0; \ if test -n "$(check_misc_sources)"; then \ tools_dir=$(top_srcdir)/tools \ sh $(top_srcdir)/tools/check-misc.sh \ $(addprefix $(srcdir)/,$(check_misc_sources)) || fail=1; \ fi; \ if test -n "$(check_c_sources)"; then \ tools_dir=$(top_srcdir)/tools \ sh $(top_srcdir)/tools/check-c-style.sh \ $(addprefix $(srcdir)/,$(check_c_sources)) || fail=1; \ fi;\ if test yes = "$(ENABLE_CODING_STYLE_CHECKS)"; then \ exit "$$fail";\ else \ exit 0;\ fi check-local: check-coding-style dist-hook: $(shell for x in $(CLEANFILES); do rm -f $(distdir)/$$x ; done) wocky-signals-marshal.list: $(handwritten_sources) Makefile.am $(AM_V_GEN)( cd $(srcdir) && \ sed -n -e 's/.*_wocky_signals_marshal_\([[:upper:][:digit:]]*__[[:upper:][:digit:]_]*\).*/\1/p' \ $(handwritten_sources) ) \ | sed -e 's/__/:/' -e 'y/_/,/' | sort -u > $@.tmp @if cmp -s $@.tmp $@; then \ rm $@.tmp; \ else \ mv $@.tmp $@; \ fi %-signals-marshal.h: %-signals-marshal.list Makefile.am $(AM_V_GEN)glib-genmarshal --header --prefix=_$(subst -,_,$*)_signals_marshal $< > $@ %-signals-marshal.c: %-signals-marshal.list Makefile.am $(AM_V_GEN){ echo '#include "$*-signals-marshal.h"' && \ glib-genmarshal --body --prefix=_$(subst -,_,$*)_signals_marshal $< ; \ } > $@ # rules for making the glib enum objects wocky-enumtypes.h: $(enumtype_sources) Makefile.am $(AM_V_GEN)glib-mkenums \ --fhead "#ifndef __WOCKY_ENUM_TYPES_H__\n#define __WOCKY_ENUM_TYPES_H__\n\n#include \n\nG_BEGIN_DECLS\n" \ --fprod "/* enumerations from \"@filename@\" */\n" \ --vhead "GType @enum_name@_get_type (void);\n#define WOCKY_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ --ftail "G_END_DECLS\n\n#endif /* __WOCKY_ENUM_TYPES_H__ */" \ $(enumtype_sources) > $@ wocky-enumtypes.c: $(enumtype_sources) Makefile.am $(AM_V_GEN)glib-mkenums \ --fhead "#include \"config.h\"\n" \ --fhead "#include <$*.h>" \ --fprod "\n/* enumerations from \"@filename@\" */\n#include \"@filename@\"" \ --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \ $(enumtype_sources) > $@ Android.mk: Makefile.am $(built_sources) $(built_headers) androgenizer -:PROJECT wocky -:SHARED wocky -:TAGS eng debug \ -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ -:SOURCES $(handwritten_sources) $(built_sources) \ -:CFLAGS $(DEFS) $(CFLAGS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CFLAGS) \ -:CPPFLAGS $(CPPFLAGS) $(AM_CPPFLAGS) \ -:LDFLAGS $(AM_LDFLAGS) $(libwocky_la_LIBADD) \ > $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-xmpp-writer.h0000664000175000017500000000606311720661341025643 0ustar00cassidycassidy00000000000000/* * wocky-xmpp-writer.h - Header for WockyXmppWriter * Copyright (C) 2006 Collabora Ltd. * @author Sjoerd Simons * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined (WOCKY_H_INSIDE) && !defined (WOCKY_COMPILATION) # error "Only can be included directly." #endif #ifndef __WOCKY_XMPP_WRITER_H__ #define __WOCKY_XMPP_WRITER_H__ #include #include "wocky-stanza.h" #include "wocky-node-tree.h" G_BEGIN_DECLS typedef struct _WockyXmppWriter WockyXmppWriter; /** * WockyXmppWriterClass: * * The class of a #WockyXmppWriter. */ typedef struct _WockyXmppWriterClass WockyXmppWriterClass; typedef struct _WockyXmppWriterPrivate WockyXmppWriterPrivate; struct _WockyXmppWriterClass { /**/ GObjectClass parent_class; }; struct _WockyXmppWriter { /**/ GObject parent; WockyXmppWriterPrivate *priv; }; GType wocky_xmpp_writer_get_type (void); /* TYPE MACROS */ #define WOCKY_TYPE_XMPP_WRITER \ (wocky_xmpp_writer_get_type ()) #define WOCKY_XMPP_WRITER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), WOCKY_TYPE_XMPP_WRITER, \ WockyXmppWriter)) #define WOCKY_XMPP_WRITER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), WOCKY_TYPE_XMPP_WRITER, \ WockyXmppWriterClass)) #define WOCKY_IS_XMPP_WRITER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), WOCKY_TYPE_XMPP_WRITER)) #define WOCKY_IS_XMPP_WRITER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), WOCKY_TYPE_XMPP_WRITER)) #define WOCKY_XMPP_WRITER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), WOCKY_TYPE_XMPP_WRITER, \ WockyXmppWriterClass)) WockyXmppWriter *wocky_xmpp_writer_new (void); WockyXmppWriter *wocky_xmpp_writer_new_no_stream (void); void wocky_xmpp_writer_stream_open (WockyXmppWriter *writer, const gchar *to, const gchar *from, const gchar *version, const gchar *lang, const gchar *id, const guint8 **data, gsize *length); void wocky_xmpp_writer_stream_close (WockyXmppWriter *writer, const guint8 **data, gsize *length); void wocky_xmpp_writer_write_stanza (WockyXmppWriter *writer, WockyStanza *stanza, const guint8 **data, gsize *length); void wocky_xmpp_writer_write_node_tree (WockyXmppWriter *writer, WockyNodeTree *tree, const guint8 **data, gsize *length); void wocky_xmpp_writer_flush (WockyXmppWriter *writer); G_END_DECLS #endif /* #ifndef __WOCKY_XMPP_WRITER_H__*/ telepathy-gabble-0.18.3/lib/ext/wocky/wocky/wocky-data-form.c0000664000175000017500000007056112212322440025205 0ustar00cassidycassidy00000000000000/* * wocky-data-form.c - WockyDataForm * Copyright © 2009–2010 Collabora Ltd. * Copyright © 2010 Nokia Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** * SECTION: wocky-data-form * @title: WockyDataForm * @short_description: An object to represent an XMPP data form * @include: wocky/wocky-data-form.h * * An object that represents an XMPP data form as described in * XEP-0004. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "wocky-data-form.h" #include #include "wocky-namespaces.h" #include "wocky-utils.h" #define WOCKY_DEBUG_FLAG WOCKY_DEBUG_DATA_FORM #include "wocky-debug-internal.h" G_DEFINE_TYPE (WockyDataForm, wocky_data_form, G_TYPE_OBJECT) /* properties */ enum { PROP_TITLE = 1, PROP_INSTRUCTIONS, }; /* private structure */ struct _WockyDataFormPrivate { gchar *title; gchar *instructions; /* (gchar *) => owned (WockyDataFormField *) */ GHashTable *reported; gboolean dispose_has_run; }; GQuark wocky_data_form_error_quark (void) { static GQuark quark = 0; if (quark == 0) quark = g_quark_from_static_string ("wocky-data-form-error"); return quark; } static WockyDataFormFieldOption * wocky_data_form_field_option_new (const gchar *label, const gchar *value) { WockyDataFormFieldOption *option; g_assert (value != NULL); option = g_slice_new0 (WockyDataFormFieldOption); option->label = g_strdup (label); option->value = g_strdup (value); return option; } static void wocky_data_form_field_option_free (WockyDataFormFieldOption *option) { g_free (option->label); g_free (option->value); g_slice_free (WockyDataFormFieldOption, option); } /* pass ownership of the default_value, raw_value_contents, the value * and the options list */ static WockyDataFormField * wocky_data_form_field_new ( WockyDataFormFieldType type, const gchar *var, const gchar *label, const gchar *desc, gboolean required, GValue *default_value, gchar **raw_value_contents, GValue *value, GSList *options) { WockyDataFormField *field; field = g_slice_new0 (WockyDataFormField); field->type = type; field->var = g_strdup (var); field->label = g_strdup (label); field->desc = g_strdup (desc); field->required = required; field->default_value = default_value; field->raw_value_contents = raw_value_contents; field->value = value; field->options = options; return field; } static void wocky_data_form_field_free (WockyDataFormField *field) { if (field == NULL) return; g_free (field->var); g_free (field->label); g_free (field->desc); g_strfreev (field->raw_value_contents); if (field->default_value != NULL) wocky_g_value_slice_free (field->default_value); if (field->value != NULL) wocky_g_value_slice_free (field->value); g_slist_foreach (field->options, (GFunc) wocky_data_form_field_option_free, NULL); g_slist_free (field->options); g_slice_free (WockyDataFormField, field); } static void wocky_data_form_init (WockyDataForm *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, WOCKY_TYPE_DATA_FORM, WockyDataFormPrivate); self->fields = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); self->fields_list = NULL; self->priv->reported = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) wocky_data_form_field_free); self->results = NULL; } static void wocky_data_form_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { WockyDataForm *self = WOCKY_DATA_FORM (object); WockyDataFormPrivate *priv = self->priv; switch (property_id) { case PROP_TITLE: priv->title = g_value_dup_string (value); break; case PROP_INSTRUCTIONS: priv->instructions = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_data_form_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { WockyDataForm *self = WOCKY_DATA_FORM (object); WockyDataFormPrivate *priv = self->priv; switch (property_id) { case PROP_TITLE: g_value_set_string (value, priv->title); break; case PROP_INSTRUCTIONS: g_value_set_string (value, priv->instructions); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wocky_data_form_dispose (GObject *object) { WockyDataForm *self = WOCKY_DATA_FORM (object); WockyDataFormPrivate *priv = self->priv; if (priv->dispose_has_run) return; priv->dispose_has_run = TRUE; if (G_OBJECT_CLASS (wocky_data_form_parent_class)->dispose) G_OBJECT_CLASS (wocky_data_form_parent_class)->dispose (object); } static void data_form_field_list_free (GSList *fields) { g_slist_foreach (fields, (GFunc) wocky_data_form_field_free, NULL); g_slist_free (fields); } static void wocky_data_form_finalize (GObject *object) { WockyDataForm *self = WOCKY_DATA_FORM (object); WockyDataFormPrivate *priv = self->priv; g_free (priv->title); g_free (priv->instructions); g_hash_table_unref (self->fields); data_form_field_list_free (self->fields_list); g_slist_foreach (self->results, (GFunc) data_form_field_list_free, NULL); g_slist_free (self->results); g_hash_table_unref (priv->reported); G_OBJECT_CLASS (wocky_data_form_parent_class)->finalize (object); } static void wocky_data_form_class_init ( WockyDataFormClass *wocky_data_form_class) { GObjectClass *object_class = G_OBJECT_CLASS (wocky_data_form_class); GParamSpec *param_spec; g_type_class_add_private (wocky_data_form_class, sizeof (WockyDataFormPrivate)); object_class->set_property = wocky_data_form_set_property; object_class->get_property = wocky_data_form_get_property; object_class->dispose = wocky_data_form_dispose; object_class->finalize = wocky_data_form_finalize; param_spec = g_param_spec_string ("title", "title", "Title", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_TITLE, param_spec); param_spec = g_param_spec_string ("instructions", "instructions", "Instructions", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_INSTRUCTIONS, param_spec); } static const gchar * type_to_str (WockyDataFormFieldType type) { return wocky_enum_to_nick (WOCKY_TYPE_DATA_FORM_FIELD_TYPE, type); } /* * extract_options_list: * @node: a node * * Returns: a list of (WockyDataFormFieldOption *) containing all the *
]]>

Subscribers receive the change notification, as usual for PEP. (For all the other PEP nodes described in this document, the process is the same, and has been omitted from this document for conciseness.)

10.0.0.123 Base64Base64... #005FE4,#00A0FF
]]>

In link-local XMPP, none of this happens. Instead, the ip4-address property is implicitly available, and the key and color properties are encoded in the _presence._tcp TXT record.

The 'color' property is mapped to the 'olpc-color' TXT record key:

11111@xo-12-34-56._presence._tcp.local. IN TXT "olpc-color=#005FE4,#00A0FF"

The 'key' property is mapped to the 'olpc-key-part0', 'olpc-key-part1', ... properties, split as necessary to fit in the 255-byte limit for TXT records. Because mDNS TXT records are 8-bit-clean, the segments contain raw binary rather than the Base64 binary used in XMPP:

11111@xo-12-34-56._presence._tcp.local. IN TXT "olpc-key-part0=binarybinary..." 11111@xo-12-34-56._presence._tcp.local. IN TXT "olpc-key-part1=binarybinary..." 11111@xo-12-34-56._presence._tcp.local. IN TXT "olpc-key-part2=binarybinary..."

(As currently implemented, the "raw binary" is in fact *also* Base64, so the data seen in XMPP is doubly Base64'd. However, this is not guaranteed to remain the case, so the protocols need to assume the underlying byte array for the key can contain anything.)

Implementors must be careful to ensure that there is no key in the TXT record for the key segment 1 greater than the last one they need (in this case, olpc-key-part3 must be removed if present).

The Neighbourhood view on the OLPC groups XO icons by their current activity, so XOs must notify each other of current-activity changes.

As currently implemented, this is done for both public and private activities, which represents an information leak. (FIXME)

Note that the 'type' attribute is in fact the activity ID; the name is for historical reasons.

room="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@conference.jabber.laptop.org" type="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"/>
]]>

In link-local XMPP, the current activity is mapped to a pair of keys in the TXT record: olpc-current-activity (the activity ID) and olpc-current-activity-room (the Salut rMulticast chat room name).

11111@xo-12-34-56._presence._tcp.local. IN TXT "olpc-current-activity=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 11111@xo-12-34-56._presence._tcp.local. IN TXT "olpc-current-activity-room=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"

For activities to be handled by the Sugar environment, certain properties are needed. Because there is no server-side storage corresponding to a chat room and accessible by all participants, participants each publish the properties of all their activities.

To keep participants' idea of the activity properties in sync, when the properties change, the participant making the change MUST send a broadcast message to the chatroom, notifying other participants of the new properties.

This <message/> MUST be sent before updating the PEP node with the activity properties.

to='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@conference.jabber.laptop.org'> org.laptop.Connect Connect Activity #005FE4,#00A0FF 0
]]>

For public activities, the participants all announce all their activities and their properties in a PEP node.

When an activity becomes private, the participants all delete it from their activity-properties PEP nodes.

org.laptop.Connect Connect Activity #005FE4,#00A0FF 0 org.laptop.HelloMesh Example Activity #005FE4,#00A0FF 0
]]>

The participants all announce all their list of activities in yet another PEP node, for backwards compatibility. This mechanism will be removed in a future version of this protocol.

Note that again, the 'type' attribute is in fact the activity ID; the name is for historical reasons.

]]>

In link-local XMPP, the activity properties are mapped to the _olpc-activity1._udp record. Each participant in each public activity publishes an mDNS service named chatroomname:publishedname@hostname, like so:

; Advertised by 11111... aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:11111@xo-12-34-56._olpc-activity1._udp.local. IN SRV 0 xo-12-34-56.local. _olpc-activity1._udp.local. IN PTR aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:11111@xo-12-34-56._olpc-activity1._udp.local. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "txtvers=0" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "room=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "activity-id=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "name=Connect Activity" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "color=#005FE4,#00A0FF" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "type=org.laptop.ConnectActivity" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "tags=" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:11111@xo-12-34-56._olpc-activity1._udp.local. IN SRV 0 xo-12-34-56.local. _olpc-activity1._udp.local. IN PTR bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:11111@xo-12-34-56._olpc-activity1._udp.local. bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "txtvers=0" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "room=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "activity-id=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "name=Example Activity" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "color=#005FE4,#00A0FF" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "type=org.laptop.HelloMesh" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:11111@xo-12-34-56._olpc-activity1._udp.local IN TXT "tags=" ; Advertised by 22222... - suppose here that 22222... is in the activity ; aaaaa... but not in bbbbb... aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:22222@xo-22-22-22._olpc-activity1._udp.local. IN SRV 0 xo-22-22-22.local. _olpc_activity._udp.local. IN PTR aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:22222@xo-22-22-22._olpc-activity1._udp.local. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:22222@xo-22-22-22._olpc-activity1._udp.local IN TXT "txtvers=0" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:22222@xo-22-22-22._olpc-activity1._udp.local IN TXT "room=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:22222@xo-22-22-22._olpc-activity1._udp.local IN TXT "activity-id=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:22222@xo-22-22-22._olpc-activity1._udp.local IN TXT "name=Connect Activity" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:22222@xo-22-22-22._olpc-activity1._udp.local IN TXT "color=#005FE4,#00A0FF" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:22222@xo-22-22-22._olpc-activity1._udp.local IN TXT "type=org.laptop.ConnectActivity" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:22222@xo-22-22-22._olpc-activity1._udp.local IN TXT "tags="

The <message/> sent to the chat room with the updated properties is much the same as for XMPP:

org.laptop.Connect Connect Activity #005FE4,#00A0FF 0 ]]>

When an activity becomes private, the participants all delete it from their activity-properties and activities PEP nodes. In this example, the XO whose JID starts with 11111 makes the activity whose ID starts with aaaaa private, and removes it from their PEP nodes; the XO whose JID starts with 22222 responds by removing it from their PEP nodes too.

To a third XO observing the PEP nodes, this is indistinguishable from both XOs leaving the activity simultaneously, which is what we want.

to='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@conference.jabber.laptop.org'> org.laptop.Connect Connect Activity #005FE4,#00A0FF 1
org.laptop.HelloMesh Example Activity #005FE4,#00A0FF 0 ]]>

Instead of deleting activities from their PEP records, link-local peers delete them from their mDNS records.

The <message/> sent to the chat room with the updated properties is, again, much the same as for XMPP.

Before inviting a buddy to an activity, OLPC users are expected to send them the activity properties. These are sent in a <message/> stanza referred to as a "pseudo-invitation". If the activity is private, then this is the only opportunity the invitee has to get the activity properties.

org.laptop.Connect Connect Activity #0d1c38,#49bce4 1 ]]>

If the activity properties change before the invitee joins the activity, the inviter must notify the invitee by re-sending the pseudo-invitation (only).

org.laptop.Connect this name changed #0d1c38,#49bce4 1
]]>

If the inviter leaves the activity before the invitee joins, the invitee can no longer rely on being notified about any changes; if the activity was private, the invitee can't even rely on being able to see whether it exists. Accordingly, the inviter should cancel their invitation; if all invitations to a private activity have been cancelled, the invitee should assume that the activity has disappeared.

]]>

There isn't the concept of sending an invitation via the MUC service in link-local XMPP, so the process can be made somewhat simpler.

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
224.0.0.1
23453 org.laptop.Connect Connect Activity #0d1c38,#49bce4 1
]]>
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
224.0.0.1
23453 org.laptop.Connect The name changed #0d1c38,#49bce4 1
]]>
]]>

Properties have the same syntax and semantics as the "parameters" in XEP-proto-tubes.

Putting the current activity in a PEP node, even if it's private, leaks the room name.

None.

None.

]]> ]]> ]]> ]]> telepathy-gabble-0.18.3/docs/Makefile.am0000664000175000017500000000176512332440117021170 0ustar00cassidycassidy00000000000000tools_dir = $(top_srcdir)/tools # htmldir is not defined by autoconf < 2.59c htmldir = $(if $(filter-out @%@,@htmldir@),@htmldir@,$(datadir)/doc/$(PACKAGE)) man_MANS = telepathy-gabble.8 html_DATA = \ olpc.html \ muc-bytestream.html \ si-multiple.html \ tubes.html EXTRA_DIST = \ $(man_MANS:.8=.8.in) \ $(html_DATA:.html=.xml) \ tube-caps.txt \ xep.dtd \ xep.ent \ xep.xsd \ xep.xsl CLEANFILES = \ $(man_MANS) \ $(html_DATA) %.8: %.8.in Makefile $(AM_V_GEN)sed -e 's,[@]libexecdir[@],@libexecdir@,' < $< > $@ $(html_DATA): %.html: %.xml xep.xsl xep.dtd xep.ent $(AM_V_GEN)$(XSLTPROC) $(srcdir)/xep.xsl $< > $@ proto-xep-upload: $(html_DATA) rsync -P $(html_DATA) people.collabora.co.uk:public_html/ .PHONY: proto-xep-upload maintainer-update-from-xmpp.org: set -e; \ for x in xep.dtd xep.ent xep.xsd xep.xsl; do \ uri=svn://svn.xmpp.org:7938/xmpp/trunk/extensions/$$x; \ svn info $$uri; \ svn cat $$uri > $$x.tmp; \ mv $$x.tmp $$x; \ done telepathy-gabble-0.18.3/docs/tube-caps.txt0000644000175000017500000000316211570651565021565 0ustar00cassidycassidy00000000000000Tubes are meant to allow arbitrary applications to communicate with your IM contacts. To know whether it's possible to start a StreamTube or DBusTube channel with a contact, we need to know whether they support tubes at all: Gabble advertises the capability "http://telepathy.freedesktop.org/xmpp/tubes/" (NS_TUBES) for that. But we also need to know whether, for example, Bob has an application that can handle VNC stream tubes (for Share My Desktop). At the XMPP level, that's implemented as advertising "http://telepathy.freedesktop.org/xmpp/tubes/stream#vnc". Gabble knows how to translate between this representation and the representation used on D-Bus. For XMPP → Telepathy, it translates "http://telepathy.freedesktop.org/xmpp/tubes/stream#$foo" into the channel class { ChannelType: StreamTube, StreamTube.Service: $foo, } In the other direction, it looks through the channel classes passed to ContactCapabilities.UpdateCapabilities and performs the reverse translation to figure out what to advertise on XMPP. Mission Control calls UpdateCapabilities by basically concatenating every installed or running client's HandlerChannelFilter property. So if you have a client installed that says it can handle { ChannelType: StreamTube, StreamTube.Service: "vnc", } MC relays that fact to Gabble, and Gabble can advertise the right capability. Thus, Gabble doesn't need to know anything at all about the possible applications that can be built on tubes to be able to advertise support for them. telepathy-gabble-0.18.3/docs/tubes.xml0000644000175000017500000011410211252175230020765 0ustar00cassidycassidy00000000000000 ]>
Tubes over XMPP A protocol for extensible collaboration over XMPP, designed specifically to implement Telepathy Tubes. This document is copyright 2007 Collabora Ltd. and may be distributed under the same terms as the Telepathy specification. proto-tubes ProtoXEP External extension Telepathy project Telepathy project XMPP Core XEP-0045 XEP-0047 XEP-0095 XEP-proto-muc-bytestream NOT YET ASSIGNED Simon McVittie simon.mcvittie@collabora.co.uk simon.mcvittie@collabora.co.uk Alban Crequy alban.crequy@collabora.co.uk alban.crequy@collabora.co.uk Robert McQueen robert.mcqueen@collabora.co.uk robert.mcqueen@collabora.co.uk Gabble 0.7.17 2008-12-14 ac/ram

Define Tube capabilities.

Gabble 0.7.0 2007-09-27 smcv
  • Don't copy stream tubes into MUC presence
  • Tube IDs must be numeric (uint32)
  • Don't put initiator in MUC stream tube info
  • Use a mesage-based protocol to offer 1-1 stream tubes, rather than the weird default bytestream thing
  • Non-initiator can close 1-1 stream tubes too
  • Remove /protocol/ from namespace URI
0.0.1 2007-09-25 smcv

First draft. Only protocol changes are listed in subsequent proto-XEP versions.

The XML namespace defined here is &NS_TUBES; (NS_TUBES in the telepathy-gabble source code).

The Telepathy project defines an API called Tubes to be used by arbitrary collaborative applications to communicate with instant messaging contacts. This API is intended to be the same for several IM protocols.

Tubes can be used in two types of context, referred to in Telepathy as Tubes channels:

  • In a multi-user chat room (on XMPP this means XEP-0045) - each MUC may have a tubes channel
  • On a peer-to-peer basis - each pair of contacts may have a Tubes channel

Each tube has a service name, used to dispatch it to an appropriate client application, and some essentially arbitrary parameters understood by that client application. The tube's initiator (the contact who started it) must also be tracked.

The following tube types are currently supported:

  • D-Bus - a D-Bus message stream. In a MUC context this behaves like the D-Bus bus daemon, so participants can send each other private messages, or can send broadcast messages which are received by everyone in the MUC (including themselves). Each MUC participant has a D-Bus unique name. In a 1-1 context this behaves like a peer-to-peer D-Bus connection - arbitrary D-Bus messages can be sent by each participant and are received by the other participant.
  • Stream - a TCP-like bytestream. The initiator exports a service using a listening socket. The other participant(s) can open one or more reliable stream connections which are forwarded through the instant messaging protocol as (possibly out-of-band) bytestreams.

As well as sending and receiving data, the following operations are supported:

  • List the tubes available in this Tubes channel, including their initiator, type, service, parameters and state
  • List the unique-names corresponding to the contacts (JIDs) in a D-Bus tube, if it's in a MUC channel
hello aGVsbG8= 123 -123 ]]> hello aGVsbG8= 123 -123 ]]> announcement. --> base64base64... ]]> hello aGVsbG8= 123 -123 anonymous password /plots/macbeth ]]> and not in order to disambiguate between SI-based streams in a MUC Tubes channel, and SI-based streams in a 1-1 channel between two members of a MUC. The first witch MUST NOT copy the tube into her own presence in this case - only the initiator should put stream tubes in their presence, since stream tubes cannot continue after the initiator leaves. --> ]]> hello aGVsbG8= 123 -123 ]]>

Leaving the MUC also implicitly implies leaving all tubes.

type='dbus' service='com.example.Chess' id='333'> montagues-vs-capulets.conf ]]> http://jabber.org/protocol/ibb ]]> /poetry/for-juliet/ ]]> http://jabber.org/protocol/ibb ]]>

If Juliet's web browser opens multiple parallel connections to her XMPP implementation, the implementation will open multiple parallel SI streams as shown above, and Romeo's XMPP implementation will open multiple parallel connections to his web server. This MUST be supported by implementations.

]]> ]]>

Only stream tubes use a message stanza to be closed. D-Bus tubes are closed implicitly when the underlying bytestream is closed and thus do not need an explicit message stanza.

swords ]]> swords ]]> ]]> swords swords ]]> swords /warez ]]> and not . Romeo MUST NOT copy the tube into his own tube announcements in this case - only the initiator should announce stream tubes, since stream tubes cannot continue after the initiator leaves. --> jabber:iq:oob x-tcp://angstbook.local:1234 ]]> swords ]]>

Leaving the link-local MUC (a leave or split event from rMulticast) also implicitly implies leaving all tubes.

The tube feature is advertised with XEP-0115 Entity Capabilities using this string:

http://telepathy.freedesktop.org/xmpp/tubes

We want to know which tube the contacts can handle. There is two different kind of tube capabilities:

  • Can my contact receive a tube offer of a specific service?
  • Can my contact offer a tube of a specific service?

Only the first kind is considered. The second is out of scope of this specification. Each specific service is advertised with XEP-0115 Entity Capabilities with this string:

http://telepathy.freedesktop.org/xmpp/tubes/$type#$service

where $type is the tube type (either "dbus" or "stream") and $service is the service name (e.g. "vnc" or "TicTacTube").

The D-Bus unique names used in the MUC SHOULD be ":2." followed by the MUC nick (i.e. the resource part of the MUC JID) processed with the following algorithm:

  • Let utf8nick be the MUC nick encoded using UTF-8
  • If utf8nick has 186 octets or fewer, encode it using Base64; otherwise encode a string consisting of the first 169 octets of utf8nick, followed by the 20 octets of the SHA-1 of utf8nick (note that this is the whole of the raw binary SHA-1, and not the first half of the SHA-1 written in hexadecimal).
  • Remove all whitespace
  • Replace "+" with "_", "/" with "-" and "=" with "A"

This produces collision-free unique names of length no more than 251 octets (4/3 * 186 + 3) for nicknames no longer than 186 UTF-8 octets (replacing "=" with "A" is harmless here because XMPP resources cannot contain U+0000).

For longer nicknames it makes collisions highly unlikely, and produces 255-octet unique names (4/3 * 189 + 3), which still fit into D-Bus' 255-octet limit.

The choice of 186 and 169 for the magic numbers ensures that these long nicknames can only have unique-name collisions with other long nicknames, and that the Base64 encoding step when applied to long nicknames does not leave any trailing "=" characters.

Implementations MUST NOT use unique names that start with ":2." but are not formed according to the above rules, and SHOULD treat tube elements containing such a dbus-name as if they were invalid.

For backwards compatibility with earlier implementations, the dbus-name MAY also be ":1." followed by an arbitrary unique string of up to 252 characters chosen from A-Z, a-z, 0-9, "-" or "_".

The D-Bus unique names used in a link-local MUC SHOULD be ":2." followed by the _presence._tcp instance name (e.g. mercutio@mab) processed with the algorithm above.

Again, implementations MUST NOT use unique names that start with ":2." but are not formed according to the above rules, and SHOULD treat tube elements containing such a dbus-name as if they were invalid.

The Tubes SI profile is indicated by the profile string &NS_TUBES;. A Tubes SI IQ can be classified as follows:

  • If the IQ contains a <tube> element with the namespace &NS_TUBES;, then the IQ represents a new tube being offered.
  • If the IQ contains a <stream> element with the namespace &NS_TUBES;, then the IQ represents a new connection to an existing stream tube in a 1-1 Tubes channel.
  • If the IQ contains a <muc-stream> element with the namespace &NS_TUBES;, then the IQ represents a new connection to an existing stream tube in a MUC Tubes channel - this message type is invalid and must be rejected unless received via a MUC.
  • Otherwise, the SI is invalid and MUST be rejected.

The allowed parameter types are:

  • "str": A Unicode string containing no zero bytes '\0'. In this implementation it cannot contain any other character forbidden by XML either. The <parameter> character content is the string itself. The corresponding D-Bus signature is 's'. This corresponds to xs:string in XML Schema Part 2.
  • "bytes": An array of bytes, represented in Base64. The corresponding D-Bus signature is 'ay'. This corresponds to xs:base64Binary in XML Schema Part 2.
  • "uint": An unsigned integer representable in 32 bits. The corresponding D-Bus signature is 'u' or 'q' on input, 'u' on output. The element's character content is an ASCII unsigned decimal integer. This corresponds to xs:unsignedInt in XML Schema Part 2.
  • "int": A signed integer representable in 32 bits using two's complement. The corresponding D-Bus signature is 'i' or 'n' on input, 'i' on output, and the element's character content is an ASCII decimal integer, possibly starting with '-' or '+'. This corresponds to xs:int in XML Schema Part 2.
  • "bool": A boolean value represented as one of the strings "false", "true", "0" or "1", as per xs:boolean in XML Schema Part 2. The corresponding D-Bus signature is 'b'. (Implementation note: early versions of Tubes in Gabble only accepted "0" or "1", so implementations that care about backwards compatibility SHOULD emit those representations).

FIXME: how big do we want to allow a message to be? In the D-Bus specification the limit is 2**27 bytes, in the default dbus-daemon configuration (as used on the system bus) it's 32M.

FIXME: limit how many messages are queued up somehow (the system bus limits it to 127M in total)

FIXME

None.

None, this isn't a real XEP (yet?).

]]>

The string "short" produces the unique name ":2.c2hvcnQA".

The string "FirstWitch", as used in the examples, produces the unique name ":2.Rmlyc3RXaXRjaAAA".

The string "Second witch", as used in the examples, produces the unique name ":2.U2Vjb25kIHdpdGNo".

The string consisting of 18 repetitions of "0123456789" followed by "012345" (186 characters) produces a unique name consisting of ":2.", followed by 6 repetitions of the 40-character string "MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5", followed by "MDEyMzQ1".

The string consisting of 18 repetitions of "0123456789" followed by "0123456" (187 characters) produces a unique name consisting of ":2.", followed by 5 repetitions of the 40-character string above, followed by "MDEyMzQ1Njc4OTAxMjM0NTY3OEVd9C5NgmmRD6jp1ftG6XUEc11x".

The string consisting of 20 repetitions of "0123456789" (200 characters) produces a unique name consisting of ":2.", followed by 5 repetitions of the 40-character string above, followed by "MDEyMzQ1Njc4OTAxMjM0NTY3OO-utwRnwcoUFhnJVMKg5pm9Hxal".

telepathy-gabble-0.18.3/docs/telepathy-gabble.8.in0000664000175000017500000000404112332440117023031 0ustar00cassidycassidy00000000000000.TH TELEPATHY-GABBLE "8" "October 2007" "Telepathy" "D-Bus services" \" This man page was written by Simon McVittie for the Debian project, \" but may be used by others. \" Copyright © 2007 Collabora Ltd. \" It may be distributed under the same terms as telepathy-gabble itself. .SH NAME telepathy-gabble \- Telepathy connection manager for XMPP (Jabber) .SH SYNOPSIS \fB@libexecdir@/telepathy\-gabble\fR .SH DESCRIPTION Gabble implements the Telepathy D-Bus specification for XMPP (Jabber), allowing Telepathy clients like .BR empathy (1) to connect to XMPP accounts, including Google Talk. .PP It is a D-Bus service which runs on the session bus, and should usually be started automatically by D-Bus activation. However, it might be useful to start it manually for debugging. .SH OPTIONS There are no command-line options. .SH ENVIRONMENT .TP \fBGABBLE_LOGFILE\fR=\fIfilename\fR If set, debug output will go to the given file rather than to stderr. If \fB+\fR is prepended to the \fIfilename\fR (e.g. \fBGABBLE_LOGFILE=+gabble.log\fR), debug output will be appended to the file; otherwise, any existing file will be replaced. .TP \fBGABBLE_DEBUG\fR=\fItype\fR May be set to "all" for full debug output, or various undocumented options (which may change from release to release) to filter the output. .TP \fBWOCKY_DEBUG\fR=\fItype\fR May be set to "all" for full debug output from the Wocky XMPP library used by Gabble, or various undocumented options (which may change from release to release) to filter the output. For general Gabble debugging, "net" is recommended. .TP \fBGABBLE_PERSIST\fR=\fI1\fR If set (to any value), Gabble will continue running until killed, rather than timing out if it has no open connections for a few seconds. .TP \fBGABBLE_PLUGIN_DIR\fR=\fIdirectory\fR If set, and Gabble was compiled with plugin support, plugins will be loaded from \fIdirectory\fR rather than from the default directory. .SH SEE ALSO .IR http://telepathy.freedesktop.org/ , .IR http://telepathy.freedesktop.org/wiki/CategoryGabble , .BR empathy (1) telepathy-gabble-0.18.3/docs/muc-bytestream.xml0000644000175000017500000001631011165152371022612 0ustar00cassidycassidy00000000000000
MUC Bytestreams A protocol for message transfer within a MUC. This document is copyright 2007 Collabora Ltd. and may be distributed under the same terms as the Telepathy specification. proto-muc-bytestream ProtoXEP External extension Telepathy project Telepathy project XMPP Core XEP-0045 NOT YET ASSIGNED Simon McVittie simon.mcvittie@collabora.co.uk simon.mcvittie@collabora.co.uk 0.0.1 2007-09-07 smcv

First draft.

This document describes a protocol for tunneling binary message streams through an XMPP MUC (XEP-0045). It's designed for use in Tubes but could be useful for other similar protocols.

The XML namespace defined here is http://telepathy.freedesktop.org/xmpp/protocol/muc-bytestream (NS_MUC_BYTESTREAM in Gabble source code).

D-Bus Tubes require a mechanism by which binary messages, possibly larger than the MUC service's maximum message size, can be transmitted through a MUC, preserving message boundaries. Multicasting messages to all participants, and sending unicast messages to a single participant, are both required.

The protocol used is intentionally similar to IBB (XEP-0047).

MUC Bytestream messages are multiplexed using a stream ID similar to that used in In-Band Bytestreams. As with In-Band Bytestreams, the stream ID SHOULD be randomly generated in a way that will avoid collisions, and any specification that references this one will need to describe how the stream ID can be associated with a higher-level construct (e.g. a Tube).

The uniqueness requirement for stream IDs is per-MUC, not per-participant, so collision avoidance must occur with the same scope.

Within a particular message stream, some messages can be broadcast to all participants in the MUC while some messages can be sent to a particular participant.

base64base64...
]]> base64base64...
]]>

Messages which are too large for the MUC to relay them intact SHOULD be "fragmented", i.e. split into multiple stanzas.

To send messages which need to be fragmented, set the 'frag' attribute to "first" on the first part of the message, "middle" on any intermediate parts and "last" on the last part. Setting 'frag' to "complete", or omitting it, means the XMPP stanza is a complete message in the underlying message stream, i.e. it is simultaneously the first and last fragment.

When receiving messages, participants MUST buffer and reassemble fragmented messages independently for each (sender, 'sid') pair.

When a participant has started to send a fragmented message, it MUST send all the fragments of that message, finishing with one with 'frag' set to "last", before it starts to send any subsequent message with the same 'sid' attribute.

If a participant leaves the MUC, or signals via a higher-level protocol that it has left the MUC Bytestream stream with a particular 'sid', any buffered fragments from that sender representing an incomplete message SHOULD be discarded by recipients.

base64base64... base64base64... base64base64... ]]>

Senders can cause denial of service to recipients via memory exhaustion if they send very large fragmented messages. Recipients MUST impose a limit on the size of message they will reassemble; higher-level protocols that reference this one SHOULD recommend a suitable limit for that protocol.

None.

None.

]]> telepathy-gabble-0.18.3/docs/xep.ent0000644000175000017500000062654511423525545020460 0ustar00cassidycassidy00000000000000 Namespace Versioning regarding the possibility of incrementing the version number)"> If the protocol defined in this specification undergoes a revision that is not fully backwards-compatible with an older version, the XMPP Registrar shall increment the protocol version number found at the end of the XML namespaces defined herein, as described in Section 4 of XEP-0053.

"> Protocol Namespaces regarding issuance of one or more permanent namespaces)"> http://xmpp.org/registrar/alt-connections.html>"> http://xmpp.org/registrar/amp-actions.html>"> http://xmpp.org/registrar/amp-conditions.html>"> http://xmpp.org/registrar/errors.html>"> http://xmpp.org/registrar/compress.html>"> http://xmpp.org/registrar/disco-categories.html>"> http://xmpp.org/registrar/disco-features.html>"> http://xmpp.org/registrar/formtypes.html>"> http://xmpp.org/registrar/jingle-apps.html>"> http://xmpp.org/registrar/jingle-transports.html>"> http://xmpp.org/registrar/linklocal.html>"> http://xmpp.org/registrar/mucstatus.html>"> http://xmpp.org/registrar/namespaces.html>"> http://xmpp.org/registrar/nodes.html>"> http://xmpp.org/registrar/querytypes.html>"> http://xmpp.org/registrar/shim.html>"> http://xmpp.org/registrar/si-profiles.html>"> http://xmpp.org/registrar/stream-features.html>"> http://xmpp.org/registrar/xdv-prefixes.html>"> http://xmpp.org/registrar/xdv-datatypes.html>"> n-1"> A"> B"> x"> 1...eZ"> y"> A"> A2"> B"> B2"> x"> y"> 1...HeZ"> A"> B"> A"> B"> A"> B"> A"> B"> A"> B"> A"> B"> A"> B"> A"> B"> A"> B"> A"> 1A...RSZA"> 1B...RSZB"> 1A...RSHZA"> A"> B"> A"> B"> A"> A"> B"> 2n-1"> 32"> 1...xZ"> This XMPP Extension Protocol is copyright © 1999 - 2009 by the XMPP Standards Foundation (XSF). Permission is hereby granted, free of charge, to any person obtaining a copy of this specification (the "Specification"), to make use of the Specification without restriction, including without limitation the rights to implement the Specification in a software program, deploy the Specification in a network service, and copy, modify, merge, publish, translate, distribute, sublicense, or sell copies of the Specification, and to permit persons to whom the Specification is furnished to do so, subject to the condition that the foregoing copyright notice and this permission notice shall be included in all copies or substantial portions of the Specification. Unless separate permission is granted, modified works that are redistributed shall not contain misleading information regarding the authors, title, number, or publisher of the Specification, and shall not claim endorsement of the modified works by the authors, any organization or project to which the authors belong, or the XMPP Standards Foundation. ## NOTE WELL: This Specification is provided on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. ## In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall the XMPP Standards Foundation or any author of this Specification be liable for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising from, out of, or in connection with the Specification or the implementation, deployment, or other use of the Specification (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if the XMPP Standards Foundation or such author has been advised of the possibility of such damages. This XMPP Extension Protocol has been contributed in full conformance with the XSF's Intellectual Property Rights Policy (a copy of which can be found at <http://xmpp.org/extensions/ipr-policy.shtml> or obtained by writing to XMPP Standards Foundation, c/o Peter Saint-Andre, 1899 Wynkoop Street, Suite 600, Denver, CO 80202 USA). " > Note: This document describes a protocol or best practice that is intended for incorporation into the specification that will supersede &rfc3920; within the Internet Standards Process, i.e., &rfc3920bis;. This document is provided only for the purpose of open community discussion of the potential modification and will be obsoleted as soon as the relevant RFC is published.

" > Note: This document describes a protocol or best practice that is intended for incorporation into the specification that will supersede &rfc3921; within the Internet Standards Process, i.e., &rfc3921bis;. This document is provided only for the purpose of open community discussion of the potential modification and will be obsoleted as soon as the relevant RFC is published.

" > In accordance with Section 3.2.2.1 of XML Schema Part 2: Datatypes, the allowable lexical representations for the xs:boolean datatype are the strings "0" and "false" for the concept 'false' and the strings "1" and "true" for the concept 'true'; implementations MUST support both styles of lexical representation." > In order to submit new values to this registry, the registrant shall define an XML fragment of the following form and either include it in the relevant XMPP Extension Protocol or send it to the email address <registrar@xmpp.org>:

" > The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in &rfc2119;.

' > XSF Board of Directors The XSF Board of Directors is an elected body that possesses overall responsibility for the affairs of the XMPP Standards Foundation. For further information, see <http://xmpp.org/xsf/board/>." > XSF Bylaws The Bylaws of the XMPP Standards Foundation (XSF) define the legal basis and operating procedures of the XSF. For further information, see <http://xmpp.org/xsf/docs/bylaws.shtml>." > XMPP Council The XMPP Council is a technical steering committee, authorized by the XSF Board of Directors and elected by XSF members, that approves of new XMPP Extensions Protocols and oversees the XSF's standards process. For further information, see <http://xmpp.org/council/>." > XMPP Extensions Editor The XMPP Extensions Editor is the individual appointed by the XSF Board of Directors to handle protocol submissions and provide day-to-day management of the XSF's standards process. For further information, see <http://xmpp.org/extensions/editor.shtml>." > XMPP Intermediate Certification Authority The XMPP Intermediate Certification Authority (ICA) issues free domain certificates to administrators of XMPP-based services. For further information, see <http://xmpp.org/ca/>." > XMPP Standards Foundation (XSF) The XMPP Standards Foundation (XSF) is an independent, non-profit membership organization that develops open extensions to the IETF's Extensible Messaging and Presence Protocol (XMPP). For further information, see <http://xmpp.org/xsf/>." > XSF-IETF list The XSF-IETF list is for discussion of matters of mutual interest to the XMPP Standards Foundation and the Internet Engineering Task Force. The primary focus of the list is technical, mainly regarding XSF use of IETF technologies (e.g., references to RFCs in XMPP Extension Protocols) and IETF use of XSF technologies (e.g., references to XMPP Extension Protocols in Internet-Drafts and RFCs). To subscribe to the list or view the list archives, visit <http://mail.jabber.org/mailman/listinfo/jsf-ietf/>." > XSF IPR Policy The XSF IPR Policy defines the XMPP Standards Foundation's official policy regarding intellectual property rights (IPR) as they pertain to XMPP Extension Protocols (XEPs). For further information, see <http://xmpp.org/extensions/ipr-policy.shtml>." > XMPP Registrar The XMPP Registrar maintains a list of reserved protocol namespaces as well as registries of parameters used in the context of XMPP extension protocols approved by the XMPP Standards Foundation. For further information, see <http://xmpp.org/registrar/>." > Standards SIG The Standards SIG is a standing Special Interest Group devoted to development of XMPP Extension Protocols. The discussion list of the Standards SIG is the primary venue for discussion of XMPP protocol extensions, as well as for announcements by the XMPP Extensions Editor and XMPP Registrar. To subscribe to the list or view the list archives, visit <http://mail.jabber.org/mailman/listinfo/standards/>." > jabberd The jabberd server is the original server implementation of the Jabber/XMPP protocols, first developed by Jeremie Miller, inventor of Jabber. For further information, see <http://jabberd.org/>." > The General Public License The General Public License is the primary code license for free software as defined by the Free Software Foundation. For further information, see <http://www.gnu.org/licenses/gpl.txt>." > The Lesser General Public License The Lesser General Public License is a secondary code license for free software as defined by the Free Software Foundation. For further information, see <http://www.gnu.org/licenses/lgpl.txt>." > The Open Source Initiative The Open Source Initiative defines the term 'open source' and maintains a list of open-source code licenses. For further information, see <http://www.opensource.org/>." > CAcert CAcert is a community-driven certificate authority which issues validated certificates based on participation in a web of trust rather than payment of a fee. For further information, see <http://www.cacert.org/>." > Dublin Core Metadata Initiative (DCMI) The Dublin Core Metadata Initiative (DCMI) is an organization dedicated to promoting the widespread adoption of interoperable metadata standards. For further information, see <http://www.dublincore.org/>." > FIX Protocol, Ltd. FIX Protocol, Ltd. is a securities industry consortium that has developed the Financial Information eXchange Protocol (FIX). For further information, see <http://www.fixprotocol.org/>." > Internet Assigned Numbers Authority (IANA) The Internet Assigned Numbers Authority (IANA) is the central coordinator for the assignment of unique parameter values for Internet protocols, such as port numbers and URI schemes. For further information, see <http://www.iana.org/>." > Internet Engineering Task Force (IETF) The Internet Engineering Task Force is the principal body engaged in the development of new Internet standard specifications, best known for its work on standards such as HTTP and SMTP. For further information, see <http://www.ietf.org/>." > International Organization for Standardization (ISO) The International Organization for Standardization develops standards a wide variety of technical domains. For further information, see <http://www.iso.org/>." > International Telecommunication Union (ITU) The International Telecommunication Union develops technical and operating standards (such as H.323) for international telecommunication services. For further information, see <http://www.itu.int/>." > OASIS OASIS is a not-for-profit, international consortium that drives the development, convergence and adoption of e-business standards. For further information, see <http://www.oasis-open.org/>." > Open Mobile Alliance (OMA) The Open Mobile Alliance is the focal point for the development of mobile service enabler specifications, which support the creation of interoperable end-to-end mobile services. For further information, see <http://www.openmobilealliance.org/>." > StartCom Free SSL Certification Authority The StartCom Free SSL Certification Authority is a certification authority that offers free or low-cost X.509 certificates to Internet user and server administrators. It is is also the root CA for the XMPP Intermediate Certification Authority run by the XMPP Standards Foundation. For further information, see <http://cert.startcom.org/>." > XMPP Working Group The XMPP Working Group was created by the Internet Engineering Task Force to define an adaptation of the base Jabber protocols that could be considered an IETF-approved instant messaging and presence technology. For further information, see <http://www.ietf.org/html.charters/xmpp-charter.html>." > World Wide Web Consortium (W3C) The World Wide Web Consortium defines data formats and markup languages (such as HTML and XML) for use over the Internet. For further information, see <http://www.w3.org/>." > Canonical XML Canonical XML 1.0 <http://www.w3.org/TR/xml-c14n>." > Cascading Style Sheets Cascading Style Sheets, level 1 <http://www.w3.org/TR/REC-CSS1>." > Efficient XML Interchange Efficient XML Interchange (EXI) Format 1.0 <http://www.w3.org/TR/exi>." > HTML 4.0 HTML 4.0 <http://www.w3.org/TR/REC-html40>." > W3C Process Document W3C Process Document <http://www.w3.org/Consortium/Process-20010719/process.html>." > SOAP SOAP <http://www.w3.org/TR/SOAP/>." > SOAP Version 1.2 Part 0 SOAP Version 1.2 Part 0: Primer <http://www.w3.org/TR/soap12-part0>." > SOAP Version 1.2 Part 1 SOAP Version 1.2 Part 1: Messaging <http://www.w3.org/TR/soap12-part1>." > SOAP Version 1.2 Part 2 SOAP Version 1.2 Part 2: Adjuncts <http://www.w3.org/TR/soap12-part2>." > SOAP 1.2 Attachment Feature SOAP 1.2 Attachment Feature <http://www.w3.org/TR/soap12-af/>." > SOAP Email Binding SOAP Version 1.2 Email Binding <http://www.w3.org/TR/soap12-email>." > SOAP Message Transmission Optimization Mechanism SOAP Message Transmission Optimization Mechanism <http://www.w3.org/TR/soap12-mtom>." > Resource Representation SOAP Header Block Resource Representation SOAP Header Block <http://www.w3.org/TR/soap12-rep>." > Scalable Vector Graphics (SVG) Scalable Vector Graphics (SVG) 1.1 Specification <http://www.w3.org/TR/SVG11/>." > Inaccessibility of Visually-Oriented Anti-Robot Tests Inaccessibility of Visually-Oriented Anti-Robot Tests <http://www.w3.org/TR/turingtest/>." > XForms 1.0 XForms 1.0 <http://www.w3.org/TR/xforms>." > XHTML 1.0 XHTML 1.0 <http://www.w3.org/TR/xhtml1>." > XHTML 2.0 XHTML 2.0 <http://www.w3.org/TR/xhtml2>." > XHTML Basic XHTML Basic <http://www.w3.org/TR/xhtml-basic>." > Modularization of XHTML Modularization of XHTML <http://www.w3.org/TR/2004/WD-xhtml-modularization-20040218/>." > XInclude XML Inclusions (XInclude) 1.0 <http://www.w3.org/TR/xinclude/>." > Resource Description Framework Resource Description Framework (RDF) <http://www.w3.org/RDF/>." > XML 1.0 Extensible Markup Language (XML) 1.0 (Fourth Edition) <http://www.w3.org/TR/REC-xml/>." > XML Encryption XML Encryption Syntax and Processing <http://www.w3.org/TR/2002/REC-xmlenc-core-20021210/>." > Namespaces in XML Namespaces in XML <http://www.w3.org/TR/REC-xml-names/>." > XML Schema Part 1 XML Schema Part 1: Structures <http://www.w3.org/TR/xmlschema-1/>." > XML Schema Part 2 XML Schema Part 2: Datatypes <http://www.w3.org/TR/xmlschema-2/>." > XML Signature XML Signature Syntax and Processing <http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/>." > XML-binary Optimized Packaging XML-binary Optimized Packaging <http://www.w3.org/TR/xop10/>." > XPath XML Path Language <http://www.w3.org/TR/xpath>." > XSL Transformations XSL Transformations <http://www.w3.org/TR/xslt/>." > WSDL WSDL 1.1 Specification <http://www.w3.org/TR/wsdl>." > Common Alerting Protocol Common Alerting Protocol, v. 1.0 <http://www.oasis-open.org/committees/documents.php?wg_abbrev=emergency>." > Security Assertion Markup Language Security Assertion Markup Language <http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=security>." > Arcfour A Stream Cipher Encryption Algorithm 'Arcfour' <http://www.watersprings.org/pub/id/draft-kaukonen-cipher-arcfour-03.txt>." > draft-dawson-vcard-xml-dtd-03 draft-dawson-vcard-xml-dtd-03 <http://www.watersprings.org/pub/id/draft-dawson-vcard-xml-dtd-03.txt>. Work in progress." > ANSI X9.52 ANSI X9.52: Triple Data Encryption Algorithm Modes of Operation (1998)." > Blowfish Description of a New Variable-Length Key, 64-Bit Block Cipher (Blowfish) <http://www.schneier.com/paper-blowfish-fse.html>." > IDEA The IDEA Block Cipher <http://perso.ens-lyon.fr/jean-luc.beuchat/IDEA/>." > Data Encryption Standard Data Encryption Standard: Federal Information Processing Standards Publication 46-3 <http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf>." > SHA Secure Hash Standard: Federal Information Processing Standards Publication 180-2 <http://csrc.nist.gov/publications/fips/fips180-2/fips186-2withchangenotice.pdf>." > DSS Digital Signature Standard: Federal Information Processing Standards Publication 186 <http://csrc.nist.gov/publications/fips/fips186-2/fips186-2-change1.pdf>." > AES Advanced Encryption Standard: Federal Information Processing Standards Publication 197 <http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf>." > HMAC The Keyed-Hash Message Authentication Code (HMAC): Federal Information Processing Standards Publication 198 <http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf>." > Recommendation for Block Cipher Modes of Operation Recommendation for Block Cipher Modes of Operation: Federal Information Processing Standards Publication 800-38a <http://csrc.nist.gov/publications/ nistpubs/800-38a/sp800-38a.pdf>." > Off-the-Record Communication Off-the-Record Communication, or, Why Not to Use PGP <http://www.cypherpunks.ca/otr/otr-codecon.pdf> <http://www.cypherpunks.ca/otr/otr-wpes.pdf>." > Serpent The Serpent Block Cipher <http://www.cl.cam.ac.uk/~rja14/serpent.html>." > SIGMA SIGMA: the 'SIGn-and-MAc' Approach to Authenticated Diffie-Hellman and its Use in the IKE Protocols (Hugo Krawczyk, June 12 2003) <http://www.ee.technion.ac.il/~hugo/sigma.ps>." > SSL SSL V3.0 <http://wp.netscape.com/eng/ssl3/draft302.txt>." > Twofish The Twofish Block Cipher <http://www.schneier.com/twofish.html>." > Whirlpool The Whirlpool Hash Function <http://paginas.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html>." > H.323 ITU Recommendation H.323: Packet-based Multimedia Communications Systems (September 1999)." > ASN.1 X.680: Abstract Syntax Notation One (ASN.1): Specification of basic notation <http:://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf>." > BER X.690: ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER) <http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf>." > ITU E.164 ITU Recommendation E.164/I.331: The International Public Telecommunication Numbering Plan (1997). This specification is not freely available; a short summary is located at <http://en.wikipedia.org/wiki/E.164>." > X.500 X.500: The Directory: Overview of concepts, models and service <http://www.itu.int/rec/T-REC-X.500-200102-I/en>." > X.841 X.841: Security techniques - Security information objects for access control <http://www.itu.int/rec/T-REC-X.841-200010-I/en>." > US-ASCII Coded Character Set - 7-bit American Standard Code for Information Interchange (American National Standards Institute X3.4, 1986)." > Bayeux Protocol Bayeux Protocol <http://svn.cometd.org/trunk/bayeux/bayeux.html>." > DCMI Metadata Terms Dublin Core Metadata Initiative: DCMI Metadata Terms <http://dublincore.org/documents/dcmi-terms/>." > Standard ECMA-151 Standard ECMA-151: Data Compression for Information Interchange - Adaptive Coding with Embedded Dictionary - DLCZ Algorithm <http://www.ecma-international.org/publications/standards/Ecma-151.htm>." > ECMAScript (JavaScript) Standard ECMA-262: ECMAScript Language Specification 3rd edition <http://www.ecma-international.org/publications/standards/Ecma-262.htm>." > Financial Information eXchange Protocol (FIX) The Financial Information eXchange Protocol (FIX) is a messaging standard developed specifically for the real-time electronic exchange of securities transactions. For further information, see <http://www.fixprotocol.org/>." > FIXML FIXML is an XML representation of the data format used in Financial Information eXchange Protocol (FIX), which abstracts the FIX data format from the underlying FIX transport mechanism. For further information, see <http://www.fixprotocol.org/cgi-bin/Spec.cgi?menu=4>." > Friend of a Friend (FOAF) Friend of a Friend (FOAF) <http://xmlns.com/foaf/0.1/>." > Information and Content Exchange Information and Content Exchange <http://www.icestandard.org/>." > IC-ISM Common Information Sharing Standard for Information Security Marking: XML Implementation, Office of the Director of National Intelligence, Release 2.0.3, 15 February 2006." > ISO 8601 ISO 8601: Representation of Dates and Times (2000). This specification is not freely available; however, a good summary is located at <http://www.cl.cam.ac.uk/~mgk25/iso-time.html>." > OAuth OAuth Core 1.0 <http://oauth.net/core/1.0/>." > OpenID OpenID Authentication 2.0 <http://openid.net/specs/openid-authentication-2_0.html>." > Introduction to Petname Systems Introduction to Petname Systems <http://www.skyhunter.com/marcs/petnames/IntroPetNames.html>." > Reverse HTTP Reverse HTTP <http://tools.ietf.org/html/draft-lentczner-rhttp>." > Rich Text Format (RTF) Rich Text Format (RTF) Version 1.5 Specification <http://msdn.microsoft.com/library/en-us/dnrtfspec/html/rtfspec.asp>." > SDN.801c SDN.801c: Access Control Concept and Mechanism, US National Security Agency, Revision C, 12 May 1999." > Unicode The Unicode Standard, Version 3.2.0 (The Unicode Consortium, 2000)." > Wireless Access Protocol (WAP) Wireless Access Protocol (WAP) <http://www.wapforum.org/>." > The Web Socket Protocol The Web Socket Protocol <http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol>." > WV Client-Server Protocol v1.1 Wireless Village Client-Server Protocol v1.1 <http://www.openmobilealliance.org/tech/affiliates/wv/wvindex.html>." > XHTML Friends Network (XFN) XHTML Friends Network (XFN) <http://gmpg.org/xfn/index>." > XML-RPC XML-RPC <http://www.xmlrpc.com/spec>." > RFC 768 RFC 768: User Datagram Protocol <http://tools.ietf.org/html/rfc0768>." > RFC 793 RFC 793: Transmission Control Protocol <http://tools.ietf.org/html/rfc0793>." > RFC 822 RFC 822: Standard for the Format of ARPA Internet Text Messages <http://tools.ietf.org/html/rfc0822>." > RFC 862 RFC 862: Echo Protocol <http://tools.ietf.org/html/rfc0862>." > RFC 918 RFC 918: Post Office Protocol <http://tools.ietf.org/html/rfc0918>." > RFC 958 RFC 958: Network Time Protocol (NTP) <http://tools.ietf.org/html/rfc0958>." > RFC 959 RFC 959: File Transfer Protocol <http://tools.ietf.org/html/rfc0959>." > RFC 1034 RFC 1034: Domain Names - Concepts and Facilities <http://tools.ietf.org/html/rfc1034>." > RFC 1035 RFC 1035: Domain Names - Implementation and Specification <http://tools.ietf.org/html/rfc1035>." > RFC 1123 RFC 1123: Requirements for Internet Hosts -- Application and Support <http://tools.ietf.org/html/rfc1123>." > RFC 1305 RFC 1305: Network Time Protocol (Version 3) <http://tools.ietf.org/html/rfc1305>." > RFC 1321 RFC 1321: The MD5 Message-Digest Algorithm <http://tools.ietf.org/html/rfc1321>." > RFC 1393 RFC 1393: Traceroute Using an IP Option <http://tools.ietf.org/html/rfc1393>." > RFC 1459 RFC 1459: Internet Relay Chat <http://tools.ietf.org/html/rfc1459>." > RFC 1464 RFC 1464: Using the Domain Name System To Store Arbitrary String Attributes <http://tools.ietf.org/html/rfc1464>." > RFC 1750 RFC 1750: Randomness Recommendations for Security <http://tools.ietf.org/html/rfc1750>." > RFC 1808 RFC 1808: Uniform Resource Locators <http://tools.ietf.org/html/rfc1808>." > RFC 1886 RFC 1886: DNS Extensions to support IP version 6 <http://tools.ietf.org/html/rfc1886>." > RFC 1889 RFC 1889: RTP: A Transport Protocol for Real-Time Applications <http://tools.ietf.org/html/rfc1889>." > RFC 1893 RFC 1893: Enhanced Mail System Status Codes <http://tools.ietf.org/html/rfc1893>." > RFC 1928 RFC 1928: SOCKS Protocol Version 5 <http://tools.ietf.org/html/rfc1928>." > RFC 1929 RFC 1929: Username/Password Authentication for SOCKS V5 <http://tools.ietf.org/html/rfc1929>." > RFC 1939 RFC 1939: Post Office Protocol - Version 3 <http://tools.ietf.org/html/rfc1939>." > RFC 1945 RFC 1945: Hypertext Transfer Protocol -- HTTP/1.0 <http://tools.ietf.org/html/rfc1945>." > RFC 1950 RFC 1950: ZLIB Compressed Data Format Specification version 3.3 <http://tools.ietf.org/html/rfc1950>." > RFC 2026 RFC 2026: The Internet Standards Process <http://tools.ietf.org/html/rfc2026>." > RFC 2045 RFC 2045: Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies <http://tools.ietf.org/html/rfc2045>." > RFC 2068 RFC 2068: Hypertext Transport Protocol -- HTTP/1.1 <http://tools.ietf.org/html/rfc2068>." > RFC 2104 RFC 2104: HMAC: Keyed-Hashing for Message Authentication <http://tools.ietf.org/html/rfc2104>." > RFC 2109 RFC 2109: HTTP State Mangement Mechanism <http://tools.ietf.org/html/rfc2109>." > RFC 2111 RFC 2111: Content-ID and Message-ID Uniform Resource Locators <http://tools.ietf.org/html/rfc2111>." > RFC 2119 RFC 2119: Key words for use in RFCs to Indicate Requirement Levels <http://tools.ietf.org/html/rfc2119>." > RFC 2142 RFC 2142: Mailbox Names for Common Services, Roles and Functions <http://tools.ietf.org/html/rfc2142>." > RFC 2144 RFC 2144: The CAST-128 Encryption Algorithm <http://tools.ietf.org/html/rfc2144>." > RFC 2183 RFC 2183: Communicating Presentation Information in Internet Messages: The Content-Disposition Header Field <http://tools.ietf.org/html/rfc2183>." > RFC 2222 RFC 2222: Simple Authentication and Security Layer (SASL) <http://tools.ietf.org/html/rfc2222>." > RFC 2244 RFC 2244: ACAP -- Application Configuration Access Protocol <http://tools.ietf.org/html/rfc2244>." > RFC 2251 RFC 2251: Lightweight Directory Access Protocol (v3) <http://tools.ietf.org/html/rfc2251>." > RFC 2252 RFC 2252: Lightweight Directory Access Protocol (v3): Attribute Syntax Definitions <http://tools.ietf.org/html/rfc2252>." > RFC 2253 RFC 2253: Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names <http://tools.ietf.org/html/rfc2253>." > RFC 2256 RFC 2256: A Summary of the X.500(96) User Schema for use with LDAPv3 <http://tools.ietf.org/html/rfc2256>." > RFC 2277 RFC 2277: IETF Policy on Character Sets and Languages <http://tools.ietf.org/html/rfc2277>." > RFC 2246 RFC 2246: The TLS Protocol Version 1.0 <http://tools.ietf.org/html/rfc2246>." > RFC 2317 RFC 2317: Classless IN-ADDR.ARPA delegation <http://tools.ietf.org/html/rfc2317>." > RFC 2326 RFC 2326: Real Time Streaming Protocol (RTSP) <http://tools.ietf.org/html/rfc2326>." > RFC 2327 RFC 2327: SDP: Session Description Protocol <http://tools.ietf.org/html/rfc2327>." > RFC 2350 RFC 2350: Expectations for Computer Security Incident Response <http://tools.ietf.org/html/rfc2350>." > RFC 2368 RFC 2368: The mailto URL scheme <http://tools.ietf.org/html/rfc2368>." > RFC 2397 RFC 2397: The data: URL scheme <http://tools.ietf.org/html/rfc2397>." > RFC 2405 RFC 2405: The ESP DES-CBC Cipher Algorithm With Explicit IV <http://tools.ietf.org/html/rfc2405>." > RFC 2406 RFC 2406: IP Encapsulating Security Payload (ESP) <http://tools.ietf.org/html/rfc2406>." > RFC 2409 RFC 2409: The Internet Key Exchange (IKE) <http://tools.ietf.org/html/rfc2409>." > RFC 2412 RFC 2412: The OAKLEY Key Determination Protocol <http://tools.ietf.org/html/rfc2412>." > RFC 2413 RFC 2413: Dublin Core Metadata for Resource Discovery <http://tools.ietf.org/html/rfc2413>." > RFC 2414 RFC 2414: Increasing TCP's Initial Window <http://tools.ietf.org/html/rfc2414>." > RFC 2420 RFC 2420: The PPP Triple-DES Encryption Protocol (3DESE) <http://tools.ietf.org/html/rfc2420>." > RFC 2426 RFC 2426: vCard MIME Directory Profile <http://tools.ietf.org/html/rfc2426>." > RFC 2437 RFC 2437: PKCS #1: RSA Cryptography Specifications Version 2.0 <http://tools.ietf.org/html/rfc2437>." > RFC 2451 RFC 2451: The ESP CBC-Mode Cipher Algorithms <http://tools.ietf.org/html/rfc2451>." > RFC 2510 RFC 2510: Internet X.509 Public Key Infrastructure Certificate Management Protocols <http://tools.ietf.org/html/rfc2510>." > RFC 2518 RFC 2518: HTTP Extensions for Distributed Authoring -- WEBDAV <http://tools.ietf.org/html/rfc2518>." > rfc2518bis RFC 2518: HTTP Extensions for Distributed Authoring -- WebDAV <http://tools.ietf.org/html/draft-ietf-webdav-rfc2518bis>." > RFC 2595 RFC 2595: Using TLS with IMAP, POP3 and ACAP <http://tools.ietf.org/html/rfc2595>." > RFC 2606 RFC 2606: Reserved Top Level DNS Names <http://tools.ietf.org/html/rfc2606>." > RFC 2608 RFC 2608: Service Location Protocol, Version 2 <http://tools.ietf.org/html/rfc2608>." > RFC 2616 RFC 2616: Hypertext Transport Protocol -- HTTP/1.1 <http://tools.ietf.org/html/rfc2616>." > RFC 2617 RFC 2617: HTTP Authentication: Basic and Digest Access Authentication <http://tools.ietf.org/html/rfc2617>." > RFC 2631 RFC 2631: Diffie-Hellman Key Agreement Method <http://tools.ietf.org/html/rfc2631>." > RFC 2633 RFC 2633: S/MIME Version 3 Message Specification <http://tools.ietf.org/html/rfc2633>." > RFC 2634 RFC 2634: Enhanced Security Services for S/MIME <http://tools.ietf.org/html/rfc2634>." > RFC 2648 RFC 2648: A URN Namespace for IETF Documents <http://tools.ietf.org/html/rfc2648>." > RFC 2778 RFC 2778: A Model for Presence and Instant Messaging <http://tools.ietf.org/html/rfc2778>." > RFC 2779 RFC 2779: A Model for Presence and Instant Messaging <http://tools.ietf.org/html/rfc2779>." > RFC 2782 RFC 2782: A DNS RR for specifying the location of services (DNS SRV) <http://tools.ietf.org/html/rfc2782>." > RFC 2798 RFC 2798: Definition of the inetOrgPerson LDAP Object Class <http://tools.ietf.org/html/rfc2798>." > RFC 2806 RFC 2806: URLs for Telephone Calls <http://tools.ietf.org/html/rfc2806>." > RFC 2810 RFC 2810: Internet Relay Chat: Architecture <http://tools.ietf.org/html/rfc2810>." > RFC 2811 RFC 2811: Internet Relay Chat: Channel Management <http://tools.ietf.org/html/rfc2811>." > RFC 2812 RFC 2812: Internet Relay Chat: Client Protocol <http://tools.ietf.org/html/rfc2812>." > RFC 2813 RFC 2813: Internet Relay Chat: Server Protocol <http://tools.ietf.org/html/rfc2813>." > RFC 2817 RFC 2817: Upgrading to TLS Within HTTP/1.1 <http://tools.ietf.org/html/rfc2817>." > RFC 2818 RFC 2818: HTTP Over TLS <http://tools.ietf.org/html/rfc2818>." > RFC 2821 RFC 2821: Simple Mail Transfer Protocol <http://tools.ietf.org/html/rfc2821>." > RFC 2822 RFC 2822: Internet Message Format <http://tools.ietf.org/html/rfc2822>." > RFC 2831 RFC 2831: Using Digest Authentication as a SASL Mechanism <http://tools.ietf.org/html/rfc2831>." > RFC 2833 RFC 2833: RTP Payload for DTMF Digits, Telephony Tones and Telephony Signals <http://tools.ietf.org/html/rfc2833>." > RFC 2965 RFC 2965: HTTP State Management Mechanism <http://tools.ietf.org/html/rfc2965>." > RFC 3023 RFC 3023: XML Media Types <http://tools.ietf.org/html/rfc3023>." > RFC 3066 RFC 3066: Tags for the Identification of Languages <http://tools.ietf.org/html/rfc3066>." > RFC 3067 RFC 3067: TERENA's Incident Object Description and Exchange Format Requirements <http://tools.ietf.org/html/rfc3067>." > RFC 3080 RFC 3080: The Blocks Extensible Exchange Protocol Core (BEEP) <http://tools.ietf.org/html/rfc3080>." > RFC 3117 RFC 3117: On the Design of Application Protocols <http://tools.ietf.org/html/rfc3117>." > RFC 3174 RFC 3174: US Secure Hash Algorithm 1 (SHA1) <http://tools.ietf.org/html/rfc3174>." > RFC 3217 RFC 3217: Triple-DES and RC2 Key Wrapping <http://tools.ietf.org/html/rfc3217>." > RFC 3261 RFC 3261: Session Initiation Protocol (SIP) <http://tools.ietf.org/html/rfc3261>." > RFC 3264 RFC 3264: An Offer/Answer Model with the Session Description Protocol (SDP) <http://tools.ietf.org/html/rfc3264>." > RFC 3269 RFC 3269: UTF-8, a transformation format of ISO 10646 <http://tools.ietf.org/html/rfc3269>." > RFC 3261 RFC 3261: Session Initiation Protocol <http://tools.ietf.org/html/rfc3261>." > RFC 3281 RFC 3281: An Internet Attribute Certificate Profile for Authorization <http://tools.ietf.org/html/rfc3281>." > RFC 3288 RFC 3288: Using the Simple Object Access Protocol (SOAP) in Blocks Extensible Exchange Protocol (BEEP) <http://tools.ietf.org/html/rfc3288>." > RFC 3312 RFC 3312: Integration of Resource Management and Session Initiation Protocol (SIP) <http://tools.ietf.org/html/rfc3312>." > RFC 3330 RFC 3330: Special-Use IPv4 Addresses <http://tools.ietf.org/html/rfc3330>." > RFC 3340 RFC 3340: The Application Exchange Core (APEX) <http://tools.ietf.org/html/rfc3340>." > RFC 3341 RFC 3341: The Application Exchange (APEX) Access Service <http://tools.ietf.org/html/rfc3341>." > RFC 3342 RFC 3342: The Application Exchange (APEX) Option Party Pack, Part Deux! <http://tools.ietf.org/html/rfc3342>." > RFC 3343 RFC 3343: The Application Exchange (APEX) Presence Service <http://tools.ietf.org/html/rfc3343>." > RFC 3370 RFC 3370: Cryptographic Message Syntax (CMS) Algorithms <http://tools.ietf.org/html/rfc3370>." > RFC 3389 RFC 3389: Real-time Transport Protocol (RTP) Payload for Comfort Noise (CN) <http://tools.ietf.org/html/rfc3389>." > RFC 3394 RFC 3394: Advanced Encryption Standard (AES) Key Wrap Algorithm <http://tools.ietf.org/html/rfc3394>." > RFC 3401 RFC 3401: Dynamic Delegation Discovery System (DDDS) Part One: The Comprehensive DDDS <http://tools.ietf.org/html/rfc3401>." > RFC 3403 RFC 3403: Dynamic Delegation Discovery System (DDDS) Part Three: The Domain Name System (DNS) Database <http://tools.ietf.org/html/rfc3403>." > RFC 3404 RFC 3404: Dynamic Delegation Discovery System (DDDS) Part Four: The Uniform Resource Identifiers (URI) Resolution Application <http://tools.ietf.org/html/rfc3404>." > RFC 3428 RFC 3428: Session Initiation Protocol (SIP) Extension for Instant Messaging <http://tools.ietf.org/html/rfc3428>." > RFC 3447 RFC 3447: Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications Version 2.1 <http://tools.ietf.org/html/rfc3447>." > RFC 3454 RFC 3454: Preparation of Internationalized Strings (stringprep) <http://tools.ietf.org/html/rfc3454>." > RFC 3489 RFC 3489: STUN - Simple Traversal of User Datagram Protocol (UDP) Through Network Address Translators (NATs) <http://tools.ietf.org/html/rfc3489>." > RFC 3490 RFC 3490: Internationalizing Domain Names in Applications (IDNA) <http://tools.ietf.org/html/rfc3490>." > RFC 3514 RFC 3514: The Security Flag in the IPv4 Header <http://tools.ietf.org/html/rfc3514>." > RFC 3526 RFC 3526: More Modular Exponential (MODP) Diffie-Hellman Groups <http://tools.ietf.org/html/rfc3526>." > RFC 3548 RFC 3548: The Base16, Base32, and Base64 Data Encodings <http://tools.ietf.org/html/rfc3548>." > RFC 3550 RFC 3550: RTP: A Transport Protocol for Real-Time Applications <http://tools.ietf.org/html/rfc3550>." > RFC 3551 RFC 3551: RTP Profile for Audio and Video Conferences with Minimal Control <http://tools.ietf.org/html/rfc3551>." > RFC 3552 RFC 3552: Guidelines for Writing RFC Text on Security Considerations <http://tools.ietf.org/html/rfc3552>." > RFC 3555 RFC 3555: MIME Type Registration of RTP Payload Formats <http://tools.ietf.org/html/rfc3555>." > RFC 3605 RFC 3605: Real Time Control Protocol (RTCP) attribute in Session Description Protocol (SDP) <http://tools.ietf.org/html/rfc3605>." > RFC 3711 RFC 3711: The Secure Real-time Transport Protocol (SRTP) <http://tools.ietf.org/html/rfc3711>." > RFC 3744 RFC 3744: Web Distributed Authoring and Versioning (WebDAV) Access Control Protocol <http://tools.ietf.org/html/rfc3744>." > RFC 3749 RFC 3749: Transport Layer Security Protocol Compression Methods <http://tools.ietf.org/html/rfc3749>." > RFC 3766 RFC 3766: Determining Strengths For Public Keys Used For Exchanging Symmetric Keys <http://tools.ietf.org/html/rfc3766>." > RFC 3859 RFC 3859: Common Profile for Presence (CPP) <http://tools.ietf.org/html/rfc3859>." > RFC 3860 RFC 3860: Common Profile for Instant Messaging (CPIM) <http://tools.ietf.org/html/rfc3860>." > RFC 3861 RFC 3861: Address Resolution for Instant Messaging and Presence <http://tools.ietf.org/html/rfc3861>." > RFC 3862 RFC 3862: Common Presence and Instant Messaging (CPIM): Message Format <http://tools.ietf.org/html/rfc3862>." > RFC 3863 RFC 3863: Presence Information Data Format (PIDF) <http://tools.ietf.org/html/rfc3863>." > RFC 3920 RFC 3920: Extensible Messaging and Presence Protocol (XMPP): Core <http://tools.ietf.org/html/rfc3920>." > RFC 3921 RFC 3921: Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence <http://tools.ietf.org/html/rfc3921>." > RFC 3922 RFC 3922: Mapping the Extensible Messaging and Presence Protocol (XMPP) to Common Presence and Instant Messaging (CPIM) <http://tools.ietf.org/html/rfc3922>." > RFC 3923 RFC 3923: End-to-End Signing and Object Encryption for the Extensible Messaging and Presence Protocol (XMPP) <http://tools.ietf.org/html/rfc3923>." > RFC 3927 RFC 3927: Dynamic Configuration of IPv4 Link-Local Addresses <http://tools.ietf.org/html/rfc3927>." > RFC 3958 RFC 3958: Domain-Based Application Service Location Using SRV RRs and the Dynamic Delegation Discovery Service (DDDS) <http://tools.ietf.org/html/rfc3958>." > RFC 3959 RFC 3959: The Early Session Disposition Type for the Session Initiation Protocol (SIP) <http://tools.ietf.org/html/rfc3959>." > RFC 3960 RFC 3960: Early Media and Ringing Tone Generation in the Session Initiation Protocol (SIP) <http://tools.ietf.org/html/rfc3960>." > RFC 3966 RFC 3966: The tel URI for Telephone Numbers <http://tools.ietf.org/html/rfc3966>." > RFC 3984 RFC 3984: RTP Payload Format for H.264 Video <http://tools.ietf.org/html/rfc3984>." > RFC 3986 RFC 3986: Uniform Resource Identifiers (URI): Generic Syntax <http://tools.ietf.org/html/rfc3986>." > RFC 3987 RFC 3987: Internationalized Resource Identifiers (IRIs) <http://tools.ietf.org/html/rfc3987>." > RFC 4032 RFC 4032: Update to the Session Initiation Protocol (SIP) Preconditions Framework <http://tools.ietf.org/html/rfc4032>." > RFC 4033 RFC 4033: DNS Security Introduction and Requirements <http://tools.ietf.org/html/rfc4033>." > RFC 4086 RFC 4086: Randomness Requirements for Security <http://tools.ietf.org/html/rfc4086>." > RFC 4119 RFC 4119: A Presence-based GEOPRIV Location Object Format <http://tools.ietf.org/html/rfc4119>." > RFC 4122 RFC 4122: A Universally Unique IDentifier (UUID) URN Namespace <http://tools.ietf.org/html/rfc4122>." > RFC 4227 RFC 4227: Using the Simple Object Access Protocol (SOAP) in Blocks Extensible Exchange Protocol (BEEP) <http://tools.ietf.org/html/rfc4227>." > RFC 4251 RFC 4251: The Secure Shell (SSH) Protocol Architecture <http://tools.ietf.org/html/rfc4251>." > RFC 4252 RFC 4252: The Secure Shell (SHS) Authentication Protocol <http://tools.ietf.org/html/rfc4252>." > RFC 4253 RFC 4253: The Secure Shell (SSH) Transport Layer Protocol <http://tools.ietf.org/html/rfc4253>." > RFC 4270 RFC 4270: Attacks on Cryptographic Hashes in Internet Protocols <http://tools.ietf.org/html/rfc4270>." > RFC 4281 RFC 4281: The Codecs Parameter for "Bucket" Media Types <http://tools.ietf.org/html/rfc4281>." > RFC 4287 RFC 4287: The Atom Syndication Format <http://tools.ietf.org/html/rfc4287>." > RFC 4301 RFC 4301: Security Architecture for the Internet Protocol <http://tools.ietf.org/html/rfc4301>." > RFC 4306 RFC 4306: Internet Key Exchange (IKEv2) Protocol <http://tools.ietf.org/html/rfc4306>." > RFC 4344 RFC 4344: SSH Transport Layer Encryption Modes <http://tools.ietf.org/html/rfc4344>." > RFC 4346 RFC 4346: The Transport Layer Security (TLS) Protocol Version 1.1 <http://tools.ietf.org/html/rfc4346>." > RFC 4347 RFC 4347: Datagram Transport Layer Security <http://tools.ietf.org/html/rfc4347>." > RFC 4366 RFC 4366: Transport Layer Security (TLS) Extensions <http://tools.ietf.org/html/rfc4366>." > RFC 4395 RFC 4395: Guidelines and Registration Procedures for New URI Schemes <http://tools.ietf.org/html/rfc4395>." > RFC 4422 RFC 4422: Simple Authentication and Security Layer (SASL) <http://tools.ietf.org/html/rfc4422>." > RFC 4425 RFC 4425: RTP Payload Format for Video Codec 1 (VC-1) <http://tools.ietf.org/html/rfc4425>." > RFC 4467 RFC 4467: Internet Message Access Protocol (IMAP) - URLAUTH Extension <http://tools.ietf.org/html/rfc4467>." > RFC 4480 RFC 4480: RPID: Rich Presence Extensions to the Presence Information Data Format (PIDF) <http://tools.ietf.org/html/rfc4480>." > RFC 4481 RFC 4481: Timed Presence Extensions to the Presence Information Data Format (PIDF) to Indicate Status Information for Past and Future Time Intervals <http://tools.ietf.org/html/rfc4481>." > RFC 4505 RFC 4505: The SASL ANONYMOUS Mechanism <http://tools.ietf.org/html/rfc4505>." > RFC 4551 RFC 4551: IMAP Extension for Conditional STORE Operation or Quick Flag Changes Resynchronization <http://tools.ietf.org/html/rfc4551>." > RFC 4566 RFC 4566: SDP: Session Description Protocol <http://tools.ietf.org/html/rfc4566>." > RFC 4568 RFC 4568: Session Description Protocol (SDP) Security Descriptions for Media Streams <http://tools.ietf.org/html/rfc4568>." > RFC 4571 RFC 4571: Framing Real-time Transport Protocol (RTP) and RTP Control Protocol (RTCP) Packets over Connection-Oriented Transport <http://tools.ietf.org/html/rfc4571>." > RFC 4585 RFC 4585: Extended RTP Profile for Real-time Transport Control Protocol (RTCP)-Based Feedback (RTP/AVPF) <http://tools.ietf.org/html/rfc4585>." > RFC 4622 RFC 4622: Internationalized Resource Identifiers (IRIs) and Uniform Resource Identifiers (URIs) for the Extensible Messaging and Presence Protocol (XMPP) <http://tools.ietf.org/html/rfc4622>." > RFC 4627 RFC 4627: The application/json Media Type for JavaScript Object Notation (JSON) <http://tools.ietf.org/html/rfc4627>." > RFC 4646 RFC 4646: Tags for Identifying Languages <http://tools.ietf.org/html/rfc4646>." > RFC 4648 RFC 4648: The Base16, Base32, and Base64 Data Encodings <http://tools.ietf.org/html/rfc4648>." > RFC 4685 RFC 4685: Atom Threading Extensions <http://tools.ietf.org/html/rfc4685>." > RFC 4732 RFC 4732: Internet Denial-of-Service Considerations <http://tools.ietf.org/html/rfc4732>." > RFC 4733 RFC 4733: RTP Payload for DTMF Digits, Telephony Tones, and Telephony Signals <http://tools.ietf.org/html/rfc4733>." > RFC 4752 RFC 4752: The Kerberos V5 ("GSSAPI") Simple Authentication and Security Layer (SASL) Mechanism <http://tools.ietf.org/html/rfc4752>." > RFC 4790 RFC 4790: Internet Application Protocol Collation Registry <http://tools.ietf.org/html/rfc4790>." > RFC 4848 RFC 4848: Domain-Based Application Service Location Using URIs and the Dynamic Delegation Discovery Service (DDDS) <http://tools.ietf.org/html/rfc4848>." > RFC 4854 RFC 4854: A Uniform Resource Name (URN) Namespace for Extensions to the Extensible Messaging and Presence Protocol (XMPP) <http://tools.ietf.org/html/rfc4854>." > RFC 4880 RFC 4880: OpenPGP Message Format <http://tools.ietf.org/html/rfc4880>." > RFC 5023 RFC 5023: The Atom Publishing Protocol <http://tools.ietf.org/html/rfc5023>." > RFC 5054 RFC 5054: Using the Secure Remote Password (SRP) Protocol for TLS Authentication <http://tools.ietf.org/html/rfc5054>." > RFC 5056 RFC 5056: On the Use of Channel Bindings to Secure Channels <http://tools.ietf.org/html/rfc5056>." > RFC 5070 RFC 5070: The Incident Object Description Exchange Format <http://tools.ietf.org/html/rfc5070>." > RFC 5081 RFC 5081: Using OpenPGP Keys for Transport Layer Security (TLS) Authentication <http://tools.ietf.org/html/rfc5081>." > RFC 5122 RFC 5122: Internationalized Resource Identifiers (IRIs) and Uniform Resource Identifiers (URIs) for the Extensible Messaging and Presence Protocol (XMPP) <http://tools.ietf.org/html/rfc5122>." > RFC 5124 RFC 5124: Extended Secure RTP Profile for Real-time Transport Control Protocol (RTCP)-Based Feedback (RTP/SAVPF) <http://tools.ietf.org/html/rfc5124>." > RFC 5246 RFC 5246: The Transport Layer Security (TLS) Protocol Version 1.2 <http://tools.ietf.org/html/rfc5246>." > RFC 5359 RFC 5359: Session Initiation Protocol Service Examples <http://tools.ietf.org/html/rfc5359>." > RFC 5389 RFC 5389: Session Traversal Utilities for NAT (STUN) <http://tools.ietf.org/html/rfc5389>." > RFC 5391 RFC 5391: RTP Payload Format for ITU-T Recommendation G.711.1 <http://tools.ietf.org/html/rfc5391>." > RFC 5574 RTP Payload Format for the Speex Codec <http://tools.ietf.org/html/rfc5574>." > AtomSub Atomsub: Transporting Atom Notifications over the Publish-Subscribe Extension to the Extensible Messaging and Presence Protocol (XMPP) <http://xmpp.org/internet-drafts/draft-saintandre-atompub-notify-07.html>. Work in progress." > DNS-Based Service Discovery DNS-Based Service Discovery <http://tools.ietf.org/html/draft-cheshire-dnsext-dns-sd>. Work in progress." > DTLS-SRTP Datagram Transport Layer Security (DTLS) Extension to Establish Keys for Secure Real-time Transport Protocol (SRTP) <http://tools.ietf.org/html/draft-ietf-avt-dtls-srtp>. Work in progress." > Geopriv Policy Geopriv Policy <http://tools.ietf.org/html/draft-ietf-geopriv-policy>. Work in progress." > IAX IAX: Inter-Asterisk eXchange Version 2 <http://tools.ietf.org/html/draft-ietf-guy-iax>. Work in progress." > Interactive Connectivity Establishment (ICE) Interactive Connectivity Establishment (ICE): A Methodology for Network Address Translator (NAT) Traversal for Offer/Answer Protocols <http://tools.ietf.org/html/draft-ietf-mmusic-ice>. Work in progress." > TCP Candidates with Interactive Connectivity Establishment (ICE) TCP Candidates with Interactive Connectivity Establishment (ICE) <http://tools.ietf.org/html/draft-ietf-mmusic-ice-tcp>. Work in progress." > draft-ietf-kitten-gssapi-domain-based-names GSS-API Internationalization and Domain-Based Service Names and Name Type <http://tools.ietf.org/html/draft-ietf-kitten-gssapi-domain-based-names>. Work in progress." > draft-ietf-kitten-krb5-gssapi-domain-based-names GSS-API Domain-Based Service Names Mapping for the Kerberos V GSS Mechanism <http://tools.ietf.org/html/draft-ietf-kitten-krb5-gssapi-domain-based-names>. Work in progress." > Multicast DNS Multicast DNS <http://tools.ietf.org/html/draft-cheshire-dnsext-multicastdns>. Work in progress." > Presence Information Data Format (PIDF) RFC 3863: Presence Information Data Format (PIDF) <http://tools.ietf.org/html/rfc3863>." > Application Mechanism for maintaining alive the Network Address Translator (NAT) mappings associated to RTP flows Application Mechanism for maintaining alive the Network Address Translator (NAT) mappings associated to RTP flows <http://tools.ietf.org/html/draft-ietf-avt-app-rtp-keepalive>. Work in progress." > RTP Payload Format for Theora Encoded Video RTP Payload Format for Theora Encoded Video <http://tools.ietf.org/html/draft-barbato-avt-rtp-theora>. Work in progress." > draft-ietf-sasl-gssapi The Kerberos V5 (GSSAPI) SASL mechanism <http://tools.ietf.org/html/draft-ietf-sasl-gssapi>. Work in progress." > draft-cridland-sasl-tls-sessions On the use of TLS Session resumption and SASL EXTERNAL <http://tools.ietf.org/html/draft-cridland-sasl-tls-sessions>. Work in progress." > SCRAM Salted Challenge Response (SCRAM) SASL Mechanism <http://tools.ietf.org/html/draft-newman-auth-scram>. Work in progress." > RTP Over DTLS Real-Time Transport Protocol (RTP) over Datagram Transport Layer Security (DTLS) <http://tools.ietf.org/html/draft-fischl-mmusic-sdp-dtls>. Work in progress." > Sieve Extension: Notifications Sieve Extension: Notifications <http://tools.ietf.org/html/draft-ietf-sieve-notify>. Work in progress." > Sieve Notification Mechanism: xmpp Sieve Notification Mechanism: xmpp <http://tools.ietf.org/html/draft-ietf-sieve-notify-xmpp>. Work in progress." > SIP URI Service Discovery using DNS-SD SIP URI Service Discovery using DNS-SD <http://tools.ietf.org/html/draft-lee-sip-dns-sd-uri>. Work in progress." > Session Description and Capability Negotiation (SDPng) Session Description and Capability Negotiation (SDPng) <http://tools.ietf.org/html/draft-ietf-mmusic-sdpng>. Work in progress." > X.509 Authentication in SSH2 X.509 Authentication in SSH2 <http://tools.ietf.org/html/draft-ietf-secsh-x509>. Work in progress." > Improving TCP's Robustness to Blind In-Window Attacks Improving TCP's Robustness to Blind In-Window Attacks <http://tools.ietf.org/html/draft-ietf-tcpm-tcpsecure>. Work in progress." > TURN Traversal Using Relays around NAT (TURN): Relay Extensions to Session Traversal Utilities for NAT (STUN) <http://tools.ietf.org/html/draft-ietf-behave-turn>. Work in progress." > ZRTP ZRTP: Media Path Key Agreement for Secure RTP <http://tools.ietf.org/html/draft-zimmermann-avt-zrtp>. Work in progress." > IANA Mail Content Disposition Values and Parameters Registry IANA registry of Mail Content Disposition Values and Parameters <http://www.iana.org/assignments/mail-cont-disp>." > IANA Hash Function Textual Names Registry IANA registry of Hash Function Textual Names <http://www.iana.org/assignments/hash-function-text-names>." > IANA MIME Atom Link Relations Registry IANA registry of Atom link relations <http://www.iana.org/assignments/link-relations.html>." > IANA MIME Media Types Registry IANA registry of MIME media types <http://www.iana.org/assignments/media-types>." > IANA Port Numbers Registry IANA registry of port numbers <http://www.iana.org/assignments/port-numbers>." > IANA SASL Mechanisms Registry IANA registry of mechanisms used in the Simple Authentication and Security Layer protocol <http://www.iana.org/assignments/sasl-mechanisms>." > IANA Session Description Protocol Parameters Registry IANA registry of parameters related to the Session Description Protocol <http://www.iana.org/assignments/sdp-parameters>." > IANA Session Initiation Protocol Parameters Registry IANA registry of parameters related to the Session Initiation Protocol <http://www.iana.org/assignments/sip-parameters>." > IANA Service Location Protocol, Version 2 (SLPv2) Templates IANA registry of parameters related to the Service Location Protocol templates <http://www.iana.org/assignments/svrloc-templates.htm>." > IANA Secure Shell Protocol Parameters Registry IANA registry of parameters related to secure shell <http://www.iana.org/assignments/ssh-parameters>." > rfc3920bis rfc3920bis: proposed revisions to Extensible Messaging and Presence Protocol (XMPP): Core <http://tools.ietf.org/html/draft-ietf-xmpp-3920bis>. (work in progress)" > rfc3921bis rfc3921bis: proposed revisions to Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence <http://tools.ietf.org/html/draft-ietf-xmpp-3921bis>. (work in progress)" > XMPP Extensible Messaging and Presence Protocol (XMPP) <http://xmpp.org/>." > XMPP Core RFC 3920: Extensible Messaging and Presence Protocol (XMPP): Core <http://tools.ietf.org/html/rfc3920>." > XMPP IM RFC 3921: Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence <http://tools.ietf.org/html/rfc3921>." > XMPP CPIM RFC 3922: Mapping the Extensible Messaging and Presence Protocol (XMPP) to Common Presence and Instant Messaging (CPIM) <http://tools.ietf.org/html/rfc3922>." > XMPP E2E RFC 3923: End-to-End Signing and Object Encryption for the Extensible Messaging and Presence Protocol (XMPP) <http://tools.ietf.org/html/rfc3923>." > XMPP URI Scheme Internationalized Resource Identifiers (IRIs) and Uniform Resource Identifiers (URIs) for the Extensible Messaging and Presence Protocol (XMPP) <http://tools.ietf.org/html/rfc5122>." > draft-saintandre-sip-xmpp-chat Interworking between the Session Initiation Protocol (SIP) and the Extensible Messaging and Presence Protocol (XMPP): One-to-One Text Chat <http://tools.ietf.org/html/draft-saintandre-sip-xmpp-chat> (work in progress)." > draft-saintandre-sip-xmpp-core Interworking between the Session Initiation Protocol (SIP) and the Extensible Messaging and Presence Protocol (XMPP): Core <http://tools.ietf.org/html/draft-saintandre-sip-xmpp-core> (work in progress)." > draft-saintandre-sip-xmpp-im Interworking between the Session Initiation Protocol (SIP) and the Extensible Messaging and Presence Protocol (XMPP): Instant Messaging <http://tools.ietf.org/html/draft-saintandre-sip-xmpp-im> (work in progress)." > draft-saintandre-sip-xmpp-media Interworking between the Session Initiation Protocol (SIP) and the Extensible Messaging and Presence Protocol (XMPP): Media Sessions <http://tools.ietf.org/html/draft-saintandre-sip-xmpp-media> (work in progress)." > draft-saintandre-sip-xmpp-presence Interworking between the Session Initiation Protocol (SIP) and the Extensible Messaging and Presence Protocol (XMPP): Presence <http://tools.ietf.org/html/draft-saintandre-sip-xmpp-presence> (work in progress)." > XMPP URNs A Uniform Resource Name (URN) Namespace for Extensions to the Extensible Messaging and Presence Protocol (XMPP) <http://tools.ietf.org/html/rfc4854>." > Jingle XTLS Extensible Messaging and Presence Protocol (XMPP) End-to-End Encryption Using Transport Layer Security ("XTLS") <http://tools.ietf.org/html/draft-meyer-xmpp-e2e-encryption>." > Client Certificate Management for SASL EXTERNAL Management and Use of Client Certificates for the Extensible Messaging and Presence Protocol (XMPP) <http://tools.ietf.org/html/draft-meyer-xmpp-sasl-cert-management>." > Peter Saint-Andre stpeter@jabber.org stpeter@jabber.org https://stpeter.im/ " > Dave Smith dizzyd@jabber.org dizzyd@jabber.org " > Thomas Muldowney temas@jabber.org temas@jabber.org " > Matthew Miller linuxwolf@outer-planes.net linuxwolf@outer-planes.net " > Peter Millard " > Joe Hildebrand jhildebr@cisco.com hildjj@jabber.org " > Ryan Eatmon reatmon@jabber.org reatmon@jabber.org " > Jeremie Miller jer@jabber.org jer@jabber.org " > Justin Karneges justin@affinix.com justin@andbit.net " > Ralph Meijer ralphm@ik.nu ralphm@ik.nu " > Julian Missig julian@jabber.org julian@jabber.org " > Ian Paterson ian.paterson@clientside.co.uk ian@zoofy.com " > Scott Ludwig scottlu@google.com scottlu@google.com " > Joe Beda jbeda@google.com jbeda@google.com " > Valerie Mercier valerie.mercier@orange-ftgroup.com vmercier@jabber.com " > Sean Egan seanegan@google.com seanegan@google.com " > Robert McQueen robert.mcqueen@collabora.co.uk robert.mcqueen@collabora.co.uk " > Kevin Smith kevin@kismith.co.uk kevdadrum@jabber.ex.ac.uk " > Remko Tronçon http://el-tramo.be/ " > Dave Cridland dave.cridland@isode.com dave.cridland@isode.com " > Fabio Forno fabio.forno@gmail.com ff@jabber.bluendo.com " > Pavel Šimerda pavlix@pavlix.net http://www.pavlix.net/ " > Diana Cionoiu diana@null.ro l-fy@jabber.null.ro " > Dirk Meyer dmeyer@tzi.de dmeyer@jabber.org " > Jack Moffitt jack@chesspark.com jack@chesspark.com " > Kurt Zeilenga Kurt.Zeilenga@Isode.COM Kurt.Zeilenga@Isode.COM " > XMPP Extension Protocols XEP-0001: XMPP Extension Protocols <http://xmpp.org/extensions/xep-0001.html>." > Special Interest Groups XEP-0002: Special Interest Groups <http://xmpp.org/extensions/xep-0002.html>." > Proxy Accept Socket Service XEP-0002: Proxy Accept Socket Service <http://xmpp.org/extensions/xep-0003.html>." > Data Forms XEP-0004: Data Forms <http://xmpp.org/extensions/xep-0004.html>." > IQ-Based Avatars XEP-0008: IQ-Based Avatars <http://xmpp.org/extensions/xep-0008.html>." > Jabber-RPC XEP-0009: Jabber-RPC <http://xmpp.org/extensions/xep-0009.html>." > Jabber Browsing XEP-0011: Jabber Browsing <http://xmpp.org/extensions/xep-0011.html>." > Last Activity XEP-0012: Last Activity <http://xmpp.org/extensions/xep-0012.html>." > Flexible Offline Message Retrieval XEP-0013: Flexible Offline Message Retrieval <http://xmpp.org/extensions/xep-0013.html>." > Privacy Lists XEP-0016: Privacy Lists <http://xmpp.org/extensions/xep-0016.html>." > Invisible Presence XEP-0018: Invisible Presence <http://xmpp.org/extensions/xep-0018.html>." > Streamlining the SIGs XEP-0019: Streamlining the SIGs <http://xmpp.org/extensions/xep-0019.html>." > Feature Negotiation XEP-0020: Feature Negotiation <http://xmpp.org/extensions/xep-0020.html>." > Jabber Event Notification Service XEP-0021: Jabber Event Notification Service <http://xmpp.org/extensions/xep-0021.html>." > Message Events XEP-0022: Message Events <http://xmpp.org/extensions/xep-0022.html>." > Message Expiration XEP-0023: Message Expiration <http://xmpp.org/extensions/xep-0023.html>." > Publish/Subscribe XEP-0024: Publish/Subscribe <http://xmpp.org/extensions/xep-0024.html>." > Jabber HTTP Polling XEP-0025: Jabber HTTP Polling <http://xmpp.org/extensions/xep-0025.html>." > Internationalization XEP-0026: Internationalization <http://xmpp.org/extensions/xep-0026.html>." > Current Jabber OpenPGP Usage XEP-0027: Current Jabber OpenPGP Usage <http://xmpp.org/extensions/xep-0027.html>." > Definition of Jabber Identifiers XEP-0029: Definition of Jabber Identifiers <http://xmpp.org/extensions/xep-0029.html>." > Service Discovery XEP-0030: Service Discovery <http://xmpp.org/extensions/xep-0030.html>." > A Framework for Securing Jabber Conversations XEP-0031: A Framework for Securing Jabber Conversations <http://xmpp.org/extensions/xep-0031.html>." > Jabber URI Scheme XEP-0032: Jabber URI Scheme <http://xmpp.org/extensions/xep-0032.html>." > Extended Stanza Addressing XEP-0033: Extended Stanza Addressing <http://xmpp.org/extensions/xep-0033.html>." > SASL Integration XEP-0034: SASL Integration <http://xmpp.org/extensions/xep-0034.html>." > SSL/TLS Integration XEP-0035: SSL/TLS Integration <http://xmpp.org/extensions/xep-0035.html>." > Pub-sub Subscriptions XEP-0036: Pub-sub Subscriptions <http://xmpp.org/extensions/xep-0036.html>." > Icon Styles XEP-0038: Icon Styles <http://xmpp.org/extensions/xep-0038.html>." > Statistics Gathering XEP-0039: Statistics Gathering <http://xmpp.org/extensions/xep-0039.html>." > Robust Publish-Subscribe XEP-0040: Robust Publish-Subscribe <http://xmpp.org/extensions/xep-0040.html>." > Jidlink XEP-0041: Jidlink <http://xmpp.org/extensions/xep-0041.html>." > Jabber OOB Broadcast Service XEP-0042: Jabber OOB Broadcast Service <http://xmpp.org/extensions/xep-0042.html>." > Jabber Database Access XEP-0043: Jabber Database Access <http://xmpp.org/extensions/xep-0043.html>." > Full Namespace Support in XML Streams XEP-0044: Full Namespace Support in XML Streams <http://xmpp.org/extensions/xep-0044.html>." > Multi-User Chat XEP-0045: Multi-User Chat <http://xmpp.org/extensions/xep-0045.html>." > Direct TCP XEP-0046: Direct TCP <http://xmpp.org/extensions/xep-0046.html>." > In-Band Bytestreams XEP-0047: In-Band Bytestreams <http://xmpp.org/extensions/xep-0047.html>." > Bookmark Storage XEP-0048: Bookmark Storage <http://xmpp.org/extensions/xep-0048.html>." > Private XML Storage XEP-0049: Private XML Storage <http://xmpp.org/extensions/xep-0049.html>." > Ad-Hoc Commands XEP-0050: Ad-Hoc Commands <http://xmpp.org/extensions/xep-0050.html>." > Redirect and Connection Transfer XEP-0051: Redirect and Connection Transfer <http://xmpp.org/extensions/xep-0051.html>." > File Transfer XEP-0052: File Transfer <http://xmpp.org/extensions/xep-0052.html>." > XMPP Registrar Function XEP-0053: XMPP Registrar Function <http://xmpp.org/extensions/xep-0053.html>." > vcard-temp XEP-0054: vcard-temp <http://xmpp.org/extensions/xep-0054.html>." > Jabber Search XEP-0055: Jabber Search <http://xmpp.org/extensions/xep-0055.html>." > Business Data Interchange XEP-0056: Business Data Interchange <http://xmpp.org/extensions/xep-0056.html>." > Extended Roster XEP-0057: Extended Roster <http://xmpp.org/extensions/xep-0057.html>." > Multi-User Text Editing XEP-0058: Multi-User Text Editing <http://xmpp.org/extensions/xep-0058.html>." > Result Set Management XEP-0059: Result Set Management <http://xmpp.org/extensions/xep-0059.html>." > Publish-Subscribe XEP-0060: Publish-Subscribe <http://xmpp.org/extensions/xep-0060.html>." > Shared Notes XEP-0061: Shared Notes <http://xmpp.org/extensions/xep-0061.html>." > Packet Filtering XEP-0062: Packet Filtering <http://xmpp.org/extensions/xep-0062.html>." > Basic Filtering Operations XEP-0063: Basic Filtering Operations <http://xmpp.org/extensions/xep-0063.html>." > XPath Filtering XEP-0064: XPath Filtering <http://xmpp.org/extensions/xep-0064.html>." > SOCKS5 Bytestreams XEP-0065: SOCKS5 Bytestreams <http://xmpp.org/extensions/xep-0065.html>." > Out-of-Band Data XEP-0066: Out of Band Data <http://xmpp.org/extensions/xep-0066.html>." > Stock Data Transmission XEP-0067: Stock Data Transmission <http://xmpp.org/extensions/xep-0067.html>." > Field Standardization for Data Forms XEP-0068: Field Data Standardization for Data Forms <http://xmpp.org/extensions/xep-0068.html>." > Compliance SIG XEP-0069: Compliance SIG <http://xmpp.org/extensions/xep-0069.html>." > Verifying HTTP Requests via XMPP XEP-0070: Verifying HTTP Requests via XMPP <http://xmpp.org/extensions/xep-0070.html>." > XHTML-IM XEP-0071: XHTML-IM <http://xmpp.org/extensions/xep-0071.html>." > SOAP over XMPP XEP-0072: SOAP over XMPP <http://xmpp.org/extensions/xep-0072.html>." > Basic IM Protocol Suite XEP-0073: Basic IM Protocol Suite <http://xmpp.org/extensions/xep-0073.html>." > Simple Access Control XEP-0074: Simple Access Control <http://xmpp.org/extensions/xep-0074.html>." > Jabber Object Access Protocol XEP-0075: Jabber Object Access Protocol <http://xmpp.org/extensions/xep-0075.html>." > Malicious Stanzas XEP-0076: Malicious Stanzas <http://xmpp.org/extensions/xep-0076.html>." > In-Band Registration XEP-0077: In-Band Registration <http://xmpp.org/extensions/xep-0077.html>." > Non-SASL Authentication XEP-0078: Non-SASL Authentication <http://xmpp.org/extensions/xep-0078.html>." > Advanced Message Processing XEP-0079: Advanced Message Processing <http://xmpp.org/extensions/xep-0079.html>." > User Geolocation XEP-0080: User Geolocation <http://xmpp.org/extensions/xep-0080.html>." > Jabber MIME Type XEP-0081: Jabber MIME Type <http://xmpp.org/extensions/xep-0081.html>." > XMPP Date and Time Profiles XEP-0082: XMPP Date and Time Profiles <http://xmpp.org/extensions/xep-0082.html>." > Nested Roster Groups XEP-0083: Nested Roster Groups <http://xmpp.org/extensions/xep-0083.html>." > User Avatar XEP-0084: User Avatar <http://xmpp.org/extensions/xep-0084.html>." > Chat State Notifications XEP-0085: Chat State Notifications <http://xmpp.org/extensions/xep-0085.html>." > Error Condition Mappings XEP-0086: Error Condition Mappings <http://xmpp.org/extensions/xep-0086.html>." > Stream Initiation XEP-0087: Stream Initiation <http://xmpp.org/extensions/xep-0087.html>." > Client Webtabs XEP-0088: Client Webtabs <http://xmpp.org/extensions/xep-0088.html>." > Generic Alerts XEP-0089: Generic Alerts <http://xmpp.org/extensions/xep-0089.html>." > Legacy Entity Time XEP-0090: Legacy Entity Time <http://xmpp.org/extensions/xep-0090.html>." > Legacy Delayed Delivery XEP-0091: Legacy Delayed Delivery <http://xmpp.org/extensions/xep-0091.html>." > Software Version XEP-0092: Software Version <http://xmpp.org/extensions/xep-0092.html>." > Roster Item Exchange XEP-0093: Roster Item Exchange <http://xmpp.org/extensions/xep-0093.html>." > Agent Information XEP-0094: Agent Information <http://xmpp.org/extensions/xep-0094.html>." > Stream Initiation XEP-0095: Stream Initiation <http://xmpp.org/extensions/xep-0095.html>." > SI File Transfer XEP-0096: SI File Transfer <http://xmpp.org/extensions/xep-0096.html>." > iCal Envelope XEP-0097: iCal Envelope <http://xmpp.org/extensions/xep-0097.html>." > Enchanced Private XML Storage XEP-0098: Enchanced Private XML Storage <http://xmpp.org/extensions/xep-0098.html>." > IQ Query Action Protocol XEP-0099: IQ Query Action Protocol <http://xmpp.org/extensions/xep-0099.html>." > Gateway Interaction XEP-0100: Gateway Interaction <http://xmpp.org/extensions/xep-0100.html>." > HTTP Authentication using Jabber Tickets XEP-0101: HTTP Authentication using Jabber Tickets <http://xmpp.org/extensions/xep-0101.html>." > Security Extensions XEP-0102: Security Extensions <http://xmpp.org/extensions/xep-0102.html>." > URL Address Information XEP-0103: URL Address Information <http://xmpp.org/extensions/xep-0103.html>." > HTTP Scheme for URL Data XEP-0104: HTTP Scheme for URL Data <http://xmpp.org/extensions/xep-0104.html>." > Tree Transfer Stream Initiation Profile XEP-0105: Tree Transfer Stream Initiation Profile <http://xmpp.org/extensions/xep-0105.html>." > JID Escaping XEP-0106: JID Escaping <http://xmpp.org/extensions/xep-0106.html>." > User Mood XEP-0107: User Mood <http://xmpp.org/extensions/xep-0107.html>." > User Activity XEP-0108: User Activity <http://xmpp.org/extensions/xep-0108.html>." > Vacation Messages XEP-0109: Vacation Messages <http://xmpp.org/extensions/xep-0109.html>." > Generic Maps XEP-0110: Generic Maps <http://xmpp.org/extensions/xep-0110.html>." > A Transport for Initiating and Negotiating Sessions XEP-0111: A Transport for Initiating and Negotiating Sessions <http://xmpp.org/extensions/xep-0111.html>." > User Physical Location XEP-0112: User Physical Location <http://xmpp.org/extensions/xep-0112.html>." > Simple Whiteboarding XEP-0113: Simple Whiteboarding <http://xmpp.org/extensions/xep-0113.html>." > Jabber Component Protocol XEP-0114: Jabber Component Protocol <http://xmpp.org/extensions/xep-0114.html>." > Entity Capabilities XEP-0115: Entity Capabilities <http://xmpp.org/extensions/xep-0115.html>." > Encrypted Session Negotiation XEP-0116: Encrypted Session Negotiation <http://xmpp.org/extensions/xep-0116.html>." > Intermediate IM Protocol Suite XEP-0117: Intermediate IM Protocol Suite <http://xmpp.org/extensions/xep-0117.html>." > User Tune XEP-0118: User Tune <http://xmpp.org/extensions/xep-0118.html>." > Extended Presence Protocol Suite XEP-0119: Extended Presence Protocol Suite <http://xmpp.org/extensions/xep-0119.html>." > Infobits XEP-0120: Infobits <http://xmpp.org/extensions/xep-0120.html>." > Dublin Core Infobits Mapping XEP-0121: Dublin Core Infobits Mapping <http://xmpp.org/extensions/xep-0121.html>." > Data Forms Validation XEP-0122: Data Forms Validation <http://xmpp.org/extensions/xep-0122.html>." > Entity Metadata XEP-0123: Entity Metadata <http://xmpp.org/extensions/xep-0123.html>." > BOSH XEP-0124: Bidirectional-streams Over Synchronous HTTP <http://xmpp.org/extensions/xep-0124.html>." > vCard Infobits Mapping XEP-0125: vCard Infobits Mapping <http://xmpp.org/extensions/xep-0125.html>." > Invisibility XEP-0126: Invisibility <http://xmpp.org/extensions/xep-0126.html>." > Common Alerting Protocol (CAP) over XMPP XEP-0127: Common Alerting Protocol (CAP) over XMPP <http://xmpp.org/extensions/xep-0127.html>." > Service Discovery Extensions XEP-0128: Service Discovery Extensions <http://xmpp.org/extensions/xep-0128.html>." > WebDAV File Transfers XEP-0129: WebDAV File Transfers <http://xmpp.org/extensions/xep-0129.html>." > Waiting Lists XEP-0130: Waiting Lists <http://xmpp.org/extensions/xep-0130.html>." > Stanza Headers and Internet Metadata XEP-0131: Stanza Headers and Internet Metadata <http://xmpp.org/extensions/xep-0131.html>." > Presence Obtained via Kinesthetic Excitation (POKE) XEP-0132: Presence Obtained via Kinesthetic Excitation (POKE) <http://xmpp.org/extensions/xep-0132.html>." > Service Administration XEP-0133: Service Administration <http://xmpp.org/extensions/xep-0133.html>." > XMPP Design Guidelines XEP-0134: XMPP Design Guidelines <http://xmpp.org/extensions/xep-0134.html>." > File Sharing XEP-0135: File Sharing <http://xmpp.org/extensions/xep-0135.html>." > Message Archiving XEP-0136: Message Archiving <http://xmpp.org/extensions/xep-0136.html>." > Publishing Stream Initiation Requests XEP-0137: Publishing Stream Initiation Requests <http://xmpp.org/extensions/xep-0137.html>." > Stream Compression XEP-0138: Stream Compression <http://xmpp.org/extensions/xep-0138.html>." > Security SIG XEP-0139: Security SIG <http://xmpp.org/extensions/xep-0139.html>." > Shared Groups XEP-0140: Shared Groups <http://xmpp.org/extensions/xep-0140.html>." > Data Forms Layout XEP-0141: Data Forms Layout <http://xmpp.org/extensions/xep-0141.html>." > Workgroup Queues XEP-0142: Workgroup Queues <http://xmpp.org/extensions/xep-0142.html>." > Guidelines for Authors of XMPP Extension Protocols XEP-0143: Guidelines for Authors of XMPP Extension Protocols <http://xmpp.org/extensions/xep-0143.html>." > Roster Item Exchange XEP-0144: Roster Item Exchange <http://xmpp.org/extensions/xep-0144.html>." > Annotations XEP-0145: Annotations <http://xmpp.org/extensions/xep-0145.html>." > Remote Controlling Clients XEP-0146: Remote Controlling Clients <http://xmpp.org/extensions/xep-0146.html>." > XMPP URI Query Components XEP-0147: XMPP URI Query Components <http://xmpp.org/extensions/xep-0147.html>." > Instant Messaging Intelligence Quotient (IM IQ) XEP-0148: Instant Messaging Intelligence Quotient (IM IQ) <http://xmpp.org/extensions/xep-0148.html>." > Time Periods XEP-0149: Time Periods <http://xmpp.org/extensions/xep-0149.html>." > Use of Entity Tags in XMPP Extensions XEP-0150: Use of Entity Tags in XMPP Extensions <http://xmpp.org/extensions/xep-0150.html>." > Virtual Presence XEP-0151: Virtual Presence <http://xmpp.org/extensions/xep-0151.html>." > Reachability Addresses XEP-0152: Reachability Addresses <http://xmpp.org/extensions/xep-0152.html>." > vCard-Based Avatars XEP-0153: vCard-Based Avatars <http://xmpp.org/extensions/xep-0153.html>." > User Profile XEP-0154: User Profile <http://xmpp.org/extensions/xep-0154.html>." > Stanza Session Negotiation XEP-0155: Stanza Session Negotiation <http://xmpp.org/extensions/xep-0155.html>." > Discovering Alternative XMPP Connection Methods XEP-0156: Discovering Alternative XMPP Connection Methods <http://xmpp.org/extensions/xep-0156.html>." > Contact Addresses for XMPP Services XEP-0157: Contact Addresses for XMPP Services <http://xmpp.org/extensions/xep-0157.html>." > CAPTCHA Forms XEP-0158: CAPTCHA Forms <http://xmpp.org/extensions/xep-0158.html>." > SPIM-Blocking Control XEP-0159: SPIM-Blocking Control <http://xmpp.org/extensions/xep-0159.html>." > Best Practices for Handling Offline Messages XEP-0160: Best Practices for Handling Offline Messages <http://xmpp.org/extensions/xep-0160.html>." > SPIM Reporting XEP-0161: SPIM Reporting <http://xmpp.org/extensions/xep-0161.html>." > Best Practices for Roster and Subscription Management XEP-0162: Best Practices for Roster and Subscription Management <http://xmpp.org/extensions/xep-0162.html>." > Personal Eventing Protocol XEP-0163: Personal Eventing Protocol <http://xmpp.org/extensions/xep-0163.html>." > vCard Filtering XEP-0164: vCard Filtering <http://xmpp.org/extensions/xep-0164.html>." > Best Practices to Prevent JID Mimicking XEP-0165: Best Practices to Prevent JID Mimicking <http://xmpp.org/extensions/xep-0165.html>." > Jingle XEP-0166: Jingle <http://xmpp.org/extensions/xep-0166.html>." > Jingle RTP Sessions XEP-0167: Jingle RTP Sessions <http://xmpp.org/extensions/xep-0167.html>." > Resource Application Priority XEP-0168: Resource Application Priority <http://xmpp.org/extensions/xep-0168.html>." > Twas The Night Before Christmas (Jabber Version) XEP-0169: Twas The Night Before Christmas (Jabber Version) <http://xmpp.org/extensions/xep-0169.html>." > Recommended Order of Stream Feature Negotiation XEP-0170: Recommended Order of Stream Feature Negotiation <http://xmpp.org/extensions/xep-0170.html>." > Language Translation XEP-0171: Language Translation <http://xmpp.org/extensions/xep-0171.html>." > User Nickname XEP-0172: User Nickname <http://xmpp.org/extensions/xep-0172.html>." > Pubsub Subscription Storage XEP-0173: Pubsub Subscription Storage <http://xmpp.org/extensions/xep-0173.html>." > Link-Local Messaging XEP-0174: Link-Local Messaging <http://xmpp.org/extensions/xep-0174.html>." > Best Practices for Use of SASL ANONYMOUS XEP-0175: Best Practices for Use of SASL ANONYMOUS <http://xmpp.org/extensions/xep-0175.html>." > Jingle ICE-UDP Transport Method XEP-0176: Jingle ICE-UDP Transport Method <http://xmpp.org/extensions/xep-0176.html>." > Jingle Raw UDP Transport Method XEP-0177: Jingle Raw UDP Transport Method <http://xmpp.org/extensions/xep-0177.html>." > Best Practices for Use of SASL EXTERNAL XEP-0178: Best Practices for Use of SASL EXTERNAL <http://xmpp.org/extensions/xep-0178.html>." > Jingle IAX Transport Method XEP-0179: Jingle IAX Transport Method <http://xmpp.org/extensions/xep-0179.html>." > Jingle Video via RTP XEP-0180: Jingle Video via RTP <http://xmpp.org/extensions/xep-0180.html>." > Jingle DTMF XEP-0181: Jingle DTMF <http://xmpp.org/extensions/xep-0181.html>." > Application-Specific Error Conditions XEP-0182: Application-Specific Error Conditions <http://xmpp.org/extensions/xep-0182.html>." > Jingle Telepathy Transport Method XEP-0183: Jingle Telepathy Transport Method <http://xmpp.org/extensions/xep-0183.html>." > Message Receipts XEP-0184: Message Receipts <http://xmpp.org/extensions/xep-0184.html>." > Dialback Key Generation and Validation XEP-0185: Dialback Key Generation and Validation <http://xmpp.org/extensions/xep-0185.html>." > Invisible Command XEP-0186: Invisible Command <http://xmpp.org/extensions/xep-0186.html>." > Offline Encrypted Sessions XEP-0187: Offline Encrypted Sessions <http://xmpp.org/extensions/xep-0187.html>." > Cryptographic Design of Encrypted Sessions XEP-0188: Cryptographic Design of Encrypted Sessions <http://xmpp.org/extensions/xep-0188.html>." > Public Key Publishing XEP-0189: Public Key Publishing <http://xmpp.org/extensions/xep-0189.html>." > Best Practice for Closing Idle Streams XEP-0190: Best Practice for Closing Idle Streams <http://xmpp.org/extensions/xep-0190.html>." > Simple Communications Blocking XEP-0191: Simple Communications Blocking <http://xmpp.org/extensions/xep-0191.html>." > Proposed Stream Feature Improvements XEP-0192: Proposed Stream Feature Improvements <http://xmpp.org/extensions/xep-0192.html>." > Proposed Resource Binding Improvements XEP-0193: Proposed Resource Binding Improvements <http://xmpp.org/extensions/xep-0193.html>." > User Chatting XEP-0194: User Chatting <http://xmpp.org/extensions/xep-0194.html>." > User Browsing XEP-0195: User Browsing <http://xmpp.org/extensions/xep-0195.html>." > User Gaming XEP-0196: User Gaming <http://xmpp.org/extensions/xep-0196.html>." > User Viewing XEP-0197: User Viewing <http://xmpp.org/extensions/xep-0197.html>." > Stanza Acknowledgements XEP-0198: Stanza Acknowledgements <http://xmpp.org/extensions/xep-0198.html>." > XMPP Ping XEP-0199: XMPP Ping <http://xmpp.org/extensions/xep-0199.html>." > Stanza Encryption XEP-0200: Stanza Encryption <http://xmpp.org/extensions/xep-0200.html>." > Best Practices for Message Threads XEP-0201: Best Practices for Message Threads <http://xmpp.org/extensions/xep-0201.html>." > Entity Time XEP-0202: Entity Time <http://xmpp.org/extensions/xep-0202.html>." > Delayed Delivery XEP-0203: Delayed Delivery <http://xmpp.org/extensions/xep-0203.html>." > Collaborative Data Objects XEP-0204: Collaborative Data Objects <http://xmpp.org/extensions/xep-0204.html>." > Best Practices to Discourage Denial of Service Attacks XEP-0205: Best Practices to Discourage Denial of Service Attacks <http://xmpp.org/extensions/xep-0205.html>." > XMPP Over BOSH XEP-0206: XMPP Over BOSH <http://xmpp.org/extensions/xep-0206.html>." > XMPP Eventing via Pubsub XEP-0207: Eventing via Pubsub <http://xmpp.org/extensions/xep-0207.html>." > Bootstrapping Implementation of Jingle XEP-0208: Bootstrapping Implementation of Jingle <http://xmpp.org/extensions/xep-0208.html>." > Metacontacts XEP-0209: Metacontacts <http://xmpp.org/extensions/xep-0209.html>." > Requirements for Encrypted Sessions XEP-0210: Requirements for Encrypted Sessions <http://xmpp.org/extensions/xep-0210.html>." > XMPP Basic Client 2008 XEP-0211: XMPP Basic Client 2008 <http://xmpp.org/extensions/xep-0211.html>." > XMPP Basic Server 2008 XEP-0212: XMPP Basic Server 2008 <http://xmpp.org/extensions/xep-0212.html>." > XMPP Intermediate IM Client 2008 XEP-0213: XMPP Intermediate IM Client 2008 <http://xmpp.org/extensions/xep-0213.html>." > File Repository and Sharing XEP-0214: File Repository and Sharing <http://xmpp.org/extensions/xep-0214.html>." > External Service Discovery XEP-0215: External Service Discovery <http://xmpp.org/extensions/xep-0215.html>." > XMPP Intermediate IM Server 2008 XEP-0216: XMPP Intermediate IM Server 2008 <http://xmpp.org/extensions/xep-0216.html>." > Simplified Encrypted Session Negotiation XEP-0217: Simplified Encrypted Session Negotiation <http://xmpp.org/extensions/xep-0217.html>." > Bootstrapping Implementation of Encrypted Sessions XEP-0218: Bootstrapping Implementation of Encrypted Sessions <http://xmpp.org/extensions/xep-0218.html>." > Hop Check XEP-0219: Hop Check <http://xmpp.org/extensions/xep-0219.html>." > Server Dialback XEP-0220: Server Dialback <http://xmpp.org/extensions/xep-0220.html>." > Data Forms Media Element XEP-0221: Data Forms Media Element <http://xmpp.org/extensions/xep-0221.html>." > Best Practices for Persistent Storage of Public Data via Publish-Subscribe XEP-0222: Best Practices for Persistent Storage of Public Data via Publish-Subscribe <http://xmpp.org/extensions/xep-0222.html>." > Best Practices for Persistent Storage of Private Data via Publish-Subscribe XEP-0223: Best Practices for Persistent Storage of Private Data via Publish-Subscribe <http://xmpp.org/extensions/xep-0223.html>." > Attention XEP-0224: Attention <http://xmpp.org/extensions/xep-0224.html>." > Component Connections XEP-0225: Component Connections <http://xmpp.org/extensions/xep-0225.html>." > Message Stanza Profiles XEP-0226: Message Stanza Profiles <http://xmpp.org/extensions/xep-0226.html>." > Portable Import/Export Format for XMPP-IM Servers XEP-0227: Portable Import/Export Format for XMPP-IM Servers <http://xmpp.org/extensions/xep-0227.html>." > Requirements for Shared Editing XEP-0228: Requirements for Shared Editing <http://xmpp.org/extensions/xep-0228.html>." > Stream Compression with LZW XEP-0229: Stream Compression with LZW <http://xmpp.org/extensions/xep-0229.html>." > Service Discovery Notifications XEP-0230: Service Discovery Notifications <http://xmpp.org/extensions/xep-0230.html>." > Bits of Binary XEP-0231: Bits of Binary <http://xmpp.org/extensions/xep-0231.html>." > Software Information XEP-0232: Software Information <http://xmpp.org/extensions/xep-0232.html>." > Use of Domain-Based Service Names in XMPP SASL Negotiation XEP-0233: Use of Domain-Based Service Names in XMPP SASL Negotiation <http://xmpp.org/extensions/xep-0233.html>." > Jingle File Transfer XEP-0234: Jingle File Transfer <http://xmpp.org/extensions/xep-0234.html>." > Direct Invitations XEP-0235: Direct Invitations <http://xmpp.org/extensions/xep-0235.html>." > Abuse Reporting XEP-0236: Abuse Reporting <http://xmpp.org/extensions/xep-0236.html>." > Roster Sequencing XEP-0237: Roster Sequencing <http://xmpp.org/extensions/xep-0237.html>." > XMPP Protocol Flows for Inter-Domain Federation XEP-0238: XMPP Protocol Flows for Inter-Domain Federation <http://xmpp.org/extensions/xep-0238.html>." > Binary XMPP XEP-0239: Binary XMPP <http://xmpp.org/extensions/xep-0239.html>." > Auto-Discovery of JabberIDs XEP-0240: Auto-Discovery of JabberIDs <http://xmpp.org/extensions/xep-0240.html>." > Encryption of Archived Messages XEP-0241: Encryption of Archived Messages <http://xmpp.org/extensions/xep-0241.html>." > XMPP Client Compliance 2009 XEP-0242: XMPP Client Compliance 2009 <http://xmpp.org/extensions/xep-0242.html>." > XMPP Server Compliance 2009 XEP-0243: XMPP Server Compliance 2009 <http://xmpp.org/extensions/xep-0243.html>." > IO Data XEP-0244: IO Data <http://xmpp.org/extensions/xep-0244.html>." > The /me Command XEP-0245: The /me Command <http://xmpp.org/extensions/xep-0245.html>." > End-to-End XML Streams XEP-0246: End-to-End XML Streams <http://xmpp.org/extensions/xep-0246.html>." > Jingle XML Streams XEP-0247: Jingle XML Streams <http://xmpp.org/extensions/xep-0247.html>." > PubSub Collection Nodes XEP-0248: PubSub Collection Nodes <http://xmpp.org/extensions/xep-0248.html>." > Direct MUC Invitations XEP-0249: Direct MUC Invitations <http://xmpp.org/extensions/xep-0249.html>." > C2C Authentication Using TLS XEP-0250: C2C Authentication Using TLS <http://xmpp.org/extensions/xep-0250.html>." > Jingle Session Transfer XEP-0251: Jingle Session Transfer <http://xmpp.org/extensions/xep-0251.html>." > BOSH Script Syntax XEP-0252: BOSH Script Syntax <http://xmpp.org/extensions/xep-0252.html>." > PubSub Chaining XEP-0253: PubSub Chaining <http://xmpp.org/extensions/xep-0253.html>." > PubSub Queueing XEP-0254: PubSub Queueing <http://xmpp.org/extensions/xep-0254.html>." > Location Query XEP-0255: Location Query <http://xmpp.org/extensions/xep-0255.html>." > Last Activity in Presence XEP-0256: Last Activity in Presence <http://xmpp.org/extensions/xep-0256.html>." > Client Certificate Management for SASL EXTERNAL XEP-0257: Client Certificate Management for SASL EXTERNAL <http://xmpp.org/extensions/xep-0257.html>." > Security Labels in XMPP XEP-0258: Security Labels in XMPP <http://xmpp.org/extensions/xep-0258.html>." > Message Mine-ing XEP-0259: Message Mine-ing <http://xmpp.org/extensions/xep-0259.html>." > Jingle SOCKS5 Bytestreams Transport Method XEP-0260: Jingle SOCKS5 Bytestreams Transport Method <http://xmpp.org/extensions/xep-0260.html>." > Jingle In-Band Bytestreams Transport Method XEP-0261: Jingle In-Band Bytestreams Transport Method <http://xmpp.org/extensions/xep-0261.html>." > Use of ZRTP in Jingle RTP Sessions XEP-0262: Use of ZRTP in Jingle RTP Sessions <http://xmpp.org/extensions/xep-0262.html>." > ECO-XMPP XEP-0263: ECO-XMPP <http://xmpp.org/extensions/xep-0263.html>." > File Transfer Thumbnails XEP-0264: File Transfer Thumbnails <http://xmpp.org/extensions/xep-0264.html>." > Out-of-Band Stream Data XEP-0265: Out-of-Band Stream Data <http://xmpp.org/extensions/xep-0265.html>." > Codecs for Jingle RTP Sessions XEP-0266: Codecs for Jingle RTP Sessions <http://xmpp.org/extensions/xep-0266.html>." > Server Rosters XEP-0267: Server Rosters <http://xmpp.org/extensions/xep-0267.html>." > Incident Reporting XEP-0268: Incident Reporting <http://xmpp.org/extensions/xep-0268.html>." > Jingle Early Media XEP-0269: Jingle Early Media <http://xmpp.org/extensions/xep-0269.html>." > XMPP Compliance Suites 2010 XEP-0270: XMPP Compliance Suites 2010 <http://xmpp.org/extensions/xep-0270.html>." > XMPP Nodes XEP-0271: XMPP Nodes <http://xmpp.org/extensions/xep-0271.html>." > Multiparty Jingle XEP-0272: Multiparty Jingle <http://xmpp.org/extensions/xep-0272.html>." > Stanza Interception and Filtering Technology XEP-0273: Stanza Interception and Filtering Technology <http://xmpp.org/extensions/xep-0273.html>." > Design Considerations for Digital Signatures in XMPP XEP-0274: Design Considerations for Digital Signatures in XMPP <http://xmpp.org/extensions/xep-0274.html>." > telepathy-gabble-0.18.3/docs/xep.dtd0000644000175000017500000001166611423525545020435 0ustar00cassidycassidy00000000000000 telepathy-gabble-0.18.3/docs/si-multiple.xml0000644000175000017500000001027311203043217022106 0ustar00cassidycassidy00000000000000 ]>
Stream initiation multi-bytestreams extension Extension of XEP-0095 allowing to negotiate more than one bytestream to be used as a fallback. Copyright (c) 2008 Collabora Limited. This document may be distributed under the same terms as the Telepathy specification. si-multiple ProtoXEP Extension Standards Telepathy project XMPP Core XEP-0095 NOT YET ASSIGNED Guillaume Desmottes guillaume.desmottes@collabora.co.uk guillaume.desmottes@collabora.co.uk 0.0.1 2008-12-11 cassidy

First draft.

This document describes an extension of the Stream Initiation (SI) protocol. With current SI protocol, the receiver has to choose which bytestream method he wants to use for the data streaming. If he chooses an efficient method as SOCKS5 (XEP-0065) and this method fails because of network topology, the SI fails and data can't be transferred. The protocol described in this document aims to solve this problem by allowing users to fallback to another bytestream method if the first one failed.

When sending a SI request, the sender informs the receiver that he supports multi-bytestreams by adding the si-multiple node.

]]>

If the receiver support multi-bytestreams as well, he sends a list of the methods supported instead of the normal SI reply. Bytestreams will be try by the sender in that order.

XEP-0047). Each bytestream is negotiated according the protocol described in its XEP. Once a bytestream has been sucessfully established, all the data are send using it and the other methods are not used.

None.

None.

None.

TODO
telepathy-gabble-0.18.3/docs/Makefile.in0000664000175000017500000004303412332443655021206 0ustar00cassidycassidy00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = docs DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_config_dir.m4 \ $(top_srcdir)/m4/compiler.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/tp-compiler-flag.m4 \ $(top_srcdir)/m4/tp-compiler-warnings.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man8dir = $(mandir)/man8 am__installdirs = "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(htmldir)" NROFF = nroff MANS = $(man_MANS) DATA = $(html_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLIENT_TYPE = @CLIENT_TYPE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_CODING_STYLE_CHECKS = @ENABLE_CODING_STYLE_CHECKS@ ENABLE_PLUGINS = @ENABLE_PLUGINS@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NICE_CFLAGS = @NICE_CFLAGS@ NICE_LIBS = @NICE_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOUP_CFLAGS = @SOUP_CFLAGS@ SOUP_LIBS = @SOUP_LIBS@ STRIP = @STRIP@ TEST_PYTHON = @TEST_PYTHON@ TP_GLIB_CFLAGS = @TP_GLIB_CFLAGS@ TP_GLIB_LIBS = @TP_GLIB_LIBS@ VERSION = @VERSION@ WOCKY_CFLAGS = @WOCKY_CFLAGS@ WOCKY_LIBS = @WOCKY_LIBS@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gabbletestsdir = @gabbletestsdir@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ # htmldir is not defined by autoconf < 2.59c htmldir = $(if $(filter-out @%@,@htmldir@),@htmldir@,$(datadir)/doc/$(PACKAGE)) includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ pluginexecdir = @pluginexecdir@ pluginexeclibdir = @pluginexeclibdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ tools_dir = $(top_srcdir)/tools man_MANS = telepathy-gabble.8 html_DATA = \ olpc.html \ muc-bytestream.html \ si-multiple.html \ tubes.html EXTRA_DIST = \ $(man_MANS:.8=.8.in) \ $(html_DATA:.html=.xml) \ tube-caps.txt \ xep.dtd \ xep.ent \ xep.xsd \ xep.xsl CLEANFILES = \ $(man_MANS) \ $(html_DATA) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu docs/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-man8: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man8dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.8[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ done; } uninstall-man8: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) install-htmlDATA: $(html_DATA) @$(NORMAL_INSTALL) @list='$(html_DATA)'; test -n "$(htmldir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)'"; \ $(MKDIR_P) "$(DESTDIR)$(htmldir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(htmldir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(htmldir)" || exit $$?; \ done uninstall-htmlDATA: @$(NORMAL_UNINSTALL) @list='$(html_DATA)'; test -n "$(htmldir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(htmldir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(MANS) $(DATA) installdirs: for dir in "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(htmldir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-htmlDATA install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man8 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-htmlDATA uninstall-man uninstall-man: uninstall-man8 .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-htmlDATA install-info install-info-am \ install-man install-man8 install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags-am uninstall uninstall-am uninstall-htmlDATA \ uninstall-man uninstall-man8 %.8: %.8.in Makefile $(AM_V_GEN)sed -e 's,[@]libexecdir[@],@libexecdir@,' < $< > $@ $(html_DATA): %.html: %.xml xep.xsl xep.dtd xep.ent $(AM_V_GEN)$(XSLTPROC) $(srcdir)/xep.xsl $< > $@ proto-xep-upload: $(html_DATA) rsync -P $(html_DATA) people.collabora.co.uk:public_html/ .PHONY: proto-xep-upload maintainer-update-from-xmpp.org: set -e; \ for x in xep.dtd xep.ent xep.xsd xep.xsl; do \ uri=svn://svn.xmpp.org:7938/xmpp/trunk/extensions/$$x; \ svn info $$uri; \ svn cat $$uri > $$x.tmp; \ mv $$x.tmp $$x; \ done # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: telepathy-gabble-0.18.3/docs/xep.xsl0000644000175000017500000013132711423525545020465 0ustar00cassidycassidy00000000000000 XEP-<xsl:value-of select='/xep/header/number'/>:<xsl:text> </xsl:text><xsl:value-of select='/xep/header/title' /> DC.Title DC.Description DC.Publisher XMPP Standards Foundation DC.Contributor XMPP Extensions Editor DC.Date DC.Type XMPP Extension Protocol DC.Format XHTML DC.Identifier XEP- DC.Language en DC.Rights

XEP-:

Abstract:
Author:
Authors: ,
Copyright: © 1999 - 2009 XMPP Standards Foundation. SEE LEGAL NOTICES.
Status:
Type:
Version:
Last Updated:

NOTICE: This Historical specification provides canonical documentation of a protocol that is in use within the Jabber/XMPP community. This document is not a standards-track specification within the XMPP Standards Foundation's standards process; however, it might be converted to standards-track in the future or might be obsoleted by a more modern protocol.

NOTICE: This document is Humorous. It MAY provide amusement but SHOULD NOT be taken seriously.

NOTICE: This Informational specification defines a best practice or protocol profile that has been approved by the XMPP Council and/or the XSF Board of Directors. Implementations are encouraged and the best practice or protocol profile is appropriate for deployment in production systems.

NOTICE: This Procedural document defines a process or activity of the XMPP Standards Foundation (XSF) that has been approved by the XMPP Council and/or the XSF Board of Directors. The XSF is currently following the process or activity defined herein and will do so until this document is deprecated or obsoleted.

WARNING: Consideration of this document has been Deferred by the XMPP Standards Foundation. Implementation of the protocol described herein is not recommended.

WARNING: This document has been Deprecated by the XMPP Standards Foundation. Implementation of the protocol described herein is not recommended. Developers desiring similar functionality are advised to implement the protocol that supersedes this one (if any).

NOTICE: The protocol defined herein is a Draft Standard of the XMPP Standards Foundation. Implementations are encouraged and the protocol is appropriate for deployment in production systems, but some changes to the protocol are possible before it becomes a Final Standard.

NOTICE: This Historical document attempts to provide canonical documentation of a protocol that is in use within the Jabber/XMPP community. Publication as an XMPP Extension Protocol does not imply approval of this proposal by the XMPP Standards Foundation. This document is not a standards-track specification within the XMPP Standards Foundation's standards process; however, it might be converted to standards-track in the future or might be obsoleted by a more modern protocol.

WARNING: This Informational document is Experimental. Publication as an XMPP Extension Protocol does not imply approval of this proposal by the XMPP Standards Foundation. Implementation of the best practice or protocol profile described herein is encouraged in exploratory implementations, although production systems are advised to carefully consider whether it is appropriate to deploy implementations of this protocol before it advances to a status of Draft.

NOTICE: This Procedural document proposes that the process or activity defined herein shall be followed by the XMPP Standards Foundation (XSF). However, this process or activity has not yet been approved by the XMPP Council and/or the XSF Board of Directors and is therefore not currently in force.

WARNING: This Standards-Track document is Experimental. Publication as an XMPP Extension Protocol does not imply approval of this proposal by the XMPP Standards Foundation. Implementation of the protocol described herein is encouraged in exploratory implementations, but production systems are advised to carefully consider whether it is appropriate to deploy implementations of this protocol before it advances to a status of Draft.

NOTICE: The protocol defined herein is a Final Standard of the XMPP Standards Foundation and can be considered a stable technology for implementation and deployment.

WARNING: This document has been obsoleted by the XMPP Standards Foundation. Implementation of the protocol described herein is not recommended. Developers desiring similar functionality are advised to implement the protocol that supersedes this one (if any).

NOTICE: This document is currently within Last Call or under consideration by the XMPP Council for advancement to the next stage in the XSF standards process. The Last Call ends on . Please send your feedback to the standards@xmpp.org discussion list.

WARNING: This document has not yet been accepted for consideration or approved in any official manner by the XMPP Standards Foundation, and this document is not yet an XMPP Extension Protocol (XEP). If this document is accepted as a XEP by the XMPP Council, it will be published at <http://xmpp.org/extensions/> and announced on the <standards@xmpp.org> mailing list.

WARNING: This document has been Rejected by the XMPP Council. Implementation of the protocol described herein is not recommended under any circumstances.

WARNING: This document has been retracted by the author(s). Implementation of the protocol described herein is not recommended. Developers desiring similar functionality are advised to implement the protocol that supersedes this one (if any).




Appendices


Appendix A: Document Information

Series: XEP
Number:
Publisher: XMPP Standards Foundation
Status: http://xmpp.org/extensions/xep-0001.html#states-
Type: http://xmpp.org/extensions/xep-0001.html#types-
Version:
Last Updated:
Expires:
Approving Body: XSF Board of Directors
Approving Body: XMPP Council
Dependencies:
Dependencies: None
Supersedes:
Supersedes: None
Superseded By:
Superseded By: None
Short Name:
Registry: http://xmpp.org/registrar/ .html <>
http://svn.xmpp.org:18080/browse/XMPP/trunk/extensions/xep- .xml http://svn.xmpp.org:18080//changelog/~rss/XMPP/trunk/extensions/xep- .xml/rss.xml Source Control: HTML  RSS


Appendix B: Author Information


Appendix C: Legal Notices


Appendix D: Relation to XMPP

The Extensible Messaging and Presence Protocol (XMPP) is defined in the XMPP Core (RFC 3920) and XMPP IM (RFC 3921) specifications contributed by the XMPP Standards Foundation to the Internet Standards Process, which is managed by the Internet Engineering Task Force in accordance with RFC 2026. Any protocol defined in this document has been developed outside the Internet Standards Process and is to be understood as an extension to XMPP rather than as an evolution, development, or modification of XMPP itself.


Appendix E: Discussion Venue

http://mail.jabber.org/mailman/listinfo/ @xmpp.org

There exists a special venue for discussion related to the technology described in this document: the <> mailing list.

The primary venue for discussion of XMPP Extension Protocols is the <standards@xmpp.org> discussion list.

Discussion by the membership of the XSF might also be appropriate (see <http://mail.jabber.org/mailman/listinfo/members> for details).

The primary venue for discussion of XMPP Extension Protocols is the <standards@xmpp.org> discussion list.

Discussion on other xmpp.org discussion lists might also be appropriate; see <http://xmpp.org/about/discuss.shtml> for a complete list.

Given that this XMPP Extension Protocol normatively references IETF technologies, discussion on the <xsf-ietf@xmpp.org> list might also be appropriate.

Errata can be sent to <editor@xmpp.org>.


Appendix F: Requirements Conformance

The following requirements keywords as used in this document are to be interpreted as described in RFC 2119: "MUST", "SHALL", "REQUIRED"; "MUST NOT", "SHALL NOT"; "SHOULD", "RECOMMENDED"; "SHOULD NOT", "NOT RECOMMENDED"; "MAY", "OPTIONAL".


Appendix G: Notes


Appendix H: Revision History

Note: Older versions of this specification might be available at http://xmpp.org/extensions/attic/


END

Table of Contents

DC.Creator

See Author Note
Organization:
Email: mailto:
JabberID: xmpp:
URI:

Copyright

Permissions

Disclaimer of Warranty

Limitation of Liability

IPR Conformance

, XML Schema for namespace: <>
Schema: <>

Version ()

()
.
# sect-

. sect-

.
    # sect-
.
       # sect-
.
         # sect-


  • example-Example .

    table-Table :

    [ ]

    .

    telepathy-gabble-0.18.3/config.guess0000755000175000017500000012746312332443655020540 0ustar00cassidycassidy00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012, 2013 Free Software Foundation, Inc. timestamp='2012-12-29' # This file 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 3 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, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD # # Please send patches with a ChangeLog entry to config-patches@gnu.org. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-gnu else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-gnueabi else echo ${UNAME_MACHINE}-unknown-linux-gnueabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-gnu exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-gnu exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; i*86:Linux:*:*) LIBC=gnu eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __dietlibc__ LIBC=dietlibc #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` echo "${UNAME_MACHINE}-pc-linux-${LIBC}" exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; or32:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; padre:Linux:*:*) echo sparc-unknown-linux-gnu exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-gnu exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in i386) eval $set_cc_for_build if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then UNAME_PROCESSOR="x86_64" fi fi ;; unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; esac eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: telepathy-gabble-0.18.3/plugins/0000775000175000017500000000000012332445275017666 5ustar00cassidycassidy00000000000000telepathy-gabble-0.18.3/plugins/Makefile.am0000664000175000017500000000314712332441362021720 0ustar00cassidycassidy00000000000000installable_plugins = \ libconsole.la \ libgateways.la libtest_only_plugins = \ libtest.la # libtesting-only plugins if ENABLE_INSTALLED_TESTS noinst_LTLIBRARIES = \ $(NULL) libtestplugindir = $(gabbletestsdir)/plugins libtestplugin_LTLIBRARIES = \ $(libtest_only_plugins) \ $(NULL) libtest_la_LDFLAGS = $(AM_LDFLAGS) else noinst_LTLIBRARIES = \ $(libtest_only_plugins) \ $(NULL) # because libtest.la is not installed, libtool will want to compile it as static # despite -shared (a convenience library), unless we also use -rpath libtest_la_LDFLAGS = $(AM_LDFLAGS) -rpath $(pluginexecdir) endif if ENABLE_PLUGINS pluginexec_LTLIBRARIES = $(installable_plugins) dist_bin_SCRIPTS = \ telepathy-gabble-xmpp-console else # we still compile the plugin (just to make sure it compiles!) but we don't # install it noinst_LTLIBRARIES += $(installable_plugins) EXTRA_DIST = \ telepathy-gabble-xmpp-console endif AM_LDFLAGS = -avoid-version -shared -no-undefined ALL_PLUGIN_LIBS = \ @WOCKY_LIBS@ \ @GLIB_LIBS@ \ @TP_GLIB_LIBS@ \ $(top_builddir)/extensions/libgabble-extensions.la \ $(top_builddir)/src/libgabble-plugins.la libtest_la_LIBADD = $(ALL_PLUGIN_LIBS) libgateways_la_LIBADD = $(ALL_PLUGIN_LIBS) libconsole_la_LIBADD = $(ALL_PLUGIN_LIBS) libtest_la_SOURCES = \ test.c \ test.h libgateways_la_SOURCES = \ gateways.c \ gateways.h libconsole_la_SOURCES = \ console.c \ console.h AM_CFLAGS = $(ERROR_CFLAGS) \ -I $(top_srcdir) -I $(top_builddir) \ @DBUS_CFLAGS@ @GLIB_CFLAGS@ @WOCKY_CFLAGS@ @TP_GLIB_CFLAGS@ \ -I $(top_srcdir)/gabble -I $(top_builddir)/gabble \ -I $(top_srcdir)/plugins telepathy-gabble-0.18.3/plugins/console.c0000664000175000017500000004423612332441362021476 0ustar00cassidycassidy00000000000000/* XML console plugin * * Copyright © 2011 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "console.h" #include #include #include #include "extensions/extensions.h" #include /************************* * Plugin implementation * *************************/ static guint debug = 0; #define DEBUG(format, ...) \ G_STMT_START { \ if (debug != 0) \ g_debug ("%s: " format, G_STRFUNC, ## __VA_ARGS__); \ } G_STMT_END static const GDebugKey debug_keys[] = { { "console", 1 }, { NULL, 0 } }; static void plugin_iface_init ( gpointer g_iface, gpointer data); static const gchar * const sidecar_interfaces[] = { GABBLE_IFACE_GABBLE_PLUGIN_CONSOLE, NULL }; G_DEFINE_TYPE_WITH_CODE (GabbleConsolePlugin, gabble_console_plugin, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GABBLE_TYPE_PLUGIN, plugin_iface_init); ) static void gabble_console_plugin_init (GabbleConsolePlugin *self) { } static void gabble_console_plugin_class_init (GabbleConsolePluginClass *klass) { } static void gabble_console_plugin_create_sidecar_async ( GabblePlugin *plugin, const gchar *sidecar_interface, GabblePluginConnection *connection, WockySession *session, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (plugin), callback, user_data, gabble_console_plugin_create_sidecar_async); GabbleSidecar *sidecar = NULL; if (!tp_strdiff (sidecar_interface, GABBLE_IFACE_GABBLE_PLUGIN_CONSOLE)) { sidecar = g_object_new (GABBLE_TYPE_CONSOLE_SIDECAR, "connection", connection, "session", session, NULL); } else { g_simple_async_result_set_error (result, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "'%s' not implemented", sidecar_interface); } if (sidecar != NULL) g_simple_async_result_set_op_res_gpointer (result, sidecar, g_object_unref); g_simple_async_result_complete_in_idle (result); g_object_unref (result); } static GabbleSidecar * gabble_console_plugin_create_sidecar_finish ( GabblePlugin *plugin, GAsyncResult *result, GError **error) { GabbleSidecar *sidecar; if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) return NULL; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (plugin), gabble_console_plugin_create_sidecar_async), NULL); sidecar = GABBLE_SIDECAR (g_simple_async_result_get_op_res_gpointer ( G_SIMPLE_ASYNC_RESULT (result))); return g_object_ref (sidecar); } static void plugin_iface_init ( gpointer g_iface, gpointer data G_GNUC_UNUSED) { GabblePluginInterface *iface = g_iface; iface->name = "XMPP console"; iface->version = PACKAGE_VERSION; iface->sidecar_interfaces = sidecar_interfaces; iface->create_sidecar_async = gabble_console_plugin_create_sidecar_async; iface->create_sidecar_finish = gabble_console_plugin_create_sidecar_finish; } GabblePlugin * gabble_plugin_create (void) { debug = g_parse_debug_string (g_getenv ("GABBLE_DEBUG"), debug_keys, G_N_ELEMENTS (debug_keys) - 1); DEBUG ("loaded"); return g_object_new (GABBLE_TYPE_CONSOLE_PLUGIN, NULL); } /************************** * Sidecar implementation * **************************/ enum { PROP_0, PROP_CONNECTION, PROP_SESSION, PROP_SPEW }; struct _GabbleConsoleSidecarPrivate { WockySession *session; TpBaseConnection *connection; WockyXmppReader *reader; WockyXmppWriter *writer; /* %TRUE if we should emit signals when sending or receiving stanzas */ gboolean spew; /* 0 if spew is FALSE; or a WockyPorter handler id for all incoming stanzas * if spew is TRUE. */ guint incoming_handler; /* 0 if spew is FALSE; a GLib signal handler id for WockyPorter::sending if * spew is TRUE. */ gulong sending_id; }; static void sidecar_iface_init ( gpointer g_iface, gpointer data); static void console_iface_init ( gpointer g_iface, gpointer data); static void gabble_console_sidecar_set_spew ( GabbleConsoleSidecar *self, gboolean spew); G_DEFINE_TYPE_WITH_CODE (GabbleConsoleSidecar, gabble_console_sidecar, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SIDECAR, sidecar_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_GABBLE_PLUGIN_CONSOLE, console_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, tp_dbus_properties_mixin_iface_init); ) static void gabble_console_sidecar_init (GabbleConsoleSidecar *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_CONSOLE_SIDECAR, GabbleConsoleSidecarPrivate); self->priv->reader = wocky_xmpp_reader_new_no_stream_ns ( WOCKY_XMPP_NS_JABBER_CLIENT); self->priv->writer = wocky_xmpp_writer_new_no_stream (); } static void gabble_console_sidecar_get_property ( GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GabbleConsoleSidecar *self = GABBLE_CONSOLE_SIDECAR (object); switch (property_id) { case PROP_SPEW: g_value_set_boolean (value, self->priv->spew); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); } } static void gabble_console_sidecar_set_property ( GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleConsoleSidecar *self = GABBLE_CONSOLE_SIDECAR (object); switch (property_id) { case PROP_CONNECTION: g_assert (self->priv->connection == NULL); /* construct-only */ self->priv->connection = g_value_dup_object (value); break; case PROP_SESSION: g_assert (self->priv->session == NULL); /* construct-only */ self->priv->session = g_value_dup_object (value); break; case PROP_SPEW: gabble_console_sidecar_set_spew (self, g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); } } static void gabble_console_sidecar_dispose (GObject *object) { void (*chain_up) (GObject *) = G_OBJECT_CLASS (gabble_console_sidecar_parent_class)->dispose; GabbleConsoleSidecar *self = GABBLE_CONSOLE_SIDECAR (object); gabble_console_sidecar_set_spew (self, FALSE); tp_clear_object (&self->priv->connection); tp_clear_object (&self->priv->reader); tp_clear_object (&self->priv->writer); tp_clear_object (&self->priv->session); if (chain_up != NULL) chain_up (object); } static void gabble_console_sidecar_class_init (GabbleConsoleSidecarClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); static TpDBusPropertiesMixinPropImpl console_props[] = { { "SpewStanzas", "spew-stanzas", "spew-stanzas" }, { NULL }, }; static TpDBusPropertiesMixinIfaceImpl interfaces[] = { { GABBLE_IFACE_GABBLE_PLUGIN_CONSOLE, tp_dbus_properties_mixin_getter_gobject_properties, /* FIXME: if we were feeling clever, we'd override the setter so that * we can monitor the bus name of any application which sets * SpewStanzas to TRUE and flip it back to false when that application * dies. * * Alternatively, we could just replace this sidecar with a channel. */ tp_dbus_properties_mixin_setter_gobject_properties, console_props }, { NULL }, }; object_class->get_property = gabble_console_sidecar_get_property; object_class->set_property = gabble_console_sidecar_set_property; object_class->dispose = gabble_console_sidecar_dispose; g_type_class_add_private (klass, sizeof (GabbleConsoleSidecarPrivate)); g_object_class_install_property (object_class, PROP_CONNECTION, g_param_spec_object ("connection", "Connection", "Gabble connection", GABBLE_TYPE_PLUGIN_CONNECTION, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_SESSION, g_param_spec_object ("session", "Session", "Wocky session", WOCKY_TYPE_SESSION, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_SPEW, g_param_spec_boolean ("spew-stanzas", "SpewStanzas", "If %TRUE, someone wants us to spit out a tonne of stanzas", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); klass->props_class.interfaces = interfaces; tp_dbus_properties_mixin_class_init (object_class, G_STRUCT_OFFSET (GabbleConsoleSidecarClass, props_class)); } static void sidecar_iface_init ( gpointer g_iface, gpointer data) { GabbleSidecarInterface *iface = g_iface; iface->interface = GABBLE_IFACE_GABBLE_PLUGIN_CONSOLE; iface->get_immutable_properties = NULL; } static gboolean incoming_cb ( WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { GabbleConsoleSidecar *self = GABBLE_CONSOLE_SIDECAR (user_data); const guint8 *body; gsize length; wocky_xmpp_writer_write_stanza (self->priv->writer, stanza, &body, &length); gabble_svc_gabble_plugin_console_emit_stanza_received (self, (const gchar *) body); return FALSE; } static void sending_cb ( WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { GabbleConsoleSidecar *self = GABBLE_CONSOLE_SIDECAR (user_data); if (stanza != NULL) { const guint8 *body; gsize length; wocky_xmpp_writer_write_stanza (self->priv->writer, stanza, &body, &length); gabble_svc_gabble_plugin_console_emit_stanza_sent (self, (const gchar *) body); } } static void gabble_console_sidecar_set_spew ( GabbleConsoleSidecar *self, gboolean spew) { GabbleConsoleSidecarPrivate *priv = self->priv; if (!spew != !priv->spew) { WockyPorter *porter = wocky_session_get_porter (self->priv->session); const gchar *props[] = { "SpewStanzas", NULL }; priv->spew = spew; tp_dbus_properties_mixin_emit_properties_changed (G_OBJECT (self), GABBLE_IFACE_GABBLE_PLUGIN_CONSOLE, props); if (spew) { g_return_if_fail (priv->incoming_handler == 0); priv->incoming_handler = wocky_porter_register_handler_from_anyone ( porter, WOCKY_STANZA_TYPE_NONE, WOCKY_STANZA_SUB_TYPE_NONE, WOCKY_PORTER_HANDLER_PRIORITY_MAX, incoming_cb, self, NULL); g_return_if_fail (priv->sending_id == 0); priv->sending_id = g_signal_connect (porter, "sending", (GCallback) sending_cb, self); } else { g_return_if_fail (priv->incoming_handler != 0); wocky_porter_unregister_handler (porter, priv->incoming_handler); priv->incoming_handler = 0; g_return_if_fail (priv->sending_id != 0); g_signal_handler_disconnect (porter, priv->sending_id); priv->sending_id = 0; } } } static void return_from_send_iq ( GObject *source, GAsyncResult *result, gpointer user_data) { GabbleConsoleSidecar *self = GABBLE_CONSOLE_SIDECAR (source); DBusGMethodInvocation *context = user_data; GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); GError *error = NULL; if (g_simple_async_result_propagate_error (simple, &error)) { dbus_g_method_return_error (context, error); g_error_free (error); } else { WockyStanza *reply = g_simple_async_result_get_op_res_gpointer (simple); WockyStanzaSubType sub_type; const guint8 *body; gsize length; wocky_stanza_get_type_info (reply, NULL, &sub_type); wocky_xmpp_writer_write_stanza (self->priv->writer, reply, &body, &length); /* woop woop */ gabble_svc_gabble_plugin_console_return_from_send_iq (context, sub_type == WOCKY_STANZA_SUB_TYPE_RESULT ? "result" : "error", (const gchar *) body); } } static void console_iq_reply_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { WockyPorter *porter = WOCKY_PORTER (source); GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); GError *error = NULL; WockyStanza *reply = wocky_porter_send_iq_finish (porter, result, &error); if (reply != NULL) { g_simple_async_result_set_op_res_gpointer (simple, reply, g_object_unref); } else { g_simple_async_result_set_from_error (simple, error); g_error_free (error); } g_simple_async_result_complete (simple); g_object_unref (simple); } static gboolean get_iq_type (const gchar *type_str, WockyStanzaSubType *sub_type_out, GError **error) { if (!wocky_strdiff (type_str, "get")) { *sub_type_out = WOCKY_STANZA_SUB_TYPE_GET; return TRUE; } if (!wocky_strdiff (type_str, "set")) { *sub_type_out = WOCKY_STANZA_SUB_TYPE_SET; return TRUE; } g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Type must be 'get' or 'set', not '%s'", type_str); return FALSE; } static gboolean validate_jid (const gchar **to, GError **error) { if (tp_str_empty (*to)) { *to = NULL; return TRUE; } if (wocky_decode_jid (*to, NULL, NULL, NULL)) return TRUE; g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "'%s' is not a valid (or empty) JID", *to); return FALSE; } /* * @xml: doesn't actually have to be a top-level stanza. It can be the body of * an IQ or whatever. If it has no namespace, it's assumed to be in * jabber:client. */ static gboolean parse_me_a_stanza ( GabbleConsoleSidecar *self, const gchar *xml, WockyStanza **stanza_out, GError **error) { GabbleConsoleSidecarPrivate *priv = self->priv; WockyStanza *stanza; wocky_xmpp_reader_reset (priv->reader); wocky_xmpp_reader_push (priv->reader, (const guint8 *) xml, strlen (xml)); *error = wocky_xmpp_reader_get_error (priv->reader); if (*error != NULL) return FALSE; stanza = wocky_xmpp_reader_pop_stanza (priv->reader); if (stanza == NULL) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Incomplete stanza! Bad person."); return FALSE; } *stanza_out = stanza; return TRUE; } static void console_send_iq ( GabbleSvcGabblePluginConsole *sidecar, const gchar *type_str, const gchar *to, const gchar *body, DBusGMethodInvocation *context) { GabbleConsoleSidecar *self = GABBLE_CONSOLE_SIDECAR (sidecar); WockyPorter *porter = wocky_session_get_porter (self->priv->session); WockyStanzaSubType sub_type; WockyStanza *fragment; GError *error = NULL; if (get_iq_type (type_str, &sub_type, &error) && validate_jid (&to, &error) && parse_me_a_stanza (self, body, &fragment, &error)) { GSimpleAsyncResult *simple = g_simple_async_result_new (G_OBJECT (self), return_from_send_iq, context, console_send_iq); WockyStanza *stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, sub_type, NULL, to, NULL); wocky_node_add_node_tree (wocky_stanza_get_top_node (stanza), WOCKY_NODE_TREE (fragment)); wocky_porter_send_iq_async (porter, stanza, NULL, console_iq_reply_cb, simple); g_object_unref (fragment); } else { DEBUG ("%s", error->message); dbus_g_method_return_error (context, error); g_error_free (error); } } static void console_stanza_sent_cb ( GObject *source, GAsyncResult *result, gpointer user_data) { WockyPorter *porter = WOCKY_PORTER (source); DBusGMethodInvocation *context = user_data; GError *error = NULL; if (wocky_porter_send_finish (porter, result, &error)) { gabble_svc_gabble_plugin_console_return_from_send_stanza (context); } else { dbus_g_method_return_error (context, error); g_clear_error (&error); } } static gboolean stanza_looks_coherent ( WockyStanza *stanza, GError **error) { WockyNode *top_node = wocky_stanza_get_top_node (stanza); WockyStanzaType t; WockyStanzaSubType st; wocky_stanza_get_type_info (stanza, &t, &st); if (t == WOCKY_STANZA_TYPE_UNKNOWN) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "I don't know what a <%s xmlns='%s'/> is", top_node->name, g_quark_to_string (top_node->ns)); return FALSE; } else if (st == WOCKY_STANZA_SUB_TYPE_UNKNOWN) { g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "I don't know what type='%s' means", wocky_node_get_attribute (top_node, "type")); return FALSE; } return TRUE; } static void console_send_stanza ( GabbleSvcGabblePluginConsole *sidecar, const gchar *xml, DBusGMethodInvocation *context) { GabbleConsoleSidecar *self = GABBLE_CONSOLE_SIDECAR (sidecar); WockyPorter *porter = wocky_session_get_porter (self->priv->session); WockyStanza *stanza = NULL; GError *error = NULL; if (parse_me_a_stanza (self, xml, &stanza, &error) && stanza_looks_coherent (stanza, &error)) { wocky_porter_send_async (porter, stanza, NULL, console_stanza_sent_cb, context); } else { DEBUG ("%s", error->message); dbus_g_method_return_error (context, error); g_error_free (error); } tp_clear_object (&stanza); } static void console_iface_init ( gpointer klass, gpointer data G_GNUC_UNUSED) { #define IMPLEMENT(x) gabble_svc_gabble_plugin_console_implement_##x (\ klass, console_##x) IMPLEMENT (send_iq); IMPLEMENT (send_stanza); #undef IMPLEMENT } telepathy-gabble-0.18.3/plugins/console.h0000664000175000017500000000651312332441362021477 0ustar00cassidycassidy00000000000000/* XML console plugin * * Copyright © 2011 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include typedef struct _GabbleConsolePlugin GabbleConsolePlugin; typedef struct _GabbleConsolePluginClass GabbleConsolePluginClass; typedef struct _GabbleConsolePluginPrivate GabbleConsolePluginPrivate; struct _GabbleConsolePlugin { GObject parent; GabbleConsolePluginPrivate *priv; }; struct _GabbleConsolePluginClass { GObjectClass parent; }; GType gabble_console_plugin_get_type (void); #define GABBLE_TYPE_CONSOLE_PLUGIN \ (gabble_console_plugin_get_type ()) #define GABBLE_CONSOLE_PLUGIN(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GABBLE_TYPE_CONSOLE_PLUGIN, \ GabbleConsolePlugin)) #define GABBLE_CONSOLE_PLUGIN_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), GABBLE_TYPE_CONSOLE_PLUGIN, \ GabbleConsolePluginClass)) #define GABBLE_IS_CONSOLE_PLUGIN(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GABBLE_TYPE_CONSOLE_PLUGIN)) #define GABBLE_IS_CONSOLE_PLUGIN_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), GABBLE_TYPE_CONSOLE_PLUGIN)) #define GABBLE_CONSOLE_PLUGIN_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_CONSOLE_PLUGIN, \ GabbleConsolePluginClass)) typedef struct _GabbleConsoleSidecar GabbleConsoleSidecar; typedef struct _GabbleConsoleSidecarClass GabbleConsoleSidecarClass; typedef struct _GabbleConsoleSidecarPrivate GabbleConsoleSidecarPrivate; struct _GabbleConsoleSidecar { GObject parent; GabbleConsoleSidecarPrivate *priv; }; struct _GabbleConsoleSidecarClass { GObjectClass parent; TpDBusPropertiesMixinClass props_class; }; GType gabble_console_sidecar_get_type (void); #define GABBLE_TYPE_CONSOLE_SIDECAR \ (gabble_console_sidecar_get_type ()) #define GABBLE_CONSOLE_SIDECAR(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GABBLE_TYPE_CONSOLE_SIDECAR, \ GabbleConsoleSidecar)) #define GABBLE_CONSOLE_SIDECAR_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), GABBLE_TYPE_CONSOLE_SIDECAR, \ GabbleConsoleSidecarClass)) #define GABBLE_IS_CONSOLE_SIDECAR(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GABBLE_TYPE_CONSOLE_SIDECAR)) #define GABBLE_IS_CONSOLE_SIDECAR_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), GABBLE_TYPE_CONSOLE_SIDECAR)) #define GABBLE_CONSOLE_SIDECAR_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_CONSOLE_SIDECAR, \ GabbleConsoleSidecarClass)) telepathy-gabble-0.18.3/plugins/test.h0000664000175000017500000001173011720700311021001 0ustar00cassidycassidy00000000000000#include #include #include #include #include /* Plugin */ typedef struct _TestPluginClass TestPluginClass; typedef struct _TestPlugin TestPlugin; struct _TestPluginClass { GObjectClass parent; }; struct _TestPlugin { GObject parent; }; GType test_plugin_get_type (void); #define TEST_TYPE_PLUGIN \ (test_plugin_get_type ()) #define TEST_PLUGIN(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), TEST_TYPE_PLUGIN, TestPlugin)) #define TEST_PLUGIN_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), TEST_TYPE_PLUGIN, \ TestPluginClass)) #define TEST_IS_PLUGIN(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), TEST_TYPE_PLUGIN)) #define TEST_IS_PLUGIN_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), TEST_TYPE_PLUGIN)) #define TEST_PLUGIN_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_PLUGIN, \ TestPluginClass)) /* Sidecar */ typedef struct _TestSidecarClass TestSidecarClass; typedef struct _TestSidecar TestSidecar; struct _TestSidecarClass { GObjectClass parent; }; struct _TestSidecar { GObject parent; }; GType test_sidecar_get_type (void); #define TEST_TYPE_SIDECAR \ (test_sidecar_get_type ()) #define TEST_SIDECAR(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), TEST_TYPE_SIDECAR, TestSidecar)) #define TEST_SIDECAR_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), TEST_TYPE_SIDECAR, \ TestSidecarClass)) #define TEST_IS_SIDECAR(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), TEST_TYPE_SIDECAR)) #define TEST_IS_SIDECAR_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), TEST_TYPE_SIDECAR)) #define TEST_SIDECAR_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_SIDECAR, \ TestSidecarClass)) /* Sidecar with properties */ typedef struct _TestSidecarPropsClass TestSidecarPropsClass; typedef struct _TestSidecarProps TestSidecarProps; struct _TestSidecarPropsClass { GObjectClass parent; }; struct _TestSidecarProps { GObject parent; GHashTable *props; }; GType test_sidecar_props_get_type (void); #define TEST_TYPE_SIDECAR_PROPS \ (test_sidecar_props_get_type ()) #define TEST_SIDECAR_PROPS(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), TEST_TYPE_SIDECAR_PROPS, TestSidecarProps)) #define TEST_SIDECAR_PROPS_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), TEST_TYPE_SIDECAR_PROPS, \ TestSidecarPropsClass)) #define TEST_IS_SIDECAR_PROPS(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), TEST_TYPE_SIDECAR_PROPS)) #define TEST_IS_SIDECAR_PROPS_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), TEST_TYPE_SIDECAR_PROPS)) #define TEST_SIDECAR_PROPS_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_SIDECAR_PROPS, \ TestSidecarPropsClass)) /* Sidecar which sends an IQ and waits for a reply before being ready. */ typedef struct _TestSidecarIQClass TestSidecarIQClass; typedef struct _TestSidecarIQ TestSidecarIQ; struct _TestSidecarIQClass { GObjectClass parent; }; struct _TestSidecarIQ { GObject parent; GSimpleAsyncResult *result; WockySession *session; GabblePluginConnection *connection; }; GType test_sidecar_iq_get_type (void); #define TEST_TYPE_SIDECAR_IQ \ (test_sidecar_iq_get_type ()) #define TEST_SIDECAR_IQ(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), TEST_TYPE_SIDECAR_IQ, TestSidecarIQ)) #define TEST_SIDECAR_IQ_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), TEST_TYPE_SIDECAR_IQ, \ TestSidecarIQClass)) #define TEST_IS_SIDECAR_IQ(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), TEST_TYPE_SIDECAR_IQ)) #define TEST_IS_SIDECAR_IQ_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), TEST_TYPE_SIDECAR_IQ)) #define TEST_SIDECAR_IQ_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_SIDECAR_IQ, \ TestSidecarIQClass)) /* Test channel manager */ typedef struct _TestChannelManager TestChannelManager; typedef struct _TestChannelManagerClass TestChannelManagerClass; struct _TestChannelManagerClass { GObjectClass parent_class; }; struct _TestChannelManager { GObject parent; GabblePluginConnection *plugin_connection; }; GType test_channel_manager_get_type (void); /* TYPE MACROS */ #define TEST_TYPE_CHANNEL_MANAGER \ (test_channel_manager_get_type ()) #define TEST_CHANNEL_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST((obj), TEST_TYPE_CHANNEL_MANAGER, TestChannelManager)) #define TEST_CHANNEL_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), TEST_TYPE_CHANNEL_MANAGER,\ TestChannelManagerClass)) #define TEST_IS_CHANNEL_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), TEST_TYPE_CHANNEL_MANAGER)) #define TEST_IS_CHANNEL_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass), TEST_TYPE_CHANNEL_MANAGER)) #define TEST_CHANNEL_MANAGER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_CHANNEL_MANAGER,\ TestChannelManagerClass)) telepathy-gabble-0.18.3/plugins/gateways.c0000664000175000017500000003723512332440117021656 0ustar00cassidycassidy00000000000000/* Gateway registration plugin * * Copyright © 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "config.h" #include "gateways.h" #include #include #include #include "extensions/extensions.h" #include /************************* * Plugin implementation * *************************/ static guint debug = 0; #define DEBUG(format, ...) \ G_STMT_START { \ if (debug != 0) \ g_debug ("%s: " format, G_STRFUNC, ## __VA_ARGS__); \ } G_STMT_END static const GDebugKey debug_keys[] = { { "gateways", 1 }, { NULL, 0 } }; static void plugin_iface_init ( gpointer g_iface, gpointer data); static const gchar * const sidecar_interfaces[] = { GABBLE_IFACE_GABBLE_PLUGIN_GATEWAYS, NULL }; G_DEFINE_TYPE_WITH_CODE (GabbleGatewayPlugin, gabble_gateway_plugin, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GABBLE_TYPE_PLUGIN, plugin_iface_init); ) static void gabble_gateway_plugin_init (GabbleGatewayPlugin *self) { } static void gabble_gateway_plugin_class_init (GabbleGatewayPluginClass *klass) { } static void gabble_gateway_plugin_create_sidecar_async ( GabblePlugin *plugin, const gchar *sidecar_interface, GabblePluginConnection *connection, WockySession *session, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (plugin), callback, user_data, gabble_gateway_plugin_create_sidecar_async); GabbleSidecar *sidecar = NULL; if (!tp_strdiff (sidecar_interface, GABBLE_IFACE_GABBLE_PLUGIN_GATEWAYS)) { sidecar = g_object_new (GABBLE_TYPE_GATEWAY_SIDECAR, "connection", connection, "session", session, NULL); } else { g_simple_async_result_set_error (result, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "'%s' not implemented", sidecar_interface); } if (sidecar != NULL) g_simple_async_result_set_op_res_gpointer (result, sidecar, g_object_unref); g_simple_async_result_complete_in_idle (result); g_object_unref (result); } static GabbleSidecar * gabble_gateway_plugin_create_sidecar_finish ( GabblePlugin *plugin, GAsyncResult *result, GError **error) { GabbleSidecar *sidecar; if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) return NULL; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (plugin), gabble_gateway_plugin_create_sidecar_async), NULL); sidecar = GABBLE_SIDECAR (g_simple_async_result_get_op_res_gpointer ( G_SIMPLE_ASYNC_RESULT (result))); return g_object_ref (sidecar); } static void plugin_iface_init ( gpointer g_iface, gpointer data G_GNUC_UNUSED) { GabblePluginInterface *iface = g_iface; iface->name = "Gateway registration plugin"; iface->version = PACKAGE_VERSION; iface->sidecar_interfaces = sidecar_interfaces; iface->create_sidecar_async = gabble_gateway_plugin_create_sidecar_async; iface->create_sidecar_finish = gabble_gateway_plugin_create_sidecar_finish; } GabblePlugin * gabble_plugin_create (void) { debug = g_parse_debug_string (g_getenv ("GABBLE_DEBUG"), debug_keys, G_N_ELEMENTS (debug_keys) - 1); DEBUG ("loaded"); return g_object_new (GABBLE_TYPE_GATEWAY_PLUGIN, NULL); } /************************** * Sidecar implementation * **************************/ enum { PROP_0, PROP_CONNECTION, PROP_SESSION }; struct _GabbleGatewaySidecarPrivate { WockySession *session; TpBaseConnection *connection; guint subscribe_id; guint subscribed_id; GHashTable *gateways; }; static void sidecar_iface_init ( gpointer g_iface, gpointer data); static void gateway_iface_init ( gpointer g_iface, gpointer data); G_DEFINE_TYPE_WITH_CODE (GabbleGatewaySidecar, gabble_gateway_sidecar, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SIDECAR, sidecar_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_GABBLE_PLUGIN_GATEWAYS, gateway_iface_init); ) static void gabble_gateway_sidecar_init (GabbleGatewaySidecar *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_GATEWAY_SIDECAR, GabbleGatewaySidecarPrivate); self->priv->gateways = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); } static void gabble_gateway_sidecar_set_property ( GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GabbleGatewaySidecar *self = GABBLE_GATEWAY_SIDECAR (object); switch (property_id) { case PROP_CONNECTION: g_assert (self->priv->connection == NULL); /* construct-only */ self->priv->connection = g_value_dup_object (value); break; case PROP_SESSION: g_assert (self->priv->session == NULL); /* construct-only */ self->priv->session = g_value_dup_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); } } static void gabble_gateway_sidecar_dispose (GObject *object) { void (*chain_up) (GObject *) = G_OBJECT_CLASS (gabble_gateway_sidecar_parent_class)->dispose; GabbleGatewaySidecar *self = GABBLE_GATEWAY_SIDECAR (object); tp_clear_object (&self->priv->connection); if (self->priv->session != NULL) { WockyPorter *porter = wocky_session_get_porter (self->priv->session); wocky_porter_unregister_handler (porter, self->priv->subscribe_id); wocky_porter_unregister_handler (porter, self->priv->subscribed_id); } tp_clear_object (&self->priv->session); if (chain_up != NULL) chain_up (object); } static gboolean presence_cb (WockyPorter *porter, WockyStanza *stanza, gpointer user_data) { GabbleGatewaySidecar *self = GABBLE_GATEWAY_SIDECAR (user_data); const gchar *from; gchar *normalized = NULL; gboolean ret = FALSE; WockyStanzaSubType subtype; wocky_stanza_get_type_info (stanza, NULL, &subtype); switch (subtype) { case WOCKY_STANZA_SUB_TYPE_SUBSCRIBED: /* Someone has allowed us to subscribe to them */ break; case WOCKY_STANZA_SUB_TYPE_SUBSCRIBE: /* Someone wants to subscribe to us */ break; default: g_return_val_if_reached (FALSE); } from = wocky_node_get_attribute ( wocky_stanza_get_top_node (stanza), "from"); if (from == NULL || strchr (from, '@') != NULL || strchr (from, '/') != NULL) goto finally; normalized = wocky_normalise_jid (from); if (g_hash_table_lookup (self->priv->gateways, normalized) == NULL) goto finally; if (subtype == WOCKY_STANZA_SUB_TYPE_SUBSCRIBE) { WockyStanza *reply; /* It's a gateway we've registered with during this session, and they * want to subscribe to us. OK, let them. */ DEBUG ("Allowing gateway '%s' to subscribe to us", normalized); reply = wocky_stanza_build (WOCKY_STANZA_TYPE_PRESENCE, WOCKY_STANZA_SUB_TYPE_SUBSCRIBED, NULL, normalized, NULL); wocky_porter_send (porter, reply); g_object_unref (reply); } else { /* It's a gateway we've registered with during this session, letting us * know that yes, we may subscribe to them. Good. */ DEBUG ("Gateway '%s' allowed us to subscribe to it", normalized); /* Eventually, we'll return success from the D-Bus method call here. */ } ret = TRUE; finally: g_free (normalized); return ret; } static void gabble_gateway_sidecar_constructed (GObject *object) { void (*chain_up) (GObject *) = G_OBJECT_CLASS (gabble_gateway_sidecar_parent_class)->constructed; GabbleGatewaySidecar *self = GABBLE_GATEWAY_SIDECAR (object); WockyPorter *porter; if (chain_up != NULL) chain_up (object); g_assert (self->priv->session != NULL); g_assert (self->priv->connection != NULL); porter = wocky_session_get_porter (self->priv->session); self->priv->subscribe_id = wocky_porter_register_handler_from_anyone (porter, WOCKY_STANZA_TYPE_PRESENCE, WOCKY_STANZA_SUB_TYPE_SUBSCRIBE, WOCKY_PORTER_HANDLER_PRIORITY_MAX, presence_cb, self, NULL); self->priv->subscribed_id = wocky_porter_register_handler_from_anyone (porter, WOCKY_STANZA_TYPE_PRESENCE, WOCKY_STANZA_SUB_TYPE_SUBSCRIBED, WOCKY_PORTER_HANDLER_PRIORITY_MAX, presence_cb, self, NULL); } static void gabble_gateway_sidecar_class_init (GabbleGatewaySidecarClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = gabble_gateway_sidecar_set_property; object_class->dispose = gabble_gateway_sidecar_dispose; object_class->constructed = gabble_gateway_sidecar_constructed; g_type_class_add_private (klass, sizeof (GabbleGatewaySidecarPrivate)); g_object_class_install_property (object_class, PROP_CONNECTION, g_param_spec_object ("connection", "Connection", "Gabble connection", GABBLE_TYPE_PLUGIN_CONNECTION, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_SESSION, g_param_spec_object ("session", "Session", "Wocky session", WOCKY_TYPE_SESSION, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); } static void sidecar_iface_init ( gpointer g_iface, gpointer data) { GabbleSidecarInterface *iface = g_iface; iface->interface = GABBLE_IFACE_GABBLE_PLUGIN_GATEWAYS; iface->get_immutable_properties = NULL; } typedef struct { DBusGMethodInvocation *context; gchar *gateway; } PendingRegistration; static PendingRegistration * pending_registration_new (DBusGMethodInvocation *context, const gchar *gateway) { PendingRegistration *pr = g_slice_new (PendingRegistration); pr->context = context; pr->gateway = g_strdup (gateway); return pr; } static void pending_registration_free (PendingRegistration *pr) { g_assert (pr->context == NULL); g_free (pr->gateway); g_slice_free (PendingRegistration, pr); } #define NON_NULL (((int *) NULL) + 1) static void register_cb (GObject *source, GAsyncResult *result, gpointer user_data) { WockyPorter *porter = WOCKY_PORTER (source); PendingRegistration *pr = user_data; WockyStanza *reply; GError *error = NULL; reply = wocky_porter_send_iq_finish (porter, result, &error); if (reply == NULL || wocky_stanza_extract_errors (reply, NULL, &error, NULL, NULL)) { GError *tp_error = NULL; /* specific error cases for registration: 'conflict' and * 'not-acceptable' are documented */ if (error->domain == WOCKY_XMPP_ERROR) { switch (error->code) { case WOCKY_XMPP_ERROR_CONFLICT: g_set_error (&tp_error, TP_ERROR, TP_ERROR_REGISTRATION_EXISTS, "someone else registered that username: %s", error->message); break; case WOCKY_XMPP_ERROR_NOT_ACCEPTABLE: g_set_error (&tp_error, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "registration not acceptable: %s", error->message); break; default: gabble_set_tp_error_from_wocky (error, &tp_error); break; } } else { /* generic fallback */ gabble_set_tp_error_from_wocky (error, &tp_error); } DEBUG ("Failed to register with '%s': %s", pr->gateway, tp_error->message); dbus_g_method_return_error (pr->context, tp_error); pr->context = NULL; g_error_free (error); g_error_free (tp_error); } else { WockyStanza *request; DEBUG ("Registered with '%s', exchanging presence...", pr->gateway); /* attempt to subscribe to the gateway's presence (FIXME: is this * harmless if we're already subscribed to it?) */ request = wocky_stanza_build (WOCKY_STANZA_TYPE_PRESENCE, WOCKY_STANZA_SUB_TYPE_SUBSCRIBE, NULL, pr->gateway, NULL); wocky_porter_send (porter, request); g_object_unref (request); gabble_svc_gabble_plugin_gateways_return_from_register (pr->context); pr->context = NULL; } tp_clear_object (&reply); pending_registration_free (pr); } static void gateways_register ( GabbleSvcGabblePluginGateways *sidecar, const gchar *gateway, const gchar *username, const gchar *password, DBusGMethodInvocation *context) { GabbleGatewaySidecar *self = GABBLE_GATEWAY_SIDECAR (sidecar); WockyPorter *porter = wocky_session_get_porter (self->priv->session); WockyStanza *stanza; gchar *normalized_gateway; GError *error = NULL; if (strchr (gateway, '@') != NULL) { g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Gateway names cannot contain '@': %s", gateway); goto error; } if (strchr (gateway, '/') != NULL) { g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Gateway names cannot contain '/': %s", gateway); goto error; } if (!wocky_decode_jid (gateway, NULL, &normalized_gateway, NULL)) { g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Invalid gateway name: %s", gateway); goto error; } DEBUG ("Trying to register on '%s' as '%s'", gateway, username); /* steals ownership of normalized_gateway */ g_hash_table_replace (self->priv->gateways, normalized_gateway, NON_NULL); /* This is a *really* minimal implementation. We're meant to ask the gateway * what parameters it supports (a XEP-0077 pseudo-form or a XEP-0004 data * form), then fill in the blanks to actually make a request. * * However, because we're hard-coded to take only a username and a password, * we might as well just fire off a request with those in and see if it * works. If it doesn't, then we couldn't have registered anyway... * * A more general API for service registration could look like this: * * method Plugin.GetService() -> o, a{s(*)} [where * is some * representation of the type of the parameter] * property Service.Parameters: readable a{s(*)} [likewise] * property Service.Registered: readable b * method Service.Register(a{sv}) * method Service.Unregister() * method Service.Release() [distributed refcounting] */ stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_SET, NULL, normalized_gateway, '(', "query", ':', WOCKY_XEP77_NS_REGISTER, '(', "username", '$', username, ')', '(', "password", '$', password, ')', ')', NULL); wocky_porter_send_iq_async (porter, stanza, NULL, register_cb, pending_registration_new (context, normalized_gateway)); g_object_unref (stanza); return; error: DEBUG ("%s", error->message); dbus_g_method_return_error (context, error); g_error_free (error); } static void gateway_iface_init ( gpointer klass, gpointer data G_GNUC_UNUSED) { #define IMPLEMENT(x) gabble_svc_gabble_plugin_gateways_implement_##x (\ klass, gateways_##x) IMPLEMENT (register); #undef IMPLEMENT } telepathy-gabble-0.18.3/plugins/telepathy-gabble-xmpp-console0000775000175000017500000003321412332441362025443 0ustar00cassidycassidy00000000000000#!/usr/bin/env python # vim: set fileencoding=utf-8 sts=4 sw=4 et : """ The world's worst XMPP console user interface. Pass it the bus name of a Gabble connection; type some words; get minimalistic error reporting. Copyright © 2011 Collabora Ltd. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """ import sys import re from xml.dom import minidom from gi.repository import Gtk from gi.repository import GLib from gi.repository import Gio from gi.repository import GtkSource PADDING = 6 def pathify(name): return '/' + name.replace('.', '/') def nameify(path): return (path[1:]).replace('/', '.') CONN_FUTURE_IFACE = "org.freedesktop.Telepathy.Connection.FUTURE" CONSOLE_IFACE = "org.freedesktop.Telepathy.Gabble.Plugin.Console" class StanzaViewer(Gtk.ScrolledWindow): def __init__(self): Gtk.ScrolledWindow.__init__(self) self.b = GtkSource.Buffer() self.view = GtkSource.View.new_with_buffer(self.b) self.b.set_language( GtkSource.LanguageManager.get_default().get_language('xml')) self.b.set_highlight_matching_brackets(False) self.view.set_editable(False) self.view.set_wrap_mode(Gtk.WrapMode.WORD_CHAR) self.view.set_property('expand', True) self.add(self.view) def clear(self): self.b.set_text("") def append_stanza(self, xml): pretty = minidom.parseString(xml).toprettyxml() pretty = pretty.replace('\n', '') i = self.b.get_end_iter() self.b.insert(i, pretty + '\n') def append_comment(self, text): i = self.b.get_end_iter() self.b.insert(i, '\n' % text) def tell_me_everything(self): return self.b.get_property('text') class SpinWrapper(Gtk.Notebook): PRIMARY_PAGE = 0 SPINNER_PAGE = 1 def __init__(self, main_widget): Gtk.Notebook.__init__(self) self.set_show_tabs(False) self.set_show_border(False) self.insert_page(main_widget, None, self.PRIMARY_PAGE) self.spinner = Gtk.Spinner() self.spinner.set_property('halign', Gtk.Align.CENTER) self.spinner.set_property('valign', Gtk.Align.CENTER) self.spinner.set_property('width-request', 32) self.spinner.set_property('height-request', 32) self.insert_page(self.spinner, None, self.SPINNER_PAGE) def start_spinning(self): self.set_current_page(self.SPINNER_PAGE) self.spinner.start() def stop_spinning(self): self.spinner.stop() self.set_current_page(self.PRIMARY_PAGE) class Page(Gtk.Grid): def __init__(self, console_proxy): Gtk.Grid.__init__(self) self.console_proxy = console_proxy self.set_column_spacing(PADDING) self.set_row_spacing(PADDING) def add_title(self, title, below=None): label = Gtk.Label() label.set_markup("%s" % title) label.set_property('xalign', 0) if below is None: self.attach(label, 0, 0, 2, 1) else: self.attach_next_to(label, below, Gtk.PositionType.BOTTOM, 2, 1) return label def add_label(self, title, below=None): label = Gtk.Label(title) label.set_property('margin-left', PADDING) label.set_property('xalign', 0) if below is None: self.attach(label, 0, 0, 1, 1) else: self.attach_next_to(label, below, Gtk.PositionType.BOTTOM, 1, 1) return label class IQPage(Page): def __init__(self, console_proxy): Page.__init__(self, console_proxy) request_label = self.add_title("Request") recipient_label, recipient_entry = self.add_label_entry_pair( 'To:', below=request_label) self.recipient_entry = recipient_entry type_label = self.add_label('IQ Type:', below=recipient_label) self.get_button = Gtk.RadioButton.new_with_label([], "get") self.get_button.set_active(True) self.set_button = Gtk.RadioButton.new_with_label_from_widget( self.get_button, "set") box = Gtk.ButtonBox.new(Gtk.Orientation.HORIZONTAL) box.set_layout(Gtk.ButtonBoxStyle.START) box.add(self.get_button) box.add(self.set_button) self.attach_next_to(box, type_label, Gtk.PositionType.RIGHT, 1, 1) body_label, body_entry = self.add_label_entry_pair( 'Body:', below=type_label) body_entry.set_text( "") body_entry.set_icon_from_stock( Gtk.EntryIconPosition.SECONDARY, Gtk.STOCK_GO_FORWARD) body_entry.set_icon_tooltip_text( Gtk.EntryIconPosition.SECONDARY, "Send this IQ") self.body_entry = body_entry reply_label = self.add_title("Reply", below=body_label) self.stanza_viewer = StanzaViewer() self.stanza_viewer.append_comment("send a request to see the reply here") self.result_nb = SpinWrapper(self.stanza_viewer) self.attach_next_to(self.result_nb, reply_label, Gtk.PositionType.BOTTOM, 2, 1) body_entry.connect('activate', self.send_iq) body_entry.connect('icon-release', self.send_iq) def add_label_entry_pair(self, title, below): label = self.add_label(title, below) entry = Gtk.Entry() entry.set_property('margin-right', PADDING) entry.set_property('hexpand', True) self.attach_next_to(entry, label, Gtk.PositionType.RIGHT, 1, 1) return label, entry def send_iq(self, *misc): type = 'get' if self.get_button.get_active() else 'set' to = self.recipient_entry.get_text() body = self.body_entry.get_text() self.console_proxy.SendIQ('(sss)', type, to, body, result_handler=self.send_iq_cb) self.result_nb.start_spinning() def send_iq_cb(self, proxy, result, user_data): self.stanza_viewer.clear() if isinstance(result, Exception): self.stanza_viewer.append_comment("error:\n%s" % result) else: reply_type, reply = result self.stanza_viewer.append_stanza(reply) self.result_nb.stop_spinning() class StanzaPage(Page): def __init__(self, console_proxy): Page.__init__(self, console_proxy) title = self.add_title("Enter a complete stanza:") self.sv = StanzaViewer() self.sv.view.set_editable(True) self.sv.append_stanza("Been on any nice boats recently?") self.spin_wrapper = SpinWrapper(self.sv) self.attach_next_to(self.spin_wrapper, title, Gtk.PositionType.BOTTOM, 2, 1) self.result_label = self.add_label('', self.spin_wrapper) self.result_label.set_property('hexpand', True) self.result_label.set_line_wrap(True) b = Gtk.Button.new_with_mnemonic("_Send") b.connect('clicked', self.__send_stanza) b.set_property('hexpand', False) self.attach_next_to(b, self.result_label, Gtk.PositionType.RIGHT, 1, 1) def __send_stanza(self, button): self.console_proxy.SendStanza('(s)', self.sv.tell_me_everything(), result_handler=self.__send_stanza_cb) self.spin_wrapper.start_spinning() def __send_stanza_cb(self, proxy, result, user_data): if isinstance(result, Exception): # FIXME: this sucks. You can't just get the free text bit without # the D-Bus error bit. t = result.message else: t = "yes sir, captain tightpants" self.result_label.set_text(t) self.spin_wrapper.stop_spinning() class SnoopyPage(Page): def __init__(self, console_proxy): Page.__init__(self, console_proxy) label = self.add_label("Stanza monitor:") label.set_property('hexpand', True) switch = Gtk.Switch() self.attach_next_to(switch, label, Gtk.PositionType.RIGHT, 1, 1) self.stanza_viewer = StanzaViewer() self.attach_next_to(self.stanza_viewer, label, Gtk.PositionType.BOTTOM, 2, 1) switch.set_active(self.get_remote_active()) switch.connect('notify::active', self.__switch_switched_cb) self.console_proxy.connect('g-signal', self.__g_signal_cb) def teardown(self): """Turn off the monitor when we quit.""" self.__set_spew(False) def __set_spew(self, spew): args = GLib.Variant("(ssv)", (CONSOLE_IFACE, "SpewStanzas", GLib.Variant.new_boolean(spew))) self.console_proxy.call_sync( "org.freedesktop.DBus.Properties.Set", args, 0, -1, None) def get_remote_active(self): return self.console_proxy.get_cached_property('SpewStanzas').get_boolean() def __switch_switched_cb(self, switch, pspec): remote = self.get_remote_active() new_local = switch.get_active() if new_local != remote: self.__set_spew(new_local) self.stanza_viewer.append_comment( 'started monitoring' if new_local else 'stopped monitoring') def __g_signal_cb(self, console_proxy, sender_name, signal_name, parameters): if signal_name in ['StanzaSent', 'StanzaReceived']: outgoing = (signal_name == 'StanzaSent') xml, = parameters self.stanza_viewer.append_comment('sent' if outgoing else 'received') self.stanza_viewer.append_stanza(xml) class Window(Gtk.Window): IQ_PAGE = 0 STANZA_PAGE = 1 SNOOPY_PAGE = 2 def __init__(self, bus, connection_bus_name): Gtk.Window.__init__(self) self.set_title('XMPP Console') self.set_default_size(600, 371) conn_future_proxy = Gio.DBusProxy.new_sync(bus, 0, None, connection_bus_name, pathify(connection_bus_name), CONN_FUTURE_IFACE, None) try: sidecar_path, _ = conn_future_proxy.EnsureSidecar('(s)', CONSOLE_IFACE) except Exception, e: print """ Couldn't connect to the XMPP console interface on '%(connection_bus_name)s': %(e)s Check that it's a running Jabber connection, and that you have the console plugin installed.""" % locals() raise SystemExit(2) self.console_proxy = Gio.DBusProxy.new_sync(bus, 0, None, connection_bus_name, sidecar_path, CONSOLE_IFACE, None) # Build up the UI self.nb = Gtk.Notebook() self.add(self.nb) self.iq = IQPage(self.console_proxy) self.nb.insert_page(self.iq, Gtk.Label.new_with_mnemonic("_IQ console"), self.IQ_PAGE) self.stanza = StanzaPage(self.console_proxy) self.nb.insert_page(self.stanza, Gtk.Label.new_with_mnemonic("Send a s_tanza"), self.STANZA_PAGE) self.snoopy = SnoopyPage(self.console_proxy) self.nb.insert_page(self.snoopy, Gtk.Label.new_with_mnemonic("_Monitor network traffic"), self.SNOOPY_PAGE) self.connect('destroy', Window.__destroy_cb) def __destroy_cb(self): self.snoopy.teardown() Gtk.main_quit() GABBLE_PREFIX = 'org.freedesktop.Telepathy.Connection.gabble.jabber.' AM_BUS_NAME = 'org.freedesktop.Telepathy.AccountManager' ACCOUNT_PREFIX = '/org/freedesktop/Telepathy/Account' ACCOUNT_IFACE = 'org.freedesktop.Telepathy.Account' def usage(): print """ Usage: %(arg0)s gabble/jabber/blahblah %(arg0)s %(prefix)sblahblah List account identifiers using `mc-tool list | grep gabble`. List connection bus names using `qdbus | grep gabble`. """ % { 'arg0': sys.argv[0], 'prefix': GABBLE_PREFIX, } raise SystemExit(1) if __name__ == '__main__': bus = Gio.bus_get_sync(Gio.BusType.SESSION, None) if len(sys.argv) != 2: usage() thing = sys.argv[1] if re.match('^gabble/jabber/[a-zA-Z0-9_]+$', thing): # Looks like an account path to me. account_proxy = Gio.DBusProxy.new_sync(bus, 0, None, AM_BUS_NAME, '%s/%s' % (ACCOUNT_PREFIX, thing), ACCOUNT_IFACE, None) path = account_proxy.get_cached_property('Connection').get_string() if path == '/': print "%s is not online" % thing raise SystemExit(1) else: thing = nameify(path) if not re.match('^%s[a-zA-Z0-9_]+$' % GABBLE_PREFIX, thing): usage() win = Window(bus, thing) win.show_all() Gtk.main() """ .,,. ,;;*;;;;, .-'``;-');;. /' .-. /*;; .' \d \;; .;;;, / o ` \; ,__. ,;*;;;*;, \__, _.__,' \_.-') __)--.;;;;;*;;;;, `""`;;;\ /-')_) __) `\' ';;;;;; ;*;;; -') `)_) |\ | ;;;;*; ;;;;| `---` O | | ;;*;;; *;*;\| O / ;;;;;* ;;;;;/| .-------\ / ;*;;;;; ;;;*;/ \ | '. (`. ;;;*;;; ;;;;;'. ; | ) \ | ;;;;;; ,;*;;;;\/ |. / /` | ';;;*; ;;;;;;/ |/ / /__/ ';;; '*jgs/ | / | ;*; `""""` `""""` ;' """ telepathy-gabble-0.18.3/plugins/gateways.h0000664000175000017500000000637411720700311021656 0ustar00cassidycassidy00000000000000/* Gateway registration plugin * * Copyright © 2010 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include typedef struct _GabbleGatewayPlugin GabbleGatewayPlugin; typedef struct _GabbleGatewayPluginClass GabbleGatewayPluginClass; typedef struct _GabbleGatewayPluginPrivate GabbleGatewayPluginPrivate; struct _GabbleGatewayPlugin { GObject parent; GabbleGatewayPluginPrivate *priv; }; struct _GabbleGatewayPluginClass { GObjectClass parent; }; GType gabble_gateway_plugin_get_type (void); #define GABBLE_TYPE_GATEWAY_PLUGIN \ (gabble_gateway_plugin_get_type ()) #define GABBLE_GATEWAY_PLUGIN(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GABBLE_TYPE_GATEWAY_PLUGIN, \ GabbleGatewayPlugin)) #define GABBLE_GATEWAY_PLUGIN_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), GABBLE_TYPE_GATEWAY_PLUGIN, \ GabbleGatewayPluginClass)) #define GABBLE_IS_GATEWAY_PLUGIN(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GABBLE_TYPE_GATEWAY_PLUGIN)) #define GABBLE_IS_GATEWAY_PLUGIN_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), GABBLE_TYPE_GATEWAY_PLUGIN)) #define GABBLE_GATEWAY_PLUGIN_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_GATEWAY_PLUGIN, \ GabbleGatewayPluginClass)) typedef struct _GabbleGatewaySidecar GabbleGatewaySidecar; typedef struct _GabbleGatewaySidecarClass GabbleGatewaySidecarClass; typedef struct _GabbleGatewaySidecarPrivate GabbleGatewaySidecarPrivate; struct _GabbleGatewaySidecar { GObject parent; GabbleGatewaySidecarPrivate *priv; }; struct _GabbleGatewaySidecarClass { GObjectClass parent; }; GType gabble_gateway_sidecar_get_type (void); #define GABBLE_TYPE_GATEWAY_SIDECAR \ (gabble_gateway_sidecar_get_type ()) #define GABBLE_GATEWAY_SIDECAR(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GABBLE_TYPE_GATEWAY_SIDECAR, \ GabbleGatewaySidecar)) #define GABBLE_GATEWAY_SIDECAR_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), GABBLE_TYPE_GATEWAY_SIDECAR, \ GabbleGatewaySidecarClass)) #define GABBLE_IS_GATEWAY_SIDECAR(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GABBLE_TYPE_GATEWAY_SIDECAR)) #define GABBLE_IS_GATEWAY_SIDECAR_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), GABBLE_TYPE_GATEWAY_SIDECAR)) #define GABBLE_GATEWAY_SIDECAR_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_GATEWAY_SIDECAR, \ GabbleGatewaySidecarClass)) telepathy-gabble-0.18.3/plugins/test.c0000664000175000017500000004503612332441362021012 0ustar00cassidycassidy00000000000000#include "config.h" #include "test.h" #include #include #include #include "extensions/extensions.h" #include #include #define DEBUG(msg, ...) \ g_debug ("%s: " msg, G_STRFUNC, ##__VA_ARGS__) /***************************** * TestPlugin implementation * *****************************/ static void plugin_iface_init ( gpointer g_iface, gpointer data); #define IFACE_TEST "org.freedesktop.Telepathy.Gabble.Plugin.Test" #define IFACE_TEST_PROPS IFACE_TEST ".Props" #define IFACE_TEST_BUGGY IFACE_TEST ".Buggy" #define IFACE_TEST_IQ IFACE_TEST ".IQ" static const gchar * const sidecar_interfaces[] = { IFACE_TEST, IFACE_TEST_PROPS, IFACE_TEST_BUGGY, IFACE_TEST_IQ, NULL }; G_DEFINE_TYPE_WITH_CODE (TestPlugin, test_plugin, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GABBLE_TYPE_PLUGIN, plugin_iface_init); ) static void test_plugin_init (TestPlugin *object) { DEBUG ("%p", object); } static void test_plugin_class_init (TestPluginClass *klass) { } static void sidecar_iq_created_cb ( GObject *source, GAsyncResult *new_result, gpointer user_data) { GSimpleAsyncResult *result = user_data; GabbleSidecar *sidecar = GABBLE_SIDECAR (source); GError *error = NULL; if (g_async_initable_init_finish (G_ASYNC_INITABLE (source), new_result, &error)) { g_simple_async_result_set_op_res_gpointer (result, sidecar, g_object_unref); } else { g_simple_async_result_set_from_error (result, error); g_clear_error (&error); g_object_unref (sidecar); } g_simple_async_result_complete (result); g_object_unref (result); } static void test_plugin_create_sidecar_async ( GabblePlugin *plugin, const gchar *sidecar_interface, GabblePluginConnection *plugin_connection, WockySession *session, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (plugin), callback, user_data, test_plugin_create_sidecar_async); GabbleSidecar *sidecar = NULL; if (!tp_strdiff (sidecar_interface, IFACE_TEST)) { sidecar = g_object_new (TEST_TYPE_SIDECAR, NULL); } else if (!tp_strdiff (sidecar_interface, IFACE_TEST_PROPS)) { sidecar = g_object_new (TEST_TYPE_SIDECAR_PROPS, NULL); } else if (!tp_strdiff (sidecar_interface, IFACE_TEST_IQ)) { g_async_initable_new_async (TEST_TYPE_SIDECAR_IQ, G_PRIORITY_DEFAULT, NULL, sidecar_iq_created_cb, result, "session", session, "plugin-connection", plugin_connection, NULL); return; } else { /* This deliberately doesn't check for IFACE_TEST_BUGGY, to test Gabble's * reactions to buggy plugins. :) */ g_simple_async_result_set_error (result, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED, "'%s' not implemented", sidecar_interface); } if (sidecar != NULL) g_simple_async_result_set_op_res_gpointer (result, sidecar, g_object_unref); g_simple_async_result_complete_in_idle (result); g_object_unref (result); } static GabbleSidecar * test_plugin_create_sidecar_finish ( GabblePlugin *plugin, GAsyncResult *result, GError **error) { GabbleSidecar *sidecar; if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) return NULL; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (plugin), test_plugin_create_sidecar_async), NULL); sidecar = GABBLE_SIDECAR (g_simple_async_result_get_op_res_gpointer ( G_SIMPLE_ASYNC_RESULT (result))); return g_object_ref (sidecar); } static GPtrArray * test_plugin_create_channel_managers (GabblePlugin *plugin, GabblePluginConnection *plugin_connection) { GPtrArray *ret = g_ptr_array_new (); DEBUG ("plugin %p on connection %p", plugin, plugin_connection); g_ptr_array_add (ret, g_object_new (TEST_TYPE_CHANNEL_MANAGER, "plugin-connection", plugin_connection, NULL)); return ret; } static TpPresenceStatusSpec test_presences[] = { { "testbusy", TP_CONNECTION_PRESENCE_TYPE_BUSY, TRUE, NULL, NULL, NULL }, { "testaway", TP_CONNECTION_PRESENCE_TYPE_AWAY, FALSE, NULL, NULL, NULL }, { NULL, 0, FALSE, NULL, NULL, NULL } }; static GabblePluginPrivacyListMap privacy_list_map[] = { { "testbusy", "test-busy-list" }, { NULL, NULL }, }; static void plugin_iface_init ( gpointer g_iface, gpointer data G_GNUC_UNUSED) { GabblePluginInterface *iface = g_iface; iface->name = "Sidecar test plugin"; iface->version = PACKAGE_VERSION; iface->sidecar_interfaces = sidecar_interfaces; iface->create_sidecar_async = test_plugin_create_sidecar_async; iface->create_sidecar_finish = test_plugin_create_sidecar_finish; iface->create_channel_managers = test_plugin_create_channel_managers; iface->presence_statuses = test_presences; iface->privacy_list_map = privacy_list_map; } GabblePlugin * gabble_plugin_create () { return g_object_new (test_plugin_get_type (), NULL); } /****************************** * TestSidecar implementation * ******************************/ static void sidecar_iface_init ( gpointer g_iface, gpointer data); G_DEFINE_TYPE_WITH_CODE (TestSidecar, test_sidecar, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SIDECAR, sidecar_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_GABBLE_PLUGIN_TEST, NULL); ) static void test_sidecar_init (TestSidecar *object) { DEBUG ("%p", object); } static void test_sidecar_class_init (TestSidecarClass *klass) { } static void sidecar_iface_init ( gpointer g_iface, gpointer data) { GabbleSidecarInterface *iface = g_iface; iface->interface = IFACE_TEST; iface->get_immutable_properties = NULL; } /*********************************** * TestSidecarProps implementation * ***********************************/ static void sidecar_props_iface_init ( gpointer g_iface, gpointer data); G_DEFINE_TYPE_WITH_CODE (TestSidecarProps, test_sidecar_props, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SIDECAR, sidecar_props_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_GABBLE_PLUGIN_TEST, NULL); ) static void test_sidecar_props_init (TestSidecarProps *object) { DEBUG ("%p", object); object->props = tp_asv_new ( IFACE_TEST_PROPS ".Greeting", G_TYPE_STRING, "oh hai", NULL); } static void test_sidecar_props_finalize (GObject *object) { TestSidecarProps *self = TEST_SIDECAR_PROPS (object); void (*chain_up) (GObject *) = G_OBJECT_CLASS (test_sidecar_props_parent_class)->finalize; g_hash_table_unref (self->props); if (chain_up != NULL) chain_up (object); } static void test_sidecar_props_class_init (TestSidecarPropsClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = test_sidecar_props_finalize; } static GHashTable * sidecar_props_get_immutable_properties (GabbleSidecar *sidecar) { TestSidecarProps *self = TEST_SIDECAR_PROPS (sidecar); return g_hash_table_ref (self->props); } static void sidecar_props_iface_init ( gpointer g_iface, gpointer data) { GabbleSidecarInterface *iface = g_iface; iface->interface = IFACE_TEST_PROPS; iface->get_immutable_properties = sidecar_props_get_immutable_properties; } /******************************** * TestSidecarIQ implementation * ********************************/ static void sidecar_iq_iface_init ( gpointer g_iface, gpointer data); static void async_initable_iface_init ( gpointer g_iface, gpointer data); G_DEFINE_TYPE_WITH_CODE (TestSidecarIQ, test_sidecar_iq, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SIDECAR, sidecar_iq_iface_init); G_IMPLEMENT_INTERFACE (GABBLE_TYPE_SVC_GABBLE_PLUGIN_TEST, NULL); G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init); ) enum { PROP_SESSION = 1, PROP_CONNECTION = 2 }; static void test_sidecar_iq_init (TestSidecarIQ *object) { DEBUG ("%p", object); } static void test_sidecar_iq_set_property ( GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { TestSidecarIQ *self = TEST_SIDECAR_IQ (object); switch (property_id) { case PROP_SESSION: self->session = g_value_dup_object (value); break; case PROP_CONNECTION: { self->connection = g_value_dup_object (value); if (self->connection) { GabbleCapabilitySet *features; const gchar *applications[] = { "com.example.test1", "com.example.test2", NULL }; GPtrArray *identities; WockyDiscoIdentity *identity; gchar *hash; guint i; features = gabble_capability_set_new (); for (i = 0; applications[i] != NULL; i++) gabble_capability_set_add (features, applications[i]); identities = wocky_disco_identity_array_new (); identity = wocky_disco_identity_new ("test", "app-list", NULL, "Test"); g_ptr_array_add (identities, identity); /* set own caps so we proper reply to disco#info */ hash = gabble_plugin_connection_add_sidecar_own_caps (self->connection, features, identities); g_free (hash); wocky_disco_identity_array_free (identities); gabble_capability_set_free (features); } } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); } } static void test_sidecar_iq_dispose (GObject *object) { TestSidecarIQ *self = TEST_SIDECAR_IQ (object); DEBUG ("called for %p", object); tp_clear_object (&self->session); tp_clear_object (&self->connection); } static void test_sidecar_iq_class_init (TestSidecarIQClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = test_sidecar_iq_set_property; object_class->dispose = test_sidecar_iq_dispose; g_object_class_install_property (object_class, PROP_SESSION, g_param_spec_object ("session", "SESSION", "THIS IS A WOCKY SESSION YOU CAN TELL BY THE TYPE", WOCKY_TYPE_SESSION, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_CONNECTION, g_param_spec_object ("plugin-connection", "Gabble Plugin Connection", "Gabble Plugin Connection", GABBLE_TYPE_PLUGIN_CONNECTION, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); } static void sidecar_iq_iface_init ( gpointer g_iface, gpointer data) { GabbleSidecarInterface *iface = g_iface; iface->interface = IFACE_TEST_IQ; iface->get_immutable_properties = NULL; } static void iq_cb ( GObject *source, GAsyncResult *nested_result, gpointer user_data) { GSimpleAsyncResult *result = user_data; GError *error = NULL; WockyStanza *reply; reply = wocky_porter_send_iq_finish (WOCKY_PORTER (source), nested_result, &error); if (reply == NULL) { g_simple_async_result_set_from_error (result, error); g_clear_error (&error); } else { WockyStanzaSubType t; wocky_stanza_get_type_info (reply, NULL, &t); if (t == WOCKY_STANZA_SUB_TYPE_RESULT) g_simple_async_result_set_op_res_gboolean (result, TRUE); else g_simple_async_result_set_error (result, TP_ERROR, TP_ERROR_NOT_AVAILABLE, "server said no!"); g_object_unref (reply); } g_simple_async_result_complete (result); } static void sidecar_iq_init_async ( GAsyncInitable *initable, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { TestSidecarIQ *self = TEST_SIDECAR_IQ (initable); GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, sidecar_iq_init_async); WockyPorter *porter = wocky_session_get_porter (self->session); WockyStanza *iq; iq = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, "sidecar.example.com", '(', "query", ':', "http://example.com/sidecar", '(', "oh-hai", ')', ')', NULL); wocky_porter_send_iq_async (porter, iq, cancellable, iq_cb, result); } static gboolean sidecar_iq_init_finish ( GAsyncInitable *initable, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); if (g_simple_async_result_propagate_error (simple, error)) return FALSE; g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (initable), sidecar_iq_init_async), FALSE); return g_simple_async_result_get_op_res_gboolean (simple); } static void async_initable_iface_init ( gpointer g_iface, gpointer data) { GAsyncInitableIface *iface = g_iface; iface->init_async = sidecar_iq_init_async; iface->init_finish = sidecar_iq_init_finish; } /*********************************** * TestChannelManager implementation * ***********************************/ static void channel_manager_iface_init (gpointer, gpointer); static void caps_channel_manager_iface_init (gpointer g_iface, gpointer iface_data); G_DEFINE_TYPE_WITH_CODE (TestChannelManager, test_channel_manager, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER, channel_manager_iface_init) G_IMPLEMENT_INTERFACE (GABBLE_TYPE_CAPS_CHANNEL_MANAGER, caps_channel_manager_iface_init)); static void test_channel_manager_init (TestChannelManager *self) { } static void test_channel_manager_set_property ( GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { TestChannelManager *self = TEST_CHANNEL_MANAGER (object); switch (property_id) { case PROP_CONNECTION: /* Not reffing this: the connection owns all channel managers, so it * must outlive us. Taking a reference leads to a cycle. */ self->plugin_connection = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void test_channel_manager_get_property ( GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { TestChannelManager *self = TEST_CHANNEL_MANAGER (object); switch (property_id) { case PROP_CONNECTION: g_value_set_object (value, self->plugin_connection); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void test_channel_manager_porter_available_cb (GabbleConnection *connection, WockyPorter *porter, gpointer user_data) { DEBUG ("now we have a porter: %p", porter); /* so now we can call things like wocky_porter_register_handler_* * and get some stanzas. */ } static void test_channel_manager_constructed (GObject *object) { TestChannelManager *self = TEST_CHANNEL_MANAGER (object); if (G_OBJECT_CLASS (test_channel_manager_parent_class)->constructed != NULL) G_OBJECT_CLASS (test_channel_manager_parent_class)->constructed (object); tp_g_signal_connect_object (self->plugin_connection, "porter-available", G_CALLBACK (test_channel_manager_porter_available_cb), self, 0); } static void test_channel_manager_class_init (TestChannelManagerClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); oclass->set_property = test_channel_manager_set_property; oclass->get_property = test_channel_manager_get_property; oclass->constructed = test_channel_manager_constructed; g_object_class_install_property (oclass, PROP_CONNECTION, g_param_spec_object ("plugin-connection", "Gabble Plugin Connection", "Gabble Plugin Connection", GABBLE_TYPE_PLUGIN_CONNECTION, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); } static void test_channel_manager_type_foreach_channel_class (GType type, TpChannelManagerTypeChannelClassFunc func, gpointer user_data) { GHashTable *table = tp_asv_new ( TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING, "com.jonnylamb.lolbags", TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT, TP_HANDLE_TYPE_NONE, NULL); const gchar * const chock_a_block_full_of_strings[] = { "com.jonnylamb.omg", "com.jonnylamb.brokethebuild", NULL }; func (type, table, chock_a_block_full_of_strings, user_data); g_hash_table_unref (table); } static void test_channel_manager_represent_client ( GabbleCapsChannelManager *manager, const gchar *client_name, const GPtrArray *filters, const gchar * const *cap_tokens, GabbleCapabilitySet *cap_set, GPtrArray *data_forms) { WockyStanza *stanza; WockyDataForm *form; if (tp_strdiff (client_name, "dataformtest")) return; stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_NONE, NULL, "badger", '(', "x", ':', "jabber:x:data", '@', "type", "result", '(', "field", '@', "var", "FORM_TYPE", '@', "type", "hidden", '(', "value", '$', "gabble:test:channel:manager:data:form", ')', ')', '(', "field", '@', "var", "animal", '(', "value", '$', "badger", ')', '(', "value", '$', "snake", ')', '(', "value", '$', "weasel", ')', ')', '(', "field", '@', "var", "cheese", '(', "value", '$', "omgnothorriblecheese", ')', ')', '(', "field", '@', "var", "favourite_crane", '(', "value", '$', "a tall one", ')', '(', "value", '$', "a short one", ')', ')', '(', "field", '@', "var", "running_out_of", '(', "value", '$', "ideas", ')', '(', "value", '$', "cake", ')', ')', ')', NULL); form = wocky_data_form_new_from_node ( wocky_node_get_first_child (wocky_stanza_get_top_node (stanza)), NULL); g_ptr_array_add (data_forms, form); g_object_unref (stanza); } static void channel_manager_iface_init (gpointer g_iface, gpointer iface_data) { TpChannelManagerIface *iface = g_iface; iface->type_foreach_channel_class = test_channel_manager_type_foreach_channel_class; /* not requestable. */ iface->ensure_channel = NULL; iface->create_channel = NULL; iface->request_channel = NULL; iface->foreach_channel_class = NULL; } static void caps_channel_manager_iface_init (gpointer g_iface, gpointer iface_data) { GabbleCapsChannelManagerInterface *iface = g_iface; iface->represent_client = test_channel_manager_represent_client; } telepathy-gabble-0.18.3/plugins/Makefile.in0000664000175000017500000007017412332443655021744 0ustar00cassidycassidy00000000000000# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ # we still compile the plugin (just to make sure it compiles!) but we don't # install it @ENABLE_PLUGINS_FALSE@am__append_1 = $(installable_plugins) subdir = plugins DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(am__dist_bin_SCRIPTS_DIST) $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_config_dir.m4 \ $(top_srcdir)/m4/compiler.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/tp-compiler-flag.m4 \ $(top_srcdir)/m4/tp-compiler-warnings.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libtestplugindir)" \ "$(DESTDIR)$(pluginexecdir)" "$(DESTDIR)$(bindir)" LTLIBRARIES = $(libtestplugin_LTLIBRARIES) $(noinst_LTLIBRARIES) \ $(pluginexec_LTLIBRARIES) am__DEPENDENCIES_1 = \ $(top_builddir)/extensions/libgabble-extensions.la \ $(top_builddir)/src/libgabble-plugins.la libconsole_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am_libconsole_la_OBJECTS = console.lo libconsole_la_OBJECTS = $(am_libconsole_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = @ENABLE_INSTALLED_TESTS_FALSE@@ENABLE_PLUGINS_FALSE@am_libconsole_la_rpath = @ENABLE_INSTALLED_TESTS_TRUE@@ENABLE_PLUGINS_FALSE@am_libconsole_la_rpath = @ENABLE_PLUGINS_TRUE@am_libconsole_la_rpath = -rpath $(pluginexecdir) libgateways_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am_libgateways_la_OBJECTS = gateways.lo libgateways_la_OBJECTS = $(am_libgateways_la_OBJECTS) @ENABLE_INSTALLED_TESTS_FALSE@@ENABLE_PLUGINS_FALSE@am_libgateways_la_rpath = @ENABLE_INSTALLED_TESTS_TRUE@@ENABLE_PLUGINS_FALSE@am_libgateways_la_rpath = @ENABLE_PLUGINS_TRUE@am_libgateways_la_rpath = -rpath $(pluginexecdir) libtest_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am_libtest_la_OBJECTS = test.lo libtest_la_OBJECTS = $(am_libtest_la_OBJECTS) libtest_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libtest_la_LDFLAGS) $(LDFLAGS) -o $@ @ENABLE_INSTALLED_TESTS_FALSE@am_libtest_la_rpath = @ENABLE_INSTALLED_TESTS_TRUE@am_libtest_la_rpath = -rpath \ @ENABLE_INSTALLED_TESTS_TRUE@ $(libtestplugindir) am__dist_bin_SCRIPTS_DIST = telepathy-gabble-xmpp-console SCRIPTS = $(dist_bin_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libconsole_la_SOURCES) $(libgateways_la_SOURCES) \ $(libtest_la_SOURCES) DIST_SOURCES = $(libconsole_la_SOURCES) $(libgateways_la_SOURCES) \ $(libtest_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLIENT_TYPE = @CLIENT_TYPE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_CODING_STYLE_CHECKS = @ENABLE_CODING_STYLE_CHECKS@ ENABLE_PLUGINS = @ENABLE_PLUGINS@ ERROR_CFLAGS = @ERROR_CFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ GLIB_LIBS = @GLIB_LIBS@ GMODULE_CFLAGS = @GMODULE_CFLAGS@ GMODULE_LIBS = @GMODULE_LIBS@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NICE_CFLAGS = @NICE_CFLAGS@ NICE_LIBS = @NICE_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOUP_CFLAGS = @SOUP_CFLAGS@ SOUP_LIBS = @SOUP_LIBS@ STRIP = @STRIP@ TEST_PYTHON = @TEST_PYTHON@ TP_GLIB_CFLAGS = @TP_GLIB_CFLAGS@ TP_GLIB_LIBS = @TP_GLIB_LIBS@ VERSION = @VERSION@ WOCKY_CFLAGS = @WOCKY_CFLAGS@ WOCKY_LIBS = @WOCKY_LIBS@ XSLTPROC = @XSLTPROC@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ gabbletestsdir = @gabbletestsdir@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ pluginexecdir = @pluginexecdir@ pluginexeclibdir = @pluginexeclibdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ installable_plugins = \ libconsole.la \ libgateways.la libtest_only_plugins = \ libtest.la @ENABLE_INSTALLED_TESTS_FALSE@noinst_LTLIBRARIES = \ @ENABLE_INSTALLED_TESTS_FALSE@ $(libtest_only_plugins) $(NULL) \ @ENABLE_INSTALLED_TESTS_FALSE@ $(am__append_1) # libtesting-only plugins @ENABLE_INSTALLED_TESTS_TRUE@noinst_LTLIBRARIES = $(NULL) \ @ENABLE_INSTALLED_TESTS_TRUE@ $(am__append_1) @ENABLE_INSTALLED_TESTS_TRUE@libtestplugindir = $(gabbletestsdir)/plugins @ENABLE_INSTALLED_TESTS_TRUE@libtestplugin_LTLIBRARIES = \ @ENABLE_INSTALLED_TESTS_TRUE@ $(libtest_only_plugins) \ @ENABLE_INSTALLED_TESTS_TRUE@ $(NULL) # because libtest.la is not installed, libtool will want to compile it as static # despite -shared (a convenience library), unless we also use -rpath @ENABLE_INSTALLED_TESTS_FALSE@libtest_la_LDFLAGS = $(AM_LDFLAGS) -rpath $(pluginexecdir) @ENABLE_INSTALLED_TESTS_TRUE@libtest_la_LDFLAGS = $(AM_LDFLAGS) @ENABLE_PLUGINS_TRUE@pluginexec_LTLIBRARIES = $(installable_plugins) @ENABLE_PLUGINS_TRUE@dist_bin_SCRIPTS = \ @ENABLE_PLUGINS_TRUE@ telepathy-gabble-xmpp-console @ENABLE_PLUGINS_FALSE@EXTRA_DIST = \ @ENABLE_PLUGINS_FALSE@ telepathy-gabble-xmpp-console AM_LDFLAGS = -avoid-version -shared -no-undefined ALL_PLUGIN_LIBS = \ @WOCKY_LIBS@ \ @GLIB_LIBS@ \ @TP_GLIB_LIBS@ \ $(top_builddir)/extensions/libgabble-extensions.la \ $(top_builddir)/src/libgabble-plugins.la libtest_la_LIBADD = $(ALL_PLUGIN_LIBS) libgateways_la_LIBADD = $(ALL_PLUGIN_LIBS) libconsole_la_LIBADD = $(ALL_PLUGIN_LIBS) libtest_la_SOURCES = \ test.c \ test.h libgateways_la_SOURCES = \ gateways.c \ gateways.h libconsole_la_SOURCES = \ console.c \ console.h AM_CFLAGS = $(ERROR_CFLAGS) \ -I $(top_srcdir) -I $(top_builddir) \ @DBUS_CFLAGS@ @GLIB_CFLAGS@ @WOCKY_CFLAGS@ @TP_GLIB_CFLAGS@ \ -I $(top_srcdir)/gabble -I $(top_builddir)/gabble \ -I $(top_srcdir)/plugins all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu plugins/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libtestpluginLTLIBRARIES: $(libtestplugin_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(libtestplugin_LTLIBRARIES)'; test -n "$(libtestplugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libtestplugindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libtestplugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libtestplugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libtestplugindir)"; \ } uninstall-libtestpluginLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(libtestplugin_LTLIBRARIES)'; test -n "$(libtestplugindir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libtestplugindir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libtestplugindir)/$$f"; \ done clean-libtestpluginLTLIBRARIES: -test -z "$(libtestplugin_LTLIBRARIES)" || rm -f $(libtestplugin_LTLIBRARIES) @list='$(libtestplugin_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } install-pluginexecLTLIBRARIES: $(pluginexec_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pluginexec_LTLIBRARIES)'; test -n "$(pluginexecdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(pluginexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pluginexecdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pluginexecdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pluginexecdir)"; \ } uninstall-pluginexecLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pluginexec_LTLIBRARIES)'; test -n "$(pluginexecdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pluginexecdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pluginexecdir)/$$f"; \ done clean-pluginexecLTLIBRARIES: -test -z "$(pluginexec_LTLIBRARIES)" || rm -f $(pluginexec_LTLIBRARIES) @list='$(pluginexec_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libconsole.la: $(libconsole_la_OBJECTS) $(libconsole_la_DEPENDENCIES) $(EXTRA_libconsole_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(am_libconsole_la_rpath) $(libconsole_la_OBJECTS) $(libconsole_la_LIBADD) $(LIBS) libgateways.la: $(libgateways_la_OBJECTS) $(libgateways_la_DEPENDENCIES) $(EXTRA_libgateways_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(am_libgateways_la_rpath) $(libgateways_la_OBJECTS) $(libgateways_la_LIBADD) $(LIBS) libtest.la: $(libtest_la_OBJECTS) $(libtest_la_DEPENDENCIES) $(EXTRA_libtest_la_DEPENDENCIES) $(AM_V_CCLD)$(libtest_la_LINK) $(am_libtest_la_rpath) $(libtest_la_OBJECTS) $(libtest_la_LIBADD) $(LIBS) install-dist_binSCRIPTS: $(dist_bin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-dist_binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/console.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gateways.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(SCRIPTS) installdirs: for dir in "$(DESTDIR)$(libtestplugindir)" "$(DESTDIR)$(pluginexecdir)" "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtestpluginLTLIBRARIES clean-libtool \ clean-noinstLTLIBRARIES clean-pluginexecLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-libtestpluginLTLIBRARIES install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-dist_binSCRIPTS install-pluginexecLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-dist_binSCRIPTS \ uninstall-libtestpluginLTLIBRARIES \ uninstall-pluginexecLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtestpluginLTLIBRARIES clean-libtool \ clean-noinstLTLIBRARIES clean-pluginexecLTLIBRARIES \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dist_binSCRIPTS \ install-dvi install-dvi-am install-exec install-exec-am \ install-html install-html-am install-info install-info-am \ install-libtestpluginLTLIBRARIES install-man install-pdf \ install-pdf-am install-pluginexecLTLIBRARIES install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-dist_binSCRIPTS \ uninstall-libtestpluginLTLIBRARIES \ uninstall-pluginexecLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: